Compare commits
52 Commits
v1.132.0
...
focus_rings
| Author | SHA1 | Date | |
|---|---|---|---|
| 9806e94f6f | |||
| 2e8a286540 | |||
| 038a82c4f1 | |||
| 2c2dd01bf0 | |||
| ac73e163df | |||
| d89e88bb3f | |||
| 3ce353393a | |||
| 0e4cf9ac57 | |||
| 07290580a6 | |||
| d9ce74b896 | |||
| 4c0f79b162 | |||
| 9851d24628 | |||
| fe6cbd93b1 | |||
| df20788088 | |||
| 3d042cc7f1 | |||
| 85446c5862 | |||
| fb52ac0f5b | |||
| 48bcbee6ed | |||
| f621f8ef2c | |||
| 7f69abbf0d | |||
| 895b2bf5cd | |||
| f64e6f5dc3 | |||
| 64e738f79d | |||
| a17390a422 | |||
| 1b5fc9c665 | |||
| 23717ce981 | |||
| 2fd05e8447 | |||
| c664d99a34 | |||
| 21c7d70336 | |||
| ad272333db | |||
| 460d594791 | |||
| e6c575c33e | |||
| 85ac0512a6 | |||
| 205260d31c | |||
| 3858973be5 | |||
| 02994883fe | |||
| a1f8150c30 | |||
| d85ef19bfc | |||
| d0014bdf94 | |||
| e822e3eca9 | |||
| 644defa4a1 | |||
| 1fe3c7b9b3 | |||
| 0d60be3d87 | |||
| 765da7b182 | |||
| b037158028 | |||
| a03902f174 | |||
| 1d610ad9cb | |||
| dab4870fed | |||
| 37f5e6e2cb | |||
| 57d622bc43 | |||
| c167e46ec7 | |||
| 6ce8a1deeb |
@@ -96,7 +96,7 @@ jobs:
|
|||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
|
||||||
with:
|
with:
|
||||||
file: cli/Dockerfile
|
file: cli/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@45775bd8235c68ba998cffa5171334d58593da47 # v3
|
uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@45775bd8235c68ba998cffa5171334d58593da47 # v3
|
uses: github/codeql-action/autobuild@28deaeda66b76a05916b6923827895f2b14ab387 # v3
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -76,6 +76,6 @@ jobs:
|
|||||||
# ./location_of_script_within_repo/buildscript.sh
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@45775bd8235c68ba998cffa5171334d58593da47 # v3
|
uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3
|
||||||
with:
|
with:
|
||||||
category: '/language:${{matrix.language}}'
|
category: '/language:${{matrix.language}}'
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
id: build
|
id: build
|
||||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
@@ -266,7 +266,7 @@ jobs:
|
|||||||
- build_and_push_ml
|
- build_and_push_ml
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/digests
|
path: ${{ runner.temp }}/digests
|
||||||
pattern: ml-digests-${{ matrix.device }}-*
|
pattern: ml-digests-${{ matrix.device }}-*
|
||||||
@@ -407,7 +407,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
id: build
|
id: build
|
||||||
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
|
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
|
||||||
with:
|
with:
|
||||||
context: ${{ env.context }}
|
context: ${{ env.context }}
|
||||||
file: ${{ env.file }}
|
file: ${{ env.file }}
|
||||||
@@ -454,7 +454,7 @@ jobs:
|
|||||||
- build_and_push_server
|
- build_and_push_server
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/digests
|
path: ${{ runner.temp }}/digests
|
||||||
pattern: server-digests-*
|
pattern: server-digests-*
|
||||||
|
|||||||
@@ -72,4 +72,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: docs-build-output
|
name: docs-build-output
|
||||||
path: docs/build/
|
path: docs/build/
|
||||||
|
include-hidden-files: true
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Download APK
|
- name: Download APK
|
||||||
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||||
with:
|
with:
|
||||||
name: release-apk-signed
|
name: release-apk-signed
|
||||||
|
|
||||||
|
|||||||
@@ -105,12 +105,12 @@ jobs:
|
|||||||
actions: read
|
actions: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Install the latest version of uv
|
- name: Install the latest version of uv
|
||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
|
||||||
|
|
||||||
- name: Run zizmor 🌈
|
- name: Run zizmor 🌈
|
||||||
run: uvx zizmor --format=sarif . > results.sarif
|
run: uvx zizmor --format=sarif . > results.sarif
|
||||||
@@ -118,7 +118,7 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Upload SARIF file
|
- name: Upload SARIF file
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
category: zizmor
|
category: zizmor
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install uv
|
- name: Install uv
|
||||||
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
|
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
|
||||||
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5
|
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
||||||
# TODO: add caching when supported (https://github.com/actions/setup-python/pull/818)
|
# TODO: add caching when supported (https://github.com/actions/setup-python/pull/818)
|
||||||
# with:
|
# with:
|
||||||
# python-version: 3.11
|
# python-version: 3.11
|
||||||
|
|||||||
Vendored
+48
-30
@@ -1,45 +1,63 @@
|
|||||||
{
|
{
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"[javascript]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.formatOnSave": true
|
|
||||||
},
|
|
||||||
"[typescript]": {
|
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.formatOnSave": true
|
|
||||||
},
|
|
||||||
"[css]": {
|
"[css]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.tabSize": 2,
|
"editor.formatOnSave": true,
|
||||||
"editor.formatOnSave": true
|
|
||||||
},
|
|
||||||
"[svelte]": {
|
|
||||||
"editor.defaultFormatter": "svelte.svelte-vscode",
|
|
||||||
"editor.tabSize": 2
|
"editor.tabSize": 2
|
||||||
},
|
},
|
||||||
"svelte.enable-ts-plugin": true,
|
|
||||||
"eslint.validate": [
|
|
||||||
"javascript",
|
|
||||||
"svelte"
|
|
||||||
],
|
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
|
||||||
"[dart]": {
|
"[dart]": {
|
||||||
|
"editor.defaultFormatter": "Dart-Code.dart-code",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.selectionHighlight": false,
|
"editor.selectionHighlight": false,
|
||||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||||
"editor.suggestSelection": "first",
|
"editor.suggestSelection": "first",
|
||||||
"editor.tabCompletion": "onlySnippets",
|
"editor.tabCompletion": "onlySnippets",
|
||||||
"editor.wordBasedSuggestions": "off",
|
"editor.wordBasedSuggestions": "off"
|
||||||
"editor.defaultFormatter": "Dart-Code.dart-code"
|
|
||||||
},
|
},
|
||||||
"cSpell.words": [
|
"[javascript]": {
|
||||||
"immich"
|
"editor.codeActionsOnSave": {
|
||||||
],
|
"source.organizeImports": "explicit",
|
||||||
|
"source.removeUnusedImports": "explicit"
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.tabSize": 2
|
||||||
|
},
|
||||||
|
"[json]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.tabSize": 2
|
||||||
|
},
|
||||||
|
"[jsonc]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.tabSize": 2
|
||||||
|
},
|
||||||
|
"[svelte]": {
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": "explicit",
|
||||||
|
"source.removeUnusedImports": "explicit"
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "svelte.svelte-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.tabSize": 2
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": "explicit",
|
||||||
|
"source.removeUnusedImports": "explicit"
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.tabSize": 2
|
||||||
|
},
|
||||||
|
"cSpell.words": ["immich"],
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"eslint.validate": ["javascript", "svelte"],
|
||||||
"explorer.fileNesting.enabled": true,
|
"explorer.fileNesting.enabled": true,
|
||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
|
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart",
|
||||||
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart"
|
"*.ts": "${capture}.spec.ts,${capture}.mock.ts"
|
||||||
}
|
},
|
||||||
|
"svelte.enable-ts-plugin": true,
|
||||||
|
"typescript.preferences.importModuleSpecifier": "non-relative"
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,9 @@ e2e:
|
|||||||
prod:
|
prod:
|
||||||
docker compose -f ./docker/docker-compose.prod.yml up --build -V --remove-orphans
|
docker compose -f ./docker/docker-compose.prod.yml up --build -V --remove-orphans
|
||||||
|
|
||||||
|
prod-down:
|
||||||
|
docker compose -f ./docker/docker-compose.prod.yml down --remove-orphans
|
||||||
|
|
||||||
prod-scale:
|
prod-scale:
|
||||||
docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
|
docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM node:22.14.0-alpine3.20@sha256:40be979442621049f40b1d51a26b55e281246b5de4e5f51a18da7beb6e17e3f9 AS core
|
FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS core
|
||||||
|
|
||||||
WORKDIR /usr/src/open-api/typescript-sdk
|
WORKDIR /usr/src/open-api/typescript-sdk
|
||||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
||||||
|
|||||||
Generated
+124
-136
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.62",
|
"version": "2.2.65",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.62",
|
"version": "2.2.65",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
},
|
},
|
||||||
"../open-api/typescript-sdk": {
|
"../open-api/typescript-sdk": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -647,9 +647,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/core": {
|
"node_modules/@eslint/core": {
|
||||||
"version": "0.12.0",
|
"version": "0.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
|
||||||
"integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
|
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -697,9 +697,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.24.0",
|
"version": "9.25.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz",
|
||||||
"integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==",
|
"integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -730,19 +730,6 @@
|
|||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
|
|
||||||
"version": "0.13.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
|
|
||||||
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/json-schema": "^7.0.15"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@humanfs/core": {
|
"node_modules/@humanfs/core": {
|
||||||
"version": "0.19.1",
|
"version": "0.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||||
@@ -1380,17 +1367,17 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz",
|
||||||
"integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==",
|
"integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.30.1",
|
"@typescript-eslint/scope-manager": "8.31.0",
|
||||||
"@typescript-eslint/type-utils": "8.30.1",
|
"@typescript-eslint/type-utils": "8.31.0",
|
||||||
"@typescript-eslint/utils": "8.30.1",
|
"@typescript-eslint/utils": "8.31.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.30.1",
|
"@typescript-eslint/visitor-keys": "8.31.0",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@@ -1410,16 +1397,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz",
|
||||||
"integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==",
|
"integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.30.1",
|
"@typescript-eslint/scope-manager": "8.31.0",
|
||||||
"@typescript-eslint/types": "8.30.1",
|
"@typescript-eslint/types": "8.31.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.30.1",
|
"@typescript-eslint/typescript-estree": "8.31.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.30.1",
|
"@typescript-eslint/visitor-keys": "8.31.0",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1435,14 +1422,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz",
|
||||||
"integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==",
|
"integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.30.1",
|
"@typescript-eslint/types": "8.31.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.30.1"
|
"@typescript-eslint/visitor-keys": "8.31.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1453,14 +1440,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz",
|
||||||
"integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==",
|
"integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.30.1",
|
"@typescript-eslint/typescript-estree": "8.31.0",
|
||||||
"@typescript-eslint/utils": "8.30.1",
|
"@typescript-eslint/utils": "8.31.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.0.1"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
@@ -1477,9 +1464,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz",
|
||||||
"integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==",
|
"integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1491,14 +1478,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz",
|
||||||
"integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==",
|
"integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.30.1",
|
"@typescript-eslint/types": "8.31.0",
|
||||||
"@typescript-eslint/visitor-keys": "8.30.1",
|
"@typescript-eslint/visitor-keys": "8.31.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@@ -1544,16 +1531,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz",
|
||||||
"integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==",
|
"integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "8.30.1",
|
"@typescript-eslint/scope-manager": "8.31.0",
|
||||||
"@typescript-eslint/types": "8.30.1",
|
"@typescript-eslint/types": "8.31.0",
|
||||||
"@typescript-eslint/typescript-estree": "8.30.1"
|
"@typescript-eslint/typescript-estree": "8.31.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1568,13 +1555,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz",
|
||||||
"integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==",
|
"integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.30.1",
|
"@typescript-eslint/types": "8.31.0",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1586,9 +1573,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/coverage-v8": {
|
"node_modules/@vitest/coverage-v8": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz",
|
||||||
"integrity": "sha512-MgV6D2dhpD6Hp/uroUoAIvFqA8AuvXEFBC2eepG3WFc1pxTfdk1LEqqkWoWhjz+rytoqrnUUCdf6Lzco3iHkLQ==",
|
"integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1601,7 +1588,7 @@
|
|||||||
"istanbul-reports": "^3.1.7",
|
"istanbul-reports": "^3.1.7",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"magicast": "^0.3.5",
|
"magicast": "^0.3.5",
|
||||||
"std-env": "^3.8.1",
|
"std-env": "^3.9.0",
|
||||||
"test-exclude": "^7.0.1",
|
"test-exclude": "^7.0.1",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -1609,8 +1596,8 @@
|
|||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@vitest/browser": "3.1.1",
|
"@vitest/browser": "3.1.2",
|
||||||
"vitest": "3.1.1"
|
"vitest": "3.1.2"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@vitest/browser": {
|
"@vitest/browser": {
|
||||||
@@ -1619,14 +1606,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/expect": {
|
"node_modules/@vitest/expect": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz",
|
||||||
"integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==",
|
"integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/spy": "3.1.1",
|
"@vitest/spy": "3.1.2",
|
||||||
"@vitest/utils": "3.1.1",
|
"@vitest/utils": "3.1.2",
|
||||||
"chai": "^5.2.0",
|
"chai": "^5.2.0",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -1635,13 +1622,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/mocker": {
|
"node_modules/@vitest/mocker": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz",
|
||||||
"integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==",
|
"integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/spy": "3.1.1",
|
"@vitest/spy": "3.1.2",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"magic-string": "^0.30.17"
|
"magic-string": "^0.30.17"
|
||||||
},
|
},
|
||||||
@@ -1662,9 +1649,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/pretty-format": {
|
"node_modules/@vitest/pretty-format": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz",
|
||||||
"integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==",
|
"integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1675,13 +1662,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/runner": {
|
"node_modules/@vitest/runner": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz",
|
||||||
"integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==",
|
"integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/utils": "3.1.1",
|
"@vitest/utils": "3.1.2",
|
||||||
"pathe": "^2.0.3"
|
"pathe": "^2.0.3"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -1689,13 +1676,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/snapshot": {
|
"node_modules/@vitest/snapshot": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz",
|
||||||
"integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==",
|
"integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/pretty-format": "3.1.1",
|
"@vitest/pretty-format": "3.1.2",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"pathe": "^2.0.3"
|
"pathe": "^2.0.3"
|
||||||
},
|
},
|
||||||
@@ -1704,9 +1691,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/spy": {
|
"node_modules/@vitest/spy": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz",
|
||||||
"integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==",
|
"integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1717,13 +1704,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitest/utils": {
|
"node_modules/@vitest/utils": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz",
|
||||||
"integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==",
|
"integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/pretty-format": "3.1.1",
|
"@vitest/pretty-format": "3.1.2",
|
||||||
"loupe": "^3.1.3",
|
"loupe": "^3.1.3",
|
||||||
"tinyrainbow": "^2.0.0"
|
"tinyrainbow": "^2.0.0"
|
||||||
},
|
},
|
||||||
@@ -2183,9 +2170,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/es-module-lexer": {
|
"node_modules/es-module-lexer": {
|
||||||
"version": "1.6.0",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
||||||
"integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
|
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -2254,20 +2241,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.24.0",
|
"version": "9.25.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz",
|
||||||
"integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==",
|
"integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
"@eslint/config-array": "^0.20.0",
|
"@eslint/config-array": "^0.20.0",
|
||||||
"@eslint/config-helpers": "^0.2.0",
|
"@eslint/config-helpers": "^0.2.1",
|
||||||
"@eslint/core": "^0.12.0",
|
"@eslint/core": "^0.13.0",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@eslint/js": "9.24.0",
|
"@eslint/js": "9.25.1",
|
||||||
"@eslint/plugin-kit": "^0.2.7",
|
"@eslint/plugin-kit": "^0.2.8",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.4.2",
|
"@humanwhocodes/retry": "^0.4.2",
|
||||||
@@ -4197,15 +4184,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript-eslint": {
|
"node_modules/typescript-eslint": {
|
||||||
"version": "8.30.1",
|
"version": "8.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.0.tgz",
|
||||||
"integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==",
|
"integrity": "sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "8.30.1",
|
"@typescript-eslint/eslint-plugin": "8.31.0",
|
||||||
"@typescript-eslint/parser": "8.30.1",
|
"@typescript-eslint/parser": "8.31.0",
|
||||||
"@typescript-eslint/utils": "8.30.1"
|
"@typescript-eslint/utils": "8.31.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -4292,18 +4279,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.3.2",
|
"version": "6.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz",
|
||||||
"integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==",
|
"integrity": "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.4.3",
|
"fdir": "^6.4.4",
|
||||||
"picomatch": "^4.0.2",
|
"picomatch": "^4.0.2",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"rollup": "^4.34.9",
|
"rollup": "^4.34.9",
|
||||||
"tinyglobby": "^0.2.12"
|
"tinyglobby": "^0.2.13"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"vite": "bin/vite.js"
|
"vite": "bin/vite.js"
|
||||||
@@ -4367,9 +4354,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite-node": {
|
"node_modules/vite-node": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz",
|
||||||
"integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==",
|
"integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4438,31 +4425,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vitest": {
|
"node_modules/vitest": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz",
|
||||||
"integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==",
|
"integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/expect": "3.1.1",
|
"@vitest/expect": "3.1.2",
|
||||||
"@vitest/mocker": "3.1.1",
|
"@vitest/mocker": "3.1.2",
|
||||||
"@vitest/pretty-format": "^3.1.1",
|
"@vitest/pretty-format": "^3.1.2",
|
||||||
"@vitest/runner": "3.1.1",
|
"@vitest/runner": "3.1.2",
|
||||||
"@vitest/snapshot": "3.1.1",
|
"@vitest/snapshot": "3.1.2",
|
||||||
"@vitest/spy": "3.1.1",
|
"@vitest/spy": "3.1.2",
|
||||||
"@vitest/utils": "3.1.1",
|
"@vitest/utils": "3.1.2",
|
||||||
"chai": "^5.2.0",
|
"chai": "^5.2.0",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"expect-type": "^1.2.0",
|
"expect-type": "^1.2.1",
|
||||||
"magic-string": "^0.30.17",
|
"magic-string": "^0.30.17",
|
||||||
"pathe": "^2.0.3",
|
"pathe": "^2.0.3",
|
||||||
"std-env": "^3.8.1",
|
"std-env": "^3.9.0",
|
||||||
"tinybench": "^2.9.0",
|
"tinybench": "^2.9.0",
|
||||||
"tinyexec": "^0.3.2",
|
"tinyexec": "^0.3.2",
|
||||||
|
"tinyglobby": "^0.2.13",
|
||||||
"tinypool": "^1.0.2",
|
"tinypool": "^1.0.2",
|
||||||
"tinyrainbow": "^2.0.0",
|
"tinyrainbow": "^2.0.0",
|
||||||
"vite": "^5.0.0 || ^6.0.0",
|
"vite": "^5.0.0 || ^6.0.0",
|
||||||
"vite-node": "3.1.1",
|
"vite-node": "3.1.2",
|
||||||
"why-is-node-running": "^2.3.0"
|
"why-is-node-running": "^2.3.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -4478,8 +4466,8 @@
|
|||||||
"@edge-runtime/vm": "*",
|
"@edge-runtime/vm": "*",
|
||||||
"@types/debug": "^4.1.12",
|
"@types/debug": "^4.1.12",
|
||||||
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
|
||||||
"@vitest/browser": "3.1.1",
|
"@vitest/browser": "3.1.2",
|
||||||
"@vitest/ui": "3.1.1",
|
"@vitest/ui": "3.1.2",
|
||||||
"happy-dom": "*",
|
"happy-dom": "*",
|
||||||
"jsdom": "*"
|
"jsdom": "*"
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.62",
|
"version": "2.2.65",
|
||||||
"description": "Command Line Interface (CLI) for Immich",
|
"description": "Command Line Interface (CLI) for Immich",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1
|
image: docker.io/valkey/valkey:8-bookworm@sha256:c855f98e09d558a0d7cc1a4e56473231206a4c54c0114ada9c485b47aeb92ec8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1
|
image: docker.io/valkey/valkey:8-bookworm@sha256:c855f98e09d558a0d7cc1a4e56473231206a4c54c0114ada9c485b47aeb92ec8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
@@ -102,7 +102,7 @@ services:
|
|||||||
command: [ './run.sh', '-disable-reporting' ]
|
command: [ './run.sh', '-disable-reporting' ]
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
image: grafana/grafana:11.6.0-ubuntu@sha256:fd8fa48213c624e1a95122f1d93abbf1cf1cbe85fc73212c1e599dbd76c63ff8
|
image: grafana/grafana:11.6.1-ubuntu@sha256:6fc273288470ef499dd3c6b36aeade093170d4f608f864c5dd3a7fabeae77b50
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1
|
image: docker.io/valkey/valkey:8-bookworm@sha256:c855f98e09d558a0d7cc1a4e56473231206a4c54c0114ada9c485b47aeb92ec8
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ online generators you can use.
|
|||||||
2. Paste the link to your JSON style in either the **Light Style** or **Dark Style**. (You can add different styles which will help make the map style more appropriate depending on whether you set **Immich** to Light or Dark mode.)
|
2. Paste the link to your JSON style in either the **Light Style** or **Dark Style**. (You can add different styles which will help make the map style more appropriate depending on whether you set **Immich** to Light or Dark mode.)
|
||||||
3. Save your selections. Reload the map, and enjoy your custom map style!
|
3. Save your selections. Reload the map, and enjoy your custom map style!
|
||||||
|
|
||||||
## Use Maptiler to build a custom style
|
## Use MapTiler to build a custom style
|
||||||
|
|
||||||
Customizing the map style can be done easily using Maptiler, if you do not want to write an entire JSON document by hand.
|
Customizing the map style can be done easily using MapTiler, if you do not want to write an entire JSON document by hand.
|
||||||
|
|
||||||
1. Create a free account at https://cloud.maptiler.com
|
1. Create a free account at https://cloud.maptiler.com
|
||||||
2. Once logged in, you can either create a brand new map by clicking on **New Map**, selecting a starter map, and then clicking **Customize**, OR by selecting a **Standard Map** and customizing it from there.
|
2. Once logged in, you can either create a brand new map by clicking on **New Map**, selecting a starter map, and then clicking **Customize**, OR by selecting a **Standard Map** and customizing it from there.
|
||||||
3. The **editor** interface is self-explanatory. You can change colors, remove visible layers, or add optional layers (e.g., administrative, topo, hydro, etc.) in the composer.
|
3. The **editor** interface is self-explanatory. You can change colors, remove visible layers, or add optional layers (e.g., administrative, topo, hydro, etc.) in the composer.
|
||||||
4. Once you have your map composed, click on **Save** at the top right. Give it a unique name to save it to your account.
|
4. Once you have your map composed, click on **Save** at the top right. Give it a unique name to save it to your account.
|
||||||
5. Next, **Publish** your style using the **Publish** button at the top right. This will deploy it to production, which means it is able to be exposed over the Internet. Maptiler will present an interactive side-by-side map with the original and your changes prior to publication.<br/>
|
5. Next, **Publish** your style using the **Publish** button at the top right. This will deploy it to production, which means it is able to be exposed over the Internet. MapTiler will present an interactive side-by-side map with the original and your changes prior to publication.<br/>
|
||||||
6. Maptiler will warn you that changing the map will change it across all apps using the map. Since no apps are using the map yet, this is okay.
|
6. MapTiler will warn you that changing the map will change it across all apps using the map. Since no apps are using the map yet, this is okay.
|
||||||
7. Clicking on the name of your new map at the top left will bring you to the item's **details** page. From here, copy the link to the JSON style under **Use vector style**. This link will automatically contain your personal API key to Maptiler.
|
7. Clicking on the name of your new map at the top left will bring you to the item's **details** page. From here, copy the link to the JSON style under **Use vector style**. This link will automatically contain your personal API key to MapTiler.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Database Queries
|
# Database Queries
|
||||||
|
|
||||||
:::danger
|
:::danger
|
||||||
Keep in mind that mucking around in the database might set the moon on fire. Avoid modifying the database directly when possible, and always have current backups.
|
Keep in mind that mucking around in the database might set the Moon on fire. Avoid modifying the database directly when possible, and always have current backups.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
|
|||||||
@@ -252,6 +252,13 @@ const milestones: Item[] = [
|
|||||||
description: 'Browse your photos and videos in their folder structure inside the mobile app',
|
description: 'Browse your photos and videos in their folder structure inside the mobile app',
|
||||||
release: 'v1.130.0',
|
release: 'v1.130.0',
|
||||||
}),
|
}),
|
||||||
|
{
|
||||||
|
icon: mdiStar,
|
||||||
|
iconColor: 'gold',
|
||||||
|
title: '60,000 Stars',
|
||||||
|
description: 'Reached 60K Stars on GitHub!',
|
||||||
|
getDateLabel: withLanguage(new Date(2025, 2, 4)),
|
||||||
|
},
|
||||||
withRelease({
|
withRelease({
|
||||||
icon: mdiTagFaces,
|
icon: mdiTagFaces,
|
||||||
iconColor: 'teal',
|
iconColor: 'teal',
|
||||||
@@ -260,13 +267,6 @@ const milestones: Item[] = [
|
|||||||
'Manually tag or remove faces in photos and videos, even when automatic detection misses or misidentifies them.',
|
'Manually tag or remove faces in photos and videos, even when automatic detection misses or misidentifies them.',
|
||||||
release: 'v1.127.0',
|
release: 'v1.127.0',
|
||||||
}),
|
}),
|
||||||
{
|
|
||||||
icon: mdiStar,
|
|
||||||
iconColor: 'gold',
|
|
||||||
title: '60,000 Stars',
|
|
||||||
description: 'Reached 60K Stars on GitHub!',
|
|
||||||
getDateLabel: withLanguage(new Date(2025, 2, 4)),
|
|
||||||
},
|
|
||||||
withRelease({
|
withRelease({
|
||||||
icon: mdiLinkEdit,
|
icon: mdiLinkEdit,
|
||||||
iconColor: 'crimson',
|
iconColor: 'crimson',
|
||||||
|
|||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
Policy: https://github.com/immich-app/immich/blob/main/SECURITY.md
|
||||||
|
Contact: mailto:security@immich.app
|
||||||
|
Preferred-Languages: en
|
||||||
|
Expires: 2026-05-01T23:59:00.000Z
|
||||||
|
Canonical: https://immich.app/.well-known/security.txt
|
||||||
Vendored
+12
@@ -1,4 +1,16 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"label": "v1.132.3",
|
||||||
|
"url": "https://v1.132.3.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.132.2",
|
||||||
|
"url": "https://v1.132.2.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.132.1",
|
||||||
|
"url": "https://v1.132.1.archive.immich.app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "v1.132.0",
|
"label": "v1.132.0",
|
||||||
"url": "https://v1.132.0.archive.immich.app"
|
"url": "https://v1.132.0.archive.immich.app"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ services:
|
|||||||
- 2285:2285
|
- 2285:2285
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
|
image: redis:6.2-alpine@sha256:3211c33a618c457e5d241922c975dbc4f446d0bdb2dc75694f5573ef8e2d01fa
|
||||||
|
|
||||||
database:
|
database:
|
||||||
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
|
image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
|
||||||
|
|||||||
Generated
+408
-344
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ describe(`/oauth`, () => {
|
|||||||
it(`should throw an error if the state mismatches`, async () => {
|
it(`should throw an error if the state mismatches`, async () => {
|
||||||
const callbackParams = await loginWithOAuth('oauth-auto-register');
|
const callbackParams = await loginWithOAuth('oauth-auto-register');
|
||||||
const { state } = await loginWithOAuth('oauth-auto-register');
|
const { state } = await loginWithOAuth('oauth-auto-register');
|
||||||
const { status, body } = await request(app)
|
const { status } = await request(app)
|
||||||
.post('/oauth/callback')
|
.post('/oauth/callback')
|
||||||
.send({ ...callbackParams, state });
|
.send({ ...callbackParams, state });
|
||||||
expect(status).toBeGreaterThanOrEqual(400);
|
expect(status).toBeGreaterThanOrEqual(400);
|
||||||
|
|||||||
@@ -215,6 +215,19 @@ describe('/admin/users', () => {
|
|||||||
const user = await getMyUser({ headers: asBearerAuth(token.accessToken) });
|
const user = await getMyUser({ headers: asBearerAuth(token.accessToken) });
|
||||||
expect(user).toMatchObject({ email: nonAdmin.userEmail });
|
expect(user).toMatchObject({ email: nonAdmin.userEmail });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should update the avatar color', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.put(`/admin/users/${admin.userId}`)
|
||||||
|
.send({ avatarColor: 'orange' })
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
|
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toMatchObject({ avatarColor: 'orange' });
|
||||||
|
|
||||||
|
const after = await getUserAdmin({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) });
|
||||||
|
expect(after).toMatchObject({ avatarColor: 'orange' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PUT /admin/users/:id/preferences', () => {
|
describe('PUT /admin/users/:id/preferences', () => {
|
||||||
@@ -240,19 +253,6 @@ describe('/admin/users', () => {
|
|||||||
expect(after).toMatchObject({ memories: { enabled: false } });
|
expect(after).toMatchObject({ memories: { enabled: false } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update the avatar color', async () => {
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.put(`/admin/users/${admin.userId}/preferences`)
|
|
||||||
.send({ avatar: { color: 'orange' } })
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
||||||
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toMatchObject({ avatar: { color: 'orange' } });
|
|
||||||
|
|
||||||
const after = await getUserPreferencesAdmin({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) });
|
|
||||||
expect(after).toMatchObject({ avatar: { color: 'orange' } });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update download archive size', async () => {
|
it('should update download archive size', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.put(`/admin/users/${admin.userId}/preferences`)
|
.put(`/admin/users/${admin.userId}/preferences`)
|
||||||
|
|||||||
@@ -139,6 +139,19 @@ describe('/users', () => {
|
|||||||
profileChangedAt: expect.anything(),
|
profileChangedAt: expect.anything(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should update avatar color', async () => {
|
||||||
|
const { status, body } = await request(app)
|
||||||
|
.put(`/users/me`)
|
||||||
|
.send({ avatarColor: 'blue' })
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||||
|
|
||||||
|
expect(status).toBe(200);
|
||||||
|
expect(body).toMatchObject({ avatarColor: 'blue' });
|
||||||
|
|
||||||
|
const after = await getMyUser({ headers: asBearerAuth(admin.accessToken) });
|
||||||
|
expect(after).toMatchObject({ avatarColor: 'blue' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PUT /users/me/preferences', () => {
|
describe('PUT /users/me/preferences', () => {
|
||||||
@@ -158,19 +171,6 @@ describe('/users', () => {
|
|||||||
expect(after).toMatchObject({ memories: { enabled: false } });
|
expect(after).toMatchObject({ memories: { enabled: false } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update avatar color', async () => {
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.put(`/users/me/preferences`)
|
|
||||||
.send({ avatar: { color: 'blue' } })
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
||||||
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toMatchObject({ avatar: { color: 'blue' } });
|
|
||||||
|
|
||||||
const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
|
|
||||||
expect(after).toMatchObject({ avatar: { color: 'blue' } });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should require an integer for download archive size', async () => {
|
it('should require an integer for download archive size', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.put(`/users/me/preferences`)
|
.put(`/users/me/preferences`)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ test.describe('Registration', () => {
|
|||||||
|
|
||||||
// login
|
// login
|
||||||
await expect(page).toHaveTitle(/Login/);
|
await expect(page).toHaveTitle(/Login/);
|
||||||
await page.goto('/auth/login');
|
await page.goto('/auth/login?autoLaunch=0');
|
||||||
await page.getByLabel('Email').fill('admin@immich.app');
|
await page.getByLabel('Email').fill('admin@immich.app');
|
||||||
await page.getByLabel('Password').fill('password');
|
await page.getByLabel('Password').fill('password');
|
||||||
await page.getByRole('button', { name: 'Login' }).click();
|
await page.getByRole('button', { name: 'Login' }).click();
|
||||||
@@ -59,7 +59,7 @@ test.describe('Registration', () => {
|
|||||||
await context.clearCookies();
|
await context.clearCookies();
|
||||||
|
|
||||||
// login
|
// login
|
||||||
await page.goto('/auth/login');
|
await page.goto('/auth/login?autoLaunch=0');
|
||||||
await page.getByLabel('Email').fill('user@immich.cloud');
|
await page.getByLabel('Email').fill('user@immich.cloud');
|
||||||
await page.getByLabel('Password').fill('password');
|
await page.getByLabel('Password').fill('password');
|
||||||
await page.getByRole('button', { name: 'Login' }).click();
|
await page.getByRole('button', { name: 'Login' }).click();
|
||||||
@@ -72,7 +72,7 @@ test.describe('Registration', () => {
|
|||||||
await page.getByRole('button', { name: 'Change password' }).click();
|
await page.getByRole('button', { name: 'Change password' }).click();
|
||||||
|
|
||||||
// login with new password
|
// login with new password
|
||||||
await expect(page).toHaveURL('/auth/login');
|
await expect(page).toHaveURL('/auth/login?autoLaunch=0');
|
||||||
await page.getByLabel('Email').fill('user@immich.cloud');
|
await page.getByLabel('Email').fill('user@immich.cloud');
|
||||||
await page.getByLabel('Password').fill('new-password');
|
await page.getByLabel('Password').fill('new-password');
|
||||||
await page.getByRole('button', { name: 'Login' }).click();
|
await page.getByRole('button', { name: 'Login' }).click();
|
||||||
|
|||||||
@@ -21,23 +21,9 @@ test.describe('Photo Viewer', () => {
|
|||||||
test.beforeEach(async ({ context, page }) => {
|
test.beforeEach(async ({ context, page }) => {
|
||||||
// before each test, login as user
|
// before each test, login as user
|
||||||
await utils.setAuthCookies(context, admin.accessToken);
|
await utils.setAuthCookies(context, admin.accessToken);
|
||||||
await page.goto('/photos');
|
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('initially shows a loading spinner', async ({ page }) => {
|
|
||||||
await page.route(`/api/assets/${asset.id}/thumbnail**`, async (route) => {
|
|
||||||
// slow down the request for thumbnail, so spinner has chance to show up
|
|
||||||
await new Promise((f) => setTimeout(f, 2000));
|
|
||||||
await route.continue();
|
|
||||||
});
|
|
||||||
await page.goto(`/photos/${asset.id}`);
|
|
||||||
await page.waitForLoadState('load');
|
|
||||||
// this is the spinner
|
|
||||||
await page.waitForSelector('svg[role=status]');
|
|
||||||
await expect(page.getByTestId('loading-spinner')).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('loads original photo when zoomed', async ({ page }) => {
|
test('loads original photo when zoomed', async ({ page }) => {
|
||||||
await page.goto(`/photos/${asset.id}`);
|
await page.goto(`/photos/${asset.id}`);
|
||||||
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ test.describe('Shared Links', () => {
|
|||||||
await page.goto(`/share/${sharedLink.key}`);
|
await page.goto(`/share/${sharedLink.key}`);
|
||||||
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
|
||||||
await page.getByRole('button', { name: 'Download' }).click();
|
await page.getByRole('button', { name: 'Download' }).click();
|
||||||
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
|
|
||||||
await page.waitForEvent('download');
|
await page.waitForEvent('download');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+11
-7
@@ -192,26 +192,22 @@
|
|||||||
"oauth_auto_register": "Auto register",
|
"oauth_auto_register": "Auto register",
|
||||||
"oauth_auto_register_description": "Automatically register new users after signing in with OAuth",
|
"oauth_auto_register_description": "Automatically register new users after signing in with OAuth",
|
||||||
"oauth_button_text": "Button text",
|
"oauth_button_text": "Button text",
|
||||||
"oauth_client_id": "Client ID",
|
"oauth_client_secret_description": "Required if PKCE (Proof Key for Code Exchange) is not supported by the OAuth provider",
|
||||||
"oauth_client_secret": "Client Secret",
|
|
||||||
"oauth_enable_description": "Login with OAuth",
|
"oauth_enable_description": "Login with OAuth",
|
||||||
"oauth_issuer_url": "Issuer URL",
|
|
||||||
"oauth_mobile_redirect_uri": "Mobile redirect URI",
|
"oauth_mobile_redirect_uri": "Mobile redirect URI",
|
||||||
"oauth_mobile_redirect_uri_override": "Mobile redirect URI override",
|
"oauth_mobile_redirect_uri_override": "Mobile redirect URI override",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Enable when OAuth provider does not allow a mobile URI, like '{callback}'",
|
"oauth_mobile_redirect_uri_override_description": "Enable when OAuth provider does not allow a mobile URI, like '{callback}'",
|
||||||
"oauth_profile_signing_algorithm": "Profile signing algorithm",
|
|
||||||
"oauth_profile_signing_algorithm_description": "Algorithm used to sign the user profile.",
|
|
||||||
"oauth_scope": "Scope",
|
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
"oauth_settings_description": "Manage OAuth login settings",
|
"oauth_settings_description": "Manage OAuth login settings",
|
||||||
"oauth_settings_more_details": "For more details about this feature, refer to the <link>docs</link>.",
|
"oauth_settings_more_details": "For more details about this feature, refer to the <link>docs</link>.",
|
||||||
"oauth_signing_algorithm": "Signing algorithm",
|
|
||||||
"oauth_storage_label_claim": "Storage label claim",
|
"oauth_storage_label_claim": "Storage label claim",
|
||||||
"oauth_storage_label_claim_description": "Automatically set the user's storage label to the value of this claim.",
|
"oauth_storage_label_claim_description": "Automatically set the user's storage label to the value of this claim.",
|
||||||
"oauth_storage_quota_claim": "Storage quota claim",
|
"oauth_storage_quota_claim": "Storage quota claim",
|
||||||
"oauth_storage_quota_claim_description": "Automatically set the user's storage quota to the value of this claim.",
|
"oauth_storage_quota_claim_description": "Automatically set the user's storage quota to the value of this claim.",
|
||||||
"oauth_storage_quota_default": "Default storage quota (GiB)",
|
"oauth_storage_quota_default": "Default storage quota (GiB)",
|
||||||
"oauth_storage_quota_default_description": "Quota in GiB to be used when no claim is provided (Enter 0 for unlimited quota).",
|
"oauth_storage_quota_default_description": "Quota in GiB to be used when no claim is provided (Enter 0 for unlimited quota).",
|
||||||
|
"oauth_timeout": "Request Timeout",
|
||||||
|
"oauth_timeout_description": "Timeout for requests in milliseconds",
|
||||||
"offline_paths": "Offline Paths",
|
"offline_paths": "Offline Paths",
|
||||||
"offline_paths_description": "These results may be due to manual deletion of files that are not part of an external library.",
|
"offline_paths_description": "These results may be due to manual deletion of files that are not part of an external library.",
|
||||||
"password_enable_description": "Login with email and password",
|
"password_enable_description": "Login with email and password",
|
||||||
@@ -853,10 +849,12 @@
|
|||||||
"failed_to_keep_this_delete_others": "Failed to keep this asset and delete the other assets",
|
"failed_to_keep_this_delete_others": "Failed to keep this asset and delete the other assets",
|
||||||
"failed_to_load_asset": "Failed to load asset",
|
"failed_to_load_asset": "Failed to load asset",
|
||||||
"failed_to_load_assets": "Failed to load assets",
|
"failed_to_load_assets": "Failed to load assets",
|
||||||
|
"failed_to_load_notifications": "Failed to load notifications",
|
||||||
"failed_to_load_people": "Failed to load people",
|
"failed_to_load_people": "Failed to load people",
|
||||||
"failed_to_remove_product_key": "Failed to remove product key",
|
"failed_to_remove_product_key": "Failed to remove product key",
|
||||||
"failed_to_stack_assets": "Failed to stack assets",
|
"failed_to_stack_assets": "Failed to stack assets",
|
||||||
"failed_to_unstack_assets": "Failed to un-stack assets",
|
"failed_to_unstack_assets": "Failed to un-stack assets",
|
||||||
|
"failed_to_update_notification_status": "Failed to update notification status",
|
||||||
"import_path_already_exists": "This import path already exists.",
|
"import_path_already_exists": "This import path already exists.",
|
||||||
"incorrect_email_or_password": "Incorrect email or password",
|
"incorrect_email_or_password": "Incorrect email or password",
|
||||||
"paths_validation_failed": "{paths, plural, one {# path} other {# paths}} failed validation",
|
"paths_validation_failed": "{paths, plural, one {# path} other {# paths}} failed validation",
|
||||||
@@ -1199,6 +1197,9 @@
|
|||||||
"map_settings_only_show_favorites": "Show Favorite Only",
|
"map_settings_only_show_favorites": "Show Favorite Only",
|
||||||
"map_settings_theme_settings": "Map Theme",
|
"map_settings_theme_settings": "Map Theme",
|
||||||
"map_zoom_to_see_photos": "Zoom out to see photos",
|
"map_zoom_to_see_photos": "Zoom out to see photos",
|
||||||
|
"mark_as_read": "Mark as read",
|
||||||
|
"mark_all_as_read": "Mark all as read",
|
||||||
|
"marked_all_as_read": "Marked all as read",
|
||||||
"matches": "Matches",
|
"matches": "Matches",
|
||||||
"media_type": "Media type",
|
"media_type": "Media type",
|
||||||
"memories": "Memories",
|
"memories": "Memories",
|
||||||
@@ -1225,6 +1226,8 @@
|
|||||||
"month": "Month",
|
"month": "Month",
|
||||||
"monthly_title_text_date_format": "MMMM y",
|
"monthly_title_text_date_format": "MMMM y",
|
||||||
"more": "More",
|
"more": "More",
|
||||||
|
"moved_to_archive": "Moved {count, plural, one {# asset} other {# assets}} to archive",
|
||||||
|
"moved_to_library": "Moved {count, plural, one {# asset} other {# assets}} to library",
|
||||||
"moved_to_trash": "Moved to trash",
|
"moved_to_trash": "Moved to trash",
|
||||||
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
|
"multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping",
|
||||||
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
|
"multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping",
|
||||||
@@ -1260,6 +1263,7 @@
|
|||||||
"no_places": "No places",
|
"no_places": "No places",
|
||||||
"no_results": "No results",
|
"no_results": "No results",
|
||||||
"no_results_description": "Try a synonym or more general keyword",
|
"no_results_description": "Try a synonym or more general keyword",
|
||||||
|
"no_notifications": "No notifications",
|
||||||
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
|
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
|
||||||
"not_in_any_album": "Not in any album",
|
"not_in_any_album": "Not in any album",
|
||||||
"not_selected": "Not selected",
|
"not_selected": "Not selected",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ARG DEVICE=cpu
|
ARG DEVICE=cpu
|
||||||
|
|
||||||
FROM python:3.11-bookworm@sha256:a3e280261e448b95d49423532ccd6e5329c39d171c10df1457891ff7c5e2301b AS builder-cpu
|
FROM python:3.11-bookworm@sha256:ab60e444e04215a62671149f24c59cc2893b49cb5dad26f9d139077a86be760e AS builder-cpu
|
||||||
|
|
||||||
FROM builder-cpu AS builder-openvino
|
FROM builder-cpu AS builder-openvino
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
|||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends g++
|
RUN apt-get update && apt-get install -y --no-install-recommends g++
|
||||||
|
|
||||||
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:db305ce8edc1c2df4988b9d23471465d90d599cc55571e6501421c173a33bb0b /uv /uvx /bin/
|
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:4a6c9444b126bd325fba904bff796bf91fb777bf6148d60109c4cb1de2ffc497 /uv /uvx /bin/
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||||
@@ -63,11 +63,11 @@ RUN if [ "$DEVICE" = "rocm" ]; then \
|
|||||||
uv pip install /opt/onnxruntime_rocm-*.whl; \
|
uv pip install /opt/onnxruntime_rocm-*.whl; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
FROM python:3.11-slim-bookworm@sha256:82c07f2f6e35255b92eb16f38dbd22679d5e8fb523064138d7c6468e7bf0c15b AS prod-cpu
|
FROM python:3.11-slim-bookworm@sha256:97ef3198ec8c78690587167bb6a4905d00ffe053900687bdae93ad667e507cbb AS prod-cpu
|
||||||
|
|
||||||
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
|
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
|
||||||
|
|
||||||
FROM python:3.11-slim-bookworm@sha256:82c07f2f6e35255b92eb16f38dbd22679d5e8fb523064138d7c6468e7bf0c15b AS prod-openvino
|
FROM python:3.11-slim-bookworm@sha256:97ef3198ec8c78690587167bb6a4905d00ffe053900687bdae93ad667e507cbb AS prod-openvino
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
|
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
|
||||||
|
|||||||
Generated
+116
-26
@@ -69,6 +69,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", size = 85481, upload_time = "2023-12-16T17:06:55.989Z" },
|
{ url = "https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", size = 85481, upload_time = "2023-12-16T17:06:55.989Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bidict"
|
||||||
|
version = "0.23.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9a/6e/026678aa5a830e07cd9498a05d3e7e650a4f56a42f267a53d22bcda1bdc9/bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71", size = 29093, upload_time = "2024-02-18T19:09:05.748Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload_time = "2024-02-18T19:09:04.156Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "25.1.0"
|
version = "25.1.0"
|
||||||
@@ -1200,15 +1209,16 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "locust"
|
name = "locust"
|
||||||
version = "2.35.0"
|
version = "2.36.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "configargparse" },
|
{ name = "configargparse" },
|
||||||
{ name = "flask" },
|
{ name = "flask" },
|
||||||
{ name = "flask-cors" },
|
{ name = "flask-cors" },
|
||||||
{ name = "flask-login" },
|
{ name = "flask-login" },
|
||||||
{ name = "gevent", marker = "python_full_version != '3.13.*'" },
|
{ name = "gevent" },
|
||||||
{ name = "geventhttpclient" },
|
{ name = "geventhttpclient" },
|
||||||
|
{ name = "locust-cloud" },
|
||||||
{ name = "msgpack" },
|
{ name = "msgpack" },
|
||||||
{ name = "psutil" },
|
{ name = "psutil" },
|
||||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||||
@@ -1219,9 +1229,25 @@ dependencies = [
|
|||||||
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||||
{ name = "werkzeug" },
|
{ name = "werkzeug" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/79/21/d5aeeee74173d73d7d8d392e307ec24d8281fca69a2bf1f19199bd84c498/locust-2.35.0.tar.gz", hash = "sha256:97f83e591646ca3227644cfb6d4fa590e9a3e3d791ab18b216ca98be235b9b24", size = 2240690, upload_time = "2025-04-16T12:10:25.037Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/6d/90/55d4fbc8911e5e6ec4072caaca9e8b7b2b11279435c0d1330c9966b0c898/locust-2.36.2.tar.gz", hash = "sha256:604aff7535f5a83b7f666d32373b2dc74ad260c7c3d1dc274f4c82844be72eb6", size = 2251110, upload_time = "2025-04-25T14:03:35.919Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/15/9e92757c08af3f0c0168ab6480315ed6374396d635f70055df5c42cfa672/locust-2.35.0-py3-none-any.whl", hash = "sha256:fb9e0ec25c5db3ed6a3c6d48e7236d7c2c370b0ddae102e9badcb2d3d101abde", size = 2258054, upload_time = "2025-04-16T12:10:22.608Z" },
|
{ url = "https://files.pythonhosted.org/packages/ab/f5/99dab104be69122eee3513dcdc6e0b32d59ca1f4cfd8715470c5f3aa7643/locust-2.36.2-py3-none-any.whl", hash = "sha256:74239f493f44035b25a87a0665deadf41d213b3dcd45774398e511dec15e26eb", size = 2267937, upload_time = "2025-04-25T14:03:33.671Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "locust-cloud"
|
||||||
|
version = "1.20.7"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "configargparse" },
|
||||||
|
{ name = "gevent" },
|
||||||
|
{ name = "platformdirs" },
|
||||||
|
{ name = "python-socketio", extra = ["client"] },
|
||||||
|
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/94/47/1ec2478f3d4e526fb8d667b01a75b22093b2e66aea665b5369dd656ceec9/locust_cloud-1.20.7.tar.gz", hash = "sha256:24c16b767adffab51b97f489bcf142e16e2439354fb4296ecbb3e87ad20e220a", size = 448622, upload_time = "2025-04-28T11:01:49.381Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/07/62b5b174c77d4281235405f1ffd439f12a877e434e007a24a5299c461e39/locust_cloud-1.20.7-py3-none-any.whl", hash = "sha256:f38214e77993d0ee87114dafa857e1689789ed4bfe4ae57c2b9dc754674f08bc", size = 406619, upload_time = "2025-04-28T11:01:43.135Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1722,11 +1748,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "4.1.0"
|
version = "4.3.7"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/62/d1/7feaaacb1a3faeba96c06e6c5091f90695cc0f94b7e8e1a3a3fe2b33ff9a/platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420", size = 19760, upload_time = "2023-12-04T15:32:15.925Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291, upload_time = "2025-03-19T20:36:10.989Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/53/42fe5eab4a09d251a76d0043e018172db324a23fcdac70f77a551c11f618/platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", size = 17420, upload_time = "2023-12-04T15:32:13.795Z" },
|
{ url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499, upload_time = "2025-03-19T20:36:09.038Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2005,6 +2031,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/44/2f/62ea1c8b593f4e093cc1a7768f0d46112107e790c3e478532329e434f00b/python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a", size = 19482, upload_time = "2023-02-24T06:46:36.009Z" },
|
{ url = "https://files.pythonhosted.org/packages/44/2f/62ea1c8b593f4e093cc1a7768f0d46112107e790c3e478532329e434f00b/python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a", size = 19482, upload_time = "2023-02-24T06:46:36.009Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-engineio"
|
||||||
|
version = "4.12.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "simple-websocket" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f7/e1/eee1129544b7f78fa2afa9fa0fce153cdcb21015b9b331d1b8adf90f45cb/python_engineio-4.12.0.tar.gz", hash = "sha256:f42a36a868d7063aa10ddccf6bd6117a169b6bd00d7ca53999772093b62014f9", size = 91503, upload_time = "2025-04-12T15:30:23.905Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/f7/0aeea75424c47633c1d98557a2323be23bed31fa950f00161b34a5150d06/python_engineio-4.12.0-py3-none-any.whl", hash = "sha256:a0c47c129c39777e8ebc6d18011efd50db2144e4e8f08983acae8a3614626535", size = 59319, upload_time = "2025-04-12T15:30:22.325Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-multipart"
|
name = "python-multipart"
|
||||||
version = "0.0.20"
|
version = "0.0.20"
|
||||||
@@ -2014,6 +2052,25 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload_time = "2024-12-16T19:45:44.423Z" },
|
{ url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload_time = "2024-12-16T19:45:44.423Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-socketio"
|
||||||
|
version = "5.13.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "bidict" },
|
||||||
|
{ name = "python-engineio" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/21/1a/396d50ccf06ee539fa758ce5623b59a9cb27637fc4b2dc07ed08bf495e77/python_socketio-5.13.0.tar.gz", hash = "sha256:ac4e19a0302ae812e23b712ec8b6427ca0521f7c582d6abb096e36e24a263029", size = 121125, upload_time = "2025-04-12T15:46:59.933Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/32/b4fb8585d1be0f68bde7e110dffbcf354915f77ad8c778563f0ad9655c02/python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf", size = 77800, upload_time = "2025-04-12T15:46:58.412Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.optional-dependencies]
|
||||||
|
client = [
|
||||||
|
{ name = "requests" },
|
||||||
|
{ name = "websocket-client" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pywin32"
|
name = "pywin32"
|
||||||
version = "306"
|
version = "306"
|
||||||
@@ -2226,27 +2283,27 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.11.6"
|
version = "0.11.7"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/d9/11/bcef6784c7e5d200b8a1f5c2ddf53e5da0efec37e6e5a44d163fb97e04ba/ruff-0.11.6.tar.gz", hash = "sha256:bec8bcc3ac228a45ccc811e45f7eb61b950dbf4cf31a67fa89352574b01c7d79", size = 4010053, upload_time = "2025-04-17T13:35:53.905Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/5b/89/6f9c9674818ac2e9cc2f2b35b704b7768656e6b7c139064fc7ba8fbc99f1/ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4", size = 4054861, upload_time = "2025-04-24T18:49:37.007Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/6e/1f/8848b625100ebcc8740c8bac5b5dd8ba97dd4ee210970e98832092c1635b/ruff-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:d84dcbe74cf9356d1bdb4a78cf74fd47c740bf7bdeb7529068f69b08272239a1", size = 10248105, upload_time = "2025-04-17T13:35:14.758Z" },
|
{ url = "https://files.pythonhosted.org/packages/b4/ec/21927cb906c5614b786d1621dba405e3d44f6e473872e6df5d1a6bca0455/ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c", size = 10245403, upload_time = "2025-04-24T18:48:40.459Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e0/47/c44036e70c6cc11e6ee24399c2a1e1f1e99be5152bd7dff0190e4b325b76/ruff-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9bc583628e1096148011a5d51ff3c836f51899e61112e03e5f2b1573a9b726de", size = 11001494, upload_time = "2025-04-17T13:35:18.444Z" },
|
{ url = "https://files.pythonhosted.org/packages/e2/af/fec85b6c2c725bcb062a354dd7cbc1eed53c33ff3aa665165871c9c16ddf/ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee", size = 11007166, upload_time = "2025-04-24T18:48:44.742Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ed/5b/170444061650202d84d316e8f112de02d092bff71fafe060d3542f5bc5df/ruff-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2959049faeb5ba5e3b378709e9d1bf0cab06528b306b9dd6ebd2a312127964a", size = 10352151, upload_time = "2025-04-17T13:35:20.563Z" },
|
{ url = "https://files.pythonhosted.org/packages/31/9a/2d0d260a58e81f388800343a45898fd8df73c608b8261c370058b675319a/ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada", size = 10378076, upload_time = "2025-04-24T18:48:47.918Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/91/f02839fb3787c678e112c8865f2c3e87cfe1744dcc96ff9fc56cfb97dda2/ruff-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c5d4e30d9d0de7fedbfb3e9e20d134b73a30c1e74b596f40f0629d5c28a193", size = 10541951, upload_time = "2025-04-17T13:35:22.522Z" },
|
{ url = "https://files.pythonhosted.org/packages/c2/c4/9b09b45051404d2e7dd6d9dbcbabaa5ab0093f9febcae664876a77b9ad53/ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64", size = 10557138, upload_time = "2025-04-24T18:48:51.707Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9e/f3/c09933306096ff7a08abede3cc2534d6fcf5529ccd26504c16bf363989b5/ruff-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4b9a4e1439f7d0a091c6763a100cef8fbdc10d68593df6f3cfa5abdd9246e", size = 10079195, upload_time = "2025-04-17T13:35:24.485Z" },
|
{ url = "https://files.pythonhosted.org/packages/5e/5e/f62a1b6669870a591ed7db771c332fabb30f83c967f376b05e7c91bccd14/ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201", size = 10095726, upload_time = "2025-04-24T18:48:54.243Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e0/0d/a87f8933fccbc0d8c653cfbf44bedda69c9582ba09210a309c066794e2ee/ruff-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5edf270223dd622218256569636dc3e708c2cb989242262fe378609eccf1308", size = 11698918, upload_time = "2025-04-17T13:35:26.504Z" },
|
{ url = "https://files.pythonhosted.org/packages/45/59/a7aa8e716f4cbe07c3500a391e58c52caf665bb242bf8be42c62adef649c/ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6", size = 11672265, upload_time = "2025-04-24T18:48:57.639Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/52/7d/8eac0bd083ea8a0b55b7e4628428203441ca68cd55e0b67c135a4bc6e309/ruff-0.11.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f55844e818206a9dd31ff27f91385afb538067e2dc0beb05f82c293ab84f7d55", size = 12319426, upload_time = "2025-04-17T13:35:28.452Z" },
|
{ url = "https://files.pythonhosted.org/packages/dd/e3/101a8b707481f37aca5f0fcc3e42932fa38b51add87bfbd8e41ab14adb24/ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4", size = 12331418, upload_time = "2025-04-24T18:49:00.697Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/dc/d0c17d875662d0c86fadcf4ca014ab2001f867621b793d5d7eef01b9dcce/ruff-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d8f782286c5ff562e4e00344f954b9320026d8e3fae2ba9e6948443fafd9ffc", size = 11791012, upload_time = "2025-04-17T13:35:30.455Z" },
|
{ url = "https://files.pythonhosted.org/packages/dd/71/037f76cbe712f5cbc7b852e4916cd3cf32301a30351818d32ab71580d1c0/ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e", size = 11794506, upload_time = "2025-04-24T18:49:03.545Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f9/f3/81a1aea17f1065449a72509fc7ccc3659cf93148b136ff2a8291c4bc3ef1/ruff-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01c63ba219514271cee955cd0adc26a4083df1956d57847978383b0e50ffd7d2", size = 13949947, upload_time = "2025-04-17T13:35:33.133Z" },
|
{ url = "https://files.pythonhosted.org/packages/ca/de/e450b6bab1fc60ef263ef8fcda077fb4977601184877dce1c59109356084/ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63", size = 13939084, upload_time = "2025-04-24T18:49:07.159Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/61/9f/a3e34de425a668284e7024ee6fd41f452f6fa9d817f1f3495b46e5e3a407/ruff-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15adac20ef2ca296dd3d8e2bedc6202ea6de81c091a74661c3666e5c4c223ff6", size = 11471753, upload_time = "2025-04-17T13:35:35.416Z" },
|
{ url = "https://files.pythonhosted.org/packages/0e/2c/1e364cc92970075d7d04c69c928430b23e43a433f044474f57e425cbed37/ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502", size = 11450441, upload_time = "2025-04-24T18:49:11.41Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/c5/4a57a86d12542c0f6e2744f262257b2aa5a3783098ec14e40f3e4b3a354a/ruff-0.11.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4dd6b09e98144ad7aec026f5588e493c65057d1b387dd937d7787baa531d9bc2", size = 10417121, upload_time = "2025-04-17T13:35:38.224Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/7d/1b048eb460517ff9accd78bca0fa6ae61df2b276010538e586f834f5e402/ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92", size = 10441060, upload_time = "2025-04-24T18:49:14.184Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/58/3f/a3b4346dff07ef5b862e2ba06d98fcbf71f66f04cf01d375e871382b5e4b/ruff-0.11.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:45b2e1d6c0eed89c248d024ea95074d0e09988d8e7b1dad8d3ab9a67017a5b03", size = 10073829, upload_time = "2025-04-17T13:35:40.255Z" },
|
{ url = "https://files.pythonhosted.org/packages/3a/57/8dc6ccfd8380e5ca3d13ff7591e8ba46a3b330323515a4996b991b10bd5d/ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94", size = 10058689, upload_time = "2025-04-24T18:49:17.559Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/93/cc/7ed02e0b86a649216b845b3ac66ed55d8aa86f5898c5f1691797f408fcb9/ruff-0.11.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd40de4115b2ec4850302f1a1d8067f42e70b4990b68838ccb9ccd9f110c5e8b", size = 11076108, upload_time = "2025-04-17T13:35:42.559Z" },
|
{ url = "https://files.pythonhosted.org/packages/23/bf/20487561ed72654147817885559ba2aa705272d8b5dee7654d3ef2dbf912/ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6", size = 11073703, upload_time = "2025-04-24T18:49:20.247Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/39/5e/5b09840fef0eff1a6fa1dea6296c07d09c17cb6fb94ed5593aa591b50460/ruff-0.11.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:77cda2dfbac1ab73aef5e514c4cbfc4ec1fbef4b84a44c736cc26f61b3814cd9", size = 11512366, upload_time = "2025-04-17T13:35:45.702Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/27/04f2db95f4ef73dccedd0c21daf9991cc3b7f29901a4362057b132075aa4/ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6", size = 11532822, upload_time = "2025-04-24T18:49:23.765Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/4c/1cd5a84a412d3626335ae69f5f9de2bb554eea0faf46deb1f0cb48534042/ruff-0.11.6-py3-none-win32.whl", hash = "sha256:5151a871554be3036cd6e51d0ec6eef56334d74dfe1702de717a995ee3d5b287", size = 10485900, upload_time = "2025-04-17T13:35:47.695Z" },
|
{ url = "https://files.pythonhosted.org/packages/e1/72/43b123e4db52144c8add336581de52185097545981ff6e9e58a21861c250/ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26", size = 10362436, upload_time = "2025-04-24T18:49:27.377Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/42/46/8997872bc44d43df986491c18d4418f1caff03bc47b7f381261d62c23442/ruff-0.11.6-py3-none-win_amd64.whl", hash = "sha256:cce85721d09c51f3b782c331b0abd07e9d7d5f775840379c640606d3159cae0e", size = 11558592, upload_time = "2025-04-17T13:35:49.837Z" },
|
{ url = "https://files.pythonhosted.org/packages/c5/a0/3e58cd76fdee53d5c8ce7a56d84540833f924ccdf2c7d657cb009e604d82/ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a", size = 11566676, upload_time = "2025-04-24T18:49:30.938Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766, upload_time = "2025-04-17T13:35:52.014Z" },
|
{ url = "https://files.pythonhosted.org/packages/68/ca/69d7c7752bce162d1516e5592b1cc6b6668e9328c0d270609ddbeeadd7cf/ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177", size = 10677936, upload_time = "2025-04-24T18:49:34.392Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2349,6 +2406,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ef/15/88e46eb9387e905704b69849618e699dc2f54407d8953cc4ec4b8b46528d/setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc", size = 931070, upload_time = "2024-07-09T16:07:58.829Z" },
|
{ url = "https://files.pythonhosted.org/packages/ef/15/88e46eb9387e905704b69849618e699dc2f54407d8953cc4ec4b8b46528d/setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc", size = 931070, upload_time = "2024-07-09T16:07:58.829Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simple-websocket"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "wsproto" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b0/d4/bfa032f961103eba93de583b161f0e6a5b63cebb8f2c7d0c6e6efe1e3d2e/simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4", size = 17300, upload_time = "2024-10-10T22:39:31.412Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c", size = 13842, upload_time = "2024-10-10T22:39:29.645Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
@@ -2652,6 +2721,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload_time = "2024-01-06T02:10:55.763Z" },
|
{ url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload_time = "2024-01-06T02:10:55.763Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "websocket-client"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e6/30/fba0d96b4b5fbf5948ed3f4681f7da2f9f64512e1d303f94b4cc174c24a5/websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da", size = 54648, upload_time = "2024-04-23T22:16:16.976Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload_time = "2024-04-23T22:16:14.422Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "websockets"
|
name = "websockets"
|
||||||
version = "12.0"
|
version = "12.0"
|
||||||
@@ -2711,6 +2789,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/9d/6e/e792999e816d19d7fcbfa94c730936750036d65656a76a5a688b57a656c4/werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8", size = 227274, upload_time = "2024-05-05T23:10:29.567Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/6e/e792999e816d19d7fcbfa94c730936750036d65656a76a5a688b57a656c4/werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8", size = 227274, upload_time = "2024-05-05T23:10:29.567Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wsproto"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "h11" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload_time = "2022-08-23T19:58:21.447Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload_time = "2022-08-23T19:58:19.96Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zope-event"
|
name = "zope-event"
|
||||||
version = "5.0"
|
version = "5.0"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
android:maxSdkVersion="32" />
|
android:maxSdkVersion="32" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="32" />
|
android:maxSdkVersion="32" />
|
||||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.MANAGE_MEDIA" />
|
<uses-permission android:name="android.permission.MANAGE_MEDIA" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package app.alextran.immich
|
package app.alextran.immich
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.ContentValues
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||||
@@ -23,6 +23,7 @@ import io.flutter.plugin.common.PluginRegistry
|
|||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android plugin for Dart `BackgroundService` and file trash operations
|
* Android plugin for Dart `BackgroundService` and file trash operations
|
||||||
@@ -33,7 +34,8 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
|
|||||||
private var fileTrashChannel: MethodChannel? = null
|
private var fileTrashChannel: MethodChannel? = null
|
||||||
private var context: Context? = null
|
private var context: Context? = null
|
||||||
private var pendingResult: Result? = null
|
private var pendingResult: Result? = null
|
||||||
private val PERMISSION_REQUEST_CODE = 1001
|
private val permissionRequestCode = 1001
|
||||||
|
private val trashRequestCode = 1002
|
||||||
private var activityBinding: ActivityPluginBinding? = null
|
private var activityBinding: ActivityPluginBinding? = null
|
||||||
|
|
||||||
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
@@ -138,36 +140,35 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
|
|||||||
|
|
||||||
// File Trash methods moved from MainActivity
|
// File Trash methods moved from MainActivity
|
||||||
"moveToTrash" -> {
|
"moveToTrash" -> {
|
||||||
val fileName = call.argument<String>("fileName")
|
val mediaUrls = call.argument<List<String>>("mediaUrls")
|
||||||
if (fileName != null) {
|
if (mediaUrls != null) {
|
||||||
if (hasManageStoragePermission()) {
|
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && hasManageMediaPermission()) {
|
||||||
val success = moveToTrash(fileName)
|
moveToTrash(mediaUrls, result)
|
||||||
result.success(success)
|
|
||||||
} else {
|
} else {
|
||||||
result.error("PERMISSION_DENIED", "Storage permission required", null)
|
result.error("PERMISSION_DENIED", "Media permission required", null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.error("INVALID_NAME", "The file name is not specified.", null)
|
result.error("INVALID_NAME", "The mediaUrls is not specified.", null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"restoreFromTrash" -> {
|
"restoreFromTrash" -> {
|
||||||
val fileName = call.argument<String>("fileName")
|
val fileName = call.argument<String>("fileName")
|
||||||
if (fileName != null) {
|
val type = call.argument<Int>("type")
|
||||||
if (hasManageStoragePermission()) {
|
if (fileName != null && type != null) {
|
||||||
val success = untrashImage(fileName)
|
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && hasManageMediaPermission()) {
|
||||||
result.success(success)
|
restoreFromTrash(fileName, type, result)
|
||||||
} else {
|
} else {
|
||||||
result.error("PERMISSION_DENIED", "Storage permission required", null)
|
result.error("PERMISSION_DENIED", "Media permission required", null)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.error("INVALID_NAME", "The file name is not specified.", null)
|
result.error("INVALID_NAME", "The file name is not specified.", null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"requestManageStoragePermission" -> {
|
"requestManageMediaPermission" -> {
|
||||||
if (!hasManageStoragePermission()) {
|
if (!hasManageMediaPermission()) {
|
||||||
requestManageStoragePermission(result)
|
requestManageMediaPermission(result)
|
||||||
} else {
|
} else {
|
||||||
Log.e("Manage storage permission", "Permission already granted")
|
Log.e("Manage storage permission", "Permission already granted")
|
||||||
result.success(true)
|
result.success(true)
|
||||||
@@ -178,100 +179,98 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// File Trash methods moved from MainActivity
|
private fun hasManageMediaPermission(): Boolean {
|
||||||
private fun hasManageStoragePermission(): Boolean {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
MediaStore.canManageMedia(context!!);
|
||||||
Environment.isExternalStorageManager()
|
} else {
|
||||||
} else {
|
false
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestManageStoragePermission(result: Result) {
|
private fun requestManageMediaPermission(result: Result) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
pendingResult = result // Store the result callback
|
pendingResult = result // Store the result callback
|
||||||
val activity = activityBinding?.activity ?: return
|
val activity = activityBinding?.activity ?: return
|
||||||
|
|
||||||
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
|
val intent = Intent(Settings.ACTION_REQUEST_MANAGE_MEDIA)
|
||||||
intent.data = Uri.parse("package:${activity.packageName}")
|
intent.data = "package:${activity.packageName}".toUri()
|
||||||
activity.startActivityForResult(intent, PERMISSION_REQUEST_CODE)
|
activity.startActivityForResult(intent, permissionRequestCode)
|
||||||
} else {
|
} else {
|
||||||
result.success(true)
|
result.success(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveToTrash(fileName: String): Boolean {
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
val contentResolver = context?.contentResolver ?: return false
|
private fun moveToTrash(mediaUrls: List<String>, result: Result) {
|
||||||
val uri = getFileUri(fileName)
|
val urisToTrash = mediaUrls.map { it.toUri() }
|
||||||
|
if (urisToTrash.isEmpty()) {
|
||||||
|
result.error("INVALID_ARGS", "No valid URIs provided", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTrash(urisToTrash, true, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
private fun restoreFromTrash(name: String, type: Int, result: Result) {
|
||||||
|
val uri = getTrashedFileUri(name, type)
|
||||||
|
if (uri == null) {
|
||||||
|
Log.e("TrashError", "Asset Uri cannot be found obtained")
|
||||||
|
result.error("TrashError", "Asset Uri cannot be found obtained", null)
|
||||||
|
return
|
||||||
|
}
|
||||||
Log.e("FILE_URI", uri.toString())
|
Log.e("FILE_URI", uri.toString())
|
||||||
return uri?.let { moveToTrash(it) } ?: false
|
uri.let { toggleTrash(listOf(it), false, result) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveToTrash(contentUri: Uri): Boolean {
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
val contentResolver = context?.contentResolver ?: return false
|
private fun toggleTrash(contentUris: List<Uri>, isTrashed: Boolean, result: Result) {
|
||||||
return try {
|
val activity = activityBinding?.activity
|
||||||
val values = ContentValues().apply {
|
val contentResolver = context?.contentResolver
|
||||||
put(MediaStore.MediaColumns.IS_TRASHED, 1) // Move to trash
|
if (activity == null || contentResolver == null) {
|
||||||
|
result.error("TrashError", "Activity or ContentResolver not available", null)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
val updated = contentResolver.update(contentUri, values, null, null)
|
|
||||||
updated > 0
|
try {
|
||||||
} catch (e: Exception) {
|
val pendingIntent = MediaStore.createTrashRequest(contentResolver, contentUris, isTrashed)
|
||||||
Log.e("TrashError", "Error moving to trash", e)
|
pendingResult = result // Store for onActivityResult
|
||||||
false
|
activity.startIntentSenderForResult(
|
||||||
|
pendingIntent.intentSender,
|
||||||
|
trashRequestCode,
|
||||||
|
null, 0, 0, 0
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("TrashError", "Error creating or starting trash request", e)
|
||||||
|
result.error("TrashError", "Error creating or starting trash request", null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFileUri(fileName: String): Uri? {
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
|
private fun getTrashedFileUri(fileName: String, type: Int): Uri? {
|
||||||
val contentResolver = context?.contentResolver ?: return null
|
val contentResolver = context?.contentResolver ?: return null
|
||||||
val contentUri = MediaStore.Files.getContentUri("external")
|
val queryUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
||||||
val projection = arrayOf(MediaStore.Images.Media._ID)
|
|
||||||
val selection = "${MediaStore.Images.Media.DISPLAY_NAME} = ?"
|
|
||||||
val selectionArgs = arrayOf(fileName)
|
|
||||||
var fileUri: Uri? = null
|
|
||||||
|
|
||||||
contentResolver.query(contentUri, projection, selection, selectionArgs, null)?.use { cursor ->
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
|
|
||||||
fileUri = ContentUris.withAppendedId(contentUri, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fileUri
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun untrashImage(name: String): Boolean {
|
|
||||||
val contentResolver = context?.contentResolver ?: return false
|
|
||||||
val uri = getTrashedFileUri(contentResolver, name)
|
|
||||||
Log.e("FILE_URI", uri.toString())
|
|
||||||
return uri?.let { untrashImage(it) } ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun untrashImage(contentUri: Uri): Boolean {
|
|
||||||
val contentResolver = context?.contentResolver ?: return false
|
|
||||||
return try {
|
|
||||||
val values = ContentValues().apply {
|
|
||||||
put(MediaStore.MediaColumns.IS_TRASHED, 0) // Restore file
|
|
||||||
}
|
|
||||||
val updated = contentResolver.update(contentUri, values, null, null)
|
|
||||||
updated > 0
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("TrashError", "Error restoring file", e)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTrashedFileUri(contentResolver: ContentResolver, fileName: String): Uri? {
|
|
||||||
val contentUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
|
||||||
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
|
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
|
||||||
|
|
||||||
val queryArgs = Bundle().apply {
|
val queryArgs = Bundle().apply {
|
||||||
putString(ContentResolver.QUERY_ARG_SQL_SELECTION, "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?")
|
putString(
|
||||||
|
ContentResolver.QUERY_ARG_SQL_SELECTION,
|
||||||
|
"${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?"
|
||||||
|
)
|
||||||
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(fileName))
|
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(fileName))
|
||||||
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY)
|
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY)
|
||||||
}
|
}
|
||||||
|
|
||||||
contentResolver.query(contentUri, projection, queryArgs, null)?.use { cursor ->
|
contentResolver.query(queryUri, projection, queryArgs, null)?.use { cursor ->
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
|
val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
|
||||||
|
// same order as AssetType from dart
|
||||||
|
val contentUri = when (type) {
|
||||||
|
1 -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||||
|
2 -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||||
|
3 -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
|
||||||
|
else -> queryUri
|
||||||
|
}
|
||||||
return ContentUris.withAppendedId(contentUri, id)
|
return ContentUris.withAppendedId(contentUri, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,12 +300,19 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
|
|||||||
|
|
||||||
// ActivityResultListener implementation
|
// ActivityResultListener implementation
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
|
||||||
if (requestCode == PERMISSION_REQUEST_CODE) {
|
if (requestCode == permissionRequestCode) {
|
||||||
val granted = hasManageStoragePermission()
|
val granted = hasManageMediaPermission()
|
||||||
pendingResult?.success(granted)
|
pendingResult?.success(granted)
|
||||||
pendingResult = null
|
pendingResult = null
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestCode == trashRequestCode) {
|
||||||
|
val approved = resultCode == Activity.RESULT_OK
|
||||||
|
pendingResult?.success(approved)
|
||||||
|
pendingResult = null
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ platform :android do
|
|||||||
task: 'bundle',
|
task: 'bundle',
|
||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 194,
|
"android.injected.version.code" => 197,
|
||||||
"android.injected.version.name" => "1.132.0",
|
"android.injected.version.name" => "1.132.3",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||||
|
|||||||
@@ -261,9 +261,11 @@
|
|||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
LastSwiftMigration = 1100;
|
LastSwiftMigration = 1100;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
FAC6F88F2D287C890078CB2F = {
|
FAC6F88F2D287C890078CB2F = {
|
||||||
CreatedOnToolsVersion = 16.0;
|
CreatedOnToolsVersion = 16.0;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -541,7 +543,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 201;
|
CURRENT_PROJECT_VERSION = 205;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -685,7 +687,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 201;
|
CURRENT_PROJECT_VERSION = 205;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -715,7 +717,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 201;
|
CURRENT_PROJECT_VERSION = 205;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -748,7 +750,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 201;
|
CURRENT_PROJECT_VERSION = 205;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -769,6 +771,7 @@
|
|||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug.ShareExtension;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
@@ -791,7 +794,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 201;
|
CURRENT_PROJECT_VERSION = 205;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -811,6 +814,7 @@
|
|||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.ShareExtension;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -831,7 +835,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 201;
|
CURRENT_PROJECT_VERSION = 205;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -851,6 +855,7 @@
|
|||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile.ShareExtension;
|
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile.ShareExtension;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.131.3</string>
|
<string>1.132.3</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>201</string>
|
<string>205</string>
|
||||||
<key>FLTEnableImpeller</key>
|
<key>FLTEnableImpeller</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -18,8 +18,11 @@ default_platform(:ios)
|
|||||||
platform :ios do
|
platform :ios do
|
||||||
desc "iOS Release"
|
desc "iOS Release"
|
||||||
lane :release do
|
lane :release do
|
||||||
|
enable_automatic_code_signing(
|
||||||
|
path: "./Runner.xcodeproj",
|
||||||
|
)
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.132.0"
|
version_number: "1.132.3"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
abstract interface class ILocalFilesManager {
|
abstract interface class ILocalFilesManager {
|
||||||
Future<bool> moveToTrash(String fileName);
|
Future<bool> moveToTrash(List<String> mediaUrls);
|
||||||
Future<bool> restoreFromTrash(String fileName);
|
Future<bool> restoreFromTrash(String fileName, int type);
|
||||||
Future<bool> requestManageStoragePermission();
|
Future<bool> requestManageMediaPermission();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
@@ -13,7 +12,6 @@ import 'package:immich_mobile/providers/server_info.provider.dart';
|
|||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||||
import 'package:immich_mobile/utils/map_utils.dart';
|
|
||||||
import 'package:immich_mobile/widgets/album/album_thumbnail_card.dart';
|
import 'package:immich_mobile/widgets/album/album_thumbnail_card.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_app_bar.dart';
|
import 'package:immich_mobile/widgets/common/immich_app_bar.dart';
|
||||||
import 'package:immich_mobile/widgets/common/user_avatar.dart';
|
import 'package:immich_mobile/widgets/common/user_avatar.dart';
|
||||||
@@ -357,66 +355,51 @@ class PlacesCollectionCard extends StatelessWidget {
|
|||||||
final widthFactor = isTablet ? 0.25 : 0.5;
|
final widthFactor = isTablet ? 0.25 : 0.5;
|
||||||
final size = context.width * widthFactor - 20.0;
|
final size = context.width * widthFactor - 20.0;
|
||||||
|
|
||||||
return FutureBuilder<(Position?, LocationPermission?)>(
|
return GestureDetector(
|
||||||
future: MapUtils.checkPermAndGetLocation(
|
onTap: () => context.pushRoute(
|
||||||
context: context,
|
PlacesCollectionRoute(
|
||||||
silent: true,
|
currentLocation: null,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
builder: (context, snapshot) {
|
child: Column(
|
||||||
var position = snapshot.data?.$1;
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
return GestureDetector(
|
children: [
|
||||||
onTap: () => context.pushRoute(
|
SizedBox(
|
||||||
PlacesCollectionRoute(
|
height: size,
|
||||||
currentLocation: position != null
|
width: size,
|
||||||
? LatLng(position.latitude, position.longitude)
|
child: DecoratedBox(
|
||||||
: null,
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(20)),
|
||||||
|
color:
|
||||||
|
context.colorScheme.secondaryContainer.withAlpha(100),
|
||||||
|
),
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: MapThumbnail(
|
||||||
|
zoom: 8,
|
||||||
|
centre: const LatLng(
|
||||||
|
21.44950,
|
||||||
|
-157.91959,
|
||||||
|
),
|
||||||
|
showAttribution: false,
|
||||||
|
themeMode: context.isDarkTheme
|
||||||
|
? ThemeMode.dark
|
||||||
|
: ThemeMode.light,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
Padding(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
padding: const EdgeInsets.all(8.0),
|
||||||
children: [
|
child: Text(
|
||||||
SizedBox(
|
'places'.tr(),
|
||||||
height: size,
|
style: context.textTheme.titleSmall?.copyWith(
|
||||||
width: size,
|
color: context.colorScheme.onSurface,
|
||||||
child: DecoratedBox(
|
fontWeight: FontWeight.w500,
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
const BorderRadius.all(Radius.circular(20)),
|
|
||||||
color: context.colorScheme.secondaryContainer
|
|
||||||
.withAlpha(100),
|
|
||||||
),
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: snapshot.connectionState ==
|
|
||||||
ConnectionState.waiting
|
|
||||||
? const Center(child: CircularProgressIndicator())
|
|
||||||
: MapThumbnail(
|
|
||||||
zoom: 8,
|
|
||||||
centre: LatLng(
|
|
||||||
position?.latitude ?? 21.44950,
|
|
||||||
position?.longitude ?? -157.91959,
|
|
||||||
),
|
|
||||||
showAttribution: false,
|
|
||||||
themeMode: context.isDarkTheme
|
|
||||||
? ThemeMode.dark
|
|
||||||
: ThemeMode.light,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(
|
|
||||||
'places'.tr(),
|
|
||||||
style: context.textTheme.titleSmall?.copyWith(
|
|
||||||
color: context.colorScheme.onSurface,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class PermissionOnboardingPage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'grant_permission',
|
'continue',
|
||||||
).tr(),
|
).tr(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,21 +3,23 @@ import 'package:immich_mobile/interfaces/local_files_manager.interface.dart';
|
|||||||
import 'package:immich_mobile/utils/local_files_manager.dart';
|
import 'package:immich_mobile/utils/local_files_manager.dart';
|
||||||
|
|
||||||
final localFilesManagerRepositoryProvider =
|
final localFilesManagerRepositoryProvider =
|
||||||
Provider((ref) => LocalFilesManagerRepository());
|
Provider((ref) => const LocalFilesManagerRepository());
|
||||||
|
|
||||||
class LocalFilesManagerRepository implements ILocalFilesManager {
|
class LocalFilesManagerRepository implements ILocalFilesManager {
|
||||||
|
const LocalFilesManagerRepository();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> moveToTrash(String fileName) async {
|
Future<bool> moveToTrash(List<String> mediaUrls) async {
|
||||||
return await LocalFilesManager.moveToTrash(fileName);
|
return await LocalFilesManager.moveToTrash(mediaUrls);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> restoreFromTrash(String fileName) async {
|
Future<bool> restoreFromTrash(String fileName, int type) async {
|
||||||
return await LocalFilesManager.restoreFromTrash(fileName);
|
return await LocalFilesManager.restoreFromTrash(fileName, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> requestManageStoragePermission() async {
|
Future<bool> requestManageMediaPermission() async {
|
||||||
return await LocalFilesManager.requestManageStoragePermission();
|
return await LocalFilesManager.requestManageMediaPermission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,9 +255,12 @@ class SyncService {
|
|||||||
.where((asset) => idsToDelete.contains(asset.remoteId))
|
.where((asset) => idsToDelete.contains(asset.remoteId))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
for (var asset in matchedAssets) {
|
final mediaUrls = await Future.wait(
|
||||||
_localFilesManager.moveToTrash(asset.fileName);
|
matchedAssets
|
||||||
}
|
.map((asset) => asset.local?.getMediaUrl() ?? Future.value(null)),
|
||||||
|
);
|
||||||
|
|
||||||
|
await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes remote-only assets, updates merged assets to be local-only
|
/// Deletes remote-only assets, updates merged assets to be local-only
|
||||||
@@ -819,13 +822,29 @@ class SyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _toggleTrashStatusForAssets(List<Asset> assetsList) async {
|
Future<void> _toggleTrashStatusForAssets(List<Asset> assetsList) async {
|
||||||
for (var asset in assetsList) {
|
final trashMediaUrls = <String>[];
|
||||||
|
|
||||||
|
for (final asset in assetsList) {
|
||||||
if (asset.isTrashed) {
|
if (asset.isTrashed) {
|
||||||
_localFilesManager.moveToTrash(asset.fileName);
|
final mediaUrl = await asset.local?.getMediaUrl();
|
||||||
|
if (mediaUrl == null) {
|
||||||
|
_log.warning(
|
||||||
|
"Failed to get media URL for asset ${asset.name} while moving to trash",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
trashMediaUrls.add(mediaUrl);
|
||||||
} else {
|
} else {
|
||||||
_localFilesManager.restoreFromTrash(asset.fileName);
|
await _localFilesManager.restoreFromTrash(
|
||||||
|
asset.fileName,
|
||||||
|
asset.type.index,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trashMediaUrls.isNotEmpty) {
|
||||||
|
await _localFilesManager.moveToTrash(trashMediaUrls);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts or updates the assets in the database with their ExifInfo (if any)
|
/// Inserts or updates the assets in the database with their ExifInfo (if any)
|
||||||
|
|||||||
@@ -1,38 +1,37 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
class LocalFilesManager {
|
abstract final class LocalFilesManager {
|
||||||
|
static final Logger _logger = Logger('LocalFilesManager');
|
||||||
static const MethodChannel _channel = MethodChannel('file_trash');
|
static const MethodChannel _channel = MethodChannel('file_trash');
|
||||||
|
|
||||||
static Future<bool> moveToTrash(String fileName) async {
|
static Future<bool> moveToTrash(List<String> mediaUrls) async {
|
||||||
try {
|
try {
|
||||||
final bool success =
|
return await _channel
|
||||||
await _channel.invokeMethod('moveToTrash', {'fileName': fileName});
|
.invokeMethod('moveToTrash', {'mediaUrls': mediaUrls});
|
||||||
return success;
|
} catch (e, s) {
|
||||||
} on PlatformException catch (e) {
|
_logger.warning('Error moving file to trash', e, s);
|
||||||
debugPrint('Error moving to trash: ${e.message}');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> restoreFromTrash(String fileName) async {
|
static Future<bool> restoreFromTrash(String fileName, int type) async {
|
||||||
try {
|
try {
|
||||||
final bool success = await _channel
|
return await _channel.invokeMethod(
|
||||||
.invokeMethod('restoreFromTrash', {'fileName': fileName});
|
'restoreFromTrash',
|
||||||
return success;
|
{'fileName': fileName, 'type': type},
|
||||||
} on PlatformException catch (e) {
|
);
|
||||||
debugPrint('Error restoring file: ${e.message}');
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error restore file from trash', e, s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool> requestManageStoragePermission() async {
|
static Future<bool> requestManageMediaPermission() async {
|
||||||
try {
|
try {
|
||||||
final bool success =
|
return await _channel.invokeMethod('requestManageMediaPermission');
|
||||||
await _channel.invokeMethod('requestManageStoragePermission');
|
} catch (e, s) {
|
||||||
return success;
|
_logger.warning('Error requesting manage media permission', e, s);
|
||||||
} on PlatformException catch (e) {
|
|
||||||
debugPrint('Error requesting permission: ${e.message}');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/android_device_asset.entity.dart';
|
import 'package:immich_mobile/entities/android_device_asset.entity.dart';
|
||||||
@@ -17,6 +17,8 @@ import 'package:immich_mobile/infrastructure/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
// ignore: import_rule_photo_manager
|
||||||
|
import 'package:photo_manager/photo_manager.dart';
|
||||||
|
|
||||||
const int targetVersion = 10;
|
const int targetVersion = 10;
|
||||||
|
|
||||||
@@ -69,14 +71,45 @@ Future<void> _migrateDeviceAsset(Isar db) async {
|
|||||||
: (await db.iOSDeviceAssets.where().findAll())
|
: (await db.iOSDeviceAssets.where().findAll())
|
||||||
.map((i) => _DeviceAsset(assetId: i.id, hash: i.hash))
|
.map((i) => _DeviceAsset(assetId: i.id, hash: i.hash))
|
||||||
.toList();
|
.toList();
|
||||||
final localAssets = (await db.assets
|
|
||||||
.where()
|
final PermissionState ps = await PhotoManager.requestPermissionExtend();
|
||||||
.anyOf(ids, (query, id) => query.localIdEqualTo(id.assetId))
|
if (!ps.hasAccess) {
|
||||||
.findAll())
|
if (kDebugMode) {
|
||||||
.map((a) => _DeviceAsset(assetId: a.localId!, dateTime: a.fileModifiedAt))
|
debugPrint(
|
||||||
.toList();
|
"[MIGRATION] Photo library permission not granted. Skipping device asset migration.",
|
||||||
debugPrint("Device Asset Ids length - ${ids.length}");
|
);
|
||||||
debugPrint("Local Asset Ids length - ${localAssets.length}");
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<_DeviceAsset> localAssets = [];
|
||||||
|
final List<AssetPathEntity> paths =
|
||||||
|
await PhotoManager.getAssetPathList(onlyAll: true);
|
||||||
|
|
||||||
|
if (paths.isEmpty) {
|
||||||
|
localAssets = (await db.assets
|
||||||
|
.where()
|
||||||
|
.anyOf(ids, (query, id) => query.localIdEqualTo(id.assetId))
|
||||||
|
.findAll())
|
||||||
|
.map(
|
||||||
|
(a) => _DeviceAsset(assetId: a.localId!, dateTime: a.fileModifiedAt),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
} else {
|
||||||
|
final AssetPathEntity albumWithAll = paths.first;
|
||||||
|
final int assetCount = await albumWithAll.assetCountAsync;
|
||||||
|
|
||||||
|
final List<AssetEntity> allDeviceAssets =
|
||||||
|
await albumWithAll.getAssetListRange(start: 0, end: assetCount);
|
||||||
|
|
||||||
|
localAssets = allDeviceAssets
|
||||||
|
.map((a) => _DeviceAsset(assetId: a.id, dateTime: a.modifiedDateTime))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint("[MIGRATION] Device Asset Ids length - ${ids.length}");
|
||||||
|
debugPrint("[MIGRATION] Local Asset Ids length - ${localAssets.length}");
|
||||||
ids.sort((a, b) => a.assetId.compareTo(b.assetId));
|
ids.sort((a, b) => a.assetId.compareTo(b.assetId));
|
||||||
localAssets.sort((a, b) => a.assetId.compareTo(b.assetId));
|
localAssets.sort((a, b) => a.assetId.compareTo(b.assetId));
|
||||||
final List<DeviceAssetEntity> toAdd = [];
|
final List<DeviceAssetEntity> toAdd = [];
|
||||||
@@ -95,15 +128,27 @@ Future<void> _migrateDeviceAsset(Isar db) async {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
onlyFirst: (deviceAsset) {
|
onlyFirst: (deviceAsset) {
|
||||||
debugPrint(
|
if (kDebugMode) {
|
||||||
'DeviceAsset not found in local assets: ${deviceAsset.assetId}',
|
debugPrint(
|
||||||
);
|
'[MIGRATION] Local asset not found in DeviceAsset: ${deviceAsset.assetId}',
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onlySecond: (asset) {
|
onlySecond: (asset) {
|
||||||
debugPrint('Local asset not found in DeviceAsset: ${asset.assetId}');
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
'[MIGRATION] Local asset not found in DeviceAsset: ${asset.assetId}',
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
debugPrint("Total number of device assets migrated - ${toAdd.length}");
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
debugPrint(
|
||||||
|
"[MIGRATION] Total number of device assets migrated - ${toAdd.length}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await db.writeTxn(() async {
|
await db.writeTxn(() async {
|
||||||
await db.deviceAssetEntitys.putAll(toAdd);
|
await db.deviceAssetEntitys.putAll(toAdd);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/providers/asset.provider.dart';
|
import 'package:immich_mobile/providers/asset.provider.dart';
|
||||||
import 'package:immich_mobile/services/asset.service.dart';
|
import 'package:immich_mobile/services/asset.service.dart';
|
||||||
import 'package:immich_mobile/services/share.service.dart';
|
import 'package:immich_mobile/services/share.service.dart';
|
||||||
|
import 'package:immich_mobile/utils/translation.dart';
|
||||||
import 'package:immich_mobile/widgets/common/date_time_picker.dart';
|
import 'package:immich_mobile/widgets/common/date_time_picker.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
import 'package:immich_mobile/widgets/common/location_picker.dart';
|
import 'package:immich_mobile/widgets/common/location_picker.dart';
|
||||||
@@ -57,12 +58,13 @@ Future<void> handleArchiveAssets(
|
|||||||
.read(assetProvider.notifier)
|
.read(assetProvider.notifier)
|
||||||
.toggleArchive(selection, shouldArchive);
|
.toggleArchive(selection, shouldArchive);
|
||||||
|
|
||||||
final assetOrAssets = selection.length > 1 ? 'assets' : 'asset';
|
final message = shouldArchive
|
||||||
final archiveOrLibrary = shouldArchive ? 'archive' : 'library';
|
? t('moved_to_archive', {'count': selection.length})
|
||||||
|
: t('moved_to_library', {'count': selection.length});
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ImmichToast.show(
|
ImmichToast.show(
|
||||||
context: context,
|
context: context,
|
||||||
msg: 'Moved ${selection.length} $assetOrAssets to $archiveOrLibrary',
|
msg: message,
|
||||||
gravity: toastGravity,
|
gravity: toastGravity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:intl/message_format.dart';
|
||||||
|
|
||||||
|
String t(String key, [Map<String, Object>? args]) {
|
||||||
|
try {
|
||||||
|
String message = key.tr();
|
||||||
|
if (args != null) {
|
||||||
|
return MessageFormat(message).format(args);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
} catch (e) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -97,6 +97,7 @@ class ImmichAssetGrid extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
if (7 - scaleFactor.value.toInt() != perRow.value) {
|
if (7 - scaleFactor.value.toInt() != perRow.value) {
|
||||||
perRow.value = 7 - scaleFactor.value.toInt();
|
perRow.value = 7 - scaleFactor.value.toInt();
|
||||||
|
settings.setSetting(AppSettingsEnum.tilesPerRow, perRow.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -755,7 +755,7 @@ class _MonthTitle extends StatelessWidget {
|
|||||||
key: Key("month-$title"),
|
key: Key("month-$title"),
|
||||||
padding: const EdgeInsets.only(left: 12.0, top: 24.0),
|
padding: const EdgeInsets.only(left: 12.0, top: 24.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
toBeginningOfSentenceCase(title, context.locale.languageCode),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 26,
|
fontSize: 26,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
@@ -786,7 +786,7 @@ class _Title extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GroupDividerTitle(
|
return GroupDividerTitle(
|
||||||
text: title,
|
text: toBeginningOfSentenceCase(title, context.locale.languageCode),
|
||||||
multiselectEnabled: selectionActive,
|
multiselectEnabled: selectionActive,
|
||||||
onSelect: () => selectAssets(assets),
|
onSelect: () => selectAssets(assets),
|
||||||
onDeselect: () => deselectAssets(assets),
|
onDeselect: () => deselectAssets(assets),
|
||||||
|
|||||||
@@ -207,9 +207,27 @@ class LoginForm extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String generateRandomString(int length) {
|
String generateRandomString(int length) {
|
||||||
|
const chars =
|
||||||
|
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
|
||||||
final random = Random.secure();
|
final random = Random.secure();
|
||||||
return base64Url
|
return String.fromCharCodes(
|
||||||
.encode(List<int>.generate(32, (i) => random.nextInt(256)));
|
Iterable.generate(
|
||||||
|
length,
|
||||||
|
(_) => chars.codeUnitAt(random.nextInt(chars.length)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> randomBytes(int length) {
|
||||||
|
final random = Random.secure();
|
||||||
|
return List<int>.generate(length, (i) => random.nextInt(256));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Per specification, the code verifier must be 43-128 characters long
|
||||||
|
/// and consist of characters [A-Z, a-z, 0-9, "-", ".", "_", "~"]
|
||||||
|
/// https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
|
||||||
|
String randomCodeVerifier() {
|
||||||
|
return base64Url.encode(randomBytes(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> generatePKCECodeChallenge(String codeVerifier) async {
|
Future<String> generatePKCECodeChallenge(String codeVerifier) async {
|
||||||
@@ -223,7 +241,8 @@ class LoginForm extends HookConsumerWidget {
|
|||||||
String? oAuthServerUrl;
|
String? oAuthServerUrl;
|
||||||
|
|
||||||
final state = generateRandomString(32);
|
final state = generateRandomString(32);
|
||||||
final codeVerifier = generateRandomString(64);
|
|
||||||
|
final codeVerifier = randomCodeVerifier();
|
||||||
final codeChallenge = await generatePKCECodeChallenge(codeVerifier);
|
final codeChallenge = await generatePKCECodeChallenge(codeVerifier);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class AdvancedSettings extends HookConsumerWidget {
|
|||||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||||
int sdkVersion = androidInfo.version.sdkInt;
|
int sdkVersion = androidInfo.version.sdkInt;
|
||||||
return sdkVersion >= 30;
|
return sdkVersion >= 31;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ class AdvancedSettings extends HookConsumerWidget {
|
|||||||
if (value) {
|
if (value) {
|
||||||
final result = await ref
|
final result = await ref
|
||||||
.read(localFilesManagerRepositoryProvider)
|
.read(localFilesManagerRepositoryProvider)
|
||||||
.requestManageStoragePermission();
|
.requestManageMediaPermission();
|
||||||
manageLocalMediaAndroid.value = result;
|
manageLocalMediaAndroid.value = result;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+18
-4
@@ -3,7 +3,7 @@ Immich API
|
|||||||
|
|
||||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.132.0
|
- API version: 1.132.3
|
||||||
- Generator version: 7.8.0
|
- Generator version: 7.8.0
|
||||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||||
|
|
||||||
@@ -145,8 +145,15 @@ Class | Method | HTTP request | Description
|
|||||||
*MemoriesApi* | [**removeMemoryAssets**](doc//MemoriesApi.md#removememoryassets) | **DELETE** /memories/{id}/assets |
|
*MemoriesApi* | [**removeMemoryAssets**](doc//MemoriesApi.md#removememoryassets) | **DELETE** /memories/{id}/assets |
|
||||||
*MemoriesApi* | [**searchMemories**](doc//MemoriesApi.md#searchmemories) | **GET** /memories |
|
*MemoriesApi* | [**searchMemories**](doc//MemoriesApi.md#searchmemories) | **GET** /memories |
|
||||||
*MemoriesApi* | [**updateMemory**](doc//MemoriesApi.md#updatememory) | **PUT** /memories/{id} |
|
*MemoriesApi* | [**updateMemory**](doc//MemoriesApi.md#updatememory) | **PUT** /memories/{id} |
|
||||||
*NotificationsAdminApi* | [**getNotificationTemplateAdmin**](doc//NotificationsAdminApi.md#getnotificationtemplateadmin) | **POST** /notifications/admin/templates/{name} |
|
*NotificationsApi* | [**deleteNotification**](doc//NotificationsApi.md#deletenotification) | **DELETE** /notifications/{id} |
|
||||||
*NotificationsAdminApi* | [**sendTestEmailAdmin**](doc//NotificationsAdminApi.md#sendtestemailadmin) | **POST** /notifications/admin/test-email |
|
*NotificationsApi* | [**deleteNotifications**](doc//NotificationsApi.md#deletenotifications) | **DELETE** /notifications |
|
||||||
|
*NotificationsApi* | [**getNotification**](doc//NotificationsApi.md#getnotification) | **GET** /notifications/{id} |
|
||||||
|
*NotificationsApi* | [**getNotifications**](doc//NotificationsApi.md#getnotifications) | **GET** /notifications |
|
||||||
|
*NotificationsApi* | [**updateNotification**](doc//NotificationsApi.md#updatenotification) | **PUT** /notifications/{id} |
|
||||||
|
*NotificationsApi* | [**updateNotifications**](doc//NotificationsApi.md#updatenotifications) | **PUT** /notifications |
|
||||||
|
*NotificationsAdminApi* | [**createNotification**](doc//NotificationsAdminApi.md#createnotification) | **POST** /admin/notifications |
|
||||||
|
*NotificationsAdminApi* | [**getNotificationTemplateAdmin**](doc//NotificationsAdminApi.md#getnotificationtemplateadmin) | **POST** /admin/notifications/templates/{name} |
|
||||||
|
*NotificationsAdminApi* | [**sendTestEmailAdmin**](doc//NotificationsAdminApi.md#sendtestemailadmin) | **POST** /admin/notifications/test-email |
|
||||||
*OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback |
|
*OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback |
|
||||||
*OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link |
|
*OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link |
|
||||||
*OAuthApi* | [**redirectOAuthToMobile**](doc//OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect |
|
*OAuthApi* | [**redirectOAuthToMobile**](doc//OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect |
|
||||||
@@ -300,7 +307,6 @@ Class | Method | HTTP request | Description
|
|||||||
- [AssetStatsResponseDto](doc//AssetStatsResponseDto.md)
|
- [AssetStatsResponseDto](doc//AssetStatsResponseDto.md)
|
||||||
- [AssetTypeEnum](doc//AssetTypeEnum.md)
|
- [AssetTypeEnum](doc//AssetTypeEnum.md)
|
||||||
- [AudioCodec](doc//AudioCodec.md)
|
- [AudioCodec](doc//AudioCodec.md)
|
||||||
- [AvatarResponse](doc//AvatarResponse.md)
|
|
||||||
- [AvatarUpdate](doc//AvatarUpdate.md)
|
- [AvatarUpdate](doc//AvatarUpdate.md)
|
||||||
- [BulkIdResponseDto](doc//BulkIdResponseDto.md)
|
- [BulkIdResponseDto](doc//BulkIdResponseDto.md)
|
||||||
- [BulkIdsDto](doc//BulkIdsDto.md)
|
- [BulkIdsDto](doc//BulkIdsDto.md)
|
||||||
@@ -361,9 +367,17 @@ Class | Method | HTTP request | Description
|
|||||||
- [MemoryUpdateDto](doc//MemoryUpdateDto.md)
|
- [MemoryUpdateDto](doc//MemoryUpdateDto.md)
|
||||||
- [MergePersonDto](doc//MergePersonDto.md)
|
- [MergePersonDto](doc//MergePersonDto.md)
|
||||||
- [MetadataSearchDto](doc//MetadataSearchDto.md)
|
- [MetadataSearchDto](doc//MetadataSearchDto.md)
|
||||||
|
- [NotificationCreateDto](doc//NotificationCreateDto.md)
|
||||||
|
- [NotificationDeleteAllDto](doc//NotificationDeleteAllDto.md)
|
||||||
|
- [NotificationDto](doc//NotificationDto.md)
|
||||||
|
- [NotificationLevel](doc//NotificationLevel.md)
|
||||||
|
- [NotificationType](doc//NotificationType.md)
|
||||||
|
- [NotificationUpdateAllDto](doc//NotificationUpdateAllDto.md)
|
||||||
|
- [NotificationUpdateDto](doc//NotificationUpdateDto.md)
|
||||||
- [OAuthAuthorizeResponseDto](doc//OAuthAuthorizeResponseDto.md)
|
- [OAuthAuthorizeResponseDto](doc//OAuthAuthorizeResponseDto.md)
|
||||||
- [OAuthCallbackDto](doc//OAuthCallbackDto.md)
|
- [OAuthCallbackDto](doc//OAuthCallbackDto.md)
|
||||||
- [OAuthConfigDto](doc//OAuthConfigDto.md)
|
- [OAuthConfigDto](doc//OAuthConfigDto.md)
|
||||||
|
- [OAuthTokenEndpointAuthMethod](doc//OAuthTokenEndpointAuthMethod.md)
|
||||||
- [OnThisDayDto](doc//OnThisDayDto.md)
|
- [OnThisDayDto](doc//OnThisDayDto.md)
|
||||||
- [PartnerDirection](doc//PartnerDirection.md)
|
- [PartnerDirection](doc//PartnerDirection.md)
|
||||||
- [PartnerResponseDto](doc//PartnerResponseDto.md)
|
- [PartnerResponseDto](doc//PartnerResponseDto.md)
|
||||||
|
|||||||
Generated
+9
-1
@@ -44,6 +44,7 @@ part 'api/jobs_api.dart';
|
|||||||
part 'api/libraries_api.dart';
|
part 'api/libraries_api.dart';
|
||||||
part 'api/map_api.dart';
|
part 'api/map_api.dart';
|
||||||
part 'api/memories_api.dart';
|
part 'api/memories_api.dart';
|
||||||
|
part 'api/notifications_api.dart';
|
||||||
part 'api/notifications_admin_api.dart';
|
part 'api/notifications_admin_api.dart';
|
||||||
part 'api/o_auth_api.dart';
|
part 'api/o_auth_api.dart';
|
||||||
part 'api/partners_api.dart';
|
part 'api/partners_api.dart';
|
||||||
@@ -107,7 +108,6 @@ part 'model/asset_stack_response_dto.dart';
|
|||||||
part 'model/asset_stats_response_dto.dart';
|
part 'model/asset_stats_response_dto.dart';
|
||||||
part 'model/asset_type_enum.dart';
|
part 'model/asset_type_enum.dart';
|
||||||
part 'model/audio_codec.dart';
|
part 'model/audio_codec.dart';
|
||||||
part 'model/avatar_response.dart';
|
|
||||||
part 'model/avatar_update.dart';
|
part 'model/avatar_update.dart';
|
||||||
part 'model/bulk_id_response_dto.dart';
|
part 'model/bulk_id_response_dto.dart';
|
||||||
part 'model/bulk_ids_dto.dart';
|
part 'model/bulk_ids_dto.dart';
|
||||||
@@ -168,9 +168,17 @@ part 'model/memory_type.dart';
|
|||||||
part 'model/memory_update_dto.dart';
|
part 'model/memory_update_dto.dart';
|
||||||
part 'model/merge_person_dto.dart';
|
part 'model/merge_person_dto.dart';
|
||||||
part 'model/metadata_search_dto.dart';
|
part 'model/metadata_search_dto.dart';
|
||||||
|
part 'model/notification_create_dto.dart';
|
||||||
|
part 'model/notification_delete_all_dto.dart';
|
||||||
|
part 'model/notification_dto.dart';
|
||||||
|
part 'model/notification_level.dart';
|
||||||
|
part 'model/notification_type.dart';
|
||||||
|
part 'model/notification_update_all_dto.dart';
|
||||||
|
part 'model/notification_update_dto.dart';
|
||||||
part 'model/o_auth_authorize_response_dto.dart';
|
part 'model/o_auth_authorize_response_dto.dart';
|
||||||
part 'model/o_auth_callback_dto.dart';
|
part 'model/o_auth_callback_dto.dart';
|
||||||
part 'model/o_auth_config_dto.dart';
|
part 'model/o_auth_config_dto.dart';
|
||||||
|
part 'model/o_auth_token_endpoint_auth_method.dart';
|
||||||
part 'model/on_this_day_dto.dart';
|
part 'model/on_this_day_dto.dart';
|
||||||
part 'model/partner_direction.dart';
|
part 'model/partner_direction.dart';
|
||||||
part 'model/partner_response_dto.dart';
|
part 'model/partner_response_dto.dart';
|
||||||
|
|||||||
+51
-4
@@ -16,7 +16,54 @@ class NotificationsAdminApi {
|
|||||||
|
|
||||||
final ApiClient apiClient;
|
final ApiClient apiClient;
|
||||||
|
|
||||||
/// Performs an HTTP 'POST /notifications/admin/templates/{name}' operation and returns the [Response].
|
/// Performs an HTTP 'POST /admin/notifications' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [NotificationCreateDto] notificationCreateDto (required):
|
||||||
|
Future<Response> createNotificationWithHttpInfo(NotificationCreateDto notificationCreateDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/admin/notifications';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = notificationCreateDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'POST',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [NotificationCreateDto] notificationCreateDto (required):
|
||||||
|
Future<NotificationDto?> createNotification(NotificationCreateDto notificationCreateDto,) async {
|
||||||
|
final response = await createNotificationWithHttpInfo(notificationCreateDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'NotificationDto',) as NotificationDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'POST /admin/notifications/templates/{name}' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
/// * [String] name (required):
|
/// * [String] name (required):
|
||||||
@@ -24,7 +71,7 @@ class NotificationsAdminApi {
|
|||||||
/// * [TemplateDto] templateDto (required):
|
/// * [TemplateDto] templateDto (required):
|
||||||
Future<Response> getNotificationTemplateAdminWithHttpInfo(String name, TemplateDto templateDto,) async {
|
Future<Response> getNotificationTemplateAdminWithHttpInfo(String name, TemplateDto templateDto,) async {
|
||||||
// ignore: prefer_const_declarations
|
// ignore: prefer_const_declarations
|
||||||
final apiPath = r'/notifications/admin/templates/{name}'
|
final apiPath = r'/admin/notifications/templates/{name}'
|
||||||
.replaceAll('{name}', name);
|
.replaceAll('{name}', name);
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
// ignore: prefer_final_locals
|
||||||
@@ -68,13 +115,13 @@ class NotificationsAdminApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'POST /notifications/admin/test-email' operation and returns the [Response].
|
/// Performs an HTTP 'POST /admin/notifications/test-email' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
/// * [SystemConfigSmtpDto] systemConfigSmtpDto (required):
|
/// * [SystemConfigSmtpDto] systemConfigSmtpDto (required):
|
||||||
Future<Response> sendTestEmailAdminWithHttpInfo(SystemConfigSmtpDto systemConfigSmtpDto,) async {
|
Future<Response> sendTestEmailAdminWithHttpInfo(SystemConfigSmtpDto systemConfigSmtpDto,) async {
|
||||||
// ignore: prefer_const_declarations
|
// ignore: prefer_const_declarations
|
||||||
final apiPath = r'/notifications/admin/test-email';
|
final apiPath = r'/admin/notifications/test-email';
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
// ignore: prefer_final_locals
|
||||||
Object? postBody = systemConfigSmtpDto;
|
Object? postBody = systemConfigSmtpDto;
|
||||||
|
|||||||
+311
@@ -0,0 +1,311 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationsApi {
|
||||||
|
NotificationsApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||||
|
|
||||||
|
final ApiClient apiClient;
|
||||||
|
|
||||||
|
/// Performs an HTTP 'DELETE /notifications/{id}' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
Future<Response> deleteNotificationWithHttpInfo(String id,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/notifications/{id}'
|
||||||
|
.replaceAll('{id}', id);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'DELETE',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
Future<void> deleteNotification(String id,) async {
|
||||||
|
final response = await deleteNotificationWithHttpInfo(id,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'DELETE /notifications' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [NotificationDeleteAllDto] notificationDeleteAllDto (required):
|
||||||
|
Future<Response> deleteNotificationsWithHttpInfo(NotificationDeleteAllDto notificationDeleteAllDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/notifications';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = notificationDeleteAllDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'DELETE',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [NotificationDeleteAllDto] notificationDeleteAllDto (required):
|
||||||
|
Future<void> deleteNotifications(NotificationDeleteAllDto notificationDeleteAllDto,) async {
|
||||||
|
final response = await deleteNotificationsWithHttpInfo(notificationDeleteAllDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /notifications/{id}' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
Future<Response> getNotificationWithHttpInfo(String id,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/notifications/{id}'
|
||||||
|
.replaceAll('{id}', id);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
Future<NotificationDto?> getNotification(String id,) async {
|
||||||
|
final response = await getNotificationWithHttpInfo(id,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'NotificationDto',) as NotificationDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /notifications' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id:
|
||||||
|
///
|
||||||
|
/// * [NotificationLevel] level:
|
||||||
|
///
|
||||||
|
/// * [NotificationType] type:
|
||||||
|
///
|
||||||
|
/// * [bool] unread:
|
||||||
|
Future<Response> getNotificationsWithHttpInfo({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/notifications';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
if (id != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'id', id));
|
||||||
|
}
|
||||||
|
if (level != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'level', level));
|
||||||
|
}
|
||||||
|
if (type != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'type', type));
|
||||||
|
}
|
||||||
|
if (unread != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'unread', unread));
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id:
|
||||||
|
///
|
||||||
|
/// * [NotificationLevel] level:
|
||||||
|
///
|
||||||
|
/// * [NotificationType] type:
|
||||||
|
///
|
||||||
|
/// * [bool] unread:
|
||||||
|
Future<List<NotificationDto>?> getNotifications({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async {
|
||||||
|
final response = await getNotificationsWithHttpInfo( id: id, level: level, type: type, unread: unread, );
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
final responseBody = await _decodeBodyBytes(response);
|
||||||
|
return (await apiClient.deserializeAsync(responseBody, 'List<NotificationDto>') as List)
|
||||||
|
.cast<NotificationDto>()
|
||||||
|
.toList(growable: false);
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'PUT /notifications/{id}' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [NotificationUpdateDto] notificationUpdateDto (required):
|
||||||
|
Future<Response> updateNotificationWithHttpInfo(String id, NotificationUpdateDto notificationUpdateDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/notifications/{id}'
|
||||||
|
.replaceAll('{id}', id);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = notificationUpdateDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'PUT',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [NotificationUpdateDto] notificationUpdateDto (required):
|
||||||
|
Future<NotificationDto?> updateNotification(String id, NotificationUpdateDto notificationUpdateDto,) async {
|
||||||
|
final response = await updateNotificationWithHttpInfo(id, notificationUpdateDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'NotificationDto',) as NotificationDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'PUT /notifications' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [NotificationUpdateAllDto] notificationUpdateAllDto (required):
|
||||||
|
Future<Response> updateNotificationsWithHttpInfo(NotificationUpdateAllDto notificationUpdateAllDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/notifications';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = notificationUpdateAllDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'PUT',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [NotificationUpdateAllDto] notificationUpdateAllDto (required):
|
||||||
|
Future<void> updateNotifications(NotificationUpdateAllDto notificationUpdateAllDto,) async {
|
||||||
|
final response = await updateNotificationsWithHttpInfo(notificationUpdateAllDto,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+16
-2
@@ -270,8 +270,6 @@ class ApiClient {
|
|||||||
return AssetTypeEnumTypeTransformer().decode(value);
|
return AssetTypeEnumTypeTransformer().decode(value);
|
||||||
case 'AudioCodec':
|
case 'AudioCodec':
|
||||||
return AudioCodecTypeTransformer().decode(value);
|
return AudioCodecTypeTransformer().decode(value);
|
||||||
case 'AvatarResponse':
|
|
||||||
return AvatarResponse.fromJson(value);
|
|
||||||
case 'AvatarUpdate':
|
case 'AvatarUpdate':
|
||||||
return AvatarUpdate.fromJson(value);
|
return AvatarUpdate.fromJson(value);
|
||||||
case 'BulkIdResponseDto':
|
case 'BulkIdResponseDto':
|
||||||
@@ -392,12 +390,28 @@ class ApiClient {
|
|||||||
return MergePersonDto.fromJson(value);
|
return MergePersonDto.fromJson(value);
|
||||||
case 'MetadataSearchDto':
|
case 'MetadataSearchDto':
|
||||||
return MetadataSearchDto.fromJson(value);
|
return MetadataSearchDto.fromJson(value);
|
||||||
|
case 'NotificationCreateDto':
|
||||||
|
return NotificationCreateDto.fromJson(value);
|
||||||
|
case 'NotificationDeleteAllDto':
|
||||||
|
return NotificationDeleteAllDto.fromJson(value);
|
||||||
|
case 'NotificationDto':
|
||||||
|
return NotificationDto.fromJson(value);
|
||||||
|
case 'NotificationLevel':
|
||||||
|
return NotificationLevelTypeTransformer().decode(value);
|
||||||
|
case 'NotificationType':
|
||||||
|
return NotificationTypeTypeTransformer().decode(value);
|
||||||
|
case 'NotificationUpdateAllDto':
|
||||||
|
return NotificationUpdateAllDto.fromJson(value);
|
||||||
|
case 'NotificationUpdateDto':
|
||||||
|
return NotificationUpdateDto.fromJson(value);
|
||||||
case 'OAuthAuthorizeResponseDto':
|
case 'OAuthAuthorizeResponseDto':
|
||||||
return OAuthAuthorizeResponseDto.fromJson(value);
|
return OAuthAuthorizeResponseDto.fromJson(value);
|
||||||
case 'OAuthCallbackDto':
|
case 'OAuthCallbackDto':
|
||||||
return OAuthCallbackDto.fromJson(value);
|
return OAuthCallbackDto.fromJson(value);
|
||||||
case 'OAuthConfigDto':
|
case 'OAuthConfigDto':
|
||||||
return OAuthConfigDto.fromJson(value);
|
return OAuthConfigDto.fromJson(value);
|
||||||
|
case 'OAuthTokenEndpointAuthMethod':
|
||||||
|
return OAuthTokenEndpointAuthMethodTypeTransformer().decode(value);
|
||||||
case 'OnThisDayDto':
|
case 'OnThisDayDto':
|
||||||
return OnThisDayDto.fromJson(value);
|
return OnThisDayDto.fromJson(value);
|
||||||
case 'PartnerDirection':
|
case 'PartnerDirection':
|
||||||
|
|||||||
Generated
+9
@@ -100,6 +100,15 @@ String parameterToString(dynamic value) {
|
|||||||
if (value is MemoryType) {
|
if (value is MemoryType) {
|
||||||
return MemoryTypeTypeTransformer().encode(value).toString();
|
return MemoryTypeTypeTransformer().encode(value).toString();
|
||||||
}
|
}
|
||||||
|
if (value is NotificationLevel) {
|
||||||
|
return NotificationLevelTypeTransformer().encode(value).toString();
|
||||||
|
}
|
||||||
|
if (value is NotificationType) {
|
||||||
|
return NotificationTypeTypeTransformer().encode(value).toString();
|
||||||
|
}
|
||||||
|
if (value is OAuthTokenEndpointAuthMethod) {
|
||||||
|
return OAuthTokenEndpointAuthMethodTypeTransformer().encode(value).toString();
|
||||||
|
}
|
||||||
if (value is PartnerDirection) {
|
if (value is PartnerDirection) {
|
||||||
return PartnerDirectionTypeTransformer().encode(value).toString();
|
return PartnerDirectionTypeTransformer().encode(value).toString();
|
||||||
}
|
}
|
||||||
|
|||||||
+180
@@ -0,0 +1,180 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class NotificationCreateDto {
|
||||||
|
/// Returns a new [NotificationCreateDto] instance.
|
||||||
|
NotificationCreateDto({
|
||||||
|
this.data,
|
||||||
|
this.description,
|
||||||
|
this.level,
|
||||||
|
this.readAt,
|
||||||
|
required this.title,
|
||||||
|
this.type,
|
||||||
|
required this.userId,
|
||||||
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
Object? data;
|
||||||
|
|
||||||
|
String? description;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
NotificationLevel? level;
|
||||||
|
|
||||||
|
DateTime? readAt;
|
||||||
|
|
||||||
|
String title;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
NotificationType? type;
|
||||||
|
|
||||||
|
String userId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is NotificationCreateDto &&
|
||||||
|
other.data == data &&
|
||||||
|
other.description == description &&
|
||||||
|
other.level == level &&
|
||||||
|
other.readAt == readAt &&
|
||||||
|
other.title == title &&
|
||||||
|
other.type == type &&
|
||||||
|
other.userId == userId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(data == null ? 0 : data!.hashCode) +
|
||||||
|
(description == null ? 0 : description!.hashCode) +
|
||||||
|
(level == null ? 0 : level!.hashCode) +
|
||||||
|
(readAt == null ? 0 : readAt!.hashCode) +
|
||||||
|
(title.hashCode) +
|
||||||
|
(type == null ? 0 : type!.hashCode) +
|
||||||
|
(userId.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'NotificationCreateDto[data=$data, description=$description, level=$level, readAt=$readAt, title=$title, type=$type, userId=$userId]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
if (this.data != null) {
|
||||||
|
json[r'data'] = this.data;
|
||||||
|
} else {
|
||||||
|
// json[r'data'] = null;
|
||||||
|
}
|
||||||
|
if (this.description != null) {
|
||||||
|
json[r'description'] = this.description;
|
||||||
|
} else {
|
||||||
|
// json[r'description'] = null;
|
||||||
|
}
|
||||||
|
if (this.level != null) {
|
||||||
|
json[r'level'] = this.level;
|
||||||
|
} else {
|
||||||
|
// json[r'level'] = null;
|
||||||
|
}
|
||||||
|
if (this.readAt != null) {
|
||||||
|
json[r'readAt'] = this.readAt!.toUtc().toIso8601String();
|
||||||
|
} else {
|
||||||
|
// json[r'readAt'] = null;
|
||||||
|
}
|
||||||
|
json[r'title'] = this.title;
|
||||||
|
if (this.type != null) {
|
||||||
|
json[r'type'] = this.type;
|
||||||
|
} else {
|
||||||
|
// json[r'type'] = null;
|
||||||
|
}
|
||||||
|
json[r'userId'] = this.userId;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [NotificationCreateDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static NotificationCreateDto? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "NotificationCreateDto");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return NotificationCreateDto(
|
||||||
|
data: mapValueOfType<Object>(json, r'data'),
|
||||||
|
description: mapValueOfType<String>(json, r'description'),
|
||||||
|
level: NotificationLevel.fromJson(json[r'level']),
|
||||||
|
readAt: mapDateTime(json, r'readAt', r''),
|
||||||
|
title: mapValueOfType<String>(json, r'title')!,
|
||||||
|
type: NotificationType.fromJson(json[r'type']),
|
||||||
|
userId: mapValueOfType<String>(json, r'userId')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<NotificationCreateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <NotificationCreateDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = NotificationCreateDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, NotificationCreateDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, NotificationCreateDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = NotificationCreateDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of NotificationCreateDto-objects as value to a dart map
|
||||||
|
static Map<String, List<NotificationCreateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<NotificationCreateDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = NotificationCreateDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'title',
|
||||||
|
'userId',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class NotificationDeleteAllDto {
|
||||||
|
/// Returns a new [NotificationDeleteAllDto] instance.
|
||||||
|
NotificationDeleteAllDto({
|
||||||
|
this.ids = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is NotificationDeleteAllDto &&
|
||||||
|
_deepEquality.equals(other.ids, ids);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(ids.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'NotificationDeleteAllDto[ids=$ids]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'ids'] = this.ids;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [NotificationDeleteAllDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static NotificationDeleteAllDto? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "NotificationDeleteAllDto");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return NotificationDeleteAllDto(
|
||||||
|
ids: json[r'ids'] is Iterable
|
||||||
|
? (json[r'ids'] as Iterable).cast<String>().toList(growable: false)
|
||||||
|
: const [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<NotificationDeleteAllDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <NotificationDeleteAllDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = NotificationDeleteAllDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, NotificationDeleteAllDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, NotificationDeleteAllDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = NotificationDeleteAllDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of NotificationDeleteAllDto-objects as value to a dart map
|
||||||
|
static Map<String, List<NotificationDeleteAllDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<NotificationDeleteAllDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = NotificationDeleteAllDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'ids',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
+182
@@ -0,0 +1,182 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class NotificationDto {
|
||||||
|
/// Returns a new [NotificationDto] instance.
|
||||||
|
NotificationDto({
|
||||||
|
required this.createdAt,
|
||||||
|
this.data,
|
||||||
|
this.description,
|
||||||
|
required this.id,
|
||||||
|
required this.level,
|
||||||
|
this.readAt,
|
||||||
|
required this.title,
|
||||||
|
required this.type,
|
||||||
|
});
|
||||||
|
|
||||||
|
DateTime createdAt;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
Object? data;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
String? description;
|
||||||
|
|
||||||
|
String id;
|
||||||
|
|
||||||
|
NotificationLevel level;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
DateTime? readAt;
|
||||||
|
|
||||||
|
String title;
|
||||||
|
|
||||||
|
NotificationType type;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is NotificationDto &&
|
||||||
|
other.createdAt == createdAt &&
|
||||||
|
other.data == data &&
|
||||||
|
other.description == description &&
|
||||||
|
other.id == id &&
|
||||||
|
other.level == level &&
|
||||||
|
other.readAt == readAt &&
|
||||||
|
other.title == title &&
|
||||||
|
other.type == type;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(createdAt.hashCode) +
|
||||||
|
(data == null ? 0 : data!.hashCode) +
|
||||||
|
(description == null ? 0 : description!.hashCode) +
|
||||||
|
(id.hashCode) +
|
||||||
|
(level.hashCode) +
|
||||||
|
(readAt == null ? 0 : readAt!.hashCode) +
|
||||||
|
(title.hashCode) +
|
||||||
|
(type.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'NotificationDto[createdAt=$createdAt, data=$data, description=$description, id=$id, level=$level, readAt=$readAt, title=$title, type=$type]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
|
||||||
|
if (this.data != null) {
|
||||||
|
json[r'data'] = this.data;
|
||||||
|
} else {
|
||||||
|
// json[r'data'] = null;
|
||||||
|
}
|
||||||
|
if (this.description != null) {
|
||||||
|
json[r'description'] = this.description;
|
||||||
|
} else {
|
||||||
|
// json[r'description'] = null;
|
||||||
|
}
|
||||||
|
json[r'id'] = this.id;
|
||||||
|
json[r'level'] = this.level;
|
||||||
|
if (this.readAt != null) {
|
||||||
|
json[r'readAt'] = this.readAt!.toUtc().toIso8601String();
|
||||||
|
} else {
|
||||||
|
// json[r'readAt'] = null;
|
||||||
|
}
|
||||||
|
json[r'title'] = this.title;
|
||||||
|
json[r'type'] = this.type;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [NotificationDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static NotificationDto? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "NotificationDto");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return NotificationDto(
|
||||||
|
createdAt: mapDateTime(json, r'createdAt', r'')!,
|
||||||
|
data: mapValueOfType<Object>(json, r'data'),
|
||||||
|
description: mapValueOfType<String>(json, r'description'),
|
||||||
|
id: mapValueOfType<String>(json, r'id')!,
|
||||||
|
level: NotificationLevel.fromJson(json[r'level'])!,
|
||||||
|
readAt: mapDateTime(json, r'readAt', r''),
|
||||||
|
title: mapValueOfType<String>(json, r'title')!,
|
||||||
|
type: NotificationType.fromJson(json[r'type'])!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<NotificationDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <NotificationDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = NotificationDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, NotificationDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, NotificationDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = NotificationDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of NotificationDto-objects as value to a dart map
|
||||||
|
static Map<String, List<NotificationDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<NotificationDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = NotificationDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'createdAt',
|
||||||
|
'id',
|
||||||
|
'level',
|
||||||
|
'title',
|
||||||
|
'type',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationLevel {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const NotificationLevel._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value;
|
||||||
|
|
||||||
|
String toJson() => value;
|
||||||
|
|
||||||
|
static const success = NotificationLevel._(r'success');
|
||||||
|
static const error = NotificationLevel._(r'error');
|
||||||
|
static const warning = NotificationLevel._(r'warning');
|
||||||
|
static const info = NotificationLevel._(r'info');
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][NotificationLevel].
|
||||||
|
static const values = <NotificationLevel>[
|
||||||
|
success,
|
||||||
|
error,
|
||||||
|
warning,
|
||||||
|
info,
|
||||||
|
];
|
||||||
|
|
||||||
|
static NotificationLevel? fromJson(dynamic value) => NotificationLevelTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<NotificationLevel> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <NotificationLevel>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = NotificationLevel.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [NotificationLevel] to String,
|
||||||
|
/// and [decode] dynamic data back to [NotificationLevel].
|
||||||
|
class NotificationLevelTypeTransformer {
|
||||||
|
factory NotificationLevelTypeTransformer() => _instance ??= const NotificationLevelTypeTransformer._();
|
||||||
|
|
||||||
|
const NotificationLevelTypeTransformer._();
|
||||||
|
|
||||||
|
String encode(NotificationLevel data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a NotificationLevel.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
NotificationLevel? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
switch (data) {
|
||||||
|
case r'success': return NotificationLevel.success;
|
||||||
|
case r'error': return NotificationLevel.error;
|
||||||
|
case r'warning': return NotificationLevel.warning;
|
||||||
|
case r'info': return NotificationLevel.info;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [NotificationLevelTypeTransformer] instance.
|
||||||
|
static NotificationLevelTypeTransformer? _instance;
|
||||||
|
}
|
||||||
|
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationType {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const NotificationType._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value;
|
||||||
|
|
||||||
|
String toJson() => value;
|
||||||
|
|
||||||
|
static const jobFailed = NotificationType._(r'JobFailed');
|
||||||
|
static const backupFailed = NotificationType._(r'BackupFailed');
|
||||||
|
static const systemMessage = NotificationType._(r'SystemMessage');
|
||||||
|
static const custom = NotificationType._(r'Custom');
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][NotificationType].
|
||||||
|
static const values = <NotificationType>[
|
||||||
|
jobFailed,
|
||||||
|
backupFailed,
|
||||||
|
systemMessage,
|
||||||
|
custom,
|
||||||
|
];
|
||||||
|
|
||||||
|
static NotificationType? fromJson(dynamic value) => NotificationTypeTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<NotificationType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <NotificationType>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = NotificationType.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [NotificationType] to String,
|
||||||
|
/// and [decode] dynamic data back to [NotificationType].
|
||||||
|
class NotificationTypeTypeTransformer {
|
||||||
|
factory NotificationTypeTypeTransformer() => _instance ??= const NotificationTypeTypeTransformer._();
|
||||||
|
|
||||||
|
const NotificationTypeTypeTransformer._();
|
||||||
|
|
||||||
|
String encode(NotificationType data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a NotificationType.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
NotificationType? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
switch (data) {
|
||||||
|
case r'JobFailed': return NotificationType.jobFailed;
|
||||||
|
case r'BackupFailed': return NotificationType.backupFailed;
|
||||||
|
case r'SystemMessage': return NotificationType.systemMessage;
|
||||||
|
case r'Custom': return NotificationType.custom;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [NotificationTypeTypeTransformer] instance.
|
||||||
|
static NotificationTypeTypeTransformer? _instance;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class NotificationUpdateAllDto {
|
||||||
|
/// Returns a new [NotificationUpdateAllDto] instance.
|
||||||
|
NotificationUpdateAllDto({
|
||||||
|
this.ids = const [],
|
||||||
|
this.readAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
List<String> ids;
|
||||||
|
|
||||||
|
DateTime? readAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is NotificationUpdateAllDto &&
|
||||||
|
_deepEquality.equals(other.ids, ids) &&
|
||||||
|
other.readAt == readAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(ids.hashCode) +
|
||||||
|
(readAt == null ? 0 : readAt!.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'NotificationUpdateAllDto[ids=$ids, readAt=$readAt]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'ids'] = this.ids;
|
||||||
|
if (this.readAt != null) {
|
||||||
|
json[r'readAt'] = this.readAt!.toUtc().toIso8601String();
|
||||||
|
} else {
|
||||||
|
// json[r'readAt'] = null;
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [NotificationUpdateAllDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static NotificationUpdateAllDto? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "NotificationUpdateAllDto");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return NotificationUpdateAllDto(
|
||||||
|
ids: json[r'ids'] is Iterable
|
||||||
|
? (json[r'ids'] as Iterable).cast<String>().toList(growable: false)
|
||||||
|
: const [],
|
||||||
|
readAt: mapDateTime(json, r'readAt', r''),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<NotificationUpdateAllDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <NotificationUpdateAllDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = NotificationUpdateAllDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, NotificationUpdateAllDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, NotificationUpdateAllDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = NotificationUpdateAllDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of NotificationUpdateAllDto-objects as value to a dart map
|
||||||
|
static Map<String, List<NotificationUpdateAllDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<NotificationUpdateAllDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = NotificationUpdateAllDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'ids',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
+29
-26
@@ -10,52 +10,56 @@
|
|||||||
|
|
||||||
part of openapi.api;
|
part of openapi.api;
|
||||||
|
|
||||||
class AvatarResponse {
|
class NotificationUpdateDto {
|
||||||
/// Returns a new [AvatarResponse] instance.
|
/// Returns a new [NotificationUpdateDto] instance.
|
||||||
AvatarResponse({
|
NotificationUpdateDto({
|
||||||
required this.color,
|
this.readAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
UserAvatarColor color;
|
DateTime? readAt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is AvatarResponse &&
|
bool operator ==(Object other) => identical(this, other) || other is NotificationUpdateDto &&
|
||||||
other.color == color;
|
other.readAt == readAt;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(color.hashCode);
|
(readAt == null ? 0 : readAt!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'AvatarResponse[color=$color]';
|
String toString() => 'NotificationUpdateDto[readAt=$readAt]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
json[r'color'] = this.color;
|
if (this.readAt != null) {
|
||||||
|
json[r'readAt'] = this.readAt!.toUtc().toIso8601String();
|
||||||
|
} else {
|
||||||
|
// json[r'readAt'] = null;
|
||||||
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new [AvatarResponse] instance and imports its values from
|
/// Returns a new [NotificationUpdateDto] instance and imports its values from
|
||||||
/// [value] if it's a [Map], null otherwise.
|
/// [value] if it's a [Map], null otherwise.
|
||||||
// ignore: prefer_constructors_over_static_methods
|
// ignore: prefer_constructors_over_static_methods
|
||||||
static AvatarResponse? fromJson(dynamic value) {
|
static NotificationUpdateDto? fromJson(dynamic value) {
|
||||||
upgradeDto(value, "AvatarResponse");
|
upgradeDto(value, "NotificationUpdateDto");
|
||||||
if (value is Map) {
|
if (value is Map) {
|
||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return AvatarResponse(
|
return NotificationUpdateDto(
|
||||||
color: UserAvatarColor.fromJson(json[r'color'])!,
|
readAt: mapDateTime(json, r'readAt', r''),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<AvatarResponse> listFromJson(dynamic json, {bool growable = false,}) {
|
static List<NotificationUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
final result = <AvatarResponse>[];
|
final result = <NotificationUpdateDto>[];
|
||||||
if (json is List && json.isNotEmpty) {
|
if (json is List && json.isNotEmpty) {
|
||||||
for (final row in json) {
|
for (final row in json) {
|
||||||
final value = AvatarResponse.fromJson(row);
|
final value = NotificationUpdateDto.fromJson(row);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
result.add(value);
|
result.add(value);
|
||||||
}
|
}
|
||||||
@@ -64,12 +68,12 @@ class AvatarResponse {
|
|||||||
return result.toList(growable: growable);
|
return result.toList(growable: growable);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, AvatarResponse> mapFromJson(dynamic json) {
|
static Map<String, NotificationUpdateDto> mapFromJson(dynamic json) {
|
||||||
final map = <String, AvatarResponse>{};
|
final map = <String, NotificationUpdateDto>{};
|
||||||
if (json is Map && json.isNotEmpty) {
|
if (json is Map && json.isNotEmpty) {
|
||||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
for (final entry in json.entries) {
|
for (final entry in json.entries) {
|
||||||
final value = AvatarResponse.fromJson(entry.value);
|
final value = NotificationUpdateDto.fromJson(entry.value);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
map[entry.key] = value;
|
map[entry.key] = value;
|
||||||
}
|
}
|
||||||
@@ -78,14 +82,14 @@ class AvatarResponse {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// maps a json object with a list of AvatarResponse-objects as value to a dart map
|
// maps a json object with a list of NotificationUpdateDto-objects as value to a dart map
|
||||||
static Map<String, List<AvatarResponse>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
static Map<String, List<NotificationUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
final map = <String, List<AvatarResponse>>{};
|
final map = <String, List<NotificationUpdateDto>>{};
|
||||||
if (json is Map && json.isNotEmpty) {
|
if (json is Map && json.isNotEmpty) {
|
||||||
// ignore: parameter_assignments
|
// ignore: parameter_assignments
|
||||||
json = json.cast<String, dynamic>();
|
json = json.cast<String, dynamic>();
|
||||||
for (final entry in json.entries) {
|
for (final entry in json.entries) {
|
||||||
map[entry.key] = AvatarResponse.listFromJson(entry.value, growable: growable,);
|
map[entry.key] = NotificationUpdateDto.listFromJson(entry.value, growable: growable,);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
@@ -93,7 +97,6 @@ class AvatarResponse {
|
|||||||
|
|
||||||
/// The list of required keys that must be present in a JSON.
|
/// The list of required keys that must be present in a JSON.
|
||||||
static const requiredKeys = <String>{
|
static const requiredKeys = <String>{
|
||||||
'color',
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class OAuthTokenEndpointAuthMethod {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const OAuthTokenEndpointAuthMethod._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value;
|
||||||
|
|
||||||
|
String toJson() => value;
|
||||||
|
|
||||||
|
static const post = OAuthTokenEndpointAuthMethod._(r'client_secret_post');
|
||||||
|
static const basic = OAuthTokenEndpointAuthMethod._(r'client_secret_basic');
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][OAuthTokenEndpointAuthMethod].
|
||||||
|
static const values = <OAuthTokenEndpointAuthMethod>[
|
||||||
|
post,
|
||||||
|
basic,
|
||||||
|
];
|
||||||
|
|
||||||
|
static OAuthTokenEndpointAuthMethod? fromJson(dynamic value) => OAuthTokenEndpointAuthMethodTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<OAuthTokenEndpointAuthMethod> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <OAuthTokenEndpointAuthMethod>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = OAuthTokenEndpointAuthMethod.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [OAuthTokenEndpointAuthMethod] to String,
|
||||||
|
/// and [decode] dynamic data back to [OAuthTokenEndpointAuthMethod].
|
||||||
|
class OAuthTokenEndpointAuthMethodTypeTransformer {
|
||||||
|
factory OAuthTokenEndpointAuthMethodTypeTransformer() => _instance ??= const OAuthTokenEndpointAuthMethodTypeTransformer._();
|
||||||
|
|
||||||
|
const OAuthTokenEndpointAuthMethodTypeTransformer._();
|
||||||
|
|
||||||
|
String encode(OAuthTokenEndpointAuthMethod data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a OAuthTokenEndpointAuthMethod.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
OAuthTokenEndpointAuthMethod? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
switch (data) {
|
||||||
|
case r'client_secret_post': return OAuthTokenEndpointAuthMethod.post;
|
||||||
|
case r'client_secret_basic': return OAuthTokenEndpointAuthMethod.basic;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [OAuthTokenEndpointAuthMethodTypeTransformer] instance.
|
||||||
|
static OAuthTokenEndpointAuthMethodTypeTransformer? _instance;
|
||||||
|
}
|
||||||
|
|
||||||
Generated
+12
@@ -66,6 +66,10 @@ class Permission {
|
|||||||
static const memoryPeriodRead = Permission._(r'memory.read');
|
static const memoryPeriodRead = Permission._(r'memory.read');
|
||||||
static const memoryPeriodUpdate = Permission._(r'memory.update');
|
static const memoryPeriodUpdate = Permission._(r'memory.update');
|
||||||
static const memoryPeriodDelete = Permission._(r'memory.delete');
|
static const memoryPeriodDelete = Permission._(r'memory.delete');
|
||||||
|
static const notificationPeriodCreate = Permission._(r'notification.create');
|
||||||
|
static const notificationPeriodRead = Permission._(r'notification.read');
|
||||||
|
static const notificationPeriodUpdate = Permission._(r'notification.update');
|
||||||
|
static const notificationPeriodDelete = Permission._(r'notification.delete');
|
||||||
static const partnerPeriodCreate = Permission._(r'partner.create');
|
static const partnerPeriodCreate = Permission._(r'partner.create');
|
||||||
static const partnerPeriodRead = Permission._(r'partner.read');
|
static const partnerPeriodRead = Permission._(r'partner.read');
|
||||||
static const partnerPeriodUpdate = Permission._(r'partner.update');
|
static const partnerPeriodUpdate = Permission._(r'partner.update');
|
||||||
@@ -147,6 +151,10 @@ class Permission {
|
|||||||
memoryPeriodRead,
|
memoryPeriodRead,
|
||||||
memoryPeriodUpdate,
|
memoryPeriodUpdate,
|
||||||
memoryPeriodDelete,
|
memoryPeriodDelete,
|
||||||
|
notificationPeriodCreate,
|
||||||
|
notificationPeriodRead,
|
||||||
|
notificationPeriodUpdate,
|
||||||
|
notificationPeriodDelete,
|
||||||
partnerPeriodCreate,
|
partnerPeriodCreate,
|
||||||
partnerPeriodRead,
|
partnerPeriodRead,
|
||||||
partnerPeriodUpdate,
|
partnerPeriodUpdate,
|
||||||
@@ -263,6 +271,10 @@ class PermissionTypeTransformer {
|
|||||||
case r'memory.read': return Permission.memoryPeriodRead;
|
case r'memory.read': return Permission.memoryPeriodRead;
|
||||||
case r'memory.update': return Permission.memoryPeriodUpdate;
|
case r'memory.update': return Permission.memoryPeriodUpdate;
|
||||||
case r'memory.delete': return Permission.memoryPeriodDelete;
|
case r'memory.delete': return Permission.memoryPeriodDelete;
|
||||||
|
case r'notification.create': return Permission.notificationPeriodCreate;
|
||||||
|
case r'notification.read': return Permission.notificationPeriodRead;
|
||||||
|
case r'notification.update': return Permission.notificationPeriodUpdate;
|
||||||
|
case r'notification.delete': return Permission.notificationPeriodDelete;
|
||||||
case r'partner.create': return Permission.partnerPeriodCreate;
|
case r'partner.create': return Permission.partnerPeriodCreate;
|
||||||
case r'partner.read': return Permission.partnerPeriodRead;
|
case r'partner.read': return Permission.partnerPeriodRead;
|
||||||
case r'partner.update': return Permission.partnerPeriodUpdate;
|
case r'partner.update': return Permission.partnerPeriodUpdate;
|
||||||
|
|||||||
+20
-3
@@ -28,6 +28,8 @@ class SystemConfigOAuthDto {
|
|||||||
required this.signingAlgorithm,
|
required this.signingAlgorithm,
|
||||||
required this.storageLabelClaim,
|
required this.storageLabelClaim,
|
||||||
required this.storageQuotaClaim,
|
required this.storageQuotaClaim,
|
||||||
|
required this.timeout,
|
||||||
|
required this.tokenEndpointAuthMethod,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool autoLaunch;
|
bool autoLaunch;
|
||||||
@@ -61,6 +63,11 @@ class SystemConfigOAuthDto {
|
|||||||
|
|
||||||
String storageQuotaClaim;
|
String storageQuotaClaim;
|
||||||
|
|
||||||
|
/// Minimum value: 1
|
||||||
|
int timeout;
|
||||||
|
|
||||||
|
OAuthTokenEndpointAuthMethod tokenEndpointAuthMethod;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigOAuthDto &&
|
bool operator ==(Object other) => identical(this, other) || other is SystemConfigOAuthDto &&
|
||||||
other.autoLaunch == autoLaunch &&
|
other.autoLaunch == autoLaunch &&
|
||||||
@@ -77,7 +84,9 @@ class SystemConfigOAuthDto {
|
|||||||
other.scope == scope &&
|
other.scope == scope &&
|
||||||
other.signingAlgorithm == signingAlgorithm &&
|
other.signingAlgorithm == signingAlgorithm &&
|
||||||
other.storageLabelClaim == storageLabelClaim &&
|
other.storageLabelClaim == storageLabelClaim &&
|
||||||
other.storageQuotaClaim == storageQuotaClaim;
|
other.storageQuotaClaim == storageQuotaClaim &&
|
||||||
|
other.timeout == timeout &&
|
||||||
|
other.tokenEndpointAuthMethod == tokenEndpointAuthMethod;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
@@ -96,10 +105,12 @@ class SystemConfigOAuthDto {
|
|||||||
(scope.hashCode) +
|
(scope.hashCode) +
|
||||||
(signingAlgorithm.hashCode) +
|
(signingAlgorithm.hashCode) +
|
||||||
(storageLabelClaim.hashCode) +
|
(storageLabelClaim.hashCode) +
|
||||||
(storageQuotaClaim.hashCode);
|
(storageQuotaClaim.hashCode) +
|
||||||
|
(timeout.hashCode) +
|
||||||
|
(tokenEndpointAuthMethod.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'SystemConfigOAuthDto[autoLaunch=$autoLaunch, autoRegister=$autoRegister, buttonText=$buttonText, clientId=$clientId, clientSecret=$clientSecret, defaultStorageQuota=$defaultStorageQuota, enabled=$enabled, issuerUrl=$issuerUrl, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri, profileSigningAlgorithm=$profileSigningAlgorithm, scope=$scope, signingAlgorithm=$signingAlgorithm, storageLabelClaim=$storageLabelClaim, storageQuotaClaim=$storageQuotaClaim]';
|
String toString() => 'SystemConfigOAuthDto[autoLaunch=$autoLaunch, autoRegister=$autoRegister, buttonText=$buttonText, clientId=$clientId, clientSecret=$clientSecret, defaultStorageQuota=$defaultStorageQuota, enabled=$enabled, issuerUrl=$issuerUrl, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri, profileSigningAlgorithm=$profileSigningAlgorithm, scope=$scope, signingAlgorithm=$signingAlgorithm, storageLabelClaim=$storageLabelClaim, storageQuotaClaim=$storageQuotaClaim, timeout=$timeout, tokenEndpointAuthMethod=$tokenEndpointAuthMethod]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@@ -118,6 +129,8 @@ class SystemConfigOAuthDto {
|
|||||||
json[r'signingAlgorithm'] = this.signingAlgorithm;
|
json[r'signingAlgorithm'] = this.signingAlgorithm;
|
||||||
json[r'storageLabelClaim'] = this.storageLabelClaim;
|
json[r'storageLabelClaim'] = this.storageLabelClaim;
|
||||||
json[r'storageQuotaClaim'] = this.storageQuotaClaim;
|
json[r'storageQuotaClaim'] = this.storageQuotaClaim;
|
||||||
|
json[r'timeout'] = this.timeout;
|
||||||
|
json[r'tokenEndpointAuthMethod'] = this.tokenEndpointAuthMethod;
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +158,8 @@ class SystemConfigOAuthDto {
|
|||||||
signingAlgorithm: mapValueOfType<String>(json, r'signingAlgorithm')!,
|
signingAlgorithm: mapValueOfType<String>(json, r'signingAlgorithm')!,
|
||||||
storageLabelClaim: mapValueOfType<String>(json, r'storageLabelClaim')!,
|
storageLabelClaim: mapValueOfType<String>(json, r'storageLabelClaim')!,
|
||||||
storageQuotaClaim: mapValueOfType<String>(json, r'storageQuotaClaim')!,
|
storageQuotaClaim: mapValueOfType<String>(json, r'storageQuotaClaim')!,
|
||||||
|
timeout: mapValueOfType<int>(json, r'timeout')!,
|
||||||
|
tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod.fromJson(json[r'tokenEndpointAuthMethod'])!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -207,6 +222,8 @@ class SystemConfigOAuthDto {
|
|||||||
'signingAlgorithm',
|
'signingAlgorithm',
|
||||||
'storageLabelClaim',
|
'storageLabelClaim',
|
||||||
'storageQuotaClaim',
|
'storageQuotaClaim',
|
||||||
|
'timeout',
|
||||||
|
'tokenEndpointAuthMethod',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -13,6 +13,7 @@ part of openapi.api;
|
|||||||
class UserAdminCreateDto {
|
class UserAdminCreateDto {
|
||||||
/// Returns a new [UserAdminCreateDto] instance.
|
/// Returns a new [UserAdminCreateDto] instance.
|
||||||
UserAdminCreateDto({
|
UserAdminCreateDto({
|
||||||
|
this.avatarColor,
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.name,
|
required this.name,
|
||||||
this.notify,
|
this.notify,
|
||||||
@@ -22,6 +23,8 @@ class UserAdminCreateDto {
|
|||||||
this.storageLabel,
|
this.storageLabel,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UserAvatarColor? avatarColor;
|
||||||
|
|
||||||
String email;
|
String email;
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
@@ -51,6 +54,7 @@ class UserAdminCreateDto {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is UserAdminCreateDto &&
|
bool operator ==(Object other) => identical(this, other) || other is UserAdminCreateDto &&
|
||||||
|
other.avatarColor == avatarColor &&
|
||||||
other.email == email &&
|
other.email == email &&
|
||||||
other.name == name &&
|
other.name == name &&
|
||||||
other.notify == notify &&
|
other.notify == notify &&
|
||||||
@@ -62,6 +66,7 @@ class UserAdminCreateDto {
|
|||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
|
(avatarColor == null ? 0 : avatarColor!.hashCode) +
|
||||||
(email.hashCode) +
|
(email.hashCode) +
|
||||||
(name.hashCode) +
|
(name.hashCode) +
|
||||||
(notify == null ? 0 : notify!.hashCode) +
|
(notify == null ? 0 : notify!.hashCode) +
|
||||||
@@ -71,10 +76,15 @@ class UserAdminCreateDto {
|
|||||||
(storageLabel == null ? 0 : storageLabel!.hashCode);
|
(storageLabel == null ? 0 : storageLabel!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UserAdminCreateDto[email=$email, name=$name, notify=$notify, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
|
String toString() => 'UserAdminCreateDto[avatarColor=$avatarColor, email=$email, name=$name, notify=$notify, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
|
if (this.avatarColor != null) {
|
||||||
|
json[r'avatarColor'] = this.avatarColor;
|
||||||
|
} else {
|
||||||
|
// json[r'avatarColor'] = null;
|
||||||
|
}
|
||||||
json[r'email'] = this.email;
|
json[r'email'] = this.email;
|
||||||
json[r'name'] = this.name;
|
json[r'name'] = this.name;
|
||||||
if (this.notify != null) {
|
if (this.notify != null) {
|
||||||
@@ -110,6 +120,7 @@ class UserAdminCreateDto {
|
|||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return UserAdminCreateDto(
|
return UserAdminCreateDto(
|
||||||
|
avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']),
|
||||||
email: mapValueOfType<String>(json, r'email')!,
|
email: mapValueOfType<String>(json, r'email')!,
|
||||||
name: mapValueOfType<String>(json, r'name')!,
|
name: mapValueOfType<String>(json, r'name')!,
|
||||||
notify: mapValueOfType<bool>(json, r'notify'),
|
notify: mapValueOfType<bool>(json, r'notify'),
|
||||||
|
|||||||
+12
-1
@@ -13,6 +13,7 @@ part of openapi.api;
|
|||||||
class UserAdminUpdateDto {
|
class UserAdminUpdateDto {
|
||||||
/// Returns a new [UserAdminUpdateDto] instance.
|
/// Returns a new [UserAdminUpdateDto] instance.
|
||||||
UserAdminUpdateDto({
|
UserAdminUpdateDto({
|
||||||
|
this.avatarColor,
|
||||||
this.email,
|
this.email,
|
||||||
this.name,
|
this.name,
|
||||||
this.password,
|
this.password,
|
||||||
@@ -21,6 +22,8 @@ class UserAdminUpdateDto {
|
|||||||
this.storageLabel,
|
this.storageLabel,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UserAvatarColor? avatarColor;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
@@ -60,6 +63,7 @@ class UserAdminUpdateDto {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is UserAdminUpdateDto &&
|
bool operator ==(Object other) => identical(this, other) || other is UserAdminUpdateDto &&
|
||||||
|
other.avatarColor == avatarColor &&
|
||||||
other.email == email &&
|
other.email == email &&
|
||||||
other.name == name &&
|
other.name == name &&
|
||||||
other.password == password &&
|
other.password == password &&
|
||||||
@@ -70,6 +74,7 @@ class UserAdminUpdateDto {
|
|||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
|
(avatarColor == null ? 0 : avatarColor!.hashCode) +
|
||||||
(email == null ? 0 : email!.hashCode) +
|
(email == null ? 0 : email!.hashCode) +
|
||||||
(name == null ? 0 : name!.hashCode) +
|
(name == null ? 0 : name!.hashCode) +
|
||||||
(password == null ? 0 : password!.hashCode) +
|
(password == null ? 0 : password!.hashCode) +
|
||||||
@@ -78,10 +83,15 @@ class UserAdminUpdateDto {
|
|||||||
(storageLabel == null ? 0 : storageLabel!.hashCode);
|
(storageLabel == null ? 0 : storageLabel!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UserAdminUpdateDto[email=$email, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
|
String toString() => 'UserAdminUpdateDto[avatarColor=$avatarColor, email=$email, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
|
if (this.avatarColor != null) {
|
||||||
|
json[r'avatarColor'] = this.avatarColor;
|
||||||
|
} else {
|
||||||
|
// json[r'avatarColor'] = null;
|
||||||
|
}
|
||||||
if (this.email != null) {
|
if (this.email != null) {
|
||||||
json[r'email'] = this.email;
|
json[r'email'] = this.email;
|
||||||
} else {
|
} else {
|
||||||
@@ -124,6 +134,7 @@ class UserAdminUpdateDto {
|
|||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return UserAdminUpdateDto(
|
return UserAdminUpdateDto(
|
||||||
|
avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']),
|
||||||
email: mapValueOfType<String>(json, r'email'),
|
email: mapValueOfType<String>(json, r'email'),
|
||||||
name: mapValueOfType<String>(json, r'name'),
|
name: mapValueOfType<String>(json, r'name'),
|
||||||
password: mapValueOfType<String>(json, r'password'),
|
password: mapValueOfType<String>(json, r'password'),
|
||||||
|
|||||||
+1
-9
@@ -13,7 +13,6 @@ part of openapi.api;
|
|||||||
class UserPreferencesResponseDto {
|
class UserPreferencesResponseDto {
|
||||||
/// Returns a new [UserPreferencesResponseDto] instance.
|
/// Returns a new [UserPreferencesResponseDto] instance.
|
||||||
UserPreferencesResponseDto({
|
UserPreferencesResponseDto({
|
||||||
required this.avatar,
|
|
||||||
required this.download,
|
required this.download,
|
||||||
required this.emailNotifications,
|
required this.emailNotifications,
|
||||||
required this.folders,
|
required this.folders,
|
||||||
@@ -25,8 +24,6 @@ class UserPreferencesResponseDto {
|
|||||||
required this.tags,
|
required this.tags,
|
||||||
});
|
});
|
||||||
|
|
||||||
AvatarResponse avatar;
|
|
||||||
|
|
||||||
DownloadResponse download;
|
DownloadResponse download;
|
||||||
|
|
||||||
EmailNotificationsResponse emailNotifications;
|
EmailNotificationsResponse emailNotifications;
|
||||||
@@ -47,7 +44,6 @@ class UserPreferencesResponseDto {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is UserPreferencesResponseDto &&
|
bool operator ==(Object other) => identical(this, other) || other is UserPreferencesResponseDto &&
|
||||||
other.avatar == avatar &&
|
|
||||||
other.download == download &&
|
other.download == download &&
|
||||||
other.emailNotifications == emailNotifications &&
|
other.emailNotifications == emailNotifications &&
|
||||||
other.folders == folders &&
|
other.folders == folders &&
|
||||||
@@ -61,7 +57,6 @@ class UserPreferencesResponseDto {
|
|||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(avatar.hashCode) +
|
|
||||||
(download.hashCode) +
|
(download.hashCode) +
|
||||||
(emailNotifications.hashCode) +
|
(emailNotifications.hashCode) +
|
||||||
(folders.hashCode) +
|
(folders.hashCode) +
|
||||||
@@ -73,11 +68,10 @@ class UserPreferencesResponseDto {
|
|||||||
(tags.hashCode);
|
(tags.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UserPreferencesResponseDto[avatar=$avatar, download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, sharedLinks=$sharedLinks, tags=$tags]';
|
String toString() => 'UserPreferencesResponseDto[download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, sharedLinks=$sharedLinks, tags=$tags]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
json[r'avatar'] = this.avatar;
|
|
||||||
json[r'download'] = this.download;
|
json[r'download'] = this.download;
|
||||||
json[r'emailNotifications'] = this.emailNotifications;
|
json[r'emailNotifications'] = this.emailNotifications;
|
||||||
json[r'folders'] = this.folders;
|
json[r'folders'] = this.folders;
|
||||||
@@ -99,7 +93,6 @@ class UserPreferencesResponseDto {
|
|||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return UserPreferencesResponseDto(
|
return UserPreferencesResponseDto(
|
||||||
avatar: AvatarResponse.fromJson(json[r'avatar'])!,
|
|
||||||
download: DownloadResponse.fromJson(json[r'download'])!,
|
download: DownloadResponse.fromJson(json[r'download'])!,
|
||||||
emailNotifications: EmailNotificationsResponse.fromJson(json[r'emailNotifications'])!,
|
emailNotifications: EmailNotificationsResponse.fromJson(json[r'emailNotifications'])!,
|
||||||
folders: FoldersResponse.fromJson(json[r'folders'])!,
|
folders: FoldersResponse.fromJson(json[r'folders'])!,
|
||||||
@@ -156,7 +149,6 @@ class UserPreferencesResponseDto {
|
|||||||
|
|
||||||
/// The list of required keys that must be present in a JSON.
|
/// The list of required keys that must be present in a JSON.
|
||||||
static const requiredKeys = <String>{
|
static const requiredKeys = <String>{
|
||||||
'avatar',
|
|
||||||
'download',
|
'download',
|
||||||
'emailNotifications',
|
'emailNotifications',
|
||||||
'folders',
|
'folders',
|
||||||
|
|||||||
+12
-1
@@ -13,11 +13,14 @@ part of openapi.api;
|
|||||||
class UserUpdateMeDto {
|
class UserUpdateMeDto {
|
||||||
/// Returns a new [UserUpdateMeDto] instance.
|
/// Returns a new [UserUpdateMeDto] instance.
|
||||||
UserUpdateMeDto({
|
UserUpdateMeDto({
|
||||||
|
this.avatarColor,
|
||||||
this.email,
|
this.email,
|
||||||
this.name,
|
this.name,
|
||||||
this.password,
|
this.password,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UserAvatarColor? avatarColor;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
@@ -44,6 +47,7 @@ class UserUpdateMeDto {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is UserUpdateMeDto &&
|
bool operator ==(Object other) => identical(this, other) || other is UserUpdateMeDto &&
|
||||||
|
other.avatarColor == avatarColor &&
|
||||||
other.email == email &&
|
other.email == email &&
|
||||||
other.name == name &&
|
other.name == name &&
|
||||||
other.password == password;
|
other.password == password;
|
||||||
@@ -51,15 +55,21 @@ class UserUpdateMeDto {
|
|||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
|
(avatarColor == null ? 0 : avatarColor!.hashCode) +
|
||||||
(email == null ? 0 : email!.hashCode) +
|
(email == null ? 0 : email!.hashCode) +
|
||||||
(name == null ? 0 : name!.hashCode) +
|
(name == null ? 0 : name!.hashCode) +
|
||||||
(password == null ? 0 : password!.hashCode);
|
(password == null ? 0 : password!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'UserUpdateMeDto[email=$email, name=$name, password=$password]';
|
String toString() => 'UserUpdateMeDto[avatarColor=$avatarColor, email=$email, name=$name, password=$password]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
|
if (this.avatarColor != null) {
|
||||||
|
json[r'avatarColor'] = this.avatarColor;
|
||||||
|
} else {
|
||||||
|
// json[r'avatarColor'] = null;
|
||||||
|
}
|
||||||
if (this.email != null) {
|
if (this.email != null) {
|
||||||
json[r'email'] = this.email;
|
json[r'email'] = this.email;
|
||||||
} else {
|
} else {
|
||||||
@@ -87,6 +97,7 @@ class UserUpdateMeDto {
|
|||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return UserUpdateMeDto(
|
return UserUpdateMeDto(
|
||||||
|
avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']),
|
||||||
email: mapValueOfType<String>(json, r'email'),
|
email: mapValueOfType<String>(json, r'email'),
|
||||||
name: mapValueOfType<String>(json, r'name'),
|
name: mapValueOfType<String>(json, r'name'),
|
||||||
password: mapValueOfType<String>(json, r'password'),
|
password: mapValueOfType<String>(json, r'password'),
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ name: immich_mobile
|
|||||||
description: Immich - selfhosted backup media file on mobile phone
|
description: Immich - selfhosted backup media file on mobile phone
|
||||||
|
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 1.132.0+194
|
version: 1.132.3+197
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.3.0 <4.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
|||||||
@@ -206,6 +206,141 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/notifications": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "createNotification",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationCreateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications (Admin)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/notifications/templates/{name}": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "getNotificationTemplateAdmin",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/TemplateDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/TemplateResponseDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications (Admin)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/notifications/test-email": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "sendTestEmailAdmin",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/SystemConfigSmtpDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/TestEmailResponseDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications (Admin)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/users": {
|
"/admin/users": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "searchUsersAdmin",
|
"operationId": "searchUsersAdmin",
|
||||||
@@ -3485,15 +3620,224 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/notifications/admin/templates/{name}": {
|
"/notifications": {
|
||||||
"post": {
|
"delete": {
|
||||||
"operationId": "getNotificationTemplateAdmin",
|
"operationId": "deleteNotifications",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationDeleteAllDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"operationId": "getNotifications",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"name": "name",
|
"name": "id",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "level",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationLevel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationType"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unread",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/NotificationDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"operationId": "updateNotifications",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationUpdateAllDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/notifications/{id}": {
|
||||||
|
"delete": {
|
||||||
|
"operationId": "deleteNotification",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
"required": true,
|
"required": true,
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"operationId": "getNotification",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotificationDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Notifications"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"operationId": "updateNotification",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3502,7 +3846,7 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TemplateDto"
|
"$ref": "#/components/schemas/NotificationUpdateDto"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3513,7 +3857,7 @@
|
|||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/TemplateResponseDto"
|
"$ref": "#/components/schemas/NotificationDto"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3532,49 +3876,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"Notifications (Admin)"
|
"Notifications"
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/notifications/admin/test-email": {
|
|
||||||
"post": {
|
|
||||||
"operationId": "sendTestEmailAdmin",
|
|
||||||
"parameters": [],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/SystemConfigSmtpDto"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/components/schemas/TestEmailResponseDto"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"description": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": [
|
|
||||||
{
|
|
||||||
"bearer": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cookie": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"api_key": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"Notifications (Admin)"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7656,7 +7958,7 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"title": "Immich",
|
"title": "Immich",
|
||||||
"description": "Immich API",
|
"description": "Immich API",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"contact": {}
|
"contact": {}
|
||||||
},
|
},
|
||||||
"tags": [],
|
"tags": [],
|
||||||
@@ -8884,21 +9186,6 @@
|
|||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"AvatarResponse": {
|
|
||||||
"properties": {
|
|
||||||
"color": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/UserAvatarColor"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"color"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"AvatarUpdate": {
|
"AvatarUpdate": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"color": {
|
"color": {
|
||||||
@@ -10341,6 +10628,157 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"NotificationCreateDto": {
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/NotificationLevel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"readAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/NotificationType"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"userId"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"NotificationDeleteAllDto": {
|
||||||
|
"properties": {
|
||||||
|
"ids": {
|
||||||
|
"items": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"ids"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"NotificationDto": {
|
||||||
|
"properties": {
|
||||||
|
"createdAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"level": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/NotificationLevel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"readAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/NotificationType"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"createdAt",
|
||||||
|
"id",
|
||||||
|
"level",
|
||||||
|
"title",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"NotificationLevel": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"error",
|
||||||
|
"warning",
|
||||||
|
"info"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"NotificationType": {
|
||||||
|
"enum": [
|
||||||
|
"JobFailed",
|
||||||
|
"BackupFailed",
|
||||||
|
"SystemMessage",
|
||||||
|
"Custom"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"NotificationUpdateAllDto": {
|
||||||
|
"properties": {
|
||||||
|
"ids": {
|
||||||
|
"items": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"readAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"ids"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"NotificationUpdateDto": {
|
||||||
|
"properties": {
|
||||||
|
"readAt": {
|
||||||
|
"format": "date-time",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"OAuthAuthorizeResponseDto": {
|
"OAuthAuthorizeResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"url": {
|
"url": {
|
||||||
@@ -10386,6 +10824,13 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"OAuthTokenEndpointAuthMethod": {
|
||||||
|
"enum": [
|
||||||
|
"client_secret_post",
|
||||||
|
"client_secret_basic"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"OnThisDayDto": {
|
"OnThisDayDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"year": {
|
"year": {
|
||||||
@@ -10615,6 +11060,10 @@
|
|||||||
"memory.read",
|
"memory.read",
|
||||||
"memory.update",
|
"memory.update",
|
||||||
"memory.delete",
|
"memory.delete",
|
||||||
|
"notification.create",
|
||||||
|
"notification.read",
|
||||||
|
"notification.update",
|
||||||
|
"notification.delete",
|
||||||
"partner.create",
|
"partner.create",
|
||||||
"partner.read",
|
"partner.read",
|
||||||
"partner.update",
|
"partner.update",
|
||||||
@@ -12962,6 +13411,17 @@
|
|||||||
},
|
},
|
||||||
"storageQuotaClaim": {
|
"storageQuotaClaim": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"timeout": {
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"tokenEndpointAuthMethod": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/OAuthTokenEndpointAuthMethod"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -12979,7 +13439,9 @@
|
|||||||
"scope",
|
"scope",
|
||||||
"signingAlgorithm",
|
"signingAlgorithm",
|
||||||
"storageLabelClaim",
|
"storageLabelClaim",
|
||||||
"storageQuotaClaim"
|
"storageQuotaClaim",
|
||||||
|
"timeout",
|
||||||
|
"tokenEndpointAuthMethod"
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@@ -13621,6 +14083,14 @@
|
|||||||
},
|
},
|
||||||
"UserAdminCreateDto": {
|
"UserAdminCreateDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarColor": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/UserAvatarColor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"format": "email",
|
"format": "email",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -13763,6 +14233,14 @@
|
|||||||
},
|
},
|
||||||
"UserAdminUpdateDto": {
|
"UserAdminUpdateDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarColor": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/UserAvatarColor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"format": "email",
|
"format": "email",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -13826,9 +14304,6 @@
|
|||||||
},
|
},
|
||||||
"UserPreferencesResponseDto": {
|
"UserPreferencesResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"avatar": {
|
|
||||||
"$ref": "#/components/schemas/AvatarResponse"
|
|
||||||
},
|
|
||||||
"download": {
|
"download": {
|
||||||
"$ref": "#/components/schemas/DownloadResponse"
|
"$ref": "#/components/schemas/DownloadResponse"
|
||||||
},
|
},
|
||||||
@@ -13858,7 +14333,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"avatar",
|
|
||||||
"download",
|
"download",
|
||||||
"emailNotifications",
|
"emailNotifications",
|
||||||
"folders",
|
"folders",
|
||||||
@@ -13952,6 +14426,14 @@
|
|||||||
},
|
},
|
||||||
"UserUpdateMeDto": {
|
"UserUpdateMeDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarColor": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/UserAvatarColor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"format": "email",
|
"format": "email",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"license": "GNU Affero General Public License version 3",
|
"license": "GNU Affero General Public License version 3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oazapfts/runtime": "^1.0.2"
|
"@oazapfts/runtime": "^1.0.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/sdk",
|
"name": "@immich/sdk",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./build/index.js",
|
"main": "./build/index.js",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Immich
|
* Immich
|
||||||
* 1.132.0
|
* 1.132.3
|
||||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||||
* See https://www.npmjs.com/package/oazapfts
|
* See https://www.npmjs.com/package/oazapfts
|
||||||
*/
|
*/
|
||||||
@@ -39,6 +39,48 @@ export type ActivityCreateDto = {
|
|||||||
export type ActivityStatisticsResponseDto = {
|
export type ActivityStatisticsResponseDto = {
|
||||||
comments: number;
|
comments: number;
|
||||||
};
|
};
|
||||||
|
export type NotificationCreateDto = {
|
||||||
|
data?: object;
|
||||||
|
description?: string | null;
|
||||||
|
level?: NotificationLevel;
|
||||||
|
readAt?: string | null;
|
||||||
|
title: string;
|
||||||
|
"type"?: NotificationType;
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
|
export type NotificationDto = {
|
||||||
|
createdAt: string;
|
||||||
|
data?: object;
|
||||||
|
description?: string;
|
||||||
|
id: string;
|
||||||
|
level: NotificationLevel;
|
||||||
|
readAt?: string;
|
||||||
|
title: string;
|
||||||
|
"type": NotificationType;
|
||||||
|
};
|
||||||
|
export type TemplateDto = {
|
||||||
|
template: string;
|
||||||
|
};
|
||||||
|
export type TemplateResponseDto = {
|
||||||
|
html: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
export type SystemConfigSmtpTransportDto = {
|
||||||
|
host: string;
|
||||||
|
ignoreCert: boolean;
|
||||||
|
password: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
export type SystemConfigSmtpDto = {
|
||||||
|
enabled: boolean;
|
||||||
|
"from": string;
|
||||||
|
replyTo: string;
|
||||||
|
transport: SystemConfigSmtpTransportDto;
|
||||||
|
};
|
||||||
|
export type TestEmailResponseDto = {
|
||||||
|
messageId: string;
|
||||||
|
};
|
||||||
export type UserLicense = {
|
export type UserLicense = {
|
||||||
activatedAt: string;
|
activatedAt: string;
|
||||||
activationKey: string;
|
activationKey: string;
|
||||||
@@ -64,6 +106,7 @@ export type UserAdminResponseDto = {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
export type UserAdminCreateDto = {
|
export type UserAdminCreateDto = {
|
||||||
|
avatarColor?: (UserAvatarColor) | null;
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
notify?: boolean;
|
notify?: boolean;
|
||||||
@@ -76,6 +119,7 @@ export type UserAdminDeleteDto = {
|
|||||||
force?: boolean;
|
force?: boolean;
|
||||||
};
|
};
|
||||||
export type UserAdminUpdateDto = {
|
export type UserAdminUpdateDto = {
|
||||||
|
avatarColor?: (UserAvatarColor) | null;
|
||||||
email?: string;
|
email?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
@@ -83,9 +127,6 @@ export type UserAdminUpdateDto = {
|
|||||||
shouldChangePassword?: boolean;
|
shouldChangePassword?: boolean;
|
||||||
storageLabel?: string | null;
|
storageLabel?: string | null;
|
||||||
};
|
};
|
||||||
export type AvatarResponse = {
|
|
||||||
color: UserAvatarColor;
|
|
||||||
};
|
|
||||||
export type DownloadResponse = {
|
export type DownloadResponse = {
|
||||||
archiveSize: number;
|
archiveSize: number;
|
||||||
includeEmbeddedVideos: boolean;
|
includeEmbeddedVideos: boolean;
|
||||||
@@ -122,7 +163,6 @@ export type TagsResponse = {
|
|||||||
sidebarWeb: boolean;
|
sidebarWeb: boolean;
|
||||||
};
|
};
|
||||||
export type UserPreferencesResponseDto = {
|
export type UserPreferencesResponseDto = {
|
||||||
avatar: AvatarResponse;
|
|
||||||
download: DownloadResponse;
|
download: DownloadResponse;
|
||||||
emailNotifications: EmailNotificationsResponse;
|
emailNotifications: EmailNotificationsResponse;
|
||||||
folders: FoldersResponse;
|
folders: FoldersResponse;
|
||||||
@@ -663,28 +703,15 @@ export type MemoryUpdateDto = {
|
|||||||
memoryAt?: string;
|
memoryAt?: string;
|
||||||
seenAt?: string;
|
seenAt?: string;
|
||||||
};
|
};
|
||||||
export type TemplateDto = {
|
export type NotificationDeleteAllDto = {
|
||||||
template: string;
|
ids: string[];
|
||||||
};
|
};
|
||||||
export type TemplateResponseDto = {
|
export type NotificationUpdateAllDto = {
|
||||||
html: string;
|
ids: string[];
|
||||||
name: string;
|
readAt?: string | null;
|
||||||
};
|
};
|
||||||
export type SystemConfigSmtpTransportDto = {
|
export type NotificationUpdateDto = {
|
||||||
host: string;
|
readAt?: string | null;
|
||||||
ignoreCert: boolean;
|
|
||||||
password: string;
|
|
||||||
port: number;
|
|
||||||
username: string;
|
|
||||||
};
|
|
||||||
export type SystemConfigSmtpDto = {
|
|
||||||
enabled: boolean;
|
|
||||||
"from": string;
|
|
||||||
replyTo: string;
|
|
||||||
transport: SystemConfigSmtpTransportDto;
|
|
||||||
};
|
|
||||||
export type TestEmailResponseDto = {
|
|
||||||
messageId: string;
|
|
||||||
};
|
};
|
||||||
export type OAuthConfigDto = {
|
export type OAuthConfigDto = {
|
||||||
codeChallenge?: string;
|
codeChallenge?: string;
|
||||||
@@ -1288,6 +1315,8 @@ export type SystemConfigOAuthDto = {
|
|||||||
signingAlgorithm: string;
|
signingAlgorithm: string;
|
||||||
storageLabelClaim: string;
|
storageLabelClaim: string;
|
||||||
storageQuotaClaim: string;
|
storageQuotaClaim: string;
|
||||||
|
timeout: number;
|
||||||
|
tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod;
|
||||||
};
|
};
|
||||||
export type SystemConfigPasswordLoginDto = {
|
export type SystemConfigPasswordLoginDto = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@@ -1388,6 +1417,7 @@ export type TrashResponseDto = {
|
|||||||
count: number;
|
count: number;
|
||||||
};
|
};
|
||||||
export type UserUpdateMeDto = {
|
export type UserUpdateMeDto = {
|
||||||
|
avatarColor?: (UserAvatarColor) | null;
|
||||||
email?: string;
|
email?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
@@ -1454,6 +1484,43 @@ export function deleteActivity({ id }: {
|
|||||||
method: "DELETE"
|
method: "DELETE"
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
export function createNotification({ notificationCreateDto }: {
|
||||||
|
notificationCreateDto: NotificationCreateDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 201;
|
||||||
|
data: NotificationDto;
|
||||||
|
}>("/admin/notifications", oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: notificationCreateDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
export function getNotificationTemplateAdmin({ name, templateDto }: {
|
||||||
|
name: string;
|
||||||
|
templateDto: TemplateDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: TemplateResponseDto;
|
||||||
|
}>(`/admin/notifications/templates/${encodeURIComponent(name)}`, oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: templateDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
export function sendTestEmailAdmin({ systemConfigSmtpDto }: {
|
||||||
|
systemConfigSmtpDto: SystemConfigSmtpDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: TestEmailResponseDto;
|
||||||
|
}>("/admin/notifications/test-email", oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: systemConfigSmtpDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
export function searchUsersAdmin({ withDeleted }: {
|
export function searchUsersAdmin({ withDeleted }: {
|
||||||
withDeleted?: boolean;
|
withDeleted?: boolean;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
@@ -2322,29 +2389,71 @@ export function addMemoryAssets({ id, bulkIdsDto }: {
|
|||||||
body: bulkIdsDto
|
body: bulkIdsDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
export function getNotificationTemplateAdmin({ name, templateDto }: {
|
export function deleteNotifications({ notificationDeleteAllDto }: {
|
||||||
name: string;
|
notificationDeleteAllDto: NotificationDeleteAllDto;
|
||||||
templateDto: TemplateDto;
|
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchText("/notifications", oazapfts.json({
|
||||||
status: 200;
|
|
||||||
data: TemplateResponseDto;
|
|
||||||
}>(`/notifications/admin/templates/${encodeURIComponent(name)}`, oazapfts.json({
|
|
||||||
...opts,
|
...opts,
|
||||||
method: "POST",
|
method: "DELETE",
|
||||||
body: templateDto
|
body: notificationDeleteAllDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
export function sendTestEmailAdmin({ systemConfigSmtpDto }: {
|
export function getNotifications({ id, level, $type, unread }: {
|
||||||
systemConfigSmtpDto: SystemConfigSmtpDto;
|
id?: string;
|
||||||
|
level?: NotificationLevel;
|
||||||
|
$type?: NotificationType;
|
||||||
|
unread?: boolean;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
status: 200;
|
status: 200;
|
||||||
data: TestEmailResponseDto;
|
data: NotificationDto[];
|
||||||
}>("/notifications/admin/test-email", oazapfts.json({
|
}>(`/notifications${QS.query(QS.explode({
|
||||||
|
id,
|
||||||
|
level,
|
||||||
|
"type": $type,
|
||||||
|
unread
|
||||||
|
}))}`, {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
export function updateNotifications({ notificationUpdateAllDto }: {
|
||||||
|
notificationUpdateAllDto: NotificationUpdateAllDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchText("/notifications", oazapfts.json({
|
||||||
...opts,
|
...opts,
|
||||||
method: "POST",
|
method: "PUT",
|
||||||
body: systemConfigSmtpDto
|
body: notificationUpdateAllDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
export function deleteNotification({ id }: {
|
||||||
|
id: string;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchText(`/notifications/${encodeURIComponent(id)}`, {
|
||||||
|
...opts,
|
||||||
|
method: "DELETE"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
export function getNotification({ id }: {
|
||||||
|
id: string;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: NotificationDto;
|
||||||
|
}>(`/notifications/${encodeURIComponent(id)}`, {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
export function updateNotification({ id, notificationUpdateDto }: {
|
||||||
|
id: string;
|
||||||
|
notificationUpdateDto: NotificationUpdateDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: NotificationDto;
|
||||||
|
}>(`/notifications/${encodeURIComponent(id)}`, oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "PUT",
|
||||||
|
body: notificationUpdateDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
export function startOAuth({ oAuthConfigDto }: {
|
export function startOAuth({ oAuthConfigDto }: {
|
||||||
@@ -3453,6 +3562,18 @@ export enum UserAvatarColor {
|
|||||||
Gray = "gray",
|
Gray = "gray",
|
||||||
Amber = "amber"
|
Amber = "amber"
|
||||||
}
|
}
|
||||||
|
export enum NotificationLevel {
|
||||||
|
Success = "success",
|
||||||
|
Error = "error",
|
||||||
|
Warning = "warning",
|
||||||
|
Info = "info"
|
||||||
|
}
|
||||||
|
export enum NotificationType {
|
||||||
|
JobFailed = "JobFailed",
|
||||||
|
BackupFailed = "BackupFailed",
|
||||||
|
SystemMessage = "SystemMessage",
|
||||||
|
Custom = "Custom"
|
||||||
|
}
|
||||||
export enum UserStatus {
|
export enum UserStatus {
|
||||||
Active = "active",
|
Active = "active",
|
||||||
Removing = "removing",
|
Removing = "removing",
|
||||||
@@ -3527,6 +3648,10 @@ export enum Permission {
|
|||||||
MemoryRead = "memory.read",
|
MemoryRead = "memory.read",
|
||||||
MemoryUpdate = "memory.update",
|
MemoryUpdate = "memory.update",
|
||||||
MemoryDelete = "memory.delete",
|
MemoryDelete = "memory.delete",
|
||||||
|
NotificationCreate = "notification.create",
|
||||||
|
NotificationRead = "notification.read",
|
||||||
|
NotificationUpdate = "notification.update",
|
||||||
|
NotificationDelete = "notification.delete",
|
||||||
PartnerCreate = "partner.create",
|
PartnerCreate = "partner.create",
|
||||||
PartnerRead = "partner.read",
|
PartnerRead = "partner.read",
|
||||||
PartnerUpdate = "partner.update",
|
PartnerUpdate = "partner.update",
|
||||||
@@ -3736,6 +3861,10 @@ export enum LogLevel {
|
|||||||
Error = "error",
|
Error = "error",
|
||||||
Fatal = "fatal"
|
Fatal = "fatal"
|
||||||
}
|
}
|
||||||
|
export enum OAuthTokenEndpointAuthMethod {
|
||||||
|
ClientSecretPost = "client_secret_post",
|
||||||
|
ClientSecretBasic = "client_secret_basic"
|
||||||
|
}
|
||||||
export enum TimeBucketSize {
|
export enum TimeBucketSize {
|
||||||
Day = "DAY",
|
Day = "DAY",
|
||||||
Month = "MONTH"
|
Month = "MONTH"
|
||||||
|
|||||||
+10
-10
@@ -6,14 +6,14 @@ WORKDIR /usr/src/app
|
|||||||
COPY server/package.json server/package-lock.json ./
|
COPY server/package.json server/package-lock.json ./
|
||||||
COPY server/patches ./patches
|
COPY server/patches ./patches
|
||||||
RUN npm ci && \
|
RUN npm ci && \
|
||||||
# exiftool-vendored.pl, sharp-linux-x64 and sharp-linux-arm64 are the only ones we need
|
# exiftool-vendored.pl, sharp-linux-x64 and sharp-linux-arm64 are the only ones we need
|
||||||
# they're marked as optional dependencies, so we need to copy them manually after pruning
|
# they're marked as optional dependencies, so we need to copy them manually after pruning
|
||||||
rm -rf node_modules/@img/sharp-libvips* && \
|
rm -rf node_modules/@img/sharp-libvips* && \
|
||||||
rm -rf node_modules/@img/sharp-linuxmusl-x64
|
rm -rf node_modules/@img/sharp-linuxmusl-x64
|
||||||
ENV PATH="${PATH}:/usr/src/app/bin" \
|
ENV PATH="${PATH}:/usr/src/app/bin" \
|
||||||
IMMICH_ENV=development \
|
IMMICH_ENV=development \
|
||||||
NVIDIA_DRIVER_CAPABILITIES=all \
|
NVIDIA_DRIVER_CAPABILITIES=all \
|
||||||
NVIDIA_VISIBLE_DEVICES=all
|
NVIDIA_VISIBLE_DEVICES=all
|
||||||
ENTRYPOINT ["tini", "--", "/bin/sh"]
|
ENTRYPOINT ["tini", "--", "/bin/sh"]
|
||||||
|
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img
|
|||||||
COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl
|
COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl
|
||||||
|
|
||||||
# web build
|
# web build
|
||||||
FROM node:22.14.0-alpine3.20@sha256:40be979442621049f40b1d51a26b55e281246b5de4e5f51a18da7beb6e17e3f9 AS web
|
FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS web
|
||||||
|
|
||||||
WORKDIR /usr/src/open-api/typescript-sdk
|
WORKDIR /usr/src/open-api/typescript-sdk
|
||||||
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./
|
||||||
@@ -47,8 +47,8 @@ FROM ghcr.io/immich-app/base-server-prod:202504081114@sha256:8353bcbdb4e6579300a
|
|||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
NVIDIA_DRIVER_CAPABILITIES=all \
|
NVIDIA_DRIVER_CAPABILITIES=all \
|
||||||
NVIDIA_VISIBLE_DEVICES=all
|
NVIDIA_VISIBLE_DEVICES=all
|
||||||
COPY --from=prod /usr/src/app/node_modules ./node_modules
|
COPY --from=prod /usr/src/app/node_modules ./node_modules
|
||||||
COPY --from=prod /usr/src/app/dist ./dist
|
COPY --from=prod /usr/src/app/dist ./dist
|
||||||
COPY --from=prod /usr/src/app/bin ./bin
|
COPY --from=prod /usr/src/app/bin ./bin
|
||||||
|
|||||||
Generated
+1642
-263
File diff suppressed because it is too large
Load Diff
+9
-3
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich",
|
"name": "immich",
|
||||||
"version": "1.132.0",
|
"version": "1.132.3",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
|
"compression": "^1.8.0",
|
||||||
"cookie": "^1.0.2",
|
"cookie": "^1.0.2",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"exiftool-vendored": "^28.3.1",
|
"exiftool-vendored": "^28.3.1",
|
||||||
@@ -88,7 +89,7 @@
|
|||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"sanitize-html": "^2.14.0",
|
"sanitize-html": "^2.14.0",
|
||||||
"semver": "^7.6.2",
|
"semver": "^7.6.2",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.34.0",
|
||||||
"sirv": "^3.0.0",
|
"sirv": "^3.0.0",
|
||||||
"tailwindcss-preset-email": "^1.3.2",
|
"tailwindcss-preset-email": "^1.3.2",
|
||||||
"thumbhash": "^0.1.1",
|
"thumbhash": "^0.1.1",
|
||||||
@@ -108,6 +109,7 @@
|
|||||||
"@types/archiver": "^6.0.0",
|
"@types/archiver": "^6.0.0",
|
||||||
"@types/async-lock": "^1.4.2",
|
"@types/async-lock": "^1.4.2",
|
||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/compression": "^1.7.5",
|
||||||
"@types/cookie-parser": "^1.4.8",
|
"@types/cookie-parser": "^1.4.8",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/fluent-ffmpeg": "^2.1.21",
|
"@types/fluent-ffmpeg": "^2.1.21",
|
||||||
@@ -132,7 +134,8 @@
|
|||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
"jsdom": "^26.1.0",
|
"jsdom": "^26.1.0",
|
||||||
"mock-fs": "^5.2.0",
|
"mock-fs": "^5.2.0",
|
||||||
"node-addon-api": "^8.3.0",
|
"node-addon-api": "^8.3.1",
|
||||||
|
"node-gyp": "^11.2.0",
|
||||||
"patch-package": "^8.0.0",
|
"patch-package": "^8.0.0",
|
||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"prettier": "^3.0.2",
|
"prettier": "^3.0.2",
|
||||||
@@ -152,5 +155,8 @@
|
|||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.14.0"
|
"node": "22.14.0"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"sharp": "^0.34.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const imports = [
|
|||||||
BullModule.registerQueue(...bull.queues),
|
BullModule.registerQueue(...bull.queues),
|
||||||
ClsModule.forRoot(cls.config),
|
ClsModule.forRoot(cls.config),
|
||||||
OpenTelemetryModule.forRoot(otel),
|
OpenTelemetryModule.forRoot(otel),
|
||||||
KyselyModule.forRoot(getKyselyConfig(database.config.kysely)),
|
KyselyModule.forRoot(getKyselyConfig(database.config)),
|
||||||
];
|
];
|
||||||
|
|
||||||
class BaseModule implements OnModuleInit, OnModuleDestroy {
|
class BaseModule implements OnModuleInit, OnModuleDestroy {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { DatabaseRepository } from 'src/repositories/database.repository';
|
|||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import 'src/schema';
|
import 'src/schema';
|
||||||
import { schemaDiff, schemaFromCode, schemaFromDatabase } from 'src/sql-tools';
|
import { schemaDiff, schemaFromCode, schemaFromDatabase } from 'src/sql-tools';
|
||||||
import { getKyselyConfig } from 'src/utils/database';
|
import { asPostgresConnectionConfig, getKyselyConfig } from 'src/utils/database';
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
const command = process.argv[2];
|
const command = process.argv[2];
|
||||||
@@ -56,7 +56,7 @@ const main = async () => {
|
|||||||
const getDatabaseClient = () => {
|
const getDatabaseClient = () => {
|
||||||
const configRepository = new ConfigRepository();
|
const configRepository = new ConfigRepository();
|
||||||
const { database } = configRepository.getEnv();
|
const { database } = configRepository.getEnv();
|
||||||
return new Kysely<any>(getKyselyConfig(database.config.kysely));
|
return new Kysely<any>(getKyselyConfig(database.config));
|
||||||
};
|
};
|
||||||
|
|
||||||
const runQuery = async (query: string) => {
|
const runQuery = async (query: string) => {
|
||||||
@@ -105,7 +105,7 @@ const create = (path: string, up: string[], down: string[]) => {
|
|||||||
const compare = async () => {
|
const compare = async () => {
|
||||||
const configRepository = new ConfigRepository();
|
const configRepository = new ConfigRepository();
|
||||||
const { database } = configRepository.getEnv();
|
const { database } = configRepository.getEnv();
|
||||||
const db = postgres(database.config.kysely);
|
const db = postgres(asPostgresConnectionConfig(database.config));
|
||||||
|
|
||||||
const source = schemaFromCode();
|
const source = schemaFromCode();
|
||||||
const target = await schemaFromDatabase(db, {});
|
const target = await schemaFromDatabase(db, {});
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class SqlGenerator {
|
|||||||
const moduleFixture = await Test.createTestingModule({
|
const moduleFixture = await Test.createTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
KyselyModule.forRoot({
|
KyselyModule.forRoot({
|
||||||
...getKyselyConfig(database.config.kysely),
|
...getKyselyConfig(database.config),
|
||||||
log: (event) => {
|
log: (event) => {
|
||||||
if (event.level === 'query') {
|
if (event.level === 'query') {
|
||||||
this.sqlLogger.logQuery(event.query.sql);
|
this.sqlLogger.logQuery(event.query.sql);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
CQMode,
|
CQMode,
|
||||||
ImageFormat,
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
|
OAuthTokenEndpointAuthMethod,
|
||||||
QueueName,
|
QueueName,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
@@ -96,6 +97,8 @@ export interface SystemConfig {
|
|||||||
scope: string;
|
scope: string;
|
||||||
signingAlgorithm: string;
|
signingAlgorithm: string;
|
||||||
profileSigningAlgorithm: string;
|
profileSigningAlgorithm: string;
|
||||||
|
tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod;
|
||||||
|
timeout: number;
|
||||||
storageLabelClaim: string;
|
storageLabelClaim: string;
|
||||||
storageQuotaClaim: string;
|
storageQuotaClaim: string;
|
||||||
};
|
};
|
||||||
@@ -260,6 +263,8 @@ export const defaults = Object.freeze<SystemConfig>({
|
|||||||
profileSigningAlgorithm: 'none',
|
profileSigningAlgorithm: 'none',
|
||||||
storageLabelClaim: 'preferred_username',
|
storageLabelClaim: 'preferred_username',
|
||||||
storageQuotaClaim: 'immich_quota',
|
storageQuotaClaim: 'immich_quota',
|
||||||
|
tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod.CLIENT_SECRET_POST,
|
||||||
|
timeout: 30_000,
|
||||||
},
|
},
|
||||||
passwordLogin: {
|
passwordLogin: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { LibraryController } from 'src/controllers/library.controller';
|
|||||||
import { MapController } from 'src/controllers/map.controller';
|
import { MapController } from 'src/controllers/map.controller';
|
||||||
import { MemoryController } from 'src/controllers/memory.controller';
|
import { MemoryController } from 'src/controllers/memory.controller';
|
||||||
import { NotificationAdminController } from 'src/controllers/notification-admin.controller';
|
import { NotificationAdminController } from 'src/controllers/notification-admin.controller';
|
||||||
|
import { NotificationController } from 'src/controllers/notification.controller';
|
||||||
import { OAuthController } from 'src/controllers/oauth.controller';
|
import { OAuthController } from 'src/controllers/oauth.controller';
|
||||||
import { PartnerController } from 'src/controllers/partner.controller';
|
import { PartnerController } from 'src/controllers/partner.controller';
|
||||||
import { PersonController } from 'src/controllers/person.controller';
|
import { PersonController } from 'src/controllers/person.controller';
|
||||||
@@ -47,6 +48,7 @@ export const controllers = [
|
|||||||
LibraryController,
|
LibraryController,
|
||||||
MapController,
|
MapController,
|
||||||
MemoryController,
|
MemoryController,
|
||||||
|
NotificationController,
|
||||||
NotificationAdminController,
|
NotificationAdminController,
|
||||||
OAuthController,
|
OAuthController,
|
||||||
PartnerController,
|
PartnerController,
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
import { Body, Controller, HttpCode, HttpStatus, Param, Post } from '@nestjs/common';
|
import { Body, Controller, HttpCode, HttpStatus, Param, Post } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto';
|
import {
|
||||||
|
NotificationCreateDto,
|
||||||
|
NotificationDto,
|
||||||
|
TemplateDto,
|
||||||
|
TemplateResponseDto,
|
||||||
|
TestEmailResponseDto,
|
||||||
|
} from 'src/dtos/notification.dto';
|
||||||
import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
|
import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { EmailTemplate } from 'src/repositories/email.repository';
|
import { EmailTemplate } from 'src/repositories/email.repository';
|
||||||
import { NotificationService } from 'src/services/notification.service';
|
import { NotificationAdminService } from 'src/services/notification-admin.service';
|
||||||
|
|
||||||
@ApiTags('Notifications (Admin)')
|
@ApiTags('Notifications (Admin)')
|
||||||
@Controller('notifications/admin')
|
@Controller('admin/notifications')
|
||||||
export class NotificationAdminController {
|
export class NotificationAdminController {
|
||||||
constructor(private service: NotificationService) {}
|
constructor(private service: NotificationAdminService) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
@Authenticated({ admin: true })
|
||||||
|
createNotification(@Auth() auth: AuthDto, @Body() dto: NotificationCreateDto): Promise<NotificationDto> {
|
||||||
|
return this.service.create(auth, dto);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('test-email')
|
@Post('test-email')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { Body, Controller, Delete, Get, Param, Put, Query } from '@nestjs/common';
|
||||||
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
|
import {
|
||||||
|
NotificationDeleteAllDto,
|
||||||
|
NotificationDto,
|
||||||
|
NotificationSearchDto,
|
||||||
|
NotificationUpdateAllDto,
|
||||||
|
NotificationUpdateDto,
|
||||||
|
} from 'src/dtos/notification.dto';
|
||||||
|
import { Permission } from 'src/enum';
|
||||||
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
|
import { NotificationService } from 'src/services/notification.service';
|
||||||
|
import { UUIDParamDto } from 'src/validation';
|
||||||
|
|
||||||
|
@ApiTags('Notifications')
|
||||||
|
@Controller('notifications')
|
||||||
|
export class NotificationController {
|
||||||
|
constructor(private service: NotificationService) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
@Authenticated({ permission: Permission.NOTIFICATION_READ })
|
||||||
|
getNotifications(@Auth() auth: AuthDto, @Query() dto: NotificationSearchDto): Promise<NotificationDto[]> {
|
||||||
|
return this.service.search(auth, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put()
|
||||||
|
@Authenticated({ permission: Permission.NOTIFICATION_UPDATE })
|
||||||
|
updateNotifications(@Auth() auth: AuthDto, @Body() dto: NotificationUpdateAllDto): Promise<void> {
|
||||||
|
return this.service.updateAll(auth, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete()
|
||||||
|
@Authenticated({ permission: Permission.NOTIFICATION_DELETE })
|
||||||
|
deleteNotifications(@Auth() auth: AuthDto, @Body() dto: NotificationDeleteAllDto): Promise<void> {
|
||||||
|
return this.service.deleteAll(auth, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
@Authenticated({ permission: Permission.NOTIFICATION_READ })
|
||||||
|
getNotification(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<NotificationDto> {
|
||||||
|
return this.service.get(auth, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put(':id')
|
||||||
|
@Authenticated({ permission: Permission.NOTIFICATION_UPDATE })
|
||||||
|
updateNotification(
|
||||||
|
@Auth() auth: AuthDto,
|
||||||
|
@Param() { id }: UUIDParamDto,
|
||||||
|
@Body() dto: NotificationUpdateDto,
|
||||||
|
): Promise<NotificationDto> {
|
||||||
|
return this.service.update(auth, id, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
@Authenticated({ permission: Permission.NOTIFICATION_DELETE })
|
||||||
|
deleteNotification(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||||
|
return this.service.delete(auth, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,7 +90,7 @@ export class StorageCore {
|
|||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getImagePath(asset: ThumbnailPathEntity, type: GeneratedImageType, format: ImageFormat) {
|
static getImagePath(asset: ThumbnailPathEntity, type: GeneratedImageType, format: 'jpeg' | 'webp') {
|
||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-2
@@ -9,6 +9,7 @@ import {
|
|||||||
Permission,
|
Permission,
|
||||||
SharedLinkType,
|
SharedLinkType,
|
||||||
SourceType,
|
SourceType,
|
||||||
|
UserAvatarColor,
|
||||||
UserStatus,
|
UserStatus,
|
||||||
} from 'src/enum';
|
} from 'src/enum';
|
||||||
import { OnThisDayData, UserMetadataItem } from 'src/types';
|
import { OnThisDayData, UserMetadataItem } from 'src/types';
|
||||||
@@ -122,6 +123,7 @@ export type User = {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
avatarColor: UserAvatarColor | null;
|
||||||
profileImagePath: string;
|
profileImagePath: string;
|
||||||
profileChangedAt: Date;
|
profileChangedAt: Date;
|
||||||
};
|
};
|
||||||
@@ -264,7 +266,15 @@ export type AssetFace = {
|
|||||||
person?: Person | null;
|
person?: Person | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const userColumns = ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'] as const;
|
const userColumns = ['id', 'name', 'email', 'avatarColor', 'profileImagePath', 'profileChangedAt'] as const;
|
||||||
|
const userWithPrefixColumns = [
|
||||||
|
'users.id',
|
||||||
|
'users.name',
|
||||||
|
'users.email',
|
||||||
|
'users.avatarColor',
|
||||||
|
'users.profileImagePath',
|
||||||
|
'users.profileChangedAt',
|
||||||
|
] as const;
|
||||||
|
|
||||||
export const columns = {
|
export const columns = {
|
||||||
asset: [
|
asset: [
|
||||||
@@ -306,7 +316,7 @@ export const columns = {
|
|||||||
'shared_links.password',
|
'shared_links.password',
|
||||||
],
|
],
|
||||||
user: userColumns,
|
user: userColumns,
|
||||||
userWithPrefix: ['users.id', 'users.name', 'users.email', 'users.profileImagePath', 'users.profileChangedAt'],
|
userWithPrefix: userWithPrefixColumns,
|
||||||
userAdmin: [
|
userAdmin: [
|
||||||
...userColumns,
|
...userColumns,
|
||||||
'createdAt',
|
'createdAt',
|
||||||
@@ -323,6 +333,7 @@ export const columns = {
|
|||||||
],
|
],
|
||||||
tag: ['tags.id', 'tags.value', 'tags.createdAt', 'tags.updatedAt', 'tags.color', 'tags.parentId'],
|
tag: ['tags.id', 'tags.value', 'tags.createdAt', 'tags.updatedAt', 'tags.color', 'tags.parentId'],
|
||||||
apiKey: ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'],
|
apiKey: ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'],
|
||||||
|
notification: ['id', 'createdAt', 'level', 'type', 'title', 'description', 'data', 'readAt'],
|
||||||
syncAsset: [
|
syncAsset: [
|
||||||
'id',
|
'id',
|
||||||
'ownerId',
|
'ownerId',
|
||||||
|
|||||||
Vendored
+18
@@ -11,6 +11,8 @@ import {
|
|||||||
AssetStatus,
|
AssetStatus,
|
||||||
AssetType,
|
AssetType,
|
||||||
MemoryType,
|
MemoryType,
|
||||||
|
NotificationLevel,
|
||||||
|
NotificationType,
|
||||||
Permission,
|
Permission,
|
||||||
SharedLinkType,
|
SharedLinkType,
|
||||||
SourceType,
|
SourceType,
|
||||||
@@ -263,6 +265,21 @@ export interface Memories {
|
|||||||
updateId: Generated<string>;
|
updateId: Generated<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Notifications {
|
||||||
|
id: Generated<string>;
|
||||||
|
createdAt: Generated<Timestamp>;
|
||||||
|
updatedAt: Generated<Timestamp>;
|
||||||
|
deletedAt: Timestamp | null;
|
||||||
|
updateId: Generated<string>;
|
||||||
|
userId: string;
|
||||||
|
level: Generated<NotificationLevel>;
|
||||||
|
type: NotificationType;
|
||||||
|
title: string;
|
||||||
|
description: string | null;
|
||||||
|
data: any | null;
|
||||||
|
readAt: Timestamp | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MemoriesAssetsAssets {
|
export interface MemoriesAssetsAssets {
|
||||||
assetsId: string;
|
assetsId: string;
|
||||||
memoriesId: string;
|
memoriesId: string;
|
||||||
@@ -463,6 +480,7 @@ export interface DB {
|
|||||||
memories: Memories;
|
memories: Memories;
|
||||||
memories_assets_assets: MemoriesAssetsAssets;
|
memories_assets_assets: MemoriesAssetsAssets;
|
||||||
migrations: Migrations;
|
migrations: Migrations;
|
||||||
|
notifications: Notifications;
|
||||||
move_history: MoveHistory;
|
move_history: MoveHistory;
|
||||||
naturalearth_countries: NaturalearthCountries;
|
naturalearth_countries: NaturalearthCountries;
|
||||||
partners_audit: PartnersAudit;
|
partners_audit: PartnersAudit;
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { IsString } from 'class-validator';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsEnum, IsString } from 'class-validator';
|
||||||
|
import { NotificationLevel, NotificationType } from 'src/enum';
|
||||||
|
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
export class TestEmailResponseDto {
|
export class TestEmailResponseDto {
|
||||||
messageId!: string;
|
messageId!: string;
|
||||||
@@ -11,3 +14,106 @@ export class TemplateDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
template!: string;
|
template!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NotificationDto {
|
||||||
|
id!: string;
|
||||||
|
@ValidateDate()
|
||||||
|
createdAt!: Date;
|
||||||
|
@ApiProperty({ enum: NotificationLevel, enumName: 'NotificationLevel' })
|
||||||
|
level!: NotificationLevel;
|
||||||
|
@ApiProperty({ enum: NotificationType, enumName: 'NotificationType' })
|
||||||
|
type!: NotificationType;
|
||||||
|
title!: string;
|
||||||
|
description?: string;
|
||||||
|
data?: any;
|
||||||
|
readAt?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotificationSearchDto {
|
||||||
|
@Optional()
|
||||||
|
@ValidateUUID({ optional: true })
|
||||||
|
id?: string;
|
||||||
|
|
||||||
|
@IsEnum(NotificationLevel)
|
||||||
|
@Optional()
|
||||||
|
@ApiProperty({ enum: NotificationLevel, enumName: 'NotificationLevel' })
|
||||||
|
level?: NotificationLevel;
|
||||||
|
|
||||||
|
@IsEnum(NotificationType)
|
||||||
|
@Optional()
|
||||||
|
@ApiProperty({ enum: NotificationType, enumName: 'NotificationType' })
|
||||||
|
type?: NotificationType;
|
||||||
|
|
||||||
|
@ValidateBoolean({ optional: true })
|
||||||
|
unread?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotificationCreateDto {
|
||||||
|
@Optional()
|
||||||
|
@IsEnum(NotificationLevel)
|
||||||
|
@ApiProperty({ enum: NotificationLevel, enumName: 'NotificationLevel' })
|
||||||
|
level?: NotificationLevel;
|
||||||
|
|
||||||
|
@IsEnum(NotificationType)
|
||||||
|
@Optional()
|
||||||
|
@ApiProperty({ enum: NotificationType, enumName: 'NotificationType' })
|
||||||
|
type?: NotificationType;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
title!: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@Optional({ nullable: true })
|
||||||
|
description?: string | null;
|
||||||
|
|
||||||
|
@Optional({ nullable: true })
|
||||||
|
data?: any;
|
||||||
|
|
||||||
|
@ValidateDate({ optional: true, nullable: true })
|
||||||
|
readAt?: Date | null;
|
||||||
|
|
||||||
|
@ValidateUUID()
|
||||||
|
userId!: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotificationUpdateDto {
|
||||||
|
@ValidateDate({ optional: true, nullable: true })
|
||||||
|
readAt?: Date | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotificationUpdateAllDto {
|
||||||
|
@ValidateUUID({ each: true, optional: true })
|
||||||
|
ids!: string[];
|
||||||
|
|
||||||
|
@ValidateDate({ optional: true, nullable: true })
|
||||||
|
readAt?: Date | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotificationDeleteAllDto {
|
||||||
|
@ValidateUUID({ each: true })
|
||||||
|
ids!: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MapNotification = {
|
||||||
|
id: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updateId?: string;
|
||||||
|
level: NotificationLevel;
|
||||||
|
type: NotificationType;
|
||||||
|
data: any | null;
|
||||||
|
title: string;
|
||||||
|
description: string | null;
|
||||||
|
readAt: Date | null;
|
||||||
|
};
|
||||||
|
export const mapNotification = (notification: MapNotification): NotificationDto => {
|
||||||
|
return {
|
||||||
|
id: notification.id,
|
||||||
|
createdAt: notification.createdAt,
|
||||||
|
level: notification.level,
|
||||||
|
type: notification.type,
|
||||||
|
title: notification.title,
|
||||||
|
description: notification.description ?? undefined,
|
||||||
|
data: notification.data ?? undefined,
|
||||||
|
readAt: notification.readAt ?? undefined,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
Colorspace,
|
Colorspace,
|
||||||
ImageFormat,
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
|
OAuthTokenEndpointAuthMethod,
|
||||||
QueueName,
|
QueueName,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
@@ -33,7 +34,7 @@ import {
|
|||||||
VideoContainer,
|
VideoContainer,
|
||||||
} from 'src/enum';
|
} from 'src/enum';
|
||||||
import { ConcurrentQueueName } from 'src/types';
|
import { ConcurrentQueueName } from 'src/types';
|
||||||
import { IsCronExpression, ValidateBoolean } from 'src/validation';
|
import { IsCronExpression, Optional, ValidateBoolean } from 'src/validation';
|
||||||
|
|
||||||
const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled;
|
const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled;
|
||||||
const isOAuthEnabled = (config: SystemConfigOAuthDto) => config.enabled;
|
const isOAuthEnabled = (config: SystemConfigOAuthDto) => config.enabled;
|
||||||
@@ -344,10 +345,19 @@ class SystemConfigOAuthDto {
|
|||||||
clientId!: string;
|
clientId!: string;
|
||||||
|
|
||||||
@ValidateIf(isOAuthEnabled)
|
@ValidateIf(isOAuthEnabled)
|
||||||
@IsNotEmpty()
|
|
||||||
@IsString()
|
@IsString()
|
||||||
clientSecret!: string;
|
clientSecret!: string;
|
||||||
|
|
||||||
|
@IsEnum(OAuthTokenEndpointAuthMethod)
|
||||||
|
@ApiProperty({ enum: OAuthTokenEndpointAuthMethod, enumName: 'OAuthTokenEndpointAuthMethod' })
|
||||||
|
tokenEndpointAuthMethod!: OAuthTokenEndpointAuthMethod;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@IsPositive()
|
||||||
|
@Optional()
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
timeout!: number;
|
||||||
|
|
||||||
@IsNumber()
|
@IsNumber()
|
||||||
@Min(0)
|
@Min(0)
|
||||||
defaultStorageQuota!: number;
|
defaultStorageQuota!: number;
|
||||||
|
|||||||
@@ -137,11 +137,6 @@ export class UserPreferencesUpdateDto {
|
|||||||
purchase?: PurchaseUpdate;
|
purchase?: PurchaseUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AvatarResponse {
|
|
||||||
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
|
||||||
color!: UserAvatarColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
class RatingsResponse {
|
class RatingsResponse {
|
||||||
enabled: boolean = false;
|
enabled: boolean = false;
|
||||||
}
|
}
|
||||||
@@ -195,7 +190,6 @@ export class UserPreferencesResponseDto implements UserPreferences {
|
|||||||
ratings!: RatingsResponse;
|
ratings!: RatingsResponse;
|
||||||
sharedLinks!: SharedLinksResponse;
|
sharedLinks!: SharedLinksResponse;
|
||||||
tags!: TagsResponse;
|
tags!: TagsResponse;
|
||||||
avatar!: AvatarResponse;
|
|
||||||
emailNotifications!: EmailNotificationsResponse;
|
emailNotifications!: EmailNotificationsResponse;
|
||||||
download!: DownloadResponse;
|
download!: DownloadResponse;
|
||||||
purchase!: PurchaseResponse;
|
purchase!: PurchaseResponse;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Transform } from 'class-transformer';
|
import { Transform } from 'class-transformer';
|
||||||
import { IsBoolean, IsEmail, IsNotEmpty, IsNumber, IsString, Min } from 'class-validator';
|
import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsString, Min } from 'class-validator';
|
||||||
import { User, UserAdmin } from 'src/database';
|
import { User, UserAdmin } from 'src/database';
|
||||||
import { UserAvatarColor, UserMetadataKey, UserStatus } from 'src/enum';
|
import { UserAvatarColor, UserMetadataKey, UserStatus } from 'src/enum';
|
||||||
import { UserMetadataItem } from 'src/types';
|
import { UserMetadataItem } from 'src/types';
|
||||||
import { getPreferences } from 'src/utils/preferences';
|
|
||||||
import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation';
|
import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation';
|
||||||
|
|
||||||
export class UserUpdateMeDto {
|
export class UserUpdateMeDto {
|
||||||
@@ -23,6 +22,11 @@ export class UserUpdateMeDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
|
@Optional({ nullable: true })
|
||||||
|
@IsEnum(UserAvatarColor)
|
||||||
|
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||||
|
avatarColor?: UserAvatarColor | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserResponseDto {
|
export class UserResponseDto {
|
||||||
@@ -41,13 +45,21 @@ export class UserLicense {
|
|||||||
activatedAt!: Date;
|
activatedAt!: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emailToAvatarColor = (email: string): UserAvatarColor => {
|
||||||
|
const values = Object.values(UserAvatarColor);
|
||||||
|
const randomIndex = Math.floor(
|
||||||
|
[...email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length,
|
||||||
|
);
|
||||||
|
return values[randomIndex];
|
||||||
|
};
|
||||||
|
|
||||||
export const mapUser = (entity: User | UserAdmin): UserResponseDto => {
|
export const mapUser = (entity: User | UserAdmin): UserResponseDto => {
|
||||||
return {
|
return {
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
email: entity.email,
|
email: entity.email,
|
||||||
name: entity.name,
|
name: entity.name,
|
||||||
profileImagePath: entity.profileImagePath,
|
profileImagePath: entity.profileImagePath,
|
||||||
avatarColor: getPreferences(entity.email, (entity as UserAdmin).metadata || []).avatar.color,
|
avatarColor: entity.avatarColor ?? emailToAvatarColor(entity.email),
|
||||||
profileChangedAt: entity.profileChangedAt,
|
profileChangedAt: entity.profileChangedAt,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -69,6 +81,11 @@ export class UserAdminCreateDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
name!: string;
|
name!: string;
|
||||||
|
|
||||||
|
@Optional({ nullable: true })
|
||||||
|
@IsEnum(UserAvatarColor)
|
||||||
|
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||||
|
avatarColor?: UserAvatarColor | null;
|
||||||
|
|
||||||
@Optional({ nullable: true })
|
@Optional({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@Transform(toSanitized)
|
@Transform(toSanitized)
|
||||||
@@ -104,6 +121,11 @@ export class UserAdminUpdateDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
|
@Optional({ nullable: true })
|
||||||
|
@IsEnum(UserAvatarColor)
|
||||||
|
@ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor })
|
||||||
|
avatarColor?: UserAvatarColor | null;
|
||||||
|
|
||||||
@Optional({ nullable: true })
|
@Optional({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
@Transform(toSanitized)
|
@Transform(toSanitized)
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ export enum Permission {
|
|||||||
MEMORY_UPDATE = 'memory.update',
|
MEMORY_UPDATE = 'memory.update',
|
||||||
MEMORY_DELETE = 'memory.delete',
|
MEMORY_DELETE = 'memory.delete',
|
||||||
|
|
||||||
|
NOTIFICATION_CREATE = 'notification.create',
|
||||||
|
NOTIFICATION_READ = 'notification.read',
|
||||||
|
NOTIFICATION_UPDATE = 'notification.update',
|
||||||
|
NOTIFICATION_DELETE = 'notification.delete',
|
||||||
|
|
||||||
PARTNER_CREATE = 'partner.create',
|
PARTNER_CREATE = 'partner.create',
|
||||||
PARTNER_READ = 'partner.read',
|
PARTNER_READ = 'partner.read',
|
||||||
PARTNER_UPDATE = 'partner.update',
|
PARTNER_UPDATE = 'partner.update',
|
||||||
@@ -332,6 +337,11 @@ export enum ImageFormat {
|
|||||||
WEBP = 'webp',
|
WEBP = 'webp',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum RawExtractedFormat {
|
||||||
|
JPEG = 'jpeg',
|
||||||
|
JXL = 'jxl',
|
||||||
|
}
|
||||||
|
|
||||||
export enum LogLevel {
|
export enum LogLevel {
|
||||||
VERBOSE = 'verbose',
|
VERBOSE = 'verbose',
|
||||||
DEBUG = 'debug',
|
DEBUG = 'debug',
|
||||||
@@ -515,6 +525,7 @@ export enum JobName {
|
|||||||
NOTIFY_SIGNUP = 'notify-signup',
|
NOTIFY_SIGNUP = 'notify-signup',
|
||||||
NOTIFY_ALBUM_INVITE = 'notify-album-invite',
|
NOTIFY_ALBUM_INVITE = 'notify-album-invite',
|
||||||
NOTIFY_ALBUM_UPDATE = 'notify-album-update',
|
NOTIFY_ALBUM_UPDATE = 'notify-album-update',
|
||||||
|
NOTIFICATIONS_CLEANUP = 'notifications-cleanup',
|
||||||
SEND_EMAIL = 'notification-send-email',
|
SEND_EMAIL = 'notification-send-email',
|
||||||
|
|
||||||
// Version check
|
// Version check
|
||||||
@@ -580,3 +591,22 @@ export enum SyncEntityType {
|
|||||||
PartnerAssetDeleteV1 = 'PartnerAssetDeleteV1',
|
PartnerAssetDeleteV1 = 'PartnerAssetDeleteV1',
|
||||||
PartnerAssetExifV1 = 'PartnerAssetExifV1',
|
PartnerAssetExifV1 = 'PartnerAssetExifV1',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum NotificationLevel {
|
||||||
|
Success = 'success',
|
||||||
|
Error = 'error',
|
||||||
|
Warning = 'warning',
|
||||||
|
Info = 'info',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum NotificationType {
|
||||||
|
JobFailed = 'JobFailed',
|
||||||
|
BackupFailed = 'BackupFailed',
|
||||||
|
SystemMessage = 'SystemMessage',
|
||||||
|
Custom = 'Custom',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OAuthTokenEndpointAuthMethod {
|
||||||
|
CLIENT_SECRET_POST = 'client_secret_post',
|
||||||
|
CLIENT_SECRET_BASIC = 'client_secret_basic',
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DatabaseExtension } from 'src/enum';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { vectorIndexQuery } from 'src/utils/database';
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
|
const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
|
||||||
@@ -8,15 +8,9 @@ export class AddCLIPEmbeddingIndex1700713994428 implements MigrationInterface {
|
|||||||
name = 'AddCLIPEmbeddingIndex1700713994428';
|
name = 'AddCLIPEmbeddingIndex1700713994428';
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
if (vectorExtension === DatabaseExtension.VECTORS) {
|
|
||||||
await queryRunner.query(`SET vectors.pgvector_compatibility=on`);
|
|
||||||
}
|
|
||||||
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
||||||
|
|
||||||
await queryRunner.query(`
|
await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: 'clip_index' }));
|
||||||
CREATE INDEX IF NOT EXISTS clip_index ON smart_search
|
|
||||||
USING hnsw (embedding vector_cosine_ops)
|
|
||||||
WITH (ef_construction = 300, m = 16)`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DatabaseExtension } from 'src/enum';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { vectorIndexQuery } from 'src/utils/database';
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
|
const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
|
||||||
@@ -8,15 +8,9 @@ export class AddFaceEmbeddingIndex1700714033632 implements MigrationInterface {
|
|||||||
name = 'AddFaceEmbeddingIndex1700714033632';
|
name = 'AddFaceEmbeddingIndex1700714033632';
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
if (vectorExtension === DatabaseExtension.VECTORS) {
|
|
||||||
await queryRunner.query(`SET vectors.pgvector_compatibility=on`);
|
|
||||||
}
|
|
||||||
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
||||||
|
|
||||||
await queryRunner.query(`
|
await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'asset_faces', indexName: 'face_index' }));
|
||||||
CREATE INDEX IF NOT EXISTS face_index ON asset_faces
|
|
||||||
USING hnsw (embedding vector_cosine_ops)
|
|
||||||
WITH (ef_construction = 300, m = 16)`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { DatabaseExtension } from 'src/enum';
|
import { DatabaseExtension } from 'src/enum';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { vectorIndexQuery } from 'src/utils/database';
|
||||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
|
const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension;
|
||||||
@@ -8,7 +9,6 @@ export class AddFaceSearchRelation1718486162779 implements MigrationInterface {
|
|||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
if (vectorExtension === DatabaseExtension.VECTORS) {
|
if (vectorExtension === DatabaseExtension.VECTORS) {
|
||||||
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
||||||
await queryRunner.query(`SET vectors.pgvector_compatibility=on`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasEmbeddings = async (tableName: string): Promise<boolean> => {
|
const hasEmbeddings = async (tableName: string): Promise<boolean> => {
|
||||||
@@ -47,21 +47,14 @@ export class AddFaceSearchRelation1718486162779 implements MigrationInterface {
|
|||||||
await queryRunner.query(`ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE real[]`);
|
await queryRunner.query(`ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE real[]`);
|
||||||
await queryRunner.query(`ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE vector(512)`);
|
await queryRunner.query(`ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE vector(512)`);
|
||||||
|
|
||||||
await queryRunner.query(`
|
await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: 'clip_index' }));
|
||||||
CREATE INDEX IF NOT EXISTS clip_index ON smart_search
|
|
||||||
USING hnsw (embedding vector_cosine_ops)
|
|
||||||
WITH (ef_construction = 300, m = 16)`);
|
|
||||||
|
|
||||||
await queryRunner.query(`
|
await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'face_search', indexName: 'face_index' }));
|
||||||
CREATE INDEX face_index ON face_search
|
|
||||||
USING hnsw (embedding vector_cosine_ops)
|
|
||||||
WITH (ef_construction = 300, m = 16)`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
if (vectorExtension === DatabaseExtension.VECTORS) {
|
if (vectorExtension === DatabaseExtension.VECTORS) {
|
||||||
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
await queryRunner.query(`SET search_path TO "$user", public, vectors`);
|
||||||
await queryRunner.query(`SET vectors.pgvector_compatibility=on`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await queryRunner.query(`ALTER TABLE asset_faces ADD COLUMN "embedding" vector(512)`);
|
await queryRunner.query(`ALTER TABLE asset_faces ADD COLUMN "embedding" vector(512)`);
|
||||||
@@ -74,9 +67,6 @@ export class AddFaceSearchRelation1718486162779 implements MigrationInterface {
|
|||||||
WHERE id = fs."faceId"`);
|
WHERE id = fs."faceId"`);
|
||||||
await queryRunner.query(`DROP TABLE face_search`);
|
await queryRunner.query(`DROP TABLE face_search`);
|
||||||
|
|
||||||
await queryRunner.query(`
|
await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'asset_faces', indexName: 'face_index' }));
|
||||||
CREATE INDEX face_index ON asset_faces
|
|
||||||
USING hnsw (embedding vector_cosine_ops)
|
|
||||||
WITH (ef_construction = 300, m = 16)`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ where
|
|||||||
and "memories"."ownerId" = $2
|
and "memories"."ownerId" = $2
|
||||||
and "memories"."deletedAt" is null
|
and "memories"."deletedAt" is null
|
||||||
|
|
||||||
|
-- AccessRepository.notification.checkOwnerAccess
|
||||||
|
select
|
||||||
|
"notifications"."id"
|
||||||
|
from
|
||||||
|
"notifications"
|
||||||
|
where
|
||||||
|
"notifications"."id" in ($1)
|
||||||
|
and "notifications"."userId" = $2
|
||||||
|
|
||||||
-- AccessRepository.person.checkOwnerAccess
|
-- AccessRepository.person.checkOwnerAccess
|
||||||
select
|
select
|
||||||
"person"."id"
|
"person"."id"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from
|
|||||||
"users"."id",
|
"users"."id",
|
||||||
"users"."name",
|
"users"."name",
|
||||||
"users"."email",
|
"users"."email",
|
||||||
|
"users"."avatarColor",
|
||||||
"users"."profileImagePath",
|
"users"."profileImagePath",
|
||||||
"users"."profileChangedAt"
|
"users"."profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -44,6 +45,7 @@ returning
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -36,6 +37,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -100,6 +102,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -124,6 +127,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -191,6 +195,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -215,6 +220,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -269,6 +275,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -292,6 +299,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
@@ -353,6 +361,7 @@ select
|
|||||||
"id",
|
"id",
|
||||||
"name",
|
"name",
|
||||||
"email",
|
"email",
|
||||||
|
"avatarColor",
|
||||||
"profileImagePath",
|
"profileImagePath",
|
||||||
"profileChangedAt"
|
"profileChangedAt"
|
||||||
from
|
from
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user