diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index a107c1ac3a..9dd57a5ec8 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -4,7 +4,7 @@ FROM ${BASEIMAGE}
# Flutter SDK
# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux
ENV FLUTTER_CHANNEL="stable"
-ENV FLUTTER_VERSION="3.24.5"
+ENV FLUTTER_VERSION="3.29.1"
ENV FLUTTER_HOME=/flutter
ENV PATH=${PATH}:${FLUTTER_HOME}/bin
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml
index 7cfd75c61b..1243a81105 100644
--- a/.github/workflows/cli.yml
+++ b/.github/workflows/cli.yml
@@ -56,7 +56,7 @@ jobs:
uses: actions/checkout@v4
- name: Set up QEMU
- uses: docker/setup-qemu-action@v3.5.0
+ uses: docker/setup-qemu-action@v3.6.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.10.0
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 96970fa460..12f3410310 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -255,19 +255,20 @@ jobs:
flavor: |
# Disable latest tag
latest=false
+ suffix=${{ matrix.suffix }}
images: |
name=${{ env.GHCR_REPO }}
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
tags: |
# Tag with branch name
- type=ref,event=branch,suffix=${{ matrix.suffix }}
+ type=ref,event=branch
# Tag with pr-number
- type=ref,event=pr,suffix=${{ matrix.suffix }}
+ type=ref,event=pr
# Tag with long commit sha hash
- type=sha,format=long,prefix=commit-,suffix=${{ matrix.suffix }}
+ type=sha,format=long,prefix=commit-
# Tag with git tag on release
- type=ref,event=tag,suffix=${{ matrix.suffix }}
- type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
+ type=ref,event=tag
+ type=raw,value=release,enable=${{ github.event_name == 'release' }}
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
@@ -408,19 +409,20 @@ jobs:
flavor: |
# Disable latest tag
latest=false
+ suffix=${{ matrix.suffix }}
images: |
name=${{ env.GHCR_REPO }}
name=${{ env.DOCKER_REPO }},enable=${{ github.event_name == 'release' }}
tags: |
# Tag with branch name
- type=ref,event=branch,suffix=${{ matrix.suffix }}
+ type=ref,event=branch
# Tag with pr-number
- type=ref,event=pr,suffix=${{ matrix.suffix }}
+ type=ref,event=pr
# Tag with long commit sha hash
- type=sha,format=long,prefix=commit-,suffix=${{ matrix.suffix }}
+ type=sha,format=long,prefix=commit-
# Tag with git tag on release
- type=ref,event=tag,suffix=${{ matrix.suffix }}
- type=raw,value=release,enable=${{ github.event_name == 'release' }},suffix=${{ matrix.suffix }}
+ type=ref,event=tag
+ type=raw,value=release,enable=${{ github.event_name == 'release' }}
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
diff --git a/.github/workflows/preview-label.yaml b/.github/workflows/preview-label.yaml
index 6468d05e80..1c324ab49f 100644
--- a/.github/workflows/preview-label.yaml
+++ b/.github/workflows/preview-label.yaml
@@ -2,7 +2,7 @@ name: Preview label
on:
pull_request:
- types: [labeled]
+ types: [labeled, closed]
jobs:
comment-status:
diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml
index 4d8d40a47b..1e2020a19d 100644
--- a/.github/workflows/static_analysis.yml
+++ b/.github/workflows/static_analysis.yml
@@ -50,6 +50,26 @@ jobs:
run: dart pub get
working-directory: ./mobile
+ - name: Run Build Runner
+ run: make build
+ working-directory: ./mobile
+
+ - name: Find file changes
+ uses: tj-actions/verify-changed-files@v20
+ id: verify-changed-files
+ with:
+ files: |
+ mobile/**/*.g.dart
+ mobile/**/*.gr.dart
+ mobile/**/*.drift.dart
+
+ - name: Verify files have not changed
+ if: steps.verify-changed-files.outputs.files_changed == 'true'
+ run: |
+ echo "ERROR: Generated files not up to date! Run make_build inside the mobile directory"
+ echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
+ exit 1
+
- name: Run dart analyze
run: dart analyze --fatal-infos
working-directory: ./mobile
@@ -61,8 +81,3 @@ jobs:
- name: Run dart custom_lint
run: dart run custom_lint
working-directory: ./mobile
-
- # Enable after riverpod generator migration is completed
- # - name: Run dart custom lint
- # run: dart run custom_lint
- # working-directory: ./mobile
diff --git a/.github/workflows/weblate-lock.yml b/.github/workflows/weblate-lock.yml
index 29a30640bd..4189e51919 100644
--- a/.github/workflows/weblate-lock.yml
+++ b/.github/workflows/weblate-lock.yml
@@ -18,8 +18,15 @@ jobs:
filters: |
i18n:
- 'i18n/!(en)**\.json'
+ - name: Debug
+ run: |
+ echo "Should run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}"
+ echo "Found i18n paths: ${{ steps.found_paths.outputs.i18n }}"
+ echo "Head ref: ${{ github.head_ref }}"
+
enforce-lock:
name: Check Weblate Lock
+ needs: [ pre-job ]
runs-on: ubuntu-latest
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
steps:
diff --git a/cli/package-lock.json b/cli/package-lock.json
index 2b40efdb45..3b16a3bf18 100644
--- a/cli/package-lock.json
+++ b/cli/package-lock.json
@@ -27,7 +27,7 @@
"@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.9",
"@types/mock-fs": "^4.13.1",
- "@types/node": "^22.13.5",
+ "@types/node": "^22.13.9",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0",
"@vitest/coverage-v8": "^3.0.0",
@@ -62,7 +62,7 @@
"@oazapfts/runtime": "^1.0.2"
},
"devDependencies": {
- "@types/node": "^22.13.5",
+ "@types/node": "^22.13.9",
"typescript": "^5.3.3"
}
},
@@ -1502,9 +1502,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.13.8",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.8.tgz",
- "integrity": "sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ==",
+ "version": "22.13.10",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
+ "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1518,17 +1518,17 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.25.0.tgz",
- "integrity": "sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz",
+ "integrity": "sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.25.0",
- "@typescript-eslint/type-utils": "8.25.0",
- "@typescript-eslint/utils": "8.25.0",
- "@typescript-eslint/visitor-keys": "8.25.0",
+ "@typescript-eslint/scope-manager": "8.26.0",
+ "@typescript-eslint/type-utils": "8.26.0",
+ "@typescript-eslint/utils": "8.26.0",
+ "@typescript-eslint/visitor-keys": "8.26.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -1544,20 +1544,20 @@
"peerDependencies": {
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz",
- "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.0.tgz",
+ "integrity": "sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.25.0",
- "@typescript-eslint/types": "8.25.0",
- "@typescript-eslint/typescript-estree": "8.25.0",
- "@typescript-eslint/visitor-keys": "8.25.0",
+ "@typescript-eslint/scope-manager": "8.26.0",
+ "@typescript-eslint/types": "8.26.0",
+ "@typescript-eslint/typescript-estree": "8.26.0",
+ "@typescript-eslint/visitor-keys": "8.26.0",
"debug": "^4.3.4"
},
"engines": {
@@ -1569,18 +1569,18 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz",
- "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz",
+ "integrity": "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.25.0",
- "@typescript-eslint/visitor-keys": "8.25.0"
+ "@typescript-eslint/types": "8.26.0",
+ "@typescript-eslint/visitor-keys": "8.26.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1591,14 +1591,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.25.0.tgz",
- "integrity": "sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz",
+ "integrity": "sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.25.0",
- "@typescript-eslint/utils": "8.25.0",
+ "@typescript-eslint/typescript-estree": "8.26.0",
+ "@typescript-eslint/utils": "8.26.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.0.1"
},
@@ -1611,13 +1611,13 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz",
- "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz",
+ "integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1629,14 +1629,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz",
- "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz",
+ "integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.25.0",
- "@typescript-eslint/visitor-keys": "8.25.0",
+ "@typescript-eslint/types": "8.26.0",
+ "@typescript-eslint/visitor-keys": "8.26.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -1652,20 +1652,20 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.25.0.tgz",
- "integrity": "sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.0.tgz",
+ "integrity": "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.25.0",
- "@typescript-eslint/types": "8.25.0",
- "@typescript-eslint/typescript-estree": "8.25.0"
+ "@typescript-eslint/scope-manager": "8.26.0",
+ "@typescript-eslint/types": "8.26.0",
+ "@typescript-eslint/typescript-estree": "8.26.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1676,17 +1676,17 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.25.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz",
- "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==",
+ "version": "8.26.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz",
+ "integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.25.0",
+ "@typescript-eslint/types": "8.26.0",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@@ -1711,9 +1711,9 @@
}
},
"node_modules/@vitest/coverage-v8": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.7.tgz",
- "integrity": "sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.8.tgz",
+ "integrity": "sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1734,8 +1734,8 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "3.0.7",
- "vitest": "3.0.7"
+ "@vitest/browser": "3.0.8",
+ "vitest": "3.0.8"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -1744,14 +1744,14 @@
}
},
"node_modules/@vitest/expect": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.7.tgz",
- "integrity": "sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz",
+ "integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "3.0.7",
- "@vitest/utils": "3.0.7",
+ "@vitest/spy": "3.0.8",
+ "@vitest/utils": "3.0.8",
"chai": "^5.2.0",
"tinyrainbow": "^2.0.0"
},
@@ -1760,13 +1760,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.7.tgz",
- "integrity": "sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz",
+ "integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "3.0.7",
+ "@vitest/spy": "3.0.8",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.17"
},
@@ -1787,9 +1787,9 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.7.tgz",
- "integrity": "sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz",
+ "integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1800,13 +1800,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.7.tgz",
- "integrity": "sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz",
+ "integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "3.0.7",
+ "@vitest/utils": "3.0.8",
"pathe": "^2.0.3"
},
"funding": {
@@ -1814,13 +1814,13 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.7.tgz",
- "integrity": "sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz",
+ "integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "3.0.7",
+ "@vitest/pretty-format": "3.0.8",
"magic-string": "^0.30.17",
"pathe": "^2.0.3"
},
@@ -1829,9 +1829,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.7.tgz",
- "integrity": "sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz",
+ "integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1842,13 +1842,13 @@
}
},
"node_modules/@vitest/utils": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.7.tgz",
- "integrity": "sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz",
+ "integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "3.0.7",
+ "@vitest/pretty-format": "3.0.8",
"loupe": "^3.1.3",
"tinyrainbow": "^2.0.0"
},
@@ -2429,13 +2429,13 @@
}
},
"node_modules/eslint-config-prettier": {
- "version": "10.0.2",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.2.tgz",
- "integrity": "sha512-1105/17ZIMjmCOJOPNfVdbXafLCLj3hPmkmB7dLgt7XsQ/zkxSuDerE/xgO3RxoHysR1N1whmquY0lSn2O0VLg==",
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz",
+ "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==",
"dev": true,
"license": "MIT",
"bin": {
- "eslint-config-prettier": "build/bin/cli.js"
+ "eslint-config-prettier": "bin/cli.js"
},
"peerDependencies": {
"eslint": ">=7.0.0"
@@ -3617,9 +3617,9 @@
}
},
"node_modules/prettier": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz",
- "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==",
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
+ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -4278,9 +4278,9 @@
}
},
"node_modules/typescript": {
- "version": "5.7.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
- "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
+ "version": "5.8.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
+ "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4349,9 +4349,9 @@
}
},
"node_modules/vite": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
- "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz",
+ "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4421,9 +4421,9 @@
}
},
"node_modules/vite-node": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.7.tgz",
- "integrity": "sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz",
+ "integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4464,19 +4464,19 @@
}
},
"node_modules/vitest": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.7.tgz",
- "integrity": "sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz",
+ "integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "3.0.7",
- "@vitest/mocker": "3.0.7",
- "@vitest/pretty-format": "^3.0.7",
- "@vitest/runner": "3.0.7",
- "@vitest/snapshot": "3.0.7",
- "@vitest/spy": "3.0.7",
- "@vitest/utils": "3.0.7",
+ "@vitest/expect": "3.0.8",
+ "@vitest/mocker": "3.0.8",
+ "@vitest/pretty-format": "^3.0.8",
+ "@vitest/runner": "3.0.8",
+ "@vitest/snapshot": "3.0.8",
+ "@vitest/spy": "3.0.8",
+ "@vitest/utils": "3.0.8",
"chai": "^5.2.0",
"debug": "^4.4.0",
"expect-type": "^1.1.0",
@@ -4488,7 +4488,7 @@
"tinypool": "^1.0.2",
"tinyrainbow": "^2.0.0",
"vite": "^5.0.0 || ^6.0.0",
- "vite-node": "3.0.7",
+ "vite-node": "3.0.8",
"why-is-node-running": "^2.3.0"
},
"bin": {
@@ -4504,8 +4504,8 @@
"@edge-runtime/vm": "*",
"@types/debug": "^4.1.12",
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
- "@vitest/browser": "3.0.7",
- "@vitest/ui": "3.0.7",
+ "@vitest/browser": "3.0.8",
+ "@vitest/ui": "3.0.8",
"happy-dom": "*",
"jsdom": "*"
},
@@ -4534,9 +4534,9 @@
}
},
"node_modules/vitest-fetch-mock": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/vitest-fetch-mock/-/vitest-fetch-mock-0.4.4.tgz",
- "integrity": "sha512-i2RNEAKBgnLWwj5DVz8ouzaHaPVg1xaYgAUmU5p+baJ149upnO+yJLPchAiY9ij8hf0PDkJVVke1pftBxmT05g==",
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/vitest-fetch-mock/-/vitest-fetch-mock-0.4.5.tgz",
+ "integrity": "sha512-nhWdCQIGtaSEUVl96pMm0WggyDGPDv5FUy/Q9Hx3cs2RGmh3Q/uRsLClGbdG3kXBkJ3br5yTUjB2MeW25TwdOA==",
"dev": true,
"license": "MIT",
"engines": {
diff --git a/cli/package.json b/cli/package.json
index e8c207fb27..334bcc0b0c 100644
--- a/cli/package.json
+++ b/cli/package.json
@@ -21,7 +21,7 @@
"@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.9",
"@types/mock-fs": "^4.13.1",
- "@types/node": "^22.13.5",
+ "@types/node": "^22.13.9",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"@typescript-eslint/parser": "^8.15.0",
"@vitest/coverage-v8": "^3.0.0",
diff --git a/docs/docs/administration/backup-and-restore.md b/docs/docs/administration/backup-and-restore.md
index 1b5cdba19a..817a7dca6d 100644
--- a/docs/docs/administration/backup-and-restore.md
+++ b/docs/docs/administration/backup-and-restore.md
@@ -30,6 +30,13 @@ As mentioned above, you should make your own backup of these together with the a
You can adjust the schedule and amount of kept backups in the [admin settings](http://my.immich.app/admin/system-settings?isOpen=backup).
By default, Immich will keep the last 14 backups and create a new backup every day at 2:00 AM.
+#### Trigger Backup
+
+You are able to trigger a backup in the [admin job status page](http://my.immich.app/admin/jobs-status).
+Visit the page, open the "Create job" modal from the top right, select "Backup Database" and click "Confirm".
+A job will run and trigger a backup, you can verify this worked correctly by checking the logs or the backup folder.
+This backup will count towards the last X backups that will be kept based on your settings.
+
#### Restoring
We hope to make restoring simpler in future versions, for now you can find the backups in the `UPLOAD_LOCATION/backups` folder on your host.
diff --git a/docs/package-lock.json b/docs/package-lock.json
index 37e6a4fe65..ba4d9af199 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -15734,9 +15734,9 @@
}
},
"node_modules/prettier": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz",
- "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==",
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
+ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"bin": {
diff --git a/docs/src/components/svg-paths.ts b/docs/src/components/svg-paths.ts
index 112ed1d70f..0903392307 100644
--- a/docs/src/components/svg-paths.ts
+++ b/docs/src/components/svg-paths.ts
@@ -1,2 +1,3 @@
export const discordPath =
- 'M 9.1367188 3.8691406 C 9.1217187 3.8691406 9.1067969 3.8700938 9.0917969 3.8710938 C 8.9647969 3.8810937 5.9534375 4.1403594 4.0234375 5.6933594 C 3.0154375 6.6253594 1 12.073203 1 16.783203 C 1 16.866203 1.0215 16.946531 1.0625 17.019531 C 2.4535 19.462531 6.2473281 20.102859 7.1113281 20.130859 L 7.1269531 20.130859 C 7.2799531 20.130859 7.4236719 20.057594 7.5136719 19.933594 L 8.3886719 18.732422 C 6.0296719 18.122422 4.8248594 17.086391 4.7558594 17.025391 C 4.5578594 16.850391 4.5378906 16.549563 4.7128906 16.351562 C 4.8068906 16.244563 4.9383125 16.189453 5.0703125 16.189453 C 5.1823125 16.189453 5.2957188 16.228594 5.3867188 16.308594 C 5.4157187 16.334594 7.6340469 18.216797 11.998047 18.216797 C 16.370047 18.216797 18.589328 16.325641 18.611328 16.306641 C 18.702328 16.227641 18.815734 16.189453 18.927734 16.189453 C 19.059734 16.189453 19.190156 16.243562 19.285156 16.351562 C 19.459156 16.549563 19.441141 16.851391 19.244141 17.025391 C 19.174141 17.087391 17.968375 18.120469 15.609375 18.730469 L 16.484375 19.933594 C 16.574375 20.057594 16.718094 20.130859 16.871094 20.130859 L 16.886719 20.130859 C 17.751719 20.103859 21.5465 19.463531 22.9375 17.019531 C 22.9785 16.947531 23 16.866203 23 16.783203 C 23 12.073203 20.984172 6.624875 19.951172 5.671875 C 18.047172 4.140875 15.036203 3.8820937 14.908203 3.8710938 C 14.895203 3.8700938 14.880188 3.8691406 14.867188 3.8691406 C 14.681188 3.8691406 14.510594 3.9793906 14.433594 4.1503906 C 14.427594 4.1623906 14.362062 4.3138281 14.289062 4.5488281 C 15.548063 4.7608281 17.094141 5.1895937 18.494141 6.0585938 C 18.718141 6.1975938 18.787437 6.4917969 18.648438 6.7167969 C 18.558438 6.8627969 18.402188 6.9433594 18.242188 6.9433594 C 18.156188 6.9433594 18.069234 6.9200937 17.990234 6.8710938 C 15.584234 5.3800938 12.578 5.3046875 12 5.3046875 C 11.422 5.3046875 8.4157187 5.3810469 6.0117188 6.8730469 C 5.9327188 6.9210469 5.8457656 6.9433594 5.7597656 6.9433594 C 5.5997656 6.9433594 5.4425625 6.86475 5.3515625 6.71875 C 5.2115625 6.49375 5.2818594 6.1985938 5.5058594 6.0585938 C 6.9058594 5.1905937 8.4528906 4.7627812 9.7128906 4.5507812 C 9.6388906 4.3147813 9.5714062 4.1643437 9.5664062 4.1523438 C 9.4894063 3.9813438 9.3217188 3.8691406 9.1367188 3.8691406 z M 12 7.3046875 C 12.296 7.3046875 14.950594 7.3403125 16.933594 8.5703125 C 17.326594 8.8143125 17.777234 8.9453125 18.240234 8.9453125 C 18.633234 8.9453125 19.010656 8.8555 19.347656 8.6875 C 19.964656 10.2405 20.690828 12.686219 20.923828 15.199219 C 20.883828 15.143219 20.840922 15.089109 20.794922 15.037109 C 20.324922 14.498109 19.644687 14.191406 18.929688 14.191406 C 18.332687 14.191406 17.754078 14.405437 17.330078 14.773438 C 17.257078 14.832437 15.505 16.21875 12 16.21875 C 8.496 16.21875 6.7450313 14.834687 6.7070312 14.804688 C 6.2540312 14.407687 5.6742656 14.189453 5.0722656 14.189453 C 4.3612656 14.189453 3.6838438 14.494391 3.2148438 15.025391 C 3.1658438 15.080391 3.1201719 15.138266 3.0761719 15.197266 C 3.3091719 12.686266 4.0344375 10.235594 4.6484375 8.6835938 C 4.9864375 8.8525938 5.3657656 8.9433594 5.7597656 8.9433594 C 6.2217656 8.9433594 6.6724531 8.8143125 7.0644531 8.5703125 C 9.0494531 7.3393125 11.704 7.3046875 12 7.3046875 z M 8.890625 10.044922 C 7.966625 10.044922 7.2167969 10.901031 7.2167969 11.957031 C 7.2167969 13.013031 7.965625 13.869141 8.890625 13.869141 C 9.815625 13.869141 10.564453 13.013031 10.564453 11.957031 C 10.564453 10.900031 9.815625 10.044922 8.890625 10.044922 z M 15.109375 10.044922 C 14.185375 10.044922 13.435547 10.901031 13.435547 11.957031 C 13.435547 13.013031 14.184375 13.869141 15.109375 13.869141 C 16.034375 13.869141 16.783203 13.013031 16.783203 11.957031 C 16.783203 10.900031 16.033375 10.044922 15.109375 10.044922 z';
+ 'M81.15,0c-1.2376,2.1973-2.3489,4.4704-3.3591,6.794-9.5975-1.4396-19.3718-1.4396-28.9945,0-.985-2.3236-2.1216-4.5967-3.3591-6.794-9.0166,1.5407-17.8059,4.2431-26.1405,8.0568C2.779,32.5304-1.6914,56.3725.5312,79.8863c9.6732,7.1476,20.5083,12.603,32.0505,16.0884,2.6014-3.4854,4.8998-7.1981,6.8698-11.0623-3.738-1.3891-7.3497-3.1318-10.8098-5.1523.9092-.6567,1.7932-1.3386,2.6519-1.9953,20.281,9.547,43.7696,9.547,64.0758,0,.8587.7072,1.7427,1.3891,2.6519,1.9953-3.4601,2.0457-7.0718,3.7632-10.835,5.1776,1.97,3.8642,4.2683,7.5769,6.8698,11.0623,11.5419-3.4854,22.3769-8.9156,32.0509-16.0631,2.626-27.2771-4.496-50.9172-18.817-71.8548C98.9811,4.2684,90.1918,1.5659,81.1752.0505l-.0252-.0505ZM42.2802,65.4144c-6.2383,0-11.4159-5.6575-11.4159-12.6535s4.9755-12.6788,11.3907-12.6788,11.5169,5.708,11.4159,12.6788c-.101,6.9708-5.026,12.6535-11.3907,12.6535ZM84.3576,65.4144c-6.2637,0-11.3907-5.6575-11.3907-12.6535s4.9755-12.6788,11.3907-12.6788,11.4917,5.708,11.3906,12.6788c-.101,6.9708-5.026,12.6535-11.3906,12.6535Z';
+export const discordViewBox = '0 0 126.644 96';
diff --git a/docs/src/components/version-switcher.tsx b/docs/src/components/version-switcher.tsx
index 016e4ac1e6..5cb23891aa 100644
--- a/docs/src/components/version-switcher.tsx
+++ b/docs/src/components/version-switcher.tsx
@@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react';
export default function VersionSwitcher(): JSX.Element {
const [versions, setVersions] = useState([]);
- const [label, setLabel] = useState('Versions');
+ const [activeLabel, setLabel] = useState('Versions');
const windowSize = useWindowSize();
@@ -48,12 +48,13 @@ export default function VersionSwitcher(): JSX.Element {
versions.length > 0 && (
@@ -35,7 +33,6 @@ function HomepageHeader() {
sacrificing your privacy.
Download the mobile app
@@ -97,9 +94,8 @@ function HomepageHeader() {
docker-compose.yml
/.env
siano aggiornati per evitare problemi e incongruenze, soprattutto se utilizzi WatchTower o altri strumenti per aggiornare Immich in automatico.",
+ "version_announcement_message": "Ehilà! È stata rilasciata una nuova versione di Immich. Leggi le release notes e assicurati che i tuoi file di configurazione siano aggiornati per evitare problemi e incongruenze, soprattutto se utilizzi WatchTower o altri strumenti per aggiornare Immich in automatico.",
"version_history": "Storico delle Versioni",
"version_history_item": "Versione installata {version} il {date}",
"video": "Video",
@@ -1343,6 +1357,7 @@
"view_all": "Vedi tutto",
"view_all_users": "Visualizza tutti gli utenti",
"view_in_timeline": "Visualizza in timeline",
+ "view_link": "Visualizza link",
"view_links": "Visualizza i link",
"view_name": "Visualizza",
"view_next_asset": "Visualizza risorsa successiva",
@@ -1359,4 +1374,4 @@
"yes": "Si",
"you_dont_have_any_shared_links": "Non è presente alcun link condiviso",
"zoom_image": "Ingrandisci immagine"
-}
+}
\ No newline at end of file
diff --git a/i18n/ja.json b/i18n/ja.json
index 98054f14ca..154e6be42e 100644
--- a/i18n/ja.json
+++ b/i18n/ja.json
@@ -256,7 +256,7 @@
"transcoding_max_b_frames": "最大Bフレーム",
"transcoding_max_b_frames_description": "値を高くすると圧縮効率が向上しますが、エンコード速度が遅くなります。古いデバイスのハードウェアアクセラレーションでは対応していない場合があります。\"0\" はBフレームを無効にし、\"-1\" はこの値を自動的に設定します。",
"transcoding_max_bitrate": "最大ビットレート",
- "transcoding_max_bitrate_description": "最大ビットレートを設定すると、品質にわずかな影響を与えながらも、ファイルサイズを予測しやすくなります。720pの場合、一般的な値は VP9 や HEVC で \"2600k\"、H.264 で \"4500k\" です。\"0\" に設定すると無効になります。",
+ "transcoding_max_bitrate_description": "最大ビットレートを設定すると、品質にわずかな影響を与えながらも、ファイルサイズを予測しやすくなります。720pの場合、一般的な値は VP9 や HEVC で \"2600 kbit/s\"、H.264 で \"4500 kbit/s\" です。\"0\" に設定すると無効になります。",
"transcoding_max_keyframe_interval": "最大キーフレーム間隔",
"transcoding_max_keyframe_interval_description": "キーフレーム間の最大フレーム間隔を設定します。値を低くすると圧縮効率が悪化しますが、シーク時間が改善され、動きの速いシーンの品質が向上する場合があります。\"0\" に設定すると、この値が自動的に設定されます。",
"transcoding_optimal_description": "設定解像度を超える動画、または容認されていない形式の動画",
@@ -1257,4 +1257,4 @@
"yes": "はい",
"you_dont_have_any_shared_links": "共有リンクはありません",
"zoom_image": "画像を拡大"
-}
+}
\ No newline at end of file
diff --git a/i18n/ko.json b/i18n/ko.json
index ef8227c3f2..29971e5e30 100644
--- a/i18n/ko.json
+++ b/i18n/ko.json
@@ -68,7 +68,7 @@
"image_prefer_embedded_preview": "포함된 미리 보기 선호",
"image_prefer_embedded_preview_setting_description": "가능한 경우 이미지 처리 시 RAW 사진에 포함된 미리 보기를 사용합니다. 포함된 미리 보기는 카메라에서 생성된 것으로 카메라마다 품질이 다릅니다. 일부 이미지의 경우 더 정확한 색상이 표현될 수 있지만 반대로 더 많은 아티팩트가 있을 수도 있습니다.",
"image_prefer_wide_gamut": "넓은 색 영역 선호",
- "image_prefer_wide_gamut_setting_description": "섬네일 이미지에 Display P3을 사용합니다. 많은 색상을 표현할 수 있어 더 정확한 표현이 가능하지만, 오래된 브라우저를 사용하는 경우 이미지가 다르게 보일 수 있습니다. 색상 왜곡을 방지하기 위해 sRGB 이미지는 이 설정이 적용되지 않습니다.",
+ "image_prefer_wide_gamut_setting_description": "섬네일 이미지에 Display P3를 사용합니다. 많은 색상을 표현할 수 있어 더 정확한 표현이 가능하지만, 오래된 브라우저를 사용하는 경우 이미지가 다르게 보일 수 있습니다. 색상 왜곡을 방지하기 위해 sRGB 이미지는 이 설정이 적용되지 않습니다.",
"image_preview_description": "메타데이터를 제거한 중간 크기의 이미지, 단일 항목을 보는 경우 및 기계 학습에 사용됨",
"image_preview_quality_description": "1부터 100 사이의 미리보기 품질. 값이 높을수록 좋지만 파일 크기가 커져 앱의 반응성이 떨어질 수 있으며, 값이 낮으면 기계 학습의 품질이 떨어질 수 있습니다.",
"image_preview_title": "미리보기 설정",
@@ -131,7 +131,7 @@
"machine_learning_smart_search_description": "CLIP 임베딩으로 자연어를 사용하여 이미지 검색",
"machine_learning_smart_search_enabled": "스마트 검색 활성화",
"machine_learning_smart_search_enabled_description": "비활성화된 경우 스마트 검색을 위한 이미지 처리를 진행하지 않습니다.",
- "machine_learning_url_description": "기계 학습 서버의 URL을 입럭합니다. 여러 개의 URL이 입력된 경우 모든 서버에 응답을 보낸 뒤 응답에 성공한 서버가 사용됩니다.",
+ "machine_learning_url_description": "기계 학습 서버의 URL을 입력합니다. URL이 여러 개인 경우 첫 번째 서버부터 마지막까지 성공적으로 응답할 때까지 한 번에 하나씩 순서대로 요청을 시도합니다. 응답하지 않는 서버는 다시 사용 가능할 때까지 일시적으로 제외됩니다.",
"manage_concurrency": "동시성 관리",
"manage_log_settings": "로그 설정 관리",
"map_dark_style": "다크 스타일",
@@ -291,7 +291,7 @@
"transcoding_max_b_frames": "최대 B 프레임",
"transcoding_max_b_frames_description": "값이 높으면 압축 효율이 향상되지만 인코딩 속도가 저하됩니다. 오래된 기기의 하드웨어 가속과 호환되지 않을 수 있습니다. 0을 입력한 경우 B 프레임을 비활성화하며, -1을 입력한 경우 자동으로 설정합니다.",
"transcoding_max_bitrate": "최대 비트레이트",
- "transcoding_max_bitrate_description": "최대 비트레이트를 지정하면 품질이 일부 저하되지만 파일 크기가 예측 가능한 수준으로 일정하게 유지됩니다. 일반적으로 720p 기준 VP9 및 HEVC는 2600k, H.264는 4500k를 사용합니다. 0을 입력한 경우 비활성화됩니다.",
+ "transcoding_max_bitrate_description": "최대 비트레이트를 지정하면 품질이 일부 저하되지만 파일 크기가 예측 가능한 수준으로 일정하게 유지됩니다. 일반적으로 720p 기준 VP9 및 HEVC는 2600 kbit/s, H.264는 4500 kbit/s를 사용합니다. 0을 입력한 경우 비활성화됩니다.",
"transcoding_max_keyframe_interval": "최대 키프레임 간격",
"transcoding_max_keyframe_interval_description": "키프레임 사이 최대 프레임 거리를 설정합니다. 값이 낮으면 압축 효율이 저하되지만 검색 시간이 개선되고 빠른 움직임이 있는 장면에서 품질이 향상됩니다. 0을 입력한 경우 자동으로 설정합니다.",
"transcoding_optimal_description": "목표 해상도보다 높은 동영상 또는 허용되지 않는 형식의 동영상",
@@ -1323,4 +1323,4 @@
"yes": "네",
"you_dont_have_any_shared_links": "생성한 공유 링크가 없습니다.",
"zoom_image": "이미지 확대"
-}
+}
\ No newline at end of file
diff --git a/i18n/lt.json b/i18n/lt.json
index 5e478a37a9..738dc7bc7f 100644
--- a/i18n/lt.json
+++ b/i18n/lt.json
@@ -20,7 +20,7 @@
"add_partner": "Pridėti partnerį",
"add_path": "Pridėti kelią",
"add_photos": "Pridėti nuotraukų",
- "add_to": "Pridėti į ...",
+ "add_to": "Pridėti į…",
"add_to_album": "Pridėti į albumą",
"add_to_shared_album": "Pridėti į bendrinamą albumą",
"add_url": "Pridėti URL",
@@ -50,6 +50,7 @@
"create_job": "Sukurti darbą",
"cron_expression": "Cron išraiška",
"cron_expression_description": "Nustatyti skanavimo intervalą naudojant cron formatą. Norėdami gauti daugiau informacijos žiūrėkite Crontab Guru",
+ "cron_expression_presets": "Išankstiniai Cron nustatymai",
"disable_login": "Išjungti prisijungimą",
"duplicate_detection_job_description": "Vykdykite mašininį mokymąsi panašių vaizdų aptikimui. Priklauso nuo išmaniosios paieškos",
"exclusion_pattern_description": "Išimčių šablonai leidžia nepaisyti failų ir aplankų skenuojant jūsų biblioteką. Tai yra naudinga, jei turite aplankų su failais, kurių nenorite importuoti, pavyzdžiui, RAW failai.",
@@ -142,6 +143,8 @@
"map_settings": "Žemėlapis",
"map_settings_description": "Tvarkyti žemėlapio parametrus",
"map_style_description": "URL į style.json žemėlapio temą",
+ "memory_cleanup_job": "Atsiminimų valymas",
+ "memory_generate_job": "Atsiminimų generavimas",
"metadata_extraction_job": "Metaduomenų nuskaitymas",
"metadata_extraction_job_description": "Kiekvieno bibliotekos elemento metaduomenų nuskaitymas, tokių kaip GPS koordinatės, veidai ar rezoliucija",
"metadata_faces_import_setting": "Įjungti veidų importą",
@@ -904,6 +907,8 @@
"removed_from_archive": "Pašalinta iš archyvo",
"removed_from_favorites": "Pašalinta iš mėgstamiausių",
"removed_from_favorites_count": "{count, plural, one {# pašalintas} few {# pašalinti} other {# pašalinta}} iš mėgstamiausių",
+ "removed_memory": "Atsiminimas pašalintas",
+ "removed_photo_from_memory": "Nuotrauka ištrinta iš atsiminimų",
"removed_tagged_assets": "Žyma pašalinta iš {count, plural, one {# elemento} other {# elementų}}",
"rename": "Pervadinti",
"repair": "Pataisyti",
diff --git a/i18n/lv.json b/i18n/lv.json
index 38b0bf6426..d962ae1bd1 100644
--- a/i18n/lv.json
+++ b/i18n/lv.json
@@ -20,7 +20,7 @@
"add_partner": "Pievienot partneri",
"add_path": "Pievienot ceļu",
"add_photos": "Pievienot fotoattēlus",
- "add_to": "Pievienot ..",
+ "add_to": "Pievienot…",
"add_to_album": "Pievienot albumam",
"add_to_shared_album": "Pievienot koplietotam albumam",
"add_url": "Pievienot URL",
@@ -49,7 +49,7 @@
"external_library_management": "Ārējo bibliotēku pārvaldība",
"face_detection": "Seju noteikšana",
"image_format": "Formāts",
- "image_format_description": "",
+ "image_format_description": "WebP veido mazākus failus nekā JPEG, taču to kodēšana ir lēnāka.",
"image_prefer_embedded_preview": "",
"image_prefer_embedded_preview_setting_description": "",
"image_prefer_wide_gamut": "",
@@ -299,12 +299,13 @@
"asset_offline": "",
"asset_uploading": "Augšupielādē...",
"assets": "aktīvi",
- "authorized_devices": "",
+ "authorized_devices": "Autorizētās ierīces",
"back": "Atpakaļ",
"backward": "",
"birthdate_saved": "Dzimšanas datums veiksmīgi saglabāts",
"birthdate_set_description": "Dzimšanas datums tiek izmantots, lai aprēķinātu šīs personas vecumu fotogrāfijas uzņemšanas brīdī.",
"blurred_background": "",
+ "bugs_and_feature_requests": "Kļūdas un funkciju pieprasījumi",
"camera": "",
"camera_brand": "",
"camera_model": "",
@@ -326,12 +327,13 @@
"clear": "Notīrīt",
"clear_all": "Notīrīt visu",
"clear_message": "",
- "clear_value": "",
+ "clear_value": "Notīrīt vērtību",
+ "clockwise": "Pulksteņrādītāja virzienā",
"close": "Aizvērt",
"collapse": "Sakļaut",
"collapse_all": "Sakļaut visu",
"color": "Krāsa",
- "color_theme": "",
+ "color_theme": "Krāsu tēma",
"comment_deleted": "Komentārs dzēsts",
"comment_options": "",
"comments_are_disabled": "",
diff --git a/i18n/mr.json b/i18n/mr.json
index 0967ef424b..ec05d6c702 100644
--- a/i18n/mr.json
+++ b/i18n/mr.json
@@ -1 +1,62 @@
-{}
+{
+ "about": "विषयी",
+ "account": "खाते",
+ "account_settings": "खाते व्यवस्था",
+ "acknowledge": "मान्यता",
+ "action": "कृती",
+ "actions": "कृत्ये",
+ "active": "सक्रिय",
+ "activity": "गतिविधि",
+ "activity_changed": "गतिविधि {enabled, select, true {enabled} other {disabled}}",
+ "add": "जोडा",
+ "add_a_description": "वर्णन करा",
+ "add_a_location": "एक स्थळ टाका",
+ "add_a_name": "नाव टाका",
+ "add_a_title": "शीर्षक टाका",
+ "add_exclusion_pattern": "अपवाद नमुना जोडा",
+ "add_import_path": "आयात मार्ग टाका",
+ "add_location": "स्थळ टाका",
+ "add_more_users": "अधिक वापरकर्ते जोडा",
+ "add_partner": "भागीदार जोडा",
+ "add_path": "मार्ग टाका",
+ "add_photos": "छायाचित्रे जोडा",
+ "add_to": "त्या मध्ये जोडा…",
+ "add_to_album": "संग्रहात टाका",
+ "add_to_shared_album": "सामायिक संग्रहात टाका",
+ "add_url": "URL जोडा",
+ "added_to_archive": "संग्रहालयात जोडले",
+ "added_to_favorites": "आवडत्यात टाकले",
+ "added_to_favorites_count": "आवडत्यात {count, number} टाकले",
+ "admin": {
+ "add_exclusion_pattern_description": "अपवाद अनुकूलन जोडा. ** आणि ? या उपयोगात ग्लोबिंग समर्थित आहे. कोणत्याही \"Raw\" नावाच्या निर्देशिकेमधील सर्व खतावण्या दुर्लक्षीत करण्यासाठी \"/Raw/\" वापरा. \".tif\" या सामान्य पथावर समाप्त असलेल्या सर्व खतावण्या दुर्लक्षीत करण्यासाठी \"**/.tif\" वापरा. विशिष्ट पथ दुर्लक्ष करण्यासाठी \"/path/to/ignore/**\" वापरा.",
+ "asset_offline_description": "ही बाह्य संग्रहालय संसाधने डिस्कवर नाहीत आणि ट्रॅशमध्ये विस्थापित केली गेली आहेत. जर फाइल संग्रहालयामध्ये विस्थापित केली गेली आहे, तर नवीन संगत संसाधन किंव्हा रोजीनिशी मध्ये तपासा. हा संसाधन वापर करण्यासाठी कृपया निम्नलिखित खतावणी पथाला इम्मीच द्वारा वापरू शकतो याची तपासणी करा आणि तो संग्रहालय चाळा.",
+ "authentication_settings": "प्रमाणीकरण साधक",
+ "authentication_settings_description": "परवलीचा शब्द, OAuth आणि अन्य प्रमाणीकरण प्रबंधन करा",
+ "authentication_settings_disable_all": "तुम्हाला खात्री आहे की तुम्ही सर्व प्रवेश पद्धती बंद करू इच्छिता? प्रवेश पूर्णपणे बंद होइल!.",
+ "authentication_settings_reenable": "परत चालू करण्यासाठी Server Command वापरा.",
+ "background_task_job": "पृष्ठभूमि कार्य",
+ "backup_database": "माहिती संचयाची सुरक्षित प्रत करा",
+ "backup_database_enable_description": "माहिती संचयाच्या प्रतिलिपी चालू करा",
+ "backup_keep_last_amount": "पूर्वीच्या किती प्रतिलिपी ठेवायच्या",
+ "backup_settings": "प्रतिलिपी व्यवस्था",
+ "backup_settings_description": "माहिती संचय प्रतिलिपी व्यवस्थापन",
+ "check_all": "सर्व तपासा",
+ "cleared_jobs": "{job}: च्या कार्यवाह्या काढल्या",
+ "config_set_by_file": "संरचना सध्या संरचना खतावणीद्वारे निश्चित केली आहे",
+ "confirm_delete_library": "तुम्हाला नक्की हे {library} संग्रहालय हटवायचे आहे का?",
+ "confirm_delete_library_assets": "तुम्हाला नक्की हे संग्रहालय हटवायचे आहे का? इम्मीच मधून {count, plural, one {# contained asset} other {all # contained assets}} काढले जातील, आणि पूर्ववत करता येणार नाहीत. छायाचित्रे डिस्क वर राहतील.",
+ "confirm_email_below": "पुष्टी करण्या साठी, खाली \"{email}\" टंकलिखित करा",
+ "confirm_reprocess_all_faces": "तुम्हाला खात्री आहे का की तुम्हाला सर्व चेहऱ्यांवर पुन्हा प्रक्रिया करायची आहे? यामुळे नाव दिलेले लोकही साफ होतील.",
+ "confirm_user_password_reset": "तुम्हाला नक्की {user} चा परवलीचा शब्द बदलायचा आहे का?",
+ "create_job": "कार्य बनवा",
+ "cron_expression": "वेळापत्रक सूत्र",
+ "cron_expression_description": "चाळन्याचे वेळापत्रक क्रॉन पद्धती ने करा. अधिक माहिती साठी पहा: क्रॉन गुरु",
+ "cron_expression_presets": "पूर्वनिर्धारित वेळापत्रक सूत्रे",
+ "disable_login": "प्रवेशाधिकर वर्ज्य करा",
+ "duplicate_detection_job_description": "सारख्या छायाचित्रांचा शोध घेण्यासाठी यांत्रिकी प्रशिक्षण द्या. ही कार्यक्षमता चतुर शोधप्रणालीवर अवलंबून आहे",
+ "exclusion_pattern_description": "आपले संग्रहालय चाळताना अपवाद नमुने आपल्याला खतावण्या आणि र्निर्देशिकेला दुर्लक्षीत करू देतात. आपल्याकडे कच्च्या खतावण्या सारख्या आयात करू इच्छित नसलेल्या असंपादित (RAW) खतावण्या असलेल्या निर्देशिका असल्यास हे उपयुक्त आहे.",
+ "external_library_created_at": "बाह्य संग्रहालय ({date} रोजी बनवले गेले)",
+ "external_library_management": "बाह्य संग्रहालय व्यवस्थापन",
+ "face_detection": "मुख संशोधन"
+ }
+}
diff --git a/i18n/ms.json b/i18n/ms.json
index 9916ca62a0..7da863750d 100644
--- a/i18n/ms.json
+++ b/i18n/ms.json
@@ -299,7 +299,7 @@
"transcoding_max_b_frames": "Bingkai-B maksimum",
"transcoding_max_b_frames_description": "Nilai yang lebih tinggi meningkatkan kecekapan mampatan, tetapi memperlahankan pengekodan. Mungkin tidak serasi dengan pecutan perkakasan pada peranti lama. 0 melumpuhkan bingkai B, manakala -1 menetapkan nilai ini secara automatik.",
"transcoding_max_bitrate": "Kadar bit maksimum",
- "transcoding_max_bitrate_description": "Menetapkan kadar bit maksima boleh menjadikan saiz fail lebih boleh diramal dengan kekurangan yang kecil kepada kualiti. Pada 720p, nilai biasa ialah 2600k untuk VP9 atau HEVC, atau 4500k untuk H.264. Dilumpuhkan jika ditetapkan kepada 0.",
+ "transcoding_max_bitrate_description": "Menetapkan kadar bit maksima boleh menjadikan saiz fail lebih boleh diramal dengan kekurangan yang kecil kepada kualiti. Pada 720p, nilai biasa ialah 2600 kbit/s untuk VP9 atau HEVC, atau 4500 kbit/s untuk H.264. Dilumpuhkan jika ditetapkan kepada 0.",
"transcoding_max_keyframe_interval": "Selangan keyframe maksimum",
"transcoding_max_keyframe_interval_description": "Menetapkan jarak bingkai maksimum antara keyframes. Nilai yang lebih rendah memburukkan kecekapan mampatan, tetapi menambah baik masa carian dan mungkin meningkatkan kualiti dalam adegan dengan pergerakan pantas. 0 menetapkan nilai ini secara automatik.",
"transcoding_optimal_description": "Video yang lebih tinggi daripada resolusi sasaran atau tidak dalam format yang diterima",
@@ -372,4 +372,4 @@
"yes": "Ya",
"you_dont_have_any_shared_links": "Anda tidak mempunyai apa-apa pautan yang dikongsi",
"zoom_image": "Zum Gambar"
-}
+}
\ No newline at end of file
diff --git a/i18n/nb_NO.json b/i18n/nb_NO.json
index b29c8c1db6..78f7941760 100644
--- a/i18n/nb_NO.json
+++ b/i18n/nb_NO.json
@@ -41,6 +41,7 @@
"backup_settings": "Backupinnstillinger",
"backup_settings_description": "Håndter innstillinger for databasebackup",
"check_all": "Merk Alle",
+ "cleanup": "Opprydding",
"cleared_jobs": "Ryddet opp jobber for: {job}",
"config_set_by_file": "Konfigurasjonen er for øyeblikket satt av en konfigurasjonsfil",
"confirm_delete_library": "Er du sikker på at du vil slette biblioteket {library}?",
@@ -96,7 +97,7 @@
"library_scanning_enable_description": "Aktiver periodisk skanning av bibliotek",
"library_settings": "Eksternt bibliotek",
"library_settings_description": "Administrer innstillinger for eksterne bibliotek",
- "library_tasks_description": "Utfør bibliotekoppgaver",
+ "library_tasks_description": "Skann eksterne biblioteker for nye og/eller endrede ressurser",
"library_watching_enable_description": "Overvåk eksterne bibliotek for filendringer",
"library_watching_settings": "Overvåkning av bibliotek (EKSPERIMENTELL)",
"library_watching_settings_description": "Se automatisk etter endrede filer",
@@ -131,7 +132,7 @@
"machine_learning_smart_search_description": "Søk etter bilder semantisk ved å bruke CLIP-embeddings",
"machine_learning_smart_search_enabled": "Aktiver smart søk",
"machine_learning_smart_search_enabled_description": "Hvis deaktivert, vil bilder ikke bli enkodet for smart søk.",
- "machine_learning_url_description": "URL til maskinlærings-serveren. Hvis mer enn en URL er lagt inn, hver server vill bli forsøkt en om gangen frem til en svarer suksessfullt, i rekkefølge fra først til sist.",
+ "machine_learning_url_description": "URL til maskinlærings-serveren. Hvis mer enn en URL er lagt inn, hver server vill bli forsøkt en om gangen frem til en svarer suksessfullt, i rekkefølge fra først til sist. Servere som ikke svarer vil midlertidig bli oversett frem til dem svarer igjen.",
"manage_concurrency": "Administrer samtidighet",
"manage_log_settings": "Administrer logginnstillinger",
"map_dark_style": "Mørk stil",
@@ -147,6 +148,8 @@
"map_settings": "Innstillinger for kart og GPS",
"map_settings_description": "Administrer kartinnstillinger",
"map_style_description": "URL til et style.json-karttema",
+ "memory_cleanup_job": "Minneopprydding",
+ "memory_generate_job": "Minnegenerering",
"metadata_extraction_job": "Hent metadata",
"metadata_extraction_job_description": "Hent metadatainformasjon fra hver fil, for eksempel GPS-posisjon og oppløsning",
"metadata_faces_import_setting": "Aktiver ansikts importering",
@@ -240,7 +243,7 @@
"storage_template_hash_verification_enabled_description": "Aktiver hasjverifisering. Ikke deaktiver dette med mindre du er sikker på konsekvensene",
"storage_template_migration": "Lagringsmal migrering",
"storage_template_migration_description": "Bruk gjeldende {template} på tidligere opplastede bilder",
- "storage_template_migration_info": "Malendringer vil kun gjelde nye ressurser. For å anvende malen på tidligere opplastede ressurser, kjør {job}.",
+ "storage_template_migration_info": "Lagringsmalen vil endre filtypen til små bokstaver. Malendringer vil kun gjelde nye ressurser. For å anvende malen på tidligere opplastede ressurser, kjør {job}.",
"storage_template_migration_job": "Migreringsjobb for lagringsmal",
"storage_template_more_details": "For mer informasjon om denne funksjonen, se (
switch (propertyId) {
case 0:
return (_UseravatarColorValueEnumMap[reader.readByteOrNull(offset)] ??
- AvatarColorEnum.primary) as P;
+ AvatarColor.primary) as P;
case 1:
return (reader.readString(offset)) as P;
case 2:
- return (reader.readBool(offset)) as P;
- case 3:
return (reader.readString(offset)) as P;
- case 4:
+ case 3:
return (reader.readBoolOrNull(offset) ?? false) as P;
- case 5:
+ case 4:
return (reader.readBool(offset)) as P;
+ case 5:
+ return (reader.readBoolOrNull(offset) ?? false) as P;
case 6:
return (reader.readBoolOrNull(offset) ?? false) as P;
case 7:
- return (reader.readBoolOrNull(offset) ?? false) as P;
- case 8:
return (reader.readBoolOrNull(offset) ?? true) as P;
- case 9:
+ case 8:
return (reader.readString(offset)) as P;
- case 10:
+ case 9:
return (reader.readStringOrNull(offset) ?? '') as P;
+ case 10:
+ return (reader.readLongOrNull(offset) ?? 0) as P;
case 11:
return (reader.readLongOrNull(offset) ?? 0) as P;
case 12:
- return (reader.readLongOrNull(offset) ?? 0) as P;
- case 13:
return (reader.readDateTime(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
@@ -247,16 +224,16 @@ const _UseravatarColorEnumValueMap = {
'amber': 9,
};
const _UseravatarColorValueEnumMap = {
- 0: AvatarColorEnum.primary,
- 1: AvatarColorEnum.pink,
- 2: AvatarColorEnum.red,
- 3: AvatarColorEnum.yellow,
- 4: AvatarColorEnum.blue,
- 5: AvatarColorEnum.green,
- 6: AvatarColorEnum.purple,
- 7: AvatarColorEnum.orange,
- 8: AvatarColorEnum.gray,
- 9: AvatarColorEnum.amber,
+ 0: AvatarColor.primary,
+ 1: AvatarColor.pink,
+ 2: AvatarColor.red,
+ 3: AvatarColor.yellow,
+ 4: AvatarColor.blue,
+ 5: AvatarColor.green,
+ 6: AvatarColor.purple,
+ 7: AvatarColor.orange,
+ 8: AvatarColor.gray,
+ 9: AvatarColor.amber,
};
Id _userGetId(User object) {
@@ -264,14 +241,10 @@ Id _userGetId(User object) {
}
List> getAll({SortUserBy? sortBy}) async {
+ return (await _db.users
+ .where()
+ .optional(
+ sortBy != null,
+ (query) => switch (sortBy!) {
+ SortUserBy.id => query.sortById(),
+ },
+ )
+ .findAll())
+ .map((u) => u.toDto())
+ .toList();
+ }
+
+ @override
+ Future
> getByUserIds(List
> getAll() async {
+ final dto = await checkNull(_api.searchUsers());
+ return dto.map(UserConverter.fromSimpleUserDto).toList();
+ }
+}
diff --git a/mobile/lib/infrastructure/utils/exif.converter.dart b/mobile/lib/infrastructure/utils/exif.converter.dart
index ca4d175460..0f6e2b0295 100644
--- a/mobile/lib/infrastructure/utils/exif.converter.dart
+++ b/mobile/lib/infrastructure/utils/exif.converter.dart
@@ -9,7 +9,7 @@ abstract final class ExifDtoConverter {
orientation: dto.orientation,
timeZone: dto.timeZone,
dateTimeOriginal: dto.dateTimeOriginal,
- isFlipped: _isOrientationFlipped(dto.orientation),
+ isFlipped: isOrientationFlipped(dto.orientation),
latitude: dto.latitude?.toDouble(),
longitude: dto.longitude?.toDouble(),
city: dto.city,
@@ -25,7 +25,7 @@ abstract final class ExifDtoConverter {
);
}
- static bool _isOrientationFlipped(String? orientation) {
+ static bool isOrientationFlipped(String? orientation) {
final value = orientation == null ? null : int.tryParse(orientation);
if (value == null) {
return false;
diff --git a/mobile/lib/infrastructure/utils/user.converter.dart b/mobile/lib/infrastructure/utils/user.converter.dart
new file mode 100644
index 0000000000..11f9ddec33
--- /dev/null
+++ b/mobile/lib/infrastructure/utils/user.converter.dart
@@ -0,0 +1,66 @@
+import 'package:immich_mobile/domain/models/user.model.dart';
+import 'package:openapi/api.dart';
+
+abstract final class UserConverter {
+ /// Base user dto used where the complete user object is not required
+ static UserDto fromSimpleUserDto(UserResponseDto dto) => UserDto(
+ uid: dto.id,
+ email: dto.email,
+ name: dto.name,
+ isAdmin: false,
+ updatedAt: DateTime.now(),
+ profileImagePath: dto.profileImagePath,
+ avatarColor: dto.avatarColor.toAvatarColor(),
+ );
+
+ static UserDto fromAdminDto(
+ UserAdminResponseDto adminDto, [
+ UserPreferencesResponseDto? preferenceDto,
+ ]) =>
+ UserDto(
+ uid: adminDto.id,
+ email: adminDto.email,
+ name: adminDto.name,
+ isAdmin: adminDto.isAdmin,
+ updatedAt: adminDto.updatedAt,
+ profileImagePath: adminDto.profileImagePath,
+ avatarColor: adminDto.avatarColor.toAvatarColor(),
+ memoryEnabled: preferenceDto?.memories.enabled ?? true,
+ inTimeline: false,
+ isPartnerSharedBy: false,
+ isPartnerSharedWith: false,
+ quotaUsageInBytes: adminDto.quotaUsageInBytes ?? 0,
+ quotaSizeInBytes: adminDto.quotaSizeInBytes ?? 0,
+ );
+
+ static UserDto fromPartnerDto(PartnerResponseDto dto) => UserDto(
+ uid: dto.id,
+ email: dto.email,
+ name: dto.name,
+ isAdmin: false,
+ updatedAt: DateTime.now(),
+ profileImagePath: dto.profileImagePath,
+ avatarColor: dto.avatarColor.toAvatarColor(),
+ memoryEnabled: false,
+ inTimeline: dto.inTimeline ?? false,
+ isPartnerSharedBy: false,
+ isPartnerSharedWith: false,
+ quotaUsageInBytes: 0,
+ quotaSizeInBytes: 0,
+ );
+}
+
+extension on UserAvatarColor {
+ AvatarColor toAvatarColor() => switch (this) {
+ UserAvatarColor.red => AvatarColor.red,
+ UserAvatarColor.green => AvatarColor.green,
+ UserAvatarColor.blue => AvatarColor.blue,
+ UserAvatarColor.purple => AvatarColor.purple,
+ UserAvatarColor.orange => AvatarColor.orange,
+ UserAvatarColor.pink => AvatarColor.pink,
+ UserAvatarColor.amber => AvatarColor.amber,
+ UserAvatarColor.yellow => AvatarColor.yellow,
+ UserAvatarColor.gray => AvatarColor.gray,
+ UserAvatarColor.primary || _ => AvatarColor.primary,
+ };
+}
diff --git a/mobile/lib/interfaces/album.interface.dart b/mobile/lib/interfaces/album.interface.dart
index 3a83a8feb7..c1696eda80 100644
--- a/mobile/lib/interfaces/album.interface.dart
+++ b/mobile/lib/interfaces/album.interface.dart
@@ -1,6 +1,6 @@
+import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/entities/album.entity.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
-import 'package:immich_mobile/entities/user.entity.dart';
import 'package:immich_mobile/interfaces/database.interface.dart';
import 'package:immich_mobile/models/albums/album_search.model.dart';
@@ -31,9 +31,9 @@ abstract interface class IAlbumRepository implements IDatabaseRepository {
Future
> getSharedWith();
- Future
> getSharedBy();
- Stream
> watchSharedWith();
- Stream
> watchSharedBy();
+ Future
> getSharedWith();
+ Future
> getSharedBy();
+ Stream
> watchSharedWith();
+ Stream
> watchSharedBy();
}
diff --git a/mobile/lib/interfaces/partner_api.interface.dart b/mobile/lib/interfaces/partner_api.interface.dart
index bca1baf66d..01149f473c 100644
--- a/mobile/lib/interfaces/partner_api.interface.dart
+++ b/mobile/lib/interfaces/partner_api.interface.dart
@@ -1,9 +1,9 @@
-import 'package:immich_mobile/entities/user.entity.dart';
+import 'package:immich_mobile/domain/models/user.model.dart';
abstract interface class IPartnerApiRepository {
- Future
> getAll(Direction direction);
- Future
> getAll(Direction direction);
+ Future
> getByIds(List
> getAll({bool self = true, UserSort? sortBy});
-
- /// Returns all users whose assets can be accessed (self+partners)
- Future
> getAllAccessible();
-
- Future
> upsertAll(List
> getAll();
- Future<({String profileImagePath})> createProfileImage({
- required String name,
- required Uint8List data,
- });
-}
diff --git a/mobile/lib/mixins/error_logger.mixin.dart b/mobile/lib/mixins/error_logger.mixin.dart
index 466028c338..482420a978 100644
--- a/mobile/lib/mixins/error_logger.mixin.dart
+++ b/mobile/lib/mixins/error_logger.mixin.dart
@@ -6,6 +6,7 @@ typedef AsyncFuture
> suggestedShareUsers =
+ final AsyncValue
> suggestedShareUsers =
ref.watch(otherUsersProvider);
- final sharedUsersList = useState
>(const []);
+ final sharedUsers = useRef
>(const []);
sharedUsers.value = ref.watch(
currentAlbumProvider.select((album) {
if (album == null) {
@@ -23,7 +23,7 @@ class AlbumSharedUserIcons extends HookConsumerWidget {
return sharedUsers.value;
}
- return album.sharedUsers.toList(growable: false);
+ return album.sharedUsers.map((u) => u.toDto()).toList(growable: false);
}),
);
diff --git a/mobile/lib/pages/album/album_shared_user_selection.page.dart b/mobile/lib/pages/album/album_shared_user_selection.page.dart
index ed8a45194d..1c797aa449 100644
--- a/mobile/lib/pages/album/album_shared_user_selection.page.dart
+++ b/mobile/lib/pages/album/album_shared_user_selection.page.dart
@@ -3,14 +3,14 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/domain/models/user.model.dart';
+import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/providers/album/album.provider.dart';
import 'package:immich_mobile/providers/album/album_title.provider.dart';
import 'package:immich_mobile/providers/album/suggested_shared_users.provider.dart';
import 'package:immich_mobile/routing/router.dart';
-import 'package:immich_mobile/entities/asset.entity.dart';
-import 'package:immich_mobile/entities/user.entity.dart';
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
@RoutePage()
@@ -21,7 +21,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
- final sharedUsersList = useState
> {
await albumService.addUsers(album, userIds);
}
- Future
>((ref) {
+final otherUsersProvider =
+ FutureProvider.autoDispose
>((ref) async {
UserService userService = ref.watch(userServiceProvider);
+ final currentUser = ref.watch(currentUserProvider);
- return userService.getUsers();
+ final allUsers = await userService.getAll();
+ allUsers.removeWhere((u) => currentUser?.id == u.id);
+ return allUsers;
});
diff --git a/mobile/lib/providers/api.provider.g.dart b/mobile/lib/providers/api.provider.g.dart
index 2573f3d291..76ccb4ad6d 100644
--- a/mobile/lib/providers/api.provider.g.dart
+++ b/mobile/lib/providers/api.provider.g.dart
@@ -6,7 +6,7 @@ part of 'api.provider.dart';
// RiverpodGenerator
// **************************************************************************
-String _$apiServiceHash() => r'5b8beddb448316bdae5e3963ff77601653715729';
+String _$apiServiceHash() => r'93a7e3b4d3004741abc3061c4688239c3a72f9c4';
/// See also [apiService].
@ProviderFor(apiService)
diff --git a/mobile/lib/providers/app_settings.provider.g.dart b/mobile/lib/providers/app_settings.provider.g.dart
index 1d2fe173b1..88cab49c1b 100644
--- a/mobile/lib/providers/app_settings.provider.g.dart
+++ b/mobile/lib/providers/app_settings.provider.g.dart
@@ -7,7 +7,7 @@ part of 'app_settings.provider.dart';
// **************************************************************************
String _$appSettingsServiceHash() =>
- r'45ea609a91d250290431a7a08a14d16b37c7515d';
+ r'3736e0d384ec7b1f896938589656dd6eb1552d60';
/// See also [appSettingsService].
@ProviderFor(appSettingsService)
diff --git a/mobile/lib/providers/asset.provider.dart b/mobile/lib/providers/asset.provider.dart
index 53fe0338ce..fef0f7b420 100644
--- a/mobile/lib/providers/asset.provider.dart
+++ b/mobile/lib/providers/asset.provider.dart
@@ -1,15 +1,16 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
+import 'package:immich_mobile/domain/services/user.service.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/entities/store.entity.dart';
+import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
import 'package:immich_mobile/providers/memory.provider.dart';
import 'package:immich_mobile/services/album.service.dart';
import 'package:immich_mobile/services/asset.service.dart';
import 'package:immich_mobile/services/etag.service.dart';
import 'package:immich_mobile/services/exif.service.dart';
import 'package:immich_mobile/services/sync.service.dart';
-import 'package:immich_mobile/services/user.service.dart';
import 'package:logging/logging.dart';
final assetProvider = StateNotifierProvider
> {
+class PartnerSharedWithNotifier extends StateNotifier
> {
final PartnerService _partnerService;
- late final StreamSubscription
> streamSub;
+ late final StreamSubscription
> streamSub;
PartnerSharedWithNotifier(this._partnerService) : super([]) {
- Function eq = const ListEquality
> {
});
}
- Future
> {
}
final partnerSharedWithProvider =
- StateNotifierProvider
> {
+class PartnerSharedByNotifier extends StateNotifier
> {
final PartnerService _partnerService;
- late final StreamSubscription
> streamSub;
+ late final StreamSubscription
> streamSub;
PartnerSharedByNotifier(this._partnerService) : super([]) {
- Function eq = const ListEquality
> {
}
final partnerSharedByProvider =
- StateNotifierProvider
>((ref) async {
+ FutureProvider.autoDispose
>((ref) async {
final otherUsers = await ref.watch(otherUsersProvider.future);
final currentPartners = ref.watch(partnerSharedByProvider);
- final available = Set
>.internal(
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef GetAllPeopleRef = AutoDisposeFutureProviderRef
>;
-String _$personAssetsHash() => r'3dfecb67a54d07e4208bcb9581b2625acd2e1832';
+String _$personAssetsHash() => r'c1d35ee0e024bd6915e21bc724be4b458a14bc24';
/// Copied from Dart SDK
class _SystemHash {
@@ -173,7 +173,7 @@ class _PersonAssetsProviderElement
String get personId => (origin as PersonAssetsProvider).personId;
}
-String _$updatePersonNameHash() => r'7145aaaf6fc38fdafe3a283ebf3d3f4fd0774cd2';
+String _$updatePersonNameHash() => r'45f7693172de522a227406d8198811434cf2bbbc';
/// See also [updatePersonName].
@ProviderFor(updatePersonName)
diff --git a/mobile/lib/providers/search/search_filter.provider.g.dart b/mobile/lib/providers/search/search_filter.provider.g.dart
index a5e70b01e8..03f88b0332 100644
--- a/mobile/lib/providers/search/search_filter.provider.g.dart
+++ b/mobile/lib/providers/search/search_filter.provider.g.dart
@@ -7,7 +7,7 @@ part of 'search_filter.provider.dart';
// **************************************************************************
String _$getSearchSuggestionsHash() =>
- r'bc1e9a1a060868f14e6eb970d2251dbfe39c6866';
+ r'bc30a65e8fcb273cbd07bab876baf67bcc794737';
/// Copied from Dart SDK
class _SystemHash {
diff --git a/mobile/lib/providers/upload_profile_image.provider.dart b/mobile/lib/providers/upload_profile_image.provider.dart
index 83f30e5018..10aa645654 100644
--- a/mobile/lib/providers/upload_profile_image.provider.dart
+++ b/mobile/lib/providers/upload_profile_image.provider.dart
@@ -3,8 +3,8 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:image_picker/image_picker.dart';
-
-import 'package:immich_mobile/services/user.service.dart';
+import 'package:immich_mobile/domain/services/user.service.dart';
+import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
enum UploadProfileStatus {
idle,
@@ -72,7 +72,7 @@ class UploadProfileImageState {
class UploadProfileImageNotifier
extends StateNotifier