Compare commits

..

1 Commits

Author SHA1 Message Date
Alex Tran
7277ea3d7a feat(server): asset_user table 2025-01-28 22:04:21 -06:00
398 changed files with 9612 additions and 12511 deletions

View File

@@ -1 +1,2 @@
blank_issues_enabled: false
blank_pull_request_template_enabled: false blank_pull_request_template_enabled: false

View File

@@ -0,0 +1,22 @@
## Description
<!--- Describe your changes in detail -->
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
Fixes # (issue)
## How Has This Been Tested?
<!-- Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration -->
- [ ] Test A
- [ ] Test B
## Screenshots (if appropriate):
## Checklist:
- [ ] I have performed a self-review of my own code
- [ ] I have made corresponding changes to the documentation if applicable

View File

@@ -1,36 +0,0 @@
## Description
<!--- Describe your changes in detail -->
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
Fixes # (issue)
## How Has This Been Tested?
<!-- Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration -->
- [ ] Test A
- [ ] Test B
<details><summary><h2>Screenshots (if appropriate)</h2></summary>
<!-- Images go below this line. -->
</details>
<!-- API endpoint changes (if relevant)
## API Changes
The `/api/something` endpoint is now `/api/something-else`
-->
## Checklist:
- [ ] I have performed a self-review of my own code
- [ ] I have made corresponding changes to the documentation if applicable
- [ ] I have no unrelated changes in the PR.
- [ ] I have confirmed that any new dependencies are strictly necessary.
- [ ] I have written tests for new code (if applicable)
- [ ] I have followed naming conventions/patterns in the surrounding code
- [ ] All code in `src/services` uses repositories implementations for database calls, filesystem operations, etc.
- [ ] All code in `src/repositories/` is pretty basic/simple and does not have any immich specific logic (that belongs in `src/services`)

View File

@@ -56,10 +56,10 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3.4.0 uses: docker/setup-qemu-action@v3.3.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.9.0 uses: docker/setup-buildx-action@v3.8.0
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
@@ -88,7 +88,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@v6.13.0 uses: docker/build-push-action@v6.12.0
with: with:
file: cli/Dockerfile file: cli/Dockerfile
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64

View File

@@ -87,6 +87,7 @@ jobs:
TAG_NEW=${{ github.event.number == 0 && github.ref_name || format('pr-{0}', github.event.number) }}${{ matrix.suffix }} TAG_NEW=${{ github.event.number == 0 && github.ref_name || format('pr-{0}', github.event.number) }}${{ matrix.suffix }}
docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_NEW $REGISTRY_NAME/$REPOSITORY:$TAG_OLD docker buildx imagetools create -t $REGISTRY_NAME/$REPOSITORY:$TAG_NEW $REGISTRY_NAME/$REPOSITORY:$TAG_OLD
build_and_push_ml: build_and_push_ml:
name: Build and Push ML name: Build and Push ML
needs: pre-job needs: pre-job
@@ -121,10 +122,10 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3.4.0 uses: docker/setup-qemu-action@v3.3.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.9.0 uses: docker/setup-buildx-action@v3.8.0
- name: Login to Docker Hub - name: Login to Docker Hub
# Only push to Docker Hub when making a release # Only push to Docker Hub when making a release
@@ -173,7 +174,7 @@ jobs:
fi fi
- name: Build and push image - name: Build and push image
uses: docker/build-push-action@v6.13.0 uses: docker/build-push-action@v6.12.0
with: with:
context: ${{ env.context }} context: ${{ env.context }}
file: ${{ env.file }} file: ${{ env.file }}
@@ -194,38 +195,33 @@ jobs:
build_and_push_server: build_and_push_server:
name: Build and Push Server name: Build and Push Server
runs-on: ${{ matrix.runner }} runs-on: ubuntu-latest
needs: pre-job needs: pre-job
if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} if: ${{ needs.pre-job.outputs.should_run_server == 'true' }}
env: env:
image: immich-server image: immich-server
context: . context: .
file: server/Dockerfile file: server/Dockerfile
GHCR_REPO: ghcr.io/${{ github.repository_owner }}/immich-server
DOCKER_REPO: altran1502/immich-server
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- platform: linux/amd64 - platforms: linux/amd64,linux/arm64
runner: ubuntu-latest device: cpu
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps: steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.3.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3.8.0
- name: Login to Docker Hub - name: Login to Docker Hub
# Only push to Docker Hub when making a release
if: ${{ github.event_name == 'release' }}
uses: docker/login-action@v3 uses: docker/login-action@v3
if: ${{ !github.event.pull_request.head.repo.fork }}
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -239,81 +235,16 @@ jobs:
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push image
id: build
uses: docker/build-push-action@v6.13.0
with:
context: ${{ env.context }}
file: ${{ env.file }}
platforms: ${{ matrix.platform }}
# Skip pushing when PR from a fork
push: ${{ !github.event.pull_request.head.repo.fork }}
labels: ${{ steps.metadata.outputs.labels }}
outputs: type=image,"name=${{ env.GHCR_REPO }},${{ env.DOCKER_REPO }}",push-by-digest=true,name-canonical=true,push=true
build-args: |
DEVICE=cpu
BUILD_ID=${{ github.run_id }}
BUILD_IMAGE=${{ github.event_name == 'release' && github.ref_name || steps.metadata.outputs.tags }}
BUILD_SOURCE_REF=${{ github.ref_name }}
BUILD_SOURCE_COMMIT=${{ github.sha }}
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
merge_server:
name: Merge & Push Server
runs-on: ubuntu-latest
if: ${{ needs.pre-job.outputs.should_run_server == 'true' && !github.event.pull_request.head.repo.fork }}
env:
GHCR_REPO: ghcr.io/${{ github.repository_owner }}/immich-server
DOCKER_REPO: altran1502/immich-server
needs:
- build_and_push_server
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Generate docker image tags - name: Generate docker image tags
id: meta id: metadata
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
flavor: | flavor: |
# Disable latest tag # Disable latest tag
latest=false latest=false
images: | images: |
name=${{ env.GHCR_REPO }} name=ghcr.io/${{ github.repository_owner }}/${{env.image}}
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }} name=altran1502/${{env.image}},enable=${{ github.event_name == 'release' }}
tags: | tags: |
# Tag with branch name # Tag with branch name
type=ref,event=branch,suffix=${{ matrix.suffix }} type=ref,event=branch,suffix=${{ matrix.suffix }}
@@ -323,16 +254,38 @@ jobs:
type=ref,event=tag,suffix=${{ matrix.suffix }} type=ref,event=tag,suffix=${{ matrix.suffix }}
type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }} type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
- name: Create manifest list and push - name: Determine build cache output
working-directory: ${{ runner.temp }}/digests id: cache-target
run: | run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ if [[ "${{ github.event_name }}" == "pull_request" ]]; then
$(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) \ # Essentially just ignore the cache output (PR can't write to registry cache)
$(printf '${{ env.DOCKER_REPO }}@sha256:%s ' *) echo "cache-to=type=local,dest=/tmp/discard,ignore-error=true" >> $GITHUB_OUTPUT
else
echo "cache-to=type=registry,mode=max,ref=ghcr.io/${{ github.repository_owner }}/immich-build-cache:${{ env.image }}" >> $GITHUB_OUTPUT
fi
- name: Build and push image
uses: docker/build-push-action@v6.12.0
with:
context: ${{ env.context }}
file: ${{ env.file }}
platforms: ${{ matrix.platforms }}
# Skip pushing when PR from a fork
push: ${{ !github.event.pull_request.head.repo.fork }}
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/immich-build-cache:${{env.image}}
cache-to: ${{ steps.cache-target.outputs.cache-to }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
build-args: |
DEVICE=${{ matrix.device }}
BUILD_ID=${{ github.run_id }}
BUILD_IMAGE=${{ github.event_name == 'release' && github.ref_name || steps.metadata.outputs.tags }}
BUILD_SOURCE_REF=${{ github.ref_name }}
BUILD_SOURCE_COMMIT=${{ github.sha }}
success-check-server: success-check-server:
name: Docker Build & Push Server Success name: Docker Build & Push Server Success
needs: [merge_server, retag_server] needs: [build_and_push_server, retag_server]
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: always() if: always()
steps: steps:

View File

@@ -1,17 +0,0 @@
name: Preview comment
on:
pull_request:
types: [labeled]
jobs:
comment-status:
runs-on: ubuntu-latest
if: ${{ github.event.label.name == 'preview' }}
permissions:
pull-requests: write
steps:
- uses: mshick/add-pr-comment@v2
with:
message-id: "preview-status"
message: "Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.cloud/"

268
cli/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.50", "version": "2.2.47",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.50", "version": "2.2.47",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
@@ -24,7 +24,7 @@
"@types/cli-progress": "^3.11.0", "@types/cli-progress": "^3.11.0",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/mock-fs": "^4.13.1", "@types/mock-fs": "^4.13.1",
"@types/node": "^22.13.1", "@types/node": "^22.10.9",
"@typescript-eslint/eslint-plugin": "^8.15.0", "@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0", "@typescript-eslint/parser": "^8.15.0",
"@vitest/coverage-v8": "^3.0.0", "@vitest/coverage-v8": "^3.0.0",
@@ -52,14 +52,14 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.126.1", "version": "1.125.6",
"dev": true, "dev": true,
"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"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.13.1", "@types/node": "^22.10.9",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }
}, },
@@ -881,9 +881,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.19.0", "version": "9.18.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
"integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -1482,9 +1482,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "22.13.1", "version": "22.10.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.9.tgz",
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", "integrity": "sha512-Ir6hwgsKyNESl/gLOcEz3krR4CBGgliDqBQ2ma4wIhEx0w+xnoeTq3tdrNw15kU3SxogDjOgv9sqdtLW8mIHaw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1498,21 +1498,21 @@
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz",
"integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==",
"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.23.0", "@typescript-eslint/scope-manager": "8.20.0",
"@typescript-eslint/type-utils": "8.23.0", "@typescript-eslint/type-utils": "8.20.0",
"@typescript-eslint/utils": "8.23.0", "@typescript-eslint/utils": "8.20.0",
"@typescript-eslint/visitor-keys": "8.23.0", "@typescript-eslint/visitor-keys": "8.20.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",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1528,16 +1528,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz",
"integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.23.0", "@typescript-eslint/scope-manager": "8.20.0",
"@typescript-eslint/types": "8.23.0", "@typescript-eslint/types": "8.20.0",
"@typescript-eslint/typescript-estree": "8.23.0", "@typescript-eslint/typescript-estree": "8.20.0",
"@typescript-eslint/visitor-keys": "8.23.0", "@typescript-eslint/visitor-keys": "8.20.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -1553,14 +1553,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz",
"integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.23.0", "@typescript-eslint/types": "8.20.0",
"@typescript-eslint/visitor-keys": "8.23.0" "@typescript-eslint/visitor-keys": "8.20.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1571,16 +1571,16 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz",
"integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.23.0", "@typescript-eslint/typescript-estree": "8.20.0",
"@typescript-eslint/utils": "8.23.0", "@typescript-eslint/utils": "8.20.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1595,9 +1595,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz",
"integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -1609,20 +1609,20 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz",
"integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.23.0", "@typescript-eslint/types": "8.20.0",
"@typescript-eslint/visitor-keys": "8.23.0", "@typescript-eslint/visitor-keys": "8.20.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",
"minimatch": "^9.0.4", "minimatch": "^9.0.4",
"semver": "^7.6.0", "semver": "^7.6.0",
"ts-api-utils": "^2.0.1" "ts-api-utils": "^2.0.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1636,16 +1636,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz",
"integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==",
"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.23.0", "@typescript-eslint/scope-manager": "8.20.0",
"@typescript-eslint/types": "8.23.0", "@typescript-eslint/types": "8.20.0",
"@typescript-eslint/typescript-estree": "8.23.0" "@typescript-eslint/typescript-estree": "8.20.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1660,13 +1660,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.23.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz",
"integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.23.0", "@typescript-eslint/types": "8.20.0",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@@ -1691,9 +1691,9 @@
} }
}, },
"node_modules/@vitest/coverage-v8": { "node_modules/@vitest/coverage-v8": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz",
"integrity": "sha512-zOOWIsj5fHh3jjGwQg+P+J1FW3s4jBu1Zqga0qW60yutsBtqEqNEJKWYh7cYn1yGD+1bdPsPdC/eL4eVK56xMg==", "integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1714,8 +1714,8 @@
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
}, },
"peerDependencies": { "peerDependencies": {
"@vitest/browser": "3.0.5", "@vitest/browser": "3.0.3",
"vitest": "3.0.5" "vitest": "3.0.3"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@vitest/browser": { "@vitest/browser": {
@@ -1724,14 +1724,14 @@
} }
}, },
"node_modules/@vitest/expect": { "node_modules/@vitest/expect": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz",
"integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.5", "@vitest/spy": "3.0.3",
"@vitest/utils": "3.0.5", "@vitest/utils": "3.0.3",
"chai": "^5.1.2", "chai": "^5.1.2",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@@ -1740,13 +1740,13 @@
} }
}, },
"node_modules/@vitest/mocker": { "node_modules/@vitest/mocker": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz",
"integrity": "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==", "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/spy": "3.0.5", "@vitest/spy": "3.0.3",
"estree-walker": "^3.0.3", "estree-walker": "^3.0.3",
"magic-string": "^0.30.17" "magic-string": "^0.30.17"
}, },
@@ -1767,9 +1767,9 @@
} }
}, },
"node_modules/@vitest/pretty-format": { "node_modules/@vitest/pretty-format": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz",
"integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1780,38 +1780,38 @@
} }
}, },
"node_modules/@vitest/runner": { "node_modules/@vitest/runner": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz",
"integrity": "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==", "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/utils": "3.0.5", "@vitest/utils": "3.0.3",
"pathe": "^2.0.2" "pathe": "^2.0.1"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
} }
}, },
"node_modules/@vitest/snapshot": { "node_modules/@vitest/snapshot": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz",
"integrity": "sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==", "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.5", "@vitest/pretty-format": "3.0.3",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",
"pathe": "^2.0.2" "pathe": "^2.0.1"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
} }
}, },
"node_modules/@vitest/spy": { "node_modules/@vitest/spy": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz",
"integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1822,13 +1822,13 @@
} }
}, },
"node_modules/@vitest/utils": { "node_modules/@vitest/utils": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz",
"integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/pretty-format": "3.0.5", "@vitest/pretty-format": "3.0.3",
"loupe": "^3.1.2", "loupe": "^3.1.2",
"tinyrainbow": "^2.0.0" "tinyrainbow": "^2.0.0"
}, },
@@ -2334,9 +2334,9 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.19.0", "version": "9.18.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
"integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2345,7 +2345,7 @@
"@eslint/config-array": "^0.19.0", "@eslint/config-array": "^0.19.0",
"@eslint/core": "^0.10.0", "@eslint/core": "^0.10.0",
"@eslint/eslintrc": "^3.2.0", "@eslint/eslintrc": "^3.2.0",
"@eslint/js": "9.19.0", "@eslint/js": "9.18.0",
"@eslint/plugin-kit": "^0.2.5", "@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
@@ -2407,9 +2407,9 @@
} }
}, },
"node_modules/eslint-plugin-prettier": { "node_modules/eslint-plugin-prettier": {
"version": "5.2.3", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.2.tgz",
"integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "integrity": "sha512-1yI3/hf35wmlq66C8yOyrujQnel+v5l1Vop5Cl2I6ylyNTT1JbuUUnV3/41PzwTzcyDp/oF0jWE3HXvcH5AQOQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2685,9 +2685,9 @@
"dev": true "dev": true
}, },
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.19.0", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
"integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"reusify": "^1.0.4" "reusify": "^1.0.4"
@@ -3180,9 +3180,9 @@
"dev": true "dev": true
}, },
"node_modules/loupe": { "node_modules/loupe": {
"version": "3.1.3", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
"integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@@ -3285,9 +3285,9 @@
} }
}, },
"node_modules/mock-fs": { "node_modules/mock-fs": {
"version": "5.5.0", "version": "5.4.1",
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz", "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.1.tgz",
"integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==", "integrity": "sha512-sz/Q8K1gXXXHR+qr0GZg2ysxCRr323kuN10O7CtQjraJsFDJ4SJ+0I5MzALz7aRp9lHk8Cc/YdsT95h9Ka1aFw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -4166,9 +4166,9 @@
} }
}, },
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "2.0.1", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz",
"integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -4288,15 +4288,15 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "6.1.0", "version": "6.0.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
"integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.24.2", "esbuild": "^0.24.2",
"postcss": "^8.5.1", "postcss": "^8.4.49",
"rollup": "^4.30.1" "rollup": "^4.23.0"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
@@ -4360,16 +4360,16 @@
} }
}, },
"node_modules/vite-node": { "node_modules/vite-node": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.5.tgz", "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz",
"integrity": "sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==", "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cac": "^6.7.14", "cac": "^6.7.14",
"debug": "^4.4.0", "debug": "^4.4.0",
"es-module-lexer": "^1.6.0", "es-module-lexer": "^1.6.0",
"pathe": "^2.0.2", "pathe": "^2.0.1",
"vite": "^5.0.0 || ^6.0.0" "vite": "^5.0.0 || ^6.0.0"
}, },
"bin": { "bin": {
@@ -4403,31 +4403,31 @@
} }
}, },
"node_modules/vitest": { "node_modules/vitest": {
"version": "3.0.5", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.5.tgz", "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz",
"integrity": "sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==", "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vitest/expect": "3.0.5", "@vitest/expect": "3.0.3",
"@vitest/mocker": "3.0.5", "@vitest/mocker": "3.0.3",
"@vitest/pretty-format": "^3.0.5", "@vitest/pretty-format": "^3.0.3",
"@vitest/runner": "3.0.5", "@vitest/runner": "3.0.3",
"@vitest/snapshot": "3.0.5", "@vitest/snapshot": "3.0.3",
"@vitest/spy": "3.0.5", "@vitest/spy": "3.0.3",
"@vitest/utils": "3.0.5", "@vitest/utils": "3.0.3",
"chai": "^5.1.2", "chai": "^5.1.2",
"debug": "^4.4.0", "debug": "^4.4.0",
"expect-type": "^1.1.0", "expect-type": "^1.1.0",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",
"pathe": "^2.0.2", "pathe": "^2.0.1",
"std-env": "^3.8.0", "std-env": "^3.8.0",
"tinybench": "^2.9.0", "tinybench": "^2.9.0",
"tinyexec": "^0.3.2", "tinyexec": "^0.3.2",
"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.0.5", "vite-node": "3.0.3",
"why-is-node-running": "^2.3.0" "why-is-node-running": "^2.3.0"
}, },
"bin": { "bin": {
@@ -4441,10 +4441,9 @@
}, },
"peerDependencies": { "peerDependencies": {
"@edge-runtime/vm": "*", "@edge-runtime/vm": "*",
"@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.0.5", "@vitest/browser": "3.0.3",
"@vitest/ui": "3.0.5", "@vitest/ui": "3.0.3",
"happy-dom": "*", "happy-dom": "*",
"jsdom": "*" "jsdom": "*"
}, },
@@ -4452,9 +4451,6 @@
"@edge-runtime/vm": { "@edge-runtime/vm": {
"optional": true "optional": true
}, },
"@types/debug": {
"optional": true
},
"@types/node": { "@types/node": {
"optional": true "optional": true
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.50", "version": "2.2.47",
"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",
@@ -20,7 +20,7 @@
"@types/cli-progress": "^3.11.0", "@types/cli-progress": "^3.11.0",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/mock-fs": "^4.13.1", "@types/mock-fs": "^4.13.1",
"@types/node": "^22.13.1", "@types/node": "^22.10.9",
"@typescript-eslint/eslint-plugin": "^8.15.0", "@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0", "@typescript-eslint/parser": "^8.15.0",
"@vitest/coverage-v8": "^3.0.0", "@vitest/coverage-v8": "^3.0.0",

View File

@@ -2,37 +2,37 @@
# Manual edits may be lost in future updates. # Manual edits may be lost in future updates.
provider "registry.opentofu.org/cloudflare/cloudflare" { provider "registry.opentofu.org/cloudflare/cloudflare" {
version = "4.52.0" version = "4.50.0"
constraints = "4.52.0" constraints = "4.50.0"
hashes = [ hashes = [
"h1:2BEJyXJtYC4B4nda/WCYUmuJYDaYk88F8t1pwPzr0iQ=", "h1:0qvD5ZKn2tMZ8cOjQrUSITIC9tKCZbrSaSswV9lOyiU=",
"h1:4IASk5SESeWKQ7JU0+M7KApuF5mZyklvwMXPBabim3c=", "h1:4N0gplrZ0zOsJv3Kx1VfIx2FwrZHbYU0Un2yfiLZIGQ=",
"h1:5ImZxxALSnWfH/4EXw/wFirSmk5Tr0ACmcysy51AafE=", "h1:81AMQq4kNKU/35U8ElQegUxG4E6xB0erIjG5xVmjIyo=",
"h1:6TJ3dxLSin4ZKBJLsZDn95H2ZYnGm8S7GGHvvXuuMQU=", "h1:EEQNADUmV3IL6x00yzy04i7OCSLeOMgM9XQkV3w71gA=",
"h1:IzTUjg9kQ4N3qizP9CjYLeHwjsuGgtxwXvfUQWyOLcA=", "h1:HD0KI7td6oiSSAnJNn8UPSGf+hKiTo4JVQYfAiU1SqM=",
"h1:NTaOQfYINA0YTG/V1/9+SYtgX1it63+cBugj4WK4FWc=", "h1:Hl+o5LtcvZg2f3l1hh9vaG/DFK6k+dTIZSeM0lXyfpo=",
"h1:PXH48LuJn329sCfMXprdMDk51EZaWFyajVvS03qhQLs=", "h1:ZUO2oIJ6jtZdvl816h0cEIiIeZ/fFCF64+abGEVxZZM=",
"h1:Pi5M+GeoMSN2eJ6QnIeXjBf19O+rby/74CfB2ocpv20=", "h1:Zio80fnEeUKdlSOhTVskMEFSLUQ6TMsMKnXc+Dy2P2A=",
"h1:ShXZ2ZjBvm3thfoPPzPT8+OhyismnydQVkUAfI8X12w=", "h1:aLLvg36evTyqjtXGV2MjAV8imktXFmry7p/xCu9GQC4=",
"h1:WQ9hu0Wge2msBbODfottCSKgu8oKUrw4Opz+fDPVVHk=", "h1:azL05eWyy2V8SWkbZZImPWvv8ynG4eqmrbZhjXBDFug=",
"h1:Z5yXML2DE0uH9UU+M0ut9JMQAORcwVZz1CxBHzeBmao=", "h1:ckMysHY4fJmr7o58XMi+DdgOTB/U/Mf1u1JA9ly3g/I=",
"h1:jqI2qKknpleS3JDSplyGYHMu0u9K/tor1ZOjFwDgEMk=", "h1:jxOwjDNjt5WCb4YjjiMsman91O8Y+MAPz6UwJ4a6F+0=",
"h1:kgfutDh14Q5nw4eg6qGFamFxIiY8Ae0FPKRBLDOzpcI=", "h1:u4OfnjSLa4Wk1IUFAzrvMnGgr8MvRHEWVDHEScPK2E8=",
"h1:zCAO7GZmfYhWb+i6TfqlqhMeDyPZWGio2IzEzAh3YTs=", "h1:wQkR1oeSkzlHn3rnVuLJRJLBHlg4EHt7Y64DeTjfkjQ=",
"zh:19be1a91c982b902c42aba47766860dfa5dc151eed1e95fd39ca642229381ef0", "zh:0ef99ed39472a94e6a0d6fa733cf0a46bce3bf66eba2873efae8846efdddc237",
"zh:1de451c4d1ecf7efbe67b6dace3426ba810711afdd644b0f1b870364c8ae91f8", "zh:2929cbbffcead171d45c88e4a7a59e9c013ea775dafa68b10da8db7cd04b6140",
"zh:352b4a2120173298622e669258744554339d959ac3a95607b117a48ee4a83238", "zh:462601c87118088e1a718842e367af7d8e7620598d426980a6d6b33de759865e",
"zh:3c6f1346d9154afbd2d558fabb4b0150fc8d559aa961254144fe1bc17fe6032f", "zh:56766eb62a74a9d88d9efb8486dd3a0c5c9db873d0a980ae9ef1e8af27d74231",
"zh:4c4c92d53fb535b1e0eff26f222bbd627b97d3b4c891ec9c321268676d06152f", "zh:6b4e8810d99498a5a20a5872982a0f1354e79cfc4a7dfe7cc656f1c7eaae47d8",
"zh:53276f68006c9ceb7cdb10a6ccf91a5c1eadd1407a28edb5741e84e88d7e29e8", "zh:6d65bdb4ec94b6eecc8abe26d94e2ca09262dc1e7a9934db829f418be0119920",
"zh:7925a97773948171a63d4f65bb81ee92fd6d07a447e36012977313293a5435c9", "zh:71adeaf31e41a358ec6095004062e43f56ee7d4b2504e5613ab351d511695641",
"zh:7dfb0a4496cfe032437386d0a2cd9229a1956e9c30bd920923c141b0f0440060",
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
"zh:8d4aa79f0a414bb4163d771063c70cd991c8fac6c766e685bac2ee12903c5bd6", "zh:89761c15908ccc2cf9c50bb5cb3be45d3ad0c45fc7c608c6b95f48c0288b7160",
"zh:a67540c13565616a7e7e51ee9366e88b0dc60046e1d75c72680e150bd02725bb", "zh:8cc5d7c5939da89cfd01f3e51c84f3576564783acea9db86bd9e32049805ed96",
"zh:a936383a4767f5393f38f622e92bf2d0c03fe04b69c284951f27345766c7b31b", "zh:987cff8225b1dd436cdcb4fc6228689ae7e4281de6896412a2a9a3325c49f05e",
"zh:d4887d73c466ff036eecf50ad6404ba38fd82ea4855296b1846d244b0f13c380", "zh:991e83ebb89867d71e01a1c215ed159efb425683b0a44707be8579eb0a337f06",
"zh:e9093c8bd5b6cd99c81666e315197791781b8f93afa14fc2e0f732d1bb2a44b7", "zh:ab8177ae2d8f5cfa90043a6f867435012cae115f6061b832a7e2462e0ae87a67",
"zh:efd3b3f1ec59a37f635aa1d4efcf178734c2fcf8ddb0d56ea690bec342da8672", "zh:d1ca34df1398f201274a6a18102975148c10ca15aa43cfc56cc9897620929509",
"zh:d34946f70201baf6dda03e3b294c6bbe40d95d0278e97b9f636ded94822b24ac",
] ]
} }

View File

@@ -5,7 +5,7 @@ terraform {
required_providers { required_providers {
cloudflare = { cloudflare = {
source = "cloudflare/cloudflare" source = "cloudflare/cloudflare"
version = "4.52.0" version = "4.50.0"
} }
} }
} }

View File

@@ -2,37 +2,37 @@
# Manual edits may be lost in future updates. # Manual edits may be lost in future updates.
provider "registry.opentofu.org/cloudflare/cloudflare" { provider "registry.opentofu.org/cloudflare/cloudflare" {
version = "4.52.0" version = "4.50.0"
constraints = "4.52.0" constraints = "4.50.0"
hashes = [ hashes = [
"h1:2BEJyXJtYC4B4nda/WCYUmuJYDaYk88F8t1pwPzr0iQ=", "h1:0qvD5ZKn2tMZ8cOjQrUSITIC9tKCZbrSaSswV9lOyiU=",
"h1:4IASk5SESeWKQ7JU0+M7KApuF5mZyklvwMXPBabim3c=", "h1:4N0gplrZ0zOsJv3Kx1VfIx2FwrZHbYU0Un2yfiLZIGQ=",
"h1:5ImZxxALSnWfH/4EXw/wFirSmk5Tr0ACmcysy51AafE=", "h1:81AMQq4kNKU/35U8ElQegUxG4E6xB0erIjG5xVmjIyo=",
"h1:6TJ3dxLSin4ZKBJLsZDn95H2ZYnGm8S7GGHvvXuuMQU=", "h1:EEQNADUmV3IL6x00yzy04i7OCSLeOMgM9XQkV3w71gA=",
"h1:IzTUjg9kQ4N3qizP9CjYLeHwjsuGgtxwXvfUQWyOLcA=", "h1:HD0KI7td6oiSSAnJNn8UPSGf+hKiTo4JVQYfAiU1SqM=",
"h1:NTaOQfYINA0YTG/V1/9+SYtgX1it63+cBugj4WK4FWc=", "h1:Hl+o5LtcvZg2f3l1hh9vaG/DFK6k+dTIZSeM0lXyfpo=",
"h1:PXH48LuJn329sCfMXprdMDk51EZaWFyajVvS03qhQLs=", "h1:ZUO2oIJ6jtZdvl816h0cEIiIeZ/fFCF64+abGEVxZZM=",
"h1:Pi5M+GeoMSN2eJ6QnIeXjBf19O+rby/74CfB2ocpv20=", "h1:Zio80fnEeUKdlSOhTVskMEFSLUQ6TMsMKnXc+Dy2P2A=",
"h1:ShXZ2ZjBvm3thfoPPzPT8+OhyismnydQVkUAfI8X12w=", "h1:aLLvg36evTyqjtXGV2MjAV8imktXFmry7p/xCu9GQC4=",
"h1:WQ9hu0Wge2msBbODfottCSKgu8oKUrw4Opz+fDPVVHk=", "h1:azL05eWyy2V8SWkbZZImPWvv8ynG4eqmrbZhjXBDFug=",
"h1:Z5yXML2DE0uH9UU+M0ut9JMQAORcwVZz1CxBHzeBmao=", "h1:ckMysHY4fJmr7o58XMi+DdgOTB/U/Mf1u1JA9ly3g/I=",
"h1:jqI2qKknpleS3JDSplyGYHMu0u9K/tor1ZOjFwDgEMk=", "h1:jxOwjDNjt5WCb4YjjiMsman91O8Y+MAPz6UwJ4a6F+0=",
"h1:kgfutDh14Q5nw4eg6qGFamFxIiY8Ae0FPKRBLDOzpcI=", "h1:u4OfnjSLa4Wk1IUFAzrvMnGgr8MvRHEWVDHEScPK2E8=",
"h1:zCAO7GZmfYhWb+i6TfqlqhMeDyPZWGio2IzEzAh3YTs=", "h1:wQkR1oeSkzlHn3rnVuLJRJLBHlg4EHt7Y64DeTjfkjQ=",
"zh:19be1a91c982b902c42aba47766860dfa5dc151eed1e95fd39ca642229381ef0", "zh:0ef99ed39472a94e6a0d6fa733cf0a46bce3bf66eba2873efae8846efdddc237",
"zh:1de451c4d1ecf7efbe67b6dace3426ba810711afdd644b0f1b870364c8ae91f8", "zh:2929cbbffcead171d45c88e4a7a59e9c013ea775dafa68b10da8db7cd04b6140",
"zh:352b4a2120173298622e669258744554339d959ac3a95607b117a48ee4a83238", "zh:462601c87118088e1a718842e367af7d8e7620598d426980a6d6b33de759865e",
"zh:3c6f1346d9154afbd2d558fabb4b0150fc8d559aa961254144fe1bc17fe6032f", "zh:56766eb62a74a9d88d9efb8486dd3a0c5c9db873d0a980ae9ef1e8af27d74231",
"zh:4c4c92d53fb535b1e0eff26f222bbd627b97d3b4c891ec9c321268676d06152f", "zh:6b4e8810d99498a5a20a5872982a0f1354e79cfc4a7dfe7cc656f1c7eaae47d8",
"zh:53276f68006c9ceb7cdb10a6ccf91a5c1eadd1407a28edb5741e84e88d7e29e8", "zh:6d65bdb4ec94b6eecc8abe26d94e2ca09262dc1e7a9934db829f418be0119920",
"zh:7925a97773948171a63d4f65bb81ee92fd6d07a447e36012977313293a5435c9", "zh:71adeaf31e41a358ec6095004062e43f56ee7d4b2504e5613ab351d511695641",
"zh:7dfb0a4496cfe032437386d0a2cd9229a1956e9c30bd920923c141b0f0440060",
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
"zh:8d4aa79f0a414bb4163d771063c70cd991c8fac6c766e685bac2ee12903c5bd6", "zh:89761c15908ccc2cf9c50bb5cb3be45d3ad0c45fc7c608c6b95f48c0288b7160",
"zh:a67540c13565616a7e7e51ee9366e88b0dc60046e1d75c72680e150bd02725bb", "zh:8cc5d7c5939da89cfd01f3e51c84f3576564783acea9db86bd9e32049805ed96",
"zh:a936383a4767f5393f38f622e92bf2d0c03fe04b69c284951f27345766c7b31b", "zh:987cff8225b1dd436cdcb4fc6228689ae7e4281de6896412a2a9a3325c49f05e",
"zh:d4887d73c466ff036eecf50ad6404ba38fd82ea4855296b1846d244b0f13c380", "zh:991e83ebb89867d71e01a1c215ed159efb425683b0a44707be8579eb0a337f06",
"zh:e9093c8bd5b6cd99c81666e315197791781b8f93afa14fc2e0f732d1bb2a44b7", "zh:ab8177ae2d8f5cfa90043a6f867435012cae115f6061b832a7e2462e0ae87a67",
"zh:efd3b3f1ec59a37f635aa1d4efcf178734c2fcf8ddb0d56ea690bec342da8672", "zh:d1ca34df1398f201274a6a18102975148c10ca15aa43cfc56cc9897620929509",
"zh:d34946f70201baf6dda03e3b294c6bbe40d95d0278e97b9f636ded94822b24ac",
] ]
} }

View File

@@ -5,7 +5,7 @@ terraform {
required_providers { required_providers {
cloudflare = { cloudflare = {
source = "cloudflare/cloudflare" source = "cloudflare/cloudflare"
version = "4.52.0" version = "4.50.0"
} }
} }
} }

View File

@@ -103,7 +103,7 @@ services:
command: ['./run.sh', '-disable-reporting'] command: ['./run.sh', '-disable-reporting']
ports: ports:
- 3000:3000 - 3000:3000
image: grafana/grafana:11.5.1-ubuntu@sha256:9a4ab78cec1a2ec7d1ca5dfd5aacec6412706a1bc9e971fc7184e2f6696a63f5 image: grafana/grafana:11.4.0-ubuntu@sha256:afccec22ba0e4815cca1d2bf3836e414322390dc78d77f1851976ffa8d61051c
volumes: volumes:
- grafana-data:/var/lib/grafana - grafana-data:/var/lib/grafana

View File

@@ -48,7 +48,6 @@ services:
vaapi-wsl: # use this for VAAPI if you're running Immich in WSL2 vaapi-wsl: # use this for VAAPI if you're running Immich in WSL2
devices: devices:
- /dev/dri:/dev/dri - /dev/dri:/dev/dri
- /dev/dxg:/dev/dxg
volumes: volumes:
- /usr/lib/wsl:/usr/lib/wsl - /usr/lib/wsl:/usr/lib/wsl
environment: environment:

View File

@@ -77,7 +77,9 @@ docker start immich_postgres # Start Postgres server
sleep 10 # Wait for Postgres server to start up sleep 10 # Wait for Postgres server to start up
docker exec -it immich_postgres bash # Enter the Docker shell and run the following command docker exec -it immich_postgres bash # Enter the Docker shell and run the following command
# Check the database user if you deviated from the default. If your backup ends in `.gz`, replace `cat` with `gunzip` # Check the database user if you deviated from the default. If your backup ends in `.gz`, replace `cat` with `gunzip`
cat < "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=postgres --username=<DB_USERNAME> cat < "/dump.sql" \
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
| psql --dbname=postgres --username=<DB_USERNAME> # Restore Backup
exit # Exit the Docker shell exit # Exit the Docker shell
docker compose up -d # Start remainder of Immich apps docker compose up -d # Start remainder of Immich apps
``` ```

View File

@@ -50,18 +50,19 @@ The Immich CLI is an [npm](https://www.npmjs.com/) package that lets users contr
The Immich backend is divided into several services, which are run as individual docker containers. The Immich backend is divided into several services, which are run as individual docker containers.
1. `immich-server` - Handle and respond to REST API requests, execute background jobs (thumbnail generation, metadata extraction, transcoding, etc.) 1. `immich-server` - Handle and respond to REST API requests
1. `immich-microservices` - Execute background jobs (thumbnail generation, metadata extraction, transcoding, etc.)
1. `immich-machine-learning` - Execute machine learning models 1. `immich-machine-learning` - Execute machine learning models
1. `postgres` - Persistent data storage 1. `postgres` - Persistent data storage
1. `redis`- Queue management for background jobs 1. `redis`- Queue management for `immich-microservices`
### Immich Server ### Immich Server
The Immich Server is a [TypeScript](https://www.typescriptlang.org/) project written for [Node.js](https://nodejs.org/). It uses the [Nest.js](https://nestjs.com) framework, [Express](https://expressjs.com/) server, and the query builder [Kysely](https://kysely.dev/). The server codebase also loosely follows the [Hexagonal Architecture](<https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)>). Specifically, we aim to separate technology specific implementations (`src/repositories`) from core business logic (`src/services`). The Immich Server is a [TypeScript](https://www.typescriptlang.org/) project written for [Node.js](https://nodejs.org/). It uses the [Nest.js](https://nestjs.com) framework, with [TypeORM](https://typeorm.io/) for database management. The server codebase also loosely follows the [Hexagonal Architecture](<https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)>). Specifically, we aim to separate technology specific implementations (`infra/`) from core business logic (`domain/`).
### API Endpoints #### REST Endpoints
An incoming HTTP request is mapped to a controller (`src/controllers`). Controllers are collections of HTTP endpoints. Each controller usually implements the following CRUD operations for its respective resource type: The server is a list of HTTP endpoints and associated handlers (controllers). Each controller usually implements the following CRUD operations:
- `POST` `/<type>` - **Create** - `POST` `/<type>` - **Create**
- `GET` `/<type>` - **Read** (all) - `GET` `/<type>` - **Read** (all)
@@ -69,13 +70,13 @@ An incoming HTTP request is mapped to a controller (`src/controllers`). Controll
- `PUT` `/<type>/:id` - **Updated** (by id) - `PUT` `/<type>/:id` - **Updated** (by id)
- `DELETE` `/<type>/:id` - **Delete** (by id) - `DELETE` `/<type>/:id` - **Delete** (by id)
### Domain Transfer Objects (DTOs) #### DTOs
The server uses [Domain Transfer Objects](https://en.wikipedia.org/wiki/Data_transfer_object) as public interfaces for the inputs (query, params, and body) and outputs (response) for each endpoint. DTOs translate to [OpenAPI](./open-api.md) schemas and control the generated code used by each client. The server uses [Domain Transfer Objects](https://en.wikipedia.org/wiki/Data_transfer_object) as public interfaces for the inputs (query, params, and body) and outputs (response) for each endpoint. DTOs translate to [OpenAPI](./open-api.md) schemas and control the generated code used by each client.
### Background Jobs ### Microservices
Immich uses a [worker](https://github.com/immich-app/immich/blob/main/server/src/utils/misc.ts#L266) to run background jobs. These jobs include: The Immich Microservices image uses the same `Dockerfile` as the Immich Server, but with a different entrypoint. The Immich Microservices service mainly handles executing jobs, which include the following:
- Thumbnail Generation - Thumbnail Generation
- Metadata Extraction - Metadata Extraction

View File

@@ -76,7 +76,7 @@ To see local changes to `@immich/ui` in Immich, do the following:
### Mobile app ### Mobile app
The mobile app `(/mobile)` will required Flutter toolchain 3.13.x and FVM to be installed on your system. The mobile app `(/mobile)` will required Flutter toolchain 3.13.x to be installed on your system.
Please refer to the [Flutter's official documentation](https://flutter.dev/docs/get-started/install) for more information on setting up the toolchain on your machine. Please refer to the [Flutter's official documentation](https://flutter.dev/docs/get-started/install) for more information on setting up the toolchain on your machine.

View File

@@ -58,7 +58,7 @@ If your photos are on a network drive, automatic file watching likely won't work
#### Troubleshooting #### Troubleshooting
If you encounter an `ENOSPC` error, you need to increase your file watcher limit. In sysctl, this key is called `fs.inotify.max_user_watches` and has a default value of 8192. Increase this number to a suitable value greater than the number of files you will be watching. Note that Immich has to watch all files in your import paths including any ignored files. If you encounter an `ENOSPC` error, you need to increase your file watcher limit. In sysctl, this key is called `fs.inotify.max_user_watched` and has a default value of 8192. Increase this number to a suitable value greater than the number of files you will be watching. Note that Immich has to watch all files in your import paths including any ignored files.
``` ```
ERROR [LibraryService] Library watcher for library c69faf55-f96d-4aa0-b83b-2d80cbc27d98 encountered error: Error: ENOSPC: System limit for number of file watchers reached, watch '/media/photo.jpg' ERROR [LibraryService] Library watcher for library c69faf55-f96d-4aa0-b83b-2d80cbc27d98 encountered error: Error: ENOSPC: System limit for number of file watchers reached, watch '/media/photo.jpg'

View File

@@ -11,7 +11,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele
- ARM NN (Mali) - ARM NN (Mali)
- CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher) - CUDA (NVIDIA GPUs with [compute capability](https://developer.nvidia.com/cuda-gpus) 5.2 or higher)
- OpenVINO (Intel GPUs such as Iris Xe and Arc) - OpenVINO (Intel discrete GPUs such as Iris Xe and Arc)
## Limitations ## Limitations
@@ -43,9 +43,8 @@ You do not need to redo any machine learning jobs after enabling hardware accele
#### OpenVINO #### OpenVINO
- Integrated GPUs are more likely to experience issues than discrete GPUs, especially for older processors or servers with low RAM. - The server must have a discrete GPU, i.e. Iris Xe or Arc. Expect issues when attempting to use integrated graphics.
- Ensure the server's kernel version is new enough to use the device for hardware accceleration. - Ensure the server's kernel version is new enough to use the device for hardware accceleration.
- Expect higher RAM usage when using OpenVINO compared to CPU processing.
## Setup ## Setup

View File

@@ -9,13 +9,12 @@ For the full list, refer to the [Immich source code](https://github.com/immich-a
## Image formats ## Image formats
| Format | Extension(s) | Supported? | Notes | | Format | Extension(s) | Supported? | Notes |
| :---------- | :---------------------------- | :----------------: | :-------------- | | :-------- | :---------------------------- | :----------------: | :-------------- |
| `AVIF` | `.avif` | :white_check_mark: | | | `AVIF` | `.avif` | :white_check_mark: | |
| `BMP` | `.bmp` | :white_check_mark: | | | `BMP` | `.bmp` | :white_check_mark: | |
| `GIF` | `.gif` | :white_check_mark: | | | `GIF` | `.gif` | :white_check_mark: | |
| `HEIC` | `.heic` | :white_check_mark: | | | `HEIC` | `.heic` | :white_check_mark: | |
| `HEIF` | `.heif` | :white_check_mark: | | | `HEIF` | `.heif` | :white_check_mark: | |
| `JPEG 2000` | `.jp2` | :white_check_mark: | |
| `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | | | `JPEG` | `.webp` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
| `JPEG XL` | `.jxl` | :white_check_mark: | | | `JPEG XL` | `.jxl` | :white_check_mark: | |
| `PNG` | `.webp` | :white_check_mark: | | | `PNG` | `.webp` | :white_check_mark: | |

View File

@@ -27,10 +27,6 @@ SELECT * FROM "assets" WHERE "originalPath" = 'upload/library/admin/2023/2023-09
SELECT * FROM "assets" WHERE "originalPath" LIKE 'upload/library/admin/2023/%'; SELECT * FROM "assets" WHERE "originalPath" LIKE 'upload/library/admin/2023/%';
``` ```
```sql title="Find by ID"
SELECT * FROM "assets" WHERE "id" = '9f94e60f-65b6-47b7-ae44-a4df7b57f0e9';
```
:::note :::note
You can calculate the checksum for a particular file by using the command `sha1sum <filename>`. You can calculate the checksum for a particular file by using the command `sha1sum <filename>`.
::: :::

View File

@@ -41,7 +41,7 @@ className="border rounded-xl"
:::info Permissions :::info Permissions
The **pgData** dataset must be owned by the user `netdata` (UID 999) for postgres to start. The other datasets must be owned by the user `root` (UID 0) or a group that includes the user `root` (UID 0) for immich to have the necessary permissions. The **pgData** dataset must be owned by the user `netdata` (UID 999) for postgres to start. The other datasets must be owned by the user `root` (UID 0) or a group that includes the user `root` (UID 0) for immich to have the necessary permissions.
If the **library** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/core/coretutorials/storage/pools/permissions/#access-control-lists) set to `Passthrough` if you plan on using a [storage template](/docs/administration/storage-template.mdx) and the dataset is configured for network sharing (its ACL type is set to `SMB/NFSv4`). When the template is applied and files need to be moved from **upload** to **library**, Immich performs `chmod` internally and needs to be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017) If the **library** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/core/coretutorials/storage/pools/permissions/#access-control-lists) set to `Passthrough` if you plan on using a [storage template](/docs/administration/storage-template.mdx) and the dataset is configured for network sharing (its ACL type is set to `SMB/NFSv4`). When the template is applied and files need to be moved from **upload** to **library**, immich performs `chmod` internally and needs to be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017)
::: :::
## Installing the Immich Application ## Installing the Immich Application
@@ -160,10 +160,6 @@ The image above has example values.
### Additional Storage [(External Libraries)](/docs/features/libraries) ### Additional Storage [(External Libraries)](/docs/features/libraries)
:::danger Advanced Users Only
This feature should only be used by advanced users. If this is your first time installing Immich, then DO NOT mount an external library until you have a working setup. Also, your mount path MUST be something unique and should NOT be your library or upload location or a Linux directory like `/lib`. The picture below shows a valid example.
:::
<img <img
src={require('./img/truenas10.webp').default} src={require('./img/truenas10.webp').default}
width="40%" width="40%"
@@ -172,7 +168,7 @@ className="border rounded-xl"
/> />
You may configure [External Libraries](/docs/features/libraries) by mounting them using **Additional Storage**. You may configure [External Libraries](/docs/features/libraries) by mounting them using **Additional Storage**.
The **Mount Path** is the location you will need to copy and paste into the External Library settings within Immich. The **Mount Path** is the loaction you will need to copy and paste into the External Library settings within Immich.
The **Host Path** is the location on the TrueNAS SCALE server where your external library is located. The **Host Path** is the location on the TrueNAS SCALE server where your external library is located.
<!-- A section for Labels would go here but I don't know what they do. --> <!-- A section for Labels would go here but I don't know what they do. -->

View File

@@ -72,7 +72,7 @@ alt="Select Plugins > Compose.Manager > Add New Stack > Label it Immich"
</ul> </ul>
</details> </details>
5. Click "**Save Changes**", you will be prompted to edit stack UI labels, just leave this blank and click "**Ok**" 5. Click "**Save Changes**", you will be promoted to edit stack UI labels, just leave this blank and click "**Ok**"
6. Select the cog ⚙️ next to Immich, click "**Edit Stack**", then click "**Env File**" 6. Select the cog ⚙️ next to Immich, click "**Edit Stack**", then click "**Env File**"
7. Paste the entire contents of the [Immich example.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file into the Unraid editor, then **before saving** edit the following: 7. Paste the entire contents of the [Immich example.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file into the Unraid editor, then **before saving** edit the following:

View File

@@ -110,9 +110,9 @@ const config = {
label: 'API', label: 'API',
}, },
{ {
href: 'https://immich.store', to: '/blog',
position: 'right', position: 'right',
label: 'Merch', label: 'Blog',
}, },
{ {
href: 'https://github.com/immich-app/immich', href: 'https://github.com/immich-app/immich',

View File

@@ -44,12 +44,12 @@ export default function VersionSwitcher(): JSX.Element {
return ( return (
versions.length > 0 && ( versions.length > 0 && (
<DropdownNavbarItem <DropdownNavbarItem
className="version-switcher-34ab39" className="navbar__item"
label={label} label={label}
mobile={windowSize === 'mobile'} mobile={windowSize === 'mobile'}
items={versions.map(({ label, url }) => ({ items={versions.map(({ label, url }) => ({
label, label,
to: url + location.pathname + location.hash, to: url,
target: '_self', target: '_self',
}))} }))}
/> />

View File

@@ -75,11 +75,6 @@ div[class^='announcementBar_'] {
font-weight: 500; font-weight: 500;
} }
/* workaround for version switcher PR 15894 */
div[class*='navbar__items'] > li:has(a[class*='version-switcher-34ab39']) {
display: none;
}
code { code {
font-weight: 600; font-weight: 600;
} }

View File

@@ -50,13 +50,6 @@ function HomepageHeader() {
> >
Demo Demo
</Link> </Link>
<Link
className="flex place-items-center place-content-center py-3 px-8 border bg-immich-primary/10 dark:bg-gray-300 rounded-xl hover:no-underline text-immich-primary dark:text-immich-dark-bg font-bold uppercase"
to="https://immich.store"
>
Buy Merch
</Link>
</div> </div>
<div className="my-12 flex gap-1 font-medium place-items-center place-content-center text-immich-primary dark:text-immich-dark-primary"> <div className="my-12 flex gap-1 font-medium place-items-center place-content-center text-immich-primary dark:text-immich-dark-primary">

View File

@@ -1,16 +1,4 @@
[ [
{
"label": "v1.126.1",
"url": "https://v1.126.1.archive.immich.app"
},
{
"label": "v1.126.0",
"url": "https://v1.126.0.archive.immich.app"
},
{
"label": "v1.125.7",
"url": "https://v1.125.7.archive.immich.app"
},
{ {
"label": "v1.125.6", "label": "v1.125.6",
"url": "https://v1.125.6.archive.immich.app" "url": "https://v1.125.6.archive.immich.app"

810
e2e/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.126.1", "version": "1.125.6",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
@@ -25,7 +25,7 @@
"@immich/sdk": "file:../open-api/typescript-sdk", "@immich/sdk": "file:../open-api/typescript-sdk",
"@playwright/test": "^1.44.1", "@playwright/test": "^1.44.1",
"@types/luxon": "^3.4.2", "@types/luxon": "^3.4.2",
"@types/node": "^22.13.1", "@types/node": "^22.10.9",
"@types/oidc-provider": "^8.5.1", "@types/oidc-provider": "^8.5.1",
"@types/pg": "^8.11.0", "@types/pg": "^8.11.0",
"@types/pngjs": "^6.0.4", "@types/pngjs": "^6.0.4",

View File

@@ -1,86 +0,0 @@
import { JobCommand, JobName, LoginResponseDto } from '@immich/sdk';
import { readFile } from 'node:fs/promises';
import { basename } from 'node:path';
import { errorDto } from 'src/responses';
import { app, testAssetDir, utils } from 'src/utils';
import request from 'supertest';
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
describe('/jobs', () => {
let admin: LoginResponseDto;
beforeAll(async () => {
await utils.resetDatabase();
admin = await utils.adminSetup({ onboarding: false });
});
describe('PUT /jobs', () => {
afterEach(async () => {
await utils.jobCommand(admin.accessToken, JobName.MetadataExtraction, {
command: JobCommand.Resume,
force: false,
});
});
it('should require authentication', async () => {
const { status, body } = await request(app).put('/jobs/metadataExtraction');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should queue metadata extraction for missing assets', async () => {
const path1 = `${testAssetDir}/formats/raw/Nikon/D700/philadelphia.nef`;
const path2 = `${testAssetDir}/formats/raw/Nikon/D80/glarus.nef`;
await utils.createAsset(admin.accessToken, {
assetData: { bytes: await readFile(path1), filename: basename(path1) },
});
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
await utils.jobCommand(admin.accessToken, JobName.MetadataExtraction, {
command: JobCommand.Pause,
force: false,
});
const { id } = await utils.createAsset(admin.accessToken, {
assetData: { bytes: await readFile(path2), filename: basename(path2) },
});
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
{
const asset = await utils.getAssetInfo(admin.accessToken, id);
expect(asset.exifInfo).toBeDefined();
expect(asset.exifInfo?.make).toBeNull();
}
await utils.jobCommand(admin.accessToken, JobName.MetadataExtraction, {
command: JobCommand.Empty,
force: false,
});
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
await utils.jobCommand(admin.accessToken, JobName.MetadataExtraction, {
command: JobCommand.Resume,
force: false,
});
await utils.jobCommand(admin.accessToken, JobName.MetadataExtraction, {
command: JobCommand.Start,
force: false,
});
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
{
const asset = await utils.getAssetInfo(admin.accessToken, id);
expect(asset.exifInfo).toBeDefined();
expect(asset.exifInfo?.make).toBe('NIKON CORPORATION');
}
});
});
});

View File

@@ -298,7 +298,6 @@ describe('/libraries', () => {
expect(status).toBe(204); expect(status).toBe(204);
await utils.waitForQueueFinish(admin.accessToken, 'library'); await utils.waitForQueueFinish(admin.accessToken, 'library');
await utils.waitForQueueFinish(admin.accessToken, 'metadataExtraction');
const { assets } = await utils.searchAssets(admin.accessToken, { const { assets } = await utils.searchAssets(admin.accessToken, {
originalPath: `${testAssetDirInternal}/temp/directoryA/assetA.png`, originalPath: `${testAssetDirInternal}/temp/directoryA/assetA.png`,

View File

@@ -1,7 +1,7 @@
import { getPerson, LoginResponseDto, PersonResponseDto } from '@immich/sdk'; import { LoginResponseDto, PersonResponseDto } from '@immich/sdk';
import { uuidDto } from 'src/fixtures'; import { uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses'; import { errorDto } from 'src/responses';
import { app, asBearerAuth, utils } from 'src/utils'; import { app, utils } from 'src/utils';
import request from 'supertest'; import request from 'supertest';
import { beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
@@ -195,7 +195,6 @@ describe('/people', () => {
.send({ .send({
name: 'New Person', name: 'New Person',
birthDate: '1990-01-01', birthDate: '1990-01-01',
color: '#333',
}); });
expect(status).toBe(201); expect(status).toBe(201);
expect(body).toMatchObject({ expect(body).toMatchObject({
@@ -204,22 +203,6 @@ describe('/people', () => {
birthDate: '1990-01-01T00:00:00.000Z', birthDate: '1990-01-01T00:00:00.000Z',
}); });
}); });
it('should create a favorite person', async () => {
const { status, body } = await request(app)
.post(`/people`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({
name: 'New Favorite Person',
isFavorite: true,
});
expect(status).toBe(201);
expect(body).toMatchObject({
id: expect.any(String),
name: 'New Favorite Person',
isFavorite: true,
});
});
}); });
describe('PUT /people/:id', () => { describe('PUT /people/:id', () => {
@@ -233,7 +216,6 @@ describe('/people', () => {
{ key: 'name', type: 'string' }, { key: 'name', type: 'string' },
{ key: 'featureFaceAssetId', type: 'string' }, { key: 'featureFaceAssetId', type: 'string' },
{ key: 'isHidden', type: 'boolean value' }, { key: 'isHidden', type: 'boolean value' },
{ key: 'isFavorite', type: 'boolean value' },
]) { ]) {
it(`should not allow null ${key}`, async () => { it(`should not allow null ${key}`, async () => {
const { status, body } = await request(app) const { status, body } = await request(app)
@@ -273,42 +255,6 @@ describe('/people', () => {
expect(status).toBe(200); expect(status).toBe(200);
expect(body).toMatchObject({ birthDate: null }); expect(body).toMatchObject({ birthDate: null });
}); });
it('should set a color', async () => {
const { status, body } = await request(app)
.put(`/people/${visiblePerson.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ color: '#555' });
expect(status).toBe(200);
expect(body).toMatchObject({ color: '#555' });
});
it('should clear a color', async () => {
const { status, body } = await request(app)
.put(`/people/${visiblePerson.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ color: null });
expect(status).toBe(200);
expect(body.color).toBeUndefined();
});
it('should mark a person as favorite', async () => {
const person = await utils.createPerson(admin.accessToken, {
name: 'visible_person',
});
expect(person.isFavorite).toBe(false);
const { status, body } = await request(app)
.put(`/people/${person.id}`)
.set('Authorization', `Bearer ${admin.accessToken}`)
.send({ isFavorite: true });
expect(status).toBe(200);
expect(body).toMatchObject({ isFavorite: true });
const person2 = await getPerson({ id: person.id }, { headers: asBearerAuth(admin.accessToken) });
expect(person2).toMatchObject({ id: person.id, isFavorite: true });
});
}); });
describe('POST /people/:id/merge', () => { describe('POST /people/:id/merge', () => {

View File

@@ -89,7 +89,7 @@ describe('/shared-links', () => {
await deleteUserAdmin({ id: user2.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) }); await deleteUserAdmin({ id: user2.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) });
}); });
describe('GET /share/:key', () => { describe('GET /share/${key}', () => {
it('should have correct asset count in meta tag for non-empty album', async () => { it('should have correct asset count in meta tag for non-empty album', async () => {
const resp = await request(shareUrl).get(`/${linkWithMetadata.key}`); const resp = await request(shareUrl).get(`/${linkWithMetadata.key}`);
expect(resp.status).toBe(200); expect(resp.status).toBe(200);
@@ -139,10 +139,7 @@ describe('/shared-links', () => {
expect(body).toEqual( expect(body).toEqual(
expect.arrayContaining([ expect.arrayContaining([
expect.objectContaining({ id: linkWithAlbum.id }), expect.objectContaining({ id: linkWithAlbum.id }),
expect.objectContaining({ expect.objectContaining({ id: linkWithAssets.id }),
id: linkWithAssets.id,
assets: expect.arrayContaining([expect.objectContaining({ id: asset1.id })]),
}),
expect.objectContaining({ id: linkWithPassword.id }), expect.objectContaining({ id: linkWithPassword.id }),
expect.objectContaining({ id: linkWithMetadata.id }), expect.objectContaining({ id: linkWithMetadata.id }),
expect.objectContaining({ id: linkWithoutMetadata.id }), expect.objectContaining({ id: linkWithoutMetadata.id }),
@@ -150,30 +147,6 @@ describe('/shared-links', () => {
); );
}); });
it('should filter on albumId', async () => {
const { status, body } = await request(app)
.get(`/shared-links?albumId=${album.id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(2);
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({ id: linkWithAlbum.id }),
expect.objectContaining({ id: linkWithPassword.id }),
]),
);
});
it('should find 0 albums', async () => {
const { status, body } = await request(app)
.get(`/shared-links?albumId=${uuidDto.notFound}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
expect(body).toHaveLength(0);
});
it('should not get shared links created by other users', async () => { it('should not get shared links created by other users', async () => {
const { status, body } = await request(app) const { status, body } = await request(app)
.get('/shared-links') .get('/shared-links')

View File

@@ -356,24 +356,5 @@ describe('/admin/users', () => {
expect(status).toBe(403); expect(status).toBe(403);
expect(body).toEqual(errorDto.forbidden); expect(body).toEqual(errorDto.forbidden);
}); });
it('should restore a user', async () => {
const user = await utils.userSetup(admin.accessToken, createUserDto.create('restore'));
await deleteUserAdmin({ id: user.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) });
const { status, body } = await request(app)
.post(`/admin/users/${user.userId}/restore`)
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
id: user.userId,
email: user.userEmail,
status: 'active',
deletedAt: null,
}),
);
});
}); });
}); });

View File

@@ -6,8 +6,6 @@ import {
CheckExistingAssetsDto, CheckExistingAssetsDto,
CreateAlbumDto, CreateAlbumDto,
CreateLibraryDto, CreateLibraryDto,
JobCommandDto,
JobName,
MetadataSearchDto, MetadataSearchDto,
Permission, Permission,
PersonCreateDto, PersonCreateDto,
@@ -31,7 +29,6 @@ import {
getConfigDefaults, getConfigDefaults,
login, login,
searchAssets, searchAssets,
sendJobCommand,
setBaseUrl, setBaseUrl,
signUpAdmin, signUpAdmin,
tagAssets, tagAssets,
@@ -478,9 +475,6 @@ export const utils = {
tagAssets: (accessToken: string, tagId: string, assetIds: string[]) => tagAssets: (accessToken: string, tagId: string, assetIds: string[]) =>
tagAssets({ id: tagId, bulkIdsDto: { ids: assetIds } }, { headers: asBearerAuth(accessToken) }), tagAssets({ id: tagId, bulkIdsDto: { ids: assetIds } }, { headers: asBearerAuth(accessToken) }),
jobCommand: async (accessToken: string, jobName: JobName, jobCommandDto: JobCommandDto) =>
sendJobCommand({ id: jobName, jobCommandDto }, { headers: asBearerAuth(accessToken) }),
setAuthCookies: async (context: BrowserContext, accessToken: string, domain = '127.0.0.1') => setAuthCookies: async (context: BrowserContext, accessToken: string, domain = '127.0.0.1') =>
await context.addCookies([ await context.addCookies([
{ {

View File

@@ -1,6 +1,4 @@
{ {
"search_by_description_example": "Hiking day in Sapa",
"search_by_description": "Search by description",
"about": "About", "about": "About",
"account": "Account", "account": "Account",
"account_settings": "Account Settings", "account_settings": "Account Settings",
@@ -436,7 +434,6 @@
"back_close_deselect": "Back, close, or deselect", "back_close_deselect": "Back, close, or deselect",
"backward": "Backward", "backward": "Backward",
"birthdate_saved": "Date of birth saved successfully", "birthdate_saved": "Date of birth saved successfully",
"show_shared_links": "Show shared links",
"birthdate_set_description": "Date of birth is used to calculate the age of this person at the time of a photo.", "birthdate_set_description": "Date of birth is used to calculate the age of this person at the time of a photo.",
"blurred_background": "Blurred background", "blurred_background": "Blurred background",
"bugs_and_feature_requests": "Bugs & Feature Requests", "bugs_and_feature_requests": "Bugs & Feature Requests",
@@ -602,8 +599,6 @@
"enable": "Enable", "enable": "Enable",
"enabled": "Enabled", "enabled": "Enabled",
"end_date": "End date", "end_date": "End date",
"rotate_left": "Rotate left",
"rotate_right": "Rotate right",
"error": "Error", "error": "Error",
"error_loading_image": "Error loading image", "error_loading_image": "Error loading image",
"error_title": "Error - Something went wrong", "error_title": "Error - Something went wrong",
@@ -646,7 +641,6 @@
"quota_higher_than_disk_size": "You set a quota higher than the disk size", "quota_higher_than_disk_size": "You set a quota higher than the disk size",
"repair_unable_to_check_items": "Unable to check {count, select, one {item} other {items}}", "repair_unable_to_check_items": "Unable to check {count, select, one {item} other {items}}",
"unable_to_add_album_users": "Unable to add users to album", "unable_to_add_album_users": "Unable to add users to album",
"unable_to_rotate_image": "Unable to rotate image",
"unable_to_add_assets_to_shared_link": "Unable to add assets to shared link", "unable_to_add_assets_to_shared_link": "Unable to add assets to shared link",
"unable_to_add_comment": "Unable to add comment", "unable_to_add_comment": "Unable to add comment",
"unable_to_add_exclusion_pattern": "Unable to add exclusion pattern", "unable_to_add_exclusion_pattern": "Unable to add exclusion pattern",
@@ -772,10 +766,8 @@
"go_to_search": "Go to search", "go_to_search": "Go to search",
"go_to_folder": "Go to folder", "go_to_folder": "Go to folder",
"group_albums_by": "Group albums by...", "group_albums_by": "Group albums by...",
"group_country": "Group by country",
"group_no": "No grouping", "group_no": "No grouping",
"group_owner": "Group by owner", "group_owner": "Group by owner",
"group_places_by": "Group places by...",
"group_year": "Group by year", "group_year": "Group by year",
"has_quota": "Has quota", "has_quota": "Has quota",
"hi_user": "Hi {name} ({email})", "hi_user": "Hi {name} ({email})",
@@ -808,7 +800,6 @@
"include_shared_albums": "Include shared albums", "include_shared_albums": "Include shared albums",
"include_shared_partner_assets": "Include shared partner assets", "include_shared_partner_assets": "Include shared partner assets",
"individual_share": "Individual share", "individual_share": "Individual share",
"individual_shares": "Individual shares",
"info": "Info", "info": "Info",
"interval": { "interval": {
"day_at_onepm": "Every day at 1pm", "day_at_onepm": "Every day at 1pm",
@@ -994,7 +985,6 @@
"pick_a_location": "Pick a location", "pick_a_location": "Pick a location",
"place": "Place", "place": "Place",
"places": "Places", "places": "Places",
"places_count": "{count, plural, one {{count, number} Place} other {{count, number} Places}}",
"play": "Play", "play": "Play",
"play_memories": "Play memories", "play_memories": "Play memories",
"play_motion_photo": "Play Motion Photo", "play_motion_photo": "Play Motion Photo",
@@ -1177,7 +1167,6 @@
"shared_from_partner": "Photos from {partner}", "shared_from_partner": "Photos from {partner}",
"shared_link_options": "Shared link options", "shared_link_options": "Shared link options",
"shared_links": "Shared links", "shared_links": "Shared links",
"shared_links_description": "Share photos and videos with a link",
"shared_photos_and_videos_count": "{assetCount, plural, other {# shared photos & videos.}}", "shared_photos_and_videos_count": "{assetCount, plural, other {# shared photos & videos.}}",
"shared_with_partner": "Shared with {partner}", "shared_with_partner": "Shared with {partner}",
"sharing": "Sharing", "sharing": "Sharing",
@@ -1287,7 +1276,6 @@
"unfavorite": "Unfavorite", "unfavorite": "Unfavorite",
"unhide_person": "Unhide person", "unhide_person": "Unhide person",
"unknown": "Unknown", "unknown": "Unknown",
"unknown_country": "Unknown Country",
"unknown_year": "Unknown Year", "unknown_year": "Unknown Year",
"unlimited": "Unlimited", "unlimited": "Unlimited",
"unlink_motion_video": "Unlink motion video", "unlink_motion_video": "Unlink motion video",

View File

@@ -312,157 +312,157 @@
"admin_password": "رمز عبور مدیر", "admin_password": "رمز عبور مدیر",
"administration": "مدیریت", "administration": "مدیریت",
"advanced": "پیشرفته", "advanced": "پیشرفته",
"album_added": "آلبوم اضافه شد", "album_added": "",
"album_added_notification_setting_description": "", "album_added_notification_setting_description": "",
"album_cover_updated": "جلد آلبوم به‌روزرسانی شد", "album_cover_updated": "",
"album_info_updated": "اطلاعات آلبوم به‌روزرسانی شد", "album_info_updated": "",
"album_name": "نام آلبوم", "album_name": "",
"album_options": "گزینه‌های آلبوم", "album_options": "",
"album_updated": "آلبوم به‌روزرسانی شد", "album_updated": "",
"album_updated_setting_description": "", "album_updated_setting_description": "",
"albums": "آلبوم‌ها", "albums": "",
"albums_count": "", "albums_count": "",
"all": "همه", "all": "",
"all_people": "همه افراد", "all_people": "",
"allow_dark_mode": "اجازه دادن به حالت تاریک", "allow_dark_mode": "",
"allow_edits": "اجازه ویرایش", "allow_edits": "",
"api_key": "کلید API", "api_key": "",
"api_keys": "کلیدهای API", "api_keys": "",
"app_settings": "تنظیمات برنامه", "app_settings": "",
"appears_in": "ظاهر می‌شود در", "appears_in": "",
"archive": "بایگانی", "archive": "",
"archive_or_unarchive_photo": "", "archive_or_unarchive_photo": "",
"archive_size": "اندازه بایگانی", "archive_size": "",
"archive_size_description": "", "archive_size_description": "",
"asset_offline": "محتوا آفلاین", "asset_offline": "",
"assets": "محتواها", "assets": "",
"authorized_devices": "دستگاه‌های مجاز", "authorized_devices": "",
"back": "بازگشت", "back": "",
"backward": "عقب", "backward": "",
"blurred_background": "پس‌زمینه محو", "blurred_background": "",
"bulk_delete_duplicates_confirmation": "", "bulk_delete_duplicates_confirmation": "",
"bulk_keep_duplicates_confirmation": "", "bulk_keep_duplicates_confirmation": "",
"bulk_trash_duplicates_confirmation": "", "bulk_trash_duplicates_confirmation": "",
"camera": "دوربین", "camera": "",
"camera_brand": "برند دوربین", "camera_brand": "",
"camera_model": "مدل دوربین", "camera_model": "",
"cancel": "لغو", "cancel": "",
"cancel_search": "لغو جستجو", "cancel_search": "",
"cannot_merge_people": "نمی‌توان افراد را ادغام کرد", "cannot_merge_people": "",
"cannot_update_the_description": "نمی‌توان توضیحات را به‌روزرسانی کرد", "cannot_update_the_description": "",
"change_date": "تغییر تاریخ", "change_date": "",
"change_expiration_time": "تغییر زمان انقضا", "change_expiration_time": "",
"change_location": "تغییر مکان", "change_location": "",
"change_name": "تغییر نام", "change_name": "",
"change_name_successfully": "نام با موفقیت تغییر یافت", "change_name_successfully": "",
"change_password": "تغییر رمز عبور", "change_password": "",
"change_your_password": "رمز عبور خود را تغییر دهید", "change_your_password": "",
"changed_visibility_successfully": "", "changed_visibility_successfully": "",
"check_all": "انتخاب همه", "check_all": "",
"check_logs": "بررسی لاگ‌ها", "check_logs": "",
"choose_matching_people_to_merge": "", "choose_matching_people_to_merge": "",
"city": "شهر", "city": "",
"clear": "پاک کردن", "clear": "",
"clear_all": "پاک کردن همه", "clear_all": "",
"clear_message": "پاک کردن پیام", "clear_message": "",
"clear_value": "پاک کردن مقدار", "clear_value": "",
"close": "بستن", "close": "",
"collapse_all": "جمع کردن همه", "collapse_all": "",
"color_theme": "تم رنگ", "color_theme": "",
"comment_options": "گزینه‌های نظر", "comment_options": "",
"comments_are_disabled": "نظرات غیرفعال هستند", "comments_are_disabled": "",
"confirm": "تأیید", "confirm": "",
"confirm_admin_password": "تأیید رمز عبور مدیر", "confirm_admin_password": "",
"confirm_delete_shared_link": "", "confirm_delete_shared_link": "",
"confirm_password": "تأیید رمز عبور", "confirm_password": "",
"contain": "شامل", "contain": "",
"context": "زمینه", "context": "",
"continue": "ادامه", "continue": "",
"copied_image_to_clipboard": "تصویر به کلیپ‌بورد کپی شد.", "copied_image_to_clipboard": "",
"copied_to_clipboard": "به کلیپ‌بورد کپی شد!", "copied_to_clipboard": "",
"copy_error": "خطا در کپی", "copy_error": "",
"copy_file_path": "کپی مسیر فایل", "copy_file_path": "",
"copy_image": "کپی تصویر", "copy_image": "",
"copy_link": "کپی لینک", "copy_link": "",
"copy_link_to_clipboard": "کپی لینک به کلیپ‌بورد", "copy_link_to_clipboard": "",
"copy_password": "کپی رمز عبور", "copy_password": "",
"copy_to_clipboard": "کپی به کلیپ‌بورد", "copy_to_clipboard": "",
"country": "کشور", "country": "",
"cover": "جلد", "cover": "",
"covers": "جلدها", "covers": "",
"create": "ایجاد", "create": "",
"create_album": "ایجاد آلبوم", "create_album": "",
"create_library": "ایجاد کتابخانه", "create_library": "",
"create_link": "ایجاد لینک", "create_link": "",
"create_link_to_share": "ایجاد لینک برای اشتراک‌گذاری", "create_link_to_share": "",
"create_new_person": "ایجاد فرد جدید", "create_new_person": "",
"create_new_user": "ایجاد کاربر جدید", "create_new_user": "",
"create_user": "ایجاد کاربر", "create_user": "",
"created": "ایجاد شد", "created": "",
"current_device": "دستگاه فعلی", "current_device": "",
"custom_locale": "", "custom_locale": "",
"custom_locale_description": "", "custom_locale_description": "",
"dark": "تاریک", "dark": "",
"date_after": "تاریخ پس از", "date_after": "",
"date_and_time": "تاریخ و زمان", "date_and_time": "",
"date_before": "تاریخ قبل از", "date_before": "",
"date_range": "بازه زمانی", "date_range": "",
"day": "روز", "day": "",
"deduplicate_all": "حذف تکراری‌ها به صورت کامل", "deduplicate_all": "",
"default_locale": "", "default_locale": "",
"default_locale_description": "", "default_locale_description": "",
"delete": "حذف", "delete": "",
"delete_album": "حذف آلبوم", "delete_album": "",
"delete_api_key_prompt": "", "delete_api_key_prompt": "",
"delete_duplicates_confirmation": "", "delete_duplicates_confirmation": "",
"delete_key": "حذف کلید", "delete_key": "",
"delete_library": "حذف کتابخانه", "delete_library": "",
"delete_link": "حذف لینک", "delete_link": "",
"delete_shared_link": "حذف لینک اشتراکی", "delete_shared_link": "",
"delete_user": "حذف کاربر", "delete_user": "",
"deleted_shared_link": "لینک اشتراکی حذف شد", "deleted_shared_link": "",
"description": "توضیحات", "description": "",
"details": "جزئیات", "details": "",
"direction": "جهت", "direction": "",
"disabled": "غیرفعال", "disabled": "",
"disallow_edits": "عدم اجازه ویرایش", "disallow_edits": "",
"discover": "کشف کردن", "discover": "",
"dismiss_all_errors": "رد تمام خطاها", "dismiss_all_errors": "",
"dismiss_error": "رد خطا", "dismiss_error": "",
"display_options": "گزینه‌های نمایش", "display_options": "",
"display_order": "ترتیب نمایش", "display_order": "",
"display_original_photos": "نمایش عکس‌های اصلی", "display_original_photos": "",
"display_original_photos_setting_description": "", "display_original_photos_setting_description": "",
"done": "انجام شد", "done": "",
"download": "دانلود", "download": "",
"download_settings": "تنظیمات دانلود", "download_settings": "",
"download_settings_description": "مدیریت تنظیمات مرتبط با دانلود محتوا", "download_settings_description": "",
"downloading": "در حال دانلود", "downloading": "",
"duplicates": "تکراری‌ها", "duplicates": "",
"duplicates_description": "", "duplicates_description": "",
"duration": "مدت زمان", "duration": "",
"edit_album": "ویرایش آلبوم", "edit_album": "",
"edit_avatar": "ویرایش آواتار", "edit_avatar": "",
"edit_date": "ویرایش تاریخ", "edit_date": "",
"edit_date_and_time": "ویرایش تاریخ و زمان", "edit_date_and_time": "",
"edit_exclusion_pattern": "ویرایش الگوی استثناء", "edit_exclusion_pattern": "",
"edit_faces": "ویرایش چهره‌ها", "edit_faces": "",
"edit_import_path": "", "edit_import_path": "",
"edit_import_paths": "", "edit_import_paths": "",
"edit_key": "ویرایش کلید", "edit_key": "",
"edit_link": "ویرایش لینک", "edit_link": "",
"edit_location": "ویرایش مکان", "edit_location": "",
"edit_name": "ویرایش نام", "edit_name": "",
"edit_people": "ویرایش افراد", "edit_people": "",
"edit_title": "ویرایش عنوان", "edit_title": "",
"edit_user": "ویرایش کاربر", "edit_user": "",
"edited": "ویرایش شد", "edited": "",
"editor": "ویرایشگر", "editor": "",
"email": "ایمیل", "email": "",
"empty_trash": "خالی کردن سطل زباله", "empty_trash": "",
"end_date": "تاریخ پایان", "end_date": "",
"error": "خطا", "error": "",
"error_loading_image": "خطا در بارگذاری تصویر", "error_loading_image": "",
"errors": { "errors": {
"exclusion_pattern_already_exists": "", "exclusion_pattern_already_exists": "",
"import_path_already_exists": "", "import_path_already_exists": "",
@@ -530,400 +530,400 @@
"unable_to_update_timeline_display_status": "", "unable_to_update_timeline_display_status": "",
"unable_to_update_user": "" "unable_to_update_user": ""
}, },
"exit_slideshow": "خروج از نمایش اسلاید", "exit_slideshow": "",
"expand_all": "باز کردن همه", "expand_all": "",
"expire_after": "منقضی شدن بعد از", "expire_after": "",
"expired": "منقضی شده", "expired": "",
"explore": "کاوش کردن", "explore": "",
"export": "صادر کردن", "export": "",
"export_as_json": "صادر کردن به‌صورت JSON", "export_as_json": "",
"extension": "پسوند", "extension": "",
"external": "خارجی", "external": "",
"external_libraries": "کتابخانه‌های خارجی", "external_libraries": "",
"favorite": "علاقه‌مندی", "favorite": "",
"favorite_or_unfavorite_photo": "", "favorite_or_unfavorite_photo": "",
"favorites": "علاقه‌مندی‌ها", "favorites": "",
"feature_photo_updated": "", "feature_photo_updated": "",
"file_name": "نام فایل", "file_name": "",
"file_name_or_extension": "نام فایل یا پسوند", "file_name_or_extension": "",
"filename": "نام فایل", "filename": "",
"filetype": "نوع فایل", "filetype": "",
"filter_people": "فیلتر افراد", "filter_people": "",
"find_them_fast": "", "find_them_fast": "",
"fix_incorrect_match": "رفع تطابق نادرست", "fix_incorrect_match": "",
"forward": "جلو", "forward": "",
"general": "عمومی", "general": "",
"get_help": "دریافت کمک", "get_help": "",
"getting_started": "شروع به کار", "getting_started": "",
"go_back": "بازگشت", "go_back": "",
"go_to_search": "رفتن به جستجو", "go_to_search": "",
"group_albums_by": "گروه‌بندی آلبوم‌ها براساس...", "group_albums_by": "",
"has_quota": "دارای سهمیه", "has_quota": "",
"hide_gallery": "پنهان کردن گالری", "hide_gallery": "",
"hide_password": "پنهان کردن رمز عبور", "hide_password": "",
"hide_person": "پنهان کردن فرد", "hide_person": "",
"host": "میزبان", "host": "",
"hour": "ساعت", "hour": "",
"image": "تصویر", "image": "",
"immich_logo": "لوگوی Immich", "immich_logo": "",
"immich_web_interface": "رابط وب Immich", "immich_web_interface": "",
"import_from_json": "وارد کردن از JSON", "import_from_json": "",
"import_path": "مسیر وارد کردن", "import_path": "",
"in_albums": "", "in_albums": "",
"in_archive": "در بایگانی", "in_archive": "",
"include_archived": "شامل بایگانی شده‌ها", "include_archived": "",
"include_shared_albums": "شامل آلبوم‌های اشتراکی", "include_shared_albums": "",
"include_shared_partner_assets": "", "include_shared_partner_assets": "",
"individual_share": "اشتراک فردی", "individual_share": "",
"info": "اطلاعات", "info": "",
"interval": { "interval": {
"day_at_onepm": "", "day_at_onepm": "",
"hours": "", "hours": "",
"night_at_midnight": "", "night_at_midnight": "",
"night_at_twoam": "" "night_at_twoam": ""
}, },
"invite_people": "دعوت افراد", "invite_people": "",
"invite_to_album": "دعوت به آلبوم", "invite_to_album": "",
"jobs": "وظایف", "jobs": "",
"keep": "نگه داشتن", "keep": "",
"keep_all": "نگه داشتن همه", "keep_all": "",
"keyboard_shortcuts": "میانبرهای صفحه‌کلید", "keyboard_shortcuts": "",
"language": "زبان", "language": "",
"language_setting_description": "انتخاب زبان دلخواه شما", "language_setting_description": "",
"last_seen": "آخرین مشاهده", "last_seen": "",
"leave": "ترک کردن", "leave": "",
"let_others_respond": "اجازه به دیگران برای پاسخ‌گویی", "let_others_respond": "",
"level": "سطح", "level": "",
"library": "کتابخانه", "library": "",
"library_options": "گزینه‌های کتابخانه", "library_options": "",
"light": "روشن", "light": "",
"link_options": "گزینه‌های لینک", "link_options": "",
"link_to_oauth": "اتصال به OAuth", "link_to_oauth": "",
"linked_oauth_account": "حساب OAuth متصل شده", "linked_oauth_account": "",
"list": "لیست", "list": "",
"loading": "در حال بارگذاری", "loading": "",
"loading_search_results_failed": "بارگذاری نتایج جستجو ناموفق بود", "loading_search_results_failed": "",
"log_out": "خروج از سیستم", "log_out": "",
"log_out_all_devices": "خروج از همه دستگاه‌ها", "log_out_all_devices": "",
"login_has_been_disabled": "ورود غیرفعال شده است.", "login_has_been_disabled": "",
"look": "نگاه کردن", "look": "",
"loop_videos": "پخش مداوم ویدئوها", "loop_videos": "",
"loop_videos_description": "", "loop_videos_description": "",
"make": "ساختن", "make": "",
"manage_shared_links": "مدیریت لینک‌های اشتراکی", "manage_shared_links": "",
"manage_sharing_with_partners": "", "manage_sharing_with_partners": "",
"manage_the_app_settings": "مدیریت تنظیمات برنامه", "manage_the_app_settings": "",
"manage_your_account": "مدیریت حساب کاربری شما", "manage_your_account": "",
"manage_your_api_keys": "مدیریت کلیدهای API شما", "manage_your_api_keys": "",
"manage_your_devices": "مدیریت دستگاه‌های متصل", "manage_your_devices": "",
"manage_your_oauth_connection": "مدیریت اتصال OAuth شما", "manage_your_oauth_connection": "",
"map": "نقشه", "map": "",
"map_marker_with_image": "", "map_marker_with_image": "",
"map_settings": "تنظیمات نقشه", "map_settings": "",
"matches": "تطابق‌ها", "matches": "",
"media_type": "نوع رسانه", "media_type": "",
"memories": "خاطرات", "memories": "",
"memories_setting_description": "", "memories_setting_description": "",
"memory": "خاطره", "memory": "",
"menu": "منو", "menu": "",
"merge": "ادغام", "merge": "",
"merge_people": "ادغام افراد", "merge_people": "",
"merge_people_limit": "", "merge_people_limit": "",
"merge_people_prompt": "", "merge_people_prompt": "",
"merge_people_successfully": "ادغام افراد با موفقیت انجام شد", "merge_people_successfully": "",
"minimize": "کوچک کردن", "minimize": "",
"minute": "دقیقه", "minute": "",
"missing": "گمشده", "missing": "",
"model": "مدل", "model": "",
"month": "ماه", "month": "",
"more": "بیشتر", "more": "",
"moved_to_trash": "به سطل زباله منتقل شد", "moved_to_trash": "",
"my_albums": "آلبوم‌های من", "my_albums": "",
"name": "نام", "name": "",
"name_or_nickname": "نام یا لقب", "name_or_nickname": "",
"never": "هرگز", "never": "",
"new_api_key": "کلید API جدید", "new_api_key": "",
"new_password": "رمز عبور جدید", "new_password": "",
"new_person": "فرد جدید", "new_person": "",
"new_user_created": "کاربر جدید ایجاد شد", "new_user_created": "",
"newest_first": "جدیدترین ابتدا", "newest_first": "",
"next": "بعدی", "next": "",
"next_memory": "خاطره بعدی", "next_memory": "",
"no": "خیر", "no": "",
"no_albums_message": "", "no_albums_message": "",
"no_archived_assets_message": "", "no_archived_assets_message": "",
"no_assets_message": "", "no_assets_message": "",
"no_duplicates_found": "هیچ تکراری یافت نشد.", "no_duplicates_found": "",
"no_exif_info_available": "اطلاعات EXIF موجود نیست", "no_exif_info_available": "",
"no_explore_results_message": "", "no_explore_results_message": "",
"no_favorites_message": "", "no_favorites_message": "",
"no_libraries_message": "", "no_libraries_message": "",
"no_name": "بدون نام", "no_name": "",
"no_places": "مکانی یافت نشد", "no_places": "",
"no_results": "نتیجه‌ای یافت نشد", "no_results": "",
"no_shared_albums_message": "", "no_shared_albums_message": "",
"not_in_any_album": "در هیچ آلبومی نیست", "not_in_any_album": "",
"note_apply_storage_label_to_previously_uploaded assets": "", "note_apply_storage_label_to_previously_uploaded assets": "",
"note_unlimited_quota": "", "note_unlimited_quota": "",
"notes": "یادداشت‌ها", "notes": "",
"notification_toggle_setting_description": "اعلان‌های ایمیلی را فعال کنید", "notification_toggle_setting_description": "",
"notifications": "اعلان‌ها", "notifications": "",
"notifications_setting_description": "مدیریت اعلان‌ها", "notifications_setting_description": "",
"oauth": "OAuth", "oauth": "",
"offline": "آفلاین", "offline": "",
"offline_paths": "مسیرهای آفلاین", "offline_paths": "",
"offline_paths_description": "", "offline_paths_description": "",
"ok": "تأیید", "ok": "",
"oldest_first": "قدیمی‌ترین ابتدا", "oldest_first": "",
"online": "آنلاین", "online": "",
"only_favorites": "فقط علاقه‌مندی‌ها", "only_favorites": "",
"open_the_search_filters": "باز کردن فیلترهای جستجو", "open_the_search_filters": "",
"options": "گزینه‌ها", "options": "",
"organize_your_library": "کتابخانه خود را سازماندهی کنید", "organize_your_library": "",
"other": "دیگر", "other": "",
"other_devices": "دستگاه‌های دیگر", "other_devices": "",
"other_variables": "متغیرهای دیگر", "other_variables": "",
"owned": "مالکیت", "owned": "",
"owner": "مالک", "owner": "",
"partner": "شریک", "partner": "",
"partner_can_access": "{partner} می‌تواند دسترسی داشته باشد", "partner_can_access": "",
"partner_can_access_assets": "", "partner_can_access_assets": "",
"partner_can_access_location": "مکان‌هایی که عکس‌های شما گرفته شده‌اند", "partner_can_access_location": "",
"partner_sharing": "اشتراک‌گذاری با شریک", "partner_sharing": "",
"partners": "شرکا", "partners": "",
"password": "رمز عبور", "password": "",
"password_does_not_match": "رمز عبور مطابقت ندارد", "password_does_not_match": "",
"password_required": "رمز عبور مورد نیاز است", "password_required": "",
"password_reset_success": "بازنشانی رمز عبور موفقیت‌آمیز بود", "password_reset_success": "",
"past_durations": { "past_durations": {
"days": "", "days": "",
"hours": "", "hours": "",
"years": "" "years": ""
}, },
"path": "مسیر", "path": "",
"pattern": "الگو", "pattern": "",
"pause": "توقف", "pause": "",
"pause_memories": "توقف خاطرات", "pause_memories": "",
"paused": "متوقف شده", "paused": "",
"pending": "در انتظار", "pending": "",
"people": "افراد", "people": "",
"people_sidebar_description": "", "people_sidebar_description": "",
"permanent_deletion_warning": "هشدار حذف دائمی", "permanent_deletion_warning": "",
"permanent_deletion_warning_setting_description": "نمایش هشدار هنگام حذف دائمی محتواها", "permanent_deletion_warning_setting_description": "",
"permanently_delete": "حذف دائمی", "permanently_delete": "",
"permanently_deleted_asset": "محتوای حذف شده دائمی", "permanently_deleted_asset": "",
"person": "فرد", "person": "",
"photos": "عکس‌ها", "photos": "",
"photos_count": "", "photos_count": "",
"photos_from_previous_years": "عکس‌های سال‌های گذشته", "photos_from_previous_years": "",
"pick_a_location": "یک مکان انتخاب کنید", "pick_a_location": "",
"place": "مکان", "place": "",
"places": "مکان‌ها", "places": "",
"play": "پخش", "play": "",
"play_memories": "پخش خاطرات", "play_memories": "",
"play_motion_photo": "پخش عکس متحرک", "play_motion_photo": "",
"play_or_pause_video": "پخش یا توقف ویدیو", "play_or_pause_video": "",
"port": "پورت", "port": "",
"preset": "پیش‌فرض", "preset": "",
"preview": "پیش‌نمایش", "preview": "",
"previous": "قبلی", "previous": "",
"previous_memory": "خاطره قبلی", "previous_memory": "",
"previous_or_next_photo": "عکس قبلی یا بعدی", "previous_or_next_photo": "",
"primary": "اصلی", "primary": "",
"profile_picture_set": "تصویر پروفایل تنظیم شد.", "profile_picture_set": "",
"public_share": "اشتراک عمومی", "public_share": "",
"reaction_options": "گزینه‌های واکنش", "reaction_options": "",
"read_changelog": "مطالعه تغییرات نسخه", "read_changelog": "",
"recent": "اخیر", "recent": "",
"recent_searches": "جستجوهای اخیر", "recent_searches": "",
"refresh": "تازه سازی", "refresh": "",
"refreshed": "تازه سازی شد", "refreshed": "",
"refreshes_every_file": "", "refreshes_every_file": "",
"remove": "حذف", "remove": "",
"remove_deleted_assets": "حذف محتواهای حذف‌شده", "remove_deleted_assets": "",
"remove_from_album": "حذف از آلبوم", "remove_from_album": "",
"remove_from_favorites": "حذف از علاقه‌مندی‌ها", "remove_from_favorites": "",
"remove_from_shared_link": "", "remove_from_shared_link": "",
"removed_api_key": "", "removed_api_key": "",
"rename": "تغییر نام", "rename": "",
"repair": "تعمیر", "repair": "",
"repair_no_results_message": "", "repair_no_results_message": "",
"replace_with_upload": "جایگزینی با آپلود", "replace_with_upload": "",
"require_password": "", "require_password": "",
"require_user_to_change_password_on_first_login": "", "require_user_to_change_password_on_first_login": "",
"reset": "بازنشانی", "reset": "",
"reset_password": "بازنشانی رمز عبور", "reset_password": "",
"reset_people_visibility": "", "reset_people_visibility": "",
"resolved_all_duplicates": "", "resolved_all_duplicates": "",
"restore": "بازیابی", "restore": "",
"restore_all": "بازیابی همه", "restore_all": "",
"restore_user": "بازیابی کاربر", "restore_user": "",
"resume": "ادامه", "resume": "",
"retry_upload": "", "retry_upload": "",
"review_duplicates": "بررسی تکراری‌ها", "review_duplicates": "",
"role": "نقش", "role": "",
"save": "ذخیره", "save": "",
"saved_api_key": "", "saved_api_key": "",
"saved_profile": "پروفایل ذخیره شد", "saved_profile": "",
"saved_settings": "تنظیمات ذخیره شد", "saved_settings": "",
"say_something": "چیزی بگویید", "say_something": "",
"scan_all_libraries": "اسکن همه کتابخانه‌ها", "scan_all_libraries": "",
"scan_settings": "تنظیمات اسکن", "scan_settings": "",
"scanning_for_album": "", "scanning_for_album": "",
"search": "جستجو", "search": "",
"search_albums": "جستجوی آلبوم‌ها", "search_albums": "",
"search_by_context": "جستجو براساس زمینه", "search_by_context": "",
"search_camera_make": "جستجوی برند دوربین...", "search_camera_make": "",
"search_camera_model": "جستجوی مدل دوربین...", "search_camera_model": "",
"search_city": "جستجوی شهر...", "search_city": "",
"search_country": "جستجوی کشور...", "search_country": "",
"search_for_existing_person": "جستجوی فرد موجود", "search_for_existing_person": "",
"search_people": "جستجوی افراد", "search_people": "",
"search_places": "جستجوی مکان‌ها", "search_places": "",
"search_state": "جستجوی ایالت...", "search_state": "",
"search_timezone": "جستجوی منطقه زمانی...", "search_timezone": "",
"search_type": "نوع جستجو", "search_type": "",
"search_your_photos": "", "search_your_photos": "",
"searching_locales": "", "searching_locales": "",
"second": "ثانیه", "second": "",
"select_album_cover": "انتخاب جلد آلبوم", "select_album_cover": "",
"select_all": "انتخاب همه", "select_all": "",
"select_avatar_color": "انتخاب رنگ آواتار", "select_avatar_color": "",
"select_face": "انتخاب چهره", "select_face": "",
"select_featured_photo": "انتخاب عکس ویژه", "select_featured_photo": "",
"select_keep_all": "انتخاب نگهداری همه", "select_keep_all": "",
"select_library_owner": "انتخاب مالک کتابخانه", "select_library_owner": "",
"select_new_face": "انتخاب چهره جدید", "select_new_face": "",
"select_photos": "انتخاب عکس‌ها", "select_photos": "",
"select_trash_all": "", "select_trash_all": "",
"selected": "انتخاب شده", "selected": "",
"send_message": "ارسال پیام", "send_message": "",
"send_welcome_email": "ارسال ایمیل خوش‌آمدگویی", "send_welcome_email": "",
"server_stats": "آمار سرور", "server_stats": "",
"set": "تنظیم", "set": "",
"set_as_album_cover": "", "set_as_album_cover": "",
"set_as_profile_picture": "", "set_as_profile_picture": "",
"set_date_of_birth": "تنظیم تاریخ تولد", "set_date_of_birth": "",
"set_profile_picture": "تنظیم تصویر پروفایل", "set_profile_picture": "",
"set_slideshow_to_fullscreen": "", "set_slideshow_to_fullscreen": "",
"settings": "تنظیمات", "settings": "",
"settings_saved": "تنظیمات ذخیره شد", "settings_saved": "",
"share": "اشتراک‌گذاری", "share": "",
"shared": "مشترک", "shared": "",
"shared_by": "مشترک توسط", "shared_by": "",
"shared_by_you": "", "shared_by_you": "",
"shared_from_partner": "عکس‌ها از {partner}", "shared_from_partner": "",
"shared_links": "لینک‌های اشتراکی", "shared_links": "",
"shared_photos_and_videos_count": "", "shared_photos_and_videos_count": "",
"shared_with_partner": "مشترک با {partner}", "shared_with_partner": "",
"sharing": "اشتراک‌گذاری", "sharing": "",
"sharing_sidebar_description": "", "sharing_sidebar_description": "",
"show_album_options": "نمایش گزینه‌های آلبوم", "show_album_options": "",
"show_and_hide_people": "", "show_and_hide_people": "",
"show_file_location": "نمایش مسیر فایل", "show_file_location": "",
"show_gallery": "نمایش گالری", "show_gallery": "",
"show_hidden_people": "نمایش افراد پنهان", "show_hidden_people": "",
"show_in_timeline": "", "show_in_timeline": "",
"show_in_timeline_setting_description": "", "show_in_timeline_setting_description": "",
"show_keyboard_shortcuts": "", "show_keyboard_shortcuts": "",
"show_metadata": "نمایش اطلاعات متا", "show_metadata": "",
"show_or_hide_info": "", "show_or_hide_info": "",
"show_password": "نمایش رمز عبور", "show_password": "",
"show_person_options": "", "show_person_options": "",
"show_progress_bar": "نمایش نوار پیشرفت", "show_progress_bar": "",
"show_search_options": "نمایش گزینه‌های جستجو", "show_search_options": "",
"shuffle": "تصادفی", "shuffle": "",
"sign_out": "خروج", "sign_out": "",
"sign_up": "ثبت‌نام", "sign_up": "",
"size": "اندازه", "size": "",
"skip_to_content": "رفتن به محتوا", "skip_to_content": "",
"slideshow": "نمایش اسلاید", "slideshow": "",
"slideshow_settings": "تنظیمات نمایش اسلاید", "slideshow_settings": "",
"sort_albums_by": "", "sort_albums_by": "",
"stack": "پشته", "stack": "",
"stack_selected_photos": "", "stack_selected_photos": "",
"stacktrace": "", "stacktrace": "",
"start": "شروع", "start": "",
"start_date": "تاریخ شروع", "start_date": "",
"state": "ایالت", "state": "",
"status": "وضعیت", "status": "",
"stop_motion_photo": "توقف عکس متحرک", "stop_motion_photo": "",
"stop_photo_sharing": "", "stop_photo_sharing": "",
"stop_photo_sharing_description": "", "stop_photo_sharing_description": "",
"stop_sharing_photos_with_user": "", "stop_sharing_photos_with_user": "",
"storage": "فضای ذخیره‌سازی", "storage": "",
"storage_label": "برچسب فضای ذخیره‌سازی", "storage_label": "",
"storage_usage": "", "storage_usage": "",
"submit": "ارسال", "submit": "",
"suggestions": "پیشنهادات", "suggestions": "",
"sunrise_on_the_beach": "", "sunrise_on_the_beach": "",
"swap_merge_direction": "تغییر جهت ادغام", "swap_merge_direction": "",
"sync": "همگام‌سازی", "sync": "",
"template": "الگو", "template": "",
"theme": "تم", "theme": "",
"theme_selection": "انتخاب تم", "theme_selection": "",
"theme_selection_description": "", "theme_selection_description": "",
"time_based_memories": "", "time_based_memories": "",
"timezone": "منطقه زمانی", "timezone": "",
"to_archive": "بایگانی", "to_archive": "",
"to_favorite": "به علاقه‌مندی‌ها", "to_favorite": "",
"to_trash": "", "to_trash": "",
"toggle_settings": "تغییر تنظیمات", "toggle_settings": "",
"toggle_theme": "تغییر تم تاریک", "toggle_theme": "",
"total_usage": "استفاده کلی", "total_usage": "",
"trash": "سطل زباله", "trash": "",
"trash_all": "", "trash_all": "",
"trash_count": "", "trash_count": "",
"trash_no_results_message": "", "trash_no_results_message": "",
"trashed_items_will_be_permanently_deleted_after": "", "trashed_items_will_be_permanently_deleted_after": "",
"type": "نوع", "type": "",
"unarchive": "", "unarchive": "",
"unfavorite": "حذف از علاقه‌مندی‌ها", "unfavorite": "",
"unhide_person": "آشکار کردن فرد", "unhide_person": "",
"unknown": "ناشناخته", "unknown": "",
"unknown_year": "سال نامشخص", "unknown_year": "",
"unlimited": "نامحدود", "unlimited": "",
"unlink_oauth": "لغو اتصال OAuth", "unlink_oauth": "",
"unlinked_oauth_account": "", "unlinked_oauth_account": "",
"unnamed_album": "آلبوم بدون نام", "unnamed_album": "",
"unnamed_share": "اشتراک بدون نام", "unnamed_share": "",
"unselect_all": "لغو انتخاب همه", "unselect_all": "",
"unstack": "", "unstack": "",
"untracked_files": "", "untracked_files": "",
"untracked_files_decription": "", "untracked_files_decription": "",
"up_next": "مورد بعدی", "up_next": "",
"updated_password": "", "updated_password": "",
"upload": "آپلود", "upload": "",
"upload_concurrency": "تعداد آپلود همزمان", "upload_concurrency": "",
"url": "آدرس", "url": "",
"usage": "استفاده", "usage": "",
"user": "کاربر", "user": "",
"user_id": "شناسه کاربر", "user_id": "",
"user_usage_detail": "جزئیات استفاده کاربر", "user_usage_detail": "",
"username": "نام کاربری", "username": "",
"users": "کاربران", "users": "",
"utilities": "ابزارها", "utilities": "",
"validate": "اعتبارسنجی", "validate": "",
"variables": "متغیرها", "variables": "",
"version": "نسخه", "version": "",
"version_announcement_message": "", "version_announcement_message": "",
"video": "ویدیو", "video": "",
"video_hover_setting": "", "video_hover_setting": "",
"video_hover_setting_description": "", "video_hover_setting_description": "",
"videos": "ویدیوها", "videos": "",
"videos_count": "", "videos_count": "",
"view": "مشاهده", "view": "",
"view_all": "مشاهده همه", "view_all": "",
"view_all_users": "مشاهده همه کاربران", "view_all_users": "",
"view_links": "مشاهده لینک‌ها", "view_links": "",
"view_next_asset": "مشاهده محتوای بعدی", "view_next_asset": "",
"view_previous_asset": "مشاهده محتوای قبلی", "view_previous_asset": "",
"waiting": "در انتظار", "waiting": "",
"week": "هفته", "week": "",
"welcome": "خوش آمدید", "welcome": "",
"welcome_to_immich": "", "welcome_to_immich": "",
"year": "سال", "year": "",
"yes": "بله", "yes": "",
"you_dont_have_any_shared_links": "", "you_dont_have_any_shared_links": "",
"zoom_image": "بزرگنمایی تصویر" "zoom_image": "بزرگنمایی تصویر"
} }

View File

@@ -1,6 +1,6 @@
{ {
"about": "เกี่ยวกับ", "about": "เกี่ยวกับ",
"account": "บัญชีผู้ใช้", "account": "บัญชี",
"account_settings": "การตั้งค่าบัญชี", "account_settings": "การตั้งค่าบัญชี",
"acknowledge": "รับทราบ", "acknowledge": "รับทราบ",
"action": "การดำเนินการ", "action": "การดำเนินการ",
@@ -155,7 +155,7 @@
"migration_job_description": "ย้ายภาพตัวอย่างสื่อและใบหน้าไปยังโครงสร้างโฟลเดอร์ล่าสุด", "migration_job_description": "ย้ายภาพตัวอย่างสื่อและใบหน้าไปยังโครงสร้างโฟลเดอร์ล่าสุด",
"no_paths_added": "ไม่ได้เพิ่มพาธ", "no_paths_added": "ไม่ได้เพิ่มพาธ",
"no_pattern_added": "ไม่ได้เพิ่มรูปแบบ", "no_pattern_added": "ไม่ได้เพิ่มรูปแบบ",
"note_apply_storage_label_previous_assets": "หากต้องการใช้ Storage Label กับไฟล์ที่อัโหลดก่อนหน้านี้ ให้รันคำสั่งนี้", "note_apply_storage_label_previous_assets": "หมายเหตุ: หากจะแปะฉลากจัดเก็บใส่สื่อที่อัโหลดก่อนหน้านี้ ให้",
"note_cannot_be_changed_later": "หมายเหตุ: ไม่สามารถเปลี่ยนภายหลังได้!", "note_cannot_be_changed_later": "หมายเหตุ: ไม่สามารถเปลี่ยนภายหลังได้!",
"note_unlimited_quota": "หมายเหตุ: ใส่เลข 0 สําหรับโควต้าไม่จํากัด", "note_unlimited_quota": "หมายเหตุ: ใส่เลข 0 สําหรับโควต้าไม่จํากัด",
"notification_email_from_address": "จากที่อยู่", "notification_email_from_address": "จากที่อยู่",
@@ -193,8 +193,8 @@
"oauth_settings_description": "จัดการการตั้งค่าล็อกอินผ่าน OAuth", "oauth_settings_description": "จัดการการตั้งค่าล็อกอินผ่าน OAuth",
"oauth_settings_more_details": "สำหรับรายละเอียดเพิ่มเติม ให้อ้างถึง<link>เอกสาร</link>", "oauth_settings_more_details": "สำหรับรายละเอียดเพิ่มเติม ให้อ้างถึง<link>เอกสาร</link>",
"oauth_signing_algorithm": "อัลกอริทึมการลงนาม", "oauth_signing_algorithm": "อัลกอริทึมการลงนาม",
"oauth_storage_label_claim": "สิทธิ์ที่ใช้อ้างถึงป้ายกำกับการจัดเก็บ", "oauth_storage_label_claim": "สิทธิ์ที่ใช้อ้างถึงฉลากการจัดเก็บ",
"oauth_storage_label_claim_description": "ตั้งป้ายกำกับการจัดเก็บของผู้ใช้งานตามสิทธิ์ที่ใช้อ้างถึงโดยอัตโนมัติ", "oauth_storage_label_claim_description": "ตั้งฉลากการจัดเก็บของผู้ใช้งานตามสิทธิ์ที่ใช้อ้างถึงโดยอัตโนมัติ",
"oauth_storage_quota_claim": "สิทธิ์ที่ใช้อ้างถึงโควต้าพื้นที่จัดเก็บ", "oauth_storage_quota_claim": "สิทธิ์ที่ใช้อ้างถึงโควต้าพื้นที่จัดเก็บ",
"oauth_storage_quota_claim_description": "ตั้งโควต้าพื้นที่จัดเก็บของผู้ใช้งานตามสิทธิ์ที่ใช้อ้างถึงโดยอัตโนมัติ", "oauth_storage_quota_claim_description": "ตั้งโควต้าพื้นที่จัดเก็บของผู้ใช้งานตามสิทธิ์ที่ใช้อ้างถึงโดยอัตโนมัติ",
"oauth_storage_quota_default": "โควต้าพื้นที่เก็บข้อมูลเริ่มต้น (GiB)", "oauth_storage_quota_default": "โควต้าพื้นที่เก็บข้อมูลเริ่มต้น (GiB)",
@@ -235,7 +235,7 @@
"storage_template_hash_verification_enabled": "ตรวจสอบ hash ไม่ผ่าน", "storage_template_hash_verification_enabled": "ตรวจสอบ hash ไม่ผ่าน",
"storage_template_hash_verification_enabled_description": "เปิดใช้งานการตรวจสอบ hash ห้ามปิดใช้งานเว้นแต่คุณจะเข้าใจผลกระทบ", "storage_template_hash_verification_enabled_description": "เปิดใช้งานการตรวจสอบ hash ห้ามปิดใช้งานเว้นแต่คุณจะเข้าใจผลกระทบ",
"storage_template_migration": "การย้ายเทมเพลตที่เก็บข้อมูล", "storage_template_migration": "การย้ายเทมเพลตที่เก็บข้อมูล",
"storage_template_migration_description": "ใช้<link>{template}</link>ปัจจุบันกับสื่อที่อัโหลดก่อนหน้านี้", "storage_template_migration_description": "ใช้<link>{template}</link>ปัจจุบันกับสื่อที่อัโหลดก่อนหน้านี้",
"storage_template_migration_job": "", "storage_template_migration_job": "",
"storage_template_path_length": "ขีดจำกัดของความยาวพาธโดยประมาณ: <b>{length, number}</b>/{limit, number}", "storage_template_path_length": "ขีดจำกัดของความยาวพาธโดยประมาณ: <b>{length, number}</b>/{limit, number}",
"storage_template_settings": "เทมเพลตการจัดเก็บข้อมูล", "storage_template_settings": "เทมเพลตการจัดเก็บข้อมูล",
@@ -313,9 +313,6 @@
"user_delete_delay_settings_description": "จํานวนวันหลังจากที่เอาออกเพื่อลบบัญชีผู้ใช้และสื่อถาวร งานลบบัญชีผู้ใช้ทํางานทุกเที่ยงคืนเพื่อตรวจสอบผู้ใช้ที่พร้อมที่จะถูกลบข้อมูลแล้ว การตั้งค่าครั้งนี้จะมีผลครั้งต่อไป", "user_delete_delay_settings_description": "จํานวนวันหลังจากที่เอาออกเพื่อลบบัญชีผู้ใช้และสื่อถาวร งานลบบัญชีผู้ใช้ทํางานทุกเที่ยงคืนเพื่อตรวจสอบผู้ใช้ที่พร้อมที่จะถูกลบข้อมูลแล้ว การตั้งค่าครั้งนี้จะมีผลครั้งต่อไป",
"user_delete_immediately": "บัญชีและสื่อของ <b>{user}</b> จะอยู่ในคิวสำหรับการลบถาวร <b>โดยทันที</b>", "user_delete_immediately": "บัญชีและสื่อของ <b>{user}</b> จะอยู่ในคิวสำหรับการลบถาวร <b>โดยทันที</b>",
"user_settings": "การตั้งค่าผู้ใช้", "user_settings": "การตั้งค่าผู้ใช้",
"user_management": "การจัดการผู้ใช้",
"user_password_has_been_reset": "รหัสผ่านของผู้ใช้ <b>{user}</b> ถูกตั้งค่าใหม่แล้ว",
"user_password_reset_description": "รหัสผ่านของผู้ใช้จะถูกตั้งค่าใหม่และส่งไปยังอีเมลที่ลงทะเบียน",
"user_settings_description": "จัดการการตั้งค่าผู้ใช้", "user_settings_description": "จัดการการตั้งค่าผู้ใช้",
"version_check_enabled_description": "เช็ค GitHub เป็นระยะ ๆ เพื่อตรวจสอบรุ่นใหม่", "version_check_enabled_description": "เช็ค GitHub เป็นระยะ ๆ เพื่อตรวจสอบรุ่นใหม่",
"version_check_settings": "ตรวจสอบรุ่น", "version_check_settings": "ตรวจสอบรุ่น",
@@ -350,14 +347,12 @@
"allow_public_user_to_download": "อนุญาตให้ผู้ใช้สาธารณะดาวน์โหลดได้", "allow_public_user_to_download": "อนุญาตให้ผู้ใช้สาธารณะดาวน์โหลดได้",
"allow_public_user_to_upload": "อนุญาตให้ผู้ใช้สาธารณะอัปโหลดได้", "allow_public_user_to_upload": "อนุญาตให้ผู้ใช้สาธารณะอัปโหลดได้",
"anti_clockwise": "ทวนเข็มนาฬิกา", "anti_clockwise": "ทวนเข็มนาฬิกา",
"api_key": "API key", "api_key": "กุญแจ API",
"api_keys": "API Keys", "api_keys": "กุญแจ API",
"app_settings": "การตั้งค่าแอป", "app_settings": "การตั้งค่าแอป",
"appears_in": "อยู่ใน", "appears_in": "อยู่ใน",
"archive": "เก็บถาวร", "archive": "เก็บถาวร",
"archive_or_unarchive_photo": "เก็บ/ไม่เก็บภาพถาวร", "archive_or_unarchive_photo": "เก็บ/ไม่เก็บภาพถาวร",
"archive_size": "ขนาดเก็บถาวร",
"archive_size_description": "ตั้งค่าขนาดสูงสุดสำหรับการดาวน์โหลด (GiB)",
"are_these_the_same_person": "เป็นคนเดียวกันหรือไม่?", "are_these_the_same_person": "เป็นคนเดียวกันหรือไม่?",
"are_you_sure_to_do_this": "คุณแน่ใจว่าต้องการทำสิ่งนี้หรือไม่?", "are_you_sure_to_do_this": "คุณแน่ใจว่าต้องการทำสิ่งนี้หรือไม่?",
"asset_added_to_album": "เพิ่มไปยังอัลบั้มแล้ว", "asset_added_to_album": "เพิ่มไปยังอัลบั้มแล้ว",
@@ -385,19 +380,19 @@
"change_name": "เปลี่ยนชื่อ", "change_name": "เปลี่ยนชื่อ",
"change_name_successfully": "เปลี่ยนชื่อเรียบร้อยแล้ว", "change_name_successfully": "เปลี่ยนชื่อเรียบร้อยแล้ว",
"change_password": "เปลี่ยนรหัสผ่าน", "change_password": "เปลี่ยนรหัสผ่าน",
"change_your_password": "เปลี่ยนรหัสผ่านของคุณ", "change_your_password": "",
"changed_visibility_successfully": "เปลี่ยนการมองเห็นเรียบร้อยแล้ว", "changed_visibility_successfully": "",
"check_logs": "ตรวจสอบบันทึก", "check_logs": "",
"city": "เมือง", "city": "เมือง",
"clear": "ล้าง", "clear": "ล้าง",
"clear_all": "ล้างทั้งหมด", "clear_all": "",
"clear_message": "ล้างข้อความ", "clear_message": "",
"clear_value": "ล้างค่า", "clear_value": "",
"close": "ปิด", "close": "ปิด",
"collapse": "ย่อ", "collapse": "ย่อ",
"collapse_all": "ย่อทั้งหมด", "collapse_all": "ย่อทั้งหมด",
"color": "สี", "color": "สี",
"color_theme": "สีธีม", "color_theme": "",
"comment_deleted": "ลบความคิดเห็นแล้ว", "comment_deleted": "ลบความคิดเห็นแล้ว",
"comment_options": "", "comment_options": "",
"comments_and_likes": "ความคิดเห็นและการถูกใจ", "comments_and_likes": "ความคิดเห็นและการถูกใจ",
@@ -455,17 +450,13 @@
"discover": "ค้นพบ", "discover": "ค้นพบ",
"dismiss_all_errors": "ปฏิเสธข้อผิดพลาดทั้งหมด", "dismiss_all_errors": "ปฏิเสธข้อผิดพลาดทั้งหมด",
"dismiss_error": "ปฏิเสธข้อผิดพลาด", "dismiss_error": "ปฏิเสธข้อผิดพลาด",
"display_options": "ตัวเลือกการแสดง", "display_options": "",
"display_order": "ลำดับการแสดงผล", "display_order": "",
"display_original_photos": "แสดงภาพต้นฉบับ", "display_original_photos": "",
"display_original_photos_setting_description": "การตั้งค่าแสดงผลรูปภาพต้นฉบับ เมื่อเปิดรูปภาพ การตั้งค่านี้อาจจะทำให้การแสดงภาพได้ช้าลง", "display_original_photos_setting_description": "เมื่อดูสื่อให้แสดงภาพต้นฉบับแทนภาพตัวอย่างเมื่อไฟล์สื่อเปิดได้บนเว็บ อาจทําให้แสดง ภาพได้ช้าลง",
"done": "ดำเนินการสำเร็จ", "done": "เร็จ",
"download": "ดาวน์โหลด", "download": "ดาวน์โหลด",
"download_include_embedded_motion_videos": "รวมวิดีโอที่ฝังอยู่ในภาพเคลื่อนไหว",
"download_include_embedded_motion_videos_description": "รวมวิดีโอที่ฝังอยู่ในภาพเคลื่อนไหวเมื่อดาวน์โหลดอัลบั้ม",
"downloading": "กำลังดาวน์โหลด", "downloading": "กำลังดาวน์โหลด",
"download_settings": "การตั้งค่าการดาวน์โหลด",
"download_settings_description": "จัดการการตั้งค่าการดาวน์โหลด",
"duration": "ระยะเวลา", "duration": "ระยะเวลา",
"edit_album": "แก้ไขอัลบั้ม", "edit_album": "แก้ไขอัลบั้ม",
"edit_avatar": "แก้ไขตัวละคร", "edit_avatar": "แก้ไขตัวละคร",
@@ -492,38 +483,6 @@
"error": "เกิดข้อผิดพลาด", "error": "เกิดข้อผิดพลาด",
"error_loading_image": "เกิดข้อผิดพลาดระหว่างโหลดภาพ", "error_loading_image": "เกิดข้อผิดพลาดระหว่างโหลดภาพ",
"errors": { "errors": {
"cannot_navigate_next_asset": "ไม่สามารถเปลี่ยนเส้นทางได้",
"cannot_navigate_previous_asset": "ไม่สามารถเปลี่ยนเส้นทางก่อนหน้าได้",
"cant_apply_changes": "เกิดข้อผิดพลาดในการเปลี่ยนแปลง",
"cant_change_activity": "Can't {enabled, select, true {disable} other {enable}} activity",
"cant_change_asset_favorite": "ไม่สามารถเปลี่ยนสื่อที่ชื่นชอบได้",
"cant_change_metadata_assets_count": "Can't change metadata of {count, plural, one {# asset} other {# assets}}",
"cant_get_faces": "เกิดข้อผิดพลาดในการเรียกดูใบหน้า",
"cant_get_number_of_comments": "ไม่สามารถเรียกดูจำนวนความคิดเห็นได้",
"cant_search_people": "ไม่สามารถค้นหาบุคคลคนได้",
"cant_search_places": "ไม่สามารถค้นหาสถานที่ได้",
"cleared_jobs": "ล้างงาน: {job} สำเร็จ",
"error_adding_assets_to_album": "เกิดข้อผิดพลาดในการเพิ่มสื่อไปยังอัลบั้ม",
"error_adding_users_to_album": "เกิดข้อผิดพลาดในการเพิ่มผู้ใช้ไปยังอัลบั้ม",
"error_deleting_shared_user": "เกิดข้อผิดพลาดในการลบผู้ใช้ที่แชร์",
"error_downloading": "ไม่สามารถดาวน์โหลด {filename} ได้",
"error_hiding_buy_button": "Error hiding buy button",
"error_removing_assets_from_album": "เกิดข้อผิดพลาดในการลบสื่อจากอัลบั้ม",
"error_selecting_all_assets": "เกิดข้อผิดพลาดในการเลือกสื่อทั้งหมด",
"exclusion_pattern_already_exists": "ข้อยกเว้นนี้มีอยู่แล้ว",
"failed_job_command": "คำสั่ง {command} ผิดพลาด สำหรับ: {job}",
"failed_to_create_album": "ไม่สามารถสร้างอัลบั้มได้",
"failed_to_create_shared_link": "ไม่สามารถสร้างลิงก์ที่แชร์ได้",
"failed_to_edit_shared_link": "ไม่สามารถแก้ไขลิงก์ที่แชร์ได้",
"failed_to_get_people": "ไม่สามารถเรียกดูบุคคลได้",
"failed_to_keep_this_delete_others": "ไม่สามารถเก็บหรือลบได้",
"failed_to_load_asset": "ไม่สามารถโหลดสื่อได้",
"failed_to_load_assets": "ไม่สามารถโหลดสื่อได้",
"failed_to_load_people": "ไม่สามารถโหลดบุคคลได้",
"failed_to_remove_product_key": "Failed to remove product key",
"failed_to_stack_assets": "Failed to stack assets",
"failed_to_unstack_assets": "Failed to un-stack assets",
"incorrect_email_or_password": "อีเมลหรือรหัสผ่านไม่ถูกต้อง",
"import_path_already_exists": "พาธนำเข้านี้มีอยู่แล้ว", "import_path_already_exists": "พาธนำเข้านี้มีอยู่แล้ว",
"unable_to_add_album_users": "ไม่สามารถเพิ่มผู้ใช้ไปยังอัลบั้มได้", "unable_to_add_album_users": "ไม่สามารถเพิ่มผู้ใช้ไปยังอัลบั้มได้",
"unable_to_add_comment": "ไม่สามารถเพิ่มความเห็นได้", "unable_to_add_comment": "ไม่สามารถเพิ่มความเห็นได้",
@@ -531,7 +490,7 @@
"unable_to_change_album_user_role": "ไม่สามารถเปลี่ยนบทบาทผู้ใช้ในอัลบั้มได้", "unable_to_change_album_user_role": "ไม่สามารถเปลี่ยนบทบาทผู้ใช้ในอัลบั้มได้",
"unable_to_change_date": "ไม่สามารถเปลี่ยนวันที่ได้", "unable_to_change_date": "ไม่สามารถเปลี่ยนวันที่ได้",
"unable_to_change_location": "ไม่สามารถเปลี่ยนตําแหน่งได้", "unable_to_change_location": "ไม่สามารถเปลี่ยนตําแหน่งได้",
"unable_to_create_admin_account": "ไม่สามารถสร้างบัญชีผู้ดูแลระบบได้", "unable_to_create_admin_account": "",
"unable_to_create_library": "ไม่สามารถสร้างคลังภาพได้", "unable_to_create_library": "ไม่สามารถสร้างคลังภาพได้",
"unable_to_create_user": "ไม่สามารถสร้างผู้ใช้ได้", "unable_to_create_user": "ไม่สามารถสร้างผู้ใช้ได้",
"unable_to_delete_album": "ไม่สามารถลบอัลบั้มได้", "unable_to_delete_album": "ไม่สามารถลบอัลบั้มได้",
@@ -572,8 +531,8 @@
"unable_to_update_settings": "ไม่สามารถอัพเดทการตั้งค่าได้", "unable_to_update_settings": "ไม่สามารถอัพเดทการตั้งค่าได้",
"unable_to_update_user": "ไม่สามารถอัพเดทผู้ใช้ได้" "unable_to_update_user": "ไม่สามารถอัพเดทผู้ใช้ได้"
}, },
"exit_slideshow": "ออกจากการนำเสนอ", "exit_slideshow": "",
"expand_all": "ขยายทั้งหมด", "expand_all": "",
"expire_after": "หมดอายุหลังจาก", "expire_after": "หมดอายุหลังจาก",
"expired": "หมดอายุแล้ว", "expired": "หมดอายุแล้ว",
"explore": "สํารวจ", "explore": "สํารวจ",
@@ -583,25 +542,22 @@
"favorite_or_unfavorite_photo": "โปรดหรือไม่โปรดภาพ", "favorite_or_unfavorite_photo": "โปรดหรือไม่โปรดภาพ",
"favorites": "รายการโปรด", "favorites": "รายการโปรด",
"feature_photo_updated": "อัพเดทภาพเด่นแล้ว", "feature_photo_updated": "อัพเดทภาพเด่นแล้ว",
"file_name": "ชื่อไฟล์", "file_name": "",
"file_name_or_extension": "นามสกุลหรือชื่อไฟล์", "file_name_or_extension": "",
"filename": "ชื่อไฟล์", "filename": "ชื่อไฟล์",
"filetype": "ชนิดไฟล์", "filetype": "ชนิดไฟล์",
"filter_people": "กรองผู้คน", "filter_people": "กรองผู้คน",
"fix_incorrect_match": "แก้ไขการจับคู่ที่ไม่ถูกต้อง", "fix_incorrect_match": "",
"forward": "ไปข้างหน้า", "forward": "ไปข้างหน้า",
"general": "ทั่วไป", "general": "ทั่วไป",
"get_help": "ขอความช่วยเหลือ", "get_help": "",
"getting_started": "เริ่มต้นใช้งาน", "getting_started": "",
"go_back": "กลับ", "go_back": "",
"go_to_search": "กลับไปยังการค้นหา", "go_to_search": "",
"group_albums_by": "จัดกลุ่มอัลบั้มตาม", "group_albums_by": "",
"group_no": "ไม่จัดกลุ่ม", "has_quota": "",
"group_owner": "จัดกลุ่มโดยเจ้าของ",
"group_year": "จัดกลุ่มตามปี",
"has_quota": "เหลือพื้นที่",
"hide_gallery": "ซ่อนคลังภาพ", "hide_gallery": "ซ่อนคลังภาพ",
"hide_password": "ซ่อนรหัสผ่าน", "hide_password": "",
"hide_person": "ซ่อนบุคคล", "hide_person": "ซ่อนบุคคล",
"host": "โฮสต์", "host": "โฮสต์",
"hour": "ชั่วโมง", "hour": "ชั่วโมง",
@@ -698,7 +654,7 @@
"no_assets_message": "กดเพื่อใส่ภาพคุณภาพแรก", "no_assets_message": "กดเพื่อใส่ภาพคุณภาพแรก",
"no_duplicates_found": "ไม่พบรายการที่ซ้ำกัน", "no_duplicates_found": "ไม่พบรายการที่ซ้ำกัน",
"no_exif_info_available": "ไม่มีข้อมูล exif", "no_exif_info_available": "ไม่มีข้อมูล exif",
"no_explore_results_message": "ไม่พบผลลัพธ์ ลองใช้คำค้นหาอื่น ๆ", "no_explore_results_message": "",
"no_favorites_message": "เพิ่มรายการโปรดเพื่อค้นหาภาพและวิดีโอที่ดีที่สุดของคุณอย่างรวดเร็ว", "no_favorites_message": "เพิ่มรายการโปรดเพื่อค้นหาภาพและวิดีโอที่ดีที่สุดของคุณอย่างรวดเร็ว",
"no_libraries_message": "สร้างคลังภาพภายนอกเพื่อดูภาพถ่ายและวิดีโอต่าง ๆ ของคุณ", "no_libraries_message": "สร้างคลังภาพภายนอกเพื่อดูภาพถ่ายและวิดีโอต่าง ๆ ของคุณ",
"no_name": "ไม่มีชื่อ", "no_name": "ไม่มีชื่อ",
@@ -714,9 +670,9 @@
"oauth": "OAuth", "oauth": "OAuth",
"official_immich_resources": "แหล่งข้อมูล Immich อย่างเป็นทางการ", "official_immich_resources": "แหล่งข้อมูล Immich อย่างเป็นทางการ",
"offline": "ออฟไลน์", "offline": "ออฟไลน์",
"ok": "ตกลง", "ok": "โอเค",
"oldest_first": "เรียงเก่าสุดก่อน", "oldest_first": "เก่าสุดก่อน",
"onboarding_welcome_user": "ยินดีต้อนรับคุณ {user}", "onboarding_welcome_user": "ยินดีต้อนรับ {user}",
"online": "ออนไลน์", "online": "ออนไลน์",
"only_favorites": "รายการโปรดเท่านั้น", "only_favorites": "รายการโปรดเท่านั้น",
"open_in_openstreetmap": "เปิดใน OpenStreetMap", "open_in_openstreetmap": "เปิดใน OpenStreetMap",
@@ -746,9 +702,9 @@
"years": "{years, plural, one {ปี} other {# ปี}}ที่ผ่านมา" "years": "{years, plural, one {ปี} other {# ปี}}ที่ผ่านมา"
}, },
"path": "", "path": "",
"pattern": "รูปแบบ", "pattern": "",
"pause": "หยุด", "pause": "หยุด",
"pause_memories": "หยุดดูความทรงจํา", "pause_memories": "",
"paused": "หยุด", "paused": "หยุด",
"pending": "กำลังรอ", "pending": "กำลังรอ",
"people": "ผู้คน", "people": "ผู้คน",
@@ -767,7 +723,7 @@
"play_motion_photo": "เล่นภาพวัตถุเคลื่อนไหว", "play_motion_photo": "เล่นภาพวัตถุเคลื่อนไหว",
"play_or_pause_video": "เล่นหรือหยุดวิดีโอ", "play_or_pause_video": "เล่นหรือหยุดวิดีโอ",
"port": "พอร์ต", "port": "พอร์ต",
"preset": "พรีเซ็ต", "preset": "",
"preview": "ตัวอย่าง", "preview": "ตัวอย่าง",
"previous": "ก่อนหน้า", "previous": "ก่อนหน้า",
"previous_memory": "ความทรงจําก่อนหน้า", "previous_memory": "ความทรงจําก่อนหน้า",
@@ -783,65 +739,61 @@
"refreshed": "รีเฟรช", "refreshed": "รีเฟรช",
"refreshes_every_file": "รีเฟรชทุกไฟล์", "refreshes_every_file": "รีเฟรชทุกไฟล์",
"remove": "ลบ", "remove": "ลบ",
"remove_deleted_assets": "ลบสื่อที่ถูกลบ", "remove_deleted_assets": "",
"remove_from_album": "ลบออกจากอัลบั้ม", "remove_from_album": "ลบออกจากอัลบั้ม",
"remove_from_favorites": "เอาออกจากรายการโปรด", "remove_from_favorites": "เอาออกจากรายการโปรด",
"remove_from_shared_link": "ลบออกจากลิงก์ที่แชร์", "remove_from_shared_link": "ลบออกจากลิงก์ที่แชร์",
"repair": "ซ่อม", "repair": "ซ่อม",
"repair_no_results_message": "ไม่สามารถซ่อมแซมได้", "repair_no_results_message": "",
"replace_with_upload": "อัปโหลดทับรูปหรือวิดีโอนี้", "replace_with_upload": "",
"require_password": "ต้องการรหัสผ่าน", "require_password": "ต้องการรหัสผ่าน",
"reset": "รีเซ็ต", "reset": "รีเซ็ต",
"reset_password": "ตั้งค่ารหัสผ่านใหม่", "reset_password": "ตั้งค่ารหัสผ่านใหม่",
"reset_people_visibility": "ปรับการมองเห็นใหม่", "reset_people_visibility": "ปรับการมองเห็นใหม่",
"restore": "เรียกคืน", "restore": "เรียกคืน",
"restore_all": "เรียกคืนทั้งหมด",
"restore_user": "เรียกคืนผู้ใช้", "restore_user": "เรียกคืนผู้ใช้",
"retry_upload": "ลองอัโหลดใหม่", "retry_upload": "ลองอัโหลดใหม่",
"review_duplicates": "ตรวจสอบรายการที่ซ้ำกัน", "review_duplicates": "",
"role": "บทบาท", "role": "บทบาท",
"save": "บันทึก", "save": "บันทึก",
"saved_profile": "แก้ไขโปรไฟล์สำเร็จ", "saved_profile": "โพรไฟล์ที่บันทึกไว้",
"saved_settings": "บันทึกการตั้งค่าสำเร็จ", "saved_settings": "การตั้งค่าที่บันทึกไว้",
"say_something": "พูดอะไรสักอย่าง", "say_something": "พูดอะไรสักอย่าง",
"scan_all_libraries": "สแกนคลังภาพทั้งหมด", "scan_all_libraries": "สแกนคลังภาพทั้งหมด",
"scan_settings": "ตั้งค่าการสแกน", "scan_settings": "ตั้งค่าการสแกน",
"search": "ค้นหา", "search": "ค้นหา",
"search_albums": "ค้นหาอัลบั้ม", "search_albums": "",
"search_by_context": "ค้นหาตามบริบท", "search_by_context": "",
"search_camera_make": "", "search_camera_make": "",
"search_camera_model": "", "search_camera_model": "",
"search_city": "ค้นหาตามเมือง", "search_city": "",
"search_country": "ค้นหาตามประเทศ", "search_country": "",
"search_for_existing_person": "ค้นหาบุคคลที่มีอยู่", "search_for_existing_person": "",
"search_no_people": "ไม่พบบุคคลคน",
"search_no_people_named": "ไม่พบ \"{name}\"",
"search_options": "ตัวเลือกการค้นหา",
"search_people": "ค้นหาผู้คน", "search_people": "ค้นหาผู้คน",
"search_places": "ค้นหาสถานที่", "search_places": "",
"search_state": "ค้นหาตามรัฐ", "search_state": "",
"search_timezone": "ค้นหาตามวันที่และเวลา", "search_timezone": "",
"search_type": "ค้นหาตามประเภท", "search_type": "",
"search_your_photos": "ค้นหารูปภาพของคุณ", "search_your_photos": "ค้นหารูปภาพของคุณ",
"searching_locales": "ค้นหาตามภูมิภาค", "searching_locales": "",
"second": "วินาที", "second": "วินาที",
"select_album_cover": "เลือกภาพปกอัลบั้ม", "select_album_cover": "",
"select_all": "เลือกทั้งหมด", "select_all": "",
"select_avatar_color": "เลือกสีพื้นหลังของรูปโปรไฟล์", "select_avatar_color": "",
"select_face": "เลือกใบหน้า", "select_face": "",
"select_featured_photo": "เลือกภาพเด่น", "select_featured_photo": "เลือกภาพเด่น",
"select_library_owner": "เลือกเจ้าของคลังภาพ", "select_library_owner": "เลือกเจ้าของคลังภาพ",
"select_new_face": "เลือกใบหน้าใหม่", "select_new_face": "",
"select_photos": "เลือกรูปภาพ", "select_photos": "เลือกรูปภาพ",
"selected": "เลือก", "selected": "เลือก",
"send_message": "ส่งข้อความ", "send_message": "",
"server_stats": "สถิติเซิร์ฟเวอร์", "server_stats": "",
"set": "", "set": "",
"set_as_album_cover": "ตั้งเป็นภาพปกอัลบั้ม", "set_as_album_cover": "",
"set_as_profile_picture": "ตั้งเป็นรูปโปรไฟล์", "set_as_profile_picture": "",
"set_date_of_birth": "ตั้งวันเกิด", "set_date_of_birth": "",
"set_profile_picture": "ตั้งรูปโปรไฟล์", "set_profile_picture": "",
"set_slideshow_to_fullscreen": "ตั้งค่าการนำเสนอเต็มจอ", "set_slideshow_to_fullscreen": "",
"settings": "ตั้งค่า", "settings": "ตั้งค่า",
"settings_saved": "บันทึกการตั้งค่าแล้ว", "settings_saved": "บันทึกการตั้งค่าแล้ว",
"share": "แชร์", "share": "แชร์",
@@ -865,21 +817,12 @@
"show_progress_bar": "แสดงความคืบหน้า แถบ", "show_progress_bar": "แสดงความคืบหน้า แถบ",
"show_search_options": "แสดงตัวเลือกการค้นหา", "show_search_options": "แสดงตัวเลือกการค้นหา",
"shuffle": "สับเปลี่ยน", "shuffle": "สับเปลี่ยน",
"sidebar": "แถบด้านข้าง",
"sidebar_display_description": "เปิดหรือปิดแถบด้านข้าง",
"sign_out": "ออกจากระบบ",
"sign_up": "ลงทะเบียน", "sign_up": "ลงทะเบียน",
"size": "ขนาด", "size": "ขนาด",
"skip_to_content": "ข้ามไปยังเนื้อหา", "skip_to_content": "ข้ามไปยังเนื้อหา",
"slideshow": "สไลด์", "slideshow": "สไลด์",
"slideshow_settings": "ตั้งค่าสไลด์", "slideshow_settings": "ตั้งค่าสไลด์",
"sort_created": "จัดเรียงตามวันที่สร้าง", "sort_albums_by": "เรียงอัลบั้มโดย...",
"sort_items": "จัดเรียงรายการ",
"sort_modified": "จัดเรียงตามวันที่แก้ไข",
"sort_oldest": "จัดเรียงตามเก่าสุด",
"sort_people_by_similarity": "จุดเรียงบุคคลตามความคล้ายคลึง",
"sort_recent": "จัดเรียงใหม่ล่าสุด",
"sort_albums_by": "จัดเรียงอัลบั้มโดย...",
"stack": "ซ้อน", "stack": "ซ้อน",
"stack_selected_photos": "", "stack_selected_photos": "",
"stacktrace": "", "stacktrace": "",
@@ -888,30 +831,25 @@
"status": "สถานะ", "status": "สถานะ",
"stop_motion_photo": "ภาพวัตถุเคลื่อนไหว", "stop_motion_photo": "ภาพวัตถุเคลื่อนไหว",
"stop_photo_sharing": "หยุดแชร์รูปภาพ?", "stop_photo_sharing": "หยุดแชร์รูปภาพ?",
"storage": "พื้นที่จัดเก็บ", "storage": "ที่จัดเก็บ",
"storage_label": "เนื้อที่จัดเก็บ", "storage_label": "ฉลากจัดเก็บ",
"storage_usage": "ใช้ไป {used} จาก {available} ",
"submit": "ส่ง", "submit": "ส่ง",
"suggestions": "ข้อเสนอแนะ", "suggestions": "ข้อเสนอแนะ",
"sunrise_on_the_beach": "พระอาทิตย์ขึ้นบนชายหาด", "sunrise_on_the_beach": "พระอาทิตย์ขึ้นบนชายหาด",
"swap_merge_direction": "สลับด้านรวม", "swap_merge_direction": "สลับด้านรวม",
"sync": "ซิงค์", "sync": "ซิงค์",
"template": "แทมแพลค", "template": "แม่แบบ",
"theme": "ธีม", "theme": "ธีม",
"theme_selection": "การเลือกธีม", "theme_selection": "การเลือกธีม",
"theme_selection_description": "ตั้งค่าธีมให้สว่างหรือมืดโดยอัตโนมัติ อิงจากค่าของเบราว์เซอร์ของคุณ", "theme_selection_description": "ตั้งค่าธีมให้สว่างหรือมืดโดยอัตโนมัติ อิงจากค่าของเบราว์เซอร์ของคุณ",
"time_based_memories": "ความทรงจําตามเวลา", "time_based_memories": "ความทรงจําตามเวลา",
"timezone": "เขตเวลา", "timezone": "เขตเวลา",
"timeline": "Timeline",
"to_archive": "จัดเก็บถาวร",
"to_change_password": "Change password",
"toggle_settings": "สลับการตั้งค่า", "toggle_settings": "สลับการตั้งค่า",
"toggle_theme": "สลับธีม", "toggle_theme": "สลับธีม",
"total_usage": "การใช้งานรวม", "total_usage": "การใช้งานรวม",
"trash": "ถังขยะ", "trash": "ขยะ",
"trash_all": "ทิ้งทั้งหมด", "trash_all": "ทิ้งทั้งหมด",
"trash_no_results_message": "รูปภาพหรือวิดีโอที่ถูกลบจะอยู่ที่นี่", "trash_no_results_message": "รูปและวีดีโอที่ถูกทิ้งจะมาโผล่ที่นี่",
"trashed_items_will_be_permanently_deleted_after": "รายการที่ถูกลบจะถูกลบทิ้งภายใน {days, plural, one {# วัน} other {# วัน}}.",
"type": "ประเภท", "type": "ประเภท",
"unarchive": "นำออกจากที่เก็บถาวร", "unarchive": "นำออกจากที่เก็บถาวร",
"unfavorite": "นำออกจากรายการโปรด", "unfavorite": "นำออกจากรายการโปรด",
@@ -924,8 +862,8 @@
"unstack": "หยุดซ้อน", "unstack": "หยุดซ้อน",
"up_next": "ต่อไป", "up_next": "ต่อไป",
"updated_password": "รหัสผ่านเปลี่ยนแล้ว", "updated_password": "รหัสผ่านเปลี่ยนแล้ว",
"upload": "อัโหลด", "upload": "อัโหลด",
"upload_concurrency": "อัโหลดพร้อมกัน", "upload_concurrency": "อัโหลดพร้อมกัน",
"url": "URL", "url": "URL",
"usage": "การใช้งาน", "usage": "การใช้งาน",
"user": "ผู้ใช้", "user": "ผู้ใช้",
@@ -935,7 +873,7 @@
"user_usage_stats_description": "ดูสถิติการใช้งานบัญชี", "user_usage_stats_description": "ดูสถิติการใช้งานบัญชี",
"username": "ชื่อผู้ใช้", "username": "ชื่อผู้ใช้",
"users": "ผู้ใช้", "users": "ผู้ใช้",
"utilities": "เครื่องมือ", "utilities": "",
"validate": "ตรวจสอบ", "validate": "ตรวจสอบ",
"variables": "ตัวแปร", "variables": "ตัวแปร",
"version": "รุ่น", "version": "รุ่น",

View File

@@ -51,10 +51,6 @@ start_docker_compose() {
show_friendly_message() { show_friendly_message() {
local ip_address local ip_address
ip_address=$(hostname -I | awk '{print $1}') ip_address=$(hostname -I | awk '{print $1}')
# If length of ip_address is 0, then we are on a Mac
if [ ${#ip_address} -eq 0 ]; then
ip_address=$(ipconfig getifaddr en0)
fi
cat <<EOF cat <<EOF
Successfully deployed Immich! Successfully deployed Immich!
You can access the website or the mobile app at http://$ip_address:2283 You can access the website or the mobile app at http://$ip_address:2283

View File

@@ -1,6 +1,6 @@
ARG DEVICE=cpu ARG DEVICE=cpu
FROM python:3.11-bookworm@sha256:14b4620f59a90f163dfa6bd252b68743f9a41d494a9fde935f9d7669d98094bb AS builder-cpu FROM python:3.11-bookworm@sha256:adb581d8ed80edd03efd4dcad66db115b9ce8de8522b01720b9f3e6146f0884c AS builder-cpu
FROM builder-cpu AS builder-openvino FROM builder-cpu AS builder-openvino
@@ -34,7 +34,7 @@ RUN python3 -m venv /opt/venv
COPY poetry.lock pyproject.toml ./ COPY poetry.lock pyproject.toml ./
RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev RUN poetry install --sync --no-interaction --no-ansi --no-root --with ${DEVICE} --without dev
FROM python:3.11-slim-bookworm@sha256:42420f737ba91d509fc60d5ed65ed0492678a90c561e1fa08786ae8ba8b52eda AS prod-cpu FROM python:3.11-slim-bookworm@sha256:6ed5bff4d7d377e2a27d9285553b8c21cfccc4f00881de1b24c9bc8d90016e82 AS prod-cpu
FROM prod-cpu AS prod-openvino FROM prod-cpu AS prod-openvino
@@ -106,22 +106,6 @@ COPY --from=builder /opt/venv /opt/venv
COPY ann/ann.py /usr/src/ann/ann.py COPY ann/ann.py /usr/src/ann/ann.py
COPY start.sh log_conf.json gunicorn_conf.py ./ COPY start.sh log_conf.json gunicorn_conf.py ./
COPY app . COPY app .
ARG BUILD_ID
ARG BUILD_IMAGE
ARG BUILD_SOURCE_REF
ARG BUILD_SOURCE_COMMIT
ENV IMMICH_BUILD=${BUILD_ID}
ENV IMMICH_BUILD_URL=https://github.com/immich-app/immich/actions/runs/${BUILD_ID}
ENV IMMICH_BUILD_IMAGE=${BUILD_IMAGE}
ENV IMMICH_BUILD_IMAGE_URL=https://github.com/immich-app/immich/pkgs/container/immich-machine-learning
ENV IMMICH_REPOSITORY=immich-app/immich
ENV IMMICH_REPOSITORY_URL=https://github.com/immich-app/immich
ENV IMMICH_SOURCE_REF=${BUILD_SOURCE_REF}
ENV IMMICH_SOURCE_COMMIT=${BUILD_SOURCE_COMMIT}
ENV IMMICH_SOURCE_URL=https://github.com/immich-app/immich/commit/${BUILD_SOURCE_COMMIT}
ENTRYPOINT ["tini", "--"] ENTRYPOINT ["tini", "--"]
CMD ["./start.sh"] CMD ["./start.sh"]

View File

@@ -758,23 +758,23 @@ test = ["pytest (>=6)"]
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.115.8" version = "0.115.6"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "fastapi-0.115.8-py3-none-any.whl", hash = "sha256:753a96dd7e036b34eeef8babdfcfe3f28ff79648f86551eb36bfc1b0bf4a8cbf"}, {file = "fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305"},
{file = "fastapi-0.115.8.tar.gz", hash = "sha256:0ce9111231720190473e222cdf0f07f7206ad7e53ea02beb1d2dc36e2f0741e9"}, {file = "fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654"},
] ]
[package.dependencies] [package.dependencies]
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
starlette = ">=0.40.0,<0.46.0" starlette = ">=0.40.0,<0.42.0"
typing-extensions = ">=4.8.0" typing-extensions = ">=4.8.0"
[package.extras] [package.extras]
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"]
[[package]] [[package]]
name = "filelock" name = "filelock"
@@ -1331,13 +1331,13 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "huggingface-hub" name = "huggingface-hub"
version = "0.28.1" version = "0.27.1"
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
optional = false optional = false
python-versions = ">=3.8.0" python-versions = ">=3.8.0"
files = [ files = [
{file = "huggingface_hub-0.28.1-py3-none-any.whl", hash = "sha256:aa6b9a3ffdae939b72c464dbb0d7f99f56e649b55c3d52406f49e0a5a620c0a7"}, {file = "huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec"},
{file = "huggingface_hub-0.28.1.tar.gz", hash = "sha256:893471090c98e3b6efbdfdacafe4052b20b84d59866fb6f54c33d9af18c303ae"}, {file = "huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b"},
] ]
[package.dependencies] [package.dependencies]
@@ -1350,13 +1350,13 @@ tqdm = ">=4.42.1"
typing-extensions = ">=3.7.4.3" typing-extensions = ">=3.7.4.3"
[package.extras] [package.extras]
all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
cli = ["InquirerPy (==0.3.4)"] cli = ["InquirerPy (==0.3.4)"]
dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
hf-transfer = ["hf-transfer (>=0.1.4)"] hf-transfer = ["hf-transfer (>=0.1.4)"]
inference = ["aiohttp"] inference = ["aiohttp"]
quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.9.0)"] quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.5.0)"]
tensorflow = ["graphviz", "pydot", "tensorflow"] tensorflow = ["graphviz", "pydot", "tensorflow"]
tensorflow-testing = ["keras (<3.0)", "tensorflow"] tensorflow-testing = ["keras (<3.0)", "tensorflow"]
testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
@@ -1625,13 +1625,13 @@ test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"]
[[package]] [[package]]
name = "locust" name = "locust"
version = "2.32.9" version = "2.32.6"
description = "Developer-friendly load testing framework" description = "Developer-friendly load testing framework"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "locust-2.32.9-py3-none-any.whl", hash = "sha256:d9447c26d2bbaec5a0ace7cadefa1a31820ed392234257b309965a43d5e8d26f"}, {file = "locust-2.32.6-py3-none-any.whl", hash = "sha256:d5c0e4f73134415d250087034431cf3ea42ca695d3dee7f10812287cacb6c4ef"},
{file = "locust-2.32.9.tar.gz", hash = "sha256:4c297afa5cdc3de15dfa79279576e5f33c1d69dd70006b51d079dcbd212201cc"}, {file = "locust-2.32.6.tar.gz", hash = "sha256:6600cc308398e724764aacc56ccddf6cfcd0127c4c92dedd5c4979dd37ef5b15"},
] ]
[package.dependencies] [package.dependencies]
@@ -1649,8 +1649,8 @@ psutil = ">=5.9.1"
pywin32 = {version = "*", markers = "sys_platform == \"win32\""} pywin32 = {version = "*", markers = "sys_platform == \"win32\""}
pyzmq = ">=25.0.0" pyzmq = ">=25.0.0"
requests = [ requests = [
{version = ">=2.26.0", markers = "python_full_version <= \"3.11.0\""},
{version = ">=2.32.2", markers = "python_full_version > \"3.11.0\""}, {version = ">=2.32.2", markers = "python_full_version > \"3.11.0\""},
{version = ">=2.26.0", markers = "python_full_version <= \"3.11.0\""},
] ]
setuptools = ">=70.0.0" setuptools = ">=70.0.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
@@ -1893,43 +1893,49 @@ files = [
[[package]] [[package]]
name = "mypy" name = "mypy"
version = "1.15.0" version = "1.14.1"
description = "Optional static typing for Python" description = "Optional static typing for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.8"
files = [ files = [
{file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"},
{file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"},
{file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"},
{file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"},
{file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"},
{file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"},
{file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"},
{file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"},
{file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"},
{file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"},
{file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"},
{file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"},
{file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"},
{file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"},
{file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"},
{file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"},
{file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"},
{file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"},
{file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"},
{file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"},
{file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"},
{file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"},
{file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"},
{file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"},
{file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"},
{file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"},
{file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"},
{file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"},
{file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"},
{file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"},
{file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"},
{file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"},
{file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"},
{file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"},
{file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"},
{file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"},
{file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"},
{file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"},
] ]
[package.dependencies] [package.dependencies]
@@ -2175,98 +2181,94 @@ files = [
[package.dependencies] [package.dependencies]
numpy = [ numpy = [
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
{version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, {version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""}, {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
{version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""}, {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
{version = ">=1.26.0", markers = "python_version >= \"3.12\""},
] ]
[[package]] [[package]]
name = "orjson" name = "orjson"
version = "3.10.15" version = "3.10.14"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04"}, {file = "orjson-3.10.14-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:849ea7845a55f09965826e816cdc7689d6cf74fe9223d79d758c714af955bcb6"},
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8"}, {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5947b139dfa33f72eecc63f17e45230a97e741942955a6c9e650069305eb73d"},
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c2c79fa308e6edb0ffab0a31fd75a7841bf2a79a20ef08a3c6e3b26814c8ca8"}, {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cde6d76910d3179dae70f164466692f4ea36da124d6fb1a61399ca589e81d69a"},
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cb85490aa6bf98abd20607ab5c8324c0acb48d6da7863a51be48505646c814"}, {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6dfbaeb7afa77ca608a50e2770a0461177b63a99520d4928e27591b142c74b1"},
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763dadac05e4e9d2bc14938a45a2d0560549561287d41c465d3c58aec818b164"}, {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa45e489ef80f28ff0e5ba0a72812b8cfc7c1ef8b46a694723807d1b07c89ebb"},
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a330b9b4734f09a623f74a7490db713695e13b67c959713b78369f26b3dee6bf"}, {file = "orjson-3.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5007abfdbb1d866e2aa8990bd1c465f0f6da71d19e695fc278282be12cffa5"},
{file = "orjson-3.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a61a4622b7ff861f019974f73d8165be1bd9a0855e1cad18ee167acacabeb061"}, {file = "orjson-3.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1b49e2af011c84c3f2d541bb5cd1e3c7c2df672223e7e3ea608f09cf295e5f8a"},
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd271247691574416b3228db667b84775c497b245fa275c6ab90dc1ffbbd2b3"}, {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:164ac155109226b3a2606ee6dda899ccfbe6e7e18b5bdc3fbc00f79cc074157d"},
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4759b109c37f635aa5c5cc93a1b26927bfde24b254bcc0e1149a9fada253d2d"}, {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6b1225024cf0ef5d15934b5ffe9baf860fe8bc68a796513f5ea4f5056de30bca"},
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e992fd5cfb8b9f00bfad2fd7a05a4299db2bbe92e6440d9dd2fab27655b3182"}, {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d6546e8073dc382e60fcae4a001a5a1bc46da5eab4a4878acc2d12072d6166d5"},
{file = "orjson-3.10.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f95fb363d79366af56c3f26b71df40b9a583b07bbaaf5b317407c4d58497852e"}, {file = "orjson-3.10.14-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f1d2942605c894162252d6259b0121bf1cb493071a1ea8cb35d79cb3e6ac5bc"},
{file = "orjson-3.10.15-cp310-cp310-win32.whl", hash = "sha256:f9875f5fea7492da8ec2444839dcc439b0ef298978f311103d0b7dfd775898ab"}, {file = "orjson-3.10.14-cp310-cp310-win32.whl", hash = "sha256:397083806abd51cf2b3bbbf6c347575374d160331a2d33c5823e22249ad3118b"},
{file = "orjson-3.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:17085a6aa91e1cd70ca8533989a18b5433e15d29c574582f76f821737c8d5806"}, {file = "orjson-3.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:fa18f949d3183a8d468367056be989666ac2bef3a72eece0bade9cdb733b3c28"},
{file = "orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6"}, {file = "orjson-3.10.14-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f506fd666dd1ecd15a832bebc66c4df45c1902fd47526292836c339f7ba665a9"},
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef"}, {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efe5fd254cfb0eeee13b8ef7ecb20f5d5a56ddda8a587f3852ab2cedfefdb5f6"},
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334"}, {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ddc8c866d7467f5ee2991397d2ea94bcf60d0048bdd8ca555740b56f9042725"},
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d"}, {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af8e42ae4363773658b8d578d56dedffb4f05ceeb4d1d4dd3fb504950b45526"},
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0"}, {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84dd83110503bc10e94322bf3ffab8bc49150176b49b4984dc1cce4c0a993bf9"},
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13"}, {file = "orjson-3.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36f5bfc0399cd4811bf10ec7a759c7ab0cd18080956af8ee138097d5b5296a95"},
{file = "orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5"}, {file = "orjson-3.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868943660fb2a1e6b6b965b74430c16a79320b665b28dd4511d15ad5038d37d5"},
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b"}, {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33449c67195969b1a677533dee9d76e006001213a24501333624623e13c7cc8e"},
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399"}, {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4c9f60f9fb0b5be66e416dcd8c9d94c3eabff3801d875bdb1f8ffc12cf86905"},
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388"}, {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0de4d6315cfdbd9ec803b945c23b3a68207fd47cbe43626036d97e8e9561a436"},
{file = "orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c"}, {file = "orjson-3.10.14-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83adda3db595cb1a7e2237029b3249c85afbe5c747d26b41b802e7482cb3933e"},
{file = "orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e"}, {file = "orjson-3.10.14-cp311-cp311-win32.whl", hash = "sha256:998019ef74a4997a9d741b1473533cdb8faa31373afc9849b35129b4b8ec048d"},
{file = "orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e"}, {file = "orjson-3.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:9d034abdd36f0f0f2240f91492684e5043d46f290525d1117712d5b8137784eb"},
{file = "orjson-3.10.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d11c0714fc85bfcf36ada1179400862da3288fc785c30e8297844c867d7505a"}, {file = "orjson-3.10.14-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2ad4b7e367efba6dc3f119c9a0fcd41908b7ec0399a696f3cdea7ec477441b09"},
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dba5a1e85d554e3897fa9fe6fbcff2ed32d55008973ec9a2b992bd9a65d2352d"}, {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f496286fc85e93ce0f71cc84fc1c42de2decf1bf494094e188e27a53694777a7"},
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7723ad949a0ea502df656948ddd8b392780a5beaa4c3b5f97e525191b102fff0"}, {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7f189bbfcded40e41a6969c1068ba305850ba016665be71a217918931416fbf"},
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6fd9bc64421e9fe9bd88039e7ce8e58d4fead67ca88e3a4014b143cec7684fd4"}, {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cc8204f0b75606869c707da331058ddf085de29558b516fc43c73ee5ee2aadb"},
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dadba0e7b6594216c214ef7894c4bd5f08d7c0135f4dd0145600be4fbcc16767"}, {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:deaa2899dff7f03ab667e2ec25842d233e2a6a9e333efa484dfe666403f3501c"},
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f59114fe318f33bbaee8ebeda696d8ccc94c9e90bc27dbe72153094e26f41"}, {file = "orjson-3.10.14-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1c3ea52642c9714dc6e56de8a451a066f6d2707d273e07fe8a9cc1ba073813d"},
{file = "orjson-3.10.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:035fb83585e0f15e076759b6fedaf0abb460d1765b6a36f48018a52858443514"}, {file = "orjson-3.10.14-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d3f9ed72e7458ded9a1fb1b4d4ed4c4fdbaf82030ce3f9274b4dc1bff7ace2b"},
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d13b7fe322d75bf84464b075eafd8e7dd9eae05649aa2a5354cfa32f43c59f17"}, {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:07520685d408a2aba514c17ccc16199ff2934f9f9e28501e676c557f454a37fe"},
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7066b74f9f259849629e0d04db6609db4cf5b973248f455ba5d3bd58a4daaa5b"}, {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:76344269b550ea01488d19a2a369ab572c1ac4449a72e9f6ac0d70eb1cbfb953"},
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88dc3f65a026bd3175eb157fea994fca6ac7c4c8579fc5a86fc2114ad05705b7"}, {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e2979d0f2959990620f7e62da6cd954e4620ee815539bc57a8ae46e2dacf90e3"},
{file = "orjson-3.10.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b342567e5465bd99faa559507fe45e33fc76b9fb868a63f1642c6bc0735ad02a"}, {file = "orjson-3.10.14-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03f61ca3674555adcb1aa717b9fc87ae936aa7a63f6aba90a474a88701278780"},
{file = "orjson-3.10.15-cp312-cp312-win32.whl", hash = "sha256:0a4f27ea5617828e6b58922fdbec67b0aa4bb844e2d363b9244c47fa2180e665"}, {file = "orjson-3.10.14-cp312-cp312-win32.whl", hash = "sha256:d5075c54edf1d6ad81d4c6523ce54a748ba1208b542e54b97d8a882ecd810fd1"},
{file = "orjson-3.10.15-cp312-cp312-win_amd64.whl", hash = "sha256:ef5b87e7aa9545ddadd2309efe6824bd3dd64ac101c15dae0f2f597911d46eaa"}, {file = "orjson-3.10.14-cp312-cp312-win_amd64.whl", hash = "sha256:175cafd322e458603e8ce73510a068d16b6e6f389c13f69bf16de0e843d7d406"},
{file = "orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6"}, {file = "orjson-3.10.14-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:0905ca08a10f7e0e0c97d11359609300eb1437490a7f32bbaa349de757e2e0c7"},
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a"}, {file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92d13292249f9f2a3e418cbc307a9fbbef043c65f4bd8ba1eb620bc2aaba3d15"},
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9"}, {file = "orjson-3.10.14-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90937664e776ad316d64251e2fa2ad69265e4443067668e4727074fe39676414"},
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0"}, {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9ed3d26c4cb4f6babaf791aa46a029265850e80ec2a566581f5c2ee1a14df4f1"},
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307"}, {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:56ee546c2bbe9599aba78169f99d1dc33301853e897dbaf642d654248280dc6e"},
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e"}, {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:901e826cb2f1bdc1fcef3ef59adf0c451e8f7c0b5deb26c1a933fb66fb505eae"},
{file = "orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7"}, {file = "orjson-3.10.14-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26336c0d4b2d44636e1e1e6ed1002f03c6aae4a8a9329561c8883f135e9ff010"},
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8"}, {file = "orjson-3.10.14-cp313-cp313-win32.whl", hash = "sha256:e2bc525e335a8545c4e48f84dd0328bc46158c9aaeb8a1c2276546e94540ea3d"},
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca"}, {file = "orjson-3.10.14-cp313-cp313-win_amd64.whl", hash = "sha256:eca04dfd792cedad53dc9a917da1a522486255360cb4e77619343a20d9f35364"},
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561"}, {file = "orjson-3.10.14-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a0fba3b8a587a54c18585f077dcab6dd251c170d85cfa4d063d5746cd595a0f"},
{file = "orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825"}, {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:175abf3d20e737fec47261d278f95031736a49d7832a09ab684026528c4d96db"},
{file = "orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890"}, {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29ca1a93e035d570e8b791b6c0feddd403c6a5388bfe870bf2aa6bba1b9d9b8e"},
{file = "orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf"}, {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f77202c80e8ab5a1d1e9faf642343bee5aaf332061e1ada4e9147dbd9eb00c46"},
{file = "orjson-3.10.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5e8afd6200e12771467a1a44e5ad780614b86abb4b11862ec54861a82d677746"}, {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e2ec73b7099b6a29b40a62e08a23b936423bd35529f8f55c42e27acccde7954"},
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da9a18c500f19273e9e104cca8c1f0b40a6470bcccfc33afcc088045d0bf5ea6"}, {file = "orjson-3.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2d1679df9f9cd9504f8dff24555c1eaabba8aad7f5914f28dab99e3c2552c9d"},
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb00b7bfbdf5d34a13180e4805d76b4567025da19a197645ca746fc2fb536586"}, {file = "orjson-3.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691ab9a13834310a263664313e4f747ceb93662d14a8bdf20eb97d27ed488f16"},
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:33aedc3d903378e257047fee506f11e0833146ca3e57a1a1fb0ddb789876c1e1"}, {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b11ed82054fce82fb74cea33247d825d05ad6a4015ecfc02af5fbce442fbf361"},
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd0099ae6aed5eb1fc84c9eb72b95505a3df4267e6962eb93cdd5af03be71c98"}, {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:e70a1d62b8288677d48f3bea66c21586a5f999c64ecd3878edb7393e8d1b548d"},
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c864a80a2d467d7786274fce0e4f93ef2a7ca4ff31f7fc5634225aaa4e9e98c"}, {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:16642f10c1ca5611251bd835de9914a4b03095e28a34c8ba6a5500b5074338bd"},
{file = "orjson-3.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c25774c9e88a3e0013d7d1a6c8056926b607a61edd423b50eb5c88fd7f2823ae"}, {file = "orjson-3.10.14-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3871bad546aa66c155e3f36f99c459780c2a392d502a64e23fb96d9abf338511"},
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e78c211d0074e783d824ce7bb85bf459f93a233eb67a5b5003498232ddfb0e8a"}, {file = "orjson-3.10.14-cp38-cp38-win32.whl", hash = "sha256:0293a88815e9bb5c90af4045f81ed364d982f955d12052d989d844d6c4e50945"},
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:43e17289ffdbbac8f39243916c893d2ae41a2ea1a9cbb060a56a4d75286351ae"}, {file = "orjson-3.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:6169d3868b190d6b21adc8e61f64e3db30f50559dfbdef34a1cd6c738d409dfc"},
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:781d54657063f361e89714293c095f506c533582ee40a426cb6489c48a637b81"}, {file = "orjson-3.10.14-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:06d4ec218b1ec1467d8d64da4e123b4794c781b536203c309ca0f52819a16c03"},
{file = "orjson-3.10.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6875210307d36c94873f553786a808af2788e362bd0cf4c8e66d976791e7b528"}, {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962c2ec0dcaf22b76dee9831fdf0c4a33d4bf9a257a2bc5d4adc00d5c8ad9034"},
{file = "orjson-3.10.15-cp38-cp38-win32.whl", hash = "sha256:305b38b2b8f8083cc3d618927d7f424349afce5975b316d33075ef0f73576b60"}, {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:21d3be4132f71ef1360385770474f29ea1538a242eef72ac4934fe142800e37f"},
{file = "orjson-3.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:5dd9ef1639878cc3efffed349543cbf9372bdbd79f478615a1c633fe4e4180d1"}, {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28ed60597c149a9e3f5ad6dd9cebaee6fb2f0e3f2d159a4a2b9b862d4748860"},
{file = "orjson-3.10.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ffe19f3e8d68111e8644d4f4e267a069ca427926855582ff01fc012496d19969"}, {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e947f70167fe18469f2023644e91ab3d24f9aed69a5e1c78e2c81b9cea553fb"},
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d433bf32a363823863a96561a555227c18a522a8217a6f9400f00ddc70139ae2"}, {file = "orjson-3.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64410696c97a35af2432dea7bdc4ce32416458159430ef1b4beb79fd30093ad6"},
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:da03392674f59a95d03fa5fb9fe3a160b0511ad84b7a3914699ea5a1b3a38da2"}, {file = "orjson-3.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8050a5d81c022561ee29cd2739de5b4445f3c72f39423fde80a63299c1892c52"},
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a63bb41559b05360ded9132032239e47983a39b151af1201f07ec9370715c82"}, {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b49a28e30d3eca86db3fe6f9b7f4152fcacbb4a467953cd1b42b94b479b77956"},
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3766ac4702f8f795ff3fa067968e806b4344af257011858cc3d6d8721588b53f"}, {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ca041ad20291a65d853a9523744eebc3f5a4b2f7634e99f8fe88320695ddf766"},
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a1c73dcc8fadbd7c55802d9aa093b36878d34a3b3222c41052ce6b0fc65f8e8"}, {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d313a2998b74bb26e9e371851a173a9b9474764916f1fc7971095699b3c6e964"},
{file = "orjson-3.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b299383825eafe642cbab34be762ccff9fd3408d72726a6b2a4506d410a71ab3"}, {file = "orjson-3.10.14-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7796692136a67b3e301ef9052bde6fe8e7bd5200da766811a3a608ffa62aaff0"},
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:abc7abecdbf67a173ef1316036ebbf54ce400ef2300b4e26a7b843bd446c2480"}, {file = "orjson-3.10.14-cp39-cp39-win32.whl", hash = "sha256:eee4bc767f348fba485ed9dc576ca58b0a9eac237f0e160f7a59bce628ed06b3"},
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:3614ea508d522a621384c1d6639016a5a2e4f027f3e4a1c93a51867615d28829"}, {file = "orjson-3.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:96a1c0ee30fb113b3ae3c748fd75ca74a157ff4c58476c47db4d61518962a011"},
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:295c70f9dc154307777ba30fe29ff15c1bcc9dfc5c48632f37d20a607e9ba85a"}, {file = "orjson-3.10.14.tar.gz", hash = "sha256:cf31f6f071a6b8e7aa1ead1fa27b935b48d00fbfa6a28ce856cfff2d5dd68eed"},
{file = "orjson-3.10.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:63309e3ff924c62404923c80b9e2048c1f74ba4b615e7584584389ada50ed428"},
{file = "orjson-3.10.15-cp39-cp39-win32.whl", hash = "sha256:a2f708c62d026fb5340788ba94a55c23df4e1869fec74be455e0b2f5363b8507"},
{file = "orjson-3.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:efcf6c735c3d22ef60c4aa27a5238f1a477df85e9b15f2142f9d669beb2d13fd"},
{file = "orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e"},
] ]
[[package]] [[package]]
@@ -2496,13 +2498,13 @@ files = [
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.10.6" version = "2.10.5"
description = "Data validation using Python type hints" description = "Data validation using Python type hints"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"},
{file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"},
] ]
[package.dependencies] [package.dependencies]
@@ -2710,13 +2712,13 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
[[package]] [[package]]
name = "pytest-asyncio" name = "pytest-asyncio"
version = "0.25.3" version = "0.25.2"
description = "Pytest support for asyncio" description = "Pytest support for asyncio"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"}, {file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"},
{file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"}, {file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"},
] ]
[package.dependencies] [package.dependencies]
@@ -3047,29 +3049,29 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.9.6" version = "0.9.2"
description = "An extremely fast Python linter and code formatter, written in Rust." description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"}, {file = "ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347"},
{file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"}, {file = "ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00"},
{file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"}, {file = "ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df"},
{file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"}, {file = "ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"}, {file = "ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"}, {file = "ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"}, {file = "ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb"},
{file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"}, {file = "ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a"},
{file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"}, {file = "ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145"},
{file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"}, {file = "ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5"},
{file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"}, {file = "ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6"},
{file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"}, {file = "ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0"},
] ]
[[package]] [[package]]

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "machine-learning" name = "machine-learning"
version = "1.126.1" version = "1.125.6"
description = "" description = ""
authors = ["Hau Tran <alex.tran1502@gmail.com>"] authors = ["Hau Tran <alex.tran1502@gmail.com>"]
readme = "README.md" readme = "README.md"

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env sh #!/usr/bin/env sh
echo "Initializing Immich ML $IMMICH_SOURCE_REF"
lib_path="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2" lib_path="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2"
# mimalloc seems to increase memory usage dramatically with openvino, need to investigate # mimalloc seems to increase memory usage dramatically with openvino, need to investigate
if ! [ "$DEVICE" = "openvino" ]; then if ! [ "$DEVICE" = "openvino" ]; then

View File

@@ -35,8 +35,8 @@ platform :android do
task: 'bundle', task: 'bundle',
build_type: 'Release', build_type: 'Release',
properties: { properties: {
"android.injected.version.code" => 184, "android.injected.version.code" => 182,
"android.injected.version.name" => "1.126.1", "android.injected.version.name" => "1.125.6",
} }
) )
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')

View File

@@ -1,10 +1,4 @@
{ {
"search_filter_contextual": "Search by context",
"search_filter_filename": "Search by file name",
"search_filter_description": "Search by description",
"search_no_result": "No results found, try a different search term or combination",
"description_search": "Hiking day in Sapa",
"search_no_more_result": "No more results",
"action_common_back": "Back", "action_common_back": "Back",
"action_common_cancel": "Cancel", "action_common_cancel": "Cancel",
"action_common_clear": "Clear", "action_common_clear": "Clear",
@@ -288,9 +282,9 @@
"header_settings_field_validator_msg": "Value cannot be empty", "header_settings_field_validator_msg": "Value cannot be empty",
"header_settings_header_name_input": "Header name", "header_settings_header_name_input": "Header name",
"header_settings_header_value_input": "Header value", "header_settings_header_value_input": "Header value",
"header_settings_page_title": "Proxy Headers", "header_settings_page_title": "Proxy Headers (EXPERIMENTAL)",
"headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request",
"headers_settings_tile_title": "Custom proxy headers (EXPERIMENTAL)", "headers_settings_tile_title": "Custom proxy headers",
"home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.", "home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.",
"home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping", "home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping",
"home_page_add_to_album_success": "Added {added} assets to album {album}.", "home_page_add_to_album_success": "Added {added} assets to album {album}.",
@@ -482,7 +476,6 @@
"search_filter_media_type_video": "Video", "search_filter_media_type_video": "Video",
"search_filter_people": "People", "search_filter_people": "People",
"search_filter_people_title": "Select people", "search_filter_people_title": "Select people",
"search_filter_people_hint": "Filter people",
"search_page_categories": "Categories", "search_page_categories": "Categories",
"search_page_favorites": "Favorites", "search_page_favorites": "Favorites",
"search_page_motion_photos": "Motion Photos", "search_page_motion_photos": "Motion Photos",

View File

@@ -541,7 +541,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 = 194; CURRENT_PROJECT_VERSION = 190;
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 +685,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 = 194; CURRENT_PROJECT_VERSION = 190;
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 +715,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 = 194; CURRENT_PROJECT_VERSION = 190;
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 +748,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 = 194; CURRENT_PROJECT_VERSION = 190;
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;
@@ -791,7 +791,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 = 194; CURRENT_PROJECT_VERSION = 190;
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;
@@ -831,7 +831,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 = 194; CURRENT_PROJECT_VERSION = 190;
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;

View File

@@ -78,7 +78,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.126.1</string> <string>1.125.2</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>194</string> <string>190</string>
<key>FLTEnableImpeller</key> <key>FLTEnableImpeller</key>
<true/> <true/>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@@ -19,7 +19,7 @@ platform :ios do
desc "iOS Release" desc "iOS Release"
lane :release do lane :release do
increment_version_number( increment_version_number(
version_number: "1.126.1" version_number: "1.125.6"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@@ -2,9 +2,3 @@ enum SortOrder {
asc, asc,
desc, desc,
} }
enum TextSearchType {
context,
filename,
description,
}

View File

@@ -545,13 +545,19 @@ enum AssetType {
} }
extension AssetTypeEnumHelper on AssetTypeEnum { extension AssetTypeEnumHelper on AssetTypeEnum {
AssetType toAssetType() => switch (this) { AssetType toAssetType() {
AssetTypeEnum.IMAGE => AssetType.image, switch (this) {
AssetTypeEnum.VIDEO => AssetType.video, case AssetTypeEnum.IMAGE:
AssetTypeEnum.AUDIO => AssetType.audio, return AssetType.image;
AssetTypeEnum.OTHER => AssetType.other, case AssetTypeEnum.VIDEO:
_ => throw Exception(), return AssetType.video;
}; case AssetTypeEnum.AUDIO:
return AssetType.audio;
case AssetTypeEnum.OTHER:
return AssetType.other;
}
throw Exception();
}
} }
/// Describes where the information of this asset came from: /// Describes where the information of this asset came from:

View File

@@ -96,16 +96,25 @@ class StoreValue {
int? intValue; int? intValue;
String? strValue; String? strValue;
T? _extract<T>(StoreKey<T> key) => switch (key.type) { T? _extract<T>(StoreKey<T> key) {
const (int) => intValue as T?, switch (key.type) {
const (bool) => intValue == null ? null : (intValue! == 1) as T, case const (int):
const (DateTime) => intValue == null return intValue as T?;
case const (bool):
return intValue == null ? null : (intValue! == 1) as T;
case const (DateTime):
return intValue == null
? null ? null
: DateTime.fromMicrosecondsSinceEpoch(intValue!) as T, : DateTime.fromMicrosecondsSinceEpoch(intValue!) as T;
const (String) => strValue as T?, case const (String):
_ when key.fromDb != null => key.fromDb!.call(Store._db, intValue!), return strValue as T?;
_ => throw TypeError(), default:
}; if (key.fromDb != null) {
return key.fromDb!.call(Store._db, intValue!);
}
}
throw TypeError();
}
static Future<StoreValue> _of<T>(T? value, StoreKey<T> key) async { static Future<StoreValue> _of<T>(T? value, StoreKey<T> key) async {
int? i; int? i;

View File

@@ -149,33 +149,56 @@ enum AvatarColorEnum {
} }
extension AvatarColorEnumHelper on UserAvatarColor { extension AvatarColorEnumHelper on UserAvatarColor {
AvatarColorEnum toAvatarColor() => switch (this) { AvatarColorEnum toAvatarColor() {
UserAvatarColor.primary => AvatarColorEnum.primary, switch (this) {
UserAvatarColor.pink => AvatarColorEnum.pink, case UserAvatarColor.primary:
UserAvatarColor.red => AvatarColorEnum.red, return AvatarColorEnum.primary;
UserAvatarColor.yellow => AvatarColorEnum.yellow, case UserAvatarColor.pink:
UserAvatarColor.blue => AvatarColorEnum.blue, return AvatarColorEnum.pink;
UserAvatarColor.green => AvatarColorEnum.green, case UserAvatarColor.red:
UserAvatarColor.purple => AvatarColorEnum.purple, return AvatarColorEnum.red;
UserAvatarColor.orange => AvatarColorEnum.orange, case UserAvatarColor.yellow:
UserAvatarColor.gray => AvatarColorEnum.gray, return AvatarColorEnum.yellow;
UserAvatarColor.amber => AvatarColorEnum.amber, case UserAvatarColor.blue:
_ => AvatarColorEnum.primary, return AvatarColorEnum.blue;
}; case UserAvatarColor.green:
return AvatarColorEnum.green;
case UserAvatarColor.purple:
return AvatarColorEnum.purple;
case UserAvatarColor.orange:
return AvatarColorEnum.orange;
case UserAvatarColor.gray:
return AvatarColorEnum.gray;
case UserAvatarColor.amber:
return AvatarColorEnum.amber;
}
return AvatarColorEnum.primary;
}
} }
extension AvatarColorToColorHelper on AvatarColorEnum { extension AvatarColorToColorHelper on AvatarColorEnum {
Color toColor([bool isDarkTheme = false]) => switch (this) { Color toColor([bool isDarkTheme = false]) {
AvatarColorEnum.primary => switch (this) {
isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF), case AvatarColorEnum.primary:
AvatarColorEnum.pink => const Color.fromARGB(255, 244, 114, 182), return isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF);
AvatarColorEnum.red => const Color.fromARGB(255, 239, 68, 68), case AvatarColorEnum.pink:
AvatarColorEnum.yellow => const Color.fromARGB(255, 234, 179, 8), return const Color.fromARGB(255, 244, 114, 182);
AvatarColorEnum.blue => const Color.fromARGB(255, 59, 130, 246), case AvatarColorEnum.red:
AvatarColorEnum.green => const Color.fromARGB(255, 22, 163, 74), return const Color.fromARGB(255, 239, 68, 68);
AvatarColorEnum.purple => const Color.fromARGB(255, 147, 51, 234), case AvatarColorEnum.yellow:
AvatarColorEnum.orange => const Color.fromARGB(255, 234, 88, 12), return const Color.fromARGB(255, 234, 179, 8);
AvatarColorEnum.gray => const Color.fromARGB(255, 75, 85, 99), case AvatarColorEnum.blue:
AvatarColorEnum.amber => const Color.fromARGB(255, 217, 119, 6), return const Color.fromARGB(255, 59, 130, 246);
}; case AvatarColorEnum.green:
return const Color.fromARGB(255, 22, 163, 74);
case AvatarColorEnum.purple:
return const Color.fromARGB(255, 147, 51, 234);
case AvatarColorEnum.orange:
return const Color.fromARGB(255, 234, 88, 12);
case AvatarColorEnum.gray:
return const Color.fromARGB(255, 75, 85, 99);
case AvatarColorEnum.amber:
return const Color.fromARGB(255, 217, 119, 6);
}
}
} }

View File

@@ -1,6 +1,3 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';
abstract interface class IPersonApiRepository { abstract interface class IPersonApiRepository {
Future<List<Person>> getAll(); Future<List<Person>> getAll();
Future<Person> update(String id, {String? name}); Future<Person> update(String id, {String? name});
@@ -9,10 +6,10 @@ abstract interface class IPersonApiRepository {
class Person { class Person {
Person({ Person({
required this.id, required this.id,
this.birthDate,
required this.isHidden, required this.isHidden,
required this.name, required this.name,
required this.thumbnailPath, required this.thumbnailPath,
this.birthDate,
this.updatedAt, this.updatedAt,
}); });
@@ -22,80 +19,4 @@ class Person {
final String name; final String name;
final String thumbnailPath; final String thumbnailPath;
final DateTime? updatedAt; final DateTime? updatedAt;
@override
String toString() {
return 'Person(id: $id, birthDate: $birthDate, isHidden: $isHidden, name: $name, thumbnailPath: $thumbnailPath, updatedAt: $updatedAt)';
}
Person copyWith({
String? id,
DateTime? birthDate,
bool? isHidden,
String? name,
String? thumbnailPath,
DateTime? updatedAt,
}) {
return Person(
id: id ?? this.id,
birthDate: birthDate ?? this.birthDate,
isHidden: isHidden ?? this.isHidden,
name: name ?? this.name,
thumbnailPath: thumbnailPath ?? this.thumbnailPath,
updatedAt: updatedAt ?? this.updatedAt,
);
}
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'birthDate': birthDate?.millisecondsSinceEpoch,
'isHidden': isHidden,
'name': name,
'thumbnailPath': thumbnailPath,
'updatedAt': updatedAt?.millisecondsSinceEpoch,
};
}
factory Person.fromMap(Map<String, dynamic> map) {
return Person(
id: map['id'] as String,
birthDate: map['birthDate'] != null
? DateTime.fromMillisecondsSinceEpoch(map['birthDate'] as int)
: null,
isHidden: map['isHidden'] as bool,
name: map['name'] as String,
thumbnailPath: map['thumbnailPath'] as String,
updatedAt: map['updatedAt'] != null
? DateTime.fromMillisecondsSinceEpoch(map['updatedAt'] as int)
: null,
);
}
String toJson() => json.encode(toMap());
factory Person.fromJson(String source) =>
Person.fromMap(json.decode(source) as Map<String, dynamic>);
@override
bool operator ==(covariant Person other) {
if (identical(this, other)) return true;
return other.id == id &&
other.birthDate == birthDate &&
other.isHidden == isHidden &&
other.name == name &&
other.thumbnailPath == thumbnailPath &&
other.updatedAt == updatedAt;
}
@override
int get hashCode {
return id.hashCode ^
birthDate.hashCode ^
isHidden.hashCode ^
name.hashCode ^
thumbnailPath.hashCode ^
updatedAt.hashCode;
}
} }

View File

@@ -235,7 +235,6 @@ class SearchDisplayFilters {
class SearchFilter { class SearchFilter {
String? context; String? context;
String? filename; String? filename;
String? description;
Set<Person> people; Set<Person> people;
SearchLocationFilter location; SearchLocationFilter location;
SearchCameraFilter camera; SearchCameraFilter camera;
@@ -248,7 +247,6 @@ class SearchFilter {
SearchFilter({ SearchFilter({
this.context, this.context,
this.filename, this.filename,
this.description,
required this.people, required this.people,
required this.location, required this.location,
required this.camera, required this.camera,
@@ -257,28 +255,9 @@ class SearchFilter {
required this.mediaType, required this.mediaType,
}); });
bool get isEmpty {
return (context == null || (context != null && context!.isEmpty)) &&
(filename == null || (filename!.isEmpty)) &&
(description == null || (description!.isEmpty)) &&
people.isEmpty &&
location.country == null &&
location.state == null &&
location.city == null &&
camera.make == null &&
camera.model == null &&
date.takenBefore == null &&
date.takenAfter == null &&
display.isNotInAlbum == false &&
display.isArchive == false &&
display.isFavorite == false &&
mediaType == AssetType.other;
}
SearchFilter copyWith({ SearchFilter copyWith({
String? context, String? context,
String? filename, String? filename,
String? description,
Set<Person>? people, Set<Person>? people,
SearchLocationFilter? location, SearchLocationFilter? location,
SearchCameraFilter? camera, SearchCameraFilter? camera,
@@ -289,7 +268,6 @@ class SearchFilter {
return SearchFilter( return SearchFilter(
context: context ?? this.context, context: context ?? this.context,
filename: filename ?? this.filename, filename: filename ?? this.filename,
description: description ?? this.description,
people: people ?? this.people, people: people ?? this.people,
location: location ?? this.location, location: location ?? this.location,
camera: camera ?? this.camera, camera: camera ?? this.camera,
@@ -301,7 +279,7 @@ class SearchFilter {
@override @override
String toString() { String toString() {
return 'SearchFilter(context: $context, filename: $filename, description: $description, people: $people, location: $location, camera: $camera, date: $date, display: $display, mediaType: $mediaType)'; return 'SearchFilter(context: $context, filename: $filename, people: $people, location: $location, camera: $camera, date: $date, display: $display, mediaType: $mediaType)';
} }
@override @override
@@ -310,7 +288,6 @@ class SearchFilter {
return other.context == context && return other.context == context &&
other.filename == filename && other.filename == filename &&
other.description == description &&
other.people == people && other.people == people &&
other.location == location && other.location == location &&
other.camera == camera && other.camera == camera &&
@@ -323,7 +300,6 @@ class SearchFilter {
int get hashCode { int get hashCode {
return context.hashCode ^ return context.hashCode ^
filename.hashCode ^ filename.hashCode ^
description.hashCode ^
people.hashCode ^ people.hashCode ^
location.hashCode ^ location.hashCode ^
camera.hashCode ^ camera.hashCode ^

View File

@@ -36,19 +36,32 @@ class AppLogPage extends HookConsumerWidget {
); );
} }
Widget buildLeadingIcon(LogLevel level) => switch (level) { Widget buildLeadingIcon(LogLevel level) {
LogLevel.INFO => colorStatusIndicator(context.primaryColor), switch (level) {
LogLevel.SEVERE => colorStatusIndicator(Colors.redAccent), case LogLevel.INFO:
LogLevel.WARNING => colorStatusIndicator(Colors.orangeAccent), return colorStatusIndicator(context.primaryColor);
_ => colorStatusIndicator(Colors.grey), case LogLevel.SEVERE:
}; return colorStatusIndicator(Colors.redAccent);
Color getTileColor(LogLevel level) => switch (level) { case LogLevel.WARNING:
LogLevel.INFO => Colors.transparent, return colorStatusIndicator(Colors.orangeAccent);
LogLevel.SEVERE => Colors.redAccent.withOpacity(0.25), default:
LogLevel.WARNING => Colors.orangeAccent.withOpacity(0.25), return colorStatusIndicator(Colors.grey);
_ => context.primaryColor.withOpacity(0.1), }
}; }
getTileColor(LogLevel level) {
switch (level) {
case LogLevel.INFO:
return Colors.transparent;
case LogLevel.SEVERE:
return Colors.redAccent.withOpacity(0.25);
case LogLevel.WARNING:
return Colors.orangeAccent.withOpacity(0.25);
default:
return context.primaryColor.withOpacity(0.1);
}
}
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(

View File

@@ -74,16 +74,26 @@ class DownloadTaskTile extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final progressPercent = (progress * 100).round(); final progressPercent = (progress * 100).round();
String getStatusText() => switch (status) { getStatusText() {
TaskStatus.running => 'downloading'.tr(), switch (status) {
TaskStatus.complete => 'download_complete'.tr(), case TaskStatus.running:
TaskStatus.failed => 'download_failed'.tr(), return 'downloading'.tr();
TaskStatus.canceled => 'download_canceled'.tr(), case TaskStatus.complete:
TaskStatus.paused => 'download_paused'.tr(), return 'download_complete'.tr();
TaskStatus.enqueued => 'download_enqueue'.tr(), case TaskStatus.failed:
TaskStatus.notFound => 'download_notfound'.tr(), return 'download_failed'.tr();
TaskStatus.waitingToRetry => 'download_waiting_to_retry'.tr(), case TaskStatus.canceled:
}; return 'download_canceled'.tr();
case TaskStatus.paused:
return 'download_paused'.tr();
case TaskStatus.enqueued:
return 'download_enqueue'.tr();
case TaskStatus.notFound:
return 'download_notfound'.tr();
case TaskStatus.waitingToRetry:
return 'download_waiting_to_retry'.tr();
}
}
return SizedBox( return SizedBox(
key: const ValueKey('download_progress'), key: const ValueKey('download_progress'),

View File

@@ -16,8 +16,6 @@ class LargeLeadingTile extends StatelessWidget {
this.trailing, this.trailing,
this.selected = false, this.selected = false,
this.disabled = false, this.disabled = false,
this.selectedTileColor,
this.tileColor,
}); });
final Widget leading; final Widget leading;
@@ -29,9 +27,6 @@ class LargeLeadingTile extends StatelessWidget {
final Widget? trailing; final Widget? trailing;
final bool selected; final bool selected;
final bool disabled; final bool disabled;
final Color? selectedTileColor;
final Color? tileColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
@@ -40,9 +35,8 @@ class LargeLeadingTile extends StatelessWidget {
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: selected color: selected
? selectedTileColor ?? ? Theme.of(context).primaryColor.withAlpha(30)
Theme.of(context).primaryColor.withAlpha(30) : Colors.transparent,
: tileColor ?? Colors.transparent,
borderRadius: BorderRadius.circular(borderRadius), borderRadius: BorderRadius.circular(borderRadius),
), ),
child: Row( child: Row(

View File

@@ -26,7 +26,6 @@ import 'package:wakelock_plus/wakelock_plus.dart';
class NativeVideoViewerPage extends HookConsumerWidget { class NativeVideoViewerPage extends HookConsumerWidget {
final Asset asset; final Asset asset;
final bool showControls; final bool showControls;
final int playbackDelayFactor;
final Widget image; final Widget image;
const NativeVideoViewerPage({ const NativeVideoViewerPage({
@@ -34,7 +33,6 @@ class NativeVideoViewerPage extends HookConsumerWidget {
required this.asset, required this.asset,
required this.image, required this.image,
this.showControls = true, this.showControls = true,
this.playbackDelayFactor = 1,
}); });
@override @override
@@ -319,16 +317,12 @@ class NativeVideoViewerPage extends HookConsumerWidget {
} }
// Delay the video playback to avoid a stutter in the swipe animation // Delay the video playback to avoid a stutter in the swipe animation
// Note, in some circumstances a longer delay is needed (eg: memories),
// the playbackDelayFactor can be used for this
// This delay seems like a hacky way to resolve underlying bugs in video
// playback, but other resolutions failed thus far
Timer( Timer(
Platform.isIOS Platform.isIOS
? Duration(milliseconds: 300 * playbackDelayFactor) ? const Duration(milliseconds: 300)
: imageToVideo : imageToVideo
? Duration(milliseconds: 200 * playbackDelayFactor) ? const Duration(milliseconds: 200)
: Duration(milliseconds: 400 * playbackDelayFactor), () { : const Duration(milliseconds: 400), () {
if (!context.mounted) { if (!context.mounted) {
return; return;
} }

View File

@@ -20,8 +20,6 @@ class TabControllerPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final isRefreshingAssets = ref.watch(assetProvider); final isRefreshingAssets = ref.watch(assetProvider);
final isRefreshingRemoteAlbums = ref.watch(isRefreshingRemoteAlbumProvider); final isRefreshingRemoteAlbums = ref.watch(isRefreshingRemoteAlbumProvider);
final isScreenLandscape =
MediaQuery.orientationOf(context) == Orientation.landscape;
Widget buildIcon({required Widget icon, required bool isProcessing}) { Widget buildIcon({required Widget icon, required bool isProcessing}) {
if (!isProcessing) return icon; if (!isProcessing) return icon;
@@ -47,7 +45,7 @@ class TabControllerPage extends HookConsumerWidget {
); );
} }
void onNavigationSelected(TabsRouter router, int index) { onNavigationSelected(TabsRouter router, int index) {
// On Photos page menu tapped // On Photos page menu tapped
if (router.activeIndex == 0 && index == 0) { if (router.activeIndex == 0 && index == 0) {
scrollToTopNotifierProvider.scrollToTop(); scrollToTopNotifierProvider.scrollToTop();
@@ -63,7 +61,12 @@ class TabControllerPage extends HookConsumerWidget {
ref.read(tabProvider.notifier).state = TabEnum.values[index]; ref.read(tabProvider.notifier).state = TabEnum.values[index];
} }
final navigationDestinations = [ bottomNavigationBar(TabsRouter tabsRouter) {
return NavigationBar(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: (index) =>
onNavigationSelected(tabsRouter, index),
destinations: [
NavigationDestination( NavigationDestination(
label: 'tab_controller_nav_photos'.tr(), label: 'tab_controller_nav_photos'.tr(),
icon: const Icon( icon: const Icon(
@@ -113,32 +116,7 @@ class TabControllerPage extends HookConsumerWidget {
), ),
), ),
), ),
]; ],
Widget bottomNavigationBar(TabsRouter tabsRouter) {
return NavigationBar(
selectedIndex: tabsRouter.activeIndex,
onDestinationSelected: (index) =>
onNavigationSelected(tabsRouter, index),
destinations: navigationDestinations,
);
}
Widget navigationRail(TabsRouter tabsRouter) {
return NavigationRail(
destinations: navigationDestinations
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(e.label),
),
)
.toList(),
onDestinationSelected: (index) =>
onNavigationSelected(tabsRouter, index),
selectedIndex: tabsRouter.activeIndex,
labelType: NavigationRailLabelType.all,
groupAlignment: 0.0,
); );
} }
@@ -157,27 +135,17 @@ class TabControllerPage extends HookConsumerWidget {
), ),
builder: (context, child) { builder: (context, child) {
final tabsRouter = AutoTabsRouter.of(context); final tabsRouter = AutoTabsRouter.of(context);
final heroedChild = HeroControllerScope(
controller: HeroController(),
child: child,
);
return PopScope( return PopScope(
canPop: tabsRouter.activeIndex == 0, canPop: tabsRouter.activeIndex == 0,
onPopInvokedWithResult: (didPop, _) => onPopInvokedWithResult: (didPop, _) =>
!didPop ? tabsRouter.setActiveIndex(0) : null, !didPop ? tabsRouter.setActiveIndex(0) : null,
child: Scaffold( child: Scaffold(
body: isScreenLandscape body: HeroControllerScope(
? Row( controller: HeroController(),
children: [ child: child,
navigationRail(tabsRouter), ),
const VerticalDivider(), bottomNavigationBar:
Expanded(child: heroedChild), multiselectEnabled ? null : bottomNavigationBar(tabsRouter),
],
)
: heroedChild,
bottomNavigationBar: multiselectEnabled || isScreenLandscape
? null
: bottomNavigationBar(tabsRouter),
), ),
); );
}, },

View File

@@ -174,19 +174,33 @@ class _AspectRatioButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
IconData iconData;
switch (label) {
case 'Free':
iconData = Icons.crop_free_rounded;
break;
case '1:1':
iconData = Icons.crop_square_rounded;
break;
case '16:9':
iconData = Icons.crop_16_9_rounded;
break;
case '3:2':
iconData = Icons.crop_3_2_rounded;
break;
case '7:5':
iconData = Icons.crop_7_5_rounded;
break;
default:
iconData = Icons.crop_free_rounded;
}
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
IconButton( IconButton(
icon: Icon( icon: Icon(
switch (label) { iconData,
'Free' => Icons.crop_free_rounded,
'1:1' => Icons.crop_square_rounded,
'16:9' => Icons.crop_16_9_rounded,
'3:2' => Icons.crop_3_2_rounded,
'7:5' => Icons.crop_7_5_rounded,
_ => Icons.crop_free_rounded,
},
color: aspectRatio.value == ratio color: aspectRatio.value == ratio
? context.primaryColor ? context.primaryColor
: context.themeData.iconTheme.color, : context.themeData.iconTheme.color,

View File

@@ -136,16 +136,23 @@ class PermissionOnboardingPage extends HookConsumerWidget {
); );
} }
final Widget child = switch (permission) { final Widget child;
PermissionStatus.limited => buildPermissionLimited(), switch (permission) {
PermissionStatus.denied => buildRequestPermission(), case PermissionStatus.limited:
PermissionStatus.granted || child = buildPermissionLimited();
PermissionStatus.provisional => break;
buildPermissionGranted(), case PermissionStatus.denied:
PermissionStatus.restricted || child = buildRequestPermission();
PermissionStatus.permanentlyDenied => break;
buildPermissionDenied() case PermissionStatus.granted:
}; case PermissionStatus.provisional:
child = buildPermissionGranted();
break;
case PermissionStatus.restricted:
case PermissionStatus.permanentlyDenied:
child = buildPermissionDenied();
break;
}
return Scaffold( return Scaffold(
body: SafeArea( body: SafeArea(

View File

@@ -5,8 +5,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/models/memories/memory.model.dart'; import 'package:immich_mobile/models/memories/memory.model.dart';
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
import 'package:immich_mobile/widgets/common/immich_image.dart'; import 'package:immich_mobile/widgets/common/immich_image.dart';
import 'package:immich_mobile/widgets/memories/memory_bottom_info.dart'; import 'package:immich_mobile/widgets/memories/memory_bottom_info.dart';
@@ -15,8 +13,6 @@ import 'package:immich_mobile/widgets/memories/memory_epilogue.dart';
import 'package:immich_mobile/widgets/memories/memory_progress_indicator.dart'; import 'package:immich_mobile/widgets/memories/memory_progress_indicator.dart';
@RoutePage() @RoutePage()
/// Expects [currentAssetProvider] to be set before navigating to this page
class MemoryPage extends HookConsumerWidget { class MemoryPage extends HookConsumerWidget {
final List<Memory> memories; final List<Memory> memories;
final int memoryIndex; final int memoryIndex;
@@ -36,7 +32,6 @@ class MemoryPage extends HookConsumerWidget {
"${currentAssetPage.value + 1}|${currentMemory.value.assets.length}", "${currentAssetPage.value + 1}|${currentMemory.value.assets.length}",
); );
const bgColor = Colors.black; const bgColor = Colors.black;
final currentAsset = useState<Asset?>(null);
/// The list of all of the asset page controllers /// The list of all of the asset page controllers
final memoryAssetPageControllers = final memoryAssetPageControllers =
@@ -140,14 +135,6 @@ class MemoryPage extends HookConsumerWidget {
ref.read(hapticFeedbackProvider.notifier).selectionClick(); ref.read(hapticFeedbackProvider.notifier).selectionClick();
currentAssetPage.value = otherIndex; currentAssetPage.value = otherIndex;
updateProgressText(); updateProgressText();
final asset = currentMemory.value.assets[otherIndex];
currentAsset.value = asset;
ref.read(currentAssetProvider.notifier).set(asset);
if (asset.isVideo || asset.isMotionPhoto) {
ref.read(videoPlaybackValueProvider.notifier).reset();
}
// Wait for page change animation to finish // Wait for page change animation to finish
await Future.delayed(const Duration(milliseconds: 400)); await Future.delayed(const Duration(milliseconds: 400));
// And then precache the next asset // And then precache the next asset
@@ -287,16 +274,6 @@ class MemoryPage extends HookConsumerWidget {
), ),
), ),
), ),
if (currentAsset.value != null &&
currentAsset.value!.isVideo)
Positioned(
bottom: 24,
right: 32,
child: Icon(
Icons.videocam_outlined,
color: Colors.grey[200],
),
),
], ],
), ),
), ),

View File

@@ -5,7 +5,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart';
@@ -32,8 +31,7 @@ class SearchPage extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final textSearchType = useState<TextSearchType>(TextSearchType.context); final isContextualSearch = useState(true);
final searchHintText = useState<String>('contextual_search'.tr());
final textSearchController = useTextEditingController(); final textSearchController = useTextEditingController();
final filter = useState<SearchFilter>( final filter = useState<SearchFilter>(
SearchFilter( SearchFilter(
@@ -51,7 +49,7 @@ class SearchPage extends HookConsumerWidget {
), ),
); );
final previousFilter = useState<SearchFilter?>(null); final previousFilter = useState(filter.value);
final peopleCurrentFilterWidget = useState<Widget?>(null); final peopleCurrentFilterWidget = useState<Widget?>(null);
final dateRangeCurrentFilterWidget = useState<Widget?>(null); final dateRangeCurrentFilterWidget = useState<Widget?>(null);
@@ -62,55 +60,19 @@ class SearchPage extends HookConsumerWidget {
final isSearching = useState(false); final isSearching = useState(false);
SnackBar searchInfoSnackBar(String message) {
return SnackBar(
content: Text(
message,
style: context.textTheme.labelLarge,
),
showCloseIcon: true,
behavior: SnackBarBehavior.fixed,
closeIconColor: context.colorScheme.onSurface,
);
}
search() async { search() async {
if (filter.value.isEmpty) { if (prefilter == null && filter.value == previousFilter.value) return;
return;
}
if (prefilter == null && filter.value == previousFilter.value) {
return;
}
isSearching.value = true; isSearching.value = true;
ref.watch(paginatedSearchProvider.notifier).clear(); ref.watch(paginatedSearchProvider.notifier).clear();
final hasResult = await ref await ref.watch(paginatedSearchProvider.notifier).search(filter.value);
.watch(paginatedSearchProvider.notifier)
.search(filter.value);
if (!hasResult) {
context.showSnackBar(
searchInfoSnackBar('search_no_result'.tr()),
);
}
previousFilter.value = filter.value; previousFilter.value = filter.value;
isSearching.value = false; isSearching.value = false;
} }
loadMoreSearchResult() async { loadMoreSearchResult() async {
isSearching.value = true; isSearching.value = true;
final hasResult = await ref await ref.watch(paginatedSearchProvider.notifier).search(filter.value);
.watch(paginatedSearchProvider.notifier)
.search(filter.value);
if (!hasResult) {
context.showSnackBar(
searchInfoSnackBar('search_no_more_result'.tr()),
);
}
isSearching.value = false; isSearching.value = false;
} }
@@ -480,148 +442,37 @@ class SearchPage extends HookConsumerWidget {
} }
handleTextSubmitted(String value) { handleTextSubmitted(String value) {
switch (textSearchType.value) { if (isContextualSearch.value) {
case TextSearchType.context:
filter.value = filter.value.copyWith( filter.value = filter.value.copyWith(
filename: '', filename: '',
context: value, context: value,
description: '',
); );
} else {
break;
case TextSearchType.filename:
filter.value = filter.value.copyWith( filter.value = filter.value.copyWith(
filename: value, filename: value,
context: '', context: '',
description: '',
); );
break;
case TextSearchType.description:
filter.value = filter.value.copyWith(
filename: '',
context: '',
description: value,
);
break;
} }
search(); search();
} }
IconData getSearchPrefixIcon() {
switch (textSearchType.value) {
case TextSearchType.context:
return Icons.image_search_rounded;
case TextSearchType.filename:
return Icons.abc_rounded;
case TextSearchType.description:
return Icons.text_snippet_outlined;
default:
return Icons.search_rounded;
}
}
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
appBar: AppBar( appBar: AppBar(
automaticallyImplyLeading: true, automaticallyImplyLeading: true,
actions: [ actions: [
Padding( Padding(
padding: const EdgeInsets.only(right: 16.0), padding: const EdgeInsets.only(right: 14.0),
child: MenuAnchor( child: IconButton(
style: MenuStyle( key: const Key('contextual_search_button'),
elevation: const WidgetStatePropertyAll(1), icon: isContextualSearch.value
shape: WidgetStateProperty.all( ? const Icon(Icons.abc_rounded)
RoundedRectangleBorder( : const Icon(Icons.image_search_rounded),
borderRadius: BorderRadius.circular(24),
),
),
padding: const WidgetStatePropertyAll(
EdgeInsets.all(4),
),
),
builder: (
BuildContext context,
MenuController controller,
Widget? child,
) {
return IconButton(
onPressed: () { onPressed: () {
if (controller.isOpen) { isContextualSearch.value = !isContextualSearch.value;
controller.close(); textSearchController.clear();
} else {
controller.open();
}
}, },
icon: const Icon(Icons.more_vert_rounded),
tooltip: 'Show text search menu',
);
},
menuChildren: [
MenuItemButton(
child: ListTile(
leading: const Icon(Icons.image_search_rounded),
title: Text(
'search_filter_contextual'.tr(),
style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: textSearchType.value == TextSearchType.context
? context.colorScheme.primary
: null,
),
),
selectedColor: context.colorScheme.primary,
selected: textSearchType.value == TextSearchType.context,
),
onPressed: () {
textSearchType.value = TextSearchType.context;
searchHintText.value = 'contextual_search'.tr();
},
),
MenuItemButton(
child: ListTile(
leading: const Icon(Icons.abc_rounded),
title: Text(
'search_filter_filename'.tr(),
style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color: textSearchType.value == TextSearchType.filename
? context.colorScheme.primary
: null,
),
),
selectedColor: context.colorScheme.primary,
selected: textSearchType.value == TextSearchType.filename,
),
onPressed: () {
textSearchType.value = TextSearchType.filename;
searchHintText.value = 'filename_search'.tr();
},
),
MenuItemButton(
child: ListTile(
leading: const Icon(Icons.text_snippet_outlined),
title: Text(
'search_filter_description'.tr(),
style: context.textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w500,
color:
textSearchType.value == TextSearchType.description
? context.colorScheme.primary
: null,
),
),
selectedColor: context.colorScheme.primary,
selected:
textSearchType.value == TextSearchType.description,
),
onPressed: () {
textSearchType.value = TextSearchType.description;
searchHintText.value = 'description_search'.tr();
},
),
],
), ),
), ),
], ],
@@ -652,10 +503,12 @@ class SearchPage extends HookConsumerWidget {
prefixIcon: prefilter != null prefixIcon: prefilter != null
? null ? null
: Icon( : Icon(
getSearchPrefixIcon(), Icons.search_rounded,
color: context.colorScheme.primary, color: context.colorScheme.primary,
), ),
hintText: searchHintText.value, hintText: isContextualSearch.value
? 'contextual_search'.tr()
: 'filename_search'.tr(),
hintStyle: context.textTheme.bodyLarge?.copyWith( hintStyle: context.textTheme.bodyLarge?.copyWith(
color: context.themeData.colorScheme.onSurfaceSecondary, color: context.themeData.colorScheme.onSurfaceSecondary,
), ),
@@ -743,11 +596,6 @@ class SearchPage extends HookConsumerWidget {
), ),
), ),
), ),
if (isSearching.value)
const Expanded(
child: Center(child: CircularProgressIndicator.adaptive()),
)
else
SearchResultGrid( SearchResultGrid(
onScrollEnd: loadMoreSearchResult, onScrollEnd: loadMoreSearchResult,
isSearching: isSearching.value, isSearching: isSearching.value,

View File

@@ -19,23 +19,17 @@ class PaginatedSearchNotifier extends StateNotifier<SearchResult> {
PaginatedSearchNotifier(this._searchService) PaginatedSearchNotifier(this._searchService)
: super(SearchResult(assets: [], nextPage: 1)); : super(SearchResult(assets: [], nextPage: 1));
Future<bool> search(SearchFilter filter) async { search(SearchFilter filter) async {
if (state.nextPage == null) { if (state.nextPage == null) return;
return false;
}
final result = await _searchService.search(filter, state.nextPage!); final result = await _searchService.search(filter, state.nextPage!);
if (result == null) { if (result == null) return;
return false;
}
state = SearchResult( state = SearchResult(
assets: [...state.assets, ...result.assets], assets: [...state.assets, ...result.assets],
nextPage: result.nextPage, nextPage: result.nextPage,
); );
return true;
} }
clear() { clear() {

View File

@@ -18,11 +18,15 @@ class AlbumRepository extends DatabaseRepository implements IAlbumRepository {
@override @override
Future<int> count({bool? local}) { Future<int> count({bool? local}) {
final baseQuery = db.albums.where(); final baseQuery = db.albums.where();
final QueryBuilder<Album, Album, QAfterWhereClause> query = switch (local) { final QueryBuilder<Album, Album, QAfterWhereClause> query;
null => baseQuery.noOp(), switch (local) {
true => baseQuery.localIdIsNotNull(), case null:
false => baseQuery.remoteIdIsNotNull(), query = baseQuery.noOp();
}; case true:
query = baseQuery.localIdIsNotNull();
case false:
query = baseQuery.remoteIdIsNotNull();
}
return query.count(); return query.count();
} }
@@ -87,11 +91,15 @@ class AlbumRepository extends DatabaseRepository implements IAlbumRepository {
if (ownerId != null) { if (ownerId != null) {
filterQuery = filterQuery.owner((q) => q.isarIdEqualTo(ownerId)); filterQuery = filterQuery.owner((q) => q.isarIdEqualTo(ownerId));
} }
final QueryBuilder<Album, Album, QAfterSortBy> query = switch (sortBy) { final QueryBuilder<Album, Album, QAfterSortBy> query;
null => filterQuery.noOp(), switch (sortBy) {
AlbumSort.remoteId => filterQuery.sortByRemoteId(), case null:
AlbumSort.localId => filterQuery.sortByLocalId(), query = filterQuery.noOp();
}; case AlbumSort.remoteId:
query = filterQuery.sortByRemoteId();
case AlbumSort.localId:
query = filterQuery.sortByLocalId();
}
return query.findAll(); return query.findAll();
} }
@@ -142,11 +150,14 @@ class AlbumRepository extends DatabaseRepository implements IAlbumRepository {
query = query.owner( query = query.owner(
(q) => q.not().isarIdEqualTo(Store.get(StoreKey.currentUser).isarId), (q) => q.not().isarIdEqualTo(Store.get(StoreKey.currentUser).isarId),
); );
break;
case QuickFilterMode.myAlbums: case QuickFilterMode.myAlbums:
query = query.owner( query = query.owner(
(q) => q.isarIdEqualTo(Store.get(StoreKey.currentUser).isarId), (q) => q.isarIdEqualTo(Store.get(StoreKey.currentUser).isarId),
); );
break;
case QuickFilterMode.all: case QuickFilterMode.all:
default:
break; break;
} }

View File

@@ -38,20 +38,27 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
query = query.ownerIdEqualTo(ownerId); query = query.ownerIdEqualTo(ownerId);
} }
if (state != null) { switch (state) {
query = switch (state) { case null:
AssetState.local => query.remoteIdIsNull(), break;
AssetState.remote => query.localIdIsNull(), case AssetState.local:
AssetState.merged => query.localIdIsNotNull().remoteIdIsNotNull(), query = query.remoteIdIsNull();
}; case AssetState.remote:
query = query.localIdIsNull();
case AssetState.merged:
query = query.localIdIsNotNull().remoteIdIsNotNull();
} }
final QueryBuilder<Asset, Asset, QAfterSortBy> sortedQuery = final QueryBuilder<Asset, Asset, QAfterSortBy> sortedQuery;
switch (sortBy) { switch (sortBy) {
null => query.noOp(), case null:
AssetSort.checksum => query.sortByChecksum(), sortedQuery = query.noOp();
AssetSort.ownerIdChecksum => query.sortByOwnerId().thenByChecksum(), case AssetSort.checksum:
}; sortedQuery = query.sortByChecksum();
case AssetSort.ownerIdChecksum:
sortedQuery = query.sortByOwnerId().thenByChecksum();
}
return sortedQuery.findAll(); return sortedQuery.findAll();
} }
@@ -77,12 +84,16 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
AssetState? state, AssetState? state,
) { ) {
final query = db.assets.remote(ids).filter(); final query = db.assets.remote(ids).filter();
return switch (state) { switch (state) {
null => query.noOp(), case null:
AssetState.local => query.remoteIdIsNull(), return query.noOp();
AssetState.remote => query.localIdIsNull(), case AssetState.local:
AssetState.merged => query.localIdIsNotEmpty().remoteIdIsNotNull(), return query.remoteIdIsNull();
}; case AssetState.remote:
return query.localIdIsNull();
case AssetState.merged:
return query.localIdIsNotEmpty().remoteIdIsNotNull();
}
} }
@override @override
@@ -93,32 +104,39 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
int? limit, int? limit,
}) { }) {
final baseQuery = db.assets.where(); final baseQuery = db.assets.where();
final QueryBuilder<Asset, Asset, QAfterFilterCondition> filteredQuery = final QueryBuilder<Asset, Asset, QAfterFilterCondition> filteredQuery;
switch (state) { switch (state) {
null => baseQuery.ownerIdEqualToAnyChecksum(ownerId).noOp(), case null:
AssetState.local => baseQuery filteredQuery = baseQuery.ownerIdEqualToAnyChecksum(ownerId).noOp();
case AssetState.local:
filteredQuery = baseQuery
.remoteIdIsNull() .remoteIdIsNull()
.filter() .filter()
.localIdIsNotNull() .localIdIsNotNull()
.ownerIdEqualTo(ownerId), .ownerIdEqualTo(ownerId);
AssetState.remote => baseQuery case AssetState.remote:
filteredQuery = baseQuery
.localIdIsNull() .localIdIsNull()
.filter() .filter()
.remoteIdIsNotNull() .remoteIdIsNotNull()
.ownerIdEqualTo(ownerId), .ownerIdEqualTo(ownerId);
AssetState.merged => baseQuery case AssetState.merged:
filteredQuery = baseQuery
.ownerIdEqualToAnyChecksum(ownerId) .ownerIdEqualToAnyChecksum(ownerId)
.filter() .filter()
.remoteIdIsNotNull() .remoteIdIsNotNull()
.localIdIsNotNull(), .localIdIsNotNull();
}; }
final QueryBuilder<Asset, Asset, QAfterSortBy> query = switch (sortBy) { final QueryBuilder<Asset, Asset, QAfterSortBy> query;
null => filteredQuery.noOp(), switch (sortBy) {
AssetSort.checksum => filteredQuery.sortByChecksum(), case null:
AssetSort.ownerIdChecksum => query = filteredQuery.noOp();
filteredQuery.sortByOwnerId().thenByChecksum(), case AssetSort.checksum:
}; query = filteredQuery.sortByChecksum();
case AssetSort.ownerIdChecksum:
query = filteredQuery.sortByOwnerId().thenByChecksum();
}
return limit == null ? query.findAll() : query.limit(limit).findAll(); return limit == null ? query.findAll() : query.limit(limit).findAll();
} }
@@ -137,16 +155,17 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
int limit = 100, int limit = 100,
}) { }) {
final baseQuery = db.assets.where(); final baseQuery = db.assets.where();
final QueryBuilder<Asset, Asset, QAfterFilterCondition> query = final QueryBuilder<Asset, Asset, QAfterFilterCondition> query;
switch (state) { switch (state) {
null => baseQuery.noOp(), case null:
AssetState.local => query = baseQuery.noOp();
baseQuery.remoteIdIsNull().filter().localIdIsNotNull(), case AssetState.local:
AssetState.remote => query = baseQuery.remoteIdIsNull().filter().localIdIsNotNull();
baseQuery.localIdIsNull().filter().remoteIdIsNotNull(), case AssetState.remote:
AssetState.merged => query = baseQuery.localIdIsNull().filter().remoteIdIsNotNull();
baseQuery.localIdIsNotNull().filter().remoteIdIsNotNull(), case AssetState.merged:
}; query = baseQuery.localIdIsNotNull().filter().remoteIdIsNotNull();
}
return _getMatchesImpl(query, ownerId, assets, limit); return _getMatchesImpl(query, ownerId, assets, limit);
} }

View File

@@ -14,11 +14,13 @@ class BackupRepository extends DatabaseRepository implements IBackupRepository {
@override @override
Future<List<BackupAlbum>> getAll({BackupAlbumSort? sort}) { Future<List<BackupAlbum>> getAll({BackupAlbumSort? sort}) {
final baseQuery = db.backupAlbums.where(); final baseQuery = db.backupAlbums.where();
final QueryBuilder<BackupAlbum, BackupAlbum, QAfterSortBy> query = final QueryBuilder<BackupAlbum, BackupAlbum, QAfterSortBy> query;
switch (sort) { switch (sort) {
null => baseQuery.noOp(), case null:
BackupAlbumSort.id => baseQuery.sortById(), query = baseQuery.noOp();
}; case BackupAlbumSort.id:
query = baseQuery.sortById();
}
return query.findAll(); return query.findAll();
} }

View File

@@ -25,10 +25,13 @@ class UserRepository extends DatabaseRepository implements IUserRepository {
final int userId = Store.get(StoreKey.currentUser).isarId; final int userId = Store.get(StoreKey.currentUser).isarId;
final QueryBuilder<User, User, QAfterWhereClause> afterWhere = final QueryBuilder<User, User, QAfterWhereClause> afterWhere =
self ? baseQuery.noOp() : baseQuery.isarIdNotEqualTo(userId); self ? baseQuery.noOp() : baseQuery.isarIdNotEqualTo(userId);
final QueryBuilder<User, User, QAfterSortBy> query = switch (sortBy) { final QueryBuilder<User, User, QAfterSortBy> query;
null => afterWhere.noOp(), switch (sortBy) {
UserSort.id => afterWhere.sortById(), case null:
}; query = afterWhere.noOp();
case UserSort.id:
query = afterWhere.sortById();
}
return query.findAll(); return query.findAll();
} }

View File

@@ -519,12 +519,18 @@ class BackupService {
return responseBody.containsKey('id') ? responseBody['id'] : null; return responseBody.containsKey('id') ? responseBody['id'] : null;
} }
String _getAssetType(AssetType assetType) => switch (assetType) { String _getAssetType(AssetType assetType) {
AssetType.audio => "AUDIO", switch (assetType) {
AssetType.image => "IMAGE", case AssetType.audio:
AssetType.video => "VIDEO", return "AUDIO";
AssetType.other => "OTHER", case AssetType.image:
}; return "IMAGE";
case AssetType.video:
return "VIDEO";
case AssetType.other:
return "OTHER";
}
}
} }
class MultipartRequest extends http.MultipartRequest { class MultipartRequest extends http.MultipartRequest {

View File

@@ -84,10 +84,6 @@ class SearchService {
? filter.filename ? filter.filename
: null, : null,
country: filter.location.country, country: filter.location.country,
description:
filter.description != null && filter.description!.isNotEmpty
? filter.description
: null,
state: filter.location.state, state: filter.location.state,
city: filter.location.city, city: filter.location.city,
make: filter.camera.make, make: filter.camera.make,
@@ -105,7 +101,7 @@ class SearchService {
); );
} }
if (response == null || response.assets.items.isEmpty) { if (response == null) {
return null; return null;
} }

View File

@@ -10,7 +10,6 @@ dynamic upgradeDto(dynamic value, String targetType) {
addDefault(value, 'ratings', RatingsResponse().toJson()); addDefault(value, 'ratings', RatingsResponse().toJson());
addDefault(value, 'people', PeopleResponse().toJson()); addDefault(value, 'people', PeopleResponse().toJson());
addDefault(value, 'tags', TagsResponse().toJson()); addDefault(value, 'tags', TagsResponse().toJson());
addDefault(value, 'sharedLinks', SharedLinksResponse().toJson());
} }
break; break;
case 'ServerConfigDto': case 'ServerConfigDto':

View File

@@ -2,8 +2,13 @@ import 'package:flutter/material.dart';
import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart';
/// Returns the suitable [IconData] to represent an [Asset]s storage location /// Returns the suitable [IconData] to represent an [Asset]s storage location
IconData storageIcon(Asset asset) => switch (asset.storage) { IconData storageIcon(Asset asset) {
AssetState.local => Icons.cloud_off_outlined, switch (asset.storage) {
AssetState.remote => Icons.cloud_outlined, case AssetState.local:
AssetState.merged => Icons.cloud_done_outlined, return Icons.cloud_off_outlined;
}; case AssetState.remote:
return Icons.cloud_outlined;
case AssetState.merged:
return Icons.cloud_done_outlined;
}
}

View File

@@ -16,14 +16,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final albumViewerState = ref.watch(albumViewerProvider); final titleTextEditController = useTextEditingController(text: albumName);
final titleTextEditController = useTextEditingController(
text: albumViewerState.isEditAlbum &&
albumViewerState.editTitleText.isNotEmpty
? albumViewerState.editTitleText
: albumName,
);
void onFocusModeChange() { void onFocusModeChange() {
if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) { if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) {

View File

@@ -204,13 +204,6 @@ class ThumbnailImage extends ConsumerWidget {
storageIcon(asset), storageIcon(asset),
color: Colors.white.withOpacity(.8), color: Colors.white.withOpacity(.8),
size: 16, size: 16,
shadows: [
Shadow(
blurRadius: 5.0,
color: Colors.black.withOpacity(0.6),
offset: const Offset(0.0, 0.0),
),
],
), ),
), ),
if (asset.isFavorite) if (asset.isFavorite)

View File

@@ -15,26 +15,36 @@ class ImmichToast {
final fToast = FToast(); final fToast = FToast();
fToast.init(context); fToast.init(context);
Color getColor(ToastType type, BuildContext context) => switch (type) { Color getColor(ToastType type, BuildContext context) {
ToastType.info => context.primaryColor, switch (type) {
ToastType.success => const Color.fromARGB(255, 78, 140, 124), case ToastType.info:
ToastType.error => const Color.fromARGB(255, 220, 48, 85), return context.primaryColor;
}; case ToastType.success:
return const Color.fromARGB(255, 78, 140, 124);
case ToastType.error:
return const Color.fromARGB(255, 220, 48, 85);
}
}
Icon getIcon(ToastType type) => switch (type) { Icon getIcon(ToastType type) {
ToastType.info => Icon( switch (type) {
case ToastType.info:
return Icon(
Icons.info_outline_rounded, Icons.info_outline_rounded,
color: context.primaryColor, color: context.primaryColor,
), );
ToastType.success => const Icon( case ToastType.success:
return const Icon(
Icons.check_circle_rounded, Icons.check_circle_rounded,
color: Color.fromARGB(255, 78, 140, 124), color: Color.fromARGB(255, 78, 140, 124),
), );
ToastType.error => const Icon( case ToastType.error:
return const Icon(
Icons.error_outline_rounded, Icons.error_outline_rounded,
color: Color.fromARGB(255, 240, 162, 156), color: Color.fromARGB(255, 240, 162, 156),
), );
}; }
}
fToast.showToast( fToast.showToast(
child: Container( child: Container(

View File

@@ -168,7 +168,7 @@ class LoginForm extends HookConsumerWidget {
populateTestLoginInfo1() { populateTestLoginInfo1() {
emailController.text = 'testuser@email.com'; emailController.text = 'testuser@email.com';
passwordController.text = 'password'; passwordController.text = 'password';
serverEndpointController.text = 'http://10.1.15.216:2283/api'; serverEndpointController.text = 'http://10.1.15.216:3000/api';
} }
login() async { login() async {

View File

@@ -59,10 +59,9 @@ class MapBottomSheet extends HookConsumerWidget {
child: DraggableScrollableSheet( child: DraggableScrollableSheet(
controller: sheetController, controller: sheetController,
minChildSize: sheetMinExtent, minChildSize: sheetMinExtent,
maxChildSize: 0.8, maxChildSize: 0.5,
initialChildSize: sheetMinExtent, initialChildSize: sheetMinExtent,
snap: true, snap: true,
snapSizes: [sheetMinExtent, 0.5, 0.8],
shouldCloseOnMinExtent: false, shouldCloseOnMinExtent: false,
builder: (ctx, scrollController) => MapAssetGrid( builder: (ctx, scrollController) => MapAssetGrid(
controller: scrollController, controller: scrollController,
@@ -79,13 +78,11 @@ class MapBottomSheet extends HookConsumerWidget {
), ),
ValueListenableBuilder( ValueListenableBuilder(
valueListenable: bottomSheetOffset, valueListenable: bottomSheetOffset,
builder: (context, value, child) { builder: (ctx, value, child) => Positioned(
return Positioned(
right: 0, right: 0,
bottom: context.height * (value + 0.02), bottom: context.height * (value + 0.02),
child: AnimatedOpacity( child: child!,
opacity: value < 0.8 ? 1 : 0, ),
duration: const Duration(milliseconds: 150),
child: ElevatedButton( child: ElevatedButton(
onPressed: onZoomToLocation, onPressed: onZoomToLocation,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
@@ -94,9 +91,6 @@ class MapBottomSheet extends HookConsumerWidget {
child: const Icon(Icons.my_location), child: const Icon(Icons.my_location),
), ),
), ),
);
},
),
], ],
); );
} }

View File

@@ -75,12 +75,11 @@ class MemoryCard extends StatelessWidget {
key: ValueKey(asset.id), key: ValueKey(asset.id),
asset: asset, asset: asset,
showControls: false, showControls: false,
playbackDelayFactor: 2,
image: ImmichImage( image: ImmichImage(
asset, asset,
width: context.width, width: context.width,
height: context.height, height: context.height,
fit: BoxFit.contain, fit: fit,
), ),
), ),
), ),

View File

@@ -4,8 +4,6 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/models/memories/memory.model.dart'; import 'package:immich_mobile/models/memories/memory.model.dart';
import 'package:immich_mobile/widgets/asset_grid/thumbnail_placeholder.dart'; import 'package:immich_mobile/widgets/asset_grid/thumbnail_placeholder.dart';
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
import 'package:immich_mobile/providers/memory.provider.dart'; import 'package:immich_mobile/providers/memory.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
@@ -35,13 +33,6 @@ class MemoryLane extends HookConsumerWidget {
), ),
onTap: (memoryIndex) { onTap: (memoryIndex) {
ref.read(hapticFeedbackProvider.notifier).heavyImpact(); ref.read(hapticFeedbackProvider.notifier).heavyImpact();
if (memories[memoryIndex].assets.isNotEmpty) {
final asset = memories[memoryIndex].assets[0];
ref.read(currentAssetProvider.notifier).set(asset);
if (asset.isVideo || asset.isMotionPhoto) {
ref.read(videoPlaybackValueProvider.notifier).reset();
}
}
context.pushRoute( context.pushRoute(
MemoryRoute( MemoryRoute(
memories: memories, memories: memories,

View File

@@ -590,15 +590,21 @@ class _PhotoViewState extends State<PhotoView>
} }
/// The default [ScaleStateCycle] /// The default [ScaleStateCycle]
PhotoViewScaleState defaultScaleStateCycle(PhotoViewScaleState actual) => PhotoViewScaleState defaultScaleStateCycle(PhotoViewScaleState actual) {
switch (actual) { switch (actual) {
PhotoViewScaleState.initial => PhotoViewScaleState.covering, case PhotoViewScaleState.initial:
PhotoViewScaleState.covering => PhotoViewScaleState.originalSize, return PhotoViewScaleState.covering;
PhotoViewScaleState.originalSize => PhotoViewScaleState.initial, case PhotoViewScaleState.covering:
PhotoViewScaleState.zoomedIn || return PhotoViewScaleState.originalSize;
PhotoViewScaleState.zoomedOut => case PhotoViewScaleState.originalSize:
PhotoViewScaleState.initial, return PhotoViewScaleState.initial;
}; case PhotoViewScaleState.zoomedIn:
case PhotoViewScaleState.zoomedOut:
return PhotoViewScaleState.initial;
default:
return PhotoViewScaleState.initial;
}
}
/// A type definition for a [Function] that receives the actual [PhotoViewScaleState] and returns the next one /// A type definition for a [Function] that receives the actual [PhotoViewScaleState] and returns the next one
/// It is used internally to walk in the "doubletap gesture cycle". /// It is used internally to walk in the "doubletap gesture cycle".

View File

@@ -9,20 +9,25 @@ double getScaleForScaleState(
PhotoViewScaleState scaleState, PhotoViewScaleState scaleState,
ScaleBoundaries scaleBoundaries, ScaleBoundaries scaleBoundaries,
) { ) {
return switch (scaleState) { switch (scaleState) {
PhotoViewScaleState.initial || case PhotoViewScaleState.initial:
PhotoViewScaleState.zoomedIn || case PhotoViewScaleState.zoomedIn:
PhotoViewScaleState.zoomedOut => case PhotoViewScaleState.zoomedOut:
_clampSize(scaleBoundaries.initialScale, scaleBoundaries), return _clampSize(scaleBoundaries.initialScale, scaleBoundaries);
PhotoViewScaleState.covering => _clampSize( case PhotoViewScaleState.covering:
return _clampSize(
_scaleForCovering( _scaleForCovering(
scaleBoundaries.outerSize, scaleBoundaries.outerSize,
scaleBoundaries.childSize, scaleBoundaries.childSize,
), ),
scaleBoundaries, scaleBoundaries,
), );
PhotoViewScaleState.originalSize => _clampSize(1.0, scaleBoundaries), case PhotoViewScaleState.originalSize:
}; return _clampSize(1.0, scaleBoundaries);
// Will never be reached
default:
return 0;
}
} }
/// Internal class to wraps custom scale boundaries (min, max and initial) /// Internal class to wraps custom scale boundaries (min, max and initial)

View File

@@ -1,12 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/interfaces/person_api.interface.dart'; import 'package:immich_mobile/interfaces/person_api.interface.dart';
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
import 'package:immich_mobile/providers/search/people.provider.dart'; import 'package:immich_mobile/providers/search/people.provider.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';
@@ -19,102 +16,28 @@ class PeoplePicker extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final formFocus = useFocusNode(); var imageSize = 45.0;
final imageSize = 60.0;
final searchQuery = useState('');
final people = ref.watch(getAllPeopleProvider); final people = ref.watch(getAllPeopleProvider);
final headers = ApiService.getRequestHeaders(); final headers = ApiService.getRequestHeaders();
final selectedPeople = useState<Set<Person>>(filter ?? {}); final selectedPeople = useState<Set<Person>>(filter ?? {});
return Column( return people.widgetWhen(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
focusNode: formFocus,
onChanged: (value) => searchQuery.value = value,
onTapOutside: (_) => formFocus.unfocus(),
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(left: 24),
filled: true,
fillColor: context.primaryColor.withOpacity(0.1),
hintStyle: context.textTheme.bodyLarge?.copyWith(
color: context.themeData.colorScheme.onSurfaceSecondary,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: BorderSide(
color: context.colorScheme.surfaceContainerHighest,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: BorderSide(
color: context.colorScheme.surfaceContainerHighest,
),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: BorderSide(
color: context.colorScheme.surfaceContainerHighest,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: BorderSide(
color: context.colorScheme.primary.withAlpha(150),
),
),
prefixIcon: Icon(
Icons.search_rounded,
color: context.colorScheme.primary,
),
hintText: 'search_filter_people_hint'.tr(),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 0),
child: Divider(
color: context.colorScheme.surfaceContainerHighest,
thickness: 1,
),
),
Expanded(
child: people.widgetWhen(
onData: (people) { onData: (people) {
return ListView.builder( return ListView.builder(
shrinkWrap: true, shrinkWrap: true,
itemCount: people itemCount: people.length,
.where(
(person) => person.name
.toLowerCase()
.contains(searchQuery.value.toLowerCase()),
)
.length,
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final person = people final person = people[index];
.where( return Card(
(person) => person.name elevation: 0,
.toLowerCase() shape: const RoundedRectangleBorder(
.contains(searchQuery.value.toLowerCase()), borderRadius: BorderRadius.all(Radius.circular(15)),
) ),
.toList()[index]; child: ListTile(
final isSelected = selectedPeople.value.contains(person);
return Padding(
padding: const EdgeInsets.only(bottom: 2.0),
child: LargeLeadingTile(
title: Text( title: Text(
person.name, person.name,
style: context.textTheme.bodyLarge?.copyWith( style: context.textTheme.bodyLarge,
fontSize: 20,
fontWeight: FontWeight.w500,
color: isSelected
? context.colorScheme.onPrimary
: context.colorScheme.onSurface,
),
), ),
leading: SizedBox( leading: SizedBox(
height: imageSize, height: imageSize,
@@ -140,17 +63,16 @@ class PeoplePicker extends HookConsumerWidget {
selectedPeople.value = {...selectedPeople.value}; selectedPeople.value = {...selectedPeople.value};
onSelect(selectedPeople.value); onSelect(selectedPeople.value);
}, },
selected: isSelected, selected: selectedPeople.value.contains(person),
selectedTileColor: context.primaryColor, selectedTileColor: context.primaryColor.withOpacity(0.2),
tileColor: context.primaryColor.withAlpha(25), shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
), ),
); );
}, },
); );
}, },
),
),
],
); );
} }
} }

View File

@@ -220,8 +220,10 @@ class NetworkStatusIcon extends StatelessWidget {
); );
} }
Widget _buildIcon(BuildContext context) => switch (status) { Widget _buildIcon(BuildContext context) {
AuxCheckStatus.loading => Padding( switch (status) {
case AuxCheckStatus.loading:
return Padding(
padding: const EdgeInsets.only(left: 4.0), padding: const EdgeInsets.only(left: 4.0),
child: SizedBox( child: SizedBox(
width: 18, width: 18,
@@ -232,8 +234,9 @@ class NetworkStatusIcon extends StatelessWidget {
key: const ValueKey('loading'), key: const ValueKey('loading'),
), ),
), ),
), );
AuxCheckStatus.valid => enabled case AuxCheckStatus.valid:
return enabled
? const Icon( ? const Icon(
Icons.check_circle_rounded, Icons.check_circle_rounded,
color: Colors.green, color: Colors.green,
@@ -243,8 +246,9 @@ class NetworkStatusIcon extends StatelessWidget {
Icons.check_circle_rounded, Icons.check_circle_rounded,
color: context.colorScheme.onSurface.withAlpha(100), color: context.colorScheme.onSurface.withAlpha(100),
key: const ValueKey('success'), key: const ValueKey('success'),
), );
AuxCheckStatus.error => enabled case AuxCheckStatus.error:
return enabled
? const Icon( ? const Icon(
Icons.error_rounded, Icons.error_rounded,
color: Colors.red, color: Colors.red,
@@ -254,7 +258,9 @@ class NetworkStatusIcon extends StatelessWidget {
Icons.error_rounded, Icons.error_rounded,
color: Colors.grey, color: Colors.grey,
key: ValueKey('error'), key: ValueKey('error'),
), );
_ => const Icon(Icons.circle_outlined, key: ValueKey('unknown')), default:
}; return const Icon(Icons.circle_outlined, key: ValueKey('unknown'));
}
}
} }

View File

@@ -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.126.1 - API version: 1.125.6
- Generator version: 7.8.0 - Generator version: 7.8.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen
@@ -93,17 +93,17 @@ Class | Method | HTTP request | Description
*AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} | *AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} |
*AlbumsApi* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} | *AlbumsApi* | [**updateAlbumInfo**](doc//AlbumsApi.md#updatealbuminfo) | **PATCH** /albums/{id} |
*AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} | *AlbumsApi* | [**updateAlbumUser**](doc//AlbumsApi.md#updatealbumuser) | **PUT** /albums/{id}/user/{userId} |
*AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | checkBulkUpload *AssetsApi* | [**checkBulkUpload**](doc//AssetsApi.md#checkbulkupload) | **POST** /assets/bulk-upload-check | Checks if assets exist by checksums
*AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | checkExistingAssets *AssetsApi* | [**checkExistingAssets**](doc//AssetsApi.md#checkexistingassets) | **POST** /assets/exist | Checks if multiple assets exist on the server and returns all existing - used by background backup
*AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets | *AssetsApi* | [**deleteAssets**](doc//AssetsApi.md#deleteassets) | **DELETE** /assets |
*AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original | *AssetsApi* | [**downloadAsset**](doc//AssetsApi.md#downloadasset) | **GET** /assets/{id}/original |
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | getAllUserAssetsByDeviceId *AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | Get all asset of a device that are in the database, ID only.
*AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} | *AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} |
*AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics | *AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics |
*AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane | *AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane |
*AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random | *AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random |
*AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback | *AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback |
*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | replaceAsset *AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | Replace the asset with new file, without changing its id
*AssetsApi* | [**runAssetJobs**](doc//AssetsApi.md#runassetjobs) | **POST** /assets/jobs | *AssetsApi* | [**runAssetJobs**](doc//AssetsApi.md#runassetjobs) | **POST** /assets/jobs |
*AssetsApi* | [**updateAsset**](doc//AssetsApi.md#updateasset) | **PUT** /assets/{id} | *AssetsApi* | [**updateAsset**](doc//AssetsApi.md#updateasset) | **PUT** /assets/{id} |
*AssetsApi* | [**updateAssets**](doc//AssetsApi.md#updateassets) | **PUT** /assets | *AssetsApi* | [**updateAssets**](doc//AssetsApi.md#updateassets) | **PUT** /assets |
@@ -408,8 +408,6 @@ Class | Method | HTTP request | Description
- [SharedLinkEditDto](doc//SharedLinkEditDto.md) - [SharedLinkEditDto](doc//SharedLinkEditDto.md)
- [SharedLinkResponseDto](doc//SharedLinkResponseDto.md) - [SharedLinkResponseDto](doc//SharedLinkResponseDto.md)
- [SharedLinkType](doc//SharedLinkType.md) - [SharedLinkType](doc//SharedLinkType.md)
- [SharedLinksResponse](doc//SharedLinksResponse.md)
- [SharedLinksUpdate](doc//SharedLinksUpdate.md)
- [SignUpDto](doc//SignUpDto.md) - [SignUpDto](doc//SignUpDto.md)
- [SmartSearchDto](doc//SmartSearchDto.md) - [SmartSearchDto](doc//SmartSearchDto.md)
- [SourceType](doc//SourceType.md) - [SourceType](doc//SourceType.md)

View File

@@ -221,8 +221,6 @@ part 'model/shared_link_create_dto.dart';
part 'model/shared_link_edit_dto.dart'; part 'model/shared_link_edit_dto.dart';
part 'model/shared_link_response_dto.dart'; part 'model/shared_link_response_dto.dart';
part 'model/shared_link_type.dart'; part 'model/shared_link_type.dart';
part 'model/shared_links_response.dart';
part 'model/shared_links_update.dart';
part 'model/sign_up_dto.dart'; part 'model/sign_up_dto.dart';
part 'model/smart_search_dto.dart'; part 'model/smart_search_dto.dart';
part 'model/source_type.dart'; part 'model/source_type.dart';

View File

@@ -16,8 +16,6 @@ class AssetsApi {
final ApiClient apiClient; final ApiClient apiClient;
/// checkBulkUpload
///
/// Checks if assets exist by checksums /// Checks if assets exist by checksums
/// ///
/// Note: This method returns the HTTP [Response]. /// Note: This method returns the HTTP [Response].
@@ -50,8 +48,6 @@ class AssetsApi {
); );
} }
/// checkBulkUpload
///
/// Checks if assets exist by checksums /// Checks if assets exist by checksums
/// ///
/// Parameters: /// Parameters:
@@ -72,8 +68,6 @@ class AssetsApi {
return null; return null;
} }
/// checkExistingAssets
///
/// Checks if multiple assets exist on the server and returns all existing - used by background backup /// Checks if multiple assets exist on the server and returns all existing - used by background backup
/// ///
/// Note: This method returns the HTTP [Response]. /// Note: This method returns the HTTP [Response].
@@ -106,8 +100,6 @@ class AssetsApi {
); );
} }
/// checkExistingAssets
///
/// Checks if multiple assets exist on the server and returns all existing - used by background backup /// Checks if multiple assets exist on the server and returns all existing - used by background backup
/// ///
/// Parameters: /// Parameters:
@@ -223,8 +215,6 @@ class AssetsApi {
return null; return null;
} }
/// getAllUserAssetsByDeviceId
///
/// Get all asset of a device that are in the database, ID only. /// Get all asset of a device that are in the database, ID only.
/// ///
/// Note: This method returns the HTTP [Response]. /// Note: This method returns the HTTP [Response].
@@ -258,8 +248,6 @@ class AssetsApi {
); );
} }
/// getAllUserAssetsByDeviceId
///
/// Get all asset of a device that are in the database, ID only. /// Get all asset of a device that are in the database, ID only.
/// ///
/// Parameters: /// Parameters:
@@ -576,8 +564,6 @@ class AssetsApi {
return null; return null;
} }
/// replaceAsset
///
/// Replace the asset with new file, without changing its id /// Replace the asset with new file, without changing its id
/// ///
/// Note: This method returns the HTTP [Response]. /// Note: This method returns the HTTP [Response].
@@ -659,8 +645,6 @@ class AssetsApi {
); );
} }
/// replaceAsset
///
/// Replace the asset with new file, without changing its id /// Replace the asset with new file, without changing its id
/// ///
/// Parameters: /// Parameters:

View File

@@ -127,10 +127,7 @@ class SharedLinksApi {
} }
/// Performs an HTTP 'GET /shared-links' operation and returns the [Response]. /// Performs an HTTP 'GET /shared-links' operation and returns the [Response].
/// Parameters: Future<Response> getAllSharedLinksWithHttpInfo() async {
///
/// * [String] albumId:
Future<Response> getAllSharedLinksWithHttpInfo({ String? albumId, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final path = r'/shared-links'; final path = r'/shared-links';
@@ -141,10 +138,6 @@ class SharedLinksApi {
final headerParams = <String, String>{}; final headerParams = <String, String>{};
final formParams = <String, String>{}; final formParams = <String, String>{};
if (albumId != null) {
queryParams.addAll(_queryParams('', 'albumId', albumId));
}
const contentTypes = <String>[]; const contentTypes = <String>[];
@@ -159,11 +152,8 @@ class SharedLinksApi {
); );
} }
/// Parameters: Future<List<SharedLinkResponseDto>?> getAllSharedLinks() async {
/// final response = await getAllSharedLinksWithHttpInfo();
/// * [String] albumId:
Future<List<SharedLinkResponseDto>?> getAllSharedLinks({ String? albumId, }) async {
final response = await getAllSharedLinksWithHttpInfo( albumId: albumId, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response)); throw ApiException(response.statusCode, await _decodeBodyBytes(response));
} }

View File

@@ -496,10 +496,6 @@ class ApiClient {
return SharedLinkResponseDto.fromJson(value); return SharedLinkResponseDto.fromJson(value);
case 'SharedLinkType': case 'SharedLinkType':
return SharedLinkTypeTypeTransformer().decode(value); return SharedLinkTypeTypeTransformer().decode(value);
case 'SharedLinksResponse':
return SharedLinksResponse.fromJson(value);
case 'SharedLinksUpdate':
return SharedLinksUpdate.fromJson(value);
case 'SignUpDto': case 'SignUpDto':
return SignUpDto.fromJson(value); return SignUpDto.fromJson(value);
case 'SmartSearchDto': case 'SmartSearchDto':

View File

@@ -20,7 +20,6 @@ class AssetBulkUpdateDto {
this.isFavorite, this.isFavorite,
this.latitude, this.latitude,
this.longitude, this.longitude,
this.orientation,
this.rating, this.rating,
}); });
@@ -68,8 +67,6 @@ class AssetBulkUpdateDto {
/// ///
num? longitude; num? longitude;
AssetBulkUpdateDtoOrientationEnum? orientation;
/// Minimum value: -1 /// Minimum value: -1
/// Maximum value: 5 /// Maximum value: 5
/// ///
@@ -89,7 +86,6 @@ class AssetBulkUpdateDto {
other.isFavorite == isFavorite && other.isFavorite == isFavorite &&
other.latitude == latitude && other.latitude == latitude &&
other.longitude == longitude && other.longitude == longitude &&
other.orientation == orientation &&
other.rating == rating; other.rating == rating;
@override @override
@@ -102,11 +98,10 @@ class AssetBulkUpdateDto {
(isFavorite == null ? 0 : isFavorite!.hashCode) + (isFavorite == null ? 0 : isFavorite!.hashCode) +
(latitude == null ? 0 : latitude!.hashCode) + (latitude == null ? 0 : latitude!.hashCode) +
(longitude == null ? 0 : longitude!.hashCode) + (longitude == null ? 0 : longitude!.hashCode) +
(orientation == null ? 0 : orientation!.hashCode) +
(rating == null ? 0 : rating!.hashCode); (rating == null ? 0 : rating!.hashCode);
@override @override
String toString() => 'AssetBulkUpdateDto[dateTimeOriginal=$dateTimeOriginal, duplicateId=$duplicateId, ids=$ids, isArchived=$isArchived, isFavorite=$isFavorite, latitude=$latitude, longitude=$longitude, orientation=$orientation, rating=$rating]'; String toString() => 'AssetBulkUpdateDto[dateTimeOriginal=$dateTimeOriginal, duplicateId=$duplicateId, ids=$ids, isArchived=$isArchived, isFavorite=$isFavorite, latitude=$latitude, longitude=$longitude, rating=$rating]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -141,11 +136,6 @@ class AssetBulkUpdateDto {
} else { } else {
// json[r'longitude'] = null; // json[r'longitude'] = null;
} }
if (this.orientation != null) {
json[r'orientation'] = this.orientation;
} else {
// json[r'orientation'] = null;
}
if (this.rating != null) { if (this.rating != null) {
json[r'rating'] = this.rating; json[r'rating'] = this.rating;
} else { } else {
@@ -172,7 +162,6 @@ class AssetBulkUpdateDto {
isFavorite: mapValueOfType<bool>(json, r'isFavorite'), isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
latitude: num.parse('${json[r'latitude']}'), latitude: num.parse('${json[r'latitude']}'),
longitude: num.parse('${json[r'longitude']}'), longitude: num.parse('${json[r'longitude']}'),
orientation: AssetBulkUpdateDtoOrientationEnum.fromJson(json[r'orientation']),
rating: num.parse('${json[r'rating']}'), rating: num.parse('${json[r'rating']}'),
); );
} }
@@ -225,95 +214,3 @@ class AssetBulkUpdateDto {
}; };
} }
class AssetBulkUpdateDtoOrientationEnum {
/// Instantiate a new enum with the provided [value].
const AssetBulkUpdateDtoOrientationEnum._(this.value);
/// The underlying value of this enum member.
final int value;
@override
String toString() => value.toString();
int toJson() => value;
static const number1 = AssetBulkUpdateDtoOrientationEnum._(1);
static const number2 = AssetBulkUpdateDtoOrientationEnum._(2);
static const number3 = AssetBulkUpdateDtoOrientationEnum._(3);
static const number4 = AssetBulkUpdateDtoOrientationEnum._(4);
static const number5 = AssetBulkUpdateDtoOrientationEnum._(5);
static const number6 = AssetBulkUpdateDtoOrientationEnum._(6);
static const number7 = AssetBulkUpdateDtoOrientationEnum._(7);
static const number8 = AssetBulkUpdateDtoOrientationEnum._(8);
/// List of all possible values in this [enum][AssetBulkUpdateDtoOrientationEnum].
static const values = <AssetBulkUpdateDtoOrientationEnum>[
number1,
number2,
number3,
number4,
number5,
number6,
number7,
number8,
];
static AssetBulkUpdateDtoOrientationEnum? fromJson(dynamic value) => AssetBulkUpdateDtoOrientationEnumTypeTransformer().decode(value);
static List<AssetBulkUpdateDtoOrientationEnum> listFromJson(dynamic json, {bool growable = false,}) {
final result = <AssetBulkUpdateDtoOrientationEnum>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = AssetBulkUpdateDtoOrientationEnum.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [AssetBulkUpdateDtoOrientationEnum] to int,
/// and [decode] dynamic data back to [AssetBulkUpdateDtoOrientationEnum].
class AssetBulkUpdateDtoOrientationEnumTypeTransformer {
factory AssetBulkUpdateDtoOrientationEnumTypeTransformer() => _instance ??= const AssetBulkUpdateDtoOrientationEnumTypeTransformer._();
const AssetBulkUpdateDtoOrientationEnumTypeTransformer._();
int encode(AssetBulkUpdateDtoOrientationEnum data) => data.value;
/// Decodes a [dynamic value][data] to a AssetBulkUpdateDtoOrientationEnum.
///
/// 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.
AssetBulkUpdateDtoOrientationEnum? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data) {
case 1: return AssetBulkUpdateDtoOrientationEnum.number1;
case 2: return AssetBulkUpdateDtoOrientationEnum.number2;
case 3: return AssetBulkUpdateDtoOrientationEnum.number3;
case 4: return AssetBulkUpdateDtoOrientationEnum.number4;
case 5: return AssetBulkUpdateDtoOrientationEnum.number5;
case 6: return AssetBulkUpdateDtoOrientationEnum.number6;
case 7: return AssetBulkUpdateDtoOrientationEnum.number7;
case 8: return AssetBulkUpdateDtoOrientationEnum.number8;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [AssetBulkUpdateDtoOrientationEnumTypeTransformer] instance.
static AssetBulkUpdateDtoOrientationEnumTypeTransformer? _instance;
}

View File

@@ -18,7 +18,6 @@ class MetadataSearchDto {
this.country, this.country,
this.createdAfter, this.createdAfter,
this.createdBefore, this.createdBefore,
this.description,
this.deviceAssetId, this.deviceAssetId,
this.deviceId, this.deviceId,
this.encodedVideoPath, this.encodedVideoPath,
@@ -42,7 +41,6 @@ class MetadataSearchDto {
this.previewPath, this.previewPath,
this.size, this.size,
this.state, this.state,
this.tagIds = const [],
this.takenAfter, this.takenAfter,
this.takenBefore, this.takenBefore,
this.thumbnailPath, this.thumbnailPath,
@@ -86,14 +84,6 @@ class MetadataSearchDto {
/// ///
DateTime? createdBefore; DateTime? createdBefore;
///
/// 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;
/// ///
/// 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
@@ -245,8 +235,6 @@ class MetadataSearchDto {
String? state; String? state;
List<String> tagIds;
/// ///
/// 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
@@ -352,7 +340,6 @@ class MetadataSearchDto {
other.country == country && other.country == country &&
other.createdAfter == createdAfter && other.createdAfter == createdAfter &&
other.createdBefore == createdBefore && other.createdBefore == createdBefore &&
other.description == description &&
other.deviceAssetId == deviceAssetId && other.deviceAssetId == deviceAssetId &&
other.deviceId == deviceId && other.deviceId == deviceId &&
other.encodedVideoPath == encodedVideoPath && other.encodedVideoPath == encodedVideoPath &&
@@ -376,7 +363,6 @@ class MetadataSearchDto {
other.previewPath == previewPath && other.previewPath == previewPath &&
other.size == size && other.size == size &&
other.state == state && other.state == state &&
_deepEquality.equals(other.tagIds, tagIds) &&
other.takenAfter == takenAfter && other.takenAfter == takenAfter &&
other.takenBefore == takenBefore && other.takenBefore == takenBefore &&
other.thumbnailPath == thumbnailPath && other.thumbnailPath == thumbnailPath &&
@@ -399,7 +385,6 @@ class MetadataSearchDto {
(country == null ? 0 : country!.hashCode) + (country == null ? 0 : country!.hashCode) +
(createdAfter == null ? 0 : createdAfter!.hashCode) + (createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) + (createdBefore == null ? 0 : createdBefore!.hashCode) +
(description == null ? 0 : description!.hashCode) +
(deviceAssetId == null ? 0 : deviceAssetId!.hashCode) + (deviceAssetId == null ? 0 : deviceAssetId!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) + (deviceId == null ? 0 : deviceId!.hashCode) +
(encodedVideoPath == null ? 0 : encodedVideoPath!.hashCode) + (encodedVideoPath == null ? 0 : encodedVideoPath!.hashCode) +
@@ -423,7 +408,6 @@ class MetadataSearchDto {
(previewPath == null ? 0 : previewPath!.hashCode) + (previewPath == null ? 0 : previewPath!.hashCode) +
(size == null ? 0 : size!.hashCode) + (size == null ? 0 : size!.hashCode) +
(state == null ? 0 : state!.hashCode) + (state == null ? 0 : state!.hashCode) +
(tagIds.hashCode) +
(takenAfter == null ? 0 : takenAfter!.hashCode) + (takenAfter == null ? 0 : takenAfter!.hashCode) +
(takenBefore == null ? 0 : takenBefore!.hashCode) + (takenBefore == null ? 0 : takenBefore!.hashCode) +
(thumbnailPath == null ? 0 : thumbnailPath!.hashCode) + (thumbnailPath == null ? 0 : thumbnailPath!.hashCode) +
@@ -439,7 +423,7 @@ class MetadataSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode); (withStacked == null ? 0 : withStacked!.hashCode);
@override @override
String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]'; String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -468,11 +452,6 @@ class MetadataSearchDto {
} else { } else {
// json[r'createdBefore'] = null; // json[r'createdBefore'] = null;
} }
if (this.description != null) {
json[r'description'] = this.description;
} else {
// json[r'description'] = null;
}
if (this.deviceAssetId != null) { if (this.deviceAssetId != null) {
json[r'deviceAssetId'] = this.deviceAssetId; json[r'deviceAssetId'] = this.deviceAssetId;
} else { } else {
@@ -580,7 +559,6 @@ class MetadataSearchDto {
} else { } else {
// json[r'state'] = null; // json[r'state'] = null;
} }
json[r'tagIds'] = this.tagIds;
if (this.takenAfter != null) { if (this.takenAfter != null) {
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String(); json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
} else { } else {
@@ -659,7 +637,6 @@ class MetadataSearchDto {
country: mapValueOfType<String>(json, r'country'), country: mapValueOfType<String>(json, r'country'),
createdAfter: mapDateTime(json, r'createdAfter', r''), createdAfter: mapDateTime(json, r'createdAfter', r''),
createdBefore: mapDateTime(json, r'createdBefore', r''), createdBefore: mapDateTime(json, r'createdBefore', r''),
description: mapValueOfType<String>(json, r'description'),
deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId'), deviceAssetId: mapValueOfType<String>(json, r'deviceAssetId'),
deviceId: mapValueOfType<String>(json, r'deviceId'), deviceId: mapValueOfType<String>(json, r'deviceId'),
encodedVideoPath: mapValueOfType<String>(json, r'encodedVideoPath'), encodedVideoPath: mapValueOfType<String>(json, r'encodedVideoPath'),
@@ -685,9 +662,6 @@ class MetadataSearchDto {
previewPath: mapValueOfType<String>(json, r'previewPath'), previewPath: mapValueOfType<String>(json, r'previewPath'),
size: num.parse('${json[r'size']}'), size: num.parse('${json[r'size']}'),
state: mapValueOfType<String>(json, r'state'), state: mapValueOfType<String>(json, r'state'),
tagIds: json[r'tagIds'] is Iterable
? (json[r'tagIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
takenAfter: mapDateTime(json, r'takenAfter', r''), takenAfter: mapDateTime(json, r'takenAfter', r''),
takenBefore: mapDateTime(json, r'takenBefore', r''), takenBefore: mapDateTime(json, r'takenBefore', r''),
thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath'), thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath'),

View File

@@ -14,10 +14,8 @@ class PeopleUpdateItem {
/// Returns a new [PeopleUpdateItem] instance. /// Returns a new [PeopleUpdateItem] instance.
PeopleUpdateItem({ PeopleUpdateItem({
this.birthDate, this.birthDate,
this.color,
this.featureFaceAssetId, this.featureFaceAssetId,
required this.id, required this.id,
this.isFavorite,
this.isHidden, this.isHidden,
this.name, this.name,
}); });
@@ -25,8 +23,6 @@ class PeopleUpdateItem {
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null. /// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
DateTime? birthDate; DateTime? birthDate;
String? color;
/// Asset is used to get the feature face thumbnail. /// Asset is used to get the feature face thumbnail.
/// ///
/// 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
@@ -39,14 +35,6 @@ class PeopleUpdateItem {
/// Person id. /// Person id.
String id; String id;
///
/// 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.
///
bool? isFavorite;
/// Person visibility /// Person visibility
/// ///
/// 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
@@ -68,10 +56,8 @@ class PeopleUpdateItem {
@override @override
bool operator ==(Object other) => identical(this, other) || other is PeopleUpdateItem && bool operator ==(Object other) => identical(this, other) || other is PeopleUpdateItem &&
other.birthDate == birthDate && other.birthDate == birthDate &&
other.color == color &&
other.featureFaceAssetId == featureFaceAssetId && other.featureFaceAssetId == featureFaceAssetId &&
other.id == id && other.id == id &&
other.isFavorite == isFavorite &&
other.isHidden == isHidden && other.isHidden == isHidden &&
other.name == name; other.name == name;
@@ -79,15 +65,13 @@ class PeopleUpdateItem {
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(birthDate == null ? 0 : birthDate!.hashCode) + (birthDate == null ? 0 : birthDate!.hashCode) +
(color == null ? 0 : color!.hashCode) +
(featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) + (featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
(id.hashCode) + (id.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isHidden == null ? 0 : isHidden!.hashCode) + (isHidden == null ? 0 : isHidden!.hashCode) +
(name == null ? 0 : name!.hashCode); (name == null ? 0 : name!.hashCode);
@override @override
String toString() => 'PeopleUpdateItem[birthDate=$birthDate, color=$color, featureFaceAssetId=$featureFaceAssetId, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]'; String toString() => 'PeopleUpdateItem[birthDate=$birthDate, featureFaceAssetId=$featureFaceAssetId, id=$id, isHidden=$isHidden, name=$name]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -96,22 +80,12 @@ class PeopleUpdateItem {
} else { } else {
// json[r'birthDate'] = null; // json[r'birthDate'] = null;
} }
if (this.color != null) {
json[r'color'] = this.color;
} else {
// json[r'color'] = null;
}
if (this.featureFaceAssetId != null) { if (this.featureFaceAssetId != null) {
json[r'featureFaceAssetId'] = this.featureFaceAssetId; json[r'featureFaceAssetId'] = this.featureFaceAssetId;
} else { } else {
// json[r'featureFaceAssetId'] = null; // json[r'featureFaceAssetId'] = null;
} }
json[r'id'] = this.id; json[r'id'] = this.id;
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
if (this.isHidden != null) { if (this.isHidden != null) {
json[r'isHidden'] = this.isHidden; json[r'isHidden'] = this.isHidden;
} else { } else {
@@ -135,10 +109,8 @@ class PeopleUpdateItem {
return PeopleUpdateItem( return PeopleUpdateItem(
birthDate: mapDateTime(json, r'birthDate', r''), birthDate: mapDateTime(json, r'birthDate', r''),
color: mapValueOfType<String>(json, r'color'),
featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'), featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
id: mapValueOfType<String>(json, r'id')!, id: mapValueOfType<String>(json, r'id')!,
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isHidden: mapValueOfType<bool>(json, r'isHidden'), isHidden: mapValueOfType<bool>(json, r'isHidden'),
name: mapValueOfType<String>(json, r'name'), name: mapValueOfType<String>(json, r'name'),
); );

View File

@@ -14,8 +14,6 @@ class PersonCreateDto {
/// Returns a new [PersonCreateDto] instance. /// Returns a new [PersonCreateDto] instance.
PersonCreateDto({ PersonCreateDto({
this.birthDate, this.birthDate,
this.color,
this.isFavorite,
this.isHidden, this.isHidden,
this.name, this.name,
}); });
@@ -23,16 +21,6 @@ class PersonCreateDto {
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null. /// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
DateTime? birthDate; DateTime? birthDate;
String? color;
///
/// 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.
///
bool? isFavorite;
/// Person visibility /// Person visibility
/// ///
/// 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
@@ -54,8 +42,6 @@ class PersonCreateDto {
@override @override
bool operator ==(Object other) => identical(this, other) || other is PersonCreateDto && bool operator ==(Object other) => identical(this, other) || other is PersonCreateDto &&
other.birthDate == birthDate && other.birthDate == birthDate &&
other.color == color &&
other.isFavorite == isFavorite &&
other.isHidden == isHidden && other.isHidden == isHidden &&
other.name == name; other.name == name;
@@ -63,13 +49,11 @@ class PersonCreateDto {
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(birthDate == null ? 0 : birthDate!.hashCode) + (birthDate == null ? 0 : birthDate!.hashCode) +
(color == null ? 0 : color!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isHidden == null ? 0 : isHidden!.hashCode) + (isHidden == null ? 0 : isHidden!.hashCode) +
(name == null ? 0 : name!.hashCode); (name == null ? 0 : name!.hashCode);
@override @override
String toString() => 'PersonCreateDto[birthDate=$birthDate, color=$color, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]'; String toString() => 'PersonCreateDto[birthDate=$birthDate, isHidden=$isHidden, name=$name]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -78,16 +62,6 @@ class PersonCreateDto {
} else { } else {
// json[r'birthDate'] = null; // json[r'birthDate'] = null;
} }
if (this.color != null) {
json[r'color'] = this.color;
} else {
// json[r'color'] = null;
}
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
if (this.isHidden != null) { if (this.isHidden != null) {
json[r'isHidden'] = this.isHidden; json[r'isHidden'] = this.isHidden;
} else { } else {
@@ -111,8 +85,6 @@ class PersonCreateDto {
return PersonCreateDto( return PersonCreateDto(
birthDate: mapDateTime(json, r'birthDate', r''), birthDate: mapDateTime(json, r'birthDate', r''),
color: mapValueOfType<String>(json, r'color'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isHidden: mapValueOfType<bool>(json, r'isHidden'), isHidden: mapValueOfType<bool>(json, r'isHidden'),
name: mapValueOfType<String>(json, r'name'), name: mapValueOfType<String>(json, r'name'),
); );

View File

@@ -14,9 +14,7 @@ class PersonResponseDto {
/// Returns a new [PersonResponseDto] instance. /// Returns a new [PersonResponseDto] instance.
PersonResponseDto({ PersonResponseDto({
required this.birthDate, required this.birthDate,
this.color,
required this.id, required this.id,
this.isFavorite,
required this.isHidden, required this.isHidden,
required this.name, required this.name,
required this.thumbnailPath, required this.thumbnailPath,
@@ -25,26 +23,8 @@ class PersonResponseDto {
DateTime? birthDate; DateTime? birthDate;
/// This property was added in v1.126.0
///
/// 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? color;
String id; String id;
/// This property was added in v1.126.0
///
/// 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.
///
bool? isFavorite;
bool isHidden; bool isHidden;
String name; String name;
@@ -63,9 +43,7 @@ class PersonResponseDto {
@override @override
bool operator ==(Object other) => identical(this, other) || other is PersonResponseDto && bool operator ==(Object other) => identical(this, other) || other is PersonResponseDto &&
other.birthDate == birthDate && other.birthDate == birthDate &&
other.color == color &&
other.id == id && other.id == id &&
other.isFavorite == isFavorite &&
other.isHidden == isHidden && other.isHidden == isHidden &&
other.name == name && other.name == name &&
other.thumbnailPath == thumbnailPath && other.thumbnailPath == thumbnailPath &&
@@ -75,16 +53,14 @@ class PersonResponseDto {
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(birthDate == null ? 0 : birthDate!.hashCode) + (birthDate == null ? 0 : birthDate!.hashCode) +
(color == null ? 0 : color!.hashCode) +
(id.hashCode) + (id.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isHidden.hashCode) + (isHidden.hashCode) +
(name.hashCode) + (name.hashCode) +
(thumbnailPath.hashCode) + (thumbnailPath.hashCode) +
(updatedAt == null ? 0 : updatedAt!.hashCode); (updatedAt == null ? 0 : updatedAt!.hashCode);
@override @override
String toString() => 'PersonResponseDto[birthDate=$birthDate, color=$color, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]'; String toString() => 'PersonResponseDto[birthDate=$birthDate, id=$id, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -92,18 +68,8 @@ class PersonResponseDto {
json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc()); json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc());
} else { } else {
// json[r'birthDate'] = null; // json[r'birthDate'] = null;
}
if (this.color != null) {
json[r'color'] = this.color;
} else {
// json[r'color'] = null;
} }
json[r'id'] = this.id; json[r'id'] = this.id;
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
json[r'isHidden'] = this.isHidden; json[r'isHidden'] = this.isHidden;
json[r'name'] = this.name; json[r'name'] = this.name;
json[r'thumbnailPath'] = this.thumbnailPath; json[r'thumbnailPath'] = this.thumbnailPath;
@@ -125,9 +91,7 @@ class PersonResponseDto {
return PersonResponseDto( return PersonResponseDto(
birthDate: mapDateTime(json, r'birthDate', r''), birthDate: mapDateTime(json, r'birthDate', r''),
color: mapValueOfType<String>(json, r'color'),
id: mapValueOfType<String>(json, r'id')!, id: mapValueOfType<String>(json, r'id')!,
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isHidden: mapValueOfType<bool>(json, r'isHidden')!, isHidden: mapValueOfType<bool>(json, r'isHidden')!,
name: mapValueOfType<String>(json, r'name')!, name: mapValueOfType<String>(json, r'name')!,
thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath')!, thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath')!,

View File

@@ -14,9 +14,7 @@ class PersonUpdateDto {
/// Returns a new [PersonUpdateDto] instance. /// Returns a new [PersonUpdateDto] instance.
PersonUpdateDto({ PersonUpdateDto({
this.birthDate, this.birthDate,
this.color,
this.featureFaceAssetId, this.featureFaceAssetId,
this.isFavorite,
this.isHidden, this.isHidden,
this.name, this.name,
}); });
@@ -24,8 +22,6 @@ class PersonUpdateDto {
/// Person date of birth. Note: the mobile app cannot currently set the birth date to null. /// Person date of birth. Note: the mobile app cannot currently set the birth date to null.
DateTime? birthDate; DateTime? birthDate;
String? color;
/// Asset is used to get the feature face thumbnail. /// Asset is used to get the feature face thumbnail.
/// ///
/// 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
@@ -35,14 +31,6 @@ class PersonUpdateDto {
/// ///
String? featureFaceAssetId; String? featureFaceAssetId;
///
/// 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.
///
bool? isFavorite;
/// Person visibility /// Person visibility
/// ///
/// 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
@@ -64,9 +52,7 @@ class PersonUpdateDto {
@override @override
bool operator ==(Object other) => identical(this, other) || other is PersonUpdateDto && bool operator ==(Object other) => identical(this, other) || other is PersonUpdateDto &&
other.birthDate == birthDate && other.birthDate == birthDate &&
other.color == color &&
other.featureFaceAssetId == featureFaceAssetId && other.featureFaceAssetId == featureFaceAssetId &&
other.isFavorite == isFavorite &&
other.isHidden == isHidden && other.isHidden == isHidden &&
other.name == name; other.name == name;
@@ -74,14 +60,12 @@ class PersonUpdateDto {
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(birthDate == null ? 0 : birthDate!.hashCode) + (birthDate == null ? 0 : birthDate!.hashCode) +
(color == null ? 0 : color!.hashCode) +
(featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) + (featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isHidden == null ? 0 : isHidden!.hashCode) + (isHidden == null ? 0 : isHidden!.hashCode) +
(name == null ? 0 : name!.hashCode); (name == null ? 0 : name!.hashCode);
@override @override
String toString() => 'PersonUpdateDto[birthDate=$birthDate, color=$color, featureFaceAssetId=$featureFaceAssetId, isFavorite=$isFavorite, isHidden=$isHidden, name=$name]'; String toString() => 'PersonUpdateDto[birthDate=$birthDate, featureFaceAssetId=$featureFaceAssetId, isHidden=$isHidden, name=$name]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -90,21 +74,11 @@ class PersonUpdateDto {
} else { } else {
// json[r'birthDate'] = null; // json[r'birthDate'] = null;
} }
if (this.color != null) {
json[r'color'] = this.color;
} else {
// json[r'color'] = null;
}
if (this.featureFaceAssetId != null) { if (this.featureFaceAssetId != null) {
json[r'featureFaceAssetId'] = this.featureFaceAssetId; json[r'featureFaceAssetId'] = this.featureFaceAssetId;
} else { } else {
// json[r'featureFaceAssetId'] = null; // json[r'featureFaceAssetId'] = null;
} }
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
if (this.isHidden != null) { if (this.isHidden != null) {
json[r'isHidden'] = this.isHidden; json[r'isHidden'] = this.isHidden;
} else { } else {
@@ -128,9 +102,7 @@ class PersonUpdateDto {
return PersonUpdateDto( return PersonUpdateDto(
birthDate: mapDateTime(json, r'birthDate', r''), birthDate: mapDateTime(json, r'birthDate', r''),
color: mapValueOfType<String>(json, r'color'),
featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'), featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isHidden: mapValueOfType<bool>(json, r'isHidden'), isHidden: mapValueOfType<bool>(json, r'isHidden'),
name: mapValueOfType<String>(json, r'name'), name: mapValueOfType<String>(json, r'name'),
); );

View File

@@ -14,10 +14,8 @@ class PersonWithFacesResponseDto {
/// Returns a new [PersonWithFacesResponseDto] instance. /// Returns a new [PersonWithFacesResponseDto] instance.
PersonWithFacesResponseDto({ PersonWithFacesResponseDto({
required this.birthDate, required this.birthDate,
this.color,
this.faces = const [], this.faces = const [],
required this.id, required this.id,
this.isFavorite,
required this.isHidden, required this.isHidden,
required this.name, required this.name,
required this.thumbnailPath, required this.thumbnailPath,
@@ -26,28 +24,10 @@ class PersonWithFacesResponseDto {
DateTime? birthDate; DateTime? birthDate;
/// This property was added in v1.126.0
///
/// 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? color;
List<AssetFaceWithoutPersonResponseDto> faces; List<AssetFaceWithoutPersonResponseDto> faces;
String id; String id;
/// This property was added in v1.126.0
///
/// 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.
///
bool? isFavorite;
bool isHidden; bool isHidden;
String name; String name;
@@ -66,10 +46,8 @@ class PersonWithFacesResponseDto {
@override @override
bool operator ==(Object other) => identical(this, other) || other is PersonWithFacesResponseDto && bool operator ==(Object other) => identical(this, other) || other is PersonWithFacesResponseDto &&
other.birthDate == birthDate && other.birthDate == birthDate &&
other.color == color &&
_deepEquality.equals(other.faces, faces) && _deepEquality.equals(other.faces, faces) &&
other.id == id && other.id == id &&
other.isFavorite == isFavorite &&
other.isHidden == isHidden && other.isHidden == isHidden &&
other.name == name && other.name == name &&
other.thumbnailPath == thumbnailPath && other.thumbnailPath == thumbnailPath &&
@@ -79,17 +57,15 @@ class PersonWithFacesResponseDto {
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(birthDate == null ? 0 : birthDate!.hashCode) + (birthDate == null ? 0 : birthDate!.hashCode) +
(color == null ? 0 : color!.hashCode) +
(faces.hashCode) + (faces.hashCode) +
(id.hashCode) + (id.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isHidden.hashCode) + (isHidden.hashCode) +
(name.hashCode) + (name.hashCode) +
(thumbnailPath.hashCode) + (thumbnailPath.hashCode) +
(updatedAt == null ? 0 : updatedAt!.hashCode); (updatedAt == null ? 0 : updatedAt!.hashCode);
@override @override
String toString() => 'PersonWithFacesResponseDto[birthDate=$birthDate, color=$color, faces=$faces, id=$id, isFavorite=$isFavorite, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]'; String toString() => 'PersonWithFacesResponseDto[birthDate=$birthDate, faces=$faces, id=$id, isHidden=$isHidden, name=$name, thumbnailPath=$thumbnailPath, updatedAt=$updatedAt]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -97,19 +73,9 @@ class PersonWithFacesResponseDto {
json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc()); json[r'birthDate'] = _dateFormatter.format(this.birthDate!.toUtc());
} else { } else {
// json[r'birthDate'] = null; // json[r'birthDate'] = null;
}
if (this.color != null) {
json[r'color'] = this.color;
} else {
// json[r'color'] = null;
} }
json[r'faces'] = this.faces; json[r'faces'] = this.faces;
json[r'id'] = this.id; json[r'id'] = this.id;
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
json[r'isHidden'] = this.isHidden; json[r'isHidden'] = this.isHidden;
json[r'name'] = this.name; json[r'name'] = this.name;
json[r'thumbnailPath'] = this.thumbnailPath; json[r'thumbnailPath'] = this.thumbnailPath;
@@ -131,10 +97,8 @@ class PersonWithFacesResponseDto {
return PersonWithFacesResponseDto( return PersonWithFacesResponseDto(
birthDate: mapDateTime(json, r'birthDate', r''), birthDate: mapDateTime(json, r'birthDate', r''),
color: mapValueOfType<String>(json, r'color'),
faces: AssetFaceWithoutPersonResponseDto.listFromJson(json[r'faces']), faces: AssetFaceWithoutPersonResponseDto.listFromJson(json[r'faces']),
id: mapValueOfType<String>(json, r'id')!, id: mapValueOfType<String>(json, r'id')!,
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isHidden: mapValueOfType<bool>(json, r'isHidden')!, isHidden: mapValueOfType<bool>(json, r'isHidden')!,
name: mapValueOfType<String>(json, r'name')!, name: mapValueOfType<String>(json, r'name')!,
thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath')!, thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath')!,

View File

@@ -32,7 +32,6 @@ class RandomSearchDto {
this.personIds = const [], this.personIds = const [],
this.size, this.size,
this.state, this.state,
this.tagIds = const [],
this.takenAfter, this.takenAfter,
this.takenBefore, this.takenBefore,
this.trashedAfter, this.trashedAfter,
@@ -159,8 +158,6 @@ class RandomSearchDto {
String? state; String? state;
List<String> tagIds;
/// ///
/// 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
@@ -272,7 +269,6 @@ class RandomSearchDto {
_deepEquality.equals(other.personIds, personIds) && _deepEquality.equals(other.personIds, personIds) &&
other.size == size && other.size == size &&
other.state == state && other.state == state &&
_deepEquality.equals(other.tagIds, tagIds) &&
other.takenAfter == takenAfter && other.takenAfter == takenAfter &&
other.takenBefore == takenBefore && other.takenBefore == takenBefore &&
other.trashedAfter == trashedAfter && other.trashedAfter == trashedAfter &&
@@ -308,7 +304,6 @@ class RandomSearchDto {
(personIds.hashCode) + (personIds.hashCode) +
(size == null ? 0 : size!.hashCode) + (size == null ? 0 : size!.hashCode) +
(state == null ? 0 : state!.hashCode) + (state == null ? 0 : state!.hashCode) +
(tagIds.hashCode) +
(takenAfter == null ? 0 : takenAfter!.hashCode) + (takenAfter == null ? 0 : takenAfter!.hashCode) +
(takenBefore == null ? 0 : takenBefore!.hashCode) + (takenBefore == null ? 0 : takenBefore!.hashCode) +
(trashedAfter == null ? 0 : trashedAfter!.hashCode) + (trashedAfter == null ? 0 : trashedAfter!.hashCode) +
@@ -323,7 +318,7 @@ class RandomSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode); (withStacked == null ? 0 : withStacked!.hashCode);
@override @override
String toString() => 'RandomSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, personIds=$personIds, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]'; String toString() => 'RandomSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, personIds=$personIds, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -418,7 +413,6 @@ class RandomSearchDto {
} else { } else {
// json[r'state'] = null; // json[r'state'] = null;
} }
json[r'tagIds'] = this.tagIds;
if (this.takenAfter != null) { if (this.takenAfter != null) {
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String(); json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
} else { } else {
@@ -508,9 +502,6 @@ class RandomSearchDto {
: const [], : const [],
size: num.parse('${json[r'size']}'), size: num.parse('${json[r'size']}'),
state: mapValueOfType<String>(json, r'state'), state: mapValueOfType<String>(json, r'state'),
tagIds: json[r'tagIds'] is Iterable
? (json[r'tagIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
takenAfter: mapDateTime(json, r'takenAfter', r''), takenAfter: mapDateTime(json, r'takenAfter', r''),
takenBefore: mapDateTime(json, r'takenBefore', r''), takenBefore: mapDateTime(json, r'takenBefore', r''),
trashedAfter: mapDateTime(json, r'trashedAfter', r''), trashedAfter: mapDateTime(json, r'trashedAfter', r''),

View File

@@ -1,107 +0,0 @@
//
// 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 SharedLinksResponse {
/// Returns a new [SharedLinksResponse] instance.
SharedLinksResponse({
this.enabled = true,
this.sidebarWeb = false,
});
bool enabled;
bool sidebarWeb;
@override
bool operator ==(Object other) => identical(this, other) || other is SharedLinksResponse &&
other.enabled == enabled &&
other.sidebarWeb == sidebarWeb;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(enabled.hashCode) +
(sidebarWeb.hashCode);
@override
String toString() => 'SharedLinksResponse[enabled=$enabled, sidebarWeb=$sidebarWeb]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'enabled'] = this.enabled;
json[r'sidebarWeb'] = this.sidebarWeb;
return json;
}
/// Returns a new [SharedLinksResponse] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static SharedLinksResponse? fromJson(dynamic value) {
upgradeDto(value, "SharedLinksResponse");
if (value is Map) {
final json = value.cast<String, dynamic>();
return SharedLinksResponse(
enabled: mapValueOfType<bool>(json, r'enabled')!,
sidebarWeb: mapValueOfType<bool>(json, r'sidebarWeb')!,
);
}
return null;
}
static List<SharedLinksResponse> listFromJson(dynamic json, {bool growable = false,}) {
final result = <SharedLinksResponse>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = SharedLinksResponse.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, SharedLinksResponse> mapFromJson(dynamic json) {
final map = <String, SharedLinksResponse>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = SharedLinksResponse.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of SharedLinksResponse-objects as value to a dart map
static Map<String, List<SharedLinksResponse>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<SharedLinksResponse>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = SharedLinksResponse.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'enabled',
'sidebarWeb',
};
}

View File

@@ -1,125 +0,0 @@
//
// 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 SharedLinksUpdate {
/// Returns a new [SharedLinksUpdate] instance.
SharedLinksUpdate({
this.enabled,
this.sidebarWeb,
});
///
/// 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.
///
bool? enabled;
///
/// 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.
///
bool? sidebarWeb;
@override
bool operator ==(Object other) => identical(this, other) || other is SharedLinksUpdate &&
other.enabled == enabled &&
other.sidebarWeb == sidebarWeb;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(enabled == null ? 0 : enabled!.hashCode) +
(sidebarWeb == null ? 0 : sidebarWeb!.hashCode);
@override
String toString() => 'SharedLinksUpdate[enabled=$enabled, sidebarWeb=$sidebarWeb]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.enabled != null) {
json[r'enabled'] = this.enabled;
} else {
// json[r'enabled'] = null;
}
if (this.sidebarWeb != null) {
json[r'sidebarWeb'] = this.sidebarWeb;
} else {
// json[r'sidebarWeb'] = null;
}
return json;
}
/// Returns a new [SharedLinksUpdate] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static SharedLinksUpdate? fromJson(dynamic value) {
upgradeDto(value, "SharedLinksUpdate");
if (value is Map) {
final json = value.cast<String, dynamic>();
return SharedLinksUpdate(
enabled: mapValueOfType<bool>(json, r'enabled'),
sidebarWeb: mapValueOfType<bool>(json, r'sidebarWeb'),
);
}
return null;
}
static List<SharedLinksUpdate> listFromJson(dynamic json, {bool growable = false,}) {
final result = <SharedLinksUpdate>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = SharedLinksUpdate.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, SharedLinksUpdate> mapFromJson(dynamic json) {
final map = <String, SharedLinksUpdate>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = SharedLinksUpdate.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of SharedLinksUpdate-objects as value to a dart map
static Map<String, List<SharedLinksUpdate>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<SharedLinksUpdate>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = SharedLinksUpdate.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
};
}

View File

@@ -34,7 +34,6 @@ class SmartSearchDto {
required this.query, required this.query,
this.size, this.size,
this.state, this.state,
this.tagIds = const [],
this.takenAfter, this.takenAfter,
this.takenBefore, this.takenBefore,
this.trashedAfter, this.trashedAfter,
@@ -170,8 +169,6 @@ class SmartSearchDto {
String? state; String? state;
List<String> tagIds;
/// ///
/// 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
@@ -269,7 +266,6 @@ class SmartSearchDto {
other.query == query && other.query == query &&
other.size == size && other.size == size &&
other.state == state && other.state == state &&
_deepEquality.equals(other.tagIds, tagIds) &&
other.takenAfter == takenAfter && other.takenAfter == takenAfter &&
other.takenBefore == takenBefore && other.takenBefore == takenBefore &&
other.trashedAfter == trashedAfter && other.trashedAfter == trashedAfter &&
@@ -305,7 +301,6 @@ class SmartSearchDto {
(query.hashCode) + (query.hashCode) +
(size == null ? 0 : size!.hashCode) + (size == null ? 0 : size!.hashCode) +
(state == null ? 0 : state!.hashCode) + (state == null ? 0 : state!.hashCode) +
(tagIds.hashCode) +
(takenAfter == null ? 0 : takenAfter!.hashCode) + (takenAfter == null ? 0 : takenAfter!.hashCode) +
(takenBefore == null ? 0 : takenBefore!.hashCode) + (takenBefore == null ? 0 : takenBefore!.hashCode) +
(trashedAfter == null ? 0 : trashedAfter!.hashCode) + (trashedAfter == null ? 0 : trashedAfter!.hashCode) +
@@ -318,7 +313,7 @@ class SmartSearchDto {
(withExif == null ? 0 : withExif!.hashCode); (withExif == null ? 0 : withExif!.hashCode);
@override @override
String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]'; String toString() => 'SmartSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@@ -419,7 +414,6 @@ class SmartSearchDto {
} else { } else {
// json[r'state'] = null; // json[r'state'] = null;
} }
json[r'tagIds'] = this.tagIds;
if (this.takenAfter != null) { if (this.takenAfter != null) {
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String(); json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
} else { } else {
@@ -501,9 +495,6 @@ class SmartSearchDto {
query: mapValueOfType<String>(json, r'query')!, query: mapValueOfType<String>(json, r'query')!,
size: num.parse('${json[r'size']}'), size: num.parse('${json[r'size']}'),
state: mapValueOfType<String>(json, r'state'), state: mapValueOfType<String>(json, r'state'),
tagIds: json[r'tagIds'] is Iterable
? (json[r'tagIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
takenAfter: mapDateTime(json, r'takenAfter', r''), takenAfter: mapDateTime(json, r'takenAfter', r''),
takenBefore: mapDateTime(json, r'takenBefore', r''), takenBefore: mapDateTime(json, r'takenBefore', r''),
trashedAfter: mapDateTime(json, r'trashedAfter', r''), trashedAfter: mapDateTime(json, r'trashedAfter', r''),

Some files were not shown because too many files have changed in this diff Show More