mirror of
https://github.com/immich-app/immich.git
synced 2025-12-12 07:41:02 -08:00
Compare commits
53 Commits
refactor/m
...
shared-dat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9996a1ec3e | ||
|
|
23fb2e0fae | ||
|
|
59accbf32a | ||
|
|
059a0e8aa8 | ||
|
|
6a55c36762 | ||
|
|
c0bff4b493 | ||
|
|
fd4c2acde8 | ||
|
|
5acf909235 | ||
|
|
fb1458c720 | ||
|
|
255dabc239 | ||
|
|
27751f8fd4 | ||
|
|
72ffa37dd9 | ||
|
|
5a7042364b | ||
|
|
db0ea0f3a8 | ||
|
|
88c0243a20 | ||
|
|
3a29522df6 | ||
|
|
50eae23f3a | ||
|
|
95419750bb | ||
|
|
5fb858a865 | ||
|
|
18084a49ec | ||
|
|
f107cb044a | ||
|
|
f4e7ea47a6 | ||
|
|
8747fc4935 | ||
|
|
287fa79d75 | ||
|
|
bcfb5bee1f | ||
|
|
538263dc38 | ||
|
|
51aec1e93d | ||
|
|
53825cc3d6 | ||
|
|
6e7c2817a3 | ||
|
|
7bd79b551c | ||
|
|
5fe954b3c9 | ||
|
|
7f81a5bd6f | ||
|
|
37a79292c0 | ||
|
|
bf6211776f | ||
|
|
6c178a04dc | ||
|
|
036d314cb6 | ||
|
|
1fc5da398a | ||
|
|
4d84338086 | ||
|
|
0ac49b00ee | ||
|
|
e427778a96 | ||
|
|
b82e29fbb4 | ||
|
|
ff19aea4ac | ||
|
|
28179a3a1d | ||
|
|
af1e18d07e | ||
|
|
270a0ff986 | ||
|
|
9d3f10372d | ||
|
|
2f1385a236 | ||
|
|
183a285584 | ||
|
|
5ce946bb5b | ||
|
|
674faf2e57 | ||
|
|
4f7702c6bf | ||
|
|
28edf5664d | ||
|
|
ec2f94cae8 |
2
.github/.nvmrc
vendored
2
.github/.nvmrc
vendored
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@@ -34,3 +34,7 @@ The `/api/something` endpoint is now `/api/something-else`
|
|||||||
- [ ] I have followed naming conventions/patterns in the surrounding code
|
- [ ] 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/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/`)
|
- [ ] All code in `src/repositories/` is pretty basic/simple and does not have any immich specific logic (that belongs in `src/services/`)
|
||||||
|
|
||||||
|
## Please describe to which degree, if any, an LLM was used in creating this pull request.
|
||||||
|
|
||||||
|
...
|
||||||
|
|||||||
96
.github/workflows/merge-translations.yml
vendored
Normal file
96
.github/workflows/merge-translations.yml
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
name: Merge translations
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
env:
|
||||||
|
WEBLATE_HOST: 'https://hosted.weblate.org'
|
||||||
|
WEBLATE_COMPONENT: 'immich/immich'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
merge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- name: Find translation PR
|
||||||
|
id: find_pr
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
gh pr list --repo $GITHUB_REPOSITORY --author weblate --json number,mergeable | read PR
|
||||||
|
echo "$PR"
|
||||||
|
|
||||||
|
echo "$PR" | jq '
|
||||||
|
if length == 1 then
|
||||||
|
.[0].number
|
||||||
|
else
|
||||||
|
error("Expected exactly 1 entry, got \(length)")
|
||||||
|
end
|
||||||
|
' 2>&1 | read PR_NUMBER || exit 1
|
||||||
|
|
||||||
|
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||||
|
echo "Selected PR $PR_NUMBER"
|
||||||
|
|
||||||
|
echo "$PR" | jq -e '.[0].mergeable == "MERGEABLE"' || { echo "PR is not mergeable" ; exit 1 }
|
||||||
|
|
||||||
|
- name: Generate a token
|
||||||
|
id: generate_token
|
||||||
|
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|
||||||
|
- name: Lock weblate
|
||||||
|
env:
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=true
|
||||||
|
|
||||||
|
- name: Commit translations
|
||||||
|
env:
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=commit
|
||||||
|
curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=push
|
||||||
|
|
||||||
|
- name: Merge PR
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||||
|
PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }}
|
||||||
|
run: |
|
||||||
|
gh api -X POST "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews" --field event='APPROVE' --field body='Automatically merging translations PR' \
|
||||||
|
| jq '.id' | read REVIEW_ID
|
||||||
|
echo "REVIEW_ID=$REVIEW_ID" >> $GITHUB_OUTPUT
|
||||||
|
gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --auto --squash
|
||||||
|
|
||||||
|
- name: Wait for PR to merge
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||||
|
PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }}
|
||||||
|
REVIEW_ID: ${{ steps.merge_pr.outputs.REVIEW_ID }}
|
||||||
|
run: |
|
||||||
|
for i in {1..10}; do
|
||||||
|
if gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json merged | jq -e '.merged == true'; then
|
||||||
|
echo "PR merged"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "PR not merged yet, waiting..."
|
||||||
|
sleep 6
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "PR did not merge in time"
|
||||||
|
gh api -X PUT "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews/$REVIEW_ID/dismissals" --field message='Merge attempt timed out' --field event='DISMISS'
|
||||||
|
gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --disable-auto
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- name: Unlock weblate
|
||||||
|
env:
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
run: |
|
||||||
|
curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=false
|
||||||
9
.github/workflows/prepare-release.yml
vendored
9
.github/workflows/prepare-release.yml
vendored
@@ -24,6 +24,15 @@ concurrency:
|
|||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
merge_translations:
|
||||||
|
uses: ./.github/workflows/merge-translations.yml
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
secrets:
|
||||||
|
PUSH_O_MATIC_APP_ID: ${{ secrets.PUSH_O_MATIC_APP_ID }}
|
||||||
|
PUSH_O_MATIC_APP_KEY: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }}
|
||||||
|
|
||||||
bump_version:
|
bump_version:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
|
|||||||
23
.github/workflows/weblate-lock.yml
vendored
23
.github/workflows/weblate-lock.yml
vendored
@@ -1,6 +1,7 @@
|
|||||||
name: Weblate checks
|
name: Weblate checks
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
pull_request_review:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
should_run: ${{ steps.found_paths.outputs.i18n == 'true' && github.head_ref != 'chore/translations'}}
|
should_run: ${{ steps.found_paths.outputs.i18n == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
@@ -32,19 +33,15 @@ jobs:
|
|||||||
permissions: {}
|
permissions: {}
|
||||||
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
if: ${{ needs.pre-job.outputs.should_run == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check weblate lock
|
- name: Bot review status
|
||||||
|
env:
|
||||||
|
PR_NUMBER: ${{ github.event.pull_request.number || github.event.pull_request_review.pull_request.number }}
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
if [[ "false" = $(curl https://hosted.weblate.org/api/components/immich/immich/lock/ | jq .locked) ]]; then
|
# Then check for APPROVED by the bot, if absent fail
|
||||||
exit 1
|
gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json reviews | jq -e '.reviews | map(select(.author.login == "github-actions[bot]" and .state == "APPROVED")) | length > 0' \
|
||||||
fi
|
|| (echo "The push-o-matic bot has not approved this PR yet" && exit 1)
|
||||||
- name: Find Pull Request
|
|
||||||
uses: juliangruber/find-pull-request-action@952b3bb1ddb2dcc0aa3479e98bb1c2d1a922f096 # v1.10.0
|
|
||||||
id: find-pr
|
|
||||||
with:
|
|
||||||
branch: chore/translations
|
|
||||||
- name: Fail if existing weblate PR
|
|
||||||
if: ${{ steps.find-pr.outputs.number }}
|
|
||||||
run: exit 1
|
|
||||||
success-check-lock:
|
success-check-lock:
|
||||||
name: Weblate Lock Check Success
|
name: Weblate Lock Check Success
|
||||||
needs: [enforce-lock]
|
needs: [enforce-lock]
|
||||||
|
|||||||
14
Makefile
14
Makefile
@@ -10,14 +10,14 @@ dev-update: prepare-volumes
|
|||||||
dev-scale: prepare-volumes
|
dev-scale: prepare-volumes
|
||||||
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
|
@trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans
|
||||||
|
|
||||||
dev-docs: prepare-volumes
|
dev-docs:
|
||||||
npm --prefix docs run start
|
npm --prefix docs run start
|
||||||
|
|
||||||
.PHONY: e2e
|
.PHONY: e2e
|
||||||
e2e: prepare-volumes
|
e2e:
|
||||||
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --remove-orphans
|
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --remove-orphans
|
||||||
|
|
||||||
e2e-update: prepare-volumes
|
e2e-update:
|
||||||
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans
|
@trap 'make e2e-down' EXIT; COMPOSE_BAKE=true docker compose -f ./e2e/docker-compose.yml up --build -V --remove-orphans
|
||||||
|
|
||||||
e2e-down:
|
e2e-down:
|
||||||
@@ -73,6 +73,8 @@ define safe_chown
|
|||||||
if chown $(2) $(or $(UID),1000):$(or $(GID),1000) "$(1)" 2>/dev/null; then \
|
if chown $(2) $(or $(UID),1000):$(or $(GID),1000) "$(1)" 2>/dev/null; then \
|
||||||
true; \
|
true; \
|
||||||
else \
|
else \
|
||||||
|
STATUS=$$?; echo "Exit code: $$STATUS $(1)"; \
|
||||||
|
echo "$$STATUS $(1)"; \
|
||||||
echo "Permission denied when changing owner of volumes and upload location. Try running 'sudo make prepare-volumes' first."; \
|
echo "Permission denied when changing owner of volumes and upload location. Try running 'sudo make prepare-volumes' first."; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi;
|
fi;
|
||||||
@@ -83,11 +85,13 @@ prepare-volumes:
|
|||||||
@$(foreach dir,$(VOLUME_DIRS),$(call safe_chown,$(dir),-R))
|
@$(foreach dir,$(VOLUME_DIRS),$(call safe_chown,$(dir),-R))
|
||||||
ifneq ($(UPLOAD_LOCATION),)
|
ifneq ($(UPLOAD_LOCATION),)
|
||||||
ifeq ($(filter /%,$(UPLOAD_LOCATION)),)
|
ifeq ($(filter /%,$(UPLOAD_LOCATION)),)
|
||||||
@mkdir -p "docker/$(UPLOAD_LOCATION)"
|
@mkdir -p "docker/$(UPLOAD_LOCATION)/photos/upload"
|
||||||
@$(call safe_chown,docker/$(UPLOAD_LOCATION),)
|
@$(call safe_chown,docker/$(UPLOAD_LOCATION),)
|
||||||
|
@$(call safe_chown,docker/$(UPLOAD_LOCATION)/photos,-R)
|
||||||
else
|
else
|
||||||
@mkdir -p "$(UPLOAD_LOCATION)"
|
@mkdir -p "$(UPLOAD_LOCATION)/photos/upload"
|
||||||
@$(call safe_chown,$(UPLOAD_LOCATION),)
|
@$(call safe_chown,$(UPLOAD_LOCATION),)
|
||||||
|
@$(call safe_chown,$(UPLOAD_LOCATION)/photos,-R)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@immich/cli",
|
"name": "@immich/cli",
|
||||||
"version": "2.2.86",
|
"version": "2.2.88",
|
||||||
"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",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/micromatch": "^4.0.9",
|
"@types/micromatch": "^4.0.9",
|
||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/node": "^22.17.1",
|
"@types/node": "^22.18.0",
|
||||||
"@vitest/coverage-v8": "^3.0.0",
|
"@vitest/coverage-v8": "^3.0.0",
|
||||||
"byte-size": "^9.0.0",
|
"byte-size": "^9.0.0",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
@@ -69,6 +69,6 @@
|
|||||||
"micromatch": "^4.0.8"
|
"micromatch": "^4.0.8"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.18.0"
|
"node": "22.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
@@ -60,6 +60,6 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.18.0"
|
"node": "22.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
docs/static/archived-versions.json
vendored
8
docs/static/archived-versions.json
vendored
@@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"label": "v1.141.1",
|
||||||
|
"url": "https://v1.141.1.archive.immich.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "v1.141.0",
|
||||||
|
"url": "https://v1.141.0.archive.immich.app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "v1.140.1",
|
"label": "v1.140.1",
|
||||||
"url": "https://v1.140.1.archive.immich.app"
|
"url": "https://v1.140.1.archive.immich.app"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
22.18.0
|
22.19.0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immich-e2e",
|
"name": "immich-e2e",
|
||||||
"version": "1.140.1",
|
"version": "1.141.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@socket.io/component-emitter": "^3.1.2",
|
"@socket.io/component-emitter": "^3.1.2",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.17.1",
|
"@types/node": "^22.18.0",
|
||||||
"@types/oidc-provider": "^9.0.0",
|
"@types/oidc-provider": "^9.0.0",
|
||||||
"@types/pg": "^8.15.1",
|
"@types/pg": "^8.15.1",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-organize-imports": "^4.0.0",
|
"prettier-plugin-organize-imports": "^4.0.0",
|
||||||
"sharp": "^0.34.0",
|
"sharp": "^0.34.3",
|
||||||
"socket.io-client": "^4.7.4",
|
"socket.io-client": "^4.7.4",
|
||||||
"supertest": "^7.0.0",
|
"supertest": "^7.0.0",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
@@ -54,6 +54,6 @@
|
|||||||
"vitest": "^3.0.0"
|
"vitest": "^3.0.0"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "22.18.0"
|
"node": "22.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ describe('/partners', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
createPartner({ id: user2.userId }, { headers: asBearerAuth(user1.accessToken) }),
|
createPartner({ partnerCreateDto: { sharedWithId: user2.userId } }, { headers: asBearerAuth(user1.accessToken) }),
|
||||||
createPartner({ id: user1.userId }, { headers: asBearerAuth(user2.accessToken) }),
|
createPartner({ partnerCreateDto: { sharedWithId: user1.userId } }, { headers: asBearerAuth(user2.accessToken) }),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -462,7 +462,8 @@ export const utils = {
|
|||||||
updateLibrary: (accessToken: string, id: string, dto: UpdateLibraryDto) =>
|
updateLibrary: (accessToken: string, id: string, dto: UpdateLibraryDto) =>
|
||||||
updateLibrary({ id, updateLibraryDto: dto }, { headers: asBearerAuth(accessToken) }),
|
updateLibrary({ id, updateLibraryDto: dto }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|
||||||
createPartner: (accessToken: string, id: string) => createPartner({ id }, { headers: asBearerAuth(accessToken) }),
|
createPartner: (accessToken: string, id: string) =>
|
||||||
|
createPartner({ partnerCreateDto: { sharedWithId: id } }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|
||||||
updateMyPreferences: (accessToken: string, userPreferencesUpdateDto: UserPreferencesUpdateDto) =>
|
updateMyPreferences: (accessToken: string, userPreferencesUpdateDto: UserPreferencesUpdateDto) =>
|
||||||
updateMyPreferences({ userPreferencesUpdateDto }, { headers: asBearerAuth(accessToken) }),
|
updateMyPreferences({ userPreferencesUpdateDto }, { headers: asBearerAuth(accessToken) }),
|
||||||
|
|||||||
@@ -396,6 +396,7 @@
|
|||||||
"advanced_settings_prefer_remote_title": "تفضل الصور البعيدة",
|
"advanced_settings_prefer_remote_title": "تفضل الصور البعيدة",
|
||||||
"advanced_settings_proxy_headers_subtitle": "عرف عناوين الوكيل التي يستخدمها Immich لارسال كل طلب شبكي",
|
"advanced_settings_proxy_headers_subtitle": "عرف عناوين الوكيل التي يستخدمها Immich لارسال كل طلب شبكي",
|
||||||
"advanced_settings_proxy_headers_title": "عناوين الوكيل",
|
"advanced_settings_proxy_headers_title": "عناوين الوكيل",
|
||||||
|
"advanced_settings_readonly_mode_title": "وضع القراءة فقط",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "تخطي التحقق من شهادة SSL لخادم النقطة النهائي. مكلوب للشهادات الموقعة ذاتيا.",
|
"advanced_settings_self_signed_ssl_subtitle": "تخطي التحقق من شهادة SSL لخادم النقطة النهائي. مكلوب للشهادات الموقعة ذاتيا.",
|
||||||
"advanced_settings_self_signed_ssl_title": "السماح بشهادات SSL الموقعة ذاتيًا",
|
"advanced_settings_self_signed_ssl_title": "السماح بشهادات SSL الموقعة ذاتيًا",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "حذف او استعادة تلقائي للاصول على هذا الجهاز عند تنفيذ العملية على الويب",
|
"advanced_settings_sync_remote_deletions_subtitle": "حذف او استعادة تلقائي للاصول على هذا الجهاز عند تنفيذ العملية على الويب",
|
||||||
|
|||||||
29
i18n/az.json
29
i18n/az.json
@@ -1,37 +1,53 @@
|
|||||||
{
|
{
|
||||||
"about": "Haqqinda",
|
"about": "Haqqında",
|
||||||
"account": "Hesab",
|
"account": "Hesab",
|
||||||
"account_settings": "Hesab parametrləri",
|
"account_settings": "Hesab parametrləri",
|
||||||
"acknowledge": "Təsdiq et",
|
"acknowledge": "Təsdiq et",
|
||||||
"action": "Əməliyyat",
|
"action": "Əməliyyat",
|
||||||
|
"action_common_update": "Yenilə",
|
||||||
"actions": "Əməliyyatlar",
|
"actions": "Əməliyyatlar",
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"activity": "Fəaliyyət",
|
"activity": "Fəaliyyət",
|
||||||
|
"activity_changed": "Fəaliyyət {enabled, select, true {aktivdir} other {aktiv deyil}}",
|
||||||
"add": "Əlavə et",
|
"add": "Əlavə et",
|
||||||
"add_a_description": "Təsviri əlavə et",
|
"add_a_description": "Təsviri əlavə et",
|
||||||
"add_a_location": "Məkan əlavə et",
|
"add_a_location": "Məkan əlavə et",
|
||||||
"add_a_name": "Ad əlavə et",
|
"add_a_name": "Ad əlavə et",
|
||||||
"add_a_title": "Başlıq əlavə et",
|
"add_a_title": "Başlıq əlavə et",
|
||||||
|
"add_birthday": "Doğum günü əlavə et",
|
||||||
|
"add_endpoint": "Son nöqtə əlavə et",
|
||||||
"add_exclusion_pattern": "İstisna nümunəsi əlavə et",
|
"add_exclusion_pattern": "İstisna nümunəsi əlavə et",
|
||||||
"add_import_path": "Import yolunu əlavə et",
|
"add_import_path": "Import yolunu əlavə et",
|
||||||
"add_location": "Məkanı əlavə et",
|
"add_location": "Məkan əlavə et",
|
||||||
"add_more_users": "Daha çox istifadəçi əlavə et",
|
"add_more_users": "Daha çox istifadəçi əlavə et",
|
||||||
"add_partner": "Partnyor əlavə et",
|
"add_partner": "Partnyor əlavə et",
|
||||||
"add_path": "Yol əlavə et",
|
"add_path": "Yol əlavə et",
|
||||||
"add_photos": "Şəkilləri əlavə et",
|
"add_photos": "Şəkillər əlavə et",
|
||||||
"add_to": "... əlavə et",
|
"add_tag": "Etiket əlavə et",
|
||||||
|
"add_to": "Bura əlavə et…",
|
||||||
"add_to_album": "Albom əlavə et",
|
"add_to_album": "Albom əlavə et",
|
||||||
|
"add_to_album_bottom_sheet_added": "{album} albomuna əlavə edildi",
|
||||||
|
"add_to_album_bottom_sheet_already_exists": "Artıq {album} albomunda var",
|
||||||
|
"add_to_album_toggle": "{album} üçün seçimi dəyişin",
|
||||||
|
"add_to_albums": "Albomlara əlavə et",
|
||||||
|
"add_to_albums_count": "Albomlara əlavə et ({count})",
|
||||||
"add_to_shared_album": "Paylaşılan alboma əlavə et",
|
"add_to_shared_album": "Paylaşılan alboma əlavə et",
|
||||||
|
"add_url": "URL əlavə et",
|
||||||
"added_to_archive": "Arxivə əlavə edildi",
|
"added_to_archive": "Arxivə əlavə edildi",
|
||||||
"added_to_favorites": "Sevimlilələrə əlavə edildi",
|
"added_to_favorites": "Sevimlilələrə əlavə edildi",
|
||||||
"added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi",
|
"added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi",
|
||||||
"admin": {
|
"admin": {
|
||||||
|
"add_exclusion_pattern_description": "İstisna şablonlarını əlavə edin. *, ** və ? ilə Globbing dəstəklənir. Məs.: \"Raw\" adlanan hər hansısa bir qovluqda bütün faylları saymamaq üçün \"**/Raw/**\"-dan istifadə edin. \".tif\" ilə bitən bütün faylları saymamaq üçün \"**/*.tif\"-dən istifadə edin. Faylı mütləq yoldan istifadə etməklə saymamaq istəyirsinizsə \"/path/to/ignore/**\"-dan istifadə edin.",
|
||||||
|
"admin_user": "Admin İstifadəçi",
|
||||||
|
"asset_offline_description": "Bu xarici kitabxana varlığı diskdə artıq tapılmadı və zibil qutusuna köçürüldü. Əgər fayl kitabxana içərisində köçürülübsə, zaman şkalanızı yeni uyğun gələn varlıq üçün yoxlayın. Varlığı yenidən qaytarmaq üçün aşağıda verilmiş fayl yolunun Immich tərəfindən əlçatan olduğundan əmin olduqdan sonra kitabxananı skan edin.",
|
||||||
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
|
"authentication_settings": "Səlahiyyətləndirmə parametrləri",
|
||||||
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
|
"authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri",
|
||||||
"authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.",
|
"authentication_settings_disable_all": "Bütün giriş etmə metodlarını söndürmək istədiyinizdən əminsinizmi? Giriş etmə funksiyası tamamilə söndürüləcəkdir.",
|
||||||
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link> -ni istifadə edin.",
|
"authentication_settings_reenable": "Yenidən aktiv etmək üçün <link> Server Əmri</link> -ni istifadə edin.",
|
||||||
"background_task_job": "Arxa plan tapşırıqları",
|
"background_task_job": "Arxa plan tapşırıqları",
|
||||||
"backup_database_enable_description": "Verilənlər bazasının ehtiyat nüsxələrini aktiv et",
|
"backup_database": "Verilənlər bazasının dump-ını yaradın",
|
||||||
|
"backup_database_enable_description": "Verilənlər bazasının artıq nüsxələrini aktiv et",
|
||||||
|
"backup_keep_last_amount": "Tutulması gərəkən nüsxələrin sayı",
|
||||||
"backup_settings": "Ehtiyat Nüsxə Parametrləri",
|
"backup_settings": "Ehtiyat Nüsxə Parametrləri",
|
||||||
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
|
"backup_settings_description": "Verilənlər bazasının ehtiyat nüsxə parametrlərini idarə et",
|
||||||
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
|
"config_set_by_file": "Konfiqurasiya hal-hazırda konfiqurasiya faylı ilə təyin olunub",
|
||||||
@@ -84,5 +100,6 @@
|
|||||||
"machine_learning_facial_recognition": "Üz Tanıma",
|
"machine_learning_facial_recognition": "Üz Tanıma",
|
||||||
"machine_learning_facial_recognition_description": "Şəkillərdəki üzləri aşkarla, tanı və qruplaşdır",
|
"machine_learning_facial_recognition_description": "Şəkillərdəki üzləri aşkarla, tanı və qruplaşdır",
|
||||||
"machine_learning_facial_recognition_model": "Üz tanıma modeli"
|
"machine_learning_facial_recognition_model": "Üz tanıma modeli"
|
||||||
}
|
},
|
||||||
|
"timeline": "Zaman şkalası"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -399,6 +399,8 @@
|
|||||||
"purchase_button_buy": "Купіць",
|
"purchase_button_buy": "Купіць",
|
||||||
"purchase_button_buy_immich": "Купіць Immich",
|
"purchase_button_buy_immich": "Купіць Immich",
|
||||||
"purchase_button_select": "Выбраць",
|
"purchase_button_select": "Выбраць",
|
||||||
|
"readonly_mode_enabled": "Уключаны рэжым толькі для чытання",
|
||||||
|
"reassign": "Перапрызначыць",
|
||||||
"remove": "Выдаліць",
|
"remove": "Выдаліць",
|
||||||
"remove_from_album": "Выдаліць з альбома",
|
"remove_from_album": "Выдаліць з альбома",
|
||||||
"remove_from_favorites": "Выдаліць з абраных",
|
"remove_from_favorites": "Выдаліць з абраных",
|
||||||
|
|||||||
24
i18n/bg.json
24
i18n/bg.json
@@ -396,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Предпочитай изображенията на сървъра",
|
"advanced_settings_prefer_remote_title": "Предпочитай изображенията на сървъра",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Дефиниране на прокси хедъри, които Immich трябва да изпраща с всяка мрежова заявка",
|
"advanced_settings_proxy_headers_subtitle": "Дефиниране на прокси хедъри, които Immich трябва да изпраща с всяка мрежова заявка",
|
||||||
"advanced_settings_proxy_headers_title": "Прокси хедъри",
|
"advanced_settings_proxy_headers_title": "Прокси хедъри",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Активира режима \"само за четене\", при който снимките могат да бъдат разглеждани, но неща като избор на няколко изображения, споделяне, изтриване са забранени. Активиране/деактивиране на режима само за четене става от картинката-аватар на потребителя от основния екран",
|
||||||
|
"advanced_settings_readonly_mode_title": "Режим само за четене",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Пропуска проверката на SSL-сертификата на сървъра. Изисква се при самоподписани сертификати.",
|
"advanced_settings_self_signed_ssl_subtitle": "Пропуска проверката на SSL-сертификата на сървъра. Изисква се при самоподписани сертификати.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Разреши самоподписани SSL сертификати",
|
"advanced_settings_self_signed_ssl_title": "Разреши самоподписани SSL сертификати",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Автоматично изтрии или възстанови обект на това устройство, когато действието е извършено през уеб-интерфейса",
|
"advanced_settings_sync_remote_deletions_subtitle": "Автоматично изтрии или възстанови обект на това устройство, когато действието е извършено през уеб-интерфейса",
|
||||||
@@ -461,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Излез от профила",
|
"app_bar_signout_dialog_title": "Излез от профила",
|
||||||
"app_settings": "Настройки ма приложението",
|
"app_settings": "Настройки ма приложението",
|
||||||
"appears_in": "Излиза в",
|
"appears_in": "Излиза в",
|
||||||
|
"apply_count": "Приложи ({count, number})",
|
||||||
"archive": "Архив",
|
"archive": "Архив",
|
||||||
"archive_action_prompt": "{count} са добавени в Архива",
|
"archive_action_prompt": "{count} са добавени в Архива",
|
||||||
"archive_or_unarchive_photo": "Архивиране или деархивиране на снимка",
|
"archive_or_unarchive_photo": "Архивиране или деархивиране на снимка",
|
||||||
@@ -500,7 +503,7 @@
|
|||||||
"assets": "Елементи",
|
"assets": "Елементи",
|
||||||
"assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}",
|
"assets_added_count": "Добавено {count, plural, one {# asset} other {# assets}}",
|
||||||
"assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума",
|
"assets_added_to_album_count": "Добавен(и) са {count, plural, one {# актив} other {# актива}} в албума",
|
||||||
"assets_added_to_albums_count": "Добавени са {assetTotal} обекта в {albumTotal} албума",
|
"assets_added_to_albums_count": "{assetTotal, plural, one {# обект е добавен} other {# обекта са добавени}} в {albumTotal, plural, one {# албум} other {# албума}}",
|
||||||
"assets_cannot_be_added_to_album_count": "{count, plural, one {Обекта не може да се добави} other {Обектите не може да се добавят}} в албума",
|
"assets_cannot_be_added_to_album_count": "{count, plural, one {Обекта не може да се добави} other {Обектите не може да се добавят}} в албума",
|
||||||
"assets_cannot_be_added_to_albums": "{count, plural, one {обект не може да бъде добавен} other {обекта не могат да бъдат добавени}} в никой от албумите",
|
"assets_cannot_be_added_to_albums": "{count, plural, one {обект не може да бъде добавен} other {обекта не могат да бъдат добавени}} в никой от албумите",
|
||||||
"assets_count": "{count, plural, one {# актив} other {# актива}}",
|
"assets_count": "{count, plural, one {# актив} other {# актива}}",
|
||||||
@@ -912,7 +915,7 @@
|
|||||||
"error_selecting_all_assets": "Грешка при избора на всички файлове",
|
"error_selecting_all_assets": "Грешка при избора на всички файлове",
|
||||||
"exclusion_pattern_already_exists": "Този модел за изключване вече съществува.",
|
"exclusion_pattern_already_exists": "Този модел за изключване вече съществува.",
|
||||||
"failed_to_create_album": "Неуспешно създаване на албум",
|
"failed_to_create_album": "Неуспешно създаване на албум",
|
||||||
"failed_to_create_shared_link": "Неуспешно създаване на споделена връзка",
|
"failed_to_create_shared_link": "Неуспешно създаване на спoделена връзка",
|
||||||
"failed_to_edit_shared_link": "Неуспешно редактиране на споделена връзка",
|
"failed_to_edit_shared_link": "Неуспешно редактиране на споделена връзка",
|
||||||
"failed_to_get_people": "Неуспешно зареждане на хора",
|
"failed_to_get_people": "Неуспешно зареждане на хора",
|
||||||
"failed_to_keep_this_delete_others": "Неуспешно запазване на този обект и изтриване на останалите обекти",
|
"failed_to_keep_this_delete_others": "Неуспешно запазване на този обект и изтриване на останалите обекти",
|
||||||
@@ -1073,12 +1076,18 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
|
"gcast_enabled_description": "За да работи тази функция зарежда външни ресурси от Google.",
|
||||||
"general": "Общи",
|
"general": "Общи",
|
||||||
|
"geolocation_instruction_all_have_location": "Всички обекти от тази дата вече имат данни за местоположение. Опитайте да включите показване на всички обекти или изберете друга дата",
|
||||||
|
"geolocation_instruction_location": "Изберете обект с GPS координати за да използвате тях или изберете място директно от картата",
|
||||||
|
"geolocation_instruction_no_date": "Изберете дата за да управлявате данните за локация на снимките и видеата от тази дата",
|
||||||
|
"geolocation_instruction_no_photos": "Не са намерени снимки или видеа от тази дата. Изберете друга дата",
|
||||||
"get_help": "Помощ",
|
"get_help": "Помощ",
|
||||||
"get_wifiname_error": "Неуспешно получаване името на Wi-Fi мрежата. Моля, убедете се, че са предоставени нужните разрешения на приложението и има връзка с Wi-Fi",
|
"get_wifiname_error": "Неуспешно получаване името на Wi-Fi мрежата. Моля, убедете се, че са предоставени нужните разрешения на приложението и има връзка с Wi-Fi",
|
||||||
"getting_started": "Как да започнем",
|
"getting_started": "Как да започнем",
|
||||||
"go_back": "Връщане назад",
|
"go_back": "Връщане назад",
|
||||||
"go_to_folder": "Отиди в папката",
|
"go_to_folder": "Отиди в папката",
|
||||||
"go_to_search": "Преминаване към търсене",
|
"go_to_search": "Преминаване към търсене",
|
||||||
|
"gps": "GPS координати",
|
||||||
|
"gps_missing": "Няма GPS координати",
|
||||||
"grant_permission": "Дай разрешение",
|
"grant_permission": "Дай разрешение",
|
||||||
"group_albums_by": "Групирай албум по...",
|
"group_albums_by": "Групирай албум по...",
|
||||||
"group_country": "Групирай по държава",
|
"group_country": "Групирай по държава",
|
||||||
@@ -1262,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Използвате версия за разработчици, силно препоръчваме да използвате официална версия!",
|
"main_branch_warning": "Използвате версия за разработчици, силно препоръчваме да използвате официална версия!",
|
||||||
"main_menu": "Главно меню",
|
"main_menu": "Главно меню",
|
||||||
"make": "Марка",
|
"make": "Марка",
|
||||||
|
"manage_geolocation": "Управление на местоположенията",
|
||||||
"manage_shared_links": "Управление на споделени връзки",
|
"manage_shared_links": "Управление на споделени връзки",
|
||||||
"manage_sharing_with_partners": "Управление на споделянето с партньори",
|
"manage_sharing_with_partners": "Управление на споделянето с партньори",
|
||||||
"manage_the_app_settings": "Управление на настройките на приложението",
|
"manage_the_app_settings": "Управление на настройките на приложението",
|
||||||
@@ -1508,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "Мобилното приложение е остаряло. Моля, актуализирай до най-новата версия.",
|
"profile_drawer_client_out_of_date_minor": "Мобилното приложение е остаряло. Моля, актуализирай до най-новата версия.",
|
||||||
"profile_drawer_client_server_up_to_date": "Клиента и сървъра са обновени",
|
"profile_drawer_client_server_up_to_date": "Клиента и сървъра са обновени",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Режима само за четене е активиран. С двоен клик върху картиката-аватар на потребителя ще деактивирате само за четене.",
|
||||||
"profile_drawer_server_out_of_date_major": "Версията на сървъра е остаряла. Моля, актуализирай поне до последната главна версия.",
|
"profile_drawer_server_out_of_date_major": "Версията на сървъра е остаряла. Моля, актуализирай поне до последната главна версия.",
|
||||||
"profile_drawer_server_out_of_date_minor": "Версията на сървъра е остаряла. Моля, актуализирай до последната версия.",
|
"profile_drawer_server_out_of_date_minor": "Версията на сървъра е остаряла. Моля, актуализирай до последната версия.",
|
||||||
"profile_image_of_user": "Профилна снимка на {user}",
|
"profile_image_of_user": "Профилна снимка на {user}",
|
||||||
@@ -1553,6 +1564,8 @@
|
|||||||
"rating_description": "Покажи EXIF оценката в панела с информация",
|
"rating_description": "Покажи EXIF оценката в панела с информация",
|
||||||
"reaction_options": "Избор на реакция",
|
"reaction_options": "Избор на реакция",
|
||||||
"read_changelog": "Прочети промените",
|
"read_changelog": "Прочети промените",
|
||||||
|
"readonly_mode_disabled": "Режима само за четене е деактивиран",
|
||||||
|
"readonly_mode_enabled": "Режима само за четене е активиран",
|
||||||
"reassign": "Преназначаване",
|
"reassign": "Преназначаване",
|
||||||
"reassigned_assets_to_existing_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на {name, select, null {съществуващ човек} other {{name}}}",
|
"reassigned_assets_to_existing_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на {name, select, null {съществуващ човек} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на нов човек",
|
"reassigned_assets_to_new_person": "Преназначени {count, plural, one {# елемент} other {# елемента}} на нов човек",
|
||||||
@@ -1722,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Създаването на албум не бе успешно",
|
"select_user_for_sharing_page_err_album": "Създаването на албум не бе успешно",
|
||||||
"selected": "Избрано",
|
"selected": "Избрано",
|
||||||
"selected_count": "{count, plural, other {# избрани}}",
|
"selected_count": "{count, plural, other {# избрани}}",
|
||||||
|
"selected_gps_coordinates": "избрани GPS координати",
|
||||||
"send_message": "Изпратете съобщение",
|
"send_message": "Изпратете съобщение",
|
||||||
"send_welcome_email": "Изпратете имейл за добре дошли",
|
"send_welcome_email": "Изпратете имейл за добре дошли",
|
||||||
"server_endpoint": "Адрес на сървъра",
|
"server_endpoint": "Адрес на сървъра",
|
||||||
@@ -1832,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "Натиснете ⇧, за да изтриете завинаги елемента",
|
"shift_to_permanent_delete": "Натиснете ⇧, за да изтриете завинаги елемента",
|
||||||
"show_album_options": "Показване опции за албум",
|
"show_album_options": "Показване опции за албум",
|
||||||
"show_albums": "Покажи албуми",
|
"show_albums": "Покажи албуми",
|
||||||
|
"show_all_assets": "Покажи всичко",
|
||||||
"show_all_people": "Покажи всички хора",
|
"show_all_people": "Покажи всички хора",
|
||||||
"show_and_hide_people": "Показване и скриване на хора",
|
"show_and_hide_people": "Показване и скриване на хора",
|
||||||
|
"show_assets_without_location": "Покажи обекти без координати",
|
||||||
"show_file_location": "Покажи местоположението на файла",
|
"show_file_location": "Покажи местоположението на файла",
|
||||||
"show_gallery": "Покажи галерия",
|
"show_gallery": "Покажи галерия",
|
||||||
"show_hidden_people": "Показване на скритите хора",
|
"show_hidden_people": "Показване на скритите хора",
|
||||||
@@ -1941,7 +1957,9 @@
|
|||||||
"to_change_password": "Промяна на паролата",
|
"to_change_password": "Промяна на паролата",
|
||||||
"to_favorite": "Любим",
|
"to_favorite": "Любим",
|
||||||
"to_login": "Вписване",
|
"to_login": "Вписване",
|
||||||
|
"to_multi_select": "за избор на няколко",
|
||||||
"to_parent": "Отиди към родителския елемент",
|
"to_parent": "Отиди към родителския елемент",
|
||||||
|
"to_select": "за избор",
|
||||||
"to_trash": "Кошче",
|
"to_trash": "Кошче",
|
||||||
"toggle_settings": "Превключване на настройките",
|
"toggle_settings": "Превключване на настройките",
|
||||||
"total": "Общо",
|
"total": "Общо",
|
||||||
@@ -1991,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "Разкачени {count, plural, one {# елемент} other {# елементи}}",
|
"unstacked_assets_count": "Разкачени {count, plural, one {# елемент} other {# елементи}}",
|
||||||
"untagged": "Немаркирани",
|
"untagged": "Немаркирани",
|
||||||
"up_next": "Следващ",
|
"up_next": "Следващ",
|
||||||
|
"update_location_action_prompt": "Обнови координатите на {count} избрани обекта с:",
|
||||||
"updated_at": "Обновено",
|
"updated_at": "Обновено",
|
||||||
"updated_password": "Паролата е актуализирана",
|
"updated_password": "Паролата е актуализирана",
|
||||||
"upload": "Качване",
|
"upload": "Качване",
|
||||||
@@ -2015,6 +2034,7 @@
|
|||||||
"use_biometric": "Използвай биометрия",
|
"use_biometric": "Използвай биометрия",
|
||||||
"use_current_connection": "използвай текущата връзка",
|
"use_current_connection": "използвай текущата връзка",
|
||||||
"use_custom_date_range": "Използвайте собствен диапазон от дати вместо това",
|
"use_custom_date_range": "Използвайте собствен диапазон от дати вместо това",
|
||||||
|
"use_this_location": "Избери това място",
|
||||||
"user": "Потребител",
|
"user": "Потребител",
|
||||||
"user_has_been_deleted": "Този потребител е премахнат.",
|
"user_has_been_deleted": "Този потребител е премахнат.",
|
||||||
"user_id": "Потребител ИД",
|
"user_id": "Потребител ИД",
|
||||||
|
|||||||
@@ -14,5 +14,10 @@
|
|||||||
"add_exclusion_pattern": "Putem wan paten wae hemi karem aot",
|
"add_exclusion_pattern": "Putem wan paten wae hemi karem aot",
|
||||||
"add_import_path": "Putem wan pat blo import",
|
"add_import_path": "Putem wan pat blo import",
|
||||||
"add_location": "Putem wan place blo hem",
|
"add_location": "Putem wan place blo hem",
|
||||||
"add_more_users": "Putem mor man"
|
"add_more_users": "Putem mor man",
|
||||||
|
"readonly_mode_enabled": "Mod blo yu no save janjem i on",
|
||||||
|
"reassigned_assets_to_new_person": "Janjem{count, plural, one {# asset} other {# assets}} blo nu man",
|
||||||
|
"reassing_hint": "janjem ol sumtin yu bin joos i go blo wan man",
|
||||||
|
"recent-albums": "album i no old tu mas",
|
||||||
|
"recent_searches": "lukabout wea i no old tu mas"
|
||||||
}
|
}
|
||||||
|
|||||||
20
i18n/ca.json
20
i18n/ca.json
@@ -396,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Prefereix imatges remotes",
|
"advanced_settings_prefer_remote_title": "Prefereix imatges remotes",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Definiu les capçaleres de proxy que Immich per enviar amb cada sol·licitud de xarxa",
|
"advanced_settings_proxy_headers_subtitle": "Definiu les capçaleres de proxy que Immich per enviar amb cada sol·licitud de xarxa",
|
||||||
"advanced_settings_proxy_headers_title": "Capçaleres de proxy",
|
"advanced_settings_proxy_headers_title": "Capçaleres de proxy",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Habilita el només de lectura mode on les fotos poden ser només vist, a coses els agrada seleccionant imatges múltiples, compartint, càsting, elimina és tot discapacitat. Habilita/Desactiva només de lectura via avatar d'usuari des de la pantalla major",
|
||||||
|
"advanced_settings_readonly_mode_title": "Mode de només lectura",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Omet la verificació del certificat SSL del servidor. Requerit per a certificats autosignats.",
|
"advanced_settings_self_signed_ssl_subtitle": "Omet la verificació del certificat SSL del servidor. Requerit per a certificats autosignats.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Permet certificats SSL autosignats",
|
"advanced_settings_self_signed_ssl_title": "Permet certificats SSL autosignats",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Suprimeix o restaura automàticament un actiu en aquest dispositiu quan es realitzi aquesta acció al web",
|
"advanced_settings_sync_remote_deletions_subtitle": "Suprimeix o restaura automàticament un actiu en aquest dispositiu quan es realitzi aquesta acció al web",
|
||||||
@@ -461,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Tanca la sessió",
|
"app_bar_signout_dialog_title": "Tanca la sessió",
|
||||||
"app_settings": "Configuració de l'app",
|
"app_settings": "Configuració de l'app",
|
||||||
"appears_in": "Apareix a",
|
"appears_in": "Apareix a",
|
||||||
|
"apply_count": "Aplicar ({count, number})",
|
||||||
"archive": "Arxiu",
|
"archive": "Arxiu",
|
||||||
"archive_action_prompt": "{count} afegit a Arxiu",
|
"archive_action_prompt": "{count} afegit a Arxiu",
|
||||||
"archive_or_unarchive_photo": "Arxivar o desarxivar fotografia",
|
"archive_or_unarchive_photo": "Arxivar o desarxivar fotografia",
|
||||||
@@ -1073,12 +1076,18 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Aquesta funció carrega recursos externs de Google per funcionar.",
|
"gcast_enabled_description": "Aquesta funció carrega recursos externs de Google per funcionar.",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
|
"geolocation_instruction_all_have_location": "Tots els actius d'aquesta data ja tenen dades d'ubicació. Prova de mostrar tots els actius o selecciona una data diferent",
|
||||||
|
"geolocation_instruction_location": "Fes click en un element amb coordinades GPS per utilitzar la seva ubicació o selecciona una ubicació des del mapa",
|
||||||
|
"geolocation_instruction_no_date": "Seleccioneu una data per gestionar dades d'ubicació per a fotos i vídeos d'aquest dia",
|
||||||
|
"geolocation_instruction_no_photos": "Cap foto o vídeo trobats per a aquesta data. Selecciona una data diferent",
|
||||||
"get_help": "Aconseguir ajuda",
|
"get_help": "Aconseguir ajuda",
|
||||||
"get_wifiname_error": "No s'ha pogut obtenir el nom de la Wi-Fi. Assegureu-vos que heu concedit els permisos necessaris i que esteu connectat a una xarxa Wi-Fi",
|
"get_wifiname_error": "No s'ha pogut obtenir el nom de la Wi-Fi. Assegureu-vos que heu concedit els permisos necessaris i que esteu connectat a una xarxa Wi-Fi",
|
||||||
"getting_started": "Començant",
|
"getting_started": "Començant",
|
||||||
"go_back": "Torna",
|
"go_back": "Torna",
|
||||||
"go_to_folder": "Anar al directori",
|
"go_to_folder": "Anar al directori",
|
||||||
"go_to_search": "Vés a cercar",
|
"go_to_search": "Vés a cercar",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "Sense GPS",
|
||||||
"grant_permission": "Concedir permís",
|
"grant_permission": "Concedir permís",
|
||||||
"group_albums_by": "Agrupa àlbums per...",
|
"group_albums_by": "Agrupa àlbums per...",
|
||||||
"group_country": "Agrupar per país",
|
"group_country": "Agrupar per país",
|
||||||
@@ -1262,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Esteu utilitzant una versió en desenvolupament; Recomanem fer servir una versió publicada!",
|
"main_branch_warning": "Esteu utilitzant una versió en desenvolupament; Recomanem fer servir una versió publicada!",
|
||||||
"main_menu": "Menú principal",
|
"main_menu": "Menú principal",
|
||||||
"make": "Fabricant",
|
"make": "Fabricant",
|
||||||
|
"manage_geolocation": "Gestioneu la vostra ubicació",
|
||||||
"manage_shared_links": "Administrar enllaços compartits",
|
"manage_shared_links": "Administrar enllaços compartits",
|
||||||
"manage_sharing_with_partners": "Gestiona la compartició amb els companys",
|
"manage_sharing_with_partners": "Gestiona la compartició amb els companys",
|
||||||
"manage_the_app_settings": "Gestioneu la configuració de l'aplicació",
|
"manage_the_app_settings": "Gestioneu la configuració de l'aplicació",
|
||||||
@@ -1508,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "L'aplicació mòbil està desactualitzada. Si us plau, actualitzeu a l'última versió menor.",
|
"profile_drawer_client_out_of_date_minor": "L'aplicació mòbil està desactualitzada. Si us plau, actualitzeu a l'última versió menor.",
|
||||||
"profile_drawer_client_server_up_to_date": "El Client i el Servidor estan actualitzats",
|
"profile_drawer_client_server_up_to_date": "El Client i el Servidor estan actualitzats",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Manera de només lectura activada. Feu doble click a la icona de l'avatar de l'usuari per sortir.",
|
||||||
"profile_drawer_server_out_of_date_major": "El servidor està desactualitzat. Si us plau, actualitzeu a l'última versió major.",
|
"profile_drawer_server_out_of_date_major": "El servidor està desactualitzat. Si us plau, actualitzeu a l'última versió major.",
|
||||||
"profile_drawer_server_out_of_date_minor": "El servidor està desactualitzat. Si us plau, actualitzeu a l'última versió menor.",
|
"profile_drawer_server_out_of_date_minor": "El servidor està desactualitzat. Si us plau, actualitzeu a l'última versió menor.",
|
||||||
"profile_image_of_user": "Imatge de perfil de {user}",
|
"profile_image_of_user": "Imatge de perfil de {user}",
|
||||||
@@ -1553,6 +1564,8 @@
|
|||||||
"rating_description": "Mostrar la valoració EXIF al panell d'informació",
|
"rating_description": "Mostrar la valoració EXIF al panell d'informació",
|
||||||
"reaction_options": "Opcions de reacció",
|
"reaction_options": "Opcions de reacció",
|
||||||
"read_changelog": "Llegeix el registre de canvis",
|
"read_changelog": "Llegeix el registre de canvis",
|
||||||
|
"readonly_mode_disabled": "Mode de només lectura desactivat",
|
||||||
|
"readonly_mode_enabled": "Mode de només lectura activat",
|
||||||
"reassign": "Reassignar",
|
"reassign": "Reassignar",
|
||||||
"reassigned_assets_to_existing_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a {name, select, null {una persona existent} other {{name}}}",
|
"reassigned_assets_to_existing_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a {name, select, null {una persona existent} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a una persona nova",
|
"reassigned_assets_to_new_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a una persona nova",
|
||||||
@@ -1722,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Error al crear l'àlbum",
|
"select_user_for_sharing_page_err_album": "Error al crear l'àlbum",
|
||||||
"selected": "Seleccionat",
|
"selected": "Seleccionat",
|
||||||
"selected_count": "{count, plural, one {# seleccionat} other {# seleccionats}}",
|
"selected_count": "{count, plural, one {# seleccionat} other {# seleccionats}}",
|
||||||
|
"selected_gps_coordinates": "seleccio de coordinades GPS",
|
||||||
"send_message": "Envia missatge",
|
"send_message": "Envia missatge",
|
||||||
"send_welcome_email": "Envia correu de benvinguda",
|
"send_welcome_email": "Envia correu de benvinguda",
|
||||||
"server_endpoint": "Endpoint de Servidor",
|
"server_endpoint": "Endpoint de Servidor",
|
||||||
@@ -1832,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "premeu ⇧ per suprimir el recurs permanentment",
|
"shift_to_permanent_delete": "premeu ⇧ per suprimir el recurs permanentment",
|
||||||
"show_album_options": "Mostra les opcions d'àlbum",
|
"show_album_options": "Mostra les opcions d'àlbum",
|
||||||
"show_albums": "Mostrar àlbums",
|
"show_albums": "Mostrar àlbums",
|
||||||
|
"show_all_assets": "Mostrar tots els elements",
|
||||||
"show_all_people": "Veure totes les persones",
|
"show_all_people": "Veure totes les persones",
|
||||||
"show_and_hide_people": "Mostra i amaga persones",
|
"show_and_hide_people": "Mostra i amaga persones",
|
||||||
|
"show_assets_without_location": "Mostra els elements sense ubicació",
|
||||||
"show_file_location": "Mostra l'ubicació del fitxer",
|
"show_file_location": "Mostra l'ubicació del fitxer",
|
||||||
"show_gallery": "Mostra la galeria",
|
"show_gallery": "Mostra la galeria",
|
||||||
"show_hidden_people": "Mostra persones ocultes",
|
"show_hidden_people": "Mostra persones ocultes",
|
||||||
@@ -1941,7 +1957,9 @@
|
|||||||
"to_change_password": "Canviar la contrasenya",
|
"to_change_password": "Canviar la contrasenya",
|
||||||
"to_favorite": "Prefereix",
|
"to_favorite": "Prefereix",
|
||||||
"to_login": "Iniciar sessió",
|
"to_login": "Iniciar sessió",
|
||||||
|
"to_multi_select": "per multi-seleccionar",
|
||||||
"to_parent": "Anar als pares",
|
"to_parent": "Anar als pares",
|
||||||
|
"to_select": "per seleccionar",
|
||||||
"to_trash": "Paperera",
|
"to_trash": "Paperera",
|
||||||
"toggle_settings": "Canvia configuració",
|
"toggle_settings": "Canvia configuració",
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
@@ -1991,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "No apilat {count, plural, one {# recurs} other {# recursos}}",
|
"unstacked_assets_count": "No apilat {count, plural, one {# recurs} other {# recursos}}",
|
||||||
"untagged": "Sense etiqueta",
|
"untagged": "Sense etiqueta",
|
||||||
"up_next": "Pròxim",
|
"up_next": "Pròxim",
|
||||||
|
"update_location_action_prompt": "Actualitza la ubicació de {count} elements seleccionats amb:",
|
||||||
"updated_at": "Actualitzat",
|
"updated_at": "Actualitzat",
|
||||||
"updated_password": "Contrasenya actualitzada",
|
"updated_password": "Contrasenya actualitzada",
|
||||||
"upload": "Pujar",
|
"upload": "Pujar",
|
||||||
@@ -2015,6 +2034,7 @@
|
|||||||
"use_biometric": "Empra biometria",
|
"use_biometric": "Empra biometria",
|
||||||
"use_current_connection": "utilitzar la connexió actual",
|
"use_current_connection": "utilitzar la connexió actual",
|
||||||
"use_custom_date_range": "Fes servir un rang de dates personalitzat",
|
"use_custom_date_range": "Fes servir un rang de dates personalitzat",
|
||||||
|
"use_this_location": "Fes clic per utilitzar la ubicació",
|
||||||
"user": "Usuari",
|
"user": "Usuari",
|
||||||
"user_has_been_deleted": "Aquest usuari ha sigut eliminat.",
|
"user_has_been_deleted": "Aquest usuari ha sigut eliminat.",
|
||||||
"user_id": "ID d'usuari",
|
"user_id": "ID d'usuari",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Otevřít vyhledávací filtry",
|
"open_the_search_filters": "Otevřít vyhledávací filtry",
|
||||||
"options": "Možnosti",
|
"options": "Možnosti",
|
||||||
"or": "nebo",
|
"or": "nebo",
|
||||||
|
"organize_into_albums": "Organizovat do alb",
|
||||||
|
"organize_into_albums_description": "Umístit existující fotky do alb s použitím aktuálního nastavení synchronizace",
|
||||||
"organize_your_library": "Uspořádejte si knihovnu",
|
"organize_your_library": "Uspořádejte si knihovnu",
|
||||||
"original": "originál",
|
"original": "originál",
|
||||||
"other": "Ostatní",
|
"other": "Ostatní",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Stav podporovatele",
|
"purchase_server_description_2": "Stav podporovatele",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Produktový klíč serveru spravuje správce",
|
"purchase_settings_server_activated": "Produktový klíč serveru spravuje správce",
|
||||||
|
"query_asset_id": "ID položky dotazu",
|
||||||
"queue_status": "Ve frontě {count}/{total}",
|
"queue_status": "Ve frontě {count}/{total}",
|
||||||
"rating": "Hodnocení hvězdičkami",
|
"rating": "Hodnocení hvězdičkami",
|
||||||
"rating_clear": "Vyčistit hodnocení",
|
"rating_clear": "Vyčistit hodnocení",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Nepodařilo se vytvořit album",
|
"select_user_for_sharing_page_err_album": "Nepodařilo se vytvořit album",
|
||||||
"selected": "Vybráno",
|
"selected": "Vybráno",
|
||||||
"selected_count": "{count, plural, one {# vybraný} few {# vybrané} other {# vybraných}}",
|
"selected_count": "{count, plural, one {# vybraný} few {# vybrané} other {# vybraných}}",
|
||||||
"selected_gps_coordinates": "vybrané GPS souřadnice",
|
"selected_gps_coordinates": "Vybrané GPS souřadnice",
|
||||||
"send_message": "Odeslat zprávu",
|
"send_message": "Odeslat zprávu",
|
||||||
"send_welcome_email": "Poslat uvítací e-mail",
|
"send_welcome_email": "Poslat uvítací e-mail",
|
||||||
"server_endpoint": "Koncový bod serveru",
|
"server_endpoint": "Koncový bod serveru",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Zobrazit další položku",
|
"view_next_asset": "Zobrazit další položku",
|
||||||
"view_previous_asset": "Zobrazit předchozí položku",
|
"view_previous_asset": "Zobrazit předchozí položku",
|
||||||
"view_qr_code": "Zobrazit QR kód",
|
"view_qr_code": "Zobrazit QR kód",
|
||||||
|
"view_similar_photos": "Zobrazit podobné fotky",
|
||||||
"view_stack": "Zobrazit seskupení",
|
"view_stack": "Zobrazit seskupení",
|
||||||
"view_user": "Zobrazit uživatele",
|
"view_user": "Zobrazit uživatele",
|
||||||
"viewer_remove_from_stack": "Odstranit ze zásobníku",
|
"viewer_remove_from_stack": "Odstranit ze zásobníku",
|
||||||
|
|||||||
143
i18n/da.json
143
i18n/da.json
@@ -126,13 +126,13 @@
|
|||||||
"machine_learning_clip_model": "CLIP-model",
|
"machine_learning_clip_model": "CLIP-model",
|
||||||
"machine_learning_clip_model_description": "Navnet på CLIP-modellen på listen <link>her</link>. Bemærk at du skal genkøre \"Smart Søgning\"-jobbet for alle billeder, hvis du skifter model.",
|
"machine_learning_clip_model_description": "Navnet på CLIP-modellen på listen <link>her</link>. Bemærk at du skal genkøre \"Smart Søgning\"-jobbet for alle billeder, hvis du skifter model.",
|
||||||
"machine_learning_duplicate_detection": "Dubletdetektion",
|
"machine_learning_duplicate_detection": "Dubletdetektion",
|
||||||
"machine_learning_duplicate_detection_enabled": "Aktiver duplikatdetektion",
|
"machine_learning_duplicate_detection_enabled": "Aktiver dubletdetektion",
|
||||||
"machine_learning_duplicate_detection_enabled_description": "Når slået fra, vil nøjagtigt identiske mediefiler blive de-duplikerede.",
|
"machine_learning_duplicate_detection_enabled_description": "Når slået fra, vil nøjagtigt identiske mediefiler stadig blive de-duplikerede.",
|
||||||
"machine_learning_duplicate_detection_setting_description": "Brug CLIP-indlejringer til at finde sandsynlige duplikater",
|
"machine_learning_duplicate_detection_setting_description": "Brug CLIP-indlejringer til at finde sandsynlige dubletter",
|
||||||
"machine_learning_enabled": "Aktivér maskinlæring",
|
"machine_learning_enabled": "Aktivér maskinlæring",
|
||||||
"machine_learning_enabled_description": "Hvis deaktiveret, vil alle ML-funktioner blive deaktiveret uanset nedenstående indstillinger.",
|
"machine_learning_enabled_description": "Hvis deaktiveret, vil alle ML-funktioner blive deaktiveret uanset nedenstående indstillinger.",
|
||||||
"machine_learning_facial_recognition": "Ansigtsgenkendelse",
|
"machine_learning_facial_recognition": "Ansigtsgenkendelse",
|
||||||
"machine_learning_facial_recognition_description": "Registrer, genkend og grupper ansigter i billeder",
|
"machine_learning_facial_recognition_description": "Opdag, genkend og gruppér ansigter i billeder",
|
||||||
"machine_learning_facial_recognition_model": "Ansigtsgenkendelsesmodel",
|
"machine_learning_facial_recognition_model": "Ansigtsgenkendelsesmodel",
|
||||||
"machine_learning_facial_recognition_model_description": "Modellerne er listet i faldende størrelsesorden. Større modeller er langsommere og bruger mere hukommelse, men giver bedre resultater. Bemærk, at du skal køre ansigtsopdagelsesopgaven igen for alle billeder, når du ændrer en model.",
|
"machine_learning_facial_recognition_model_description": "Modellerne er listet i faldende størrelsesorden. Større modeller er langsommere og bruger mere hukommelse, men giver bedre resultater. Bemærk, at du skal køre ansigtsopdagelsesopgaven igen for alle billeder, når du ændrer en model.",
|
||||||
"machine_learning_facial_recognition_setting": "Aktivér ansigtgenkendelse",
|
"machine_learning_facial_recognition_setting": "Aktivér ansigtgenkendelse",
|
||||||
@@ -221,6 +221,8 @@
|
|||||||
"oauth_mobile_redirect_uri": "Mobilomdiregerings-URL",
|
"oauth_mobile_redirect_uri": "Mobilomdiregerings-URL",
|
||||||
"oauth_mobile_redirect_uri_override": "Tilsidesættelse af mobil omdiregerings-URL",
|
"oauth_mobile_redirect_uri_override": "Tilsidesættelse af mobil omdiregerings-URL",
|
||||||
"oauth_mobile_redirect_uri_override_description": "Aktiver, når OAuth-udbyderen ikke tillader en mobil URI, som ''{callback}''",
|
"oauth_mobile_redirect_uri_override_description": "Aktiver, når OAuth-udbyderen ikke tillader en mobil URI, som ''{callback}''",
|
||||||
|
"oauth_role_claim": "Rolle attribut",
|
||||||
|
"oauth_role_claim_description": "Tildel automatisk admin adgang på basis af forekomst af denne påstand. Dén kan være enten 'user' eller 'admin'.",
|
||||||
"oauth_settings": "OAuth",
|
"oauth_settings": "OAuth",
|
||||||
"oauth_settings_description": "Administrer OAuth login-indstillinger",
|
"oauth_settings_description": "Administrer OAuth login-indstillinger",
|
||||||
"oauth_settings_more_details": "Læs flere detaljer om funktionen i <link>dokumentationen</link>.",
|
"oauth_settings_more_details": "Læs flere detaljer om funktionen i <link>dokumentationen</link>.",
|
||||||
@@ -269,6 +271,7 @@
|
|||||||
"storage_template_migration_info": "Lager-skabelonen vil konvertere alle filendelser til små bogstaver. Skabelonændringer vil kun gælde for nye mediefiler. For at anvende skabelonen retroaktivt på tidligere uploadede mediefiler skal du køre <link>{job}</link>.",
|
"storage_template_migration_info": "Lager-skabelonen vil konvertere alle filendelser til små bogstaver. Skabelonændringer vil kun gælde for nye mediefiler. For at anvende skabelonen retroaktivt på tidligere uploadede mediefiler skal du køre <link>{job}</link>.",
|
||||||
"storage_template_migration_job": "Lager Skabelon Migreringsjob",
|
"storage_template_migration_job": "Lager Skabelon Migreringsjob",
|
||||||
"storage_template_more_details": "For flere detaljer om denne funktion, referer til <template-link>Lager Skabelonen</template-link> og dens <implications-link>implikationer</implications-link>",
|
"storage_template_more_details": "For flere detaljer om denne funktion, referer til <template-link>Lager Skabelonen</template-link> og dens <implications-link>implikationer</implications-link>",
|
||||||
|
"storage_template_onboarding_description_v2": "Når aktiveret, så vil denne funktion auto-organisere filer på grundlag af en brugerdefineret skabelon. For nærmere, se <link>dokumentation</link>.",
|
||||||
"storage_template_path_length": "Anslået sti-længde begrænsning <b>{length, number}</b>/{limit, number}",
|
"storage_template_path_length": "Anslået sti-længde begrænsning <b>{length, number}</b>/{limit, number}",
|
||||||
"storage_template_settings": "Lagringsskabelon",
|
"storage_template_settings": "Lagringsskabelon",
|
||||||
"storage_template_settings_description": "Administrer mappestrukturen og filnavnet for den uploadede mediefil",
|
"storage_template_settings_description": "Administrer mappestrukturen og filnavnet for den uploadede mediefil",
|
||||||
@@ -355,7 +358,9 @@
|
|||||||
"trash_number_of_days_description": "Antal dage aktiver i skraldespanden skal beholdes inden de fjernes permanent",
|
"trash_number_of_days_description": "Antal dage aktiver i skraldespanden skal beholdes inden de fjernes permanent",
|
||||||
"trash_settings": "Skraldeindstillinger",
|
"trash_settings": "Skraldeindstillinger",
|
||||||
"trash_settings_description": "Administrér skraldeindstillinger",
|
"trash_settings_description": "Administrér skraldeindstillinger",
|
||||||
|
"unlink_all_oauth_accounts": "Ophæv link til alle OAuth konti",
|
||||||
"unlink_all_oauth_accounts_description": "Husk at fjerne linket til alle OAuth konti før du migrerer til en ny udbyder.",
|
"unlink_all_oauth_accounts_description": "Husk at fjerne linket til alle OAuth konti før du migrerer til en ny udbyder.",
|
||||||
|
"unlink_all_oauth_accounts_prompt": "Er du sikker på, at du vil ophæve link til alle OAuth konti? Dette vil nulstille OAuth ID for hver bruger og kan ikke fortrydes.",
|
||||||
"user_cleanup_job": "Bruger-oprydning",
|
"user_cleanup_job": "Bruger-oprydning",
|
||||||
"user_delete_delay": "<b>{user}</b>'s konto og mediefiler vil blive planlagt til permanent sletning om {delay, plural, one {# dag} other {# dage}}.",
|
"user_delete_delay": "<b>{user}</b>'s konto og mediefiler vil blive planlagt til permanent sletning om {delay, plural, one {# dag} other {# dage}}.",
|
||||||
"user_delete_delay_settings": "Slet forsinkelse",
|
"user_delete_delay_settings": "Slet forsinkelse",
|
||||||
@@ -390,7 +395,9 @@
|
|||||||
"advanced_settings_prefer_remote_subtitle": "Nogle enheder er meget lang tid om at indlæse miniaturebilleder af lokale elementer. Aktiver denne indstilling for at indlæse elementer fra serveren i stedet.",
|
"advanced_settings_prefer_remote_subtitle": "Nogle enheder er meget lang tid om at indlæse miniaturebilleder af lokale elementer. Aktiver denne indstilling for at indlæse elementer fra serveren i stedet.",
|
||||||
"advanced_settings_prefer_remote_title": "Foretræk elementer på serveren",
|
"advanced_settings_prefer_remote_title": "Foretræk elementer på serveren",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Definer proxy headers Immich skal sende med hver netværks forespørgsel",
|
"advanced_settings_proxy_headers_subtitle": "Definer proxy headers Immich skal sende med hver netværks forespørgsel",
|
||||||
"advanced_settings_proxy_headers_title": "Proxy Headers",
|
"advanced_settings_proxy_headers_title": "Proxy headere",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Aktiverer skrivebeskyttet tilstand, hvor billederne alene kan vises. Ting som at vælge flere billeder, dele, caste og slette er alle deaktiveret. Aktiver skrivebeskyttet tilstand via en bruger avatar fra hovedskærmen",
|
||||||
|
"advanced_settings_readonly_mode_title": "Skrivebeskyttet tilstand",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Spring verificering af SSL-certifikat over for serverens endelokation. Kræves for selvsignerede certifikater.",
|
"advanced_settings_self_signed_ssl_subtitle": "Spring verificering af SSL-certifikat over for serverens endelokation. Kræves for selvsignerede certifikater.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Tillad selvsignerede certifikater",
|
"advanced_settings_self_signed_ssl_title": "Tillad selvsignerede certifikater",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Slet eller gendan automatisk en mediefil på denne enhed, når denne handling foretages på Immich webinterface",
|
"advanced_settings_sync_remote_deletions_subtitle": "Slet eller gendan automatisk en mediefil på denne enhed, når denne handling foretages på Immich webinterface",
|
||||||
@@ -406,6 +413,7 @@
|
|||||||
"album_cover_updated": "Albumcover opdateret",
|
"album_cover_updated": "Albumcover opdateret",
|
||||||
"album_delete_confirmation": "Er du sikker på at du vil slette albummet {album}?",
|
"album_delete_confirmation": "Er du sikker på at du vil slette albummet {album}?",
|
||||||
"album_delete_confirmation_description": "Hvis dette album er delt, vil andre brugere ikke længere kunne få adgang til det.",
|
"album_delete_confirmation_description": "Hvis dette album er delt, vil andre brugere ikke længere kunne få adgang til det.",
|
||||||
|
"album_deleted": "Album slettet",
|
||||||
"album_info_card_backup_album_excluded": "EKSKLUDERET",
|
"album_info_card_backup_album_excluded": "EKSKLUDERET",
|
||||||
"album_info_card_backup_album_included": "INKLUDERET",
|
"album_info_card_backup_album_included": "INKLUDERET",
|
||||||
"album_info_updated": "Albuminfo opdateret",
|
"album_info_updated": "Albuminfo opdateret",
|
||||||
@@ -415,6 +423,7 @@
|
|||||||
"album_options": "Albumindstillinger",
|
"album_options": "Albumindstillinger",
|
||||||
"album_remove_user": "Fjern bruger?",
|
"album_remove_user": "Fjern bruger?",
|
||||||
"album_remove_user_confirmation": "Er du sikker på at du vil fjerne {user}?",
|
"album_remove_user_confirmation": "Er du sikker på at du vil fjerne {user}?",
|
||||||
|
"album_search_not_found": "Ingen album fundet som matcher din søgning",
|
||||||
"album_share_no_users": "Det ser ud til at du har delt denne album med alle brugere, eller du har ikke nogen brugere til at dele med.",
|
"album_share_no_users": "Det ser ud til at du har delt denne album med alle brugere, eller du har ikke nogen brugere til at dele med.",
|
||||||
"album_updated": "Album opdateret",
|
"album_updated": "Album opdateret",
|
||||||
"album_updated_setting_description": "Modtag en emailnotifikation når et delt album får nye mediefiler",
|
"album_updated_setting_description": "Modtag en emailnotifikation når et delt album får nye mediefiler",
|
||||||
@@ -434,6 +443,7 @@
|
|||||||
"albums_default_sort_order": "Standard album sortering",
|
"albums_default_sort_order": "Standard album sortering",
|
||||||
"albums_default_sort_order_description": "Grundlæggende sortering ved oprettelse af nyt album.",
|
"albums_default_sort_order_description": "Grundlæggende sortering ved oprettelse af nyt album.",
|
||||||
"albums_feature_description": "Samling af billeder der kan deles med andre brugere.",
|
"albums_feature_description": "Samling af billeder der kan deles med andre brugere.",
|
||||||
|
"albums_on_device_count": "Albummer på enheden ({count})",
|
||||||
"all": "Alt",
|
"all": "Alt",
|
||||||
"all_albums": "Alle albummer",
|
"all_albums": "Alle albummer",
|
||||||
"all_people": "Alle personer",
|
"all_people": "Alle personer",
|
||||||
@@ -453,7 +463,9 @@
|
|||||||
"app_bar_signout_dialog_title": "Log ud",
|
"app_bar_signout_dialog_title": "Log ud",
|
||||||
"app_settings": "Appindstillinger",
|
"app_settings": "Appindstillinger",
|
||||||
"appears_in": "Optræder i",
|
"appears_in": "Optræder i",
|
||||||
|
"apply_count": "Brug ({count, number})",
|
||||||
"archive": "Arkiv",
|
"archive": "Arkiv",
|
||||||
|
"archive_action_prompt": "{count} føjet til arkiv",
|
||||||
"archive_or_unarchive_photo": "Arkivér eller dearkivér billede",
|
"archive_or_unarchive_photo": "Arkivér eller dearkivér billede",
|
||||||
"archive_page_no_archived_assets": "Ingen arkiverede elementer blev fundet",
|
"archive_page_no_archived_assets": "Ingen arkiverede elementer blev fundet",
|
||||||
"archive_page_title": "Arkivér ({count})",
|
"archive_page_title": "Arkivér ({count})",
|
||||||
@@ -488,10 +500,12 @@
|
|||||||
"asset_uploading": "Uploader…",
|
"asset_uploading": "Uploader…",
|
||||||
"asset_viewer_settings_subtitle": "Administrer indstillinger for gallerifremviser",
|
"asset_viewer_settings_subtitle": "Administrer indstillinger for gallerifremviser",
|
||||||
"asset_viewer_settings_title": "Billedviser",
|
"asset_viewer_settings_title": "Billedviser",
|
||||||
"assets": "elementer",
|
"assets": "Objekter",
|
||||||
"assets_added_count": "Tilføjet {count, plural, one {# mediefil} other {# mediefiler}}",
|
"assets_added_count": "Tilføjet {count, plural, one {# mediefil} other {# mediefiler}}",
|
||||||
"assets_added_to_album_count": "{count, plural, one {# mediefil} other {# mediefiler}} tilføjet til albummet",
|
"assets_added_to_album_count": "{count, plural, one {# mediefil} other {# mediefiler}} tilføjet til albummet",
|
||||||
|
"assets_added_to_albums_count": "Tilføjet {assetTotal, plural, one {# asset} other {# assets}} til {albumTotal, plural, one {# album} other {# albums}}",
|
||||||
"assets_cannot_be_added_to_album_count": "{count, plural, one {Billed} other {Billeder}} kan ikke blive tilføjet til album",
|
"assets_cannot_be_added_to_album_count": "{count, plural, one {Billed} other {Billeder}} kan ikke blive tilføjet til album",
|
||||||
|
"assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} kan ikke føjes til i nogen af albummerne",
|
||||||
"assets_count": "{count, plural, one {# mediefil} other {# mediefiler}}",
|
"assets_count": "{count, plural, one {# mediefil} other {# mediefiler}}",
|
||||||
"assets_deleted_permanently": "{count} element(er) blev fjernet permanent",
|
"assets_deleted_permanently": "{count} element(er) blev fjernet permanent",
|
||||||
"assets_deleted_permanently_from_server": "{count} element(er) blev fjernet permanent fra Immich serveren",
|
"assets_deleted_permanently_from_server": "{count} element(er) blev fjernet permanent fra Immich serveren",
|
||||||
@@ -508,6 +522,7 @@
|
|||||||
"assets_trashed_count": "{count, plural, one {# mediefil} other {# mediefiler}} smidt i papirkurven",
|
"assets_trashed_count": "{count, plural, one {# mediefil} other {# mediefiler}} smidt i papirkurven",
|
||||||
"assets_trashed_from_server": "{count} element(er) blev smidt i Immich serverens papirkurv",
|
"assets_trashed_from_server": "{count} element(er) blev smidt i Immich serverens papirkurv",
|
||||||
"assets_were_part_of_album_count": "mediefil{count, plural, one {mediefil} other {mediefiler}} er allerede en del af albummet",
|
"assets_were_part_of_album_count": "mediefil{count, plural, one {mediefil} other {mediefiler}} er allerede en del af albummet",
|
||||||
|
"assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} er allerede en del af albummerne",
|
||||||
"authorized_devices": "Tilladte enheder",
|
"authorized_devices": "Tilladte enheder",
|
||||||
"automatic_endpoint_switching_subtitle": "Forbind lokalt over det anviste WiFi, når det er tilgængeligt og brug alternative forbindelser andre stæder",
|
"automatic_endpoint_switching_subtitle": "Forbind lokalt over det anviste WiFi, når det er tilgængeligt og brug alternative forbindelser andre stæder",
|
||||||
"automatic_endpoint_switching_title": "Automatisk skift af URL",
|
"automatic_endpoint_switching_title": "Automatisk skift af URL",
|
||||||
@@ -572,14 +587,18 @@
|
|||||||
"backup_controller_page_turn_on": "Slå sikkerhedskopiering til",
|
"backup_controller_page_turn_on": "Slå sikkerhedskopiering til",
|
||||||
"backup_controller_page_uploading_file_info": "Uploader filinformation",
|
"backup_controller_page_uploading_file_info": "Uploader filinformation",
|
||||||
"backup_err_only_album": "Kan ikke slette det eneste album",
|
"backup_err_only_album": "Kan ikke slette det eneste album",
|
||||||
"backup_info_card_assets": "elementer",
|
"backup_info_card_assets": "objekter",
|
||||||
"backup_manual_cancelled": "Annulleret",
|
"backup_manual_cancelled": "Annulleret",
|
||||||
"backup_manual_in_progress": "Upload er allerede undervejs. Prøv igen efter noget tid",
|
"backup_manual_in_progress": "Upload er allerede undervejs. Prøv igen efter noget tid",
|
||||||
"backup_manual_success": "Succes",
|
"backup_manual_success": "Succes",
|
||||||
"backup_manual_title": "Uploadstatus",
|
"backup_manual_title": "Uploadstatus",
|
||||||
|
"backup_options": "Backup indstillinger",
|
||||||
"backup_options_page_title": "Backupindstillinger",
|
"backup_options_page_title": "Backupindstillinger",
|
||||||
"backup_setting_subtitle": "Administrer indstillnger for upload i forgrund og baggrund",
|
"backup_setting_subtitle": "Administrer indstillnger for upload i forgrund og baggrund",
|
||||||
|
"backup_settings_subtitle": "Håndtere upload indstillinger",
|
||||||
"backward": "Baglæns",
|
"backward": "Baglæns",
|
||||||
|
"beta_sync": "Beta synkroniseringsstatus",
|
||||||
|
"beta_sync_subtitle": "Håndter det nye synkroniseringssystem",
|
||||||
"biometric_auth_enabled": "Biometrisk adgangskontrol slået til",
|
"biometric_auth_enabled": "Biometrisk adgangskontrol slået til",
|
||||||
"biometric_locked_out": "Du er låst ude af biometrisk adgangskontrol",
|
"biometric_locked_out": "Du er låst ude af biometrisk adgangskontrol",
|
||||||
"biometric_no_options": "Ingen biometrisk adgangskontrol tilgængelig",
|
"biometric_no_options": "Ingen biometrisk adgangskontrol tilgængelig",
|
||||||
@@ -614,6 +633,7 @@
|
|||||||
"cancel": "Annullér",
|
"cancel": "Annullér",
|
||||||
"cancel_search": "Annullér søgning",
|
"cancel_search": "Annullér søgning",
|
||||||
"canceled": "Annulleret",
|
"canceled": "Annulleret",
|
||||||
|
"canceling": "Annullerer",
|
||||||
"cannot_merge_people": "Kan ikke sammenflette personer",
|
"cannot_merge_people": "Kan ikke sammenflette personer",
|
||||||
"cannot_undo_this_action": "Du kan ikke fortryde denne handling!",
|
"cannot_undo_this_action": "Du kan ikke fortryde denne handling!",
|
||||||
"cannot_update_the_description": "Kan ikke opdatere beskrivelsen",
|
"cannot_update_the_description": "Kan ikke opdatere beskrivelsen",
|
||||||
@@ -645,6 +665,7 @@
|
|||||||
"clear": "Ryd",
|
"clear": "Ryd",
|
||||||
"clear_all": "Ryd alle",
|
"clear_all": "Ryd alle",
|
||||||
"clear_all_recent_searches": "Ryd alle seneste søgninger",
|
"clear_all_recent_searches": "Ryd alle seneste søgninger",
|
||||||
|
"clear_file_cache": "Ryd filcache",
|
||||||
"clear_message": "Ryd bedsked",
|
"clear_message": "Ryd bedsked",
|
||||||
"clear_value": "Ryd værdi",
|
"clear_value": "Ryd værdi",
|
||||||
"client_cert_dialog_msg_confirm": "OK",
|
"client_cert_dialog_msg_confirm": "OK",
|
||||||
@@ -715,6 +736,7 @@
|
|||||||
"create_new_user": "Opret ny bruger",
|
"create_new_user": "Opret ny bruger",
|
||||||
"create_shared_album_page_share_add_assets": "TILFØJ ELEMENT",
|
"create_shared_album_page_share_add_assets": "TILFØJ ELEMENT",
|
||||||
"create_shared_album_page_share_select_photos": "Vælg Billeder",
|
"create_shared_album_page_share_select_photos": "Vælg Billeder",
|
||||||
|
"create_shared_link": "Opret delt link",
|
||||||
"create_tag": "Opret tag",
|
"create_tag": "Opret tag",
|
||||||
"create_tag_description": "Opret et nyt tag. For indlejrede tags skal du indtaste den fulde sti til tagget inklusive skråstreger.",
|
"create_tag_description": "Opret et nyt tag. For indlejrede tags skal du indtaste den fulde sti til tagget inklusive skråstreger.",
|
||||||
"create_user": "Opret bruger",
|
"create_user": "Opret bruger",
|
||||||
@@ -727,9 +749,11 @@
|
|||||||
"current_server_address": "Nuværende serveraddresse",
|
"current_server_address": "Nuværende serveraddresse",
|
||||||
"custom_locale": "Brugerdefineret lokale",
|
"custom_locale": "Brugerdefineret lokale",
|
||||||
"custom_locale_description": "Formatér datoer og tal baseret på sproget og regionen",
|
"custom_locale_description": "Formatér datoer og tal baseret på sproget og regionen",
|
||||||
|
"custom_url": "Tilpasset URL",
|
||||||
"daily_title_text_date": "E, dd MMM",
|
"daily_title_text_date": "E, dd MMM",
|
||||||
"daily_title_text_date_year": "E, dd MMM, yyyy",
|
"daily_title_text_date_year": "E, dd MMM, yyyy",
|
||||||
"dark": "Mørk",
|
"dark": "Mørk",
|
||||||
|
"dark_theme": "Skift til mørkt tema",
|
||||||
"date_after": "Dato efter",
|
"date_after": "Dato efter",
|
||||||
"date_and_time": "Dato og klokkeslæt",
|
"date_and_time": "Dato og klokkeslæt",
|
||||||
"date_before": "Dato før",
|
"date_before": "Dato før",
|
||||||
@@ -737,6 +761,7 @@
|
|||||||
"date_of_birth_saved": "Fødselsdatoen blev gemt korrekt",
|
"date_of_birth_saved": "Fødselsdatoen blev gemt korrekt",
|
||||||
"date_range": "Datointerval",
|
"date_range": "Datointerval",
|
||||||
"day": "Dag",
|
"day": "Dag",
|
||||||
|
"days": "Dage",
|
||||||
"deduplicate_all": "Kopier alle",
|
"deduplicate_all": "Kopier alle",
|
||||||
"deduplication_criteria_1": "Billedstørrelse i bytes",
|
"deduplication_criteria_1": "Billedstørrelse i bytes",
|
||||||
"deduplication_criteria_2": "Antal EXIF-data",
|
"deduplication_criteria_2": "Antal EXIF-data",
|
||||||
@@ -745,6 +770,8 @@
|
|||||||
"default_locale": "Standardlokalitet",
|
"default_locale": "Standardlokalitet",
|
||||||
"default_locale_description": "Formatér datoer og tal baseret på din browsers regions indstillinger",
|
"default_locale_description": "Formatér datoer og tal baseret på din browsers regions indstillinger",
|
||||||
"delete": "Slet",
|
"delete": "Slet",
|
||||||
|
"delete_action_confirmation_message": "Er du sikker på, at du vil slette dette objekt? Denne handling vil flytte objektet til serverens papirkurv, og vil spørge dig, om du vil slette den lokalt",
|
||||||
|
"delete_action_prompt": "{count} slettet",
|
||||||
"delete_album": "Slet album",
|
"delete_album": "Slet album",
|
||||||
"delete_api_key_prompt": "Er du sikker på, at du vil slette denne API-nøgle?",
|
"delete_api_key_prompt": "Er du sikker på, at du vil slette denne API-nøgle?",
|
||||||
"delete_dialog_alert": "Disse elementer vil blive slettet permanent fra Immich og din enhed",
|
"delete_dialog_alert": "Disse elementer vil blive slettet permanent fra Immich og din enhed",
|
||||||
@@ -758,9 +785,12 @@
|
|||||||
"delete_key": "Slet nøgle",
|
"delete_key": "Slet nøgle",
|
||||||
"delete_library": "Slet bibliotek",
|
"delete_library": "Slet bibliotek",
|
||||||
"delete_link": "Slet link",
|
"delete_link": "Slet link",
|
||||||
|
"delete_local_action_prompt": "{count} slettet lokalt",
|
||||||
"delete_local_dialog_ok_backed_up_only": "Slet kun backup",
|
"delete_local_dialog_ok_backed_up_only": "Slet kun backup",
|
||||||
"delete_local_dialog_ok_force": "Slet alligevel",
|
"delete_local_dialog_ok_force": "Slet alligevel",
|
||||||
"delete_others": "Slet andre",
|
"delete_others": "Slet andre",
|
||||||
|
"delete_permanently": "Slet permanent",
|
||||||
|
"delete_permanently_action_prompt": "{count} slettet permanent",
|
||||||
"delete_shared_link": "Slet delt link",
|
"delete_shared_link": "Slet delt link",
|
||||||
"delete_shared_link_dialog_title": "Slet delt link",
|
"delete_shared_link_dialog_title": "Slet delt link",
|
||||||
"delete_tag": "Slet tag",
|
"delete_tag": "Slet tag",
|
||||||
@@ -771,6 +801,7 @@
|
|||||||
"description": "Beskrivelse",
|
"description": "Beskrivelse",
|
||||||
"description_input_hint_text": "Tilføj en beskrivelse...",
|
"description_input_hint_text": "Tilføj en beskrivelse...",
|
||||||
"description_input_submit_error": "Fejl med at opdatere beskrivelsen. Tjek loggen for flere detaljer",
|
"description_input_submit_error": "Fejl med at opdatere beskrivelsen. Tjek loggen for flere detaljer",
|
||||||
|
"deselect_all": "Afmarkér alt",
|
||||||
"details": "DETALJER",
|
"details": "DETALJER",
|
||||||
"direction": "Retning",
|
"direction": "Retning",
|
||||||
"disabled": "Deaktiveret",
|
"disabled": "Deaktiveret",
|
||||||
@@ -788,6 +819,7 @@
|
|||||||
"documentation": "Dokumentation",
|
"documentation": "Dokumentation",
|
||||||
"done": "Færdig",
|
"done": "Færdig",
|
||||||
"download": "Hent",
|
"download": "Hent",
|
||||||
|
"download_action_prompt": "Downloader {count} objekter",
|
||||||
"download_canceled": "Download annulleret",
|
"download_canceled": "Download annulleret",
|
||||||
"download_complete": "Download fuldført",
|
"download_complete": "Download fuldført",
|
||||||
"download_enqueue": "Donload sat i kø",
|
"download_enqueue": "Donload sat i kø",
|
||||||
@@ -814,8 +846,12 @@
|
|||||||
"edit": "Rediger",
|
"edit": "Rediger",
|
||||||
"edit_album": "Redigér album",
|
"edit_album": "Redigér album",
|
||||||
"edit_avatar": "Redigér avatar",
|
"edit_avatar": "Redigér avatar",
|
||||||
|
"edit_birthday": "Rediger fødselsdag",
|
||||||
"edit_date": "Redigér dato",
|
"edit_date": "Redigér dato",
|
||||||
"edit_date_and_time": "Redigér dato og tid",
|
"edit_date_and_time": "Redigér dato og tid",
|
||||||
|
"edit_date_and_time_action_prompt": "{count} dato og tid redigeret",
|
||||||
|
"edit_date_and_time_by_offset": "Forskyde dato med offset",
|
||||||
|
"edit_date_and_time_by_offset_interval": "Nyt datointerval: {from} - {to}",
|
||||||
"edit_description": "Rediger beskrivelse",
|
"edit_description": "Rediger beskrivelse",
|
||||||
"edit_description_prompt": "Vælg venligst en ny beskrivelse:",
|
"edit_description_prompt": "Vælg venligst en ny beskrivelse:",
|
||||||
"edit_exclusion_pattern": "Redigér udelukkelsesmønster",
|
"edit_exclusion_pattern": "Redigér udelukkelsesmønster",
|
||||||
@@ -825,6 +861,7 @@
|
|||||||
"edit_key": "Redigér nøgle",
|
"edit_key": "Redigér nøgle",
|
||||||
"edit_link": "Rediger link",
|
"edit_link": "Rediger link",
|
||||||
"edit_location": "Rediger placering",
|
"edit_location": "Rediger placering",
|
||||||
|
"edit_location_action_prompt": "{count} geolokation redigeret",
|
||||||
"edit_location_dialog_title": "Placering",
|
"edit_location_dialog_title": "Placering",
|
||||||
"edit_name": "Rediger navn",
|
"edit_name": "Rediger navn",
|
||||||
"edit_people": "Redigér personer",
|
"edit_people": "Redigér personer",
|
||||||
@@ -843,6 +880,7 @@
|
|||||||
"empty_trash": "Tøm papirkurv",
|
"empty_trash": "Tøm papirkurv",
|
||||||
"empty_trash_confirmation": "Er du sikker på, at du vil tømme papirkurven? Dette vil fjerne alle objekter i papirkurven permanent fra Immich.\nDu kan ikke fortryde denne handling!",
|
"empty_trash_confirmation": "Er du sikker på, at du vil tømme papirkurven? Dette vil fjerne alle objekter i papirkurven permanent fra Immich.\nDu kan ikke fortryde denne handling!",
|
||||||
"enable": "Aktivér",
|
"enable": "Aktivér",
|
||||||
|
"enable_backup": "Aktiver backup",
|
||||||
"enable_biometric_auth_description": "Indtast din PIN kode for at slå biometrisk adgangskontrol til",
|
"enable_biometric_auth_description": "Indtast din PIN kode for at slå biometrisk adgangskontrol til",
|
||||||
"enabled": "Aktiveret",
|
"enabled": "Aktiveret",
|
||||||
"end_date": "Slutdato",
|
"end_date": "Slutdato",
|
||||||
@@ -886,6 +924,7 @@
|
|||||||
"failed_to_load_notifications": "Kunne ikke indlæse notifikationer",
|
"failed_to_load_notifications": "Kunne ikke indlæse notifikationer",
|
||||||
"failed_to_load_people": "Indlæsning af personer mislykkedes",
|
"failed_to_load_people": "Indlæsning af personer mislykkedes",
|
||||||
"failed_to_remove_product_key": "Fjernelse af produktnøgle mislykkedes",
|
"failed_to_remove_product_key": "Fjernelse af produktnøgle mislykkedes",
|
||||||
|
"failed_to_reset_pin_code": "Kunne ikke resette PIN-koden",
|
||||||
"failed_to_stack_assets": "Det lykkedes ikke at stable mediefiler",
|
"failed_to_stack_assets": "Det lykkedes ikke at stable mediefiler",
|
||||||
"failed_to_unstack_assets": "Det lykkedes ikke at fjerne gruperingen af mediefiler",
|
"failed_to_unstack_assets": "Det lykkedes ikke at fjerne gruperingen af mediefiler",
|
||||||
"failed_to_update_notification_status": "Kunne ikke uploade notifikations status",
|
"failed_to_update_notification_status": "Kunne ikke uploade notifikations status",
|
||||||
@@ -894,6 +933,7 @@
|
|||||||
"paths_validation_failed": "{paths, plural, one {# sti} other {# stier}} slog fejl ved validering",
|
"paths_validation_failed": "{paths, plural, one {# sti} other {# stier}} slog fejl ved validering",
|
||||||
"profile_picture_transparent_pixels": "Profilbilleder kan ikke have gennemsigtige pixels. Zoom venligst ind og/eller flyt billedet.",
|
"profile_picture_transparent_pixels": "Profilbilleder kan ikke have gennemsigtige pixels. Zoom venligst ind og/eller flyt billedet.",
|
||||||
"quota_higher_than_disk_size": "Du har sat en kvote der er større end disken",
|
"quota_higher_than_disk_size": "Du har sat en kvote der er større end disken",
|
||||||
|
"something_went_wrong": "Noget gik galt",
|
||||||
"unable_to_add_album_users": "Ikke i stand til at tilføje brugere til album",
|
"unable_to_add_album_users": "Ikke i stand til at tilføje brugere til album",
|
||||||
"unable_to_add_assets_to_shared_link": "Kan ikke tilføje mediefiler til det delte link",
|
"unable_to_add_assets_to_shared_link": "Kan ikke tilføje mediefiler til det delte link",
|
||||||
"unable_to_add_comment": "Ikke i stand til at tilføje kommentar",
|
"unable_to_add_comment": "Ikke i stand til at tilføje kommentar",
|
||||||
@@ -979,6 +1019,7 @@
|
|||||||
},
|
},
|
||||||
"exif": "Exif",
|
"exif": "Exif",
|
||||||
"exif_bottom_sheet_description": "Tilføj beskrivelse...",
|
"exif_bottom_sheet_description": "Tilføj beskrivelse...",
|
||||||
|
"exif_bottom_sheet_description_error": "Fejl ved opdatering af beskrivelsen",
|
||||||
"exif_bottom_sheet_details": "DETALJER",
|
"exif_bottom_sheet_details": "DETALJER",
|
||||||
"exif_bottom_sheet_location": "LOKATION",
|
"exif_bottom_sheet_location": "LOKATION",
|
||||||
"exif_bottom_sheet_people": "PERSONER",
|
"exif_bottom_sheet_people": "PERSONER",
|
||||||
@@ -996,6 +1037,8 @@
|
|||||||
"explorer": "Udforske",
|
"explorer": "Udforske",
|
||||||
"export": "Eksportér",
|
"export": "Eksportér",
|
||||||
"export_as_json": "Eksportér som JSON",
|
"export_as_json": "Eksportér som JSON",
|
||||||
|
"export_database": "Eksporter database",
|
||||||
|
"export_database_description": "Eksporter SQLite databasen",
|
||||||
"extension": "Udvidelse",
|
"extension": "Udvidelse",
|
||||||
"external": "Ekstern",
|
"external": "Ekstern",
|
||||||
"external_libraries": "Eksterne biblioteker",
|
"external_libraries": "Eksterne biblioteker",
|
||||||
@@ -1007,6 +1050,7 @@
|
|||||||
"failed_to_load_assets": "Kunne ikke indlæse mediefiler",
|
"failed_to_load_assets": "Kunne ikke indlæse mediefiler",
|
||||||
"failed_to_load_folder": "Kunne ikke indlæse mappe",
|
"failed_to_load_folder": "Kunne ikke indlæse mappe",
|
||||||
"favorite": "Favorit",
|
"favorite": "Favorit",
|
||||||
|
"favorite_action_prompt": "{count} føjet til favoritter",
|
||||||
"favorite_or_unfavorite_photo": "Tilføj eller fjern fra yndlingsbilleder",
|
"favorite_or_unfavorite_photo": "Tilføj eller fjern fra yndlingsbilleder",
|
||||||
"favorites": "Favoritter",
|
"favorites": "Favoritter",
|
||||||
"favorites_page_no_favorites": "Ingen favoritter blev fundet",
|
"favorites_page_no_favorites": "Ingen favoritter blev fundet",
|
||||||
@@ -1021,21 +1065,29 @@
|
|||||||
"filter_people": "Filtrér personer",
|
"filter_people": "Filtrér personer",
|
||||||
"filter_places": "Filtrer steder",
|
"filter_places": "Filtrer steder",
|
||||||
"find_them_fast": "Find dem hurtigt med søgning via navn",
|
"find_them_fast": "Find dem hurtigt med søgning via navn",
|
||||||
|
"first": "Første",
|
||||||
"fix_incorrect_match": "Fix forkert match",
|
"fix_incorrect_match": "Fix forkert match",
|
||||||
"folder": "Mappe",
|
"folder": "Mappe",
|
||||||
"folder_not_found": "Mappe ikke fundet",
|
"folder_not_found": "Mappe ikke fundet",
|
||||||
"folders": "Mapper",
|
"folders": "Mapper",
|
||||||
"folders_feature_description": "Gennemse mappevisningen efter fotos og videoer på filsystemet",
|
"folders_feature_description": "Gennemse mappevisningen efter fotos og videoer på filsystemet",
|
||||||
|
"forgot_pin_code_question": "Har du glemt PIN-koden?",
|
||||||
"forward": "Fremad",
|
"forward": "Fremad",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Denne funktion indlæser eksterne ressourcer fra Google for at virke.",
|
"gcast_enabled_description": "Denne funktion indlæser eksterne ressourcer fra Google for at virke.",
|
||||||
"general": "Generel",
|
"general": "Generel",
|
||||||
|
"geolocation_instruction_all_have_location": "Alle objekter for denne dato har allerede lokations-data. Prøv at vise alle objekter eller vælg en anden dato",
|
||||||
|
"geolocation_instruction_location": "Klik på et objekt med GPS-koordinater for at bruge dettes position, eller vælg position direkte på kortet",
|
||||||
|
"geolocation_instruction_no_date": "Vælg en dato, for at administrere lokationsdata på billeder og videoer fra den dag",
|
||||||
|
"geolocation_instruction_no_photos": "Ingen fotos eller videoer fundet for den dato. Vælg en anden dato for at vise dem",
|
||||||
"get_help": "Få hjælp",
|
"get_help": "Få hjælp",
|
||||||
"get_wifiname_error": "Kunne ikke hente Wi-Fi-navn. Sørg for, at du har givet de nødvendige tilladelser og er forbundet til et Wi-Fi-netværk",
|
"get_wifiname_error": "Kunne ikke hente Wi-Fi-navn. Sørg for, at du har givet de nødvendige tilladelser og er forbundet til et Wi-Fi-netværk",
|
||||||
"getting_started": "Kom godt i gang",
|
"getting_started": "Kom godt i gang",
|
||||||
"go_back": "Gå tilbage",
|
"go_back": "Gå tilbage",
|
||||||
"go_to_folder": "Gå til mappe",
|
"go_to_folder": "Gå til mappe",
|
||||||
"go_to_search": "Gå til søgning",
|
"go_to_search": "Gå til søgning",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "Ingen GPS",
|
||||||
"grant_permission": "Giv tilladelse",
|
"grant_permission": "Giv tilladelse",
|
||||||
"group_albums_by": "Gruppér albummer efter...",
|
"group_albums_by": "Gruppér albummer efter...",
|
||||||
"group_country": "Gruppér efter land",
|
"group_country": "Gruppér efter land",
|
||||||
@@ -1046,6 +1098,9 @@
|
|||||||
"haptic_feedback_switch": "Slå haptisk feedback til",
|
"haptic_feedback_switch": "Slå haptisk feedback til",
|
||||||
"haptic_feedback_title": "Haptisk feedback",
|
"haptic_feedback_title": "Haptisk feedback",
|
||||||
"has_quota": "Har kvote",
|
"has_quota": "Har kvote",
|
||||||
|
"hash_asset": "Hash objekter",
|
||||||
|
"hashed_assets": "Hashede objekter",
|
||||||
|
"hashing": "Hasher",
|
||||||
"header_settings_add_header_tip": "Tilføj Header",
|
"header_settings_add_header_tip": "Tilføj Header",
|
||||||
"header_settings_field_validator_msg": "Værdi kan ikke være tom",
|
"header_settings_field_validator_msg": "Værdi kan ikke være tom",
|
||||||
"header_settings_header_name_input": "Header navn",
|
"header_settings_header_name_input": "Header navn",
|
||||||
@@ -1077,7 +1132,9 @@
|
|||||||
"home_page_upload_err_limit": "Det er kun muligt at lave sikkerhedskopi af 30 elementer ad gangen. Springer over",
|
"home_page_upload_err_limit": "Det er kun muligt at lave sikkerhedskopi af 30 elementer ad gangen. Springer over",
|
||||||
"host": "Host",
|
"host": "Host",
|
||||||
"hour": "Time",
|
"hour": "Time",
|
||||||
|
"hours": "Timer",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
"idle": "Inaktiv",
|
||||||
"ignore_icloud_photos": "Ignorer iCloud-billeder",
|
"ignore_icloud_photos": "Ignorer iCloud-billeder",
|
||||||
"ignore_icloud_photos_description": "Billeder der er gemt på iCloud vil ikke blive uploadet til Immich-serveren",
|
"ignore_icloud_photos_description": "Billeder der er gemt på iCloud vil ikke blive uploadet til Immich-serveren",
|
||||||
"image": "Billede",
|
"image": "Billede",
|
||||||
@@ -1135,10 +1192,13 @@
|
|||||||
"language_no_results_title": "Ingen sprog fundet",
|
"language_no_results_title": "Ingen sprog fundet",
|
||||||
"language_search_hint": "Vælg sprog...",
|
"language_search_hint": "Vælg sprog...",
|
||||||
"language_setting_description": "Vælg dit foretrukne sprog",
|
"language_setting_description": "Vælg dit foretrukne sprog",
|
||||||
|
"large_files": "Store filer",
|
||||||
|
"last": "Sidste",
|
||||||
"last_seen": "Sidst set",
|
"last_seen": "Sidst set",
|
||||||
"latest_version": "Seneste version",
|
"latest_version": "Seneste version",
|
||||||
"latitude": "Breddegrad",
|
"latitude": "Breddegrad",
|
||||||
"leave": "Forlad",
|
"leave": "Forlad",
|
||||||
|
"leave_album": "Forlad album",
|
||||||
"lens_model": "Objektivmodel",
|
"lens_model": "Objektivmodel",
|
||||||
"let_others_respond": "Lad andre svare",
|
"let_others_respond": "Lad andre svare",
|
||||||
"level": "Niveau",
|
"level": "Niveau",
|
||||||
@@ -1150,7 +1210,9 @@
|
|||||||
"library_page_sort_created": "Senest oprettet",
|
"library_page_sort_created": "Senest oprettet",
|
||||||
"library_page_sort_last_modified": "Sidst redigeret",
|
"library_page_sort_last_modified": "Sidst redigeret",
|
||||||
"library_page_sort_title": "Albumtitel",
|
"library_page_sort_title": "Albumtitel",
|
||||||
|
"licenses": "Licenser",
|
||||||
"light": "Lys",
|
"light": "Lys",
|
||||||
|
"like": "Synes om",
|
||||||
"like_deleted": "Ligesom slettet",
|
"like_deleted": "Ligesom slettet",
|
||||||
"link_motion_video": "Link bevægelsesvideo",
|
"link_motion_video": "Link bevægelsesvideo",
|
||||||
"link_to_oauth": "Link til OAuth",
|
"link_to_oauth": "Link til OAuth",
|
||||||
@@ -1158,7 +1220,9 @@
|
|||||||
"list": "Liste",
|
"list": "Liste",
|
||||||
"loading": "Indlæser",
|
"loading": "Indlæser",
|
||||||
"loading_search_results_failed": "Indlæsning af søgeresultater fejlede",
|
"loading_search_results_failed": "Indlæsning af søgeresultater fejlede",
|
||||||
|
"local": "Lokal",
|
||||||
"local_asset_cast_failed": "Kan ikke caste et aktiv, der ikke er uploadet til serveren",
|
"local_asset_cast_failed": "Kan ikke caste et aktiv, der ikke er uploadet til serveren",
|
||||||
|
"local_assets": "Lokale objekter",
|
||||||
"local_network": "Lokalt netværk",
|
"local_network": "Lokalt netværk",
|
||||||
"local_network_sheet_info": "Appen vil oprette forbindelse til serveren via denne URL, når du bruger det angivne WiFi-netværk",
|
"local_network_sheet_info": "Appen vil oprette forbindelse til serveren via denne URL, når du bruger det angivne WiFi-netværk",
|
||||||
"location_permission": "Tilladelse til placering",
|
"location_permission": "Tilladelse til placering",
|
||||||
@@ -1172,6 +1236,7 @@
|
|||||||
"locked_folder": "Låst mappe",
|
"locked_folder": "Låst mappe",
|
||||||
"log_out": "Log ud",
|
"log_out": "Log ud",
|
||||||
"log_out_all_devices": "Log ud af alle enheder",
|
"log_out_all_devices": "Log ud af alle enheder",
|
||||||
|
"logged_in_as": "Logget ind som {user}",
|
||||||
"logged_out_all_devices": "Logget ud af alle enheder",
|
"logged_out_all_devices": "Logget ud af alle enheder",
|
||||||
"logged_out_device": "Logget ud af enhed",
|
"logged_out_device": "Logget ud af enhed",
|
||||||
"login": "Log ind",
|
"login": "Log ind",
|
||||||
@@ -1180,7 +1245,7 @@
|
|||||||
"login_form_back_button_text": "Tilbage",
|
"login_form_back_button_text": "Tilbage",
|
||||||
"login_form_email_hint": "din-e-mail@e-mail.com",
|
"login_form_email_hint": "din-e-mail@e-mail.com",
|
||||||
"login_form_endpoint_hint": "http://din-server-ip:port",
|
"login_form_endpoint_hint": "http://din-server-ip:port",
|
||||||
"login_form_endpoint_url": "Server Endpoint URL",
|
"login_form_endpoint_url": "Server endepunkt URL",
|
||||||
"login_form_err_http": "Angiv venligst http:// eller https://",
|
"login_form_err_http": "Angiv venligst http:// eller https://",
|
||||||
"login_form_err_invalid_email": "Ugyldig e-mail",
|
"login_form_err_invalid_email": "Ugyldig e-mail",
|
||||||
"login_form_err_invalid_url": "Ugyldig webadresse",
|
"login_form_err_invalid_url": "Ugyldig webadresse",
|
||||||
@@ -1206,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Du bruger en udviklingsversion; vi anbefaler kraftigt at bruge en udgivelsesversion!",
|
"main_branch_warning": "Du bruger en udviklingsversion; vi anbefaler kraftigt at bruge en udgivelsesversion!",
|
||||||
"main_menu": "Hovedmenu",
|
"main_menu": "Hovedmenu",
|
||||||
"make": "Producent",
|
"make": "Producent",
|
||||||
|
"manage_geolocation": "Administrer placering",
|
||||||
"manage_shared_links": "Håndter delte links",
|
"manage_shared_links": "Håndter delte links",
|
||||||
"manage_sharing_with_partners": "Administrér deling med partnere",
|
"manage_sharing_with_partners": "Administrér deling med partnere",
|
||||||
"manage_the_app_settings": "Administrer appindstillinger",
|
"manage_the_app_settings": "Administrer appindstillinger",
|
||||||
@@ -1258,6 +1324,7 @@
|
|||||||
"merged_people_count": "{count, plural, one {# person} other {# personer}} lagt sammen",
|
"merged_people_count": "{count, plural, one {# person} other {# personer}} lagt sammen",
|
||||||
"minimize": "Minimér",
|
"minimize": "Minimér",
|
||||||
"minute": "Minut",
|
"minute": "Minut",
|
||||||
|
"minutes": "Minutter",
|
||||||
"missing": "Mangler",
|
"missing": "Mangler",
|
||||||
"model": "Model",
|
"model": "Model",
|
||||||
"month": "Måned",
|
"month": "Måned",
|
||||||
@@ -1265,6 +1332,7 @@
|
|||||||
"more": "Mere",
|
"more": "Mere",
|
||||||
"move": "Flyt",
|
"move": "Flyt",
|
||||||
"move_off_locked_folder": "Flyt ud af låst mappe",
|
"move_off_locked_folder": "Flyt ud af låst mappe",
|
||||||
|
"move_to_lock_folder_action_prompt": "{count} føjet til i den låste mappe",
|
||||||
"move_to_locked_folder": "Flyt til låst mappe",
|
"move_to_locked_folder": "Flyt til låst mappe",
|
||||||
"move_to_locked_folder_confirmation": "Disse billeder og videoer vil blive fjernet fra alle albums, og vil kun være synlig fra den låste mappe",
|
"move_to_locked_folder_confirmation": "Disse billeder og videoer vil blive fjernet fra alle albums, og vil kun være synlig fra den låste mappe",
|
||||||
"moved_to_archive": "Flyttede {count, plural, one {# mediefil} other {# mediefiler}} til arkivet",
|
"moved_to_archive": "Flyttede {count, plural, one {# mediefil} other {# mediefiler}} til arkivet",
|
||||||
@@ -1276,6 +1344,9 @@
|
|||||||
"my_albums": "Mine albummer",
|
"my_albums": "Mine albummer",
|
||||||
"name": "Navn",
|
"name": "Navn",
|
||||||
"name_or_nickname": "Navn eller kælenavn",
|
"name_or_nickname": "Navn eller kælenavn",
|
||||||
|
"network_requirement_photos_upload": "Benyt mobildatanettet for at sikkerhedskopiere dine fotos",
|
||||||
|
"network_requirement_videos_upload": "Benyt mobildatanettet for at sikkerhedskopiere dine videoer",
|
||||||
|
"network_requirements_updated": "Netværkskravene er ændret, backup-køen nulstilles",
|
||||||
"networking_settings": "Netværk",
|
"networking_settings": "Netværk",
|
||||||
"networking_subtitle": "Administrer serverens endepunktindstillinger",
|
"networking_subtitle": "Administrer serverens endepunktindstillinger",
|
||||||
"never": "aldrig",
|
"never": "aldrig",
|
||||||
@@ -1311,6 +1382,7 @@
|
|||||||
"no_results": "Ingen resultater",
|
"no_results": "Ingen resultater",
|
||||||
"no_results_description": "Prøv et synonym eller et mere generelt søgeord",
|
"no_results_description": "Prøv et synonym eller et mere generelt søgeord",
|
||||||
"no_shared_albums_message": "Opret et album for at dele billeder og videoer med personer i dit netværk",
|
"no_shared_albums_message": "Opret et album for at dele billeder og videoer med personer i dit netværk",
|
||||||
|
"no_uploads_in_progress": "Ingen upload i gang",
|
||||||
"not_in_any_album": "Ikke i noget album",
|
"not_in_any_album": "Ikke i noget album",
|
||||||
"not_selected": "Ikke valgt",
|
"not_selected": "Ikke valgt",
|
||||||
"note_apply_storage_label_to_previously_uploaded assets": "Bemærk: For at anvende Lagringsmærkat på tidligere uploadede medier, kør",
|
"note_apply_storage_label_to_previously_uploaded assets": "Bemærk: For at anvende Lagringsmærkat på tidligere uploadede medier, kør",
|
||||||
@@ -1326,6 +1398,7 @@
|
|||||||
"oauth": "OAuth",
|
"oauth": "OAuth",
|
||||||
"official_immich_resources": "Officielle Immich-ressourcer",
|
"official_immich_resources": "Officielle Immich-ressourcer",
|
||||||
"offline": "Offline",
|
"offline": "Offline",
|
||||||
|
"offset": "Forskydning",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"oldest_first": "Ældste først",
|
"oldest_first": "Ældste først",
|
||||||
"on_this_device": "På denne enhed",
|
"on_this_device": "På denne enhed",
|
||||||
@@ -1348,6 +1421,7 @@
|
|||||||
"original": "original",
|
"original": "original",
|
||||||
"other": "Andet",
|
"other": "Andet",
|
||||||
"other_devices": "Andre enheder",
|
"other_devices": "Andre enheder",
|
||||||
|
"other_entities": "Andre enheder",
|
||||||
"other_variables": "Andre variable",
|
"other_variables": "Andre variable",
|
||||||
"owned": "Egne",
|
"owned": "Egne",
|
||||||
"owner": "Ejer",
|
"owner": "Ejer",
|
||||||
@@ -1402,6 +1476,9 @@
|
|||||||
"permission_onboarding_permission_limited": "Tilladelse begrænset. For at lade Immich lave sikkerhedskopi og styre hele dit galleri, skal der gives tilladelse til billeder og videoer i indstillinger.",
|
"permission_onboarding_permission_limited": "Tilladelse begrænset. For at lade Immich lave sikkerhedskopi og styre hele dit galleri, skal der gives tilladelse til billeder og videoer i indstillinger.",
|
||||||
"permission_onboarding_request": "Immich kræver tilliadelse til at se dine billeder og videoer.",
|
"permission_onboarding_request": "Immich kræver tilliadelse til at se dine billeder og videoer.",
|
||||||
"person": "Person",
|
"person": "Person",
|
||||||
|
"person_age_months": "{months, plural, one {# month} other {# months}} gammel",
|
||||||
|
"person_age_year_months": "1 år, {months, plural, one {# month} other {# months}} gammel",
|
||||||
|
"person_age_years": "{years, plural, other {# years}} gammel",
|
||||||
"person_birthdate": "Født den {date}",
|
"person_birthdate": "Født den {date}",
|
||||||
"person_hidden": "{name}{hidden, select, true { (skjult)} other {}}",
|
"person_hidden": "{name}{hidden, select, true { (skjult)} other {}}",
|
||||||
"photo_shared_all_users": "Det ser ud til, at du har delt dine billeder med alle brugere, eller også har du ikke nogen bruger at dele med.",
|
"photo_shared_all_users": "Det ser ud til, at du har delt dine billeder med alle brugere, eller også har du ikke nogen bruger at dele med.",
|
||||||
@@ -1441,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "Mobilapp er forældet. Opdater venligst til den nyeste mindre version.",
|
"profile_drawer_client_out_of_date_minor": "Mobilapp er forældet. Opdater venligst til den nyeste mindre version.",
|
||||||
"profile_drawer_client_server_up_to_date": "Klient og server er ajour",
|
"profile_drawer_client_server_up_to_date": "Klient og server er ajour",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Skrivebeskyttet tilstand aktiveret. Dobbeltklik på bruger avatar ikonet for at afslutte.",
|
||||||
"profile_drawer_server_out_of_date_major": "Server er forældet. Opdater venligst til den nyeste større version.",
|
"profile_drawer_server_out_of_date_major": "Server er forældet. Opdater venligst til den nyeste større version.",
|
||||||
"profile_drawer_server_out_of_date_minor": "Server er forældet. Opdater venligst til den nyeste mindre version.",
|
"profile_drawer_server_out_of_date_minor": "Server er forældet. Opdater venligst til den nyeste mindre version.",
|
||||||
"profile_image_of_user": "Profilbillede af {user}",
|
"profile_image_of_user": "Profilbillede af {user}",
|
||||||
@@ -1476,15 +1554,18 @@
|
|||||||
"purchase_remove_server_product_key": "Fjern serverens produktnøgle",
|
"purchase_remove_server_product_key": "Fjern serverens produktnøgle",
|
||||||
"purchase_remove_server_product_key_prompt": "Er du sikker på, at du vil fjerne serverproduktnøglen?",
|
"purchase_remove_server_product_key_prompt": "Er du sikker på, at du vil fjerne serverproduktnøglen?",
|
||||||
"purchase_server_description_1": "For hele serveren",
|
"purchase_server_description_1": "For hele serveren",
|
||||||
"purchase_server_description_2": "Supporter status",
|
"purchase_server_description_2": "Supporterstatus",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Serverens produktnøgle administreres af administratoren",
|
"purchase_settings_server_activated": "Serverens produktnøgle administreres af administratoren",
|
||||||
|
"queue_status": "Kø {count}/{total}",
|
||||||
"rating": "Stjernebedømmelse",
|
"rating": "Stjernebedømmelse",
|
||||||
"rating_clear": "Nulstil vurdering",
|
"rating_clear": "Nulstil vurdering",
|
||||||
"rating_count": "{count, plural, one {# stjerne} other {# stjerner}}",
|
"rating_count": "{count, plural, one {# stjerne} other {# stjerner}}",
|
||||||
"rating_description": "Vis EXIF-klassificeringen i infopanelet",
|
"rating_description": "Vis EXIF-klassificeringen i infopanelet",
|
||||||
"reaction_options": "Reaktionsindstillinger",
|
"reaction_options": "Reaktionsindstillinger",
|
||||||
"read_changelog": "Læs ændringslog",
|
"read_changelog": "Læs ændringslog",
|
||||||
|
"readonly_mode_disabled": "Skrivebeskyttet tilstand deaktiveret",
|
||||||
|
"readonly_mode_enabled": "Skrivebeskyttet tilstand aktiveret",
|
||||||
"reassign": "Gentildel",
|
"reassign": "Gentildel",
|
||||||
"reassigned_assets_to_existing_person": "{count, plural, one {# mediefil} other {# mediefiler}} er blevet gentildelt til {name, select, null {en eksisterende person} other {{name}}}",
|
"reassigned_assets_to_existing_person": "{count, plural, one {# mediefil} other {# mediefiler}} er blevet gentildelt til {name, select, null {en eksisterende person} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "Gentildelt {count, plural, one {# aktiv} other {# aktiver}} til en ny person",
|
"reassigned_assets_to_new_person": "Gentildelt {count, plural, one {# aktiv} other {# aktiver}} til en ny person",
|
||||||
@@ -1507,6 +1588,8 @@
|
|||||||
"refreshing_faces": "Opdaterer ansigter",
|
"refreshing_faces": "Opdaterer ansigter",
|
||||||
"refreshing_metadata": "Opdaterer metadata",
|
"refreshing_metadata": "Opdaterer metadata",
|
||||||
"regenerating_thumbnails": "Regenererer forhåndsvisninger",
|
"regenerating_thumbnails": "Regenererer forhåndsvisninger",
|
||||||
|
"remote": "Eksternt",
|
||||||
|
"remote_assets": "Eksterne objekter",
|
||||||
"remove": "Fjern",
|
"remove": "Fjern",
|
||||||
"remove_assets_album_confirmation": "Er du sikker på, at du vil fjerne {count, plural, one {# aktiv} other {# aktiver}} fra albummet?",
|
"remove_assets_album_confirmation": "Er du sikker på, at du vil fjerne {count, plural, one {# aktiv} other {# aktiver}} fra albummet?",
|
||||||
"remove_assets_shared_link_confirmation": "Er du sikker på, at du vil fjerne {count, plural, one {# aktiv} other {# aktiver}} fra dette delte link?",
|
"remove_assets_shared_link_confirmation": "Er du sikker på, at du vil fjerne {count, plural, one {# aktiv} other {# aktiver}} fra dette delte link?",
|
||||||
@@ -1514,7 +1597,9 @@
|
|||||||
"remove_custom_date_range": "Fjern tilpasset datointerval",
|
"remove_custom_date_range": "Fjern tilpasset datointerval",
|
||||||
"remove_deleted_assets": "Fjern slettede mediefiler",
|
"remove_deleted_assets": "Fjern slettede mediefiler",
|
||||||
"remove_from_album": "Fjern fra album",
|
"remove_from_album": "Fjern fra album",
|
||||||
|
"remove_from_album_action_prompt": "{count} fjernet fra albummet",
|
||||||
"remove_from_favorites": "Fjern fra favoritter",
|
"remove_from_favorites": "Fjern fra favoritter",
|
||||||
|
"remove_from_lock_folder_action_prompt": "{count} fjernet fra den låste mappe",
|
||||||
"remove_from_locked_folder": "Fjern fra låst mappe",
|
"remove_from_locked_folder": "Fjern fra låst mappe",
|
||||||
"remove_from_locked_folder_confirmation": "Er du sikker på at du vil flytte disse billeder og videoer ud af den låste mappe? De vil være synlige i dit bibliotek.",
|
"remove_from_locked_folder_confirmation": "Er du sikker på at du vil flytte disse billeder og videoer ud af den låste mappe? De vil være synlige i dit bibliotek.",
|
||||||
"remove_from_shared_link": "Fjern fra delt link",
|
"remove_from_shared_link": "Fjern fra delt link",
|
||||||
@@ -1542,19 +1627,28 @@
|
|||||||
"reset_password": "Nulstil adgangskode",
|
"reset_password": "Nulstil adgangskode",
|
||||||
"reset_people_visibility": "Nulstil personsynlighed",
|
"reset_people_visibility": "Nulstil personsynlighed",
|
||||||
"reset_pin_code": "Nulstil PIN kode",
|
"reset_pin_code": "Nulstil PIN kode",
|
||||||
|
"reset_pin_code_description": "Hvis du har glemt din PIN-kode, kan du kontakte serveradministratoren for at få den stillet tilbage",
|
||||||
|
"reset_pin_code_success": "PIN-koden er stillet tilbage",
|
||||||
|
"reset_pin_code_with_password": "Du kan altid nulstille din PIN-kode med dit password",
|
||||||
|
"reset_sqlite": "Reset SQLite Databasen",
|
||||||
|
"reset_sqlite_confirmation": "Er du sikker på, at du vil nulstille SQLite databasen? Du er nødt til at logge ud og ind igen for at gensynkronisere dine data",
|
||||||
|
"reset_sqlite_success": "Vellykket reset af SQLite databasen",
|
||||||
"reset_to_default": "Nulstil til standard",
|
"reset_to_default": "Nulstil til standard",
|
||||||
"resolve_duplicates": "Løs dubletter",
|
"resolve_duplicates": "Løs dubletter",
|
||||||
"resolved_all_duplicates": "Alle dubletter løst",
|
"resolved_all_duplicates": "Alle dubletter løst",
|
||||||
"restore": "Gendan",
|
"restore": "Gendan",
|
||||||
"restore_all": "Gendan alle",
|
"restore_all": "Gendan alle",
|
||||||
|
"restore_trash_action_prompt": "{count} genskabt fra papirkurven",
|
||||||
"restore_user": "Gendan bruger",
|
"restore_user": "Gendan bruger",
|
||||||
"restored_asset": "Gendannet mediefilen",
|
"restored_asset": "Gendannet mediefilen",
|
||||||
"resume": "Genoptag",
|
"resume": "Genoptag",
|
||||||
"retry_upload": "Forsøg upload igen",
|
"retry_upload": "Forsøg upload igen",
|
||||||
"review_duplicates": "Gennemgå dubletter",
|
"review_duplicates": "Gennemgå dubletter",
|
||||||
|
"review_large_files": "Gennemgå store filer",
|
||||||
"role": "Rolle",
|
"role": "Rolle",
|
||||||
"role_editor": "Redaktør",
|
"role_editor": "Redaktør",
|
||||||
"role_viewer": "Seer",
|
"role_viewer": "Seer",
|
||||||
|
"running": "Kører",
|
||||||
"save": "Gem",
|
"save": "Gem",
|
||||||
"save_to_gallery": "Gem til galleri",
|
"save_to_gallery": "Gem til galleri",
|
||||||
"saved_api_key": "Gemt API-nøgle",
|
"saved_api_key": "Gemt API-nøgle",
|
||||||
@@ -1627,6 +1721,7 @@
|
|||||||
"select_album_cover": "Vælg albumcover",
|
"select_album_cover": "Vælg albumcover",
|
||||||
"select_all": "Vælg alle",
|
"select_all": "Vælg alle",
|
||||||
"select_all_duplicates": "Vælg alle dubletter",
|
"select_all_duplicates": "Vælg alle dubletter",
|
||||||
|
"select_all_in": "Vælg alt i {group}",
|
||||||
"select_avatar_color": "Vælg avatarfarve",
|
"select_avatar_color": "Vælg avatarfarve",
|
||||||
"select_face": "Vælg ansigt",
|
"select_face": "Vælg ansigt",
|
||||||
"select_featured_photo": "Vælg forsidebillede",
|
"select_featured_photo": "Vælg forsidebillede",
|
||||||
@@ -1640,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Fejlede i at oprette et nyt album",
|
"select_user_for_sharing_page_err_album": "Fejlede i at oprette et nyt album",
|
||||||
"selected": "Valgt",
|
"selected": "Valgt",
|
||||||
"selected_count": "{count, plural, one {# valgt} other {# valgte}}",
|
"selected_count": "{count, plural, one {# valgt} other {# valgte}}",
|
||||||
|
"selected_gps_coordinates": "Valgte GPS-koordinater",
|
||||||
"send_message": "Send besked",
|
"send_message": "Send besked",
|
||||||
"send_welcome_email": "Send velkomstemail",
|
"send_welcome_email": "Send velkomstemail",
|
||||||
"server_endpoint": "Server endepunkt",
|
"server_endpoint": "Server endepunkt",
|
||||||
@@ -1677,7 +1773,7 @@
|
|||||||
"setting_notifications_subtitle": "Tilpas dine notifikationspræferencer",
|
"setting_notifications_subtitle": "Tilpas dine notifikationspræferencer",
|
||||||
"setting_notifications_total_progress_subtitle": "Samlet uploadstatus (færdige/samlet antal elementer)",
|
"setting_notifications_total_progress_subtitle": "Samlet uploadstatus (færdige/samlet antal elementer)",
|
||||||
"setting_notifications_total_progress_title": "Vis samlet baggrundsuploadstatus",
|
"setting_notifications_total_progress_title": "Vis samlet baggrundsuploadstatus",
|
||||||
"setting_video_viewer_looping_title": "Looping",
|
"setting_video_viewer_looping_title": "Looper",
|
||||||
"setting_video_viewer_original_video_subtitle": "Når der streames video fra serveren, afspil da den originale selv når en omkodet udgave er tilgængelig. Kan føre til buffering. Videoer, der er tilgængelige lokalt, afspilles i original kvalitet uanset denne indstilling.",
|
"setting_video_viewer_original_video_subtitle": "Når der streames video fra serveren, afspil da den originale selv når en omkodet udgave er tilgængelig. Kan føre til buffering. Videoer, der er tilgængelige lokalt, afspilles i original kvalitet uanset denne indstilling.",
|
||||||
"setting_video_viewer_original_video_title": "Tving original video",
|
"setting_video_viewer_original_video_title": "Tving original video",
|
||||||
"settings": "Indstillinger",
|
"settings": "Indstillinger",
|
||||||
@@ -1685,6 +1781,7 @@
|
|||||||
"settings_saved": "Indstillinger er gemt",
|
"settings_saved": "Indstillinger er gemt",
|
||||||
"setup_pin_code": "Sæt in PIN kode",
|
"setup_pin_code": "Sæt in PIN kode",
|
||||||
"share": "Del",
|
"share": "Del",
|
||||||
|
"share_action_prompt": "Delte {count} objekter",
|
||||||
"share_add_photos": "Tilføj billeder",
|
"share_add_photos": "Tilføj billeder",
|
||||||
"share_assets_selected": "{count} valgt",
|
"share_assets_selected": "{count} valgt",
|
||||||
"share_dialog_preparing": "Forbereder...",
|
"share_dialog_preparing": "Forbereder...",
|
||||||
@@ -1706,6 +1803,7 @@
|
|||||||
"shared_link_clipboard_copied_massage": "Kopieret til udklipsholderen",
|
"shared_link_clipboard_copied_massage": "Kopieret til udklipsholderen",
|
||||||
"shared_link_clipboard_text": "Link: {link}\nAdgangskode: {password}",
|
"shared_link_clipboard_text": "Link: {link}\nAdgangskode: {password}",
|
||||||
"shared_link_create_error": "Der opstod en fejl i oprettelsen af et delt link",
|
"shared_link_create_error": "Der opstod en fejl i oprettelsen af et delt link",
|
||||||
|
"shared_link_custom_url_description": "Adgang til dette delte link med en selvdefineret URL",
|
||||||
"shared_link_edit_description_hint": "Indtast beskrivelse",
|
"shared_link_edit_description_hint": "Indtast beskrivelse",
|
||||||
"shared_link_edit_expire_after_option_day": "1 dag",
|
"shared_link_edit_expire_after_option_day": "1 dag",
|
||||||
"shared_link_edit_expire_after_option_days": "{count} dage",
|
"shared_link_edit_expire_after_option_days": "{count} dage",
|
||||||
@@ -1731,6 +1829,7 @@
|
|||||||
"shared_link_info_chip_metadata": "EXIF",
|
"shared_link_info_chip_metadata": "EXIF",
|
||||||
"shared_link_manage_links": "Håndter delte links",
|
"shared_link_manage_links": "Håndter delte links",
|
||||||
"shared_link_options": "Muligheder for delt link",
|
"shared_link_options": "Muligheder for delt link",
|
||||||
|
"shared_link_password_description": "Kræv et kodeord for at få adgang til dette delte link",
|
||||||
"shared_links": "Delte links",
|
"shared_links": "Delte links",
|
||||||
"shared_links_description": "Del billeder og videoer med et link",
|
"shared_links_description": "Del billeder og videoer med et link",
|
||||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# delte billeder & videoer.}}",
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# delte billeder & videoer.}}",
|
||||||
@@ -1747,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "tryk på ⇧ for at slette aktiv permanent",
|
"shift_to_permanent_delete": "tryk på ⇧ for at slette aktiv permanent",
|
||||||
"show_album_options": "Vis albumindstillinger",
|
"show_album_options": "Vis albumindstillinger",
|
||||||
"show_albums": "Vis albummer",
|
"show_albums": "Vis albummer",
|
||||||
|
"show_all_assets": "Vis alle objekter",
|
||||||
"show_all_people": "Vis alle personer",
|
"show_all_people": "Vis alle personer",
|
||||||
"show_and_hide_people": "Vis & skjul personer",
|
"show_and_hide_people": "Vis & skjul personer",
|
||||||
|
"show_assets_without_location": "Vis objekter uden lokation",
|
||||||
"show_file_location": "Vis filplacering",
|
"show_file_location": "Vis filplacering",
|
||||||
"show_gallery": "Vis galleri",
|
"show_gallery": "Vis galleri",
|
||||||
"show_hidden_people": "Vis skjulte personer",
|
"show_hidden_people": "Vis skjulte personer",
|
||||||
@@ -1780,12 +1881,14 @@
|
|||||||
"sort_created": "Dato oprettet",
|
"sort_created": "Dato oprettet",
|
||||||
"sort_items": "Antal genstande",
|
"sort_items": "Antal genstande",
|
||||||
"sort_modified": "Ændret dato",
|
"sort_modified": "Ændret dato",
|
||||||
|
"sort_newest": "Nyeste foto",
|
||||||
"sort_oldest": "Ældste foto",
|
"sort_oldest": "Ældste foto",
|
||||||
"sort_people_by_similarity": "Sorter efter personer der ligner hinanden",
|
"sort_people_by_similarity": "Sorter efter personer der ligner hinanden",
|
||||||
"sort_recent": "Seneste foto",
|
"sort_recent": "Seneste foto",
|
||||||
"sort_title": "Titel",
|
"sort_title": "Titel",
|
||||||
"source": "Kilde",
|
"source": "Kilde",
|
||||||
"stack": "Stak",
|
"stack": "Stak",
|
||||||
|
"stack_action_prompt": "{count} stakket",
|
||||||
"stack_duplicates": "Stak dubletter",
|
"stack_duplicates": "Stak dubletter",
|
||||||
"stack_select_one_photo": "Vælg ét hovedbillede til stakken",
|
"stack_select_one_photo": "Vælg ét hovedbillede til stakken",
|
||||||
"stack_selected_photos": "Stak valgte billeder",
|
"stack_selected_photos": "Stak valgte billeder",
|
||||||
@@ -1805,6 +1908,7 @@
|
|||||||
"storage_quota": "Lagringskvota",
|
"storage_quota": "Lagringskvota",
|
||||||
"storage_usage": "{used} ud af {available} brugt",
|
"storage_usage": "{used} ud af {available} brugt",
|
||||||
"submit": "Indsend",
|
"submit": "Indsend",
|
||||||
|
"success": "Vellykket",
|
||||||
"suggestions": "Anbefalinger",
|
"suggestions": "Anbefalinger",
|
||||||
"sunrise_on_the_beach": "Solopgang på stranden",
|
"sunrise_on_the_beach": "Solopgang på stranden",
|
||||||
"support": "Support",
|
"support": "Support",
|
||||||
@@ -1814,6 +1918,8 @@
|
|||||||
"sync": "Synkronisér",
|
"sync": "Synkronisér",
|
||||||
"sync_albums": "Synkroniser albummer",
|
"sync_albums": "Synkroniser albummer",
|
||||||
"sync_albums_manual_subtitle": "Synkroniser alle uploadet billeder og videoer til de valgte backupalbummer",
|
"sync_albums_manual_subtitle": "Synkroniser alle uploadet billeder og videoer til de valgte backupalbummer",
|
||||||
|
"sync_local": "Synkroniser lokalt",
|
||||||
|
"sync_remote": "Synkroniser eksternt",
|
||||||
"sync_upload_album_setting_subtitle": "Opret og upload dine billeder og videoer til de valgte albummer i Immich",
|
"sync_upload_album_setting_subtitle": "Opret og upload dine billeder og videoer til de valgte albummer i Immich",
|
||||||
"tag": "Tag",
|
"tag": "Tag",
|
||||||
"tag_assets": "Tag mediefiler",
|
"tag_assets": "Tag mediefiler",
|
||||||
@@ -1824,6 +1930,7 @@
|
|||||||
"tag_updated": "Opdateret tag: {tag}",
|
"tag_updated": "Opdateret tag: {tag}",
|
||||||
"tagged_assets": "Tagget {count, plural, one {# aktiv} other {# aktiver}}",
|
"tagged_assets": "Tagget {count, plural, one {# aktiv} other {# aktiver}}",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
|
"tap_to_run_job": "Tryk for at køre jobbet",
|
||||||
"template": "Skabelon",
|
"template": "Skabelon",
|
||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
"theme_selection": "Temavalg",
|
"theme_selection": "Temavalg",
|
||||||
@@ -1850,12 +1957,15 @@
|
|||||||
"to_change_password": "Skift adgangskode",
|
"to_change_password": "Skift adgangskode",
|
||||||
"to_favorite": "Gør til favorit",
|
"to_favorite": "Gør til favorit",
|
||||||
"to_login": "Login",
|
"to_login": "Login",
|
||||||
|
"to_multi_select": "For at vælge flere",
|
||||||
"to_parent": "Gå op",
|
"to_parent": "Gå op",
|
||||||
|
"to_select": "for at vælge",
|
||||||
"to_trash": "Papirkurv",
|
"to_trash": "Papirkurv",
|
||||||
"toggle_settings": "Slå indstillinger til eller fra",
|
"toggle_settings": "Slå indstillinger til eller fra",
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
"total_usage": "Samlet forbrug",
|
"total_usage": "Samlet forbrug",
|
||||||
"trash": "Papirkurv",
|
"trash": "Papirkurv",
|
||||||
|
"trash_action_prompt": "{count} flyttet til papirkurven",
|
||||||
"trash_all": "Smid alle ud",
|
"trash_all": "Smid alle ud",
|
||||||
"trash_count": "Slet {count, number}",
|
"trash_count": "Slet {count, number}",
|
||||||
"trash_delete_asset": "Flyt mediefil til Papirkurv",
|
"trash_delete_asset": "Flyt mediefil til Papirkurv",
|
||||||
@@ -1873,9 +1983,11 @@
|
|||||||
"unable_to_change_pin_code": "Kunne ikke ændre PIN kode",
|
"unable_to_change_pin_code": "Kunne ikke ændre PIN kode",
|
||||||
"unable_to_setup_pin_code": "Kunne ikke sætte PIN kode",
|
"unable_to_setup_pin_code": "Kunne ikke sætte PIN kode",
|
||||||
"unarchive": "Afakivér",
|
"unarchive": "Afakivér",
|
||||||
|
"unarchive_action_prompt": "{count} slettet fra Arkiv",
|
||||||
"unarchived_count": "{count, plural, other {Uarkiveret #}}",
|
"unarchived_count": "{count, plural, other {Uarkiveret #}}",
|
||||||
"undo": "Fortryd",
|
"undo": "Fortryd",
|
||||||
"unfavorite": "Fjern favorit",
|
"unfavorite": "Fjern favorit",
|
||||||
|
"unfavorite_action_prompt": "{count} slettet fra Favoritter",
|
||||||
"unhide_person": "Stop med at skjule person",
|
"unhide_person": "Stop med at skjule person",
|
||||||
"unknown": "Ukendt",
|
"unknown": "Ukendt",
|
||||||
"unknown_country": "Ukendt land",
|
"unknown_country": "Ukendt land",
|
||||||
@@ -1891,16 +2003,23 @@
|
|||||||
"unsaved_change": "Ændring, der ikke er gemt",
|
"unsaved_change": "Ændring, der ikke er gemt",
|
||||||
"unselect_all": "Fravælg alle",
|
"unselect_all": "Fravælg alle",
|
||||||
"unselect_all_duplicates": "Fjern markeringen af alle dubletter",
|
"unselect_all_duplicates": "Fjern markeringen af alle dubletter",
|
||||||
|
"unselect_all_in": "Afmarkér alle i {group}",
|
||||||
"unstack": "Fjern fra stak",
|
"unstack": "Fjern fra stak",
|
||||||
|
"unstack_action_prompt": "{count} ustakket",
|
||||||
"unstacked_assets_count": "Ikke-stablet {count, plural, one {# aktiv} other {# aktiver}}",
|
"unstacked_assets_count": "Ikke-stablet {count, plural, one {# aktiv} other {# aktiver}}",
|
||||||
|
"untagged": "Umærket",
|
||||||
"up_next": "Næste",
|
"up_next": "Næste",
|
||||||
|
"update_location_action_prompt": "Opdater lokationen for {count} valgte objekter med:",
|
||||||
"updated_at": "Opdateret",
|
"updated_at": "Opdateret",
|
||||||
"updated_password": "Opdaterede adgangskode",
|
"updated_password": "Opdaterede adgangskode",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
|
"upload_action_prompt": "{count} i kø til upload",
|
||||||
"upload_concurrency": "Upload samtidighed",
|
"upload_concurrency": "Upload samtidighed",
|
||||||
|
"upload_details": "Upload detaljer",
|
||||||
"upload_dialog_info": "Vil du sikkerhedskopiere de(t) valgte element(er) til serveren?",
|
"upload_dialog_info": "Vil du sikkerhedskopiere de(t) valgte element(er) til serveren?",
|
||||||
"upload_dialog_title": "Upload element",
|
"upload_dialog_title": "Upload element",
|
||||||
"upload_errors": "Upload afsluttet med {count, plural, one {# fejl} other {# fejl}}. Opdater siden for at se nye uploadaktiver.",
|
"upload_errors": "Upload afsluttet med {count, plural, one {# fejl} other {# fejl}}. Opdater siden for at se nye uploadaktiver.",
|
||||||
|
"upload_finished": "Upload fuldført",
|
||||||
"upload_progress": "Resterende {remaining, number} - Behandlet {processed, number}/{total, number}",
|
"upload_progress": "Resterende {remaining, number} - Behandlet {processed, number}/{total, number}",
|
||||||
"upload_skipped_duplicates": "Sprang over {count, plural, one {# duplet aktiv} other {# duplikerede aktiver}}",
|
"upload_skipped_duplicates": "Sprang over {count, plural, one {# duplet aktiv} other {# duplikerede aktiver}}",
|
||||||
"upload_status_duplicates": "Dubletter",
|
"upload_status_duplicates": "Dubletter",
|
||||||
@@ -1909,11 +2028,13 @@
|
|||||||
"upload_success": "Upload gennemført. Opdater siden for at se nye uploadaktiver.",
|
"upload_success": "Upload gennemført. Opdater siden for at se nye uploadaktiver.",
|
||||||
"upload_to_immich": "Upload til Immich ({count})",
|
"upload_to_immich": "Upload til Immich ({count})",
|
||||||
"uploading": "Uploader",
|
"uploading": "Uploader",
|
||||||
|
"uploading_media": "Uploader media",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"usage": "Forbrug",
|
"usage": "Forbrug",
|
||||||
"use_biometric": "Brug biometrisk",
|
"use_biometric": "Brug biometrisk",
|
||||||
"use_current_connection": "brug nuværende forbindelse",
|
"use_current_connection": "brug nuværende forbindelse",
|
||||||
"use_custom_date_range": "Brug tilpasset datointerval i stedet",
|
"use_custom_date_range": "Brug tilpasset datointerval i stedet",
|
||||||
|
"use_this_location": "Klik for at benytte lokationen",
|
||||||
"user": "Bruger",
|
"user": "Bruger",
|
||||||
"user_has_been_deleted": "Denne bruger er slettet.",
|
"user_has_been_deleted": "Denne bruger er slettet.",
|
||||||
"user_id": "Bruger-ID",
|
"user_id": "Bruger-ID",
|
||||||
@@ -1929,6 +2050,7 @@
|
|||||||
"user_usage_stats_description": "Vis konto anvendelsesstatistik",
|
"user_usage_stats_description": "Vis konto anvendelsesstatistik",
|
||||||
"username": "Brugernavn",
|
"username": "Brugernavn",
|
||||||
"users": "Brugere",
|
"users": "Brugere",
|
||||||
|
"users_added_to_album_count": "Føjet {count, plural, one {# bruker} other {# brukere}} til albummet",
|
||||||
"utilities": "Værktøjer",
|
"utilities": "Værktøjer",
|
||||||
"validate": "Validér",
|
"validate": "Validér",
|
||||||
"validate_endpoint_error": "Indtast en gyldig URL",
|
"validate_endpoint_error": "Indtast en gyldig URL",
|
||||||
@@ -1947,6 +2069,7 @@
|
|||||||
"view_album": "Se album",
|
"view_album": "Se album",
|
||||||
"view_all": "Se alle",
|
"view_all": "Se alle",
|
||||||
"view_all_users": "Se alle brugere",
|
"view_all_users": "Se alle brugere",
|
||||||
|
"view_details": "Vis detaljer",
|
||||||
"view_in_timeline": "Se på tidslinjen",
|
"view_in_timeline": "Se på tidslinjen",
|
||||||
"view_link": "Vis Link",
|
"view_link": "Vis Link",
|
||||||
"view_links": "Vis links",
|
"view_links": "Vis links",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Die Suchfilter öffnen",
|
"open_the_search_filters": "Die Suchfilter öffnen",
|
||||||
"options": "Optionen",
|
"options": "Optionen",
|
||||||
"or": "oder",
|
"or": "oder",
|
||||||
|
"organize_into_albums": "In Alben organisieren",
|
||||||
|
"organize_into_albums_description": "Aktuelle Synchronisationseinstellungen verwenden, um existierende Fotos in Alben zu laden",
|
||||||
"organize_your_library": "Organisiere deine Bibliothek",
|
"organize_your_library": "Organisiere deine Bibliothek",
|
||||||
"original": "Original",
|
"original": "Original",
|
||||||
"other": "Sonstiges",
|
"other": "Sonstiges",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Unterstützerstatus",
|
"purchase_server_description_2": "Unterstützerstatus",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Der Server-Produktschlüssel wird durch den Administrator verwaltet",
|
"purchase_settings_server_activated": "Der Server-Produktschlüssel wird durch den Administrator verwaltet",
|
||||||
|
"query_asset_id": "Datei-ID abfragen",
|
||||||
"queue_status": "Warteschlange {count}/{total}",
|
"queue_status": "Warteschlange {count}/{total}",
|
||||||
"rating": "Bewertung",
|
"rating": "Bewertung",
|
||||||
"rating_clear": "Bewertung löschen",
|
"rating_clear": "Bewertung löschen",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Album konnte nicht erstellt werden",
|
"select_user_for_sharing_page_err_album": "Album konnte nicht erstellt werden",
|
||||||
"selected": "Ausgewählt",
|
"selected": "Ausgewählt",
|
||||||
"selected_count": "{count, plural, other {# ausgewählt}}",
|
"selected_count": "{count, plural, other {# ausgewählt}}",
|
||||||
"selected_gps_coordinates": "Ausgewählte GPS Koordinaten",
|
"selected_gps_coordinates": "Ausgewählte GPS-Koordinaten",
|
||||||
"send_message": "Nachricht senden",
|
"send_message": "Nachricht senden",
|
||||||
"send_welcome_email": "Begrüssungsmail senden",
|
"send_welcome_email": "Begrüssungsmail senden",
|
||||||
"server_endpoint": "Server-Endpunkt",
|
"server_endpoint": "Server-Endpunkt",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Nächste Datei anzeigen",
|
"view_next_asset": "Nächste Datei anzeigen",
|
||||||
"view_previous_asset": "Vorherige Datei anzeigen",
|
"view_previous_asset": "Vorherige Datei anzeigen",
|
||||||
"view_qr_code": "QR code anzeigen",
|
"view_qr_code": "QR code anzeigen",
|
||||||
|
"view_similar_photos": "Zeige ähnliche Fotos an",
|
||||||
"view_stack": "Stapel anzeigen",
|
"view_stack": "Stapel anzeigen",
|
||||||
"view_user": "Benutzer anzeigen",
|
"view_user": "Benutzer anzeigen",
|
||||||
"viewer_remove_from_stack": "Aus Stapel entfernen",
|
"viewer_remove_from_stack": "Aus Stapel entfernen",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Open the search filters",
|
"open_the_search_filters": "Open the search filters",
|
||||||
"options": "Options",
|
"options": "Options",
|
||||||
"or": "or",
|
"or": "or",
|
||||||
|
"organize_into_albums": "Organize into albums",
|
||||||
|
"organize_into_albums_description": "Put existing photos into albums using current sync settings",
|
||||||
"organize_your_library": "Organize your library",
|
"organize_your_library": "Organize your library",
|
||||||
"original": "original",
|
"original": "original",
|
||||||
"other": "Other",
|
"other": "Other",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Supporter status",
|
"purchase_server_description_2": "Supporter status",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "The server product key is managed by the admin",
|
"purchase_settings_server_activated": "The server product key is managed by the admin",
|
||||||
|
"query_asset_id": "Query Asset ID",
|
||||||
"queue_status": "Queuing {count}/{total}",
|
"queue_status": "Queuing {count}/{total}",
|
||||||
"rating": "Star rating",
|
"rating": "Star rating",
|
||||||
"rating_clear": "Clear rating",
|
"rating_clear": "Clear rating",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Failed to create album",
|
"select_user_for_sharing_page_err_album": "Failed to create album",
|
||||||
"selected": "Selected",
|
"selected": "Selected",
|
||||||
"selected_count": "{count, plural, other {# selected}}",
|
"selected_count": "{count, plural, other {# selected}}",
|
||||||
"selected_gps_coordinates": "selected gps coordinates",
|
"selected_gps_coordinates": "Selected GPS Coordinates",
|
||||||
"send_message": "Send message",
|
"send_message": "Send message",
|
||||||
"send_welcome_email": "Send welcome email",
|
"send_welcome_email": "Send welcome email",
|
||||||
"server_endpoint": "Server Endpoint",
|
"server_endpoint": "Server Endpoint",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "View next asset",
|
"view_next_asset": "View next asset",
|
||||||
"view_previous_asset": "View previous asset",
|
"view_previous_asset": "View previous asset",
|
||||||
"view_qr_code": "View QR code",
|
"view_qr_code": "View QR code",
|
||||||
|
"view_similar_photos": "View similar photos",
|
||||||
"view_stack": "View Stack",
|
"view_stack": "View Stack",
|
||||||
"view_user": "View User",
|
"view_user": "View User",
|
||||||
"viewer_remove_from_stack": "Remove from Stack",
|
"viewer_remove_from_stack": "Remove from Stack",
|
||||||
|
|||||||
14
i18n/es.json
14
i18n/es.json
@@ -167,8 +167,8 @@
|
|||||||
"map_settings": "Mapa",
|
"map_settings": "Mapa",
|
||||||
"map_settings_description": "Administrar la configuración del mapa",
|
"map_settings_description": "Administrar la configuración del mapa",
|
||||||
"map_style_description": "Dirección URL a un tema de mapa (style.json)",
|
"map_style_description": "Dirección URL a un tema de mapa (style.json)",
|
||||||
"memory_cleanup_job": "Limpieza de memoria",
|
"memory_cleanup_job": "Limpieza de recuerdos",
|
||||||
"memory_generate_job": "Generación de memoria",
|
"memory_generate_job": "Generación de recuerdos",
|
||||||
"metadata_extraction_job": "Extracción de metadatos",
|
"metadata_extraction_job": "Extracción de metadatos",
|
||||||
"metadata_extraction_job_description": "Extraer información de metadatos de cada activo, como GPS, caras y resolución",
|
"metadata_extraction_job_description": "Extraer información de metadatos de cada activo, como GPS, caras y resolución",
|
||||||
"metadata_faces_import_setting": "Activar importación de caras",
|
"metadata_faces_import_setting": "Activar importación de caras",
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
"oauth_storage_quota_claim_description": "Fijar la cuota de almacenamiento del usuario automáticamente al valor solicitado.",
|
"oauth_storage_quota_claim_description": "Fijar la cuota de almacenamiento del usuario automáticamente al valor solicitado.",
|
||||||
"oauth_storage_quota_default": "Cuota de almacenamiento predeterminada (GiB)",
|
"oauth_storage_quota_default": "Cuota de almacenamiento predeterminada (GiB)",
|
||||||
"oauth_storage_quota_default_description": "Cuota (en GiB) que se usará cuando no se solicite un valor específico.",
|
"oauth_storage_quota_default_description": "Cuota (en GiB) que se usará cuando no se solicite un valor específico.",
|
||||||
"oauth_timeout": "Límite de tiempo para la solicitud",
|
"oauth_timeout": "Tiempo de espera agotado para la solicitud",
|
||||||
"oauth_timeout_description": "Tiempo de espera de solicitudes en milisegundos",
|
"oauth_timeout_description": "Tiempo de espera de solicitudes en milisegundos",
|
||||||
"password_enable_description": "Iniciar sesión con correo electrónico y contraseña",
|
"password_enable_description": "Iniciar sesión con correo electrónico y contraseña",
|
||||||
"password_settings": "Contraseña de Acceso",
|
"password_settings": "Contraseña de Acceso",
|
||||||
@@ -1603,8 +1603,8 @@
|
|||||||
"remove_from_locked_folder": "Eliminar de la carpeta protegida",
|
"remove_from_locked_folder": "Eliminar de la carpeta protegida",
|
||||||
"remove_from_locked_folder_confirmation": "¿Seguro que deseas sacar estas fotos y vídeos de la carpeta protegida? Si continúas, los elementos serán visibles en tu biblioteca.",
|
"remove_from_locked_folder_confirmation": "¿Seguro que deseas sacar estas fotos y vídeos de la carpeta protegida? Si continúas, los elementos serán visibles en tu biblioteca.",
|
||||||
"remove_from_shared_link": "Eliminar desde enlace compartido",
|
"remove_from_shared_link": "Eliminar desde enlace compartido",
|
||||||
"remove_memory": "Quitar memoria",
|
"remove_memory": "Quitar recuerdo",
|
||||||
"remove_photo_from_memory": "Quitar foto de esta memoria",
|
"remove_photo_from_memory": "Quitar foto de este recuerdo",
|
||||||
"remove_tag": "Quitar etiqueta",
|
"remove_tag": "Quitar etiqueta",
|
||||||
"remove_url": "Eliminar URL",
|
"remove_url": "Eliminar URL",
|
||||||
"remove_user": "Eliminar usuario",
|
"remove_user": "Eliminar usuario",
|
||||||
@@ -1612,8 +1612,8 @@
|
|||||||
"removed_from_archive": "Eliminado del archivo",
|
"removed_from_archive": "Eliminado del archivo",
|
||||||
"removed_from_favorites": "Eliminado de favoritos",
|
"removed_from_favorites": "Eliminado de favoritos",
|
||||||
"removed_from_favorites_count": "{count, plural, other {Eliminados #}} de favoritos",
|
"removed_from_favorites_count": "{count, plural, other {Eliminados #}} de favoritos",
|
||||||
"removed_memory": "Memoria eliminada",
|
"removed_memory": "Recuerdo eliminado",
|
||||||
"removed_photo_from_memory": "Se ha eliminado la foto de la memoria",
|
"removed_photo_from_memory": "Foto eliminada del recuerdo",
|
||||||
"removed_tagged_assets": "Etiqueta eliminada de {count, plural, one {# activo} other {# activos}}",
|
"removed_tagged_assets": "Etiqueta eliminada de {count, plural, one {# activo} other {# activos}}",
|
||||||
"rename": "Renombrar",
|
"rename": "Renombrar",
|
||||||
"repair": "Reparar",
|
"repair": "Reparar",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Ava otsingufiltrid",
|
"open_the_search_filters": "Ava otsingufiltrid",
|
||||||
"options": "Valikud",
|
"options": "Valikud",
|
||||||
"or": "või",
|
"or": "või",
|
||||||
|
"organize_into_albums": "Organiseeri albumitesse",
|
||||||
|
"organize_into_albums_description": "Pane olemasolevad fotod albumitesse, kasutades jooksvaid sünkroonimise seadeid",
|
||||||
"organize_your_library": "Korrasta oma kogu",
|
"organize_your_library": "Korrasta oma kogu",
|
||||||
"original": "originaal",
|
"original": "originaal",
|
||||||
"other": "Muud",
|
"other": "Muud",
|
||||||
@@ -1735,7 +1737,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Albumi lisamine ebaõnnestus",
|
"select_user_for_sharing_page_err_album": "Albumi lisamine ebaõnnestus",
|
||||||
"selected": "Valitud",
|
"selected": "Valitud",
|
||||||
"selected_count": "{count, plural, other {# valitud}}",
|
"selected_count": "{count, plural, other {# valitud}}",
|
||||||
"selected_gps_coordinates": "valitud GPS-koordinaadid",
|
"selected_gps_coordinates": "Valitud GPS-koordinaadid",
|
||||||
"send_message": "Saada sõnum",
|
"send_message": "Saada sõnum",
|
||||||
"send_welcome_email": "Saada tervituskiri",
|
"send_welcome_email": "Saada tervituskiri",
|
||||||
"server_endpoint": "Serveri lõpp-punkt",
|
"server_endpoint": "Serveri lõpp-punkt",
|
||||||
@@ -2075,6 +2077,7 @@
|
|||||||
"view_next_asset": "Vaata järgmist üksust",
|
"view_next_asset": "Vaata järgmist üksust",
|
||||||
"view_previous_asset": "Vaata eelmist üksust",
|
"view_previous_asset": "Vaata eelmist üksust",
|
||||||
"view_qr_code": "Vaata QR-koodi",
|
"view_qr_code": "Vaata QR-koodi",
|
||||||
|
"view_similar_photos": "Vaata sarnaseid fotosid",
|
||||||
"view_stack": "Vaata virna",
|
"view_stack": "Vaata virna",
|
||||||
"view_user": "Vaata kasutajat",
|
"view_user": "Vaata kasutajat",
|
||||||
"viewer_remove_from_stack": "Eemalda virnast",
|
"viewer_remove_from_stack": "Eemalda virnast",
|
||||||
|
|||||||
@@ -396,6 +396,7 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Suosi etäkuvia",
|
"advanced_settings_prefer_remote_title": "Suosi etäkuvia",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Määritä välityspalvelimen otsikot(proxy headers), jotka Immichin tulisi lähettää jokaisen verkkopyynnön mukana",
|
"advanced_settings_proxy_headers_subtitle": "Määritä välityspalvelimen otsikot(proxy headers), jotka Immichin tulisi lähettää jokaisen verkkopyynnön mukana",
|
||||||
"advanced_settings_proxy_headers_title": "Välityspalvelimen otsikot",
|
"advanced_settings_proxy_headers_title": "Välityspalvelimen otsikot",
|
||||||
|
"advanced_settings_readonly_mode_title": "Vain luku -tila",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Ohita SSL sertifikaattivarmennus palvelimen päätepisteellä. Vaaditaan self-signed -sertifikaateissa.",
|
"advanced_settings_self_signed_ssl_subtitle": "Ohita SSL sertifikaattivarmennus palvelimen päätepisteellä. Vaaditaan self-signed -sertifikaateissa.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Salli self-signed SSL -sertifikaatit",
|
"advanced_settings_self_signed_ssl_title": "Salli self-signed SSL -sertifikaatit",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Poista tai palauta kohde automaattisesti tällä laitteella, kun kyseinen toiminto suoritetaan verkossa",
|
"advanced_settings_sync_remote_deletions_subtitle": "Poista tai palauta kohde automaattisesti tällä laitteella, kun kyseinen toiminto suoritetaan verkossa",
|
||||||
@@ -866,7 +867,7 @@
|
|||||||
"edit_title": "Muokkaa otsikkoa",
|
"edit_title": "Muokkaa otsikkoa",
|
||||||
"edit_user": "Muokkaa käyttäjää",
|
"edit_user": "Muokkaa käyttäjää",
|
||||||
"edited": "Muokattu",
|
"edited": "Muokattu",
|
||||||
"editor": "Editori",
|
"editor": "Muokkaaja",
|
||||||
"editor_close_without_save_prompt": "Muutoksia ei tallenneta",
|
"editor_close_without_save_prompt": "Muutoksia ei tallenneta",
|
||||||
"editor_close_without_save_title": "Suljetaanko editori?",
|
"editor_close_without_save_title": "Suljetaanko editori?",
|
||||||
"editor_crop_tool_h2_aspect_ratios": "Kuvasuhteet",
|
"editor_crop_tool_h2_aspect_ratios": "Kuvasuhteet",
|
||||||
@@ -1633,8 +1634,8 @@
|
|||||||
"review_duplicates": "Tarkastele kaksoiskappaleita",
|
"review_duplicates": "Tarkastele kaksoiskappaleita",
|
||||||
"review_large_files": "Tarkista suuret tiedostot",
|
"review_large_files": "Tarkista suuret tiedostot",
|
||||||
"role": "Rooli",
|
"role": "Rooli",
|
||||||
"role_editor": "Editori",
|
"role_editor": "Muokkaaja",
|
||||||
"role_viewer": "Toistin",
|
"role_viewer": "Katsoja",
|
||||||
"running": "Käynnissä",
|
"running": "Käynnissä",
|
||||||
"save": "Tallenna",
|
"save": "Tallenna",
|
||||||
"save_to_gallery": "Tallenna galleriaan",
|
"save_to_gallery": "Tallenna galleriaan",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Ouvrir les filtres de recherche",
|
"open_the_search_filters": "Ouvrir les filtres de recherche",
|
||||||
"options": "Options",
|
"options": "Options",
|
||||||
"or": "ou",
|
"or": "ou",
|
||||||
|
"organize_into_albums": "Organiser dans des albums",
|
||||||
|
"organize_into_albums_description": "Mettre les photos existantes dans des albums en utilisant les paramètres de synchronisation actuels",
|
||||||
"organize_your_library": "Organiser votre bibliothèque",
|
"organize_your_library": "Organiser votre bibliothèque",
|
||||||
"original": "original",
|
"original": "original",
|
||||||
"other": "Autre",
|
"other": "Autre",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Statut de contributeur",
|
"purchase_server_description_2": "Statut de contributeur",
|
||||||
"purchase_server_title": "Serveur",
|
"purchase_server_title": "Serveur",
|
||||||
"purchase_settings_server_activated": "La clé du produit pour le Serveur est gérée par l'administrateur",
|
"purchase_settings_server_activated": "La clé du produit pour le Serveur est gérée par l'administrateur",
|
||||||
|
"query_asset_id": "ID du média requis",
|
||||||
"queue_status": "{count}/{total} en file d'attente",
|
"queue_status": "{count}/{total} en file d'attente",
|
||||||
"rating": "Étoile d'évaluation",
|
"rating": "Étoile d'évaluation",
|
||||||
"rating_clear": "Effacer l'évaluation",
|
"rating_clear": "Effacer l'évaluation",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Échec de la création de l'album",
|
"select_user_for_sharing_page_err_album": "Échec de la création de l'album",
|
||||||
"selected": "Sélectionné",
|
"selected": "Sélectionné",
|
||||||
"selected_count": "{count, plural, one {# sélectionné} other {# sélectionnés}}",
|
"selected_count": "{count, plural, one {# sélectionné} other {# sélectionnés}}",
|
||||||
"selected_gps_coordinates": "coordonnées GPS sélectionnées",
|
"selected_gps_coordinates": "Coordonnées GPS sélectionnées",
|
||||||
"send_message": "Envoyer un message",
|
"send_message": "Envoyer un message",
|
||||||
"send_welcome_email": "Envoyer un courriel de bienvenue",
|
"send_welcome_email": "Envoyer un courriel de bienvenue",
|
||||||
"server_endpoint": "Adresse du serveur",
|
"server_endpoint": "Adresse du serveur",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Voir le média suivant",
|
"view_next_asset": "Voir le média suivant",
|
||||||
"view_previous_asset": "Voir le média précédent",
|
"view_previous_asset": "Voir le média précédent",
|
||||||
"view_qr_code": "Voir le QR code",
|
"view_qr_code": "Voir le QR code",
|
||||||
|
"view_similar_photos": "Voir les photos similaires",
|
||||||
"view_stack": "Afficher la pile",
|
"view_stack": "Afficher la pile",
|
||||||
"view_user": "Voir l'utilisateur",
|
"view_user": "Voir l'utilisateur",
|
||||||
"viewer_remove_from_stack": "Retirer de la pile",
|
"viewer_remove_from_stack": "Retirer de la pile",
|
||||||
|
|||||||
22
i18n/he.json
22
i18n/he.json
@@ -396,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "העדף תמונות מרוחקות",
|
"advanced_settings_prefer_remote_title": "העדף תמונות מרוחקות",
|
||||||
"advanced_settings_proxy_headers_subtitle": "הגדר proxy headers שהיישום צריך לשלוח עם כל בקשת רשת",
|
"advanced_settings_proxy_headers_subtitle": "הגדר proxy headers שהיישום צריך לשלוח עם כל בקשת רשת",
|
||||||
"advanced_settings_proxy_headers_title": "כותרות פרוקסי",
|
"advanced_settings_proxy_headers_title": "כותרות פרוקסי",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "מאפשר את מצב לקריאה בלבד בו התמונות ניתנות לצפייה בלבד, דברים כמו בחירת תמונות מרובות, שיתוף, שידור, מחיקה הם כולם מושבתים. אפשר/השבת מצב לקריאה בלבד באמצעות יצגן המשתמש מהמסך הראשי",
|
||||||
|
"advanced_settings_readonly_mode_title": "מצב לקריאה בלבד",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "מדלג על אימות תעודת SSL עבור נקודת הקצה של השרת. דרוש עבור תעודות בחתימה עצמית.",
|
"advanced_settings_self_signed_ssl_subtitle": "מדלג על אימות תעודת SSL עבור נקודת הקצה של השרת. דרוש עבור תעודות בחתימה עצמית.",
|
||||||
"advanced_settings_self_signed_ssl_title": "התר תעודות SSL בחתימה עצמית",
|
"advanced_settings_self_signed_ssl_title": "התר תעודות SSL בחתימה עצמית",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "מחק או שחזר תמונה במכשיר זה באופן אוטומטי כאשר פעולה זו נעשית בדפדפן",
|
"advanced_settings_sync_remote_deletions_subtitle": "מחק או שחזר תמונה במכשיר זה באופן אוטומטי כאשר פעולה זו נעשית בדפדפן",
|
||||||
@@ -461,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "התנתק",
|
"app_bar_signout_dialog_title": "התנתק",
|
||||||
"app_settings": "הגדרות יישום",
|
"app_settings": "הגדרות יישום",
|
||||||
"appears_in": "מופיע ב",
|
"appears_in": "מופיע ב",
|
||||||
|
"apply_count": "החל ({count, number})",
|
||||||
"archive": "ארכיון",
|
"archive": "ארכיון",
|
||||||
"archive_action_prompt": "{count} נוספו לארכיון",
|
"archive_action_prompt": "{count} נוספו לארכיון",
|
||||||
"archive_or_unarchive_photo": "העבר תמונה לארכיון או הוצא אותה משם",
|
"archive_or_unarchive_photo": "העבר תמונה לארכיון או הוצא אותה משם",
|
||||||
@@ -842,7 +845,7 @@
|
|||||||
"duration": "משך זמן",
|
"duration": "משך זמן",
|
||||||
"edit": "ערוך",
|
"edit": "ערוך",
|
||||||
"edit_album": "ערוך אלבום",
|
"edit_album": "ערוך אלבום",
|
||||||
"edit_avatar": "ערוך תמונת פרופיל",
|
"edit_avatar": "ערוך יצגן",
|
||||||
"edit_birthday": "עריכת יום הולדת",
|
"edit_birthday": "עריכת יום הולדת",
|
||||||
"edit_date": "ערוך תאריך",
|
"edit_date": "ערוך תאריך",
|
||||||
"edit_date_and_time": "ערוך תאריך ושעה",
|
"edit_date_and_time": "ערוך תאריך ושעה",
|
||||||
@@ -1073,12 +1076,18 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "תכונה זאת טוענת משאבים חיצוניים מגוגל בכדי לפעול.",
|
"gcast_enabled_description": "תכונה זאת טוענת משאבים חיצוניים מגוגל בכדי לפעול.",
|
||||||
"general": "כללי",
|
"general": "כללי",
|
||||||
|
"geolocation_instruction_all_have_location": "לכל הפריטים עבור תאריך זה כבר יש נתוני מיקום. נסה להציג את כל הפריטים או בחר תאריך אחר",
|
||||||
|
"geolocation_instruction_location": "לחץ על פריט עם קואורדינטות GPS כדי להשתמש במיקומו, או בחר מיקום ישירות מהמפה",
|
||||||
|
"geolocation_instruction_no_date": "בחר תאריך כדי לנהל נתוני מיקום עבור תמונות וסרטונים מאותו יום",
|
||||||
|
"geolocation_instruction_no_photos": "לא נמצאו תמונות או סרטונים עבור תאריך זה. בחר תאריך אחר כדי להציג אותם",
|
||||||
"get_help": "קבל עזרה",
|
"get_help": "קבל עזרה",
|
||||||
"get_wifiname_error": "לא היה ניתן לקבל את שם האינטרנט האלחוטי שלך. יש לודא שהענקת את ההרשאות הדרושות ושאת/ה מחובר/ת לרשת אינטרנט אלחוטי",
|
"get_wifiname_error": "לא היה ניתן לקבל את שם האינטרנט האלחוטי שלך. יש לודא שהענקת את ההרשאות הדרושות ושאת/ה מחובר/ת לרשת אינטרנט אלחוטי",
|
||||||
"getting_started": "תחילת העבודה",
|
"getting_started": "תחילת העבודה",
|
||||||
"go_back": "חזור",
|
"go_back": "חזור",
|
||||||
"go_to_folder": "עבור לתיקיה",
|
"go_to_folder": "עבור לתיקיה",
|
||||||
"go_to_search": "עבור לחיפוש",
|
"go_to_search": "עבור לחיפוש",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "אין GPS",
|
||||||
"grant_permission": "להעניק הרשאה",
|
"grant_permission": "להעניק הרשאה",
|
||||||
"group_albums_by": "קבץ אלבומים לפי..",
|
"group_albums_by": "קבץ אלבומים לפי..",
|
||||||
"group_country": "קבץ לפי מדינה",
|
"group_country": "קבץ לפי מדינה",
|
||||||
@@ -1262,6 +1271,7 @@
|
|||||||
"main_branch_warning": "הגרסה המותקנת היא גרסת פיתוח; אנחנו ממליצים בחום להשתמש בגרסה יציבה!",
|
"main_branch_warning": "הגרסה המותקנת היא גרסת פיתוח; אנחנו ממליצים בחום להשתמש בגרסה יציבה!",
|
||||||
"main_menu": "תפריט ראשי",
|
"main_menu": "תפריט ראשי",
|
||||||
"make": "תוצרת",
|
"make": "תוצרת",
|
||||||
|
"manage_geolocation": "נהל מיקום",
|
||||||
"manage_shared_links": "ניהול קישורים משותפים",
|
"manage_shared_links": "ניהול קישורים משותפים",
|
||||||
"manage_sharing_with_partners": "ניהול שיתוף עם שותפים",
|
"manage_sharing_with_partners": "ניהול שיתוף עם שותפים",
|
||||||
"manage_the_app_settings": "ניהול הגדרות האפליקציה",
|
"manage_the_app_settings": "ניהול הגדרות האפליקציה",
|
||||||
@@ -1508,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "גרסת היישום לנייד מיושנת. נא לעדכן לגרסה המשנית האחרונה.",
|
"profile_drawer_client_out_of_date_minor": "גרסת היישום לנייד מיושנת. נא לעדכן לגרסה המשנית האחרונה.",
|
||||||
"profile_drawer_client_server_up_to_date": "היישום והשרת מעודכנים",
|
"profile_drawer_client_server_up_to_date": "היישום והשרת מעודכנים",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "מצב לקריאה בלבד מופעל. הקש הקשה כפולה על סמל היצגן של המשתמש כדי לצאת.",
|
||||||
"profile_drawer_server_out_of_date_major": "השרת אינו מעודכן. נא לעדכן לגרסה הראשית האחרונה.",
|
"profile_drawer_server_out_of_date_major": "השרת אינו מעודכן. נא לעדכן לגרסה הראשית האחרונה.",
|
||||||
"profile_drawer_server_out_of_date_minor": "השרת אינו מעודכן. נא לעדכן לגרסה המשנית האחרונה.",
|
"profile_drawer_server_out_of_date_minor": "השרת אינו מעודכן. נא לעדכן לגרסה המשנית האחרונה.",
|
||||||
"profile_image_of_user": "תמונת פרופיל של {user}",
|
"profile_image_of_user": "תמונת פרופיל של {user}",
|
||||||
@@ -1553,6 +1564,8 @@
|
|||||||
"rating_description": "הצג את דירוג ה-EXIF בלוח המידע",
|
"rating_description": "הצג את דירוג ה-EXIF בלוח המידע",
|
||||||
"reaction_options": "אפשרויות הגבה",
|
"reaction_options": "אפשרויות הגבה",
|
||||||
"read_changelog": "קרא את יומן השינויים",
|
"read_changelog": "קרא את יומן השינויים",
|
||||||
|
"readonly_mode_disabled": "מצב לקריאה בלבד מושבת",
|
||||||
|
"readonly_mode_enabled": "מצב לקריאה בלבד מופעל",
|
||||||
"reassign": "הקצה מחדש",
|
"reassign": "הקצה מחדש",
|
||||||
"reassigned_assets_to_existing_person": "{count, plural, one {תמונה # הוקצתה} other {# תמונות הוקצו}} מחדש אל {name, select, null {אדם קיים} other {{name}}}",
|
"reassigned_assets_to_existing_person": "{count, plural, one {תמונה # הוקצתה} other {# תמונות הוקצו}} מחדש אל {name, select, null {אדם קיים} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "{count, plural, one {תמונה # הוקצתה} other {# תמונות הוקצו}} מחדש לאדם חדש",
|
"reassigned_assets_to_new_person": "{count, plural, one {תמונה # הוקצתה} other {# תמונות הוקצו}} מחדש לאדם חדש",
|
||||||
@@ -1709,7 +1722,7 @@
|
|||||||
"select_all": "בחר הכל",
|
"select_all": "בחר הכל",
|
||||||
"select_all_duplicates": "בחר את כל הכפילויות",
|
"select_all_duplicates": "בחר את כל הכפילויות",
|
||||||
"select_all_in": "בחר הכול בתוך {group}",
|
"select_all_in": "בחר הכול בתוך {group}",
|
||||||
"select_avatar_color": "בחר צבע תמונת פרופיל",
|
"select_avatar_color": "בחר צבע יצגן",
|
||||||
"select_face": "בחר פנים",
|
"select_face": "בחר פנים",
|
||||||
"select_featured_photo": "בחר תמונה מייצגת",
|
"select_featured_photo": "בחר תמונה מייצגת",
|
||||||
"select_from_computer": "בחר מהמחשב",
|
"select_from_computer": "בחר מהמחשב",
|
||||||
@@ -1722,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "יצירת אלבום נכשלה",
|
"select_user_for_sharing_page_err_album": "יצירת אלבום נכשלה",
|
||||||
"selected": "נבחרו",
|
"selected": "נבחרו",
|
||||||
"selected_count": "{count, plural, other {# נבחרו}}",
|
"selected_count": "{count, plural, other {# נבחרו}}",
|
||||||
|
"selected_gps_coordinates": "קואורדינטות GPS שנבחרו",
|
||||||
"send_message": "שלח הודעה",
|
"send_message": "שלח הודעה",
|
||||||
"send_welcome_email": "שלח דוא\"ל קבלת פנים",
|
"send_welcome_email": "שלח דוא\"ל קבלת פנים",
|
||||||
"server_endpoint": "נקודת קצה שרת",
|
"server_endpoint": "נקודת קצה שרת",
|
||||||
@@ -1832,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "לחץ ⇧ כדי למחוק תמונה לצמיתות",
|
"shift_to_permanent_delete": "לחץ ⇧ כדי למחוק תמונה לצמיתות",
|
||||||
"show_album_options": "הצג אפשרויות אלבום",
|
"show_album_options": "הצג אפשרויות אלבום",
|
||||||
"show_albums": "הצג אלבומים",
|
"show_albums": "הצג אלבומים",
|
||||||
|
"show_all_assets": "הצג את כל הפריטים",
|
||||||
"show_all_people": "הצג את כל האנשים",
|
"show_all_people": "הצג את כל האנשים",
|
||||||
"show_and_hide_people": "הצג & הסתר אנשים",
|
"show_and_hide_people": "הצג & הסתר אנשים",
|
||||||
|
"show_assets_without_location": "הצג פריטים ללא מיקום",
|
||||||
"show_file_location": "הצג את מיקום הקובץ",
|
"show_file_location": "הצג את מיקום הקובץ",
|
||||||
"show_gallery": "הצג גלריה",
|
"show_gallery": "הצג גלריה",
|
||||||
"show_hidden_people": "הצג אנשים מוסתרים",
|
"show_hidden_people": "הצג אנשים מוסתרים",
|
||||||
@@ -1993,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "{count, plural, one {תמונה # הוסרה} other {# תמונות הוסרו}} מהערימה",
|
"unstacked_assets_count": "{count, plural, one {תמונה # הוסרה} other {# תמונות הוסרו}} מהערימה",
|
||||||
"untagged": "לא מתיוגים",
|
"untagged": "לא מתיוגים",
|
||||||
"up_next": "הבא בתור",
|
"up_next": "הבא בתור",
|
||||||
|
"update_location_action_prompt": "עדכן את המיקום של {count} פריטים שנבחרו עם:",
|
||||||
"updated_at": "עודכן",
|
"updated_at": "עודכן",
|
||||||
"updated_password": "סיסמה עודכנה",
|
"updated_password": "סיסמה עודכנה",
|
||||||
"upload": "העלאה",
|
"upload": "העלאה",
|
||||||
@@ -2017,6 +2034,7 @@
|
|||||||
"use_biometric": "השתמש באימות ביומטרי",
|
"use_biometric": "השתמש באימות ביומטרי",
|
||||||
"use_current_connection": "השתמש בחיבור נוכחי",
|
"use_current_connection": "השתמש בחיבור נוכחי",
|
||||||
"use_custom_date_range": "השתמש בטווח תאריכים מותאם במקום",
|
"use_custom_date_range": "השתמש בטווח תאריכים מותאם במקום",
|
||||||
|
"use_this_location": "לחץ כדי להשתמש במיקום",
|
||||||
"user": "משתמש",
|
"user": "משתמש",
|
||||||
"user_has_been_deleted": "משתמש זה נמחק.",
|
"user_has_been_deleted": "משתמש זה נמחק.",
|
||||||
"user_id": "מזהה משתמש",
|
"user_id": "מזהה משתמש",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"add_to_album": "Tambahkan ke album",
|
"add_to_album": "Tambahkan ke album",
|
||||||
"add_to_album_bottom_sheet_added": "Ditambahkan ke {album}",
|
"add_to_album_bottom_sheet_added": "Ditambahkan ke {album}",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Sudah ada di {album}",
|
"add_to_album_bottom_sheet_already_exists": "Sudah ada di {album}",
|
||||||
|
"add_to_albums": "Tambahkan ke album",
|
||||||
"add_to_shared_album": "Tambahkan ke album terbagi",
|
"add_to_shared_album": "Tambahkan ke album terbagi",
|
||||||
"add_url": "Tambahkan URL",
|
"add_url": "Tambahkan URL",
|
||||||
"added_to_archive": "Ditambahkan ke arsip",
|
"added_to_archive": "Ditambahkan ke arsip",
|
||||||
|
|||||||
22
i18n/it.json
22
i18n/it.json
@@ -392,10 +392,12 @@
|
|||||||
"advanced_settings_enable_alternate_media_filter_subtitle": "Usa questa opzione per filtrare i contenuti multimediali durante la sincronizzazione in base a criteri alternativi. Prova questa opzione solo se riscontri problemi con il rilevamento di tutti gli album da parte dell'app.",
|
"advanced_settings_enable_alternate_media_filter_subtitle": "Usa questa opzione per filtrare i contenuti multimediali durante la sincronizzazione in base a criteri alternativi. Prova questa opzione solo se riscontri problemi con il rilevamento di tutti gli album da parte dell'app.",
|
||||||
"advanced_settings_enable_alternate_media_filter_title": "[SPERIMENTALE] Usa un filtro alternativo per la sincronizzazione degli album del dispositivo",
|
"advanced_settings_enable_alternate_media_filter_title": "[SPERIMENTALE] Usa un filtro alternativo per la sincronizzazione degli album del dispositivo",
|
||||||
"advanced_settings_log_level_title": "Livello log: {level}",
|
"advanced_settings_log_level_title": "Livello log: {level}",
|
||||||
"advanced_settings_prefer_remote_subtitle": "Alcuni dispositivi sono molto lenti a caricare le anteprime delle immagini locali. Attivare questa impostazione per caricare invece le immagini remote.",
|
"advanced_settings_prefer_remote_subtitle": "Alcuni dispositivi sono estremamente lenti a caricare le miniature da risorse locali. Attiva questa impostazione per caricare invece le immagini remote.",
|
||||||
"advanced_settings_prefer_remote_title": "Preferisci immagini remote",
|
"advanced_settings_prefer_remote_title": "Preferisci immagini remote",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Definisci gli header per i proxy che Immich dovrebbe inviare con ogni richiesta di rete",
|
"advanced_settings_proxy_headers_subtitle": "Definisci gli header per i proxy che Immich dovrebbe inviare con ogni richiesta di rete",
|
||||||
"advanced_settings_proxy_headers_title": "Header Proxy",
|
"advanced_settings_proxy_headers_title": "Header Proxy",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Abilita la modalità di sola lettura in cui le foto possono essere solo visualizzate, mentre funzioni come la selezione di più immagini, la condivisione, la trasmissione e l'eliminazione sono tutte disabilitate. Abilita/Disabilita la sola lettura tramite l'avatar dell'utente dalla schermata principale",
|
||||||
|
"advanced_settings_readonly_mode_title": "Modalità di sola lettura",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Salta la verifica dei certificati SSL del server. Richiesto con l'uso di certificati self-signed.",
|
"advanced_settings_self_signed_ssl_subtitle": "Salta la verifica dei certificati SSL del server. Richiesto con l'uso di certificati self-signed.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Consenti certificati SSL self-signed",
|
"advanced_settings_self_signed_ssl_title": "Consenti certificati SSL self-signed",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Rimuovi o ripristina automaticamente un elemento su questo dispositivo quando l'azione è stata fatta via web",
|
"advanced_settings_sync_remote_deletions_subtitle": "Rimuovi o ripristina automaticamente un elemento su questo dispositivo quando l'azione è stata fatta via web",
|
||||||
@@ -461,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Disconnetti",
|
"app_bar_signout_dialog_title": "Disconnetti",
|
||||||
"app_settings": "Impostazioni Applicazione",
|
"app_settings": "Impostazioni Applicazione",
|
||||||
"appears_in": "Compare in",
|
"appears_in": "Compare in",
|
||||||
|
"apply_count": "Applica ({count, number})",
|
||||||
"archive": "Archivio",
|
"archive": "Archivio",
|
||||||
"archive_action_prompt": "Aggiunti {count} elementi all'Archivio",
|
"archive_action_prompt": "Aggiunti {count} elementi all'Archivio",
|
||||||
"archive_or_unarchive_photo": "Archivia o ripristina foto",
|
"archive_or_unarchive_photo": "Archivia o ripristina foto",
|
||||||
@@ -1073,12 +1076,18 @@
|
|||||||
"gcast_enabled": "Google Cast Abilitato",
|
"gcast_enabled": "Google Cast Abilitato",
|
||||||
"gcast_enabled_description": "Questa funzione carica risorse esterne da Google per poter funzionare.",
|
"gcast_enabled_description": "Questa funzione carica risorse esterne da Google per poter funzionare.",
|
||||||
"general": "Generale",
|
"general": "Generale",
|
||||||
|
"geolocation_instruction_all_have_location": "Tutte le risorse per questa data hanno già dati sulla posizione. Prova a mostrare tutte le risorse o seleziona una data diversa",
|
||||||
|
"geolocation_instruction_location": "Fai clic su una risorsa con coordinate GPS per utilizzare la sua posizione oppure seleziona una posizione direttamente dalla mappa",
|
||||||
|
"geolocation_instruction_no_date": "Seleziona una data per gestire i dati sulla posizione per foto e video di quel giorno",
|
||||||
|
"geolocation_instruction_no_photos": "Nessuna foto o video trovato per questa data. Seleziona una data diversa per visualizzarli",
|
||||||
"get_help": "Chiedi Aiuto",
|
"get_help": "Chiedi Aiuto",
|
||||||
"get_wifiname_error": "Non sono riuscito a recuperare il nome della rete Wi-Fi. Accertati di aver concesso i permessi necessari e di essere connesso ad una rete Wi-Fi",
|
"get_wifiname_error": "Non sono riuscito a recuperare il nome della rete Wi-Fi. Accertati di aver concesso i permessi necessari e di essere connesso ad una rete Wi-Fi",
|
||||||
"getting_started": "Iniziamo",
|
"getting_started": "Iniziamo",
|
||||||
"go_back": "Torna indietro",
|
"go_back": "Torna indietro",
|
||||||
"go_to_folder": "Vai alla cartella",
|
"go_to_folder": "Vai alla cartella",
|
||||||
"go_to_search": "Vai alla ricerca",
|
"go_to_search": "Vai alla ricerca",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "No GPS",
|
||||||
"grant_permission": "Concedi permesso",
|
"grant_permission": "Concedi permesso",
|
||||||
"group_albums_by": "Raggruppa album in base a...",
|
"group_albums_by": "Raggruppa album in base a...",
|
||||||
"group_country": "Raggruppa per paese",
|
"group_country": "Raggruppa per paese",
|
||||||
@@ -1181,7 +1190,7 @@
|
|||||||
"language": "Lingua",
|
"language": "Lingua",
|
||||||
"language_no_results_subtitle": "Prova a cambiare i tuoi termini di ricerca",
|
"language_no_results_subtitle": "Prova a cambiare i tuoi termini di ricerca",
|
||||||
"language_no_results_title": "Linguaggi non trovati",
|
"language_no_results_title": "Linguaggi non trovati",
|
||||||
"language_search_hint": "Cerca linguaggi...",
|
"language_search_hint": "Cerca una lingua...",
|
||||||
"language_setting_description": "Seleziona la tua lingua predefinita",
|
"language_setting_description": "Seleziona la tua lingua predefinita",
|
||||||
"large_files": "File pesanti",
|
"large_files": "File pesanti",
|
||||||
"last": "Ultimo",
|
"last": "Ultimo",
|
||||||
@@ -1262,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Stai utilizzando una versione di sviluppo. Ti consigliamo vivamente di utilizzare una versione di rilascio!",
|
"main_branch_warning": "Stai utilizzando una versione di sviluppo. Ti consigliamo vivamente di utilizzare una versione di rilascio!",
|
||||||
"main_menu": "Menu Principale",
|
"main_menu": "Menu Principale",
|
||||||
"make": "Produttore",
|
"make": "Produttore",
|
||||||
|
"manage_geolocation": "Gestisci posizione",
|
||||||
"manage_shared_links": "Gestisci link condivisi",
|
"manage_shared_links": "Gestisci link condivisi",
|
||||||
"manage_sharing_with_partners": "Gestisci la condivisione con i compagni",
|
"manage_sharing_with_partners": "Gestisci la condivisione con i compagni",
|
||||||
"manage_the_app_settings": "Gestisci le impostazioni dell'applicazione",
|
"manage_the_app_settings": "Gestisci le impostazioni dell'applicazione",
|
||||||
@@ -1508,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "L'applicazione non è aggiornata. Aggiorna all'ultima versione minore.",
|
"profile_drawer_client_out_of_date_minor": "L'applicazione non è aggiornata. Aggiorna all'ultima versione minore.",
|
||||||
"profile_drawer_client_server_up_to_date": "Client e server sono aggiornati",
|
"profile_drawer_client_server_up_to_date": "Client e server sono aggiornati",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Modalità di sola lettura abilitata. Tocca due volte l'icona dell'avatar dell'utente per disabilitarla.",
|
||||||
"profile_drawer_server_out_of_date_major": "Il server non è aggiornato. Aggiorna all'ultima versione principale.",
|
"profile_drawer_server_out_of_date_major": "Il server non è aggiornato. Aggiorna all'ultima versione principale.",
|
||||||
"profile_drawer_server_out_of_date_minor": "Il server non è aggiornato. Aggiorna all'ultima versione minore.",
|
"profile_drawer_server_out_of_date_minor": "Il server non è aggiornato. Aggiorna all'ultima versione minore.",
|
||||||
"profile_image_of_user": "Immagine profilo di {user}",
|
"profile_image_of_user": "Immagine profilo di {user}",
|
||||||
@@ -1553,6 +1564,8 @@
|
|||||||
"rating_description": "Visualizza la valutazione EXIF nel pannello informazioni",
|
"rating_description": "Visualizza la valutazione EXIF nel pannello informazioni",
|
||||||
"reaction_options": "Impostazioni Reazioni",
|
"reaction_options": "Impostazioni Reazioni",
|
||||||
"read_changelog": "Leggi Riepilogo Modifiche",
|
"read_changelog": "Leggi Riepilogo Modifiche",
|
||||||
|
"readonly_mode_disabled": "Modalità di sola lettura disabilitata",
|
||||||
|
"readonly_mode_enabled": "Modalità di sola lettura abilitata",
|
||||||
"reassign": "Riassegna",
|
"reassign": "Riassegna",
|
||||||
"reassigned_assets_to_existing_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} {name, select, null {ad una persona esistente} other {a {name}}}",
|
"reassigned_assets_to_existing_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} {name, select, null {ad una persona esistente} other {a {name}}}",
|
||||||
"reassigned_assets_to_new_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} ad una nuova persona",
|
"reassigned_assets_to_new_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} ad una nuova persona",
|
||||||
@@ -1722,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Impossibile nel creare l'album",
|
"select_user_for_sharing_page_err_album": "Impossibile nel creare l'album",
|
||||||
"selected": "Selezionato",
|
"selected": "Selezionato",
|
||||||
"selected_count": "{count, plural, one {# selezionato} other {# selezionati}}",
|
"selected_count": "{count, plural, one {# selezionato} other {# selezionati}}",
|
||||||
|
"selected_gps_coordinates": "coordinate GPS selezionate",
|
||||||
"send_message": "Manda messaggio",
|
"send_message": "Manda messaggio",
|
||||||
"send_welcome_email": "Invia email di benvenuto",
|
"send_welcome_email": "Invia email di benvenuto",
|
||||||
"server_endpoint": "Server endpoint",
|
"server_endpoint": "Server endpoint",
|
||||||
@@ -1832,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "premi ⇧ per cancellare definitivamente l'asset",
|
"shift_to_permanent_delete": "premi ⇧ per cancellare definitivamente l'asset",
|
||||||
"show_album_options": "Mostra opzioni album",
|
"show_album_options": "Mostra opzioni album",
|
||||||
"show_albums": "Mostra gli album",
|
"show_albums": "Mostra gli album",
|
||||||
|
"show_all_assets": "Mostra tutte le risorse",
|
||||||
"show_all_people": "Mostra tutte le persone",
|
"show_all_people": "Mostra tutte le persone",
|
||||||
"show_and_hide_people": "Mostra & nascondi persone",
|
"show_and_hide_people": "Mostra & nascondi persone",
|
||||||
|
"show_assets_without_location": "Mostra risorse senza posizione",
|
||||||
"show_file_location": "Mostra percorso file",
|
"show_file_location": "Mostra percorso file",
|
||||||
"show_gallery": "Mostra galleria",
|
"show_gallery": "Mostra galleria",
|
||||||
"show_hidden_people": "Mostra persone nascoste",
|
"show_hidden_people": "Mostra persone nascoste",
|
||||||
@@ -1993,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "{count, plural, one {Separato # asset} other {Separati # asset}}",
|
"unstacked_assets_count": "{count, plural, one {Separato # asset} other {Separati # asset}}",
|
||||||
"untagged": "Senza tag",
|
"untagged": "Senza tag",
|
||||||
"up_next": "Prossimo",
|
"up_next": "Prossimo",
|
||||||
|
"update_location_action_prompt": "Aggiorna la posizione di {count} risorse selezionate con:",
|
||||||
"updated_at": "Aggiornato il",
|
"updated_at": "Aggiornato il",
|
||||||
"updated_password": "Password aggiornata",
|
"updated_password": "Password aggiornata",
|
||||||
"upload": "Carica",
|
"upload": "Carica",
|
||||||
@@ -2017,6 +2034,7 @@
|
|||||||
"use_biometric": "Usa biometrica",
|
"use_biometric": "Usa biometrica",
|
||||||
"use_current_connection": "usa la connessione attuale",
|
"use_current_connection": "usa la connessione attuale",
|
||||||
"use_custom_date_range": "Altrimenti utilizza un intervallo date personalizzato",
|
"use_custom_date_range": "Altrimenti utilizza un intervallo date personalizzato",
|
||||||
|
"use_this_location": "Clicca per usare la posizione",
|
||||||
"user": "Utente",
|
"user": "Utente",
|
||||||
"user_has_been_deleted": "L'utente è stato rimosso.",
|
"user_has_been_deleted": "L'utente è stato rimosso.",
|
||||||
"user_id": "ID utente",
|
"user_id": "ID utente",
|
||||||
|
|||||||
@@ -392,7 +392,7 @@
|
|||||||
"advanced_settings_enable_alternate_media_filter_subtitle": "別の基準に従ってメディアファイルにフィルターをかけて、同期を行います。アプリがすべてのアルバムを読み込んでくれない場合にのみ、この機能を試してください。",
|
"advanced_settings_enable_alternate_media_filter_subtitle": "別の基準に従ってメディアファイルにフィルターをかけて、同期を行います。アプリがすべてのアルバムを読み込んでくれない場合にのみ、この機能を試してください。",
|
||||||
"advanced_settings_enable_alternate_media_filter_title": "[試験運用] 別のデバイスのアルバム同期フィルターを使用する",
|
"advanced_settings_enable_alternate_media_filter_title": "[試験運用] 別のデバイスのアルバム同期フィルターを使用する",
|
||||||
"advanced_settings_log_level_title": "ログレベル: {level}",
|
"advanced_settings_log_level_title": "ログレベル: {level}",
|
||||||
"advanced_settings_prefer_remote_subtitle": "デバイスによっては、デバイス上にあるサムネイルのロードに非常に時間がかかることがあります。このオプションをに有効にする事により、サーバーから直接画像をロードすることが可能です。",
|
"advanced_settings_prefer_remote_subtitle": "デバイスによっては、デバイス上にあるサムネイルのロードに非常に時間がかかることがあります。このオプションを有効にする事により、サーバーから直接画像をロードすることが可能です。",
|
||||||
"advanced_settings_prefer_remote_title": "リモートを優先する",
|
"advanced_settings_prefer_remote_title": "リモートを優先する",
|
||||||
"advanced_settings_proxy_headers_subtitle": "プロキシヘッダを設定する",
|
"advanced_settings_proxy_headers_subtitle": "プロキシヘッダを設定する",
|
||||||
"advanced_settings_proxy_headers_title": "プロキシヘッダ",
|
"advanced_settings_proxy_headers_title": "プロキシヘッダ",
|
||||||
|
|||||||
@@ -1081,6 +1081,8 @@
|
|||||||
"go_back": "뒤로",
|
"go_back": "뒤로",
|
||||||
"go_to_folder": "폴더로 이동",
|
"go_to_folder": "폴더로 이동",
|
||||||
"go_to_search": "검색으로 이동",
|
"go_to_search": "검색으로 이동",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "GPS 없음",
|
||||||
"grant_permission": "권한 부여",
|
"grant_permission": "권한 부여",
|
||||||
"group_albums_by": "다음으로 앨범 그룹화...",
|
"group_albums_by": "다음으로 앨범 그룹화...",
|
||||||
"group_country": "국가별로 그룹화",
|
"group_country": "국가별로 그룹화",
|
||||||
@@ -1264,6 +1266,7 @@
|
|||||||
"main_branch_warning": "개발 버전을 사용 중입니다. 정식 릴리스 버전 사용을 권장합니다!",
|
"main_branch_warning": "개발 버전을 사용 중입니다. 정식 릴리스 버전 사용을 권장합니다!",
|
||||||
"main_menu": "메인 메뉴",
|
"main_menu": "메인 메뉴",
|
||||||
"make": "제조사",
|
"make": "제조사",
|
||||||
|
"manage_geolocation": "위치 정보 관리",
|
||||||
"manage_shared_links": "공유 링크 관리",
|
"manage_shared_links": "공유 링크 관리",
|
||||||
"manage_sharing_with_partners": "공유할 파트너를 초대하거나 제거합니다.",
|
"manage_sharing_with_partners": "공유할 파트너를 초대하거나 제거합니다.",
|
||||||
"manage_the_app_settings": "앱 동작 및 표시 환경을 사용자 정의합니다.",
|
"manage_the_app_settings": "앱 동작 및 표시 환경을 사용자 정의합니다.",
|
||||||
|
|||||||
46
i18n/lv.json
46
i18n/lv.json
@@ -156,13 +156,18 @@
|
|||||||
"password_enable_description": "Pieteikšanās ar e-pasta adresi un paroli",
|
"password_enable_description": "Pieteikšanās ar e-pasta adresi un paroli",
|
||||||
"password_settings": "Pieteikšanās ar paroli",
|
"password_settings": "Pieteikšanās ar paroli",
|
||||||
"password_settings_description": "Pieteikšanās ar paroli iestatījumu pārvaldība",
|
"password_settings_description": "Pieteikšanās ar paroli iestatījumu pārvaldība",
|
||||||
|
"paths_validated_successfully": "Visi ceļi veiksmīgi pārbaudīti",
|
||||||
"person_cleanup_job": "Personu tīrīšana",
|
"person_cleanup_job": "Personu tīrīšana",
|
||||||
"quota_size_gib": "Kvotas izmērs (GiB)",
|
"quota_size_gib": "Kvotas izmērs (GiB)",
|
||||||
"refreshing_all_libraries": "Atsvaidzina visas bibliotēkas",
|
"refreshing_all_libraries": "Atsvaidzina visas bibliotēkas",
|
||||||
"registration": "Administratora reģistrācija",
|
"registration": "Administratora reģistrācija",
|
||||||
|
"registration_description": "Tā kā tu esi pirmais sistēmas lietotājs, tev tiks piešķirts administratora statuss un tu būsi atbildīgs par administrēšanas uzdevumiem, kā arī par citu lietotāju izveidi.",
|
||||||
"require_password_change_on_login": "Pieprasīt lietotājam mainīt paroli pēc pirmās pieteikšanās",
|
"require_password_change_on_login": "Pieprasīt lietotājam mainīt paroli pēc pirmās pieteikšanās",
|
||||||
|
"reset_settings_to_default": "Atjaunot iestatījumus uz noklusējuma vērtībām",
|
||||||
|
"reset_settings_to_recent_saved": "Atjaunot iestatījumus uz pēdējiem saglabātajiem iestatījumiem",
|
||||||
"scanning_library": "Skenē bibliotēku",
|
"scanning_library": "Skenē bibliotēku",
|
||||||
"search_jobs": "Meklēt uzdevumus…",
|
"search_jobs": "Meklēt uzdevumus…",
|
||||||
|
"send_welcome_email": "Nosūtīt sveiciena e-pastu",
|
||||||
"server_external_domain_settings": "Ārējais domēns",
|
"server_external_domain_settings": "Ārējais domēns",
|
||||||
"server_external_domain_settings_description": "Domēns publiski kopīgotajām saitēm, iekļaujot http(s)://",
|
"server_external_domain_settings_description": "Domēns publiski kopīgotajām saitēm, iekļaujot http(s)://",
|
||||||
"server_public_users": "Publiski lietotāji",
|
"server_public_users": "Publiski lietotāji",
|
||||||
@@ -187,6 +192,7 @@
|
|||||||
"theme_custom_css_settings_description": "Cascading Style Sheets ļauj pielāgot Immich izskatu.",
|
"theme_custom_css_settings_description": "Cascading Style Sheets ļauj pielāgot Immich izskatu.",
|
||||||
"theme_settings_description": "Immich tīmekļa saskarnes pielāgojumu pārvaldība",
|
"theme_settings_description": "Immich tīmekļa saskarnes pielāgojumu pārvaldība",
|
||||||
"thumbnail_generation_job": "Sīktēlu ģenerēšana",
|
"thumbnail_generation_job": "Sīktēlu ģenerēšana",
|
||||||
|
"thumbnail_generation_job_description": "Izveidot lielu, mazu un izplūdušu sīktēlu katram failam, kā arī sīktēlu katrai personai",
|
||||||
"transcoding_acceleration_api": "Paātrināšanas API",
|
"transcoding_acceleration_api": "Paātrināšanas API",
|
||||||
"transcoding_acceleration_nvenc": "NVENC (nepieciešams NVIDIA GPU)",
|
"transcoding_acceleration_nvenc": "NVENC (nepieciešams NVIDIA GPU)",
|
||||||
"transcoding_acceleration_qsv": "Quick Sync (nepieciešams 7. paaudzes vai jaunāks Intel procesors)",
|
"transcoding_acceleration_qsv": "Quick Sync (nepieciešams 7. paaudzes vai jaunāks Intel procesors)",
|
||||||
@@ -205,10 +211,13 @@
|
|||||||
"trash_number_of_days": "Dienu skaits",
|
"trash_number_of_days": "Dienu skaits",
|
||||||
"trash_settings": "Atkritnes iestatījumi",
|
"trash_settings": "Atkritnes iestatījumi",
|
||||||
"trash_settings_description": "Atkritnes iestatījumu pārvaldība",
|
"trash_settings_description": "Atkritnes iestatījumu pārvaldība",
|
||||||
|
"user_delete_delay_settings": "Dzēšanas aizture",
|
||||||
"user_delete_delay_settings_description": "Dienu skaits pēc izdzēšanas, kad neatgriezeniski tiks dzēsti lietotāja konti un faili. Lietotāju dzēšanas uzdevums tiek izpildīts pusnaktī un pārbauda, kuri lietotāji ir gatavi dzēšanai. Izmaiņas šajā iestatījumā tiks ņemtas vērā nākamajā izpildes reizē.",
|
"user_delete_delay_settings_description": "Dienu skaits pēc izdzēšanas, kad neatgriezeniski tiks dzēsti lietotāja konti un faili. Lietotāju dzēšanas uzdevums tiek izpildīts pusnaktī un pārbauda, kuri lietotāji ir gatavi dzēšanai. Izmaiņas šajā iestatījumā tiks ņemtas vērā nākamajā izpildes reizē.",
|
||||||
|
"user_delete_immediately_checkbox": "Ierindot lietotāju un failus tūlītējai dzēšanai",
|
||||||
"user_details": "Lietotāja informācija",
|
"user_details": "Lietotāja informācija",
|
||||||
"user_management": "Lietotāju pārvaldība",
|
"user_management": "Lietotāju pārvaldība",
|
||||||
"user_password_has_been_reset": "Lietotāja parole ir atiestatīta:",
|
"user_password_has_been_reset": "Lietotāja parole ir atiestatīta:",
|
||||||
|
"user_password_reset_description": "Lūdzu, norādi lietotājam pagaidu paroli un informē viņu, ka nākamajā pieslēgšanās reizē viņam būs jāmaina parole.",
|
||||||
"user_restore_description": "<b>{user}</b> konts tiks atjaunots.",
|
"user_restore_description": "<b>{user}</b> konts tiks atjaunots.",
|
||||||
"user_restore_scheduled_removal": "Atjaunot lietotāju - plānotā dzēšana {date, date, long}",
|
"user_restore_scheduled_removal": "Atjaunot lietotāju - plānotā dzēšana {date, date, long}",
|
||||||
"user_settings": "Lietotāja iestatījumi",
|
"user_settings": "Lietotāja iestatījumi",
|
||||||
@@ -238,6 +247,7 @@
|
|||||||
"album_added": "Albums pievienots",
|
"album_added": "Albums pievienots",
|
||||||
"album_added_notification_setting_description": "Saņemt e-pasta paziņojumu, kad tevi pievieno kopīgam albumam",
|
"album_added_notification_setting_description": "Saņemt e-pasta paziņojumu, kad tevi pievieno kopīgam albumam",
|
||||||
"album_cover_updated": "Albuma attēls atjaunināts",
|
"album_cover_updated": "Albuma attēls atjaunināts",
|
||||||
|
"album_delete_confirmation_description": "Ja šis albums tiek kopīgots, citi lietotāji vairs nevarēs tam piekļūt.",
|
||||||
"album_deleted": "Albums dzēsts",
|
"album_deleted": "Albums dzēsts",
|
||||||
"album_info_card_backup_album_excluded": "NEIEKĻAUTS",
|
"album_info_card_backup_album_excluded": "NEIEKĻAUTS",
|
||||||
"album_info_card_backup_album_included": "IEKĻAUTS",
|
"album_info_card_backup_album_included": "IEKĻAUTS",
|
||||||
@@ -279,6 +289,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Izrakstīties",
|
"app_bar_signout_dialog_title": "Izrakstīties",
|
||||||
"app_settings": "Lietotnes iestatījumi",
|
"app_settings": "Lietotnes iestatījumi",
|
||||||
"appears_in": "Parādās iekš",
|
"appears_in": "Parādās iekš",
|
||||||
|
"apply_count": "Pielietot ({count, number})",
|
||||||
"archive": "Arhīvs",
|
"archive": "Arhīvs",
|
||||||
"archive_page_no_archived_assets": "Nav atrasts neviens arhivēts aktīvs",
|
"archive_page_no_archived_assets": "Nav atrasts neviens arhivēts aktīvs",
|
||||||
"archive_page_title": "Arhīvs ({count})",
|
"archive_page_title": "Arhīvs ({count})",
|
||||||
@@ -337,6 +348,7 @@
|
|||||||
"backup_controller_page_background_app_refresh_enable_button_text": "Doties uz iestatījumiem",
|
"backup_controller_page_background_app_refresh_enable_button_text": "Doties uz iestatījumiem",
|
||||||
"backup_controller_page_background_battery_info_link": "Parādīt, kā",
|
"backup_controller_page_background_battery_info_link": "Parādīt, kā",
|
||||||
"backup_controller_page_background_battery_info_message": "Lai iegūtu vislabāko fona dublēšanas pieredzi, lūdzu, atspējojiet visas akumulatora optimizācijas, kas ierobežo Immich fona aktivitāti.\n\nTā kā katrai ierīcei iestatījumi ir citādāki, lūdzu, meklējiet nepieciešamo informāciju pie ierīces ražotāja.",
|
"backup_controller_page_background_battery_info_message": "Lai iegūtu vislabāko fona dublēšanas pieredzi, lūdzu, atspējojiet visas akumulatora optimizācijas, kas ierobežo Immich fona aktivitāti.\n\nTā kā katrai ierīcei iestatījumi ir citādāki, lūdzu, meklējiet nepieciešamo informāciju pie ierīces ražotāja.",
|
||||||
|
"backup_controller_page_background_battery_info_ok": "Labi",
|
||||||
"backup_controller_page_background_battery_info_title": "Akumulatora optimizācija",
|
"backup_controller_page_background_battery_info_title": "Akumulatora optimizācija",
|
||||||
"backup_controller_page_background_charging": "Tikai uzlādes laikā",
|
"backup_controller_page_background_charging": "Tikai uzlādes laikā",
|
||||||
"backup_controller_page_background_configure_error": "Neizdevās konfigurēt fona pakalpojumu",
|
"backup_controller_page_background_configure_error": "Neizdevās konfigurēt fona pakalpojumu",
|
||||||
@@ -406,6 +418,7 @@
|
|||||||
"cache_settings_title": "Kešdarbes iestatījumi",
|
"cache_settings_title": "Kešdarbes iestatījumi",
|
||||||
"camera": "Fotokamera",
|
"camera": "Fotokamera",
|
||||||
"cancel": "Atcelt",
|
"cancel": "Atcelt",
|
||||||
|
"canceled": "Atcelts",
|
||||||
"canceling": "Atceļ",
|
"canceling": "Atceļ",
|
||||||
"cannot_merge_people": "Nevar apvienot personas",
|
"cannot_merge_people": "Nevar apvienot personas",
|
||||||
"cast": "Pārraidīt",
|
"cast": "Pārraidīt",
|
||||||
@@ -424,12 +437,19 @@
|
|||||||
"change_password_form_password_mismatch": "Paroles nesakrīt",
|
"change_password_form_password_mismatch": "Paroles nesakrīt",
|
||||||
"change_password_form_reenter_new_password": "Atkārtoti ievadīt jaunu paroli",
|
"change_password_form_reenter_new_password": "Atkārtoti ievadīt jaunu paroli",
|
||||||
"change_pin_code": "Nomainīt PIN kodu",
|
"change_pin_code": "Nomainīt PIN kodu",
|
||||||
|
"check_corrupt_asset_backup_button": "Veikt pārbaudi",
|
||||||
"choose_matching_people_to_merge": "Izvēlies atbilstošas personas apvienošanai",
|
"choose_matching_people_to_merge": "Izvēlies atbilstošas personas apvienošanai",
|
||||||
"city": "Pilsēta",
|
"city": "Pilsēta",
|
||||||
"clear": "Notīrīt",
|
"clear": "Notīrīt",
|
||||||
"clear_all": "Notīrīt visu",
|
"clear_all": "Notīrīt visu",
|
||||||
"clear_file_cache": "Notīrīt failu kešatmiņu",
|
"clear_file_cache": "Notīrīt failu kešatmiņu",
|
||||||
"clear_value": "Notīrīt vērtību",
|
"clear_value": "Notīrīt vērtību",
|
||||||
|
"client_cert_dialog_msg_confirm": "Labi",
|
||||||
|
"client_cert_enter_password": "Ievadi paroli",
|
||||||
|
"client_cert_import": "Importēt",
|
||||||
|
"client_cert_import_success_msg": "Klienta sertifikāts ir importēts",
|
||||||
|
"client_cert_invalid_msg": "Nederīgs sertifikāta fails vai nepareiza parole",
|
||||||
|
"client_cert_remove_msg": "Klienta sertifikāts ir noņemts",
|
||||||
"client_cert_subtitle": "Atbalsta tikai PKCS12 (.p12, .pfx) formātu. Sertifikātu importēšana/noņemšana ir pieejama tikai pirms pieslēgšanās",
|
"client_cert_subtitle": "Atbalsta tikai PKCS12 (.p12, .pfx) formātu. Sertifikātu importēšana/noņemšana ir pieejama tikai pirms pieslēgšanās",
|
||||||
"client_cert_title": "SSL klienta sertifikāts",
|
"client_cert_title": "SSL klienta sertifikāts",
|
||||||
"clockwise": "Pulksteņrādītāja virzienā",
|
"clockwise": "Pulksteņrādītāja virzienā",
|
||||||
@@ -441,6 +461,7 @@
|
|||||||
"comment_deleted": "Komentārs dzēsts",
|
"comment_deleted": "Komentārs dzēsts",
|
||||||
"common_create_new_album": "Izveidot jaunu albumu",
|
"common_create_new_album": "Izveidot jaunu albumu",
|
||||||
"common_server_error": "Lūdzu, pārbaudiet tīkla savienojumu, pārliecinieties, vai serveris ir sasniedzams un aplikācijas/servera versijas ir saderīgas.",
|
"common_server_error": "Lūdzu, pārbaudiet tīkla savienojumu, pārliecinieties, vai serveris ir sasniedzams un aplikācijas/servera versijas ir saderīgas.",
|
||||||
|
"completed": "Pabeigts",
|
||||||
"confirm": "Apstiprināt",
|
"confirm": "Apstiprināt",
|
||||||
"confirm_new_pin_code": "Apstiprināt jauno PIN kodu",
|
"confirm_new_pin_code": "Apstiprināt jauno PIN kodu",
|
||||||
"confirm_password": "Apstiprināt paroli",
|
"confirm_password": "Apstiprināt paroli",
|
||||||
@@ -463,6 +484,7 @@
|
|||||||
"create_library": "Izveidot bibliotēku",
|
"create_library": "Izveidot bibliotēku",
|
||||||
"create_link": "Izveidot saiti",
|
"create_link": "Izveidot saiti",
|
||||||
"create_link_to_share": "Izveidot kopīgošanas saiti",
|
"create_link_to_share": "Izveidot kopīgošanas saiti",
|
||||||
|
"create_new": "IZVEIDOT JAUNU",
|
||||||
"create_new_person": "Izveidot jaunu personu",
|
"create_new_person": "Izveidot jaunu personu",
|
||||||
"create_new_user": "Izveidot jaunu lietotāju",
|
"create_new_user": "Izveidot jaunu lietotāju",
|
||||||
"create_shared_album_page_share_add_assets": "PIEVIENOT AKTĪVUS",
|
"create_shared_album_page_share_add_assets": "PIEVIENOT AKTĪVUS",
|
||||||
@@ -471,6 +493,7 @@
|
|||||||
"created_at": "Izveidots",
|
"created_at": "Izveidots",
|
||||||
"curated_object_page_title": "Lietas",
|
"curated_object_page_title": "Lietas",
|
||||||
"current_pin_code": "Esošais PIN kods",
|
"current_pin_code": "Esošais PIN kods",
|
||||||
|
"current_server_address": "Pašreizējā servera adrese",
|
||||||
"custom_locale": "Pielāgota lokalizācija",
|
"custom_locale": "Pielāgota lokalizācija",
|
||||||
"custom_locale_description": "Formatēt datumus un skaitļus atbilstoši valodai un reģionam",
|
"custom_locale_description": "Formatēt datumus un skaitļus atbilstoši valodai un reģionam",
|
||||||
"custom_url": "Pielāgots URL",
|
"custom_url": "Pielāgots URL",
|
||||||
@@ -524,21 +547,27 @@
|
|||||||
"download_action_prompt": "Lejupielādē {count} failus",
|
"download_action_prompt": "Lejupielādē {count} failus",
|
||||||
"download_canceled": "Lejupielāde atcelta",
|
"download_canceled": "Lejupielāde atcelta",
|
||||||
"download_complete": "Lejupielāde pabeigta",
|
"download_complete": "Lejupielāde pabeigta",
|
||||||
|
"download_enqueue": "Lejupielāde ierindota",
|
||||||
"download_error": "Lejupielādes kļūda",
|
"download_error": "Lejupielādes kļūda",
|
||||||
"download_failed": "Lejupielāde neizdevās",
|
"download_failed": "Lejupielāde neizdevās",
|
||||||
|
"download_finished": "Lejupielāde pabeigta",
|
||||||
"download_notfound": "Lejupielāde nav atrasta",
|
"download_notfound": "Lejupielāde nav atrasta",
|
||||||
"download_paused": "Lejupielāde nopauzēta",
|
"download_paused": "Lejupielāde nopauzēta",
|
||||||
"download_settings": "Lejupielāde",
|
"download_settings": "Lejupielāde",
|
||||||
"download_settings_description": "Ar failu lejupielādi saistīto iestatījumu pārvaldība",
|
"download_settings_description": "Ar failu lejupielādi saistīto iestatījumu pārvaldība",
|
||||||
"download_started": "Lejupielāde sākta",
|
"download_started": "Lejupielāde sākta",
|
||||||
"download_sucess": "Lejupielāde izdevās",
|
"download_sucess": "Lejupielāde izdevās",
|
||||||
|
"download_sucess_android": "Multivides fails ir lejupielādēts uz DCIM/Immich",
|
||||||
|
"download_waiting_to_retry": "Gaida, lai mēģinātu atkārtoti",
|
||||||
"downloading": "Lejupielādē",
|
"downloading": "Lejupielādē",
|
||||||
"downloading_asset_filename": "Lejupielādē failu {filename}",
|
"downloading_asset_filename": "Lejupielādē failu {filename}",
|
||||||
|
"downloading_media": "Lejupielādē failu",
|
||||||
"duplicates": "Dublikāti",
|
"duplicates": "Dublikāti",
|
||||||
"duplicates_description": "Atrisini katru grupu, norādot, kuri no tiem ir dublikāti",
|
"duplicates_description": "Atrisini katru grupu, norādot, kuri no tiem ir dublikāti",
|
||||||
"duration": "Ilgums",
|
"duration": "Ilgums",
|
||||||
"edit": "Labot",
|
"edit": "Labot",
|
||||||
"edit_album": "Labot albumu",
|
"edit_album": "Labot albumu",
|
||||||
|
"edit_avatar": "Labot avatāru",
|
||||||
"edit_birthday": "Labot dzimšanas dienu",
|
"edit_birthday": "Labot dzimšanas dienu",
|
||||||
"edit_date": "Labot datumu",
|
"edit_date": "Labot datumu",
|
||||||
"edit_date_and_time": "Labot datumu un laiku",
|
"edit_date_and_time": "Labot datumu un laiku",
|
||||||
@@ -572,6 +601,7 @@
|
|||||||
"enter_your_pin_code": "Ievadi savu PIN kodu",
|
"enter_your_pin_code": "Ievadi savu PIN kodu",
|
||||||
"enter_your_pin_code_subtitle": "Ievadi savu PIN kodu, lai piekļūtu slēgtajai mapei",
|
"enter_your_pin_code_subtitle": "Ievadi savu PIN kodu, lai piekļūtu slēgtajai mapei",
|
||||||
"error": "Kļūda",
|
"error": "Kļūda",
|
||||||
|
"error_change_sort_album": "Neizdevās nomainīt albuma kārtošanas secību",
|
||||||
"error_saving_image": "Kļūda: {error}",
|
"error_saving_image": "Kļūda: {error}",
|
||||||
"errors": {
|
"errors": {
|
||||||
"cant_get_faces": "Nevar iegūt sejas",
|
"cant_get_faces": "Nevar iegūt sejas",
|
||||||
@@ -625,10 +655,13 @@
|
|||||||
"export_database_description": "Eksportēt SQLite datubāzi",
|
"export_database_description": "Eksportēt SQLite datubāzi",
|
||||||
"extension": "Paplašinājums",
|
"extension": "Paplašinājums",
|
||||||
"external": "Ārējs",
|
"external": "Ārējs",
|
||||||
|
"external_network": "Ārējs tīkls",
|
||||||
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom",
|
"external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom",
|
||||||
"face_unassigned": "Nepiešķirts",
|
"face_unassigned": "Nepiešķirts",
|
||||||
|
"failed": "Neizdevās",
|
||||||
"failed_to_authenticate": "Neizdevās autentificēties",
|
"failed_to_authenticate": "Neizdevās autentificēties",
|
||||||
"failed_to_load_assets": "Neizdevās ielādēt failus",
|
"failed_to_load_assets": "Neizdevās ielādēt failus",
|
||||||
|
"failed_to_load_folder": "Neizdevās ielādēt mapi",
|
||||||
"favorite": "Izlase",
|
"favorite": "Izlase",
|
||||||
"favorites": "Izlase",
|
"favorites": "Izlase",
|
||||||
"favorites_page_no_favorites": "Nav atrasti iecienītākie faili",
|
"favorites_page_no_favorites": "Nav atrasti iecienītākie faili",
|
||||||
@@ -654,6 +687,8 @@
|
|||||||
"go_back": "Doties atpakaļ",
|
"go_back": "Doties atpakaļ",
|
||||||
"go_to_folder": "Doties uz mapi",
|
"go_to_folder": "Doties uz mapi",
|
||||||
"go_to_search": "Doties uz meklēšanu",
|
"go_to_search": "Doties uz meklēšanu",
|
||||||
|
"gps": "Ir koordinātas",
|
||||||
|
"gps_missing": "Nav koordinātu",
|
||||||
"grant_permission": "Piešķirt atļauju",
|
"grant_permission": "Piešķirt atļauju",
|
||||||
"group_albums_by": "Grupēt albumus pēc...",
|
"group_albums_by": "Grupēt albumus pēc...",
|
||||||
"group_country": "Grupēt pēc valsts",
|
"group_country": "Grupēt pēc valsts",
|
||||||
@@ -789,6 +824,7 @@
|
|||||||
"look": "Izskats",
|
"look": "Izskats",
|
||||||
"loop_videos_description": "Iespējot, lai automātiski videoklips tiktu cikliski palaists detaļu skatītājā.",
|
"loop_videos_description": "Iespējot, lai automātiski videoklips tiktu cikliski palaists detaļu skatītājā.",
|
||||||
"make": "Ražotājs",
|
"make": "Ražotājs",
|
||||||
|
"manage_geolocation": "Pārvaldīt atrašanās vietu",
|
||||||
"manage_shared_links": "Kopīgoto saišu pārvaldība",
|
"manage_shared_links": "Kopīgoto saišu pārvaldība",
|
||||||
"manage_sharing_with_partners": "Koplietošanas ar partneriem pārvaldība",
|
"manage_sharing_with_partners": "Koplietošanas ar partneriem pārvaldība",
|
||||||
"manage_the_app_settings": "Lietotnes iestatījumu pārvaldība",
|
"manage_the_app_settings": "Lietotnes iestatījumu pārvaldība",
|
||||||
@@ -856,6 +892,7 @@
|
|||||||
"name_or_nickname": "Vārds vai iesauka",
|
"name_or_nickname": "Vārds vai iesauka",
|
||||||
"network_requirement_photos_upload": "Izmantot mobilo datu pārraidi, lai dublētu fotoattēlus",
|
"network_requirement_photos_upload": "Izmantot mobilo datu pārraidi, lai dublētu fotoattēlus",
|
||||||
"network_requirement_videos_upload": "Izmantot mobilo datu pārraidi, lai dublētu video",
|
"network_requirement_videos_upload": "Izmantot mobilo datu pārraidi, lai dublētu video",
|
||||||
|
"networking_subtitle": "Pārvaldīt servera galapunktu iestatījumus",
|
||||||
"never": "nekad",
|
"never": "nekad",
|
||||||
"new_album": "Jauns albums",
|
"new_album": "Jauns albums",
|
||||||
"new_api_key": "Jauna API atslēga",
|
"new_api_key": "Jauna API atslēga",
|
||||||
@@ -881,6 +918,7 @@
|
|||||||
"no_results": "Nav rezultātu",
|
"no_results": "Nav rezultātu",
|
||||||
"no_results_description": "Izmēģiniet sinonīmu vai vispārīgāku atslēgvārdu",
|
"no_results_description": "Izmēģiniet sinonīmu vai vispārīgāku atslēgvārdu",
|
||||||
"not_in_any_album": "Nav nevienā albumā",
|
"not_in_any_album": "Nav nevienā albumā",
|
||||||
|
"not_selected": "Nav izvēlēts",
|
||||||
"notes": "Piezīmes",
|
"notes": "Piezīmes",
|
||||||
"nothing_here_yet": "Šeit vēl nekā nav",
|
"nothing_here_yet": "Šeit vēl nekā nav",
|
||||||
"notification_permission_dialog_content": "Lai iespējotu paziņojumus, atveriet Iestatījumi un atlasiet Atļaut.",
|
"notification_permission_dialog_content": "Lai iespējotu paziņojumus, atveriet Iestatījumi un atlasiet Atļaut.",
|
||||||
@@ -1115,12 +1153,17 @@
|
|||||||
"see_all_people": "Skatīt visas personas",
|
"see_all_people": "Skatīt visas personas",
|
||||||
"select_album_cover": "Izvēlieties albuma vāciņu",
|
"select_album_cover": "Izvēlieties albuma vāciņu",
|
||||||
"select_all_duplicates": "Atlasīt visus dublikātus",
|
"select_all_duplicates": "Atlasīt visus dublikātus",
|
||||||
|
"select_avatar_color": "Izvēlies avatāra krāsu",
|
||||||
|
"select_face": "Izvēlies seju",
|
||||||
"select_from_computer": "Izvēlēties no datora",
|
"select_from_computer": "Izvēlēties no datora",
|
||||||
"select_keep_all": "Atzīmēt visus paturēšanai",
|
"select_keep_all": "Atzīmēt visus paturēšanai",
|
||||||
|
"select_library_owner": "Izvēlies bibliotēkas īpašnieku",
|
||||||
|
"select_new_face": "Izvēlies jaunu seju",
|
||||||
"select_photos": "Fotoattēlu Izvēle",
|
"select_photos": "Fotoattēlu Izvēle",
|
||||||
"select_trash_all": "Atzīmēt visus dzēšanai",
|
"select_trash_all": "Atzīmēt visus dzēšanai",
|
||||||
"select_user_for_sharing_page_err_album": "Neizdevās izveidot albumu",
|
"select_user_for_sharing_page_err_album": "Neizdevās izveidot albumu",
|
||||||
"selected": "Izvēlētie",
|
"selected": "Izvēlētie",
|
||||||
|
"selected_gps_coordinates": "izvēlētās ģeogrāfiskās koordinātas",
|
||||||
"server_info_box_app_version": "Aplikācijas Versija",
|
"server_info_box_app_version": "Aplikācijas Versija",
|
||||||
"server_info_box_server_url": "Servera URL",
|
"server_info_box_server_url": "Servera URL",
|
||||||
"server_online": "Serveris tiešsaistē",
|
"server_online": "Serveris tiešsaistē",
|
||||||
@@ -1202,6 +1245,7 @@
|
|||||||
"sharing_silver_appbar_share_partner": "Dalīties ar partneri",
|
"sharing_silver_appbar_share_partner": "Dalīties ar partneri",
|
||||||
"show_album_options": "Rādīt albuma iespējas",
|
"show_album_options": "Rādīt albuma iespējas",
|
||||||
"show_albums": "Rādīt albumus",
|
"show_albums": "Rādīt albumus",
|
||||||
|
"show_all_assets": "Rādīt visus failus",
|
||||||
"show_all_people": "Rādīt visas personas",
|
"show_all_people": "Rādīt visas personas",
|
||||||
"show_and_hide_people": "Rādīt un slēpt personas",
|
"show_and_hide_people": "Rādīt un slēpt personas",
|
||||||
"show_file_location": "Rādīt faila atrašanās vietu",
|
"show_file_location": "Rādīt faila atrašanās vietu",
|
||||||
@@ -1325,6 +1369,7 @@
|
|||||||
"usage": "Lietojums",
|
"usage": "Lietojums",
|
||||||
"use_biometric": "Izmantot biometrisko autentifikāciju",
|
"use_biometric": "Izmantot biometrisko autentifikāciju",
|
||||||
"use_current_connection": "izmantot pašreizējo savienojumu",
|
"use_current_connection": "izmantot pašreizējo savienojumu",
|
||||||
|
"use_custom_date_range": "Izmantot pielāgotu datuma intervālu",
|
||||||
"user": "Lietotājs",
|
"user": "Lietotājs",
|
||||||
"user_has_been_deleted": "Šis lietotājs ir dzēsts.",
|
"user_has_been_deleted": "Šis lietotājs ir dzēsts.",
|
||||||
"user_id": "Lietotāja ID",
|
"user_id": "Lietotāja ID",
|
||||||
@@ -1338,6 +1383,7 @@
|
|||||||
"username": "Lietotājvārds",
|
"username": "Lietotājvārds",
|
||||||
"users": "Lietotāji",
|
"users": "Lietotāji",
|
||||||
"utilities": "Rīki",
|
"utilities": "Rīki",
|
||||||
|
"validate": "Pārbaudīt",
|
||||||
"variables": "Mainīgie",
|
"variables": "Mainīgie",
|
||||||
"version": "Versija",
|
"version": "Versija",
|
||||||
"version_announcement_closing": "Tavs draugs, Alekss",
|
"version_announcement_closing": "Tavs draugs, Alekss",
|
||||||
|
|||||||
20
i18n/ml.json
20
i18n/ml.json
@@ -13,6 +13,7 @@
|
|||||||
"add_a_location": "ഒരു സ്ഥലം ചേർക്കുക",
|
"add_a_location": "ഒരു സ്ഥലം ചേർക്കുക",
|
||||||
"add_a_name": "ഒരു പേര് ചേർക്കുക",
|
"add_a_name": "ഒരു പേര് ചേർക്കുക",
|
||||||
"add_a_title": "ഒരു ശീർഷകം ചേർക്കുക",
|
"add_a_title": "ഒരു ശീർഷകം ചേർക്കുക",
|
||||||
|
"add_birthday": "ജന്മദിനം ചേർക്കുക",
|
||||||
"add_endpoint": "എൻഡ്പോയിന്റ് ചേർക്കുക",
|
"add_endpoint": "എൻഡ്പോയിന്റ് ചേർക്കുക",
|
||||||
"add_exclusion_pattern": "ഒഴിവാക്കാനുള്ള മാതൃക ചേർക്കുക",
|
"add_exclusion_pattern": "ഒഴിവാക്കാനുള്ള മാതൃക ചേർക്കുക",
|
||||||
"add_import_path": "ഇറക്കുമതി ചെയ്യുക",
|
"add_import_path": "ഇറക്കുമതി ചെയ്യുക",
|
||||||
@@ -22,10 +23,12 @@
|
|||||||
"add_path": "പാത ചേര്ക്കുക",
|
"add_path": "പാത ചേര്ക്കുക",
|
||||||
"add_photos": "ചിത്രങ്ങള് ചേര്ക്കുക",
|
"add_photos": "ചിത്രങ്ങള് ചേര്ക്കുക",
|
||||||
"add_tag": "ടാഗ് ചേര്ക്കുക",
|
"add_tag": "ടാഗ് ചേര്ക്കുക",
|
||||||
"add_to": "ചേര്ക്കുക",
|
"add_to": "ചേര്ക്കുക…",
|
||||||
"add_to_album": "ആല്ബത്തിലേക്ക് ചേര്ക്കുക",
|
"add_to_album": "ആല്ബത്തിലേക്ക് ചേര്ക്കുക",
|
||||||
"add_to_album_bottom_sheet_added": "{album} - ലേക്ക് ചേര്ത്തു",
|
"add_to_album_bottom_sheet_added": "{album} - ലേക്ക് ചേര്ത്തു",
|
||||||
"add_to_album_bottom_sheet_already_exists": "{album} ആൽബത്തിൽ ഇപ്പോള് തന്നെ ഉണ്ട്",
|
"add_to_album_bottom_sheet_already_exists": "{album} ആൽബത്തിൽ ഇപ്പോള് തന്നെ ഉണ്ട്",
|
||||||
|
"add_to_albums": "ആൽബങ്ങളിൽ ചേർക്കുക",
|
||||||
|
"add_to_albums_count": "ആൽബങ്ങളിൽ ചേർക്കുക ({count})",
|
||||||
"add_to_shared_album": "പങ്കിട്ട ആൽബത്തിലേക്ക് ചേർക്കുക",
|
"add_to_shared_album": "പങ്കിട്ട ആൽബത്തിലേക്ക് ചേർക്കുക",
|
||||||
"add_url": "URL ചേര്ക്കുക",
|
"add_url": "URL ചേര്ക്കുക",
|
||||||
"added_to_archive": "ചരിത്രരേഖയായി (ആര്ക്കൈവ്) ചേര്ത്തിരിക്കുന്നു",
|
"added_to_archive": "ചരിത്രരേഖയായി (ആര്ക്കൈവ്) ചേര്ത്തിരിക്കുന്നു",
|
||||||
@@ -68,6 +71,17 @@
|
|||||||
"image_format": "ഘടന",
|
"image_format": "ഘടന",
|
||||||
"image_format_description": "WebP ഉണ്ടാക്കാന് സമയം എടുക്കും എങ്കിലും JPEG ഫയലുകളെക്കാള് ചെറുതായിരിക്കും.",
|
"image_format_description": "WebP ഉണ്ടാക്കാന് സമയം എടുക്കും എങ്കിലും JPEG ഫയലുകളെക്കാള് ചെറുതായിരിക്കും.",
|
||||||
"image_fullsize_description": "അധികവിവരങ്ങള് ഒഴിവാക്കിയ ചിത്രം, വലുതാക്കി കാണിക്കുമ്പോള് ഉപയോഗിക്കപ്പെടുന്നു",
|
"image_fullsize_description": "അധികവിവരങ്ങള് ഒഴിവാക്കിയ ചിത്രം, വലുതാക്കി കാണിക്കുമ്പോള് ഉപയോഗിക്കപ്പെടുന്നു",
|
||||||
"image_fullsize_enabled": "പൂര്ണ വലുപ്പത്തില് ഉള്ള ചിത്രങ്ങള് ഉണ്ടാക്കാന്പ്രാപ്തമാക്കുക"
|
"image_fullsize_enabled": "പൂര്ണ വലുപ്പത്തില് ഉള്ള ചിത്രങ്ങള് ഉണ്ടാക്കാന്പ്രാപ്തമാക്കുക",
|
||||||
}
|
"image_fullsize_quality_description": "1 മുതൽ 100 വരെയുള്ള പൂർണ്ണ വലുപ്പത്തിലുള്ള ഇമേജ് നിലവാരം. ഉയർന്നതാണ് നല്ലത്, പക്ഷേ വലിയ ഫയലുകൾ ഉത്പാദിപ്പിക്കുന്നു.",
|
||||||
|
"image_fullsize_title": "പൂർണ്ണ വലുപ്പത്തിലുള്ള ഇമേജ് ക്രമീകരണങ്ങൾ",
|
||||||
|
"image_quality": "ഗുണനിലവാരം",
|
||||||
|
"job_created": "ജോലി സൃഷ്ടിച്ചു",
|
||||||
|
"job_status": "ജോലി നില"
|
||||||
|
},
|
||||||
|
"waiting": "കാത്തിരിക്കുന്നു",
|
||||||
|
"warning": "മുന്നറിയിപ്പ്",
|
||||||
|
"week": "ആഴ്ച",
|
||||||
|
"welcome": "സ്വാഗതം",
|
||||||
|
"year": "വർഷം",
|
||||||
|
"yes": "അതെ"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Åpne søkefiltrene",
|
"open_the_search_filters": "Åpne søkefiltrene",
|
||||||
"options": "Valg",
|
"options": "Valg",
|
||||||
"or": "eller",
|
"or": "eller",
|
||||||
|
"organize_into_albums": "Organiser til albumer",
|
||||||
|
"organize_into_albums_description": "Plasser eksisterende bilder i albumer ved å bruke synkroniseringsinnstillinger",
|
||||||
"organize_your_library": "Organiser biblioteket ditt",
|
"organize_your_library": "Organiser biblioteket ditt",
|
||||||
"original": "original",
|
"original": "original",
|
||||||
"other": "Annet",
|
"other": "Annet",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Støttespiller status",
|
"purchase_server_description_2": "Støttespiller status",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Produktnøkkel for server er administrert av administratoren",
|
"purchase_settings_server_activated": "Produktnøkkel for server er administrert av administratoren",
|
||||||
|
"query_asset_id": "Forespør objektID",
|
||||||
"queue_status": "Kø {count}/{total}",
|
"queue_status": "Kø {count}/{total}",
|
||||||
"rating": "Stjernevurdering",
|
"rating": "Stjernevurdering",
|
||||||
"rating_clear": "Slett vurdering",
|
"rating_clear": "Slett vurdering",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Feilet ved oppretting av album",
|
"select_user_for_sharing_page_err_album": "Feilet ved oppretting av album",
|
||||||
"selected": "Valgt",
|
"selected": "Valgt",
|
||||||
"selected_count": "{count, plural, other {# valgt}}",
|
"selected_count": "{count, plural, other {# valgt}}",
|
||||||
"selected_gps_coordinates": "valgte GPS-koordinater",
|
"selected_gps_coordinates": "Valgte GPS-koordinater",
|
||||||
"send_message": "Send melding",
|
"send_message": "Send melding",
|
||||||
"send_welcome_email": "Send velkomstmelding",
|
"send_welcome_email": "Send velkomstmelding",
|
||||||
"server_endpoint": "Server endepunkt",
|
"server_endpoint": "Server endepunkt",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Vis neste fil",
|
"view_next_asset": "Vis neste fil",
|
||||||
"view_previous_asset": "Vis forrige fil",
|
"view_previous_asset": "Vis forrige fil",
|
||||||
"view_qr_code": "Vis QR-kode",
|
"view_qr_code": "Vis QR-kode",
|
||||||
|
"view_similar_photos": "Vis lignende bilder",
|
||||||
"view_stack": "Vis stabel",
|
"view_stack": "Vis stabel",
|
||||||
"view_user": "Vis bruker",
|
"view_user": "Vis bruker",
|
||||||
"viewer_remove_from_stack": "Fjern fra stabling",
|
"viewer_remove_from_stack": "Fjern fra stabling",
|
||||||
|
|||||||
20
i18n/nl.json
20
i18n/nl.json
@@ -396,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Externe afbeeldingen laden",
|
"advanced_settings_prefer_remote_title": "Externe afbeeldingen laden",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Definieer proxy headers die Immich bij elk netwerkverzoek moet verzenden",
|
"advanced_settings_proxy_headers_subtitle": "Definieer proxy headers die Immich bij elk netwerkverzoek moet verzenden",
|
||||||
"advanced_settings_proxy_headers_title": "Proxy headers",
|
"advanced_settings_proxy_headers_title": "Proxy headers",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Schakelt de alleen-lezenmodus in, waarbij de foto's alleen bekeken kunnen worden. Dingen zoals het selecteren van meerdere afbeeldingen, delen, casten en verwijderen zijn allemaal uitgeschakeld. Schakel alleen-lezen in of uit via de gebruikers avatar vanaf het hoofdscherm",
|
||||||
|
"advanced_settings_readonly_mode_title": "Alleen-lezen Mode",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Slaat SSL-certificaatverificatie voor de connectie met de server over. Deze optie is vereist voor zelfondertekende certificaten.",
|
"advanced_settings_self_signed_ssl_subtitle": "Slaat SSL-certificaatverificatie voor de connectie met de server over. Deze optie is vereist voor zelfondertekende certificaten.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Zelfondertekende SSL-certificaten toestaan",
|
"advanced_settings_self_signed_ssl_title": "Zelfondertekende SSL-certificaten toestaan",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Automatisch bestanden verwijderen of herstellen op dit apparaat als die actie op het web is ondernomen",
|
"advanced_settings_sync_remote_deletions_subtitle": "Automatisch bestanden verwijderen of herstellen op dit apparaat als die actie op het web is ondernomen",
|
||||||
@@ -461,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Log uit",
|
"app_bar_signout_dialog_title": "Log uit",
|
||||||
"app_settings": "App instellingen",
|
"app_settings": "App instellingen",
|
||||||
"appears_in": "Komt voor in",
|
"appears_in": "Komt voor in",
|
||||||
|
"apply_count": "Toepassen ({count, number})",
|
||||||
"archive": "Archief",
|
"archive": "Archief",
|
||||||
"archive_action_prompt": "{count} item(s) toegevoegd aan het archief",
|
"archive_action_prompt": "{count} item(s) toegevoegd aan het archief",
|
||||||
"archive_or_unarchive_photo": "Foto archiveren of uit het archief halen",
|
"archive_or_unarchive_photo": "Foto archiveren of uit het archief halen",
|
||||||
@@ -1073,12 +1076,18 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Deze functie gebruikt externe bronnen van Google om te kunnen werken.",
|
"gcast_enabled_description": "Deze functie gebruikt externe bronnen van Google om te kunnen werken.",
|
||||||
"general": "Algemeen",
|
"general": "Algemeen",
|
||||||
|
"geolocation_instruction_all_have_location": "Alle items voor deze datum hebben al locatiegegevens. Probeer alle items te tonen of selecteer een andere datum",
|
||||||
|
"geolocation_instruction_location": "Klik op een item met GPS coördinaten om de locatie te gebruiken, of selecteer een locatie direct vanaf de kaart",
|
||||||
|
"geolocation_instruction_no_date": "Selecteer een datum om locatiegegevens te beheren voor foto's en video's van die dag",
|
||||||
|
"geolocation_instruction_no_photos": "Geen foto's of video's gevonden voor deze datum. Selecteer een andere datum om ze te tonen",
|
||||||
"get_help": "Krijg hulp",
|
"get_help": "Krijg hulp",
|
||||||
"get_wifiname_error": "Kon de WiFi-naam niet ophalen. Zorg ervoor dat je de benodigde machtigingen hebt verleend en verbonden bent met een WiFi-netwerk",
|
"get_wifiname_error": "Kon de WiFi-naam niet ophalen. Zorg ervoor dat je de benodigde machtigingen hebt verleend en verbonden bent met een WiFi-netwerk",
|
||||||
"getting_started": "Aan de slag",
|
"getting_started": "Aan de slag",
|
||||||
"go_back": "Ga terug",
|
"go_back": "Ga terug",
|
||||||
"go_to_folder": "Ga naar map",
|
"go_to_folder": "Ga naar map",
|
||||||
"go_to_search": "Ga naar zoeken",
|
"go_to_search": "Ga naar zoeken",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "Geen GPS",
|
||||||
"grant_permission": "Geef toestemming",
|
"grant_permission": "Geef toestemming",
|
||||||
"group_albums_by": "Groepeer albums op...",
|
"group_albums_by": "Groepeer albums op...",
|
||||||
"group_country": "Groepeer op land",
|
"group_country": "Groepeer op land",
|
||||||
@@ -1262,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Je gebruikt een ontwikkelingsversie. We raden je ten zeerste aan een releaseversie te gebruiken!",
|
"main_branch_warning": "Je gebruikt een ontwikkelingsversie. We raden je ten zeerste aan een releaseversie te gebruiken!",
|
||||||
"main_menu": "Hoofdmenu",
|
"main_menu": "Hoofdmenu",
|
||||||
"make": "Merk",
|
"make": "Merk",
|
||||||
|
"manage_geolocation": "Beheer locatie",
|
||||||
"manage_shared_links": "Beheer gedeelde links",
|
"manage_shared_links": "Beheer gedeelde links",
|
||||||
"manage_sharing_with_partners": "Beheer delen met partners",
|
"manage_sharing_with_partners": "Beheer delen met partners",
|
||||||
"manage_the_app_settings": "Beheer de appinstellingen",
|
"manage_the_app_settings": "Beheer de appinstellingen",
|
||||||
@@ -1508,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "Mobiele app is verouderd. Werk bij naar de nieuwste subversie.",
|
"profile_drawer_client_out_of_date_minor": "Mobiele app is verouderd. Werk bij naar de nieuwste subversie.",
|
||||||
"profile_drawer_client_server_up_to_date": "App en server zijn up-to-date",
|
"profile_drawer_client_server_up_to_date": "App en server zijn up-to-date",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Alleen-lezen-modus ingeschakeld. Dubbeltik op het avatarpictogram van de gebruiker om te verlaten.",
|
||||||
"profile_drawer_server_out_of_date_major": "Server is verouderd. Werk bij naar de nieuwste hoofdversie.",
|
"profile_drawer_server_out_of_date_major": "Server is verouderd. Werk bij naar de nieuwste hoofdversie.",
|
||||||
"profile_drawer_server_out_of_date_minor": "Server is verouderd. Werk bij naar de nieuwste subversie.",
|
"profile_drawer_server_out_of_date_minor": "Server is verouderd. Werk bij naar de nieuwste subversie.",
|
||||||
"profile_image_of_user": "Profielfoto van {user}",
|
"profile_image_of_user": "Profielfoto van {user}",
|
||||||
@@ -1553,6 +1564,8 @@
|
|||||||
"rating_description": "De EXIF-waardering weergeven in het infopaneel",
|
"rating_description": "De EXIF-waardering weergeven in het infopaneel",
|
||||||
"reaction_options": "Reactie-opties",
|
"reaction_options": "Reactie-opties",
|
||||||
"read_changelog": "Lees wijzigingen",
|
"read_changelog": "Lees wijzigingen",
|
||||||
|
"readonly_mode_disabled": "Alleen-lezen modus uitgeschakeld",
|
||||||
|
"readonly_mode_enabled": "Alleen-lezen modus ingeschakeld",
|
||||||
"reassign": "Opnieuw toewijzen",
|
"reassign": "Opnieuw toewijzen",
|
||||||
"reassigned_assets_to_existing_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan {name, select, null {een bestaand persoon} other {{name}}}",
|
"reassigned_assets_to_existing_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan {name, select, null {een bestaand persoon} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan een nieuw persoon",
|
"reassigned_assets_to_new_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan een nieuw persoon",
|
||||||
@@ -1722,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Album aanmaken mislukt",
|
"select_user_for_sharing_page_err_album": "Album aanmaken mislukt",
|
||||||
"selected": "Geselecteerd",
|
"selected": "Geselecteerd",
|
||||||
"selected_count": "{count, plural, other {# geselecteerd}}",
|
"selected_count": "{count, plural, other {# geselecteerd}}",
|
||||||
|
"selected_gps_coordinates": "geselecteerde GPS coördinaten",
|
||||||
"send_message": "Bericht versturen",
|
"send_message": "Bericht versturen",
|
||||||
"send_welcome_email": "Stuur welkomstmail",
|
"send_welcome_email": "Stuur welkomstmail",
|
||||||
"server_endpoint": "Server-URL",
|
"server_endpoint": "Server-URL",
|
||||||
@@ -1832,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "druk op ⇧ om items permanent te verwijderen",
|
"shift_to_permanent_delete": "druk op ⇧ om items permanent te verwijderen",
|
||||||
"show_album_options": "Toon albumopties",
|
"show_album_options": "Toon albumopties",
|
||||||
"show_albums": "Toon albums",
|
"show_albums": "Toon albums",
|
||||||
|
"show_all_assets": "Toon alle items",
|
||||||
"show_all_people": "Toon alle mensen",
|
"show_all_people": "Toon alle mensen",
|
||||||
"show_and_hide_people": "Toon & verberg mensen",
|
"show_and_hide_people": "Toon & verberg mensen",
|
||||||
|
"show_assets_without_location": "Toon items zonder locatie",
|
||||||
"show_file_location": "Toon bestandslocatie",
|
"show_file_location": "Toon bestandslocatie",
|
||||||
"show_gallery": "Toon galerij",
|
"show_gallery": "Toon galerij",
|
||||||
"show_hidden_people": "Verbogen mensen weergeven",
|
"show_hidden_people": "Verbogen mensen weergeven",
|
||||||
@@ -1941,7 +1957,9 @@
|
|||||||
"to_change_password": "Wijzig wachtwoord",
|
"to_change_password": "Wijzig wachtwoord",
|
||||||
"to_favorite": "Toevoegen aan favorieten",
|
"to_favorite": "Toevoegen aan favorieten",
|
||||||
"to_login": "Inloggen",
|
"to_login": "Inloggen",
|
||||||
|
"to_multi_select": "naar multi-select",
|
||||||
"to_parent": "Ga naar hoofdmap",
|
"to_parent": "Ga naar hoofdmap",
|
||||||
|
"to_select": "naar selecteren",
|
||||||
"to_trash": "Prullenbak",
|
"to_trash": "Prullenbak",
|
||||||
"toggle_settings": "Zichtbaarheid instellingen wisselen",
|
"toggle_settings": "Zichtbaarheid instellingen wisselen",
|
||||||
"total": "Totaal",
|
"total": "Totaal",
|
||||||
@@ -1991,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "{count, plural, one {# item} other {# items}} ontstapeld",
|
"unstacked_assets_count": "{count, plural, one {# item} other {# items}} ontstapeld",
|
||||||
"untagged": "Ongemarkeerd",
|
"untagged": "Ongemarkeerd",
|
||||||
"up_next": "Volgende",
|
"up_next": "Volgende",
|
||||||
|
"update_location_action_prompt": "Werk de locatie bij van {count} geselecteerde items met:",
|
||||||
"updated_at": "Geüpdatet",
|
"updated_at": "Geüpdatet",
|
||||||
"updated_password": "Wachtwoord bijgewerkt",
|
"updated_password": "Wachtwoord bijgewerkt",
|
||||||
"upload": "Uploaden",
|
"upload": "Uploaden",
|
||||||
@@ -2015,6 +2034,7 @@
|
|||||||
"use_biometric": "Gebruik biometrische authenticatie",
|
"use_biometric": "Gebruik biometrische authenticatie",
|
||||||
"use_current_connection": "gebruik huidige verbinding",
|
"use_current_connection": "gebruik huidige verbinding",
|
||||||
"use_custom_date_range": "Gebruik in plaats daarvan een aangepast datumbereik",
|
"use_custom_date_range": "Gebruik in plaats daarvan een aangepast datumbereik",
|
||||||
|
"use_this_location": "Klik om locatie te gebruiken",
|
||||||
"user": "Gebruiker",
|
"user": "Gebruiker",
|
||||||
"user_has_been_deleted": "Deze gebruiker is verwijderd.",
|
"user_has_been_deleted": "Deze gebruiker is verwijderd.",
|
||||||
"user_id": "Gebruikers ID",
|
"user_id": "Gebruikers ID",
|
||||||
|
|||||||
90
i18n/pl.json
90
i18n/pl.json
@@ -44,7 +44,7 @@
|
|||||||
"authentication_settings_description": "Zarządzaj hasłem, OAuth i innymi ustawienia uwierzytelnienia",
|
"authentication_settings_description": "Zarządzaj hasłem, OAuth i innymi ustawienia uwierzytelnienia",
|
||||||
"authentication_settings_disable_all": "Czy jesteś pewny, że chcesz wyłączyć wszystkie metody logowania? Logowanie będzie całkowicie wyłączone.",
|
"authentication_settings_disable_all": "Czy jesteś pewny, że chcesz wyłączyć wszystkie metody logowania? Logowanie będzie całkowicie wyłączone.",
|
||||||
"authentication_settings_reenable": "Aby ponownie włączyć, użyj <link>Polecenia serwera</link>.",
|
"authentication_settings_reenable": "Aby ponownie włączyć, użyj <link>Polecenia serwera</link>.",
|
||||||
"background_task_job": "Zadania w Tle",
|
"background_task_job": "Zadania w tle",
|
||||||
"backup_database": "Utwórz Zrzut Bazy Danych",
|
"backup_database": "Utwórz Zrzut Bazy Danych",
|
||||||
"backup_database_enable_description": "Włącz zrzuty bazy danych",
|
"backup_database_enable_description": "Włącz zrzuty bazy danych",
|
||||||
"backup_keep_last_amount": "Ile poprzednich zrzutów przechowywać",
|
"backup_keep_last_amount": "Ile poprzednich zrzutów przechowywać",
|
||||||
@@ -396,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Preferuj obrazy zdalne",
|
"advanced_settings_prefer_remote_title": "Preferuj obrazy zdalne",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Zdefiniuj nagłówki proxy, które Immich powinien wysyłać z każdym żądaniem sieciowym",
|
"advanced_settings_proxy_headers_subtitle": "Zdefiniuj nagłówki proxy, które Immich powinien wysyłać z każdym żądaniem sieciowym",
|
||||||
"advanced_settings_proxy_headers_title": "Nagłówki proxy",
|
"advanced_settings_proxy_headers_title": "Nagłówki proxy",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Włącza tryb tylko do odczytu, w którym zdjęcia można tylko przeglądać, a takie czynności jak wybieranie wielu obrazów, udostępnianie, przesyłanie i usuwanie są wyłączone. Włącz/wyłącz tryb tylko do odczytu za pomocą awatara użytkownika na ekranie głównym",
|
||||||
|
"advanced_settings_readonly_mode_title": "Tryb tylko do odczytu",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Pomija weryfikację certyfikatu SSL dla punktu końcowego serwera. Wymagane w przypadku certyfikatów z podpisem własnym.",
|
"advanced_settings_self_signed_ssl_subtitle": "Pomija weryfikację certyfikatu SSL dla punktu końcowego serwera. Wymagane w przypadku certyfikatów z podpisem własnym.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Zezwalaj na certyfikaty SSL z podpisem własnym",
|
"advanced_settings_self_signed_ssl_title": "Zezwalaj na certyfikaty SSL z podpisem własnym",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Automatycznie usuń lub przywróć zasób na tym urządzeniu po wykonaniu tej czynności w interfejsie webowym",
|
"advanced_settings_sync_remote_deletions_subtitle": "Automatycznie usuń lub przywróć zasób na tym urządzeniu po wykonaniu tej czynności w interfejsie webowym",
|
||||||
@@ -459,8 +461,9 @@
|
|||||||
"app_bar_signout_dialog_content": "Czy na pewno chcesz się wylogować?",
|
"app_bar_signout_dialog_content": "Czy na pewno chcesz się wylogować?",
|
||||||
"app_bar_signout_dialog_ok": "Tak",
|
"app_bar_signout_dialog_ok": "Tak",
|
||||||
"app_bar_signout_dialog_title": "Wyloguj się",
|
"app_bar_signout_dialog_title": "Wyloguj się",
|
||||||
"app_settings": "Ustawienia Aplikacji",
|
"app_settings": "Ustawienia aplikacji",
|
||||||
"appears_in": "W albumach",
|
"appears_in": "W albumach",
|
||||||
|
"apply_count": "Zastosuj ({count, number})",
|
||||||
"archive": "Archiwum",
|
"archive": "Archiwum",
|
||||||
"archive_action_prompt": "{count} dodanych do Archiwum",
|
"archive_action_prompt": "{count} dodanych do Archiwum",
|
||||||
"archive_or_unarchive_photo": "Dodaj lub usuń zasób z archiwum",
|
"archive_or_unarchive_photo": "Dodaj lub usuń zasób z archiwum",
|
||||||
@@ -520,7 +523,7 @@
|
|||||||
"assets_trashed_from_server": "{count} szt. usuniętych z serwera Immich",
|
"assets_trashed_from_server": "{count} szt. usuniętych z serwera Immich",
|
||||||
"assets_were_part_of_album_count": "{count, plural, one {Zasób był} few {Zasoby były} many {Zasobów było} other {Zasobów było}} już częścią albumu",
|
"assets_were_part_of_album_count": "{count, plural, one {Zasób był} few {Zasoby były} many {Zasobów było} other {Zasobów było}} już częścią albumu",
|
||||||
"assets_were_part_of_albums_count": "{count, plural, one {Zasób był} other {Zasoby były}} już częścią albumów",
|
"assets_were_part_of_albums_count": "{count, plural, one {Zasób był} other {Zasoby były}} już częścią albumów",
|
||||||
"authorized_devices": "Upoważnione Urządzenia",
|
"authorized_devices": "Autoryzowane urządzenia",
|
||||||
"automatic_endpoint_switching_subtitle": "Połącz się lokalnie przez wyznaczoną sieć Wi-Fi, jeśli jest dostępna, i korzystaj z alternatywnych połączeń gdzie indziej",
|
"automatic_endpoint_switching_subtitle": "Połącz się lokalnie przez wyznaczoną sieć Wi-Fi, jeśli jest dostępna, i korzystaj z alternatywnych połączeń gdzie indziej",
|
||||||
"automatic_endpoint_switching_title": "Automatyczne przełączanie adresów URL",
|
"automatic_endpoint_switching_title": "Automatyczne przełączanie adresów URL",
|
||||||
"autoplay_slideshow": "Automatyczne odtwarzanie pokazu slajdów",
|
"autoplay_slideshow": "Automatyczne odtwarzanie pokazu slajdów",
|
||||||
@@ -528,7 +531,7 @@
|
|||||||
"back_close_deselect": "Wróć, zamknij lub odznacz",
|
"back_close_deselect": "Wróć, zamknij lub odznacz",
|
||||||
"background_location_permission": "Uprawnienia do lokalizacji w tle",
|
"background_location_permission": "Uprawnienia do lokalizacji w tle",
|
||||||
"background_location_permission_content": "Aby móc przełączać sieć podczas pracy w tle, Immich musi *zawsze* mieć dostęp do dokładnej lokalizacji, aby aplikacja mogła odczytać nazwę sieci Wi-Fi",
|
"background_location_permission_content": "Aby móc przełączać sieć podczas pracy w tle, Immich musi *zawsze* mieć dostęp do dokładnej lokalizacji, aby aplikacja mogła odczytać nazwę sieci Wi-Fi",
|
||||||
"backup": "Kopia Zapasowa",
|
"backup": "Kopia zapasowa",
|
||||||
"backup_album_selection_page_albums_device": "Albumy na urządzeniu ({count})",
|
"backup_album_selection_page_albums_device": "Albumy na urządzeniu ({count})",
|
||||||
"backup_album_selection_page_albums_tap": "Stuknij, aby włączyć, stuknij dwukrotnie, aby wykluczyć",
|
"backup_album_selection_page_albums_tap": "Stuknij, aby włączyć, stuknij dwukrotnie, aby wykluczyć",
|
||||||
"backup_album_selection_page_assets_scatter": "Pliki mogą być rozproszone w wielu albumach. Dzięki temu albumy mogą być włączane lub wyłączane podczas procesu tworzenia kopii zapasowej.",
|
"backup_album_selection_page_assets_scatter": "Pliki mogą być rozproszone w wielu albumach. Dzięki temu albumy mogą być włączane lub wyłączane podczas procesu tworzenia kopii zapasowej.",
|
||||||
@@ -538,12 +541,12 @@
|
|||||||
"backup_all": "Wszystkie",
|
"backup_all": "Wszystkie",
|
||||||
"backup_background_service_backup_failed_message": "Nie udało się wykonać kopii zapasowej zasobów. Ponowna próba…",
|
"backup_background_service_backup_failed_message": "Nie udało się wykonać kopii zapasowej zasobów. Ponowna próba…",
|
||||||
"backup_background_service_connection_failed_message": "Nie udało się połączyć z serwerem. Ponowna próba…",
|
"backup_background_service_connection_failed_message": "Nie udało się połączyć z serwerem. Ponowna próba…",
|
||||||
"backup_background_service_current_upload_notification": "Wysyłanie {filename}",
|
"backup_background_service_current_upload_notification": "Przesyłanie {filename}",
|
||||||
"backup_background_service_default_notification": "Sprawdzanie nowych zasobów…",
|
"backup_background_service_default_notification": "Sprawdzanie nowych zasobów…",
|
||||||
"backup_background_service_error_title": "Błąd kopii zapasowej",
|
"backup_background_service_error_title": "Błąd kopii zapasowej",
|
||||||
"backup_background_service_in_progress_notification": "Tworzenie kopii zapasowej twoich zasobów…",
|
"backup_background_service_in_progress_notification": "Tworzenie kopii zapasowej twoich zasobów…",
|
||||||
"backup_background_service_upload_failure_notification": "Błąd przesyłania {filename}",
|
"backup_background_service_upload_failure_notification": "Błąd przesyłania {filename}",
|
||||||
"backup_controller_page_albums": "Kopia Zapasowa albumów",
|
"backup_controller_page_albums": "Albumy z włączoną kopią zapasową",
|
||||||
"backup_controller_page_background_app_refresh_disabled_content": "Włącz odświeżanie aplikacji w tle w Ustawienia > Ogólne > Odświeżanie aplikacji w tle, aby móc korzystać z kopii zapasowej w tle.",
|
"backup_controller_page_background_app_refresh_disabled_content": "Włącz odświeżanie aplikacji w tle w Ustawienia > Ogólne > Odświeżanie aplikacji w tle, aby móc korzystać z kopii zapasowej w tle.",
|
||||||
"backup_controller_page_background_app_refresh_disabled_title": "Odświeżanie aplikacji w tle wyłączone",
|
"backup_controller_page_background_app_refresh_disabled_title": "Odświeżanie aplikacji w tle wyłączone",
|
||||||
"backup_controller_page_background_app_refresh_enable_button_text": "Przejdź do ustawień",
|
"backup_controller_page_background_app_refresh_enable_button_text": "Przejdź do ustawień",
|
||||||
@@ -560,29 +563,29 @@
|
|||||||
"backup_controller_page_background_turn_off": "Wyłącz usługę w tle",
|
"backup_controller_page_background_turn_off": "Wyłącz usługę w tle",
|
||||||
"backup_controller_page_background_turn_on": "Włącz usługę w tle",
|
"backup_controller_page_background_turn_on": "Włącz usługę w tle",
|
||||||
"backup_controller_page_background_wifi": "Tylko Wi-Fi",
|
"backup_controller_page_background_wifi": "Tylko Wi-Fi",
|
||||||
"backup_controller_page_backup": "Kopia Zapasowa",
|
"backup_controller_page_backup": "Kopia zapasowa",
|
||||||
"backup_controller_page_backup_selected": "Zaznaczone: ",
|
"backup_controller_page_backup_selected": "Zaznaczone: ",
|
||||||
"backup_controller_page_backup_sub": "Skopiowane zdjęcia oraz filmy",
|
"backup_controller_page_backup_sub": "Zdjęcia i filmy z utworzoną kopią zapasową",
|
||||||
"backup_controller_page_created": "Utworzono dnia: {date}",
|
"backup_controller_page_created": "Utworzono dnia: {date}",
|
||||||
"backup_controller_page_desc_backup": "Włącz kopię zapasową, aby automatycznie przesyłać nowe zasoby na serwer.",
|
"backup_controller_page_desc_backup": "Włącz kopię zapasową na pierwszym planie, aby automatycznie przesyłać nowe zasoby na serwer po otworzeniu aplikacji.",
|
||||||
"backup_controller_page_excluded": "Wykluczone: ",
|
"backup_controller_page_excluded": "Wykluczone: ",
|
||||||
"backup_controller_page_failed": "Nieudane ({count})",
|
"backup_controller_page_failed": "Nieudane ({count})",
|
||||||
"backup_controller_page_filename": "Nazwa pliku: {filename} [{size}]",
|
"backup_controller_page_filename": "Nazwa pliku: {filename} [{size}]",
|
||||||
"backup_controller_page_id": "ID: {id}",
|
"backup_controller_page_id": "ID: {id}",
|
||||||
"backup_controller_page_info": "Informacje o kopii zapasowej",
|
"backup_controller_page_info": "Informacje o kopii zapasowej",
|
||||||
"backup_controller_page_none_selected": "Brak wybranych",
|
"backup_controller_page_none_selected": "Brak wybranych",
|
||||||
"backup_controller_page_remainder": "Reszta",
|
"backup_controller_page_remainder": "Pozostałe",
|
||||||
"backup_controller_page_remainder_sub": "Pozostałe zdjęcia i albumy do wykonania kopii zapasowej z wyboru",
|
"backup_controller_page_remainder_sub": "Pozostałe zdjęcia i filmy wybrane do wykonania kopii zapasowej",
|
||||||
"backup_controller_page_server_storage": "Pamięć Serwera",
|
"backup_controller_page_server_storage": "Pamięć Serwera",
|
||||||
"backup_controller_page_start_backup": "Rozpocznij Kopię Zapasową",
|
"backup_controller_page_start_backup": "Rozpocznij Kopię Zapasową",
|
||||||
"backup_controller_page_status_off": "Kopia Zapasowa jest wyłaczona",
|
"backup_controller_page_status_off": "Automatyczne tworzenie kopii zapasowej na pierwszym planie jest wyłączone",
|
||||||
"backup_controller_page_status_on": "Kopia Zapasowa jest włączona",
|
"backup_controller_page_status_on": "Automatyczne tworzenie kopii zapasowej na pierwszym planie jest włączone",
|
||||||
"backup_controller_page_storage_format": "{used} z {total} wykorzystanych",
|
"backup_controller_page_storage_format": "Wykorzystano {used} z {total}",
|
||||||
"backup_controller_page_to_backup": "Albumy z Kopią Zapasową",
|
"backup_controller_page_to_backup": "Albumy, dla których ma być tworzona kopia zapasowa",
|
||||||
"backup_controller_page_total_sub": "Wszystkie unikalne zdjęcia i filmy z wybranych albumów",
|
"backup_controller_page_total_sub": "Wszystkie unikalne zdjęcia i filmy z wybranych albumów",
|
||||||
"backup_controller_page_turn_off": "Wyłącz Kopię Zapasową",
|
"backup_controller_page_turn_off": "Wyłącz kopię zapasową na pierwszym planie",
|
||||||
"backup_controller_page_turn_on": "Włącz Kopię Zapasową",
|
"backup_controller_page_turn_on": "Włącz kopię zapasową na pierwszym planie",
|
||||||
"backup_controller_page_uploading_file_info": "Przesyłanie informacji o pliku",
|
"backup_controller_page_uploading_file_info": "Informacje o przesyłanym pliku",
|
||||||
"backup_err_only_album": "Nie można usunąć jedynego albumu",
|
"backup_err_only_album": "Nie można usunąć jedynego albumu",
|
||||||
"backup_info_card_assets": "zasoby",
|
"backup_info_card_assets": "zasoby",
|
||||||
"backup_manual_cancelled": "Anulowano",
|
"backup_manual_cancelled": "Anulowano",
|
||||||
@@ -590,9 +593,9 @@
|
|||||||
"backup_manual_success": "Sukces",
|
"backup_manual_success": "Sukces",
|
||||||
"backup_manual_title": "Stan przesyłania",
|
"backup_manual_title": "Stan przesyłania",
|
||||||
"backup_options": "Opcje kopii zapasowej",
|
"backup_options": "Opcje kopii zapasowej",
|
||||||
"backup_options_page_title": "Opcje kopi zapasowej",
|
"backup_options_page_title": "Opcje kopii zapasowej",
|
||||||
"backup_setting_subtitle": "Zarządzaj ustawieniami przesyłania w tle i na pierwszym planie",
|
"backup_setting_subtitle": "Zarządzaj ustawieniami przesyłania w tle i na pierwszym planie",
|
||||||
"backup_settings_subtitle": "Zarządzanie ustawieniami wysyłania",
|
"backup_settings_subtitle": "Zarządzanie ustawieniami przesyłania",
|
||||||
"backward": "Do tyłu",
|
"backward": "Do tyłu",
|
||||||
"beta_sync": "Status synchronizacji w wersji Beta",
|
"beta_sync": "Status synchronizacji w wersji Beta",
|
||||||
"beta_sync_subtitle": "Zarządzaj nowym systemem synchronizacji",
|
"beta_sync_subtitle": "Zarządzaj nowym systemem synchronizacji",
|
||||||
@@ -773,7 +776,7 @@
|
|||||||
"delete_api_key_prompt": "Czy na pewno chcesz usunąć ten klucz API?",
|
"delete_api_key_prompt": "Czy na pewno chcesz usunąć ten klucz API?",
|
||||||
"delete_dialog_alert": "Te elementy zostaną trwale usunięte z Immich i z Twojego urządzenia",
|
"delete_dialog_alert": "Te elementy zostaną trwale usunięte z Immich i z Twojego urządzenia",
|
||||||
"delete_dialog_alert_local": "Elementy te zostaną trwale usunięte z Twojego urządzenia, ale nadal będą dostępne na serwerze Immich",
|
"delete_dialog_alert_local": "Elementy te zostaną trwale usunięte z Twojego urządzenia, ale nadal będą dostępne na serwerze Immich",
|
||||||
"delete_dialog_alert_local_non_backed_up": "Kopia zapasowa niektórych elementów nie jest tworzona w Immich i zostanie trwale usunięta z Twojego urządzenia",
|
"delete_dialog_alert_local_non_backed_up": "Niektóre elementy nie mają kopii zapasowej w Immich i zostaną trwale usunięte z Twojego urządzenia",
|
||||||
"delete_dialog_alert_remote": "Elementy te zostaną trwale usunięte z serwera Immich",
|
"delete_dialog_alert_remote": "Elementy te zostaną trwale usunięte z serwera Immich",
|
||||||
"delete_dialog_ok_force": "Usuń mimo to",
|
"delete_dialog_ok_force": "Usuń mimo to",
|
||||||
"delete_dialog_title": "Usuń trwale",
|
"delete_dialog_title": "Usuń trwale",
|
||||||
@@ -836,7 +839,7 @@
|
|||||||
"downloading": "Pobieranie",
|
"downloading": "Pobieranie",
|
||||||
"downloading_asset_filename": "Pobieranie zasobu {filename}",
|
"downloading_asset_filename": "Pobieranie zasobu {filename}",
|
||||||
"downloading_media": "Pobieranie multimediów",
|
"downloading_media": "Pobieranie multimediów",
|
||||||
"drop_files_to_upload": "Upuść pliki gdziekolwiek, aby je załadować",
|
"drop_files_to_upload": "Upuść pliki w dowolnym miejscu, aby je przesłać",
|
||||||
"duplicates": "Duplikaty",
|
"duplicates": "Duplikaty",
|
||||||
"duplicates_description": "Rozstrzygnij każdą grupę, określając, które zasoby są duplikatami, jeżeli są duplikatami",
|
"duplicates_description": "Rozstrzygnij każdą grupę, określając, które zasoby są duplikatami, jeżeli są duplikatami",
|
||||||
"duration": "Czas trwania",
|
"duration": "Czas trwania",
|
||||||
@@ -1073,12 +1076,18 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Ta funkcja , aby działać, ładuje zewnętrzne zasoby z Google.",
|
"gcast_enabled_description": "Ta funkcja , aby działać, ładuje zewnętrzne zasoby z Google.",
|
||||||
"general": "Ogólne",
|
"general": "Ogólne",
|
||||||
|
"geolocation_instruction_all_have_location": "Wszystkie zasoby z tego dnia mają już dane o lokalizacji. Spróbuj wyświetlić wszystkie zasoby lub wybierz inną datę",
|
||||||
|
"geolocation_instruction_location": "Kliknij na zasób z współrzędnymi GPS, aby użyć jego lokalizacji, lub wybierz lokalizację bezpośrednio z mapy",
|
||||||
|
"geolocation_instruction_no_date": "Wybierz datę, aby zarządzać danymi o lokalizacji dla zdjęć i filmów z tego dnia",
|
||||||
|
"geolocation_instruction_no_photos": "Nie znaleziono żadnych zdjęć ani filmów dla tej daty. Wybierz inną datę, aby je wyświetlić",
|
||||||
"get_help": "Pomoc",
|
"get_help": "Pomoc",
|
||||||
"get_wifiname_error": "Nie można uzyskać nazwy Wi-Fi. Upewnij się, że udzieliłeś niezbędnych uprawnień i jesteś połączony z siecią Wi-Fi",
|
"get_wifiname_error": "Nie można uzyskać nazwy Wi-Fi. Upewnij się, że udzieliłeś niezbędnych uprawnień i jesteś połączony z siecią Wi-Fi",
|
||||||
"getting_started": "Pierwsze kroki",
|
"getting_started": "Pierwsze kroki",
|
||||||
"go_back": "Wstecz",
|
"go_back": "Wstecz",
|
||||||
"go_to_folder": "Idź do folderu",
|
"go_to_folder": "Idź do folderu",
|
||||||
"go_to_search": "Przejdź do wyszukiwania",
|
"go_to_search": "Przejdź do wyszukiwania",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "Brak GPS",
|
||||||
"grant_permission": "Udziel pozwolenia",
|
"grant_permission": "Udziel pozwolenia",
|
||||||
"group_albums_by": "Grupuj albumy...",
|
"group_albums_by": "Grupuj albumy...",
|
||||||
"group_country": "Grupuj według państwa",
|
"group_country": "Grupuj według państwa",
|
||||||
@@ -1186,7 +1195,7 @@
|
|||||||
"large_files": "Duże pliki",
|
"large_files": "Duże pliki",
|
||||||
"last": "Ostatni",
|
"last": "Ostatni",
|
||||||
"last_seen": "Ostatnio widziane",
|
"last_seen": "Ostatnio widziane",
|
||||||
"latest_version": "Najnowsza Wersja",
|
"latest_version": "Najnowsza wersja",
|
||||||
"latitude": "Szerokość geograficzna",
|
"latitude": "Szerokość geograficzna",
|
||||||
"leave": "Opuść",
|
"leave": "Opuść",
|
||||||
"leave_album": "Opuść album",
|
"leave_album": "Opuść album",
|
||||||
@@ -1262,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Używasz wersji deweloperskiej. Zdecydowanie zalecamy korzystanie z wydanej wersji aplikacji!",
|
"main_branch_warning": "Używasz wersji deweloperskiej. Zdecydowanie zalecamy korzystanie z wydanej wersji aplikacji!",
|
||||||
"main_menu": "Menu główne",
|
"main_menu": "Menu główne",
|
||||||
"make": "Marka",
|
"make": "Marka",
|
||||||
|
"manage_geolocation": "Zarządzaj lokalizacją",
|
||||||
"manage_shared_links": "Zarządzaj udostępnionymi linkami",
|
"manage_shared_links": "Zarządzaj udostępnionymi linkami",
|
||||||
"manage_sharing_with_partners": "Zarządzaj dzieleniem z partnerami",
|
"manage_sharing_with_partners": "Zarządzaj dzieleniem z partnerami",
|
||||||
"manage_the_app_settings": "Zarządzaj ustawieniami aplikacji",
|
"manage_the_app_settings": "Zarządzaj ustawieniami aplikacji",
|
||||||
@@ -1417,17 +1427,17 @@
|
|||||||
"owner": "Właściciel",
|
"owner": "Właściciel",
|
||||||
"partner": "Partner",
|
"partner": "Partner",
|
||||||
"partner_can_access": "{partner} ma dostęp do",
|
"partner_can_access": "{partner} ma dostęp do",
|
||||||
"partner_can_access_assets": "Twoje wszystkie zdjęcia i filmy, oprócz tych w Archiwum i Koszu",
|
"partner_can_access_assets": "Wszystkie Twoje zdjęcia i filmy, oprócz tych w Archiwum i Koszu",
|
||||||
"partner_can_access_location": "Informacji o tym, gdzie zostały zrobione Twoje zdjęcia",
|
"partner_can_access_location": "Informacji o tym, gdzie zostały zrobione Twoje zdjęcia",
|
||||||
"partner_list_user_photos": "{user} zdjęcia",
|
"partner_list_user_photos": "Zdjęcia należące do {user}",
|
||||||
"partner_list_view_all": "Pokaż wszystkie",
|
"partner_list_view_all": "Pokaż wszystkie",
|
||||||
"partner_page_empty_message": "Twoje zdjęcia nie są udostępnione żadnemu partnerowi.",
|
"partner_page_empty_message": "Twoje zdjęcia nie są udostępnione żadnemu partnerowi.",
|
||||||
"partner_page_no_more_users": "Brak użytkowników do dodania",
|
"partner_page_no_more_users": "Brak użytkowników do dodania",
|
||||||
"partner_page_partner_add_failed": "Nie udało się dodać partnera",
|
"partner_page_partner_add_failed": "Nie udało się dodać partnera",
|
||||||
"partner_page_select_partner": "Wybierz partnera",
|
"partner_page_select_partner": "Wybierz partnera",
|
||||||
"partner_page_shared_to_title": "Udostępniono",
|
"partner_page_shared_to_title": "Udostępniono",
|
||||||
"partner_page_stop_sharing_content": "{partner} nie będzie już mieć dostępu do twoich zdjęć.",
|
"partner_page_stop_sharing_content": "{partner} nie będzie już mieć dostępu do Twoich zdjęć.",
|
||||||
"partner_sharing": "Dzielenie z Partnerami",
|
"partner_sharing": "Dzielenie z partnerami",
|
||||||
"partners": "Partnerzy",
|
"partners": "Partnerzy",
|
||||||
"password": "Hasło",
|
"password": "Hasło",
|
||||||
"password_does_not_match": "Hasła nie są takie same",
|
"password_does_not_match": "Hasła nie są takie same",
|
||||||
@@ -1504,12 +1514,13 @@
|
|||||||
"privacy": "Prywatność",
|
"privacy": "Prywatność",
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
"profile_drawer_app_logs": "Logi",
|
"profile_drawer_app_logs": "Logi",
|
||||||
"profile_drawer_client_out_of_date_major": "Aplikacja mobilna jest nieaktualna. Zaktualizuj do najnowszej wersji głównej.",
|
"profile_drawer_client_out_of_date_major": "Aplikacja mobilna jest nieaktualna. Zaktualizuj do najnowszej głównej wersji.",
|
||||||
"profile_drawer_client_out_of_date_minor": "Aplikacja mobilna jest nieaktualna. Zaktualizuj do najnowszej wersji dodatkowej.",
|
"profile_drawer_client_out_of_date_minor": "Aplikacja mobilna jest nieaktualna. Zaktualizuj do najnowszej pomniejszej wersji.",
|
||||||
"profile_drawer_client_server_up_to_date": "Klient i serwer są aktualne",
|
"profile_drawer_client_server_up_to_date": "Klient i serwer są aktualne",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
"profile_drawer_server_out_of_date_major": "Serwer jest nieaktualny. Zaktualizuj do najnowszej wersji głównej.",
|
"profile_drawer_readonly_mode": "Włączono tryb tylko do odczytu. Aby wyjść, należy dwukrotnie dotknąć ikony awatara użytkownika.",
|
||||||
"profile_drawer_server_out_of_date_minor": "Serwer jest nieaktualny. Zaktualizuj do najnowszej wersji dodatkowej.",
|
"profile_drawer_server_out_of_date_major": "Serwer jest nieaktualny. Zaktualizuj do najnowszej głównej wersji.",
|
||||||
|
"profile_drawer_server_out_of_date_minor": "Serwer jest nieaktualny. Zaktualizuj do najnowszej pomniejszej wersji.",
|
||||||
"profile_image_of_user": "Zdjęcie profilowe {user}",
|
"profile_image_of_user": "Zdjęcie profilowe {user}",
|
||||||
"profile_picture_set": "Zdjęcie profilowe ustawione.",
|
"profile_picture_set": "Zdjęcie profilowe ustawione.",
|
||||||
"public_album": "Publiczny album",
|
"public_album": "Publiczny album",
|
||||||
@@ -1553,6 +1564,8 @@
|
|||||||
"rating_description": "Wyświetl ocenę z EXIF w panelu informacji",
|
"rating_description": "Wyświetl ocenę z EXIF w panelu informacji",
|
||||||
"reaction_options": "Opcje reakcji",
|
"reaction_options": "Opcje reakcji",
|
||||||
"read_changelog": "Zobacz Zmiany",
|
"read_changelog": "Zobacz Zmiany",
|
||||||
|
"readonly_mode_disabled": "Tryb tylko do odczytu wyłączony",
|
||||||
|
"readonly_mode_enabled": "Tryb tylko do odczytu włączony",
|
||||||
"reassign": "Przypisz ponownie",
|
"reassign": "Przypisz ponownie",
|
||||||
"reassigned_assets_to_existing_person": "Przypisano ponownie {count, plural, one {# zasób} other {# zasobów}} do {name, select, null {istniejącej osoby} other {{name}}}",
|
"reassigned_assets_to_existing_person": "Przypisano ponownie {count, plural, one {# zasób} other {# zasobów}} do {name, select, null {istniejącej osoby} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "Przypisano ponownie {count, plural, one {# zasób} other {# zasobów}} do nowej osoby",
|
"reassigned_assets_to_new_person": "Przypisano ponownie {count, plural, one {# zasób} other {# zasobów}} do nowej osoby",
|
||||||
@@ -1722,10 +1735,11 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu",
|
"select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu",
|
||||||
"selected": "Zaznaczone",
|
"selected": "Zaznaczone",
|
||||||
"selected_count": "{count, plural, other {# wybrane}}",
|
"selected_count": "{count, plural, other {# wybrane}}",
|
||||||
|
"selected_gps_coordinates": "wybrane współrzędne GPS",
|
||||||
"send_message": "Wyślij wiadomość",
|
"send_message": "Wyślij wiadomość",
|
||||||
"send_welcome_email": "Wyślij e-mail powitalny",
|
"send_welcome_email": "Wyślij e-mail powitalny",
|
||||||
"server_endpoint": "Punkt końcowy serwera",
|
"server_endpoint": "Punkt końcowy serwera",
|
||||||
"server_info_box_app_version": "Wersja Aplikacji",
|
"server_info_box_app_version": "Wersja aplikacji",
|
||||||
"server_info_box_server_url": "Adres URL",
|
"server_info_box_server_url": "Adres URL",
|
||||||
"server_offline": "Serwer Offline",
|
"server_offline": "Serwer Offline",
|
||||||
"server_online": "Serwer Online",
|
"server_online": "Serwer Online",
|
||||||
@@ -1832,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "naciśnij ⇧, aby trwale usunąć zasób",
|
"shift_to_permanent_delete": "naciśnij ⇧, aby trwale usunąć zasób",
|
||||||
"show_album_options": "Pokaż opcje albumu",
|
"show_album_options": "Pokaż opcje albumu",
|
||||||
"show_albums": "Pokaż albumy",
|
"show_albums": "Pokaż albumy",
|
||||||
|
"show_all_assets": "Pokaż wszystkie zasoby",
|
||||||
"show_all_people": "Pokaż wszystkie osoby",
|
"show_all_people": "Pokaż wszystkie osoby",
|
||||||
"show_and_hide_people": "Pokaż lub ukryj osoby",
|
"show_and_hide_people": "Pokaż lub ukryj osoby",
|
||||||
|
"show_assets_without_location": "Pokaż zasoby bez lokalizacji",
|
||||||
"show_file_location": "Pokaż ścieżkę pliku",
|
"show_file_location": "Pokaż ścieżkę pliku",
|
||||||
"show_gallery": "Wyświetl galerię",
|
"show_gallery": "Wyświetl galerię",
|
||||||
"show_hidden_people": "Pokaż ukryte osoby",
|
"show_hidden_people": "Pokaż ukryte osoby",
|
||||||
@@ -1885,12 +1901,12 @@
|
|||||||
"stop_casting": "Zatrzymaj strumieniowanie",
|
"stop_casting": "Zatrzymaj strumieniowanie",
|
||||||
"stop_motion_photo": "Zatrzymaj zdjęcie w ruchu",
|
"stop_motion_photo": "Zatrzymaj zdjęcie w ruchu",
|
||||||
"stop_photo_sharing": "Przestać udostępniać swoje zdjęcia?",
|
"stop_photo_sharing": "Przestać udostępniać swoje zdjęcia?",
|
||||||
"stop_photo_sharing_description": "Od teraz {partner} nie będzie widzieć Twoich zdjęć.",
|
"stop_photo_sharing_description": "{partner} nie będzie już mieć dostępu do Twoich zdjęć.",
|
||||||
"stop_sharing_photos_with_user": "Przestań udostępniać zdjęcia temu użytkownikowi",
|
"stop_sharing_photos_with_user": "Przestań udostępniać zdjęcia temu użytkownikowi",
|
||||||
"storage": "Przestrzeń dyskowa",
|
"storage": "Przestrzeń dyskowa",
|
||||||
"storage_label": "Etykieta magazynu",
|
"storage_label": "Etykieta magazynu",
|
||||||
"storage_quota": "Limit pamięci",
|
"storage_quota": "Limit pamięci",
|
||||||
"storage_usage": "{used} z {available} użyte",
|
"storage_usage": "Wykorzystano {used} z {available}",
|
||||||
"submit": "Zatwierdź",
|
"submit": "Zatwierdź",
|
||||||
"success": "Sukces",
|
"success": "Sukces",
|
||||||
"suggestions": "Sugestie",
|
"suggestions": "Sugestie",
|
||||||
@@ -1901,7 +1917,7 @@
|
|||||||
"swap_merge_direction": "Zmień kierunek złączenia",
|
"swap_merge_direction": "Zmień kierunek złączenia",
|
||||||
"sync": "Synchronizuj",
|
"sync": "Synchronizuj",
|
||||||
"sync_albums": "Synchronizuj albumy",
|
"sync_albums": "Synchronizuj albumy",
|
||||||
"sync_albums_manual_subtitle": "Zsynchronizuj wszystkie przesłane filmy i zdjęcia z wybranymi albumami kopii zapasowych",
|
"sync_albums_manual_subtitle": "Zsynchronizuj wszystkie przesłane filmy i zdjęcia z wybranymi albumami z włączoną kopią zapasową",
|
||||||
"sync_local": "Synchronizacja lokalna",
|
"sync_local": "Synchronizacja lokalna",
|
||||||
"sync_remote": "Synchronizacja zdalna",
|
"sync_remote": "Synchronizacja zdalna",
|
||||||
"sync_upload_album_setting_subtitle": "Twórz i przesyłaj swoje zdjęcia i filmy do wybranych albumów w Immich",
|
"sync_upload_album_setting_subtitle": "Twórz i przesyłaj swoje zdjęcia i filmy do wybranych albumów w Immich",
|
||||||
@@ -1946,7 +1962,7 @@
|
|||||||
"to_select": "aby wybrać",
|
"to_select": "aby wybrać",
|
||||||
"to_trash": "Kosz",
|
"to_trash": "Kosz",
|
||||||
"toggle_settings": "Przełącz ustawienia",
|
"toggle_settings": "Przełącz ustawienia",
|
||||||
"total": "Całkowity",
|
"total": "Razem",
|
||||||
"total_usage": "Całkowite wykorzystanie",
|
"total_usage": "Całkowite wykorzystanie",
|
||||||
"trash": "Kosz",
|
"trash": "Kosz",
|
||||||
"trash_action_prompt": "{count} przeniesione do kosza",
|
"trash_action_prompt": "{count} przeniesione do kosza",
|
||||||
@@ -1993,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "{count, plural, one {Rozłożony # zasób} few {Rozłożone # zasoby} other {Rozłożonych # zasobów}}",
|
"unstacked_assets_count": "{count, plural, one {Rozłożony # zasób} few {Rozłożone # zasoby} other {Rozłożonych # zasobów}}",
|
||||||
"untagged": "Nieoznaczone",
|
"untagged": "Nieoznaczone",
|
||||||
"up_next": "Do następnego",
|
"up_next": "Do następnego",
|
||||||
|
"update_location_action_prompt": "Zaktualizuj lokalizację {count} wybranych zasobów na:",
|
||||||
"updated_at": "Zaktualizowany",
|
"updated_at": "Zaktualizowany",
|
||||||
"updated_password": "Pomyślnie zaktualizowano hasło",
|
"updated_password": "Pomyślnie zaktualizowano hasło",
|
||||||
"upload": "Prześlij",
|
"upload": "Prześlij",
|
||||||
@@ -2017,6 +2034,7 @@
|
|||||||
"use_biometric": "Użyj biometrii",
|
"use_biometric": "Użyj biometrii",
|
||||||
"use_current_connection": "użyj bieżącego połączenia",
|
"use_current_connection": "użyj bieżącego połączenia",
|
||||||
"use_custom_date_range": "Zamiast tego użyj niestandardowego zakresu dat",
|
"use_custom_date_range": "Zamiast tego użyj niestandardowego zakresu dat",
|
||||||
|
"use_this_location": "Kliknij, aby użyć lokalizacji",
|
||||||
"user": "Użytkownik",
|
"user": "Użytkownik",
|
||||||
"user_has_been_deleted": "Ten użytkownik został usunięty.",
|
"user_has_been_deleted": "Ten użytkownik został usunięty.",
|
||||||
"user_id": "ID użytkownika",
|
"user_id": "ID użytkownika",
|
||||||
|
|||||||
58
i18n/pt.json
58
i18n/pt.json
@@ -28,6 +28,9 @@
|
|||||||
"add_to_album": "Adicionar ao álbum",
|
"add_to_album": "Adicionar ao álbum",
|
||||||
"add_to_album_bottom_sheet_added": "Adicionado a {album}",
|
"add_to_album_bottom_sheet_added": "Adicionado a {album}",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Já existe em {album}",
|
"add_to_album_bottom_sheet_already_exists": "Já existe em {album}",
|
||||||
|
"add_to_album_toggle": "Alternar seleção para {album}",
|
||||||
|
"add_to_albums": "Adicionar aos álbuns",
|
||||||
|
"add_to_albums_count": "Adicionar aos álbuns ({count})",
|
||||||
"add_to_shared_album": "Adicionar ao álbum partilhado",
|
"add_to_shared_album": "Adicionar ao álbum partilhado",
|
||||||
"add_url": "Adicionar URL",
|
"add_url": "Adicionar URL",
|
||||||
"added_to_archive": "Adicionado ao arquivo",
|
"added_to_archive": "Adicionado ao arquivo",
|
||||||
@@ -355,6 +358,9 @@
|
|||||||
"trash_number_of_days_description": "Número de dias para manter os ficheiros na reciclagem antes de os eliminar permanentemente",
|
"trash_number_of_days_description": "Número de dias para manter os ficheiros na reciclagem antes de os eliminar permanentemente",
|
||||||
"trash_settings": "Definições da Reciclagem",
|
"trash_settings": "Definições da Reciclagem",
|
||||||
"trash_settings_description": "Gerir definições da reciclagem",
|
"trash_settings_description": "Gerir definições da reciclagem",
|
||||||
|
"unlink_all_oauth_accounts": "Desvincular todas as contas OAuth",
|
||||||
|
"unlink_all_oauth_accounts_description": "Lembre-se de desvincular todas as contas OAuth antes de migrar para um novo provedor.",
|
||||||
|
"unlink_all_oauth_accounts_prompt": "Tem a certeza de que deseja desvincular todas as contas OAuth? Isso redefinirá o ID OAuth de cada utilizador e não poderá ser desfeito.",
|
||||||
"user_cleanup_job": "Limpeza de utilizadores",
|
"user_cleanup_job": "Limpeza de utilizadores",
|
||||||
"user_delete_delay": "A conta e os ficheiros de <b>{user}</b> serão agendados para eliminação permanente dentro de {delay, plural, one {# dia} other {# dias}}.",
|
"user_delete_delay": "A conta e os ficheiros de <b>{user}</b> serão agendados para eliminação permanente dentro de {delay, plural, one {# dia} other {# dias}}.",
|
||||||
"user_delete_delay_settings": "Atraso de eliminação",
|
"user_delete_delay_settings": "Atraso de eliminação",
|
||||||
@@ -390,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Preferir imagens do servidor",
|
"advanced_settings_prefer_remote_title": "Preferir imagens do servidor",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Defina os cabeçalhos do proxy que o Immich deve enviar em todas comunicações com a rede",
|
"advanced_settings_proxy_headers_subtitle": "Defina os cabeçalhos do proxy que o Immich deve enviar em todas comunicações com a rede",
|
||||||
"advanced_settings_proxy_headers_title": "Cabeçalhos do Proxy",
|
"advanced_settings_proxy_headers_title": "Cabeçalhos do Proxy",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Activa o modo somente leitura, onde as fotos podem ser visualizadas. Recursos como selecionar várias imagens, partilhar, transmitir e excluir ficam deactivados. Activar/Desactivar o modo somente leitura via avatar do utilizador na janela principal",
|
||||||
|
"advanced_settings_readonly_mode_title": "Modo somente leitura",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Não validar o certificado SSL com o endereço do servidor. Isto é necessário para certificados auto-assinados.",
|
"advanced_settings_self_signed_ssl_subtitle": "Não validar o certificado SSL com o endereço do servidor. Isto é necessário para certificados auto-assinados.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Permitir certificados SSL auto-assinados",
|
"advanced_settings_self_signed_ssl_title": "Permitir certificados SSL auto-assinados",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Automaticamente eliminar ou restaurar um ficheiro neste dispositivo quando essa mesma ação for efetuada na web",
|
"advanced_settings_sync_remote_deletions_subtitle": "Automaticamente eliminar ou restaurar um ficheiro neste dispositivo quando essa mesma ação for efetuada na web",
|
||||||
@@ -455,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Sair",
|
"app_bar_signout_dialog_title": "Sair",
|
||||||
"app_settings": "Definições da Aplicação",
|
"app_settings": "Definições da Aplicação",
|
||||||
"appears_in": "Aparece em",
|
"appears_in": "Aparece em",
|
||||||
|
"apply_count": "Aplicar ({count, number})",
|
||||||
"archive": "Arquivo",
|
"archive": "Arquivo",
|
||||||
"archive_action_prompt": "{count} adicionados ao Arquivo",
|
"archive_action_prompt": "{count} adicionados ao Arquivo",
|
||||||
"archive_or_unarchive_photo": "Arquivar ou desarquivar foto",
|
"archive_or_unarchive_photo": "Arquivar ou desarquivar foto",
|
||||||
@@ -494,7 +503,9 @@
|
|||||||
"assets": "Ficheiros",
|
"assets": "Ficheiros",
|
||||||
"assets_added_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}}",
|
"assets_added_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}}",
|
||||||
"assets_added_to_album_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} ao álbum",
|
"assets_added_to_album_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} ao álbum",
|
||||||
|
"assets_added_to_albums_count": "Adicionado {assetTotal, plural, one {# asset} other {# assets}} a {albumTotal, plural, one {# album} other {# albums}}",
|
||||||
"assets_cannot_be_added_to_album_count": "Não foi possível adicionar {count, plural, one {ficheiro} other {ficheiros}} ao álbum",
|
"assets_cannot_be_added_to_album_count": "Não foi possível adicionar {count, plural, one {ficheiro} other {ficheiros}} ao álbum",
|
||||||
|
"assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} não pode ser adicionado a nenhum dos álbuns",
|
||||||
"assets_count": "{count, plural, one {# ficheiro} other {# ficheiros}}",
|
"assets_count": "{count, plural, one {# ficheiro} other {# ficheiros}}",
|
||||||
"assets_deleted_permanently": "{count} ficheiro(s) eliminado(s) permanentemente",
|
"assets_deleted_permanently": "{count} ficheiro(s) eliminado(s) permanentemente",
|
||||||
"assets_deleted_permanently_from_server": "{count} ficheiro(s) eliminado(s) permanentemente do servidor Immich",
|
"assets_deleted_permanently_from_server": "{count} ficheiro(s) eliminado(s) permanentemente do servidor Immich",
|
||||||
@@ -511,6 +522,7 @@
|
|||||||
"assets_trashed_count": "{count, plural, one {# ficheiro enviado} other {# ficheiros enviados}} para a reciclagem",
|
"assets_trashed_count": "{count, plural, one {# ficheiro enviado} other {# ficheiros enviados}} para a reciclagem",
|
||||||
"assets_trashed_from_server": "{count} ficheiro(s) do servidor Immich foi/foram enviados para a reciclagem",
|
"assets_trashed_from_server": "{count} ficheiro(s) do servidor Immich foi/foram enviados para a reciclagem",
|
||||||
"assets_were_part_of_album_count": "{count, plural, one {O ficheiro já fazia} other {Os ficheiros já faziam}} parte do álbum",
|
"assets_were_part_of_album_count": "{count, plural, one {O ficheiro já fazia} other {Os ficheiros já faziam}} parte do álbum",
|
||||||
|
"assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} já faz parte dos álbuns",
|
||||||
"authorized_devices": "Dispositivos Autorizados",
|
"authorized_devices": "Dispositivos Autorizados",
|
||||||
"automatic_endpoint_switching_subtitle": "Conecte-se localmente quando estiver em uma rede uma Wi-Fi específica e use conexões alternativas em outras redes",
|
"automatic_endpoint_switching_subtitle": "Conecte-se localmente quando estiver em uma rede uma Wi-Fi específica e use conexões alternativas em outras redes",
|
||||||
"automatic_endpoint_switching_title": "Troca automática de URL",
|
"automatic_endpoint_switching_title": "Troca automática de URL",
|
||||||
@@ -749,6 +761,7 @@
|
|||||||
"date_of_birth_saved": "Data de nascimento guardada com sucesso",
|
"date_of_birth_saved": "Data de nascimento guardada com sucesso",
|
||||||
"date_range": "Intervalo de datas",
|
"date_range": "Intervalo de datas",
|
||||||
"day": "Dia",
|
"day": "Dia",
|
||||||
|
"days": "Dias",
|
||||||
"deduplicate_all": "Remover todos os duplicados",
|
"deduplicate_all": "Remover todos os duplicados",
|
||||||
"deduplication_criteria_1": "Tamanho da imagem em bytes",
|
"deduplication_criteria_1": "Tamanho da imagem em bytes",
|
||||||
"deduplication_criteria_2": "Quantidade de dados EXIF",
|
"deduplication_criteria_2": "Quantidade de dados EXIF",
|
||||||
@@ -833,10 +846,12 @@
|
|||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
"edit_album": "Editar álbum",
|
"edit_album": "Editar álbum",
|
||||||
"edit_avatar": "Editar imagem de perfil",
|
"edit_avatar": "Editar imagem de perfil",
|
||||||
"edit_birthday": "Alterar aniversário",
|
"edit_birthday": "Editar aniversário",
|
||||||
"edit_date": "Editar data",
|
"edit_date": "Editar data",
|
||||||
"edit_date_and_time": "Editar data e hora",
|
"edit_date_and_time": "Editar data e hora",
|
||||||
"edit_date_and_time_action_prompt": "Alterada a data e hora de {count} ficheiros",
|
"edit_date_and_time_action_prompt": "Alterada a data e hora de {count} ficheiros",
|
||||||
|
"edit_date_and_time_by_offset": "Alterar data com diferença",
|
||||||
|
"edit_date_and_time_by_offset_interval": "Novo período: {from} - {to}",
|
||||||
"edit_description": "Editar descrição",
|
"edit_description": "Editar descrição",
|
||||||
"edit_description_prompt": "Por favor selecione uma nova descrição:",
|
"edit_description_prompt": "Por favor selecione uma nova descrição:",
|
||||||
"edit_exclusion_pattern": "Editar o padrão de exclusão",
|
"edit_exclusion_pattern": "Editar o padrão de exclusão",
|
||||||
@@ -909,6 +924,7 @@
|
|||||||
"failed_to_load_notifications": "Ocorreu um erro ao carregar notificações",
|
"failed_to_load_notifications": "Ocorreu um erro ao carregar notificações",
|
||||||
"failed_to_load_people": "Ocorreu um erro ao carregar pessoas",
|
"failed_to_load_people": "Ocorreu um erro ao carregar pessoas",
|
||||||
"failed_to_remove_product_key": "Ocorreu um erro ao remover chave de produto",
|
"failed_to_remove_product_key": "Ocorreu um erro ao remover chave de produto",
|
||||||
|
"failed_to_reset_pin_code": "Falha ao repor o código PIN",
|
||||||
"failed_to_stack_assets": "Ocorreu um erro ao empilhar os ficheiros",
|
"failed_to_stack_assets": "Ocorreu um erro ao empilhar os ficheiros",
|
||||||
"failed_to_unstack_assets": "Ocorreu um erro ao desempilhar ficheiros",
|
"failed_to_unstack_assets": "Ocorreu um erro ao desempilhar ficheiros",
|
||||||
"failed_to_update_notification_status": "Ocorreu um erro ao atualizar o estado das notificações",
|
"failed_to_update_notification_status": "Ocorreu um erro ao atualizar o estado das notificações",
|
||||||
@@ -917,6 +933,7 @@
|
|||||||
"paths_validation_failed": "Ocorreu um erro na validação de {paths, plural, one {# caminho} other {# caminhos}}",
|
"paths_validation_failed": "Ocorreu um erro na validação de {paths, plural, one {# caminho} other {# caminhos}}",
|
||||||
"profile_picture_transparent_pixels": "Imagem de perfil não pode ter pixeis transparentes. Por favor amplie e/ou mova a imagem.",
|
"profile_picture_transparent_pixels": "Imagem de perfil não pode ter pixeis transparentes. Por favor amplie e/ou mova a imagem.",
|
||||||
"quota_higher_than_disk_size": "Definiu uma quota maior do que o tamanho do disco",
|
"quota_higher_than_disk_size": "Definiu uma quota maior do que o tamanho do disco",
|
||||||
|
"something_went_wrong": "Algo deu errado",
|
||||||
"unable_to_add_album_users": "Não foi possível adicionar utilizadores ao álbum",
|
"unable_to_add_album_users": "Não foi possível adicionar utilizadores ao álbum",
|
||||||
"unable_to_add_assets_to_shared_link": "Não foi possível adicionar os ficheiros ao link partilhado",
|
"unable_to_add_assets_to_shared_link": "Não foi possível adicionar os ficheiros ao link partilhado",
|
||||||
"unable_to_add_comment": "Não foi possível adicionar o comentário",
|
"unable_to_add_comment": "Não foi possível adicionar o comentário",
|
||||||
@@ -1048,21 +1065,29 @@
|
|||||||
"filter_people": "Filtrar pessoas",
|
"filter_people": "Filtrar pessoas",
|
||||||
"filter_places": "Filtrar lugares",
|
"filter_places": "Filtrar lugares",
|
||||||
"find_them_fast": "Encontre-as mais rapidamente pelo nome numa pesquisa",
|
"find_them_fast": "Encontre-as mais rapidamente pelo nome numa pesquisa",
|
||||||
|
"first": "Primeiro",
|
||||||
"fix_incorrect_match": "Corrigir correspondência incorreta",
|
"fix_incorrect_match": "Corrigir correspondência incorreta",
|
||||||
"folder": "Pasta",
|
"folder": "Pasta",
|
||||||
"folder_not_found": "Pasta não encontrada",
|
"folder_not_found": "Pasta não encontrada",
|
||||||
"folders": "Pastas",
|
"folders": "Pastas",
|
||||||
"folders_feature_description": "Navegar na vista de pastas por fotos e vídeos no sistema de ficheiros",
|
"folders_feature_description": "Navegar na vista de pastas por fotos e vídeos no sistema de ficheiros",
|
||||||
|
"forgot_pin_code_question": "Esqueceu o seu PIN?",
|
||||||
"forward": "Para a frente",
|
"forward": "Para a frente",
|
||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Esta funcionalidade requer o carregamento de recursos externos da Google para poder funcionar.",
|
"gcast_enabled_description": "Esta funcionalidade requer o carregamento de recursos externos da Google para poder funcionar.",
|
||||||
"general": "Geral",
|
"general": "Geral",
|
||||||
|
"geolocation_instruction_all_have_location": "Todos os activos desta data já possuem dados de localização. Tente exibir todos os ativos ou seleccione uma data diferente",
|
||||||
|
"geolocation_instruction_location": "Clique num ativo com coordenadas GPS para usar a sua localização ou seleccione um local diretamente do mapa",
|
||||||
|
"geolocation_instruction_no_date": "Seleccione uma data para gerir os dados de localização de fotos e vídeos daquele dia",
|
||||||
|
"geolocation_instruction_no_photos": "Nenhuma foto ou vídeo encontrado para esta data. Seleccione uma data diferente para exibi-los",
|
||||||
"get_help": "Obter Ajuda",
|
"get_help": "Obter Ajuda",
|
||||||
"get_wifiname_error": "Não foi possível obter o nome do Wi-Fi. Verifique se concedeu as permissões necessárias e se está conectado a uma rede Wi-Fi",
|
"get_wifiname_error": "Não foi possível obter o nome do Wi-Fi. Verifique se concedeu as permissões necessárias e se está conectado a uma rede Wi-Fi",
|
||||||
"getting_started": "Primeiros Passos",
|
"getting_started": "Primeiros Passos",
|
||||||
"go_back": "Regressar",
|
"go_back": "Regressar",
|
||||||
"go_to_folder": "Ir para a pasta",
|
"go_to_folder": "Ir para a pasta",
|
||||||
"go_to_search": "Ir para a pesquisa",
|
"go_to_search": "Ir para a pesquisa",
|
||||||
|
"gps": "GPS",
|
||||||
|
"gps_missing": "Sem GPS",
|
||||||
"grant_permission": "Conceder permissão",
|
"grant_permission": "Conceder permissão",
|
||||||
"group_albums_by": "Agrupar álbuns por...",
|
"group_albums_by": "Agrupar álbuns por...",
|
||||||
"group_country": "Agrupar por país",
|
"group_country": "Agrupar por país",
|
||||||
@@ -1107,6 +1132,7 @@
|
|||||||
"home_page_upload_err_limit": "Só é possível enviar 30 arquivos por vez, ignorando",
|
"home_page_upload_err_limit": "Só é possível enviar 30 arquivos por vez, ignorando",
|
||||||
"host": "Servidor",
|
"host": "Servidor",
|
||||||
"hour": "Hora",
|
"hour": "Hora",
|
||||||
|
"hours": "Horas",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"idle": "Em espera",
|
"idle": "Em espera",
|
||||||
"ignore_icloud_photos": "ignorar fotos no iCloud",
|
"ignore_icloud_photos": "ignorar fotos no iCloud",
|
||||||
@@ -1167,6 +1193,7 @@
|
|||||||
"language_search_hint": "Procurar línguas...",
|
"language_search_hint": "Procurar línguas...",
|
||||||
"language_setting_description": "Selecione o seu Idioma preferido",
|
"language_setting_description": "Selecione o seu Idioma preferido",
|
||||||
"large_files": "Ficheiros Grandes",
|
"large_files": "Ficheiros Grandes",
|
||||||
|
"last": "Último",
|
||||||
"last_seen": "Visto pela ultima vez",
|
"last_seen": "Visto pela ultima vez",
|
||||||
"latest_version": "Versão mais recente",
|
"latest_version": "Versão mais recente",
|
||||||
"latitude": "Latitude",
|
"latitude": "Latitude",
|
||||||
@@ -1185,6 +1212,7 @@
|
|||||||
"library_page_sort_title": "Título do álbum",
|
"library_page_sort_title": "Título do álbum",
|
||||||
"licenses": "Licenças",
|
"licenses": "Licenças",
|
||||||
"light": "Claro",
|
"light": "Claro",
|
||||||
|
"like": "Gostar",
|
||||||
"like_deleted": "Gosto removido",
|
"like_deleted": "Gosto removido",
|
||||||
"link_motion_video": "Relacionar video animado",
|
"link_motion_video": "Relacionar video animado",
|
||||||
"link_to_oauth": "Link do OAuth",
|
"link_to_oauth": "Link do OAuth",
|
||||||
@@ -1243,6 +1271,7 @@
|
|||||||
"main_branch_warning": "Está a utilizar uma versão de desenvolvimento, recomendamos vivamente que utilize uma versão estável!",
|
"main_branch_warning": "Está a utilizar uma versão de desenvolvimento, recomendamos vivamente que utilize uma versão estável!",
|
||||||
"main_menu": "Menu Principal",
|
"main_menu": "Menu Principal",
|
||||||
"make": "Marca",
|
"make": "Marca",
|
||||||
|
"manage_geolocation": "Gerir localização",
|
||||||
"manage_shared_links": "Gerir links partilhados",
|
"manage_shared_links": "Gerir links partilhados",
|
||||||
"manage_sharing_with_partners": "Gerir partilha com parceiros",
|
"manage_sharing_with_partners": "Gerir partilha com parceiros",
|
||||||
"manage_the_app_settings": "Gerir definições da aplicação",
|
"manage_the_app_settings": "Gerir definições da aplicação",
|
||||||
@@ -1251,7 +1280,7 @@
|
|||||||
"manage_your_devices": "Gerir os seus dispositivos com sessão iniciada",
|
"manage_your_devices": "Gerir os seus dispositivos com sessão iniciada",
|
||||||
"manage_your_oauth_connection": "Gerir a sua ligação ao OAuth",
|
"manage_your_oauth_connection": "Gerir a sua ligação ao OAuth",
|
||||||
"map": "Mapa",
|
"map": "Mapa",
|
||||||
"map_assets_in_bounds": "{count, plural, one {# foto} other {# fotos}}",
|
"map_assets_in_bounds": "{count, plural, =0 {No photos in this area} one {# photo} other {# photos}}",
|
||||||
"map_cannot_get_user_location": "Impossível obter a sua localização",
|
"map_cannot_get_user_location": "Impossível obter a sua localização",
|
||||||
"map_location_dialog_yes": "Sim",
|
"map_location_dialog_yes": "Sim",
|
||||||
"map_location_picker_page_use_location": "Utilizar esta localização",
|
"map_location_picker_page_use_location": "Utilizar esta localização",
|
||||||
@@ -1295,6 +1324,7 @@
|
|||||||
"merged_people_count": "Unidas {count, plural, one {# pessoa} other {# pessoas}}",
|
"merged_people_count": "Unidas {count, plural, one {# pessoa} other {# pessoas}}",
|
||||||
"minimize": "Minimizar",
|
"minimize": "Minimizar",
|
||||||
"minute": "Minuto",
|
"minute": "Minuto",
|
||||||
|
"minutes": "Minutos",
|
||||||
"missing": "Em falta",
|
"missing": "Em falta",
|
||||||
"model": "Modelo",
|
"model": "Modelo",
|
||||||
"month": "Mês",
|
"month": "Mês",
|
||||||
@@ -1314,6 +1344,9 @@
|
|||||||
"my_albums": "Os meus álbuns",
|
"my_albums": "Os meus álbuns",
|
||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"name_or_nickname": "Nome ou alcunha",
|
"name_or_nickname": "Nome ou alcunha",
|
||||||
|
"network_requirement_photos_upload": "Usar dados móveis para fazer backup de fotos",
|
||||||
|
"network_requirement_videos_upload": "Usar dados móveis para fazer backup de vídeos",
|
||||||
|
"network_requirements_updated": "Requisitos de rede alterados, redefinindo fila de backup",
|
||||||
"networking_settings": "Conexões",
|
"networking_settings": "Conexões",
|
||||||
"networking_subtitle": "Gerencie a conexão do servidor",
|
"networking_subtitle": "Gerencie a conexão do servidor",
|
||||||
"never": "Nunca",
|
"never": "Nunca",
|
||||||
@@ -1365,6 +1398,7 @@
|
|||||||
"oauth": "OAuth",
|
"oauth": "OAuth",
|
||||||
"official_immich_resources": "Recursos oficiais do Immich",
|
"official_immich_resources": "Recursos oficiais do Immich",
|
||||||
"offline": "Offline",
|
"offline": "Offline",
|
||||||
|
"offset": "Desvio",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"oldest_first": "Mais antigo primeiro",
|
"oldest_first": "Mais antigo primeiro",
|
||||||
"on_this_device": "Neste dispositivo",
|
"on_this_device": "Neste dispositivo",
|
||||||
@@ -1442,6 +1476,9 @@
|
|||||||
"permission_onboarding_permission_limited": "Permissão limitada. Para permitir que o Immich faça backups e gerencie sua galeria, conceda permissões para fotos e vídeos nas configurações.",
|
"permission_onboarding_permission_limited": "Permissão limitada. Para permitir que o Immich faça backups e gerencie sua galeria, conceda permissões para fotos e vídeos nas configurações.",
|
||||||
"permission_onboarding_request": "O Immich requer autorização para ver as suas fotos e vídeos.",
|
"permission_onboarding_request": "O Immich requer autorização para ver as suas fotos e vídeos.",
|
||||||
"person": "Pessoa",
|
"person": "Pessoa",
|
||||||
|
"person_age_months": "{months, plural, one {# month} other {# months}} idade",
|
||||||
|
"person_age_year_months": "1 ano, {months, plural, one {# month} other {# months}} idade",
|
||||||
|
"person_age_years": "{years, plural, other {# years}} idade",
|
||||||
"person_birthdate": "Nasceu a {date}",
|
"person_birthdate": "Nasceu a {date}",
|
||||||
"person_hidden": "{name}{hidden, select, true { (oculto)} other {}}",
|
"person_hidden": "{name}{hidden, select, true { (oculto)} other {}}",
|
||||||
"photo_shared_all_users": "Parece que partilhou as suas fotos com todos os utilizadores ou não tem nenhum utilizador para partilhar.",
|
"photo_shared_all_users": "Parece que partilhou as suas fotos com todos os utilizadores ou não tem nenhum utilizador para partilhar.",
|
||||||
@@ -1481,6 +1518,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.",
|
"profile_drawer_client_out_of_date_minor": "O aplicativo está desatualizado. Por favor, atualize para a versão mais recente.",
|
||||||
"profile_drawer_client_server_up_to_date": "Cliente e Servidor atualizados",
|
"profile_drawer_client_server_up_to_date": "Cliente e Servidor atualizados",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "Modo somente leitura activado. Toque duas vezes no ícone do avatar do utilizador para sair.",
|
||||||
"profile_drawer_server_out_of_date_major": "O servidor está desatualizado. Atualize para a versão principal mais recente.",
|
"profile_drawer_server_out_of_date_major": "O servidor está desatualizado. Atualize para a versão principal mais recente.",
|
||||||
"profile_drawer_server_out_of_date_minor": "O servidor está desatualizado. Atualize para a versão mais recente.",
|
"profile_drawer_server_out_of_date_minor": "O servidor está desatualizado. Atualize para a versão mais recente.",
|
||||||
"profile_image_of_user": "Imagem de perfil de {user}",
|
"profile_image_of_user": "Imagem de perfil de {user}",
|
||||||
@@ -1526,6 +1564,8 @@
|
|||||||
"rating_description": "Mostrar a classificação EXIF no painel de informações",
|
"rating_description": "Mostrar a classificação EXIF no painel de informações",
|
||||||
"reaction_options": "Opções de reação",
|
"reaction_options": "Opções de reação",
|
||||||
"read_changelog": "Ler Novidades",
|
"read_changelog": "Ler Novidades",
|
||||||
|
"readonly_mode_disabled": "Modo somente leitura desactivado",
|
||||||
|
"readonly_mode_enabled": "Modo somente leitura activado",
|
||||||
"reassign": "Reatribuir",
|
"reassign": "Reatribuir",
|
||||||
"reassigned_assets_to_existing_person": "Reatribuir {count, plural, one {# ficheiro} other {# ficheiros}} para {name, select, null {uma pessoa existente} other {{name}}}",
|
"reassigned_assets_to_existing_person": "Reatribuir {count, plural, one {# ficheiro} other {# ficheiros}} para {name, select, null {uma pessoa existente} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "Reatribuído {count, plural, one {# ficheiro} other {# ficheiros}} a uma nova pessoa",
|
"reassigned_assets_to_new_person": "Reatribuído {count, plural, one {# ficheiro} other {# ficheiros}} a uma nova pessoa",
|
||||||
@@ -1587,6 +1627,9 @@
|
|||||||
"reset_password": "Redefinir palavra-passe",
|
"reset_password": "Redefinir palavra-passe",
|
||||||
"reset_people_visibility": "Redefinir pessoas ocultas",
|
"reset_people_visibility": "Redefinir pessoas ocultas",
|
||||||
"reset_pin_code": "Repor código PIN",
|
"reset_pin_code": "Repor código PIN",
|
||||||
|
"reset_pin_code_description": "Se esqueceu o seu código PIN, pode entrar em contato com o administrador do servidor para o repor",
|
||||||
|
"reset_pin_code_success": "Código PIN redefinido com sucesso",
|
||||||
|
"reset_pin_code_with_password": "Pode sempre repor o seu código PIN com a sua senha",
|
||||||
"reset_sqlite": "Reiniciar Base de Dados SQLite",
|
"reset_sqlite": "Reiniciar Base de Dados SQLite",
|
||||||
"reset_sqlite_confirmation": "Tem a certeza de que quer reiniciar a base de dados SQLite? Vai ter de terminar a sessão e entrar outra vez para sincronizar os dados de novo",
|
"reset_sqlite_confirmation": "Tem a certeza de que quer reiniciar a base de dados SQLite? Vai ter de terminar a sessão e entrar outra vez para sincronizar os dados de novo",
|
||||||
"reset_sqlite_success": "Base de dados SQLite reiniciada com sucesso",
|
"reset_sqlite_success": "Base de dados SQLite reiniciada com sucesso",
|
||||||
@@ -1601,6 +1644,7 @@
|
|||||||
"resume": "Continuar",
|
"resume": "Continuar",
|
||||||
"retry_upload": "Tentar carregar novamente",
|
"retry_upload": "Tentar carregar novamente",
|
||||||
"review_duplicates": "Rever itens duplicados",
|
"review_duplicates": "Rever itens duplicados",
|
||||||
|
"review_large_files": "Rever arquivos grandes",
|
||||||
"role": "Função",
|
"role": "Função",
|
||||||
"role_editor": "Editor",
|
"role_editor": "Editor",
|
||||||
"role_viewer": "Visualizador",
|
"role_viewer": "Visualizador",
|
||||||
@@ -1691,6 +1735,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Ocorreu um erro ao criar o álbum",
|
"select_user_for_sharing_page_err_album": "Ocorreu um erro ao criar o álbum",
|
||||||
"selected": "Selecionados",
|
"selected": "Selecionados",
|
||||||
"selected_count": "{count, plural, other {# selecionados}}",
|
"selected_count": "{count, plural, other {# selecionados}}",
|
||||||
|
"selected_gps_coordinates": "coordenadas gps seleccionadas",
|
||||||
"send_message": "Enviar mensagem",
|
"send_message": "Enviar mensagem",
|
||||||
"send_welcome_email": "Enviar E-mail de boas vindas",
|
"send_welcome_email": "Enviar E-mail de boas vindas",
|
||||||
"server_endpoint": "URL do servidor",
|
"server_endpoint": "URL do servidor",
|
||||||
@@ -1758,6 +1803,7 @@
|
|||||||
"shared_link_clipboard_copied_massage": "Copiado para a área de transferência",
|
"shared_link_clipboard_copied_massage": "Copiado para a área de transferência",
|
||||||
"shared_link_clipboard_text": "Ligação: {link}\nPalavra-passe: {password}",
|
"shared_link_clipboard_text": "Ligação: {link}\nPalavra-passe: {password}",
|
||||||
"shared_link_create_error": "Erro ao criar o link compartilhado",
|
"shared_link_create_error": "Erro ao criar o link compartilhado",
|
||||||
|
"shared_link_custom_url_description": "Aceda a este link partilhado com um URL personalizado",
|
||||||
"shared_link_edit_description_hint": "Digite a descrição do compartilhamento",
|
"shared_link_edit_description_hint": "Digite a descrição do compartilhamento",
|
||||||
"shared_link_edit_expire_after_option_day": "1 dia",
|
"shared_link_edit_expire_after_option_day": "1 dia",
|
||||||
"shared_link_edit_expire_after_option_days": "{count} dias",
|
"shared_link_edit_expire_after_option_days": "{count} dias",
|
||||||
@@ -1783,6 +1829,7 @@
|
|||||||
"shared_link_info_chip_metadata": "EXIF",
|
"shared_link_info_chip_metadata": "EXIF",
|
||||||
"shared_link_manage_links": "Gerenciar links compartilhados",
|
"shared_link_manage_links": "Gerenciar links compartilhados",
|
||||||
"shared_link_options": "Opções de link partilhado",
|
"shared_link_options": "Opções de link partilhado",
|
||||||
|
"shared_link_password_description": "Exigir uma senha para aceder a este link partilhado",
|
||||||
"shared_links": "Links partilhados",
|
"shared_links": "Links partilhados",
|
||||||
"shared_links_description": "Partilhar fotos e videos com um link",
|
"shared_links_description": "Partilhar fotos e videos com um link",
|
||||||
"shared_photos_and_videos_count": "{assetCount, plural, other {# Fotos & videos partilhados.}}",
|
"shared_photos_and_videos_count": "{assetCount, plural, other {# Fotos & videos partilhados.}}",
|
||||||
@@ -1799,8 +1846,10 @@
|
|||||||
"shift_to_permanent_delete": "Pressione ⇧ para eliminar o ficheiro permanentemente",
|
"shift_to_permanent_delete": "Pressione ⇧ para eliminar o ficheiro permanentemente",
|
||||||
"show_album_options": "Exibir opções do álbum",
|
"show_album_options": "Exibir opções do álbum",
|
||||||
"show_albums": "Mostrar álbuns",
|
"show_albums": "Mostrar álbuns",
|
||||||
|
"show_all_assets": "Mostrar todos os recursos",
|
||||||
"show_all_people": "Mostrar todas as pessoas",
|
"show_all_people": "Mostrar todas as pessoas",
|
||||||
"show_and_hide_people": "Mostrar & ocultar pessoas",
|
"show_and_hide_people": "Mostrar & ocultar pessoas",
|
||||||
|
"show_assets_without_location": "Mostrar recursos sem localização",
|
||||||
"show_file_location": "Exibir localização do ficheiro",
|
"show_file_location": "Exibir localização do ficheiro",
|
||||||
"show_gallery": "Exibir galeria",
|
"show_gallery": "Exibir galeria",
|
||||||
"show_hidden_people": "Exibir pessoas ocultadas",
|
"show_hidden_people": "Exibir pessoas ocultadas",
|
||||||
@@ -1832,6 +1881,7 @@
|
|||||||
"sort_created": "Data de criação",
|
"sort_created": "Data de criação",
|
||||||
"sort_items": "Número de itens",
|
"sort_items": "Número de itens",
|
||||||
"sort_modified": "Data de modificação",
|
"sort_modified": "Data de modificação",
|
||||||
|
"sort_newest": "A foto mais recente",
|
||||||
"sort_oldest": "Foto mais antiga",
|
"sort_oldest": "Foto mais antiga",
|
||||||
"sort_people_by_similarity": "Ordenar pessoas por semelhança",
|
"sort_people_by_similarity": "Ordenar pessoas por semelhança",
|
||||||
"sort_recent": "Foto mais recente",
|
"sort_recent": "Foto mais recente",
|
||||||
@@ -1907,7 +1957,9 @@
|
|||||||
"to_change_password": "Alterar palavra-passe",
|
"to_change_password": "Alterar palavra-passe",
|
||||||
"to_favorite": "Favorito",
|
"to_favorite": "Favorito",
|
||||||
"to_login": "Iniciar Sessão",
|
"to_login": "Iniciar Sessão",
|
||||||
|
"to_multi_select": "multi-selecção",
|
||||||
"to_parent": "Subir um nível",
|
"to_parent": "Subir um nível",
|
||||||
|
"to_select": "seleccionar",
|
||||||
"to_trash": "Reciclagem",
|
"to_trash": "Reciclagem",
|
||||||
"toggle_settings": "Alternar configurações",
|
"toggle_settings": "Alternar configurações",
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
@@ -1957,6 +2009,7 @@
|
|||||||
"unstacked_assets_count": "Desempilhados {count, plural, one {# ficheiro} other {# ficheiros}}",
|
"unstacked_assets_count": "Desempilhados {count, plural, one {# ficheiro} other {# ficheiros}}",
|
||||||
"untagged": "Marcador removido",
|
"untagged": "Marcador removido",
|
||||||
"up_next": "A seguir",
|
"up_next": "A seguir",
|
||||||
|
"update_location_action_prompt": "Actualize a localização de {count} activos seleccionados com:",
|
||||||
"updated_at": "Atualizado a",
|
"updated_at": "Atualizado a",
|
||||||
"updated_password": "Palavra-passe atualizada",
|
"updated_password": "Palavra-passe atualizada",
|
||||||
"upload": "Carregar",
|
"upload": "Carregar",
|
||||||
@@ -1981,6 +2034,7 @@
|
|||||||
"use_biometric": "Utilizar dados biométricos",
|
"use_biometric": "Utilizar dados biométricos",
|
||||||
"use_current_connection": "usar conexão atual",
|
"use_current_connection": "usar conexão atual",
|
||||||
"use_custom_date_range": "Utilizar um intervalo de datas personalizado",
|
"use_custom_date_range": "Utilizar um intervalo de datas personalizado",
|
||||||
|
"use_this_location": "Clique para usar a localização",
|
||||||
"user": "Utilizador",
|
"user": "Utilizador",
|
||||||
"user_has_been_deleted": "Este utilizador for eliminado.",
|
"user_has_been_deleted": "Este utilizador for eliminado.",
|
||||||
"user_id": "ID do utilizador",
|
"user_id": "ID do utilizador",
|
||||||
|
|||||||
@@ -1076,8 +1076,8 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "Esta funcionalidade carrega recursos externos do Google para funcionar.",
|
"gcast_enabled_description": "Esta funcionalidade carrega recursos externos do Google para funcionar.",
|
||||||
"general": "Geral",
|
"general": "Geral",
|
||||||
"geolocation_instruction_all_have_location": "Todos arquivos nesta data já contem dados de localização. Tente exibir todos os arquivos ou selecione uma data diferente",
|
"geolocation_instruction_all_have_location": "Todos arquivos nesta data já possuem dados de localização. Tente exibir todos os arquivos ou selecione uma data diferente",
|
||||||
"geolocation_instruction_location": "Selecione o arquivo com as coordenadas de GPS desejada, ou selecione a localização diretamente no mapa",
|
"geolocation_instruction_location": "Selecione um arquivo com as coordenadas de GPS desejada, ou selecione a localização diretamente no mapa",
|
||||||
"geolocation_instruction_no_date": "Selecione uma data para gerenciar os dados de localização das fotos e vídeos daquele dia",
|
"geolocation_instruction_no_date": "Selecione uma data para gerenciar os dados de localização das fotos e vídeos daquele dia",
|
||||||
"geolocation_instruction_no_photos": "Nenhuma foto ou vídeo encontrado nesta data. Selecione uma data diferente para ser exibida",
|
"geolocation_instruction_no_photos": "Nenhuma foto ou vídeo encontrado nesta data. Selecione uma data diferente para ser exibida",
|
||||||
"get_help": "Obter Ajuda",
|
"get_help": "Obter Ajuda",
|
||||||
|
|||||||
12
i18n/ro.json
12
i18n/ro.json
@@ -28,6 +28,9 @@
|
|||||||
"add_to_album": "Adaugă în album",
|
"add_to_album": "Adaugă în album",
|
||||||
"add_to_album_bottom_sheet_added": "Adăugat în {album}",
|
"add_to_album_bottom_sheet_added": "Adăugat în {album}",
|
||||||
"add_to_album_bottom_sheet_already_exists": "Deja în {album}",
|
"add_to_album_bottom_sheet_already_exists": "Deja în {album}",
|
||||||
|
"add_to_album_toggle": "Selectează/deselectează {album}",
|
||||||
|
"add_to_albums": "Adaugă la albume",
|
||||||
|
"add_to_albums_count": "Adaugă la albume ({count})",
|
||||||
"add_to_shared_album": "Adaugă la album partajat",
|
"add_to_shared_album": "Adaugă la album partajat",
|
||||||
"add_url": "Adăugați adresa URL",
|
"add_url": "Adăugați adresa URL",
|
||||||
"added_to_archive": "Adăugat la arhivă",
|
"added_to_archive": "Adăugat la arhivă",
|
||||||
@@ -181,6 +184,7 @@
|
|||||||
"nightly_tasks_generate_memories_setting": "Generare memorii",
|
"nightly_tasks_generate_memories_setting": "Generare memorii",
|
||||||
"nightly_tasks_generate_memories_setting_description": "Creează amintiri noi din resurse",
|
"nightly_tasks_generate_memories_setting_description": "Creează amintiri noi din resurse",
|
||||||
"nightly_tasks_missing_thumbnails_setting": "Generează miniaturi lipsă",
|
"nightly_tasks_missing_thumbnails_setting": "Generează miniaturi lipsă",
|
||||||
|
"nightly_tasks_missing_thumbnails_setting_description": "Pune în coadă elementele fără miniaturi pentru generarea miniaturilor",
|
||||||
"nightly_tasks_settings": "Setări pentru sarcinile nocturne",
|
"nightly_tasks_settings": "Setări pentru sarcinile nocturne",
|
||||||
"nightly_tasks_settings_description": "Gestionați sarcinile nocturne",
|
"nightly_tasks_settings_description": "Gestionați sarcinile nocturne",
|
||||||
"nightly_tasks_start_time_setting": "Ora de începere",
|
"nightly_tasks_start_time_setting": "Ora de începere",
|
||||||
@@ -354,6 +358,9 @@
|
|||||||
"trash_number_of_days_description": "Numǎr de zile pentru pǎstrarea fișierelor în coșul de gunoi pânǎ la ștergerea permanentǎ",
|
"trash_number_of_days_description": "Numǎr de zile pentru pǎstrarea fișierelor în coșul de gunoi pânǎ la ștergerea permanentǎ",
|
||||||
"trash_settings": "Setǎri Coș de Gunoi",
|
"trash_settings": "Setǎri Coș de Gunoi",
|
||||||
"trash_settings_description": "Gestioneazǎ setǎrile coșului de gunoi",
|
"trash_settings_description": "Gestioneazǎ setǎrile coșului de gunoi",
|
||||||
|
"unlink_all_oauth_accounts": "Deconectează toate conturile OAuth",
|
||||||
|
"unlink_all_oauth_accounts_description": "Nu uita să deconectezi toate conturile OAuth înainte de a migra la un nou furnizor.",
|
||||||
|
"unlink_all_oauth_accounts_prompt": "Ești sigur că vrei să deconectezi toate conturile OAuth? Aceasta va reseta ID-ul OAuth pentru fiecare utilizator și nu poate fi anulată.",
|
||||||
"user_cleanup_job": "Curățare utilizator",
|
"user_cleanup_job": "Curățare utilizator",
|
||||||
"user_delete_delay": "Contul și resursele utilizatorului <b>{user}</b> vor fi programate pentru ștergere permanentă în {delay, plural, one {# zi} other {# zile}}.",
|
"user_delete_delay": "Contul și resursele utilizatorului <b>{user}</b> vor fi programate pentru ștergere permanentă în {delay, plural, one {# zi} other {# zile}}.",
|
||||||
"user_delete_delay_settings": "Întârziere la ștergere",
|
"user_delete_delay_settings": "Întârziere la ștergere",
|
||||||
@@ -389,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "Preferă fotografii la distanță",
|
"advanced_settings_prefer_remote_title": "Preferă fotografii la distanță",
|
||||||
"advanced_settings_proxy_headers_subtitle": "Definește antetele proxy pe care Immich ar trebui să le trimită cu fiecare solicitare de rețea",
|
"advanced_settings_proxy_headers_subtitle": "Definește antetele proxy pe care Immich ar trebui să le trimită cu fiecare solicitare de rețea",
|
||||||
"advanced_settings_proxy_headers_title": "Antete Proxy",
|
"advanced_settings_proxy_headers_title": "Antete Proxy",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "Activează modul doar-citire, în care fotografiile pot fi doar vizualizate, iar acțiuni precum selectarea mai multor imagini, partajarea, redarea pe alt dispozitiv sau ștergerea sunt dezactivate. Activează/Dezactivează modul doar-citire din avatarul utilizatorului de pe ecranul principal.",
|
||||||
|
"advanced_settings_readonly_mode_title": "Mod doar-citire",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "Omite verificare certificate SSL pentru distinația server-ului, necesar pentru certificate auto-semnate.",
|
"advanced_settings_self_signed_ssl_subtitle": "Omite verificare certificate SSL pentru distinația server-ului, necesar pentru certificate auto-semnate.",
|
||||||
"advanced_settings_self_signed_ssl_title": "Permite certificate SSL auto-semnate",
|
"advanced_settings_self_signed_ssl_title": "Permite certificate SSL auto-semnate",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "Ștergeți sau restaurați automat un element de pe acest dispozitiv atunci când acțiunea este efectuată pe web",
|
"advanced_settings_sync_remote_deletions_subtitle": "Ștergeți sau restaurați automat un element de pe acest dispozitiv atunci când acțiunea este efectuată pe web",
|
||||||
@@ -454,6 +463,7 @@
|
|||||||
"app_bar_signout_dialog_title": "Deconectare",
|
"app_bar_signout_dialog_title": "Deconectare",
|
||||||
"app_settings": "Setări Aplicație",
|
"app_settings": "Setări Aplicație",
|
||||||
"appears_in": "Apare în",
|
"appears_in": "Apare în",
|
||||||
|
"apply_count": "Aplică ({count, number})",
|
||||||
"archive": "Arhivă",
|
"archive": "Arhivă",
|
||||||
"archive_action_prompt": "{count} adăugate la Arhivă",
|
"archive_action_prompt": "{count} adăugate la Arhivă",
|
||||||
"archive_or_unarchive_photo": "Arhiveazǎ sau dezarhiveazǎ fotografia",
|
"archive_or_unarchive_photo": "Arhiveazǎ sau dezarhiveazǎ fotografia",
|
||||||
@@ -493,7 +503,9 @@
|
|||||||
"assets": "Resurse",
|
"assets": "Resurse",
|
||||||
"assets_added_count": "Adăugat {count, plural, one {# resursă} other {# resurse}}",
|
"assets_added_count": "Adăugat {count, plural, one {# resursă} other {# resurse}}",
|
||||||
"assets_added_to_album_count": "Am adăugat {count, plural, one {# resursă} other {# resurse}} în album",
|
"assets_added_to_album_count": "Am adăugat {count, plural, one {# resursă} other {# resurse}} în album",
|
||||||
|
"assets_added_to_albums_count": "Au fost adăugate {assetTotal, plural, one {# element} other {# elemente}} la {albumTotal, plural, one {# album} other {# albume}}",
|
||||||
"assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} nu pot fi adăugate în album",
|
"assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} nu pot fi adăugate în album",
|
||||||
|
"assets_cannot_be_added_to_albums": "{count, plural, one {Elementul} other {Elementele}} nu poate fi adăugat la niciunul dintre albume",
|
||||||
"assets_count": "{count, plural, one {# resursă} other {# resurse}}",
|
"assets_count": "{count, plural, one {# resursă} other {# resurse}}",
|
||||||
"assets_deleted_permanently": "{count} poză/poze ștearsă/șterse permanent",
|
"assets_deleted_permanently": "{count} poză/poze ștearsă/șterse permanent",
|
||||||
"assets_deleted_permanently_from_server": "{count} poză/poze ștearsă/șterse permanent din serverul Immich",
|
"assets_deleted_permanently_from_server": "{count} poză/poze ștearsă/șterse permanent din serverul Immich",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Открыть фильтры поиска",
|
"open_the_search_filters": "Открыть фильтры поиска",
|
||||||
"options": "Опции",
|
"options": "Опции",
|
||||||
"or": "или",
|
"or": "или",
|
||||||
|
"organize_into_albums": "Распределить по альбомам",
|
||||||
|
"organize_into_albums_description": "Добавить уже существующие фотографии в альбомы, используя текущие настройки синхронизации",
|
||||||
"organize_your_library": "Приведите в порядок свою библиотеку",
|
"organize_your_library": "Приведите в порядок свою библиотеку",
|
||||||
"original": "оригинал",
|
"original": "оригинал",
|
||||||
"other": "Другое",
|
"other": "Другое",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Состояние поддержки",
|
"purchase_server_description_2": "Состояние поддержки",
|
||||||
"purchase_server_title": "Сервер",
|
"purchase_server_title": "Сервер",
|
||||||
"purchase_settings_server_activated": "Ключом продукта управляет администратор сервера",
|
"purchase_settings_server_activated": "Ключом продукта управляет администратор сервера",
|
||||||
|
"query_asset_id": "Идентификатор исходного объекта",
|
||||||
"queue_status": "В очереди {count}/{total}",
|
"queue_status": "В очереди {count}/{total}",
|
||||||
"rating": "Рейтинг звёзд",
|
"rating": "Рейтинг звёзд",
|
||||||
"rating_clear": "Очистить рейтинг",
|
"rating_clear": "Очистить рейтинг",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Не удалось создать альбом",
|
"select_user_for_sharing_page_err_album": "Не удалось создать альбом",
|
||||||
"selected": "Выбрано",
|
"selected": "Выбрано",
|
||||||
"selected_count": "{count, plural, one {Выбран # объект} many {Выбрано # объектов} other {Выбрано # объекта}}",
|
"selected_count": "{count, plural, one {Выбран # объект} many {Выбрано # объектов} other {Выбрано # объекта}}",
|
||||||
"selected_gps_coordinates": "выбранные координаты",
|
"selected_gps_coordinates": "Выбранные координаты",
|
||||||
"send_message": "Отправить сообщение",
|
"send_message": "Отправить сообщение",
|
||||||
"send_welcome_email": "Отправить приветственное письмо",
|
"send_welcome_email": "Отправить приветственное письмо",
|
||||||
"server_endpoint": "Адрес сервера",
|
"server_endpoint": "Адрес сервера",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Показать следующий объект",
|
"view_next_asset": "Показать следующий объект",
|
||||||
"view_previous_asset": "Показать предыдущий объект",
|
"view_previous_asset": "Показать предыдущий объект",
|
||||||
"view_qr_code": "Посмотреть QR код",
|
"view_qr_code": "Посмотреть QR код",
|
||||||
|
"view_similar_photos": "Найти похожие фотографии",
|
||||||
"view_stack": "Показать группу",
|
"view_stack": "Показать группу",
|
||||||
"view_user": "Просмотреть пользователя",
|
"view_user": "Просмотреть пользователя",
|
||||||
"viewer_remove_from_stack": "Убрать из группы",
|
"viewer_remove_from_stack": "Убрать из группы",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Otvoriť vyhľadávacie filtre",
|
"open_the_search_filters": "Otvoriť vyhľadávacie filtre",
|
||||||
"options": "Nastavenia",
|
"options": "Nastavenia",
|
||||||
"or": "alebo",
|
"or": "alebo",
|
||||||
|
"organize_into_albums": "Usporiadať do albumov",
|
||||||
|
"organize_into_albums_description": "Vložiť existujúce fotky do albumov podľa aktuálnych nastavení synchronizácie",
|
||||||
"organize_your_library": "Usporiadajte svoju knižnicu",
|
"organize_your_library": "Usporiadajte svoju knižnicu",
|
||||||
"original": "originál",
|
"original": "originál",
|
||||||
"other": "Ostatné",
|
"other": "Ostatné",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Štatút podporovateľa",
|
"purchase_server_description_2": "Štatút podporovateľa",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Produktový kľúč servera spravuje admin",
|
"purchase_settings_server_activated": "Produktový kľúč servera spravuje admin",
|
||||||
|
"query_asset_id": "ID požiadavky položky",
|
||||||
"queue_status": "V poradí {count}/{total}",
|
"queue_status": "V poradí {count}/{total}",
|
||||||
"rating": "Hodnotenie hviezdičkami",
|
"rating": "Hodnotenie hviezdičkami",
|
||||||
"rating_clear": "Vyčistiť hodnotenie",
|
"rating_clear": "Vyčistiť hodnotenie",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Nepodarilo sa vytvoriť album",
|
"select_user_for_sharing_page_err_album": "Nepodarilo sa vytvoriť album",
|
||||||
"selected": "Vybrané",
|
"selected": "Vybrané",
|
||||||
"selected_count": "{count, plural, one {# vybraná} few {# vybrané} other {# vybraných}}",
|
"selected_count": "{count, plural, one {# vybraná} few {# vybrané} other {# vybraných}}",
|
||||||
"selected_gps_coordinates": "vybrané GPS súradnice",
|
"selected_gps_coordinates": "Vybrané GPS súradnice",
|
||||||
"send_message": "Odoslať správu",
|
"send_message": "Odoslať správu",
|
||||||
"send_welcome_email": "Odoslať uvítací e-mail",
|
"send_welcome_email": "Odoslať uvítací e-mail",
|
||||||
"server_endpoint": "Koncový bod servera",
|
"server_endpoint": "Koncový bod servera",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Zobraziť nasledujúci súbor",
|
"view_next_asset": "Zobraziť nasledujúci súbor",
|
||||||
"view_previous_asset": "Zobraziť predchádzajúci súbor",
|
"view_previous_asset": "Zobraziť predchádzajúci súbor",
|
||||||
"view_qr_code": "Zobraziť QR kód",
|
"view_qr_code": "Zobraziť QR kód",
|
||||||
|
"view_similar_photos": "Zobraziť podobné fotografie",
|
||||||
"view_stack": "Zobraziť zoskupenie",
|
"view_stack": "Zobraziť zoskupenie",
|
||||||
"view_user": "Zobraziť používateľa",
|
"view_user": "Zobraziť používateľa",
|
||||||
"viewer_remove_from_stack": "Odstrániť zo zoskupenia",
|
"viewer_remove_from_stack": "Odstrániť zo zoskupenia",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Odpri iskalne filtre",
|
"open_the_search_filters": "Odpri iskalne filtre",
|
||||||
"options": "Možnosti",
|
"options": "Možnosti",
|
||||||
"or": "ali",
|
"or": "ali",
|
||||||
|
"organize_into_albums": "Organiziraj v albume",
|
||||||
|
"organize_into_albums_description": "Dodaj obstoječe fotografije v albume z uporabo trenutnih nastavitev sinhronizacije",
|
||||||
"organize_your_library": "Organiziraj svojo knjižnico",
|
"organize_your_library": "Organiziraj svojo knjižnico",
|
||||||
"original": "izvirnik",
|
"original": "izvirnik",
|
||||||
"other": "drugo",
|
"other": "drugo",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Status podpornika",
|
"purchase_server_description_2": "Status podpornika",
|
||||||
"purchase_server_title": "Strežnik",
|
"purchase_server_title": "Strežnik",
|
||||||
"purchase_settings_server_activated": "Ključ izdelka strežnika upravlja skrbnik",
|
"purchase_settings_server_activated": "Ključ izdelka strežnika upravlja skrbnik",
|
||||||
|
"query_asset_id": "ID sredstva poizvedbe",
|
||||||
"queue_status": "Čakalna vrsta {count}/{total}",
|
"queue_status": "Čakalna vrsta {count}/{total}",
|
||||||
"rating": "Ocena z zvezdicami",
|
"rating": "Ocena z zvezdicami",
|
||||||
"rating_clear": "Počisti oceno",
|
"rating_clear": "Počisti oceno",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Ogled naslednjega sredstva",
|
"view_next_asset": "Ogled naslednjega sredstva",
|
||||||
"view_previous_asset": "Ogled prejšnjega sredstva",
|
"view_previous_asset": "Ogled prejšnjega sredstva",
|
||||||
"view_qr_code": "Oglej si kodo QR",
|
"view_qr_code": "Oglej si kodo QR",
|
||||||
|
"view_similar_photos": "Oglejte si podobne fotografije",
|
||||||
"view_stack": "Ogled sklada",
|
"view_stack": "Ogled sklada",
|
||||||
"view_user": "Poglej uporabnika",
|
"view_user": "Poglej uporabnika",
|
||||||
"viewer_remove_from_stack": "Odstrani iz sklada",
|
"viewer_remove_from_stack": "Odstrani iz sklada",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Öppna sökfilter",
|
"open_the_search_filters": "Öppna sökfilter",
|
||||||
"options": "Val",
|
"options": "Val",
|
||||||
"or": "eller",
|
"or": "eller",
|
||||||
|
"organize_into_albums": "Organisera i album",
|
||||||
|
"organize_into_albums_description": "Lägg befintliga foton i album med aktuella synkroniseringsinställningar",
|
||||||
"organize_your_library": "Organisera ditt bibliotek",
|
"organize_your_library": "Organisera ditt bibliotek",
|
||||||
"original": "original",
|
"original": "original",
|
||||||
"other": "Övrigt",
|
"other": "Övrigt",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Supporterstatus",
|
"purchase_server_description_2": "Supporterstatus",
|
||||||
"purchase_server_title": "Server",
|
"purchase_server_title": "Server",
|
||||||
"purchase_settings_server_activated": "Produktnyckeln för servern hanteras av administratören",
|
"purchase_settings_server_activated": "Produktnyckeln för servern hanteras av administratören",
|
||||||
|
"query_asset_id": "Fråga om objekts-ID",
|
||||||
"queue_status": "Köande {count}/{total}",
|
"queue_status": "Köande {count}/{total}",
|
||||||
"rating": "Antal stjärnor",
|
"rating": "Antal stjärnor",
|
||||||
"rating_clear": "Ta bort betyg",
|
"rating_clear": "Ta bort betyg",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Kunde inte skapa nytt album",
|
"select_user_for_sharing_page_err_album": "Kunde inte skapa nytt album",
|
||||||
"selected": "Valda",
|
"selected": "Valda",
|
||||||
"selected_count": "{count, plural, other {# valda}}",
|
"selected_count": "{count, plural, other {# valda}}",
|
||||||
"selected_gps_coordinates": "valda GPS-koordinater",
|
"selected_gps_coordinates": "Valda GPS-koordinater",
|
||||||
"send_message": "Skicka meddelande",
|
"send_message": "Skicka meddelande",
|
||||||
"send_welcome_email": "Skicka välkomstmejl",
|
"send_welcome_email": "Skicka välkomstmejl",
|
||||||
"server_endpoint": "Server-endpoint",
|
"server_endpoint": "Server-endpoint",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Visa nästa objekt",
|
"view_next_asset": "Visa nästa objekt",
|
||||||
"view_previous_asset": "Visa föregående objekt",
|
"view_previous_asset": "Visa föregående objekt",
|
||||||
"view_qr_code": "Visa QR-kod",
|
"view_qr_code": "Visa QR-kod",
|
||||||
|
"view_similar_photos": "Visa liknande foton",
|
||||||
"view_stack": "Visa Stapel",
|
"view_stack": "Visa Stapel",
|
||||||
"view_user": "Visa Användare",
|
"view_user": "Visa Användare",
|
||||||
"viewer_remove_from_stack": "Ta bort från Stapeln",
|
"viewer_remove_from_stack": "Ta bort från Stapeln",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "Відкрийте фільтри пошуку",
|
"open_the_search_filters": "Відкрийте фільтри пошуку",
|
||||||
"options": "Налаштування",
|
"options": "Налаштування",
|
||||||
"or": "або",
|
"or": "або",
|
||||||
|
"organize_into_albums": "Упорядкувати в альбоми",
|
||||||
|
"organize_into_albums_description": "Помістити наявні фотографії в альбоми, використовуючи поточні налаштування синхронізації",
|
||||||
"organize_your_library": "Організуйте свою бібліотеку",
|
"organize_your_library": "Організуйте свою бібліотеку",
|
||||||
"original": "оригінал",
|
"original": "оригінал",
|
||||||
"other": "Інше",
|
"other": "Інше",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "Статус підтримки",
|
"purchase_server_description_2": "Статус підтримки",
|
||||||
"purchase_server_title": "Сервер",
|
"purchase_server_title": "Сервер",
|
||||||
"purchase_settings_server_activated": "Ключ продукту сервера керується адміністратором",
|
"purchase_settings_server_activated": "Ключ продукту сервера керується адміністратором",
|
||||||
|
"query_asset_id": "Ідентифікатор ресурсу запиту",
|
||||||
"queue_status": "У черзі {count} з {total}",
|
"queue_status": "У черзі {count} з {total}",
|
||||||
"rating": "Зоряний рейтинг",
|
"rating": "Зоряний рейтинг",
|
||||||
"rating_clear": "Очистити рейтинг",
|
"rating_clear": "Очистити рейтинг",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "Не вдалося створити альбом",
|
"select_user_for_sharing_page_err_album": "Не вдалося створити альбом",
|
||||||
"selected": "Обрано",
|
"selected": "Обрано",
|
||||||
"selected_count": "{count, plural, one {# обраний} other {# обраних}}",
|
"selected_count": "{count, plural, one {# обраний} other {# обраних}}",
|
||||||
"selected_gps_coordinates": "вибрані GPS-координати",
|
"selected_gps_coordinates": "Вибрані GPS-координати",
|
||||||
"send_message": "Надіслати повідомлення",
|
"send_message": "Надіслати повідомлення",
|
||||||
"send_welcome_email": "Надішліть вітальний лист",
|
"send_welcome_email": "Надішліть вітальний лист",
|
||||||
"server_endpoint": "Кінцева точка сервера",
|
"server_endpoint": "Кінцева точка сервера",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "Переглянути наступний ресурс",
|
"view_next_asset": "Переглянути наступний ресурс",
|
||||||
"view_previous_asset": "Переглянути попередній ресурс",
|
"view_previous_asset": "Переглянути попередній ресурс",
|
||||||
"view_qr_code": "Переглянути QR-код",
|
"view_qr_code": "Переглянути QR-код",
|
||||||
|
"view_similar_photos": "Переглянути схожі фотографії",
|
||||||
"view_stack": "Перегляд стеку",
|
"view_stack": "Перегляд стеку",
|
||||||
"view_user": "Переглянути користувача",
|
"view_user": "Переглянути користувача",
|
||||||
"viewer_remove_from_stack": "Видалити зі стеку",
|
"viewer_remove_from_stack": "Видалити зі стеку",
|
||||||
|
|||||||
@@ -396,6 +396,8 @@
|
|||||||
"advanced_settings_prefer_remote_title": "偏好遠端影像",
|
"advanced_settings_prefer_remote_title": "偏好遠端影像",
|
||||||
"advanced_settings_proxy_headers_subtitle": "定義 Immich 在每次網路請求時應該發送的代理標頭",
|
"advanced_settings_proxy_headers_subtitle": "定義 Immich 在每次網路請求時應該發送的代理標頭",
|
||||||
"advanced_settings_proxy_headers_title": "代理標頭",
|
"advanced_settings_proxy_headers_title": "代理標頭",
|
||||||
|
"advanced_settings_readonly_mode_subtitle": "開啟唯讀模式後,照片只能瀏覽,像是多選影像、分享、投放、刪除等功能都會關閉。可在主畫面透過使用者頭像來開啟/關閉唯讀模式",
|
||||||
|
"advanced_settings_readonly_mode_title": "唯讀模式",
|
||||||
"advanced_settings_self_signed_ssl_subtitle": "略過伺服器端點的 SSL 憑證驗證。自簽憑證時必須啟用此設定。",
|
"advanced_settings_self_signed_ssl_subtitle": "略過伺服器端點的 SSL 憑證驗證。自簽憑證時必須啟用此設定。",
|
||||||
"advanced_settings_self_signed_ssl_title": "允許自簽的 SSL 憑證",
|
"advanced_settings_self_signed_ssl_title": "允許自簽的 SSL 憑證",
|
||||||
"advanced_settings_sync_remote_deletions_subtitle": "當在網頁端執行刪除或還原操作時,自動在此裝置上刪除或還原該媒體",
|
"advanced_settings_sync_remote_deletions_subtitle": "當在網頁端執行刪除或還原操作時,自動在此裝置上刪除或還原該媒體",
|
||||||
@@ -1073,6 +1075,10 @@
|
|||||||
"gcast_enabled": "Google Cast",
|
"gcast_enabled": "Google Cast",
|
||||||
"gcast_enabled_description": "此功能需要從 Google 載入外部資源才能正常運作。",
|
"gcast_enabled_description": "此功能需要從 Google 載入外部資源才能正常運作。",
|
||||||
"general": "一般",
|
"general": "一般",
|
||||||
|
"geolocation_instruction_all_have_location": "此日期的所有項目已具有位置資料。請嘗試顯示所有項目或選擇其他日期",
|
||||||
|
"geolocation_instruction_location": "點擊具有 GPS 座標的項目以使用其位置,或直接從地圖中選擇地點",
|
||||||
|
"geolocation_instruction_no_date": "選擇日期以管理該天的照片和影片位置資料",
|
||||||
|
"geolocation_instruction_no_photos": "此日期沒有找到照片或影片。請選擇其他日期以顯示",
|
||||||
"get_help": "線上求助",
|
"get_help": "線上求助",
|
||||||
"get_wifiname_error": "無法取得 Wi-Fi 名稱。請確認您已授予必要的權限,並已連接至 Wi-Fi 網路",
|
"get_wifiname_error": "無法取得 Wi-Fi 名稱。請確認您已授予必要的權限,並已連接至 Wi-Fi 網路",
|
||||||
"getting_started": "開始使用",
|
"getting_started": "開始使用",
|
||||||
@@ -1262,6 +1268,7 @@
|
|||||||
"main_branch_warning": "您現在使用的是開發版本;我們強烈您建議使用正式發行版!",
|
"main_branch_warning": "您現在使用的是開發版本;我們強烈您建議使用正式發行版!",
|
||||||
"main_menu": "主頁面",
|
"main_menu": "主頁面",
|
||||||
"make": "製造商",
|
"make": "製造商",
|
||||||
|
"manage_geolocation": "管理位置",
|
||||||
"manage_shared_links": "管理共享連結",
|
"manage_shared_links": "管理共享連結",
|
||||||
"manage_sharing_with_partners": "管理與親朋好友的分享",
|
"manage_sharing_with_partners": "管理與親朋好友的分享",
|
||||||
"manage_the_app_settings": "管理應用程式設定",
|
"manage_the_app_settings": "管理應用程式設定",
|
||||||
@@ -1508,6 +1515,7 @@
|
|||||||
"profile_drawer_client_out_of_date_minor": "客戶端有小版本升級,請盡快升級至最新版。",
|
"profile_drawer_client_out_of_date_minor": "客戶端有小版本升級,請盡快升級至最新版。",
|
||||||
"profile_drawer_client_server_up_to_date": "客戶端和服務端都是最新的",
|
"profile_drawer_client_server_up_to_date": "客戶端和服務端都是最新的",
|
||||||
"profile_drawer_github": "GitHub",
|
"profile_drawer_github": "GitHub",
|
||||||
|
"profile_drawer_readonly_mode": "唯讀模式已開啟。請連點兩下使用者頭像圖示以退出。",
|
||||||
"profile_drawer_server_out_of_date_major": "服務端有大版本升級,請盡快升級至最新版。",
|
"profile_drawer_server_out_of_date_major": "服務端有大版本升級,請盡快升級至最新版。",
|
||||||
"profile_drawer_server_out_of_date_minor": "服務端有小版本升級,請盡快升級至最新版。",
|
"profile_drawer_server_out_of_date_minor": "服務端有小版本升級,請盡快升級至最新版。",
|
||||||
"profile_image_of_user": "{user} 的個人資料圖片",
|
"profile_image_of_user": "{user} 的個人資料圖片",
|
||||||
@@ -1553,6 +1561,8 @@
|
|||||||
"rating_description": "在資訊面板中顯示 EXIF 評等",
|
"rating_description": "在資訊面板中顯示 EXIF 評等",
|
||||||
"reaction_options": "反應選項",
|
"reaction_options": "反應選項",
|
||||||
"read_changelog": "閱覽變更日誌",
|
"read_changelog": "閱覽變更日誌",
|
||||||
|
"readonly_mode_disabled": "唯讀模式已關閉",
|
||||||
|
"readonly_mode_enabled": "唯讀模式已開啟",
|
||||||
"reassign": "重新指定",
|
"reassign": "重新指定",
|
||||||
"reassigned_assets_to_existing_person": "已將 {count, plural, other {# 個檔案}}重新指定給{name, select, null {現有的人} other {{name}}}",
|
"reassigned_assets_to_existing_person": "已將 {count, plural, other {# 個檔案}}重新指定給{name, select, null {現有的人} other {{name}}}",
|
||||||
"reassigned_assets_to_new_person": "已將 {count, plural, other {# 個檔案}}重新指定給一位新人物",
|
"reassigned_assets_to_new_person": "已將 {count, plural, other {# 個檔案}}重新指定給一位新人物",
|
||||||
@@ -1722,6 +1732,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "新增相簿失敗",
|
"select_user_for_sharing_page_err_album": "新增相簿失敗",
|
||||||
"selected": "已選擇",
|
"selected": "已選擇",
|
||||||
"selected_count": "{count, plural, other {選了 # 項}}",
|
"selected_count": "{count, plural, other {選了 # 項}}",
|
||||||
|
"selected_gps_coordinates": "已選擇的 GPS 座標",
|
||||||
"send_message": "傳訊息",
|
"send_message": "傳訊息",
|
||||||
"send_welcome_email": "傳送歡迎電子郵件",
|
"send_welcome_email": "傳送歡迎電子郵件",
|
||||||
"server_endpoint": "伺服器端點",
|
"server_endpoint": "伺服器端點",
|
||||||
@@ -1832,8 +1843,10 @@
|
|||||||
"shift_to_permanent_delete": "按 ⇧ 永久刪除檔案",
|
"shift_to_permanent_delete": "按 ⇧ 永久刪除檔案",
|
||||||
"show_album_options": "顯示相簿選項",
|
"show_album_options": "顯示相簿選項",
|
||||||
"show_albums": "顯示相簿",
|
"show_albums": "顯示相簿",
|
||||||
|
"show_all_assets": "顯示所有項目",
|
||||||
"show_all_people": "顯示所有人物",
|
"show_all_people": "顯示所有人物",
|
||||||
"show_and_hide_people": "顯示與隱藏人物",
|
"show_and_hide_people": "顯示與隱藏人物",
|
||||||
|
"show_assets_without_location": "顯示沒有地點的項目",
|
||||||
"show_file_location": "顯示文件位置",
|
"show_file_location": "顯示文件位置",
|
||||||
"show_gallery": "顯示畫廊",
|
"show_gallery": "顯示畫廊",
|
||||||
"show_hidden_people": "顯示隱藏的人物",
|
"show_hidden_people": "顯示隱藏的人物",
|
||||||
@@ -2015,6 +2028,7 @@
|
|||||||
"use_biometric": "使用生物辨識",
|
"use_biometric": "使用生物辨識",
|
||||||
"use_current_connection": "使用目前的連線",
|
"use_current_connection": "使用目前的連線",
|
||||||
"use_custom_date_range": "改用自訂日期範圍",
|
"use_custom_date_range": "改用自訂日期範圍",
|
||||||
|
"use_this_location": "點擊以使用位置",
|
||||||
"user": "使用者",
|
"user": "使用者",
|
||||||
"user_has_been_deleted": "此用戶已被刪除。",
|
"user_has_been_deleted": "此用戶已被刪除。",
|
||||||
"user_id": "使用者 ID",
|
"user_id": "使用者 ID",
|
||||||
|
|||||||
@@ -1417,6 +1417,8 @@
|
|||||||
"open_the_search_filters": "打开搜索过滤器",
|
"open_the_search_filters": "打开搜索过滤器",
|
||||||
"options": "选项",
|
"options": "选项",
|
||||||
"or": "或",
|
"or": "或",
|
||||||
|
"organize_into_albums": "整理成相册",
|
||||||
|
"organize_into_albums_description": "使用当前同步设置将现有照片放入相册",
|
||||||
"organize_your_library": "整理您的图库",
|
"organize_your_library": "整理您的图库",
|
||||||
"original": "原图",
|
"original": "原图",
|
||||||
"other": "其它",
|
"other": "其它",
|
||||||
@@ -1557,6 +1559,7 @@
|
|||||||
"purchase_server_description_2": "支持者状态",
|
"purchase_server_description_2": "支持者状态",
|
||||||
"purchase_server_title": "服务器",
|
"purchase_server_title": "服务器",
|
||||||
"purchase_settings_server_activated": "服务器产品密钥正在由管理员管理",
|
"purchase_settings_server_activated": "服务器产品密钥正在由管理员管理",
|
||||||
|
"query_asset_id": "查询资产ID",
|
||||||
"queue_status": "排队中 {count}/{total}",
|
"queue_status": "排队中 {count}/{total}",
|
||||||
"rating": "星级",
|
"rating": "星级",
|
||||||
"rating_clear": "删除星级",
|
"rating_clear": "删除星级",
|
||||||
@@ -1735,7 +1738,7 @@
|
|||||||
"select_user_for_sharing_page_err_album": "创建相册失败",
|
"select_user_for_sharing_page_err_album": "创建相册失败",
|
||||||
"selected": "已选择",
|
"selected": "已选择",
|
||||||
"selected_count": "{count, plural, other {#项已选择}}",
|
"selected_count": "{count, plural, other {#项已选择}}",
|
||||||
"selected_gps_coordinates": "选定的GPS坐标",
|
"selected_gps_coordinates": "已选定的GPS坐标",
|
||||||
"send_message": "发送消息",
|
"send_message": "发送消息",
|
||||||
"send_welcome_email": "发送欢迎邮件",
|
"send_welcome_email": "发送欢迎邮件",
|
||||||
"server_endpoint": "服务器 URL",
|
"server_endpoint": "服务器 URL",
|
||||||
@@ -2077,6 +2080,7 @@
|
|||||||
"view_next_asset": "查看下一项",
|
"view_next_asset": "查看下一项",
|
||||||
"view_previous_asset": "查看上一项",
|
"view_previous_asset": "查看上一项",
|
||||||
"view_qr_code": "查看二维码",
|
"view_qr_code": "查看二维码",
|
||||||
|
"view_similar_photos": "查看相似照片",
|
||||||
"view_stack": "查看堆叠项目",
|
"view_stack": "查看堆叠项目",
|
||||||
"view_user": "查看用户",
|
"view_user": "查看用户",
|
||||||
"viewer_remove_from_stack": "从堆叠中移除",
|
"viewer_remove_from_stack": "从堆叠中移除",
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
|||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends g++
|
RUN apt-get update && apt-get install -y --no-install-recommends g++
|
||||||
|
|
||||||
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:f3660c56d5b08d6c516360981bedc439f499b9bf37f46a216018da3777a74011 /uv /uvx /bin/
|
COPY --from=ghcr.io/astral-sh/uv:0.8.15@sha256:a5727064a0de127bdb7c9d3c1383f3a9ac307d9f2d8a391edc7896c54289ced0 /uv /uvx /bin/
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
--mount=type=bind,source=uv.lock,target=uv.lock \
|
--mount=type=bind,source=uv.lock,target=uv.lock \
|
||||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||||
|
|||||||
34
mise.lock
Normal file
34
mise.lock
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[tools.dart]
|
||||||
|
version = "3.8.2"
|
||||||
|
backend = "asdf:dart"
|
||||||
|
|
||||||
|
[tools.flutter]
|
||||||
|
version = "3.32.8-stable"
|
||||||
|
backend = "asdf:flutter"
|
||||||
|
|
||||||
|
[tools."github:CQLabs/homebrew-dcm"]
|
||||||
|
version = "1.31.4"
|
||||||
|
backend = "github:CQLabs/homebrew-dcm"
|
||||||
|
|
||||||
|
[tools."github:CQLabs/homebrew-dcm".platforms.linux-x64]
|
||||||
|
checksum = "blake3:e9df5b765df327e1248fccf2c6165a89d632a065667f99c01765bf3047b94955"
|
||||||
|
size = 8821083
|
||||||
|
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.31.4/dcm-linux-x64-release.zip"
|
||||||
|
|
||||||
|
[tools.node]
|
||||||
|
version = "22.18.0"
|
||||||
|
backend = "core:node"
|
||||||
|
|
||||||
|
[tools.node.platforms.linux-x64]
|
||||||
|
checksum = "sha256:a2e703725d8683be86bb5da967bf8272f4518bdaf10f21389e2b2c9eaeae8c8a"
|
||||||
|
size = 54824343
|
||||||
|
url = "https://nodejs.org/dist/v22.18.0/node-v22.18.0-linux-x64.tar.gz"
|
||||||
|
|
||||||
|
[tools.pnpm]
|
||||||
|
version = "10.14.0"
|
||||||
|
backend = "aqua:pnpm/pnpm"
|
||||||
|
|
||||||
|
[tools.pnpm.platforms.linux-x64]
|
||||||
|
checksum = "blake3:13dfa46b7173d3cad3bad60a756a492ecf0bce48b23eb9f793e7ccec5a09b46d"
|
||||||
|
size = 66231525
|
||||||
|
url = "https://github.com/pnpm/pnpm/releases/download/v10.14.0/pnpm-linux-x64"
|
||||||
312
mise.toml
Normal file
312
mise.toml
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
[tools]
|
||||||
|
node = "22.19.0"
|
||||||
|
flutter = "3.32.8"
|
||||||
|
pnpm = "10.14.0"
|
||||||
|
dart = "3.8.2"
|
||||||
|
|
||||||
|
[tools."github:CQLabs/homebrew-dcm"]
|
||||||
|
version = "1.31.4"
|
||||||
|
bin = "dcm"
|
||||||
|
postinstall = "chmod +x $MISE_TOOL_INSTALL_PATH/dcm"
|
||||||
|
|
||||||
|
[settings]
|
||||||
|
experimental = true
|
||||||
|
lockfile = true
|
||||||
|
pin = true
|
||||||
|
|
||||||
|
# .github
|
||||||
|
[tasks."github:install"]
|
||||||
|
run = "pnpm install --filter github --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."github:format"]
|
||||||
|
env._.path = "./.github/node_modules/.bin"
|
||||||
|
dir = ".github"
|
||||||
|
run = "prettier --check ."
|
||||||
|
|
||||||
|
[tasks."github:format-fix"]
|
||||||
|
env._.path = "./.github/node_modules/.bin"
|
||||||
|
dir = ".github"
|
||||||
|
run = "prettier --write ."
|
||||||
|
|
||||||
|
# @immich/cli
|
||||||
|
[tasks."cli:install"]
|
||||||
|
run = "pnpm install --filter @immich/cli --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."cli:build"]
|
||||||
|
env._.path = "./cli/node_modules/.bin"
|
||||||
|
dir = "cli"
|
||||||
|
run = "vite build"
|
||||||
|
|
||||||
|
[tasks."cli:test"]
|
||||||
|
env._.path = "./cli/node_modules/.bin"
|
||||||
|
dir = "cli"
|
||||||
|
run = "vite"
|
||||||
|
|
||||||
|
[tasks."cli:lint"]
|
||||||
|
env._.path = "./cli/node_modules/.bin"
|
||||||
|
dir = "cli"
|
||||||
|
run = "eslint \"src/**/*.ts\" --max-warnings 0"
|
||||||
|
|
||||||
|
[tasks."cli:lint-fix"]
|
||||||
|
run = "mise run cli:lint --fix"
|
||||||
|
|
||||||
|
[tasks."cli:format"]
|
||||||
|
env._.path = "./cli/node_modules/.bin"
|
||||||
|
dir = "cli"
|
||||||
|
run = "prettier --check ."
|
||||||
|
|
||||||
|
[tasks."cli:format-fix"]
|
||||||
|
env._.path = "./cli/node_modules/.bin"
|
||||||
|
dir = "cli"
|
||||||
|
run = "prettier --write ."
|
||||||
|
|
||||||
|
[tasks."cli:check"]
|
||||||
|
env._.path = "./cli/node_modules/.bin"
|
||||||
|
dir = "cli"
|
||||||
|
run = "tsc --noEmit"
|
||||||
|
|
||||||
|
# @immich/sdk
|
||||||
|
[tasks."sdk:install"]
|
||||||
|
run = "pnpm install --filter @immich/sdk --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."sdk:build"]
|
||||||
|
env._.path = "./open-api/typescript-sdk/node_modules/.bin"
|
||||||
|
dir = "./open-api/typescript-sdk"
|
||||||
|
run = "tsc"
|
||||||
|
|
||||||
|
# docs
|
||||||
|
[tasks."docs:install"]
|
||||||
|
run = "pnpm install --filter documentation --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."docs:start"]
|
||||||
|
env._.path = "./docs/node_modules/.bin"
|
||||||
|
dir = "docs"
|
||||||
|
run = "docusaurus --port 3005"
|
||||||
|
|
||||||
|
[tasks."docs:build"]
|
||||||
|
env._.path = "./docs/node_modules/.bin"
|
||||||
|
dir = "docs"
|
||||||
|
run = [
|
||||||
|
"jq -c < ../open-api/immich-openapi-specs.json > ./static/openapi.json || exit 0",
|
||||||
|
"docusaurus build",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[tasks."docs:preview"]
|
||||||
|
env._.path = "./docs/node_modules/.bin"
|
||||||
|
dir = "docs"
|
||||||
|
run = "docusaurus serve"
|
||||||
|
|
||||||
|
|
||||||
|
[tasks."docs:format"]
|
||||||
|
env._.path = "./docs/node_modules/.bin"
|
||||||
|
dir = "docs"
|
||||||
|
run = "prettier --check ."
|
||||||
|
|
||||||
|
[tasks."docs:format-fix"]
|
||||||
|
env._.path = "./docs/node_modules/.bin"
|
||||||
|
dir = "docs"
|
||||||
|
run = "prettier --write ."
|
||||||
|
|
||||||
|
|
||||||
|
# e2e
|
||||||
|
[tasks."e2e:install"]
|
||||||
|
run = "pnpm install --filter immich-e2e --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."e2e:test"]
|
||||||
|
env._.path = "./e2e/node_modules/.bin"
|
||||||
|
dir = "e2e"
|
||||||
|
run = "vitest --run"
|
||||||
|
|
||||||
|
[tasks."e2e:test-web"]
|
||||||
|
env._.path = "./e2e/node_modules/.bin"
|
||||||
|
dir = "e2e"
|
||||||
|
run = "playwright test"
|
||||||
|
|
||||||
|
[tasks."e2e:format"]
|
||||||
|
env._.path = "./e2e/node_modules/.bin"
|
||||||
|
dir = "e2e"
|
||||||
|
run = "prettier --check ."
|
||||||
|
|
||||||
|
[tasks."e2e:format-fix"]
|
||||||
|
env._.path = "./e2e/node_modules/.bin"
|
||||||
|
dir = "e2e"
|
||||||
|
run = "prettier --write ."
|
||||||
|
|
||||||
|
[tasks."e2e:lint"]
|
||||||
|
env._.path = "./e2e/node_modules/.bin"
|
||||||
|
dir = "e2e"
|
||||||
|
run = "eslint \"src/**/*.ts\" --max-warnings 0"
|
||||||
|
|
||||||
|
[tasks."e2e:lint-fix"]
|
||||||
|
run = "mise run e2e:lint --fix"
|
||||||
|
|
||||||
|
[tasks."e2e:check"]
|
||||||
|
env._.path = "./e2e/node_modules/.bin"
|
||||||
|
dir = "e2e"
|
||||||
|
run = "tsc --noEmit"
|
||||||
|
|
||||||
|
# i18n
|
||||||
|
[tasks."i18n:format"]
|
||||||
|
run = "mise run i18n:format-fix"
|
||||||
|
|
||||||
|
[tasks."i18n:format-fix"]
|
||||||
|
run = "pnpm dlx sort-json ./i18n/*.json"
|
||||||
|
|
||||||
|
|
||||||
|
# server
|
||||||
|
[tasks."server:install"]
|
||||||
|
run = "pnpm install --filter immich --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."server:build"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "nest build"
|
||||||
|
|
||||||
|
[tasks."server:test"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "vitest --config test/vitest.config.mjs"
|
||||||
|
|
||||||
|
[tasks."server:test-medium"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "vitest --config test/vitest.config.medium.mjs"
|
||||||
|
|
||||||
|
[tasks."server:format"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "prettier --check ."
|
||||||
|
|
||||||
|
[tasks."server:format-fix"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "prettier --write ."
|
||||||
|
|
||||||
|
[tasks."server:lint"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "eslint \"src/**/*.ts\" \"test/**/*.ts\" --max-warnings 0"
|
||||||
|
|
||||||
|
[tasks."server:lint-fix"]
|
||||||
|
run = "mise run server:lint --fix"
|
||||||
|
|
||||||
|
[tasks."server:check"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "tsc --noEmit"
|
||||||
|
|
||||||
|
[tasks."server:sql"]
|
||||||
|
dir = "server"
|
||||||
|
run = "node ./dist/bin/sync-open-api.js"
|
||||||
|
|
||||||
|
[tasks."server:open-api"]
|
||||||
|
dir = "server"
|
||||||
|
run = "node ./dist/bin/sync-open-api.js"
|
||||||
|
|
||||||
|
[tasks."server:migrations"]
|
||||||
|
dir = "server"
|
||||||
|
run = "node ./dist/bin/migrations.js"
|
||||||
|
description = "Run database migration commands (create, generate, run, debug, or query)"
|
||||||
|
|
||||||
|
[tasks."server:schema-drop"]
|
||||||
|
run = "mise run server:migrations query 'DROP schema public cascade; CREATE schema public;'"
|
||||||
|
|
||||||
|
[tasks."server:schema-reset"]
|
||||||
|
run = "mise run server:schema-drop && mise run server:migrations run"
|
||||||
|
|
||||||
|
[tasks."server:email-dev"]
|
||||||
|
env._.path = "./server/node_modules/.bin"
|
||||||
|
dir = "server"
|
||||||
|
run = "email dev -p 3050 --dir src/emails"
|
||||||
|
|
||||||
|
[tasks."server:checklist"]
|
||||||
|
run = [
|
||||||
|
"mise run server:install",
|
||||||
|
"mise run server:format",
|
||||||
|
"mise run server:lint",
|
||||||
|
"mise run server:check",
|
||||||
|
"mise run server:test-medium --run",
|
||||||
|
"mise run server:test --run",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# web
|
||||||
|
[tasks."web:install"]
|
||||||
|
run = "pnpm install --filter immich-web --frozen-lockfile"
|
||||||
|
|
||||||
|
[tasks."web:svelte-kit-sync"]
|
||||||
|
env._.path = "./web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "svelte-kit sync"
|
||||||
|
|
||||||
|
[tasks."web:build"]
|
||||||
|
env._.path = "./web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "vite build"
|
||||||
|
|
||||||
|
[tasks."web:build-stats"]
|
||||||
|
env.BUILD_STATS = "true"
|
||||||
|
env._.path = "./web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "vite build"
|
||||||
|
|
||||||
|
[tasks."web:preview"]
|
||||||
|
env._.path = "./web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "vite preview"
|
||||||
|
|
||||||
|
[tasks."web:start"]
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "vite dev --host 0.0.0.0 --port 3000"
|
||||||
|
|
||||||
|
[tasks."web:test"]
|
||||||
|
depends = "web:svelte-kit-sync"
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "vitest"
|
||||||
|
|
||||||
|
[tasks."web:format"]
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "prettier --check ."
|
||||||
|
|
||||||
|
[tasks."web:format-fix"]
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "prettier --write ."
|
||||||
|
|
||||||
|
[tasks."web:lint"]
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "eslint . --max-warnings 0"
|
||||||
|
|
||||||
|
[tasks."web:lint-p"]
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "eslint-p . --max-warnings 0 --concurrency=4"
|
||||||
|
|
||||||
|
[tasks."web:lint-fix"]
|
||||||
|
run = "mise run web:lint --fix"
|
||||||
|
|
||||||
|
[tasks."web:check"]
|
||||||
|
depends = "web:svelte-kit-sync"
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "tsc --noEmit"
|
||||||
|
|
||||||
|
[tasks."web:check-svelte"]
|
||||||
|
depends = "web:svelte-kit-sync"
|
||||||
|
env._.path = "web/node_modules/.bin"
|
||||||
|
dir = "web"
|
||||||
|
run = "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore' --ignore src/lib/components/photos-page/asset-grid.svelte"
|
||||||
|
|
||||||
|
[tasks."web:checklist"]
|
||||||
|
run = [
|
||||||
|
"mise run web:install",
|
||||||
|
"mise run web:format",
|
||||||
|
"mise run web:check",
|
||||||
|
"mise run web:test --run",
|
||||||
|
"mise run web:lint",
|
||||||
|
]
|
||||||
@@ -61,9 +61,8 @@ private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() {
|
|||||||
|
|
||||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
interface BackgroundWorkerFgHostApi {
|
interface BackgroundWorkerFgHostApi {
|
||||||
fun enableSyncWorker()
|
fun enable()
|
||||||
fun enableUploadWorker(callbackHandle: Long)
|
fun disable()
|
||||||
fun disableUploadWorker()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by BackgroundWorkerFgHostApi. */
|
/** The codec used by BackgroundWorkerFgHostApi. */
|
||||||
@@ -75,11 +74,11 @@ interface BackgroundWorkerFgHostApi {
|
|||||||
fun setUp(binaryMessenger: BinaryMessenger, api: BackgroundWorkerFgHostApi?, messageChannelSuffix: String = "") {
|
fun setUp(binaryMessenger: BinaryMessenger, api: BackgroundWorkerFgHostApi?, messageChannelSuffix: String = "") {
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
run {
|
run {
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enableSyncWorker$separatedMessageChannelSuffix", codec)
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable$separatedMessageChannelSuffix", codec)
|
||||||
if (api != null) {
|
if (api != null) {
|
||||||
channel.setMessageHandler { _, reply ->
|
channel.setMessageHandler { _, reply ->
|
||||||
val wrapped: List<Any?> = try {
|
val wrapped: List<Any?> = try {
|
||||||
api.enableSyncWorker()
|
api.enable()
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||||
@@ -91,29 +90,11 @@ interface BackgroundWorkerFgHostApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
run {
|
run {
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enableUploadWorker$separatedMessageChannelSuffix", codec)
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$separatedMessageChannelSuffix", codec)
|
||||||
if (api != null) {
|
|
||||||
channel.setMessageHandler { message, reply ->
|
|
||||||
val args = message as List<Any?>
|
|
||||||
val callbackHandleArg = args[0] as Long
|
|
||||||
val wrapped: List<Any?> = try {
|
|
||||||
api.enableUploadWorker(callbackHandleArg)
|
|
||||||
listOf(null)
|
|
||||||
} catch (exception: Throwable) {
|
|
||||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
|
||||||
}
|
|
||||||
reply.reply(wrapped)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.setMessageHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
run {
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disableUploadWorker$separatedMessageChannelSuffix", codec)
|
|
||||||
if (api != null) {
|
if (api != null) {
|
||||||
channel.setMessageHandler { _, reply ->
|
channel.setMessageHandler { _, reply ->
|
||||||
val wrapped: List<Any?> = try {
|
val wrapped: List<Any?> = try {
|
||||||
api.disableUploadWorker()
|
api.disable()
|
||||||
listOf(null)
|
listOf(null)
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||||
@@ -130,6 +111,7 @@ interface BackgroundWorkerFgHostApi {
|
|||||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
interface BackgroundWorkerBgHostApi {
|
interface BackgroundWorkerBgHostApi {
|
||||||
fun onInitialized()
|
fun onInitialized()
|
||||||
|
fun close()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by BackgroundWorkerBgHostApi. */
|
/** The codec used by BackgroundWorkerBgHostApi. */
|
||||||
@@ -156,6 +138,22 @@ interface BackgroundWorkerBgHostApi {
|
|||||||
channel.setMessageHandler(null)
|
channel.setMessageHandler(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close$separatedMessageChannelSuffix", codec)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { _, reply ->
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
api.close()
|
||||||
|
listOf(null)
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,23 +165,6 @@ class BackgroundWorkerFlutterApi(private val binaryMessenger: BinaryMessenger, p
|
|||||||
BackgroundWorkerPigeonCodec()
|
BackgroundWorkerPigeonCodec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun onLocalSync(maxSecondsArg: Long?, callback: (Result<Unit>) -> Unit)
|
|
||||||
{
|
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
|
||||||
val channelName = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onLocalSync$separatedMessageChannelSuffix"
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
|
||||||
channel.send(listOf(maxSecondsArg)) {
|
|
||||||
if (it is List<*>) {
|
|
||||||
if (it.size > 1) {
|
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
|
||||||
} else {
|
|
||||||
callback(Result.success(Unit))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(Result.failure(BackgroundWorkerPigeonUtils.createConnectionError(channelName)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun onIosUpload(isRefreshArg: Boolean, maxSecondsArg: Long?, callback: (Result<Unit>) -> Unit)
|
fun onIosUpload(isRefreshArg: Boolean, maxSecondsArg: Long?, callback: (Result<Unit>) -> Unit)
|
||||||
{
|
{
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
|
|||||||
@@ -11,17 +11,11 @@ import com.google.common.util.concurrent.ListenableFuture
|
|||||||
import com.google.common.util.concurrent.SettableFuture
|
import com.google.common.util.concurrent.SettableFuture
|
||||||
import io.flutter.FlutterInjector
|
import io.flutter.FlutterInjector
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
import io.flutter.embedding.engine.dart.DartExecutor.DartCallback
|
import io.flutter.embedding.engine.dart.DartExecutor
|
||||||
import io.flutter.embedding.engine.loader.FlutterLoader
|
import io.flutter.embedding.engine.loader.FlutterLoader
|
||||||
import io.flutter.view.FlutterCallbackInformation
|
|
||||||
|
|
||||||
private const val TAG = "BackgroundWorker"
|
private const val TAG = "BackgroundWorker"
|
||||||
|
|
||||||
enum class BackgroundTaskType {
|
|
||||||
LOCAL_SYNC,
|
|
||||||
UPLOAD,
|
|
||||||
}
|
|
||||||
|
|
||||||
class BackgroundWorker(context: Context, params: WorkerParameters) :
|
class BackgroundWorker(context: Context, params: WorkerParameters) :
|
||||||
ListenableWorker(context, params), BackgroundWorkerBgHostApi {
|
ListenableWorker(context, params), BackgroundWorkerBgHostApi {
|
||||||
private val ctx: Context = context.applicationContext
|
private val ctx: Context = context.applicationContext
|
||||||
@@ -58,25 +52,6 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
|
|||||||
loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
|
loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) {
|
||||||
engine = FlutterEngine(ctx)
|
engine = FlutterEngine(ctx)
|
||||||
|
|
||||||
// Retrieve the callback handle stored by the main Flutter app
|
|
||||||
// This handle points to the Flutter function that should be executed in the background
|
|
||||||
val callbackHandle =
|
|
||||||
ctx.getSharedPreferences(BackgroundWorkerApiImpl.SHARED_PREF_NAME, Context.MODE_PRIVATE)
|
|
||||||
.getLong(BackgroundWorkerApiImpl.SHARED_PREF_CALLBACK_HANDLE, 0L)
|
|
||||||
|
|
||||||
if (callbackHandle == 0L) {
|
|
||||||
// Without a valid callback handle, we cannot start the Flutter background execution
|
|
||||||
complete(Result.failure())
|
|
||||||
return@ensureInitializationCompleteAsync
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the Flutter engine with the specified callback as the entry point
|
|
||||||
val callback = FlutterCallbackInformation.lookupCallbackInformation(callbackHandle)
|
|
||||||
if (callback == null) {
|
|
||||||
complete(Result.failure())
|
|
||||||
return@ensureInitializationCompleteAsync
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register custom plugins
|
// Register custom plugins
|
||||||
MainActivity.registerPlugins(ctx, engine!!)
|
MainActivity.registerPlugins(ctx, engine!!)
|
||||||
flutterApi =
|
flutterApi =
|
||||||
@@ -86,8 +61,12 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
|
|||||||
api = this
|
api = this
|
||||||
)
|
)
|
||||||
|
|
||||||
engine!!.dartExecutor.executeDartCallback(
|
engine!!.dartExecutor.executeDartEntrypoint(
|
||||||
DartCallback(ctx.assets, loader.findAppBundlePath(), callback)
|
DartExecutor.DartEntrypoint(
|
||||||
|
loader.findAppBundlePath(),
|
||||||
|
"package:immich_mobile/domain/services/background_worker.service.dart",
|
||||||
|
"backgroundSyncNativeEntrypoint"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,23 +79,10 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
|
|||||||
* This method acts as a bridge between the native Android background task system and Flutter.
|
* This method acts as a bridge between the native Android background task system and Flutter.
|
||||||
*/
|
*/
|
||||||
override fun onInitialized() {
|
override fun onInitialized() {
|
||||||
val taskTypeIndex = inputData.getInt(BackgroundWorkerApiImpl.WORKER_DATA_TASK_TYPE, 0)
|
flutterApi?.onAndroidUpload { handleHostResult(it) }
|
||||||
val taskType = BackgroundTaskType.entries[taskTypeIndex]
|
|
||||||
|
|
||||||
when (taskType) {
|
|
||||||
BackgroundTaskType.LOCAL_SYNC -> flutterApi?.onLocalSync(null) { handleHostResult(it) }
|
|
||||||
BackgroundTaskType.UPLOAD -> flutterApi?.onAndroidUpload { handleHostResult(it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override fun close() {
|
||||||
* Called when the system has to stop this worker because constraints are
|
|
||||||
* no longer met or the system needs resources for more important tasks
|
|
||||||
* This is also called when the worker has been explicitly cancelled or replaced
|
|
||||||
*/
|
|
||||||
override fun onStopped() {
|
|
||||||
Log.d(TAG, "About to stop BackupWorker")
|
|
||||||
|
|
||||||
if (isComplete) {
|
if (isComplete) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -134,6 +100,16 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
|
|||||||
}, 5000)
|
}, 5000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the system has to stop this worker because constraints are
|
||||||
|
* no longer met or the system needs resources for more important tasks
|
||||||
|
* This is also called when the worker has been explicitly cancelled or replaced
|
||||||
|
*/
|
||||||
|
override fun onStopped() {
|
||||||
|
Log.d(TAG, "About to stop BackupWorker")
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleHostResult(result: kotlin.Result<Unit>) {
|
private fun handleHostResult(result: kotlin.Result<Unit>) {
|
||||||
if (isComplete) {
|
if (isComplete) {
|
||||||
return
|
return
|
||||||
@@ -154,8 +130,10 @@ class BackgroundWorker(context: Context, params: WorkerParameters) :
|
|||||||
* - Parameter success: Indicates whether the background task completed successfully
|
* - Parameter success: Indicates whether the background task completed successfully
|
||||||
*/
|
*/
|
||||||
private fun complete(success: Result) {
|
private fun complete(success: Result) {
|
||||||
|
Log.d(TAG, "About to complete BackupWorker with result: $success")
|
||||||
isComplete = true
|
isComplete = true
|
||||||
engine?.destroy()
|
engine?.destroy()
|
||||||
|
engine = null
|
||||||
flutterApi = null
|
flutterApi = null
|
||||||
completionHandler.set(success)
|
completionHandler.set(success)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ package app.alextran.immich.background
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.content.edit
|
|
||||||
import androidx.work.BackoffPolicy
|
import androidx.work.BackoffPolicy
|
||||||
import androidx.work.Constraints
|
import androidx.work.Constraints
|
||||||
import androidx.work.Data
|
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
@@ -16,19 +14,13 @@ private const val TAG = "BackgroundUploadImpl"
|
|||||||
|
|
||||||
class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
||||||
private val ctx: Context = context.applicationContext
|
private val ctx: Context = context.applicationContext
|
||||||
override fun enableSyncWorker() {
|
|
||||||
|
override fun enable() {
|
||||||
enqueueMediaObserver(ctx)
|
enqueueMediaObserver(ctx)
|
||||||
Log.i(TAG, "Scheduled media observer")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun enableUploadWorker(callbackHandle: Long) {
|
override fun disable() {
|
||||||
updateUploadEnabled(ctx, true)
|
WorkManager.getInstance(ctx).cancelUniqueWork(OBSERVER_WORKER_NAME)
|
||||||
updateCallbackHandle(ctx, callbackHandle)
|
|
||||||
Log.i(TAG, "Scheduled background upload tasks")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun disableUploadWorker() {
|
|
||||||
updateUploadEnabled(ctx, false)
|
|
||||||
WorkManager.getInstance(ctx).cancelUniqueWork(BACKGROUND_WORKER_NAME)
|
WorkManager.getInstance(ctx).cancelUniqueWork(BACKGROUND_WORKER_NAME)
|
||||||
Log.i(TAG, "Cancelled background upload tasks")
|
Log.i(TAG, "Cancelled background upload tasks")
|
||||||
}
|
}
|
||||||
@@ -37,32 +29,14 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
|||||||
private const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1"
|
private const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1"
|
||||||
private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1"
|
private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1"
|
||||||
|
|
||||||
const val WORKER_DATA_TASK_TYPE = "taskType"
|
|
||||||
|
|
||||||
const val SHARED_PREF_NAME = "Immich::Background"
|
|
||||||
const val SHARED_PREF_BACKUP_ENABLED = "Background::backup::enabled"
|
|
||||||
const val SHARED_PREF_CALLBACK_HANDLE = "Background::backup::callbackHandle"
|
|
||||||
|
|
||||||
private fun updateUploadEnabled(context: Context, enabled: Boolean) {
|
|
||||||
context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE).edit {
|
|
||||||
putBoolean(SHARED_PREF_BACKUP_ENABLED, enabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateCallbackHandle(context: Context, callbackHandle: Long) {
|
|
||||||
context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE).edit {
|
|
||||||
putLong(SHARED_PREF_CALLBACK_HANDLE, callbackHandle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enqueueMediaObserver(ctx: Context) {
|
fun enqueueMediaObserver(ctx: Context) {
|
||||||
val constraints = Constraints.Builder()
|
val constraints = Constraints.Builder()
|
||||||
.addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true)
|
.addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true)
|
||||||
.addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true)
|
.addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true)
|
||||||
.addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true)
|
.addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true)
|
||||||
.addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true)
|
.addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true)
|
||||||
.setTriggerContentUpdateDelay(5, TimeUnit.SECONDS)
|
.setTriggerContentUpdateDelay(30, TimeUnit.SECONDS)
|
||||||
.setTriggerContentMaxDelay(1, TimeUnit.MINUTES)
|
.setTriggerContentMaxDelay(3, TimeUnit.MINUTES)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val work = OneTimeWorkRequest.Builder(MediaObserver::class.java)
|
val work = OneTimeWorkRequest.Builder(MediaObserver::class.java)
|
||||||
@@ -74,15 +48,13 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
|||||||
Log.i(TAG, "Enqueued media observer worker with name: $OBSERVER_WORKER_NAME")
|
Log.i(TAG, "Enqueued media observer worker with name: $OBSERVER_WORKER_NAME")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enqueueBackgroundWorker(ctx: Context, taskType: BackgroundTaskType) {
|
fun enqueueBackgroundWorker(ctx: Context) {
|
||||||
val constraints = Constraints.Builder().setRequiresBatteryNotLow(true).build()
|
val constraints = Constraints.Builder().setRequiresBatteryNotLow(true).build()
|
||||||
|
|
||||||
val data = Data.Builder()
|
|
||||||
data.putInt(WORKER_DATA_TASK_TYPE, taskType.ordinal)
|
|
||||||
val work = OneTimeWorkRequest.Builder(BackgroundWorker::class.java)
|
val work = OneTimeWorkRequest.Builder(BackgroundWorker::class.java)
|
||||||
.setConstraints(constraints)
|
.setConstraints(constraints)
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
.setInputData(data.build()).build()
|
.build()
|
||||||
WorkManager.getInstance(ctx)
|
WorkManager.getInstance(ctx)
|
||||||
.enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.REPLACE, work)
|
.enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.REPLACE, work)
|
||||||
|
|
||||||
|
|||||||
@@ -6,29 +6,17 @@ import androidx.work.Worker
|
|||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
|
|
||||||
class MediaObserver(context: Context, params: WorkerParameters) : Worker(context, params) {
|
class MediaObserver(context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||||
private val ctx: Context = context.applicationContext
|
private val ctx: Context = context.applicationContext
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
Log.i("MediaObserver", "Content change detected, starting background worker")
|
Log.i("MediaObserver", "Content change detected, starting background worker")
|
||||||
|
// Re-enqueue itself to listen for future changes
|
||||||
|
BackgroundWorkerApiImpl.enqueueMediaObserver(ctx)
|
||||||
|
|
||||||
// Enqueue backup worker only if there are new media changes
|
// Enqueue backup worker only if there are new media changes
|
||||||
if (triggeredContentUris.isNotEmpty()) {
|
if (triggeredContentUris.isNotEmpty()) {
|
||||||
val type =
|
BackgroundWorkerApiImpl.enqueueBackgroundWorker(ctx)
|
||||||
if (isBackupEnabled(ctx)) BackgroundTaskType.UPLOAD else BackgroundTaskType.LOCAL_SYNC
|
|
||||||
BackgroundWorkerApiImpl.enqueueBackgroundWorker(ctx, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-enqueue itself to listen for future changes
|
|
||||||
BackgroundWorkerApiImpl.enqueueMediaObserver(ctx)
|
|
||||||
return Result.success()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isBackupEnabled(context: Context): Boolean {
|
|
||||||
val prefs =
|
|
||||||
context.getSharedPreferences(
|
|
||||||
BackgroundWorkerApiImpl.SHARED_PREF_NAME,
|
|
||||||
Context.MODE_PRIVATE
|
|
||||||
)
|
|
||||||
return prefs.getBoolean(BackgroundWorkerApiImpl.SHARED_PREF_BACKUP_ENABLED, false)
|
|
||||||
}
|
}
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ platform :android do
|
|||||||
task: 'bundle',
|
task: 'bundle',
|
||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 3011,
|
"android.injected.version.code" => 3013,
|
||||||
"android.injected.version.name" => "1.140.1",
|
"android.injected.version.name" => "1.141.1",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
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')
|
||||||
|
|||||||
1
mobile/drift_schemas/main/drift_schema_v10.json
generated
Normal file
1
mobile/drift_schemas/main/drift_schema_v10.json
generated
Normal file
File diff suppressed because one or more lines are too long
1
mobile/drift_schemas/main/drift_schema_v9.json
generated
Normal file
1
mobile/drift_schemas/main/drift_schema_v9.json
generated
Normal file
File diff suppressed because one or more lines are too long
@@ -39,7 +39,7 @@ class ImmichTestHelper {
|
|||||||
static Future<void> loadApp(WidgetTester tester) async {
|
static Future<void> loadApp(WidgetTester tester) async {
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
// Clear all data from Isar (reuse existing instance if available)
|
// Clear all data from Isar (reuse existing instance if available)
|
||||||
final (isar, drift, logDb) = await Bootstrap.initDB();
|
final (isar, drift, logDb) = await Bootstrap.initDB(shareAcrossIsolates: true);
|
||||||
await Bootstrap.initDomain(isar, drift, logDb);
|
await Bootstrap.initDomain(isar, drift, logDb);
|
||||||
await Store.clear();
|
await Store.clear();
|
||||||
await isar.writeTxn(() => isar.clear());
|
await isar.writeTxn(() => isar.clear());
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 77;
|
objectVersion = 54;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@@ -507,14 +507,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
@@ -543,14 +539,10 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import UIKit
|
|||||||
BackgroundServicePlugin.register(with: self.registrar(forPlugin: "BackgroundServicePlugin")!)
|
BackgroundServicePlugin.register(with: self.registrar(forPlugin: "BackgroundServicePlugin")!)
|
||||||
|
|
||||||
BackgroundServicePlugin.registerBackgroundProcessing()
|
BackgroundServicePlugin.registerBackgroundProcessing()
|
||||||
BackgroundWorkerApiImpl.registerBackgroundProcessing()
|
BackgroundWorkerApiImpl.registerBackgroundWorkers()
|
||||||
|
|
||||||
BackgroundServicePlugin.setPluginRegistrantCallback { registry in
|
BackgroundServicePlugin.setPluginRegistrantCallback { registry in
|
||||||
if !registry.hasPlugin("org.cocoapods.path-provider-foundation") {
|
if !registry.hasPlugin("org.cocoapods.path-provider-foundation") {
|
||||||
|
|||||||
@@ -73,9 +73,8 @@ class BackgroundWorkerPigeonCodec: FlutterStandardMessageCodec, @unchecked Senda
|
|||||||
|
|
||||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||||
protocol BackgroundWorkerFgHostApi {
|
protocol BackgroundWorkerFgHostApi {
|
||||||
func enableSyncWorker() throws
|
func enable() throws
|
||||||
func enableUploadWorker(callbackHandle: Int64) throws
|
func disable() throws
|
||||||
func disableUploadWorker() throws
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||||
@@ -84,52 +83,38 @@ class BackgroundWorkerFgHostApiSetup {
|
|||||||
/// Sets up an instance of `BackgroundWorkerFgHostApi` to handle messages through the `binaryMessenger`.
|
/// Sets up an instance of `BackgroundWorkerFgHostApi` to handle messages through the `binaryMessenger`.
|
||||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: BackgroundWorkerFgHostApi?, messageChannelSuffix: String = "") {
|
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: BackgroundWorkerFgHostApi?, messageChannelSuffix: String = "") {
|
||||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||||
let enableSyncWorkerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enableSyncWorker\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
let enableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
if let api = api {
|
if let api = api {
|
||||||
enableSyncWorkerChannel.setMessageHandler { _, reply in
|
enableChannel.setMessageHandler { _, reply in
|
||||||
do {
|
do {
|
||||||
try api.enableSyncWorker()
|
try api.enable()
|
||||||
reply(wrapResult(nil))
|
reply(wrapResult(nil))
|
||||||
} catch {
|
} catch {
|
||||||
reply(wrapError(error))
|
reply(wrapError(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enableSyncWorkerChannel.setMessageHandler(nil)
|
enableChannel.setMessageHandler(nil)
|
||||||
}
|
}
|
||||||
let enableUploadWorkerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enableUploadWorker\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
if let api = api {
|
if let api = api {
|
||||||
enableUploadWorkerChannel.setMessageHandler { message, reply in
|
disableChannel.setMessageHandler { _, reply in
|
||||||
let args = message as! [Any?]
|
|
||||||
let callbackHandleArg = args[0] as! Int64
|
|
||||||
do {
|
do {
|
||||||
try api.enableUploadWorker(callbackHandle: callbackHandleArg)
|
try api.disable()
|
||||||
reply(wrapResult(nil))
|
reply(wrapResult(nil))
|
||||||
} catch {
|
} catch {
|
||||||
reply(wrapError(error))
|
reply(wrapError(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enableUploadWorkerChannel.setMessageHandler(nil)
|
disableChannel.setMessageHandler(nil)
|
||||||
}
|
|
||||||
let disableUploadWorkerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disableUploadWorker\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
if let api = api {
|
|
||||||
disableUploadWorkerChannel.setMessageHandler { _, reply in
|
|
||||||
do {
|
|
||||||
try api.disableUploadWorker()
|
|
||||||
reply(wrapResult(nil))
|
|
||||||
} catch {
|
|
||||||
reply(wrapError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
disableUploadWorkerChannel.setMessageHandler(nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||||
protocol BackgroundWorkerBgHostApi {
|
protocol BackgroundWorkerBgHostApi {
|
||||||
func onInitialized() throws
|
func onInitialized() throws
|
||||||
|
func close() throws
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||||
@@ -151,11 +136,23 @@ class BackgroundWorkerBgHostApiSetup {
|
|||||||
} else {
|
} else {
|
||||||
onInitializedChannel.setMessageHandler(nil)
|
onInitializedChannel.setMessageHandler(nil)
|
||||||
}
|
}
|
||||||
|
let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
|
if let api = api {
|
||||||
|
closeChannel.setMessageHandler { _, reply in
|
||||||
|
do {
|
||||||
|
try api.close()
|
||||||
|
reply(wrapResult(nil))
|
||||||
|
} catch {
|
||||||
|
reply(wrapError(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
closeChannel.setMessageHandler(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||||
protocol BackgroundWorkerFlutterApiProtocol {
|
protocol BackgroundWorkerFlutterApiProtocol {
|
||||||
func onLocalSync(maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
|
||||||
func onIosUpload(isRefresh isRefreshArg: Bool, maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func onIosUpload(isRefresh isRefreshArg: Bool, maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
func onAndroidUpload(completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func onAndroidUpload(completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
func cancel(completion: @escaping (Result<Void, PigeonError>) -> Void)
|
func cancel(completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||||
@@ -170,24 +167,6 @@ class BackgroundWorkerFlutterApi: BackgroundWorkerFlutterApiProtocol {
|
|||||||
var codec: BackgroundWorkerPigeonCodec {
|
var codec: BackgroundWorkerPigeonCodec {
|
||||||
return BackgroundWorkerPigeonCodec.shared
|
return BackgroundWorkerPigeonCodec.shared
|
||||||
}
|
}
|
||||||
func onLocalSync(maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
|
||||||
let channelName: String = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onLocalSync\(messageChannelSuffix)"
|
|
||||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
channel.sendMessage([maxSecondsArg] as [Any?]) { response in
|
|
||||||
guard let listResponse = response as? [Any?] else {
|
|
||||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if listResponse.count > 1 {
|
|
||||||
let code: String = listResponse[0] as! String
|
|
||||||
let message: String? = nilOrValue(listResponse[1])
|
|
||||||
let details: String? = nilOrValue(listResponse[2])
|
|
||||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
|
||||||
} else {
|
|
||||||
completion(.success(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func onIosUpload(isRefresh isRefreshArg: Bool, maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
func onIosUpload(isRefresh isRefreshArg: Bool, maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||||
let channelName: String = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload\(messageChannelSuffix)"
|
let channelName: String = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload\(messageChannelSuffix)"
|
||||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import BackgroundTasks
|
import BackgroundTasks
|
||||||
import Flutter
|
import Flutter
|
||||||
|
|
||||||
enum BackgroundTaskType { case localSync, refreshUpload, processingUpload }
|
enum BackgroundTaskType { case refresh, processing }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DEBUG: Testing Background Tasks in Xcode
|
* DEBUG: Testing Background Tasks in Xcode
|
||||||
@@ -9,10 +9,6 @@ enum BackgroundTaskType { case localSync, refreshUpload, processingUpload }
|
|||||||
* To test background task functionality during development:
|
* To test background task functionality during development:
|
||||||
* 1. Pause the application in Xcode debugger
|
* 1. Pause the application in Xcode debugger
|
||||||
* 2. In the debugger console, enter one of the following commands:
|
* 2. In the debugger console, enter one of the following commands:
|
||||||
|
|
||||||
## For local sync (short-running sync):
|
|
||||||
|
|
||||||
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"app.alextran.immich.background.localSync"]
|
|
||||||
|
|
||||||
## For background refresh (short-running sync):
|
## For background refresh (short-running sync):
|
||||||
|
|
||||||
@@ -24,8 +20,6 @@ enum BackgroundTaskType { case localSync, refreshUpload, processingUpload }
|
|||||||
|
|
||||||
* To simulate task expiration (useful for testing expiration handlers):
|
* To simulate task expiration (useful for testing expiration handlers):
|
||||||
|
|
||||||
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"app.alextran.immich.background.localSync"]
|
|
||||||
|
|
||||||
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"app.alextran.immich.background.refreshUpload"]
|
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"app.alextran.immich.background.refreshUpload"]
|
||||||
|
|
||||||
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"app.alextran.immich.background.processingUpload"]
|
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"app.alextran.immich.background.processingUpload"]
|
||||||
@@ -86,28 +80,10 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
|
|||||||
* starts the engine, and sets up a timeout timer if specified.
|
* starts the engine, and sets up a timeout timer if specified.
|
||||||
*/
|
*/
|
||||||
func run() {
|
func run() {
|
||||||
// Retrieve the callback handle stored by the main Flutter app
|
|
||||||
// This handle points to the Flutter function that should be executed in the background
|
|
||||||
let callbackHandle = Int64(UserDefaults.standard.string(
|
|
||||||
forKey: BackgroundWorkerApiImpl.backgroundUploadCallbackHandleKey) ?? "0") ?? 0
|
|
||||||
|
|
||||||
if callbackHandle == 0 {
|
|
||||||
// Without a valid callback handle, we cannot start the Flutter background execution
|
|
||||||
complete(success: false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the callback handle to retrieve the actual Flutter callback information
|
|
||||||
guard let callback = FlutterCallbackCache.lookupCallbackInformation(callbackHandle) else {
|
|
||||||
// The callback handle is invalid or the callback was not found
|
|
||||||
complete(success: false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the Flutter engine with the specified callback as the entry point
|
// Start the Flutter engine with the specified callback as the entry point
|
||||||
let isRunning = engine.run(
|
let isRunning = engine.run(
|
||||||
withEntrypoint: callback.callbackName,
|
withEntrypoint: "backgroundSyncNativeEntrypoint",
|
||||||
libraryURI: callback.callbackLibraryPath
|
libraryURI: "package:immich_mobile/domain/services/background_worker.service.dart"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Verify that the Flutter engine started successfully
|
// Verify that the Flutter engine started successfully
|
||||||
@@ -127,7 +103,7 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
|
|||||||
if maxSeconds != nil {
|
if maxSeconds != nil {
|
||||||
// Schedule a timer to cancel the task after the specified timeout period
|
// Schedule a timer to cancel the task after the specified timeout period
|
||||||
Timer.scheduledTimer(withTimeInterval: TimeInterval(maxSeconds!), repeats: false) { _ in
|
Timer.scheduledTimer(withTimeInterval: TimeInterval(maxSeconds!), repeats: false) { _ in
|
||||||
self.cancel()
|
self.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,25 +114,17 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
|
|||||||
* This method acts as a bridge between the native iOS background task system and Flutter.
|
* This method acts as a bridge between the native iOS background task system and Flutter.
|
||||||
*/
|
*/
|
||||||
func onInitialized() throws {
|
func onInitialized() throws {
|
||||||
switch self.taskType {
|
flutterApi?.onIosUpload(isRefresh: self.taskType == .refresh, maxSeconds: maxSeconds.map { Int64($0) }, completion: { result in
|
||||||
case .refreshUpload, .processingUpload:
|
self.handleHostResult(result: result)
|
||||||
flutterApi?.onIosUpload(isRefresh: self.taskType == .refreshUpload,
|
})
|
||||||
maxSeconds: maxSeconds.map { Int64($0) }, completion: { result in
|
|
||||||
self.handleHostResult(result: result)
|
|
||||||
})
|
|
||||||
case .localSync:
|
|
||||||
flutterApi?.onLocalSync(maxSeconds: maxSeconds.map { Int64($0) }, completion: { result in
|
|
||||||
self.handleHostResult(result: result)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancels the currently running background task, either due to timeout or external request.
|
* Cancels the currently running background task, either due to timeout or external request.
|
||||||
* Sends a cancel signal to the Flutter side and sets up a fallback timer to ensure
|
* Sends a cancel signal to the Flutter side and sets up a fallback timer to ensure
|
||||||
* the completion handler is eventually called even if Flutter doesn't respond.
|
* the completion handler is eventually called even if Flutter doesn't respond.
|
||||||
*/
|
*/
|
||||||
func cancel() {
|
func close() {
|
||||||
if isComplete {
|
if isComplete {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -172,6 +140,7 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
|
|||||||
self.complete(success: false)
|
self.complete(success: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the result from Flutter API calls and determines the success/failure status.
|
* Handles the result from Flutter API calls and determines the success/failure status.
|
||||||
@@ -182,7 +151,7 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
|
|||||||
private func handleHostResult(result: Result<Void, PigeonError>) {
|
private func handleHostResult(result: Result<Void, PigeonError>) {
|
||||||
switch result {
|
switch result {
|
||||||
case .success(): self.complete(success: true)
|
case .success(): self.complete(success: true)
|
||||||
case .failure(_): self.cancel()
|
case .failure(_): self.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,6 +164,10 @@ class BackgroundWorker: BackgroundWorkerBgHostApi {
|
|||||||
* - Parameter success: Indicates whether the background task completed successfully
|
* - Parameter success: Indicates whether the background task completed successfully
|
||||||
*/
|
*/
|
||||||
private func complete(success: Bool) {
|
private func complete(success: Bool) {
|
||||||
|
if(isComplete) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isComplete = true
|
isComplete = true
|
||||||
engine.destroyContext()
|
engine.destroyContext()
|
||||||
completionHandler(success)
|
completionHandler(success)
|
||||||
|
|||||||
@@ -1,84 +1,40 @@
|
|||||||
import BackgroundTasks
|
import BackgroundTasks
|
||||||
|
|
||||||
class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
||||||
func enableSyncWorker() throws {
|
|
||||||
BackgroundWorkerApiImpl.scheduleLocalSync()
|
func enable() throws {
|
||||||
print("BackgroundUploadImpl:enableSyncWorker Local Sync worker scheduled")
|
BackgroundWorkerApiImpl.scheduleRefreshWorker()
|
||||||
|
BackgroundWorkerApiImpl.scheduleProcessingWorker()
|
||||||
|
print("BackgroundUploadImpl:enbale Background worker scheduled")
|
||||||
}
|
}
|
||||||
|
|
||||||
func enableUploadWorker(callbackHandle: Int64) throws {
|
func disable() throws {
|
||||||
BackgroundWorkerApiImpl.updateUploadEnabled(true)
|
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.refreshTaskID);
|
||||||
// Store the callback handle for later use when starting background Flutter isolates
|
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.processingTaskID);
|
||||||
BackgroundWorkerApiImpl.updateUploadCallbackHandle(callbackHandle)
|
print("BackgroundUploadImpl:disableUploadWorker Disabled background workers")
|
||||||
|
|
||||||
BackgroundWorkerApiImpl.scheduleRefreshUpload()
|
|
||||||
BackgroundWorkerApiImpl.scheduleProcessingUpload()
|
|
||||||
print("BackgroundUploadImpl:enableUploadWorker Scheduled background upload tasks")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func disableUploadWorker() throws {
|
private static let refreshTaskID = "app.alextran.immich.background.refreshUpload"
|
||||||
BackgroundWorkerApiImpl.updateUploadEnabled(false)
|
private static let processingTaskID = "app.alextran.immich.background.processingUpload"
|
||||||
BackgroundWorkerApiImpl.cancelUploadTasks()
|
|
||||||
print("BackgroundUploadImpl:disableUploadWorker Disabled background upload tasks")
|
|
||||||
}
|
|
||||||
|
|
||||||
public static let backgroundUploadEnabledKey = "immich:background:backup:enabled"
|
|
||||||
public static let backgroundUploadCallbackHandleKey = "immich:background:backup:callbackHandle"
|
|
||||||
|
|
||||||
private static let localSyncTaskID = "app.alextran.immich.background.localSync"
|
|
||||||
private static let refreshUploadTaskID = "app.alextran.immich.background.refreshUpload"
|
|
||||||
private static let processingUploadTaskID = "app.alextran.immich.background.processingUpload"
|
|
||||||
|
|
||||||
private static func updateUploadEnabled(_ isEnabled: Bool) {
|
public static func registerBackgroundWorkers() {
|
||||||
return UserDefaults.standard.set(isEnabled, forKey: BackgroundWorkerApiImpl.backgroundUploadEnabledKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func updateUploadCallbackHandle(_ callbackHandle: Int64) {
|
|
||||||
return UserDefaults.standard.set(String(callbackHandle), forKey: BackgroundWorkerApiImpl.backgroundUploadCallbackHandleKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func cancelUploadTasks() {
|
|
||||||
BackgroundWorkerApiImpl.updateUploadEnabled(false)
|
|
||||||
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: refreshUploadTaskID);
|
|
||||||
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: processingUploadTaskID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static func registerBackgroundProcessing() {
|
|
||||||
BGTaskScheduler.shared.register(
|
BGTaskScheduler.shared.register(
|
||||||
forTaskWithIdentifier: processingUploadTaskID, using: nil) { task in
|
forTaskWithIdentifier: processingTaskID, using: nil) { task in
|
||||||
if task is BGProcessingTask {
|
if task is BGProcessingTask {
|
||||||
handleBackgroundProcessing(task: task as! BGProcessingTask)
|
handleBackgroundProcessing(task: task as! BGProcessingTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BGTaskScheduler.shared.register(
|
BGTaskScheduler.shared.register(
|
||||||
forTaskWithIdentifier: refreshUploadTaskID, using: nil) { task in
|
forTaskWithIdentifier: refreshTaskID, using: nil) { task in
|
||||||
if task is BGAppRefreshTask {
|
if task is BGAppRefreshTask {
|
||||||
handleBackgroundRefresh(task: task as! BGAppRefreshTask, taskType: .refreshUpload)
|
handleBackgroundRefresh(task: task as! BGAppRefreshTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BGTaskScheduler.shared.register(
|
|
||||||
forTaskWithIdentifier: localSyncTaskID, using: nil) { task in
|
|
||||||
if task is BGAppRefreshTask {
|
|
||||||
handleBackgroundRefresh(task: task as! BGAppRefreshTask, taskType: .localSync)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func scheduleLocalSync() {
|
private static func scheduleRefreshWorker() {
|
||||||
let backgroundRefresh = BGAppRefreshTaskRequest(identifier: localSyncTaskID)
|
let backgroundRefresh = BGAppRefreshTaskRequest(identifier: refreshTaskID)
|
||||||
backgroundRefresh.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60) // 5 mins
|
|
||||||
|
|
||||||
do {
|
|
||||||
try BGTaskScheduler.shared.submit(backgroundRefresh)
|
|
||||||
} catch {
|
|
||||||
print("Could not schedule the local sync task \(error.localizedDescription)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static func scheduleRefreshUpload() {
|
|
||||||
let backgroundRefresh = BGAppRefreshTaskRequest(identifier: refreshUploadTaskID)
|
|
||||||
backgroundRefresh.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60) // 5 mins
|
backgroundRefresh.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60) // 5 mins
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -88,8 +44,8 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func scheduleProcessingUpload() {
|
private static func scheduleProcessingWorker() {
|
||||||
let backgroundProcessing = BGProcessingTaskRequest(identifier: processingUploadTaskID)
|
let backgroundProcessing = BGProcessingTaskRequest(identifier: processingTaskID)
|
||||||
|
|
||||||
backgroundProcessing.requiresNetworkConnectivity = true
|
backgroundProcessing.requiresNetworkConnectivity = true
|
||||||
backgroundProcessing.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 mins
|
backgroundProcessing.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 mins
|
||||||
@@ -101,16 +57,16 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func handleBackgroundRefresh(task: BGAppRefreshTask, taskType: BackgroundTaskType) {
|
private static func handleBackgroundRefresh(task: BGAppRefreshTask) {
|
||||||
scheduleRefreshUpload()
|
scheduleRefreshWorker()
|
||||||
// Restrict the refresh task to run only for a maximum of 20 seconds
|
// Restrict the refresh task to run only for a maximum of (maxSeconds) seconds
|
||||||
runBackgroundWorker(task: task, taskType: taskType, maxSeconds: 20)
|
runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func handleBackgroundProcessing(task: BGProcessingTask) {
|
private static func handleBackgroundProcessing(task: BGProcessingTask) {
|
||||||
scheduleProcessingUpload()
|
scheduleProcessingWorker()
|
||||||
// There are no restrictions for processing tasks. Although, the OS could signal expiration at any time
|
// There are no restrictions for processing tasks. Although, the OS could signal expiration at any time
|
||||||
runBackgroundWorker(task: task, taskType: .processingUpload, maxSeconds: nil)
|
runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +90,7 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
|||||||
|
|
||||||
task.expirationHandler = {
|
task.expirationHandler = {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
backgroundWorker.cancel()
|
backgroundWorker.close()
|
||||||
}
|
}
|
||||||
isSuccess = false
|
isSuccess = false
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,23 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
assetCache.countLimit = 10000
|
assetCache.countLimit = 10000
|
||||||
return assetCache
|
return assetCache
|
||||||
}()
|
}()
|
||||||
|
private static let activitySemaphore = DispatchSemaphore(value: 1)
|
||||||
|
private static let willResignActiveObserver = NotificationCenter.default.addObserver(
|
||||||
|
forName: UIApplication.willResignActiveNotification,
|
||||||
|
object: nil,
|
||||||
|
queue: .main
|
||||||
|
) { _ in
|
||||||
|
processingQueue.suspend()
|
||||||
|
activitySemaphore.wait()
|
||||||
|
}
|
||||||
|
private static let didBecomeActiveObserver = NotificationCenter.default.addObserver(
|
||||||
|
forName: UIApplication.didBecomeActiveNotification,
|
||||||
|
object: nil,
|
||||||
|
queue: .main
|
||||||
|
) { _ in
|
||||||
|
processingQueue.resume()
|
||||||
|
activitySemaphore.signal()
|
||||||
|
}
|
||||||
|
|
||||||
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String : Int64], any Error>) -> Void) {
|
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String : Int64], any Error>) -> Void) {
|
||||||
Self.processingQueue.async {
|
Self.processingQueue.async {
|
||||||
@@ -53,6 +70,7 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
else { return completion(.failure(PigeonError(code: "", message: "Invalid base64 string: \(thumbhash)", details: nil)))}
|
else { return completion(.failure(PigeonError(code: "", message: "Invalid base64 string: \(thumbhash)", details: nil)))}
|
||||||
|
|
||||||
let (width, height, pointer) = thumbHashToRGBA(hash: data)
|
let (width, height, pointer) = thumbHashToRGBA(hash: data)
|
||||||
|
self.waitForActiveState()
|
||||||
completion(.success(["pointer": Int64(Int(bitPattern: pointer.baseAddress)), "width": Int64(width), "height": Int64(height)]))
|
completion(.success(["pointer": Int64(Int(bitPattern: pointer.baseAddress)), "width": Int64(width), "height": Int64(height)]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +160,7 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
return completion(Self.cancelledResult)
|
return completion(Self.cancelledResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.waitForActiveState()
|
||||||
completion(.success(["pointer": Int64(Int(bitPattern: pointer)), "width": Int64(cgImage.width), "height": Int64(cgImage.height)]))
|
completion(.success(["pointer": Int64(Int(bitPattern: pointer)), "width": Int64(cgImage.width), "height": Int64(cgImage.height)]))
|
||||||
Self.removeRequest(requestId: requestId)
|
Self.removeRequest(requestId: requestId)
|
||||||
}
|
}
|
||||||
@@ -184,4 +203,9 @@ class ThumbnailApiImpl: ThumbnailApi {
|
|||||||
assetQueue.async { assetCache.setObject(asset, forKey: assetId as NSString) }
|
assetQueue.async { assetCache.setObject(asset, forKey: assetId as NSString) }
|
||||||
return asset
|
return asset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func waitForActiveState() {
|
||||||
|
Self.activitySemaphore.wait()
|
||||||
|
Self.activitySemaphore.signal()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,190 +1,189 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>AppGroupId</key>
|
<key>AppGroupId</key>
|
||||||
<string>$(CUSTOM_GROUP_ID)</string>
|
<string>$(CUSTOM_GROUP_ID)</string>
|
||||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||||
<array>
|
<array>
|
||||||
<string>app.alextran.immich.background.localSync</string>
|
<string>app.alextran.immich.background.refreshUpload</string>
|
||||||
<string>app.alextran.immich.background.refreshUpload</string>
|
<string>app.alextran.immich.background.processingUpload</string>
|
||||||
<string>app.alextran.immich.background.processingUpload</string>
|
<string>app.alextran.immich.backgroundFetch</string>
|
||||||
<string>app.alextran.immich.backgroundFetch</string>
|
<string>app.alextran.immich.backgroundProcessing</string>
|
||||||
<string>app.alextran.immich.backgroundProcessing</string>
|
</array>
|
||||||
</array>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<true/>
|
||||||
<true />
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<key>CFBundleDisplayName</key>
|
||||||
<key>CFBundleDisplayName</key>
|
<string>${PRODUCT_NAME}</string>
|
||||||
<string>${PRODUCT_NAME}</string>
|
<key>CFBundleDocumentTypes</key>
|
||||||
<key>CFBundleDocumentTypes</key>
|
<array>
|
||||||
<array>
|
<dict>
|
||||||
<dict>
|
<key>CFBundleTypeName</key>
|
||||||
<key>CFBundleTypeName</key>
|
<string>ShareHandler</string>
|
||||||
<string>ShareHandler</string>
|
<key>LSHandlerRank</key>
|
||||||
<key>LSHandlerRank</key>
|
<string>Alternate</string>
|
||||||
<string>Alternate</string>
|
<key>LSItemContentTypes</key>
|
||||||
<key>LSItemContentTypes</key>
|
<array>
|
||||||
<array>
|
<string>public.file-url</string>
|
||||||
<string>public.file-url</string>
|
<string>public.image</string>
|
||||||
<string>public.image</string>
|
<string>public.text</string>
|
||||||
<string>public.text</string>
|
<string>public.movie</string>
|
||||||
<string>public.movie</string>
|
<string>public.url</string>
|
||||||
<string>public.url</string>
|
<string>public.data</string>
|
||||||
<string>public.data</string>
|
</array>
|
||||||
</array>
|
</dict>
|
||||||
</dict>
|
</array>
|
||||||
</array>
|
<key>CFBundleExecutable</key>
|
||||||
<key>CFBundleExecutable</key>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<key>CFBundleIdentifier</key>
|
||||||
<key>CFBundleIdentifier</key>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<string>6.0</string>
|
||||||
<string>6.0</string>
|
<key>CFBundleLocalizations</key>
|
||||||
<key>CFBundleLocalizations</key>
|
<array>
|
||||||
<array>
|
<string>en</string>
|
||||||
<string>en</string>
|
<string>ar</string>
|
||||||
<string>ar</string>
|
<string>ca</string>
|
||||||
<string>ca</string>
|
<string>cs</string>
|
||||||
<string>cs</string>
|
<string>da</string>
|
||||||
<string>da</string>
|
<string>de</string>
|
||||||
<string>de</string>
|
<string>es</string>
|
||||||
<string>es</string>
|
<string>fi</string>
|
||||||
<string>fi</string>
|
<string>fr</string>
|
||||||
<string>fr</string>
|
<string>he</string>
|
||||||
<string>he</string>
|
<string>hi</string>
|
||||||
<string>hi</string>
|
<string>hu</string>
|
||||||
<string>hu</string>
|
<string>it</string>
|
||||||
<string>it</string>
|
<string>ja</string>
|
||||||
<string>ja</string>
|
<string>ko</string>
|
||||||
<string>ko</string>
|
<string>lv</string>
|
||||||
<string>lv</string>
|
<string>mn</string>
|
||||||
<string>mn</string>
|
<string>nb</string>
|
||||||
<string>nb</string>
|
<string>nl</string>
|
||||||
<string>nl</string>
|
<string>pl</string>
|
||||||
<string>pl</string>
|
<string>pt</string>
|
||||||
<string>pt</string>
|
<string>ro</string>
|
||||||
<string>ro</string>
|
<string>ru</string>
|
||||||
<string>ru</string>
|
<string>sk</string>
|
||||||
<string>sk</string>
|
<string>sl</string>
|
||||||
<string>sl</string>
|
<string>sr</string>
|
||||||
<string>sr</string>
|
<string>sv</string>
|
||||||
<string>sv</string>
|
<string>th</string>
|
||||||
<string>th</string>
|
<string>uk</string>
|
||||||
<string>uk</string>
|
<string>vi</string>
|
||||||
<string>vi</string>
|
<string>zh</string>
|
||||||
<string>zh</string>
|
</array>
|
||||||
</array>
|
<key>CFBundleName</key>
|
||||||
<key>CFBundleName</key>
|
<string>immich_mobile</string>
|
||||||
<string>immich_mobile</string>
|
<key>CFBundlePackageType</key>
|
||||||
<key>CFBundlePackageType</key>
|
<string>APPL</string>
|
||||||
<string>APPL</string>
|
<key>CFBundleShortVersionString</key>
|
||||||
<key>CFBundleShortVersionString</key>
|
<string>1.140.0</string>
|
||||||
<string>1.140.0</string>
|
<key>CFBundleSignature</key>
|
||||||
<key>CFBundleSignature</key>
|
<string>????</string>
|
||||||
<string>????</string>
|
<key>CFBundleURLTypes</key>
|
||||||
<key>CFBundleURLTypes</key>
|
<array>
|
||||||
<array>
|
<dict>
|
||||||
<dict>
|
<key>CFBundleTypeRole</key>
|
||||||
<key>CFBundleTypeRole</key>
|
<string>Editor</string>
|
||||||
<string>Editor</string>
|
<key>CFBundleURLName</key>
|
||||||
<key>CFBundleURLName</key>
|
<string>Share Extension</string>
|
||||||
<string>Share Extension</string>
|
<key>CFBundleURLSchemes</key>
|
||||||
<key>CFBundleURLSchemes</key>
|
<array>
|
||||||
<array>
|
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
</array>
|
||||||
</array>
|
</dict>
|
||||||
</dict>
|
<dict>
|
||||||
<dict>
|
<key>CFBundleTypeRole</key>
|
||||||
<key>CFBundleTypeRole</key>
|
<string>Editor</string>
|
||||||
<string>Editor</string>
|
<key>CFBundleURLName</key>
|
||||||
<key>CFBundleURLName</key>
|
<string>Deep Link</string>
|
||||||
<string>Deep Link</string>
|
<key>CFBundleURLSchemes</key>
|
||||||
<key>CFBundleURLSchemes</key>
|
<array>
|
||||||
<array>
|
<string>immich</string>
|
||||||
<string>immich</string>
|
</array>
|
||||||
</array>
|
</dict>
|
||||||
</dict>
|
</array>
|
||||||
</array>
|
<key>CFBundleVersion</key>
|
||||||
<key>CFBundleVersion</key>
|
<string>219</string>
|
||||||
<string>219</string>
|
<key>FLTEnableImpeller</key>
|
||||||
<key>FLTEnableImpeller</key>
|
<true/>
|
||||||
<true />
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<false/>
|
||||||
<false />
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
<key>LSApplicationQueriesSchemes</key>
|
<array>
|
||||||
<array>
|
<string>https</string>
|
||||||
<string>https</string>
|
</array>
|
||||||
</array>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<true/>
|
||||||
<true />
|
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
<string>No</string>
|
||||||
<string>No</string>
|
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
|
||||||
<key>MGLMapboxMetricsEnabledSettingShownInApp</key>
|
<true/>
|
||||||
<true />
|
<key>NSAppTransportSecurity</key>
|
||||||
<key>NSAppTransportSecurity</key>
|
<dict>
|
||||||
<dict>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<true/>
|
||||||
<true />
|
</dict>
|
||||||
</dict>
|
<key>NSBonjourServices</key>
|
||||||
<key>NSBonjourServices</key>
|
<array>
|
||||||
<array>
|
<string>_googlecast._tcp</string>
|
||||||
<string>_googlecast._tcp</string>
|
<string>_CC1AD845._googlecast._tcp</string>
|
||||||
<string>_CC1AD845._googlecast._tcp</string>
|
</array>
|
||||||
</array>
|
<key>NSCameraUsageDescription</key>
|
||||||
<key>NSCameraUsageDescription</key>
|
<string>We need to access the camera to let you take beautiful video using this app</string>
|
||||||
<string>We need to access the camera to let you take beautiful video using this app</string>
|
<key>NSFaceIDUsageDescription</key>
|
||||||
<key>NSFaceIDUsageDescription</key>
|
<string>We need to use FaceID to allow access to your locked folder</string>
|
||||||
<string>We need to use FaceID to allow access to your locked folder</string>
|
<key>NSLocalNetworkUsageDescription</key>
|
||||||
<key>NSLocalNetworkUsageDescription</key>
|
<string>We need local network permission to connect to the local server using IP address and
|
||||||
<string>We need local network permission to connect to the local server using IP address and
|
|
||||||
allow the casting feature to work</string>
|
allow the casting feature to work</string>
|
||||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
<string>We require this permission to access the local WiFi name for background upload mechanism</string>
|
<string>We require this permission to access the local WiFi name for background upload mechanism</string>
|
||||||
<key>NSLocationUsageDescription</key>
|
<key>NSLocationUsageDescription</key>
|
||||||
<string>We require this permission to access the local WiFi name</string>
|
<string>We require this permission to access the local WiFi name</string>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string>We require this permission to access the local WiFi name</string>
|
<string>We require this permission to access the local WiFi name</string>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>We need to access the microphone to let you take beautiful video using this app</string>
|
<string>We need to access the microphone to let you take beautiful video using this app</string>
|
||||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
<string>We need to manage backup your photos album</string>
|
<string>We need to manage backup your photos album</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>We need to manage backup your photos album</string>
|
<string>We need to manage backup your photos album</string>
|
||||||
<key>NSUserActivityTypes</key>
|
<key>NSUserActivityTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>INSendMessageIntent</string>
|
<string>INSendMessageIntent</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true />
|
<true/>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
<string>processing</string>
|
<string>processing</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
<key>UIStatusBarHidden</key>
|
<key>UIStatusBarHidden</key>
|
||||||
<false />
|
<false/>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<true />
|
<true/>
|
||||||
<key>io.flutter.embedded_views_preview</key>
|
<key>io.flutter.embedded_views_preview</key>
|
||||||
<true />
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ platform :ios do
|
|||||||
path: "./Runner.xcodeproj",
|
path: "./Runner.xcodeproj",
|
||||||
)
|
)
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.140.1"
|
version_number: "1.141.1"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class LocalAlbum {
|
|||||||
|
|
||||||
final int assetCount;
|
final int assetCount;
|
||||||
final BackupSelection backupSelection;
|
final BackupSelection backupSelection;
|
||||||
|
final String? linkedRemoteAlbumId;
|
||||||
|
|
||||||
const LocalAlbum({
|
const LocalAlbum({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -23,6 +24,7 @@ class LocalAlbum {
|
|||||||
this.assetCount = 0,
|
this.assetCount = 0,
|
||||||
this.backupSelection = BackupSelection.none,
|
this.backupSelection = BackupSelection.none,
|
||||||
this.isIosSharedAlbum = false,
|
this.isIosSharedAlbum = false,
|
||||||
|
this.linkedRemoteAlbumId,
|
||||||
});
|
});
|
||||||
|
|
||||||
LocalAlbum copyWith({
|
LocalAlbum copyWith({
|
||||||
@@ -32,6 +34,7 @@ class LocalAlbum {
|
|||||||
int? assetCount,
|
int? assetCount,
|
||||||
BackupSelection? backupSelection,
|
BackupSelection? backupSelection,
|
||||||
bool? isIosSharedAlbum,
|
bool? isIosSharedAlbum,
|
||||||
|
String? linkedRemoteAlbumId,
|
||||||
}) {
|
}) {
|
||||||
return LocalAlbum(
|
return LocalAlbum(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
@@ -40,6 +43,7 @@ class LocalAlbum {
|
|||||||
assetCount: assetCount ?? this.assetCount,
|
assetCount: assetCount ?? this.assetCount,
|
||||||
backupSelection: backupSelection ?? this.backupSelection,
|
backupSelection: backupSelection ?? this.backupSelection,
|
||||||
isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum,
|
isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId: linkedRemoteAlbumId ?? this.linkedRemoteAlbumId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +57,8 @@ class LocalAlbum {
|
|||||||
other.updatedAt == updatedAt &&
|
other.updatedAt == updatedAt &&
|
||||||
other.assetCount == assetCount &&
|
other.assetCount == assetCount &&
|
||||||
other.backupSelection == backupSelection &&
|
other.backupSelection == backupSelection &&
|
||||||
other.isIosSharedAlbum == isIosSharedAlbum;
|
other.isIosSharedAlbum == isIosSharedAlbum &&
|
||||||
|
other.linkedRemoteAlbumId == linkedRemoteAlbumId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -63,7 +68,8 @@ class LocalAlbum {
|
|||||||
updatedAt.hashCode ^
|
updatedAt.hashCode ^
|
||||||
assetCount.hashCode ^
|
assetCount.hashCode ^
|
||||||
backupSelection.hashCode ^
|
backupSelection.hashCode ^
|
||||||
isIosSharedAlbum.hashCode;
|
isIosSharedAlbum.hashCode ^
|
||||||
|
linkedRemoteAlbumId.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -75,6 +81,7 @@ updatedAt: $updatedAt,
|
|||||||
assetCount: $assetCount,
|
assetCount: $assetCount,
|
||||||
backupSelection: $backupSelection,
|
backupSelection: $backupSelection,
|
||||||
isIosSharedAlbum: $isIosSharedAlbum
|
isIosSharedAlbum: $isIosSharedAlbum
|
||||||
|
linkedRemoteAlbumId: $linkedRemoteAlbumId,
|
||||||
}''';
|
}''';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,36 @@
|
|||||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
enum AvatarColor {
|
||||||
|
// do not change this order or reuse indices for other purposes, adding is OK
|
||||||
|
primary("primary"),
|
||||||
|
pink("pink"),
|
||||||
|
red("red"),
|
||||||
|
yellow("yellow"),
|
||||||
|
blue("blue"),
|
||||||
|
green("green"),
|
||||||
|
purple("purple"),
|
||||||
|
orange("orange"),
|
||||||
|
gray("gray"),
|
||||||
|
amber("amber");
|
||||||
|
|
||||||
|
final String value;
|
||||||
|
const AvatarColor(this.value);
|
||||||
|
|
||||||
|
Color toColor({bool isDarkTheme = false}) => switch (this) {
|
||||||
|
AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
|
||||||
|
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
|
||||||
|
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
|
||||||
|
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
|
||||||
|
AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246),
|
||||||
|
AvatarColor.green => const Color.fromARGB(255, 22, 163, 74),
|
||||||
|
AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234),
|
||||||
|
AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12),
|
||||||
|
AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99),
|
||||||
|
AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Rename to User once Isar is removed
|
// TODO: Rename to User once Isar is removed
|
||||||
class UserDto {
|
class UserDto {
|
||||||
@@ -9,7 +38,7 @@ class UserDto {
|
|||||||
final String email;
|
final String email;
|
||||||
final String name;
|
final String name;
|
||||||
final bool isAdmin;
|
final bool isAdmin;
|
||||||
final DateTime updatedAt;
|
final DateTime? updatedAt;
|
||||||
|
|
||||||
final AvatarColor avatarColor;
|
final AvatarColor avatarColor;
|
||||||
|
|
||||||
@@ -31,8 +60,8 @@ class UserDto {
|
|||||||
required this.id,
|
required this.id,
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.isAdmin,
|
this.isAdmin = false,
|
||||||
required this.updatedAt,
|
this.updatedAt,
|
||||||
required this.profileChangedAt,
|
required this.profileChangedAt,
|
||||||
this.avatarColor = AvatarColor.primary,
|
this.avatarColor = AvatarColor.primary,
|
||||||
this.memoryEnabled = true,
|
this.memoryEnabled = true,
|
||||||
@@ -99,7 +128,8 @@ profileChangedAt: $profileChangedAt
|
|||||||
if (identical(this, other)) return true;
|
if (identical(this, other)) return true;
|
||||||
|
|
||||||
return other.id == id &&
|
return other.id == id &&
|
||||||
other.updatedAt.isAtSameMomentAs(updatedAt) &&
|
((updatedAt == null && other.updatedAt == null) ||
|
||||||
|
(updatedAt != null && other.updatedAt != null && other.updatedAt!.isAtSameMomentAs(updatedAt!))) &&
|
||||||
other.avatarColor == avatarColor &&
|
other.avatarColor == avatarColor &&
|
||||||
other.email == email &&
|
other.email == email &&
|
||||||
other.name == name &&
|
other.name == name &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'dart:ui';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
|
|
||||||
enum UserMetadataKey {
|
enum UserMetadataKey {
|
||||||
// do not change this order!
|
// do not change this order!
|
||||||
@@ -7,36 +7,6 @@ enum UserMetadataKey {
|
|||||||
license,
|
license,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AvatarColor {
|
|
||||||
// do not change this order or reuse indices for other purposes, adding is OK
|
|
||||||
primary("primary"),
|
|
||||||
pink("pink"),
|
|
||||||
red("red"),
|
|
||||||
yellow("yellow"),
|
|
||||||
blue("blue"),
|
|
||||||
green("green"),
|
|
||||||
purple("purple"),
|
|
||||||
orange("orange"),
|
|
||||||
gray("gray"),
|
|
||||||
amber("amber");
|
|
||||||
|
|
||||||
final String value;
|
|
||||||
const AvatarColor(this.value);
|
|
||||||
|
|
||||||
Color toColor({bool isDarkTheme = false}) => switch (this) {
|
|
||||||
AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
|
|
||||||
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
|
|
||||||
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
|
|
||||||
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
|
|
||||||
AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246),
|
|
||||||
AvatarColor.green => const Color.fromARGB(255, 22, 163, 74),
|
|
||||||
AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234),
|
|
||||||
AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12),
|
|
||||||
AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99),
|
|
||||||
AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class Onboarding {
|
class Onboarding {
|
||||||
final bool isOnboarded;
|
final bool isOnboarded;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:background_downloader/background_downloader.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
|
import 'package:immich_mobile/domain/utils/isolate_lock_manager.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.dart';
|
||||||
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
||||||
@@ -14,6 +15,7 @@ import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
|||||||
import 'package:immich_mobile/providers/db.provider.dart';
|
import 'package:immich_mobile/providers/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
import 'package:immich_mobile/repositories/file_media.repository.dart';
|
||||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:immich_mobile/services/auth.service.dart';
|
import 'package:immich_mobile/services/auth.service.dart';
|
||||||
import 'package:immich_mobile/services/localization.service.dart';
|
import 'package:immich_mobile/services/localization.service.dart';
|
||||||
@@ -29,13 +31,9 @@ class BackgroundWorkerFgService {
|
|||||||
const BackgroundWorkerFgService(this._foregroundHostApi);
|
const BackgroundWorkerFgService(this._foregroundHostApi);
|
||||||
|
|
||||||
// TODO: Move this call to native side once old timeline is removed
|
// TODO: Move this call to native side once old timeline is removed
|
||||||
Future<void> enableSyncService() => _foregroundHostApi.enableSyncWorker();
|
Future<void> enable() => _foregroundHostApi.enable();
|
||||||
|
|
||||||
Future<void> enableUploadService() => _foregroundHostApi.enableUploadWorker(
|
Future<void> disable() => _foregroundHostApi.disable();
|
||||||
PluginUtilities.getCallbackHandle(_backgroundSyncNativeEntrypoint)!.toRawHandle(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Future<void> disableUploadService() => _foregroundHostApi.disableUploadWorker();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||||
@@ -45,6 +43,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
final DriftLogger _driftLogger;
|
final DriftLogger _driftLogger;
|
||||||
final BackgroundWorkerBgHostApi _backgroundHostApi;
|
final BackgroundWorkerBgHostApi _backgroundHostApi;
|
||||||
final Logger _logger = Logger('BackgroundUploadBgService');
|
final Logger _logger = Logger('BackgroundUploadBgService');
|
||||||
|
late final IsolateLockManager _lockManager;
|
||||||
|
|
||||||
bool _isCleanedUp = false;
|
bool _isCleanedUp = false;
|
||||||
|
|
||||||
@@ -60,98 +59,106 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
driftProvider.overrideWith(driftOverride(drift)),
|
driftProvider.overrideWith(driftOverride(drift)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
_lockManager = IsolateLockManager(onCloseRequest: _cleanup);
|
||||||
BackgroundWorkerFlutterApi.setUp(this);
|
BackgroundWorkerFlutterApi.setUp(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get _isBackupEnabled => _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
bool get _isBackupEnabled => _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
await loadTranslations();
|
try {
|
||||||
HttpSSLOptions.apply(applyNative: false);
|
await loadTranslations();
|
||||||
await _ref.read(authServiceProvider).setOpenApiServiceEndpoint();
|
HttpSSLOptions.apply(applyNative: false);
|
||||||
|
await _ref.read(authServiceProvider).setOpenApiServiceEndpoint();
|
||||||
|
|
||||||
// Initialize the file downloader
|
// Initialize the file downloader
|
||||||
await FileDownloader().configure(
|
await FileDownloader().configure(
|
||||||
globalConfig: [
|
globalConfig: [
|
||||||
// maxConcurrent: 6, maxConcurrentByHost(server):6, maxConcurrentByGroup: 3
|
// maxConcurrent: 6, maxConcurrentByHost(server):6, maxConcurrentByGroup: 3
|
||||||
(Config.holdingQueue, (6, 6, 3)),
|
(Config.holdingQueue, (6, 6, 3)),
|
||||||
// On Android, if files are larger than 256MB, run in foreground service
|
// On Android, if files are larger than 256MB, run in foreground service
|
||||||
(Config.runInForegroundIfFileLargerThan, 256),
|
(Config.runInForegroundIfFileLargerThan, 256),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false);
|
await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false);
|
||||||
await FileDownloader().trackTasks();
|
await FileDownloader().trackTasks();
|
||||||
configureFileDownloaderNotifications();
|
configureFileDownloaderNotifications();
|
||||||
|
await _ref.read(fileMediaRepositoryProvider).enableBackgroundAccess();
|
||||||
|
|
||||||
// Notify the host that the background upload service has been initialized and is ready to use
|
// Notify the host that the background upload service has been initialized and is ready to use
|
||||||
await _backgroundHostApi.onInitialized();
|
debugPrint("Acquiring background worker lock");
|
||||||
|
if (await _lockManager.acquireLock().timeout(
|
||||||
|
const Duration(seconds: 5),
|
||||||
|
onTimeout: () {
|
||||||
|
_lockManager.cancel();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
)) {
|
||||||
|
_logger.info("Acquired background worker lock");
|
||||||
|
await _backgroundHostApi.onInitialized();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.warning("Failed to acquire background worker lock");
|
||||||
|
await _cleanup();
|
||||||
|
await _backgroundHostApi.close();
|
||||||
|
} catch (error, stack) {
|
||||||
|
_logger.severe("Failed to initialize background worker", error, stack);
|
||||||
|
_backgroundHostApi.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onLocalSync(int? maxSeconds) async {
|
|
||||||
_logger.info('Local background syncing started');
|
|
||||||
final sw = Stopwatch()..start();
|
|
||||||
|
|
||||||
final timeout = maxSeconds != null ? Duration(seconds: maxSeconds) : null;
|
|
||||||
await _syncAssets(hashTimeout: timeout, syncRemote: false);
|
|
||||||
|
|
||||||
sw.stop();
|
|
||||||
_logger.info("Local sync completed in ${sw.elapsed.inSeconds}s");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We do the following on Android upload
|
|
||||||
* - Sync local assets
|
|
||||||
* - Hash local assets 3 / 6 minutes
|
|
||||||
* - Sync remote assets
|
|
||||||
* - Check and requeue upload tasks
|
|
||||||
*/
|
|
||||||
@override
|
@override
|
||||||
Future<void> onAndroidUpload() async {
|
Future<void> onAndroidUpload() async {
|
||||||
_logger.info('Android background processing started');
|
try {
|
||||||
final sw = Stopwatch()..start();
|
_logger.info('Android background processing started');
|
||||||
|
final sw = Stopwatch()..start();
|
||||||
|
|
||||||
await _syncAssets(hashTimeout: Duration(minutes: _isBackupEnabled ? 3 : 6));
|
await _syncAssets(hashTimeout: Duration(minutes: _isBackupEnabled ? 3 : 6));
|
||||||
await _handleBackup(processBulk: false);
|
await _handleBackup(processBulk: false);
|
||||||
|
|
||||||
await _cleanup();
|
sw.stop();
|
||||||
|
_logger.info("Android background processing completed in ${sw.elapsed.inSeconds}s");
|
||||||
sw.stop();
|
} catch (error, stack) {
|
||||||
_logger.info("Android background processing completed in ${sw.elapsed.inSeconds}s");
|
_logger.severe("Failed to complete Android background processing", error, stack);
|
||||||
|
} finally {
|
||||||
|
await _cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We do the following on background upload
|
|
||||||
* - Sync local assets
|
|
||||||
* - Hash local assets
|
|
||||||
* - Sync remote assets
|
|
||||||
* - Check and requeue upload tasks
|
|
||||||
*
|
|
||||||
* The native side will not send the maxSeconds value for processing tasks
|
|
||||||
*/
|
|
||||||
@override
|
@override
|
||||||
Future<void> onIosUpload(bool isRefresh, int? maxSeconds) async {
|
Future<void> onIosUpload(bool isRefresh, int? maxSeconds) async {
|
||||||
_logger.info('iOS background upload started with maxSeconds: ${maxSeconds}s');
|
try {
|
||||||
final sw = Stopwatch()..start();
|
_logger.info('iOS background upload started with maxSeconds: ${maxSeconds}s');
|
||||||
|
final sw = Stopwatch()..start();
|
||||||
|
|
||||||
final timeout = isRefresh ? const Duration(seconds: 5) : Duration(minutes: _isBackupEnabled ? 3 : 6);
|
final timeout = isRefresh ? const Duration(seconds: 5) : Duration(minutes: _isBackupEnabled ? 3 : 6);
|
||||||
await _syncAssets(hashTimeout: timeout);
|
await _syncAssets(hashTimeout: timeout);
|
||||||
|
|
||||||
final backupFuture = _handleBackup();
|
final backupFuture = _handleBackup();
|
||||||
if (maxSeconds != null) {
|
if (maxSeconds != null) {
|
||||||
await backupFuture.timeout(Duration(seconds: maxSeconds - 1), onTimeout: () {});
|
await backupFuture.timeout(Duration(seconds: maxSeconds - 1), onTimeout: () {});
|
||||||
} else {
|
} else {
|
||||||
await backupFuture;
|
await backupFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.stop();
|
||||||
|
_logger.info("iOS background upload completed in ${sw.elapsed.inSeconds}s");
|
||||||
|
} catch (error, stack) {
|
||||||
|
_logger.severe("Failed to complete iOS background upload", error, stack);
|
||||||
|
} finally {
|
||||||
|
await _cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _cleanup();
|
|
||||||
|
|
||||||
sw.stop();
|
|
||||||
_logger.info("iOS background upload completed in ${sw.elapsed.inSeconds}s");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> cancel() async {
|
Future<void> cancel() async {
|
||||||
_logger.warning("Background upload cancelled");
|
_logger.warning("Background worker cancelled");
|
||||||
await _cleanup();
|
try {
|
||||||
|
await _cleanup();
|
||||||
|
} catch (error, stack) {
|
||||||
|
debugPrint('Failed to cleanup background worker: $error with stack: $stack');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _cleanup() async {
|
Future<void> _cleanup() async {
|
||||||
@@ -159,13 +166,27 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isCleanedUp = true;
|
try {
|
||||||
await _ref.read(backgroundSyncProvider).cancel();
|
_isCleanedUp = true;
|
||||||
await _ref.read(backgroundSyncProvider).cancelLocal();
|
_logger.info("Cleaning up background worker");
|
||||||
await _isar.close();
|
final cleanupFutures = [
|
||||||
await _drift.close();
|
_drift.close(),
|
||||||
await _driftLogger.close();
|
_driftLogger.close(),
|
||||||
_ref.dispose();
|
_ref.read(backgroundSyncProvider).cancel(),
|
||||||
|
_ref.read(backgroundSyncProvider).cancelLocal(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (_isar.isOpen) {
|
||||||
|
cleanupFutures.add(_isar.close());
|
||||||
|
}
|
||||||
|
_ref.dispose();
|
||||||
|
_lockManager.releaseLock();
|
||||||
|
|
||||||
|
await Future.wait(cleanupFutures);
|
||||||
|
_logger.info("Background worker resources cleaned up");
|
||||||
|
} catch (error, stack) {
|
||||||
|
debugPrint('Failed to cleanup background worker: $error with stack: $stack');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleBackup({bool processBulk = true}) async {
|
Future<void> _handleBackup({bool processBulk = true}) async {
|
||||||
@@ -190,7 +211,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _syncAssets({Duration? hashTimeout, bool syncRemote = true}) async {
|
Future<void> _syncAssets({Duration? hashTimeout}) async {
|
||||||
final futures = <Future<void>>[];
|
final futures = <Future<void>>[];
|
||||||
|
|
||||||
final localSyncFuture = _ref.read(backgroundSyncProvider).syncLocal().then((_) async {
|
final localSyncFuture = _ref.read(backgroundSyncProvider).syncLocal().then((_) async {
|
||||||
@@ -212,21 +233,20 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
});
|
});
|
||||||
|
|
||||||
futures.add(localSyncFuture);
|
futures.add(localSyncFuture);
|
||||||
if (syncRemote) {
|
futures.add(_ref.read(backgroundSyncProvider).syncRemote());
|
||||||
final remoteSyncFuture = _ref.read(backgroundSyncProvider).syncRemote();
|
|
||||||
futures.add(remoteSyncFuture);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Future.wait(futures);
|
await Future.wait(futures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Native entry invoked from the background worker. If renaming or moving this to a different
|
||||||
|
/// library, make sure to update the entry points and URI in native workers as well
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> _backgroundSyncNativeEntrypoint() async {
|
Future<void> backgroundSyncNativeEntrypoint() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
DartPluginRegistrant.ensureInitialized();
|
DartPluginRegistrant.ensureInitialized();
|
||||||
|
|
||||||
final (isar, drift, logDB) = await Bootstrap.initDB();
|
final (isar, drift, logDB) = await Bootstrap.initDB(shareAcrossIsolates: false);
|
||||||
await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false);
|
await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false);
|
||||||
await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init();
|
await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
@@ -35,6 +36,7 @@ class HashService {
|
|||||||
bool get isCancelled => _cancelChecker?.call() ?? false;
|
bool get isCancelled => _cancelChecker?.call() ?? false;
|
||||||
|
|
||||||
Future<void> hashAssets() async {
|
Future<void> hashAssets() async {
|
||||||
|
_log.info("Starting hashing of assets");
|
||||||
final Stopwatch stopwatch = Stopwatch()..start();
|
final Stopwatch stopwatch = Stopwatch()..start();
|
||||||
// Sorted by backupSelection followed by isCloud
|
// Sorted by backupSelection followed by isCloud
|
||||||
final localAlbums = await _localAlbumRepository.getAll(
|
final localAlbums = await _localAlbumRepository.getAll(
|
||||||
@@ -49,7 +51,7 @@ class HashService {
|
|||||||
|
|
||||||
final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id);
|
final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id);
|
||||||
if (assetsToHash.isNotEmpty) {
|
if (assetsToHash.isNotEmpty) {
|
||||||
await _hashAssets(assetsToHash);
|
await _hashAssets(album, assetsToHash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +62,7 @@ class HashService {
|
|||||||
/// Processes a list of [LocalAsset]s, storing their hash and updating the assets in the DB
|
/// Processes a list of [LocalAsset]s, storing their hash and updating the assets in the DB
|
||||||
/// with hash for those that were successfully hashed. Hashes are looked up in a table
|
/// with hash for those that were successfully hashed. Hashes are looked up in a table
|
||||||
/// [LocalAssetHashEntity] by local id. Only missing entries are newly hashed and added to the DB.
|
/// [LocalAssetHashEntity] by local id. Only missing entries are newly hashed and added to the DB.
|
||||||
Future<void> _hashAssets(List<LocalAsset> assetsToHash) async {
|
Future<void> _hashAssets(LocalAlbum album, List<LocalAsset> assetsToHash) async {
|
||||||
int bytesProcessed = 0;
|
int bytesProcessed = 0;
|
||||||
final toHash = <_AssetToPath>[];
|
final toHash = <_AssetToPath>[];
|
||||||
|
|
||||||
@@ -72,6 +74,9 @@ class HashService {
|
|||||||
|
|
||||||
final file = await _storageRepository.getFileForAsset(asset.id);
|
final file = await _storageRepository.getFileForAsset(asset.id);
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
|
_log.warning(
|
||||||
|
"Cannot get file for asset ${asset.id}, name: ${asset.name}, created on: ${asset.createdAt} from album: ${album.name}",
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,17 +84,17 @@ class HashService {
|
|||||||
toHash.add(_AssetToPath(asset: asset, path: file.path));
|
toHash.add(_AssetToPath(asset: asset, path: file.path));
|
||||||
|
|
||||||
if (toHash.length >= batchFileLimit || bytesProcessed >= batchSizeLimit) {
|
if (toHash.length >= batchFileLimit || bytesProcessed >= batchSizeLimit) {
|
||||||
await _processBatch(toHash);
|
await _processBatch(album, toHash);
|
||||||
toHash.clear();
|
toHash.clear();
|
||||||
bytesProcessed = 0;
|
bytesProcessed = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await _processBatch(toHash);
|
await _processBatch(album, toHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Processes a batch of assets.
|
/// Processes a batch of assets.
|
||||||
Future<void> _processBatch(List<_AssetToPath> toHash) async {
|
Future<void> _processBatch(LocalAlbum album, List<_AssetToPath> toHash) async {
|
||||||
if (toHash.isEmpty) {
|
if (toHash.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -114,7 +119,9 @@ class HashService {
|
|||||||
if (hash?.length == 20) {
|
if (hash?.length == 20) {
|
||||||
hashed.add(asset.copyWith(checksum: base64.encode(hash!)));
|
hashed.add(asset.copyWith(checksum: base64.encode(hash!)));
|
||||||
} else {
|
} else {
|
||||||
_log.warning("Failed to hash file for ${asset.id}: ${asset.name} created at ${asset.createdAt}");
|
_log.warning(
|
||||||
|
"Failed to hash file for ${asset.id}: ${asset.name} created at ${asset.createdAt} from album: ${album.name}",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,16 @@ class LocalAlbumService {
|
|||||||
Future<int> getCount() {
|
Future<int> getCount() {
|
||||||
return _repository.getCount();
|
return _repository.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> unlinkRemoteAlbum(String id) async {
|
||||||
|
return _repository.unlinkRemoteAlbum(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> linkRemoteAlbum(String localAlbumId, String remoteAlbumId) async {
|
||||||
|
return _repository.linkRemoteAlbum(localAlbumId, remoteAlbumId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<LocalAlbum>> getBackupAlbums() {
|
||||||
|
return _repository.getBackupAlbums();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
|||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
|
import 'package:immich_mobile/utils/datetime_helpers.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
@@ -285,7 +286,7 @@ extension on Iterable<PlatformAlbum> {
|
|||||||
(e) => LocalAlbum(
|
(e) => LocalAlbum(
|
||||||
id: e.id,
|
id: e.id,
|
||||||
name: e.name,
|
name: e.name,
|
||||||
updatedAt: e.updatedAt == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(e.updatedAt! * 1000),
|
updatedAt: tryFromSecondsSinceEpoch(e.updatedAt) ?? DateTime.now(),
|
||||||
assetCount: e.assetCount,
|
assetCount: e.assetCount,
|
||||||
),
|
),
|
||||||
).toList();
|
).toList();
|
||||||
@@ -300,8 +301,8 @@ extension on Iterable<PlatformAsset> {
|
|||||||
name: e.name,
|
name: e.name,
|
||||||
checksum: null,
|
checksum: null,
|
||||||
type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.other,
|
type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.other,
|
||||||
createdAt: e.createdAt == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(e.createdAt! * 1000),
|
createdAt: tryFromSecondsSinceEpoch(e.createdAt) ?? DateTime.now(),
|
||||||
updatedAt: e.updatedAt == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(e.updatedAt! * 1000),
|
updatedAt: tryFromSecondsSinceEpoch(e.updatedAt) ?? DateTime.now(),
|
||||||
width: e.width,
|
width: e.width,
|
||||||
height: e.height,
|
height: e.height,
|
||||||
durationInSeconds: e.durationInSeconds,
|
durationInSeconds: e.durationInSeconds,
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ class RemoteAlbumService {
|
|||||||
return _repository.get(albumId);
|
return _repository.get(albumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<RemoteAlbum?> getByName(String albumName, String ownerId) {
|
||||||
|
return _repository.getByName(albumName, ownerId);
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<RemoteAlbum>> sortAlbums(
|
Future<List<RemoteAlbum>> sortAlbums(
|
||||||
List<RemoteAlbum> albums,
|
List<RemoteAlbum> albums,
|
||||||
RemoteAlbumSortMode sortMode, {
|
RemoteAlbumSortMode sortMode, {
|
||||||
@@ -80,7 +84,6 @@ class RemoteAlbumService {
|
|||||||
|
|
||||||
Future<RemoteAlbum> createAlbum({required String title, required List<String> assetIds, String? description}) async {
|
Future<RemoteAlbum> createAlbum({required String title, required List<String> assetIds, String? description}) async {
|
||||||
final album = await _albumApiRepository.createDriftAlbum(title, description: description, assetIds: assetIds);
|
final album = await _albumApiRepository.createDriftAlbum(title, description: description, assetIds: assetIds);
|
||||||
|
|
||||||
await _repository.create(album, assetIds);
|
await _repository.create(album, assetIds);
|
||||||
|
|
||||||
return album;
|
return album;
|
||||||
|
|||||||
101
mobile/lib/domain/services/sync_linked_album.service.dart
Normal file
101
mobile/lib/domain/services/sync_linked_album.service.dart
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
|
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||||
|
|
||||||
|
final syncLinkedAlbumServiceProvider = Provider(
|
||||||
|
(ref) => SyncLinkedAlbumService(
|
||||||
|
ref.watch(localAlbumRepository),
|
||||||
|
ref.watch(remoteAlbumRepository),
|
||||||
|
ref.watch(driftAlbumApiRepositoryProvider),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
class SyncLinkedAlbumService {
|
||||||
|
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||||
|
final DriftRemoteAlbumRepository _remoteAlbumRepository;
|
||||||
|
final DriftAlbumApiRepository _albumApiRepository;
|
||||||
|
|
||||||
|
const SyncLinkedAlbumService(this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository);
|
||||||
|
|
||||||
|
Future<void> syncLinkedAlbums(String userId) async {
|
||||||
|
final selectedAlbums = await _localAlbumRepository.getBackupAlbums();
|
||||||
|
|
||||||
|
await Future.wait(
|
||||||
|
selectedAlbums.map((localAlbum) async {
|
||||||
|
final linkedRemoteAlbumId = localAlbum.linkedRemoteAlbumId;
|
||||||
|
if (linkedRemoteAlbumId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final remoteAlbum = await _remoteAlbumRepository.get(linkedRemoteAlbumId);
|
||||||
|
if (remoteAlbum == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get assets that are uploaded but not in the remote album
|
||||||
|
final assetIds = await _remoteAlbumRepository.getLinkedAssetIds(userId, localAlbum.id, linkedRemoteAlbumId);
|
||||||
|
|
||||||
|
if (assetIds.isNotEmpty) {
|
||||||
|
final album = await _albumApiRepository.addAssets(remoteAlbum.id, assetIds);
|
||||||
|
await _remoteAlbumRepository.addAssets(remoteAlbum.id, album.added);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> manageLinkedAlbums(List<LocalAlbum> localAlbums, String ownerId) async {
|
||||||
|
for (final album in localAlbums) {
|
||||||
|
await _processLocalAlbum(album, ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes a single local album to ensure proper linking with remote albums
|
||||||
|
Future<void> _processLocalAlbum(LocalAlbum localAlbum, String ownerId) {
|
||||||
|
final hasLinkedRemoteAlbum = localAlbum.linkedRemoteAlbumId != null;
|
||||||
|
|
||||||
|
if (hasLinkedRemoteAlbum) {
|
||||||
|
return _handleLinkedAlbum(localAlbum);
|
||||||
|
} else {
|
||||||
|
return _handleUnlinkedAlbum(localAlbum, ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles albums that are already linked to a remote album
|
||||||
|
Future<void> _handleLinkedAlbum(LocalAlbum localAlbum) async {
|
||||||
|
final remoteAlbumId = localAlbum.linkedRemoteAlbumId!;
|
||||||
|
final remoteAlbum = await _remoteAlbumRepository.get(remoteAlbumId);
|
||||||
|
|
||||||
|
final remoteAlbumExists = remoteAlbum != null;
|
||||||
|
if (!remoteAlbumExists) {
|
||||||
|
return _localAlbumRepository.unlinkRemoteAlbum(localAlbum.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles albums that are not linked to any remote album
|
||||||
|
Future<void> _handleUnlinkedAlbum(LocalAlbum localAlbum, String ownerId) async {
|
||||||
|
final existingRemoteAlbum = await _remoteAlbumRepository.getByName(localAlbum.name, ownerId);
|
||||||
|
|
||||||
|
if (existingRemoteAlbum != null) {
|
||||||
|
return _linkToExistingRemoteAlbum(localAlbum, existingRemoteAlbum);
|
||||||
|
} else {
|
||||||
|
return _createAndLinkNewRemoteAlbum(localAlbum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Links a local album to an existing remote album
|
||||||
|
Future<void> _linkToExistingRemoteAlbum(LocalAlbum localAlbum, dynamic existingRemoteAlbum) {
|
||||||
|
return _localAlbumRepository.linkRemoteAlbum(localAlbum.id, existingRemoteAlbum.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new remote album and links it to the local album
|
||||||
|
Future<void> _createAndLinkNewRemoteAlbum(LocalAlbum localAlbum) async {
|
||||||
|
debugPrint("Creating new remote album for local album: ${localAlbum.name}");
|
||||||
|
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(localAlbum.name, assetIds: []);
|
||||||
|
await _remoteAlbumRepository.create(newRemoteAlbum, []);
|
||||||
|
return _localAlbumRepository.linkRemoteAlbum(localAlbum.id, newRemoteAlbum.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,54 +23,17 @@ class SyncStreamService {
|
|||||||
|
|
||||||
bool get isCancelled => _cancelChecker?.call() ?? false;
|
bool get isCancelled => _cancelChecker?.call() ?? false;
|
||||||
|
|
||||||
Future<void> sync() {
|
Future<void> sync() async {
|
||||||
_logger.info("Remote sync request for user");
|
_logger.info("Remote sync request for user");
|
||||||
// Start the sync stream and handle events
|
// Start the sync stream and handle events
|
||||||
return _syncApiRepository.streamChanges(_handleEvents);
|
bool shouldReset = false;
|
||||||
}
|
await _syncApiRepository.streamChanges(_handleEvents, onReset: () => shouldReset = true);
|
||||||
|
if (shouldReset) {
|
||||||
Future<void> handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) async {
|
await _syncApiRepository.streamChanges(_handleEvents);
|
||||||
if (batchData.isEmpty) return;
|
|
||||||
|
|
||||||
_logger.info('Processing batch of ${batchData.length} AssetUploadReadyV1 events');
|
|
||||||
|
|
||||||
final List<SyncAssetV1> assets = [];
|
|
||||||
final List<SyncAssetExifV1> exifs = [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (final data in batchData) {
|
|
||||||
if (data is! Map<String, dynamic>) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final payload = data;
|
|
||||||
final assetData = payload['asset'];
|
|
||||||
final exifData = payload['exif'];
|
|
||||||
|
|
||||||
if (assetData == null || exifData == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final asset = SyncAssetV1.fromJson(assetData);
|
|
||||||
final exif = SyncAssetExifV1.fromJson(exifData);
|
|
||||||
|
|
||||||
if (asset != null && exif != null) {
|
|
||||||
assets.add(asset);
|
|
||||||
exifs.add(exif);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assets.isNotEmpty && exifs.isNotEmpty) {
|
|
||||||
await _syncStreamRepository.updateAssetsV1(assets, debugLabel: 'websocket-batch');
|
|
||||||
await _syncStreamRepository.updateAssetsExifV1(exifs, debugLabel: 'websocket-batch');
|
|
||||||
_logger.info('Successfully processed ${assets.length} assets in batch');
|
|
||||||
}
|
|
||||||
} catch (error, stackTrace) {
|
|
||||||
_logger.severe("Error processing AssetUploadReadyV1 websocket batch events", error, stackTrace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleEvents(List<SyncEvent> events, Function() abort) async {
|
Future<void> _handleEvents(List<SyncEvent> events, Function() abort, Function() reset) async {
|
||||||
List<SyncEvent> items = [];
|
List<SyncEvent> items = [];
|
||||||
for (final event in events) {
|
for (final event in events) {
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
@@ -83,6 +46,10 @@ class SyncStreamService {
|
|||||||
await _processBatch(items);
|
await _processBatch(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.type == SyncEntityType.syncResetV1) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
items.add(event);
|
items.add(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +70,8 @@ class SyncStreamService {
|
|||||||
Future<void> _handleSyncData(SyncEntityType type, Iterable<Object> data) async {
|
Future<void> _handleSyncData(SyncEntityType type, Iterable<Object> data) async {
|
||||||
_logger.fine("Processing sync data for $type of length ${data.length}");
|
_logger.fine("Processing sync data for $type of length ${data.length}");
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case SyncEntityType.authUserV1:
|
||||||
|
return _syncStreamRepository.updateAuthUsersV1(data.cast());
|
||||||
case SyncEntityType.userV1:
|
case SyncEntityType.userV1:
|
||||||
return _syncStreamRepository.updateUsersV1(data.cast());
|
return _syncStreamRepository.updateUsersV1(data.cast());
|
||||||
case SyncEntityType.userDeleteV1:
|
case SyncEntityType.userDeleteV1:
|
||||||
@@ -159,6 +128,12 @@ class SyncStreamService {
|
|||||||
// to acknowledge that the client has processed all the backfill events
|
// to acknowledge that the client has processed all the backfill events
|
||||||
case SyncEntityType.syncAckV1:
|
case SyncEntityType.syncAckV1:
|
||||||
return;
|
return;
|
||||||
|
// No-op. SyncCompleteV1 is used to signal the completion of the sync process
|
||||||
|
case SyncEntityType.syncCompleteV1:
|
||||||
|
return;
|
||||||
|
// Request to reset the client state. Clear everything related to remote entities
|
||||||
|
case SyncEntityType.syncResetV1:
|
||||||
|
return _syncStreamRepository.reset();
|
||||||
case SyncEntityType.memoryV1:
|
case SyncEntityType.memoryV1:
|
||||||
return _syncStreamRepository.updateMemoriesV1(data.cast());
|
return _syncStreamRepository.updateMemoriesV1(data.cast());
|
||||||
case SyncEntityType.memoryDeleteV1:
|
case SyncEntityType.memoryDeleteV1:
|
||||||
@@ -193,4 +168,45 @@ class SyncStreamService {
|
|||||||
_logger.warning("Unknown sync data type: $type");
|
_logger.warning("Unknown sync data type: $type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) async {
|
||||||
|
if (batchData.isEmpty) return;
|
||||||
|
|
||||||
|
_logger.info('Processing batch of ${batchData.length} AssetUploadReadyV1 events');
|
||||||
|
|
||||||
|
final List<SyncAssetV1> assets = [];
|
||||||
|
final List<SyncAssetExifV1> exifs = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (final data in batchData) {
|
||||||
|
if (data is! Map<String, dynamic>) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final payload = data;
|
||||||
|
final assetData = payload['asset'];
|
||||||
|
final exifData = payload['exif'];
|
||||||
|
|
||||||
|
if (assetData == null || exifData == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final asset = SyncAssetV1.fromJson(assetData);
|
||||||
|
final exif = SyncAssetExifV1.fromJson(exifData);
|
||||||
|
|
||||||
|
if (asset != null && exif != null) {
|
||||||
|
assets.add(asset);
|
||||||
|
exifs.add(exif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assets.isNotEmpty && exifs.isNotEmpty) {
|
||||||
|
await _syncStreamRepository.updateAssetsV1(assets, debugLabel: 'websocket-batch');
|
||||||
|
await _syncStreamRepository.updateAssetsExifV1(exifs, debugLabel: 'websocket-batch');
|
||||||
|
_logger.info('Successfully processed ${assets.length} assets in batch');
|
||||||
|
}
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
_logger.severe("Error processing AssetUploadReadyV1 websocket batch events", error, stackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:immich_mobile/domain/utils/sync_linked_album.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/sync.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/sync.provider.dart';
|
||||||
import 'package:immich_mobile/utils/isolate.dart';
|
import 'package:immich_mobile/utils/isolate.dart';
|
||||||
import 'package:worker_manager/worker_manager.dart';
|
import 'package:worker_manager/worker_manager.dart';
|
||||||
@@ -23,6 +24,7 @@ class BackgroundSyncManager {
|
|||||||
Cancelable<void>? _syncTask;
|
Cancelable<void>? _syncTask;
|
||||||
Cancelable<void>? _syncWebsocketTask;
|
Cancelable<void>? _syncWebsocketTask;
|
||||||
Cancelable<void>? _deviceAlbumSyncTask;
|
Cancelable<void>? _deviceAlbumSyncTask;
|
||||||
|
Cancelable<void>? _linkedAlbumSyncTask;
|
||||||
Cancelable<void>? _hashTask;
|
Cancelable<void>? _hashTask;
|
||||||
|
|
||||||
BackgroundSyncManager({
|
BackgroundSyncManager({
|
||||||
@@ -52,6 +54,12 @@ class BackgroundSyncManager {
|
|||||||
_syncWebsocketTask?.cancel();
|
_syncWebsocketTask?.cancel();
|
||||||
_syncWebsocketTask = null;
|
_syncWebsocketTask = null;
|
||||||
|
|
||||||
|
if (_linkedAlbumSyncTask != null) {
|
||||||
|
futures.add(_linkedAlbumSyncTask!.future);
|
||||||
|
}
|
||||||
|
_linkedAlbumSyncTask?.cancel();
|
||||||
|
_linkedAlbumSyncTask = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Future.wait(futures);
|
await Future.wait(futures);
|
||||||
} on CanceledError {
|
} on CanceledError {
|
||||||
@@ -155,6 +163,17 @@ class BackgroundSyncManager {
|
|||||||
_syncWebsocketTask = null;
|
_syncWebsocketTask = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> syncLinkedAlbum() {
|
||||||
|
if (_linkedAlbumSyncTask != null) {
|
||||||
|
return _linkedAlbumSyncTask!.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
_linkedAlbumSyncTask = runInIsolateGentle(computation: syncLinkedAlbumsIsolated);
|
||||||
|
return _linkedAlbumSyncTask!.whenComplete(() {
|
||||||
|
_linkedAlbumSyncTask = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cancelable<void> _handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) => runInIsolateGentle(
|
Cancelable<void> _handleWsAssetUploadReadyV1Batch(List<dynamic> batchData) => runInIsolateGentle(
|
||||||
|
|||||||
235
mobile/lib/domain/utils/isolate_lock_manager.dart
Normal file
235
mobile/lib/domain/utils/isolate_lock_manager.dart
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
import 'dart:isolate';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
const String kIsolateLockManagerPort = "immich://isolate_mutex";
|
||||||
|
|
||||||
|
enum _LockStatus { active, released }
|
||||||
|
|
||||||
|
class _IsolateRequest {
|
||||||
|
const _IsolateRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HeartbeatRequest extends _IsolateRequest {
|
||||||
|
// Port for the receiver to send replies back
|
||||||
|
final SendPort sendPort;
|
||||||
|
|
||||||
|
const _HeartbeatRequest(this.sendPort);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {'type': 'heartbeat', 'sendPort': sendPort};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CloseRequest extends _IsolateRequest {
|
||||||
|
const _CloseRequest();
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {'type': 'close'};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IsolateResponse {
|
||||||
|
const _IsolateResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HeartbeatResponse extends _IsolateResponse {
|
||||||
|
final _LockStatus status;
|
||||||
|
|
||||||
|
const _HeartbeatResponse(this.status);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {'type': 'heartbeat', 'status': status.index};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef OnCloseLockHolderRequest = void Function();
|
||||||
|
|
||||||
|
class IsolateLockManager {
|
||||||
|
final String _portName;
|
||||||
|
bool _hasLock = false;
|
||||||
|
ReceivePort? _receivePort;
|
||||||
|
final OnCloseLockHolderRequest? _onCloseRequest;
|
||||||
|
final Set<SendPort> _waitingIsolates = {};
|
||||||
|
// Token object - a new one is created for each acquisition attempt
|
||||||
|
Object? _currentAcquisitionToken;
|
||||||
|
|
||||||
|
IsolateLockManager({String? portName, OnCloseLockHolderRequest? onCloseRequest})
|
||||||
|
: _portName = portName ?? kIsolateLockManagerPort,
|
||||||
|
_onCloseRequest = onCloseRequest;
|
||||||
|
|
||||||
|
Future<bool> acquireLock() async {
|
||||||
|
if (_hasLock) {
|
||||||
|
Logger('BackgroundWorkerLockManager').warning("WARNING: [acquireLock] called more than once");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new token - this invalidates any previous attempt
|
||||||
|
final token = _currentAcquisitionToken = Object();
|
||||||
|
|
||||||
|
final ReceivePort rp = _receivePort = ReceivePort(_portName);
|
||||||
|
final SendPort sp = rp.sendPort;
|
||||||
|
|
||||||
|
while (!IsolateNameServer.registerPortWithName(sp, _portName)) {
|
||||||
|
// This attempt was superseded by a newer one in the same isolate
|
||||||
|
if (_currentAcquisitionToken != token) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _lockReleasedByHolder(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hasLock = true;
|
||||||
|
rp.listen(_onRequest);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _lockReleasedByHolder(Object token) async {
|
||||||
|
SendPort? holder = IsolateNameServer.lookupPortByName(_portName);
|
||||||
|
debugPrint("Found lock holder: $holder");
|
||||||
|
if (holder == null) {
|
||||||
|
// No holder, try and acquire lock
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ReceivePort tempRp = ReceivePort();
|
||||||
|
final SendPort tempSp = tempRp.sendPort;
|
||||||
|
final bs = tempRp.asBroadcastStream();
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
// Send a heartbeat request with the send port to receive reply from the holder
|
||||||
|
|
||||||
|
debugPrint("Sending heartbeat request to lock holder");
|
||||||
|
holder.send(_HeartbeatRequest(tempSp).toJson());
|
||||||
|
dynamic answer = await bs.first.timeout(const Duration(seconds: 3), onTimeout: () => null);
|
||||||
|
|
||||||
|
debugPrint("Received heartbeat response from lock holder: $answer");
|
||||||
|
// This attempt was superseded by a newer one in the same isolate
|
||||||
|
if (_currentAcquisitionToken != token) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (answer == null) {
|
||||||
|
// Holder failed, most likely killed without calling releaseLock
|
||||||
|
// Check if a different waiting isolate took the lock
|
||||||
|
if (holder == IsolateNameServer.lookupPortByName(_portName)) {
|
||||||
|
// No, remove the stale lock
|
||||||
|
IsolateNameServer.removePortNameMapping(_portName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown message type received for heartbeat request. Try again
|
||||||
|
_IsolateResponse? response = _parseResponse(answer);
|
||||||
|
if (response == null || response is! _HeartbeatResponse) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.status == _LockStatus.released) {
|
||||||
|
// Holder has released the lock
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the _LockStatus is active, we check again if the task completed
|
||||||
|
// by sending a released messaged again, if not, send a new heartbeat again
|
||||||
|
|
||||||
|
// Check if the holder completed its task after the heartbeat
|
||||||
|
answer = await bs.first.timeout(
|
||||||
|
const Duration(seconds: 3),
|
||||||
|
onTimeout: () => const _HeartbeatResponse(_LockStatus.active).toJson(),
|
||||||
|
);
|
||||||
|
|
||||||
|
response = _parseResponse(answer);
|
||||||
|
if (response is _HeartbeatResponse && response.status == _LockStatus.released) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Timeout or error
|
||||||
|
} finally {
|
||||||
|
tempRp.close();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_IsolateRequest? _parseRequest(dynamic msg) {
|
||||||
|
if (msg is! Map<String, dynamic>) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (msg['type']) {
|
||||||
|
'heartbeat' => _HeartbeatRequest(msg['sendPort']),
|
||||||
|
'close' => const _CloseRequest(),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_IsolateResponse? _parseResponse(dynamic msg) {
|
||||||
|
if (msg is! Map<String, dynamic>) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (msg['type']) {
|
||||||
|
'heartbeat' => _HeartbeatResponse(_LockStatus.values[msg['status']]),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executed in the isolate with the lock
|
||||||
|
void _onRequest(dynamic msg) {
|
||||||
|
final request = _parseRequest(msg);
|
||||||
|
if (request == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request is _HeartbeatRequest) {
|
||||||
|
// Add the send port to the list of waiting isolates
|
||||||
|
_waitingIsolates.add(request.sendPort);
|
||||||
|
request.sendPort.send(const _HeartbeatResponse(_LockStatus.active).toJson());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request is _CloseRequest) {
|
||||||
|
_onCloseRequest?.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseLock() {
|
||||||
|
if (_hasLock) {
|
||||||
|
IsolateNameServer.removePortNameMapping(_portName);
|
||||||
|
|
||||||
|
// Notify waiting isolates
|
||||||
|
for (final port in _waitingIsolates) {
|
||||||
|
port.send(const _HeartbeatResponse(_LockStatus.released).toJson());
|
||||||
|
}
|
||||||
|
_waitingIsolates.clear();
|
||||||
|
|
||||||
|
_hasLock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_receivePort?.close();
|
||||||
|
_receivePort = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancel() {
|
||||||
|
if (_hasLock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint("Cancelling ongoing acquire lock attempts");
|
||||||
|
// Create a new token to invalidate ongoing acquire lock attempts
|
||||||
|
_currentAcquisitionToken = Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
void requestHolderToClose() {
|
||||||
|
if (_hasLock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsolateNameServer.lookupPortByName(_portName)?.send(const _CloseRequest().toJson());
|
||||||
|
}
|
||||||
|
}
|
||||||
11
mobile/lib/domain/utils/sync_linked_album.dart
Normal file
11
mobile/lib/domain/utils/sync_linked_album.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
||||||
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
|
||||||
|
Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) {
|
||||||
|
final user = ref.read(currentUserProvider);
|
||||||
|
if (user == null) {
|
||||||
|
return Future.value();
|
||||||
|
}
|
||||||
|
return ref.read(syncLinkedAlbumServiceProvider).syncLinkedAlbums(user.id);
|
||||||
|
}
|
||||||
27
mobile/lib/infrastructure/entities/auth_user.entity.dart
Normal file
27
mobile/lib/infrastructure/entities/auth_user.entity.dart
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
|
class AuthUserEntity extends Table with DriftDefaultsMixin {
|
||||||
|
const AuthUserEntity();
|
||||||
|
|
||||||
|
TextColumn get id => text()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
TextColumn get email => text()();
|
||||||
|
BoolColumn get isAdmin => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
// Profile image
|
||||||
|
BoolColumn get hasProfileImage => boolean().withDefault(const Constant(false))();
|
||||||
|
DateTimeColumn get profileChangedAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
IntColumn get avatarColor => intEnum<AvatarColor>()();
|
||||||
|
|
||||||
|
// Quota
|
||||||
|
IntColumn get quotaSizeInBytes => integer().withDefault(const Constant(0))();
|
||||||
|
IntColumn get quotaUsageInBytes => integer().withDefault(const Constant(0))();
|
||||||
|
|
||||||
|
// Locked Folder
|
||||||
|
TextColumn get pinCode => text().nullable()();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column> get primaryKey => {id};
|
||||||
|
}
|
||||||
933
mobile/lib/infrastructure/entities/auth_user.entity.drift.dart
generated
Normal file
933
mobile/lib/infrastructure/entities/auth_user.entity.drift.dart
generated
Normal file
@@ -0,0 +1,933 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
import 'package:drift/drift.dart' as i0;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart'
|
||||||
|
as i1;
|
||||||
|
import 'package:immich_mobile/domain/models/user.model.dart' as i2;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.dart'
|
||||||
|
as i3;
|
||||||
|
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
|
||||||
|
|
||||||
|
typedef $$AuthUserEntityTableCreateCompanionBuilder =
|
||||||
|
i1.AuthUserEntityCompanion Function({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String email,
|
||||||
|
i0.Value<bool> isAdmin,
|
||||||
|
i0.Value<bool> hasProfileImage,
|
||||||
|
i0.Value<DateTime> profileChangedAt,
|
||||||
|
required i2.AvatarColor avatarColor,
|
||||||
|
i0.Value<int> quotaSizeInBytes,
|
||||||
|
i0.Value<int> quotaUsageInBytes,
|
||||||
|
i0.Value<String?> pinCode,
|
||||||
|
});
|
||||||
|
typedef $$AuthUserEntityTableUpdateCompanionBuilder =
|
||||||
|
i1.AuthUserEntityCompanion Function({
|
||||||
|
i0.Value<String> id,
|
||||||
|
i0.Value<String> name,
|
||||||
|
i0.Value<String> email,
|
||||||
|
i0.Value<bool> isAdmin,
|
||||||
|
i0.Value<bool> hasProfileImage,
|
||||||
|
i0.Value<DateTime> profileChangedAt,
|
||||||
|
i0.Value<i2.AvatarColor> avatarColor,
|
||||||
|
i0.Value<int> quotaSizeInBytes,
|
||||||
|
i0.Value<int> quotaUsageInBytes,
|
||||||
|
i0.Value<String?> pinCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
class $$AuthUserEntityTableFilterComposer
|
||||||
|
extends i0.Composer<i0.GeneratedDatabase, i1.$AuthUserEntityTable> {
|
||||||
|
$$AuthUserEntityTableFilterComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.ColumnFilters<String> get id => $composableBuilder(
|
||||||
|
column: $table.id,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get name => $composableBuilder(
|
||||||
|
column: $table.name,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get email => $composableBuilder(
|
||||||
|
column: $table.email,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<bool> get isAdmin => $composableBuilder(
|
||||||
|
column: $table.isAdmin,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<bool> get hasProfileImage => $composableBuilder(
|
||||||
|
column: $table.hasProfileImage,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<DateTime> get profileChangedAt => $composableBuilder(
|
||||||
|
column: $table.profileChangedAt,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnWithTypeConverterFilters<i2.AvatarColor, i2.AvatarColor, int>
|
||||||
|
get avatarColor => $composableBuilder(
|
||||||
|
column: $table.avatarColor,
|
||||||
|
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<int> get quotaSizeInBytes => $composableBuilder(
|
||||||
|
column: $table.quotaSizeInBytes,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<int> get quotaUsageInBytes => $composableBuilder(
|
||||||
|
column: $table.quotaUsageInBytes,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get pinCode => $composableBuilder(
|
||||||
|
column: $table.pinCode,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $$AuthUserEntityTableOrderingComposer
|
||||||
|
extends i0.Composer<i0.GeneratedDatabase, i1.$AuthUserEntityTable> {
|
||||||
|
$$AuthUserEntityTableOrderingComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.ColumnOrderings<String> get id => $composableBuilder(
|
||||||
|
column: $table.id,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get name => $composableBuilder(
|
||||||
|
column: $table.name,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get email => $composableBuilder(
|
||||||
|
column: $table.email,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<bool> get isAdmin => $composableBuilder(
|
||||||
|
column: $table.isAdmin,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<bool> get hasProfileImage => $composableBuilder(
|
||||||
|
column: $table.hasProfileImage,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<DateTime> get profileChangedAt => $composableBuilder(
|
||||||
|
column: $table.profileChangedAt,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<int> get avatarColor => $composableBuilder(
|
||||||
|
column: $table.avatarColor,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<int> get quotaSizeInBytes => $composableBuilder(
|
||||||
|
column: $table.quotaSizeInBytes,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<int> get quotaUsageInBytes => $composableBuilder(
|
||||||
|
column: $table.quotaUsageInBytes,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get pinCode => $composableBuilder(
|
||||||
|
column: $table.pinCode,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $$AuthUserEntityTableAnnotationComposer
|
||||||
|
extends i0.Composer<i0.GeneratedDatabase, i1.$AuthUserEntityTable> {
|
||||||
|
$$AuthUserEntityTableAnnotationComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.GeneratedColumn<String> get id =>
|
||||||
|
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get name =>
|
||||||
|
$composableBuilder(column: $table.name, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get email =>
|
||||||
|
$composableBuilder(column: $table.email, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<bool> get isAdmin =>
|
||||||
|
$composableBuilder(column: $table.isAdmin, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<bool> get hasProfileImage => $composableBuilder(
|
||||||
|
column: $table.hasProfileImage,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<DateTime> get profileChangedAt => $composableBuilder(
|
||||||
|
column: $table.profileChangedAt,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.GeneratedColumnWithTypeConverter<i2.AvatarColor, int> get avatarColor =>
|
||||||
|
$composableBuilder(
|
||||||
|
column: $table.avatarColor,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<int> get quotaSizeInBytes => $composableBuilder(
|
||||||
|
column: $table.quotaSizeInBytes,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<int> get quotaUsageInBytes => $composableBuilder(
|
||||||
|
column: $table.quotaUsageInBytes,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get pinCode =>
|
||||||
|
$composableBuilder(column: $table.pinCode, builder: (column) => column);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $$AuthUserEntityTableTableManager
|
||||||
|
extends
|
||||||
|
i0.RootTableManager<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$AuthUserEntityTable,
|
||||||
|
i1.AuthUserEntityData,
|
||||||
|
i1.$$AuthUserEntityTableFilterComposer,
|
||||||
|
i1.$$AuthUserEntityTableOrderingComposer,
|
||||||
|
i1.$$AuthUserEntityTableAnnotationComposer,
|
||||||
|
$$AuthUserEntityTableCreateCompanionBuilder,
|
||||||
|
$$AuthUserEntityTableUpdateCompanionBuilder,
|
||||||
|
(
|
||||||
|
i1.AuthUserEntityData,
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$AuthUserEntityTable,
|
||||||
|
i1.AuthUserEntityData
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
i1.AuthUserEntityData,
|
||||||
|
i0.PrefetchHooks Function()
|
||||||
|
> {
|
||||||
|
$$AuthUserEntityTableTableManager(
|
||||||
|
i0.GeneratedDatabase db,
|
||||||
|
i1.$AuthUserEntityTable table,
|
||||||
|
) : super(
|
||||||
|
i0.TableManagerState(
|
||||||
|
db: db,
|
||||||
|
table: table,
|
||||||
|
createFilteringComposer: () =>
|
||||||
|
i1.$$AuthUserEntityTableFilterComposer($db: db, $table: table),
|
||||||
|
createOrderingComposer: () =>
|
||||||
|
i1.$$AuthUserEntityTableOrderingComposer($db: db, $table: table),
|
||||||
|
createComputedFieldComposer: () => i1
|
||||||
|
.$$AuthUserEntityTableAnnotationComposer($db: db, $table: table),
|
||||||
|
updateCompanionCallback:
|
||||||
|
({
|
||||||
|
i0.Value<String> id = const i0.Value.absent(),
|
||||||
|
i0.Value<String> name = const i0.Value.absent(),
|
||||||
|
i0.Value<String> email = const i0.Value.absent(),
|
||||||
|
i0.Value<bool> isAdmin = const i0.Value.absent(),
|
||||||
|
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
||||||
|
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
||||||
|
i0.Value<i2.AvatarColor> avatarColor = const i0.Value.absent(),
|
||||||
|
i0.Value<int> quotaSizeInBytes = const i0.Value.absent(),
|
||||||
|
i0.Value<int> quotaUsageInBytes = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> pinCode = const i0.Value.absent(),
|
||||||
|
}) => i1.AuthUserEntityCompanion(
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
email: email,
|
||||||
|
isAdmin: isAdmin,
|
||||||
|
hasProfileImage: hasProfileImage,
|
||||||
|
profileChangedAt: profileChangedAt,
|
||||||
|
avatarColor: avatarColor,
|
||||||
|
quotaSizeInBytes: quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes: quotaUsageInBytes,
|
||||||
|
pinCode: pinCode,
|
||||||
|
),
|
||||||
|
createCompanionCallback:
|
||||||
|
({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String email,
|
||||||
|
i0.Value<bool> isAdmin = const i0.Value.absent(),
|
||||||
|
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
||||||
|
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
||||||
|
required i2.AvatarColor avatarColor,
|
||||||
|
i0.Value<int> quotaSizeInBytes = const i0.Value.absent(),
|
||||||
|
i0.Value<int> quotaUsageInBytes = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> pinCode = const i0.Value.absent(),
|
||||||
|
}) => i1.AuthUserEntityCompanion.insert(
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
email: email,
|
||||||
|
isAdmin: isAdmin,
|
||||||
|
hasProfileImage: hasProfileImage,
|
||||||
|
profileChangedAt: profileChangedAt,
|
||||||
|
avatarColor: avatarColor,
|
||||||
|
quotaSizeInBytes: quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes: quotaUsageInBytes,
|
||||||
|
pinCode: pinCode,
|
||||||
|
),
|
||||||
|
withReferenceMapper: (p0) => p0
|
||||||
|
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
||||||
|
.toList(),
|
||||||
|
prefetchHooksCallback: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef $$AuthUserEntityTableProcessedTableManager =
|
||||||
|
i0.ProcessedTableManager<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$AuthUserEntityTable,
|
||||||
|
i1.AuthUserEntityData,
|
||||||
|
i1.$$AuthUserEntityTableFilterComposer,
|
||||||
|
i1.$$AuthUserEntityTableOrderingComposer,
|
||||||
|
i1.$$AuthUserEntityTableAnnotationComposer,
|
||||||
|
$$AuthUserEntityTableCreateCompanionBuilder,
|
||||||
|
$$AuthUserEntityTableUpdateCompanionBuilder,
|
||||||
|
(
|
||||||
|
i1.AuthUserEntityData,
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$AuthUserEntityTable,
|
||||||
|
i1.AuthUserEntityData
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
i1.AuthUserEntityData,
|
||||||
|
i0.PrefetchHooks Function()
|
||||||
|
>;
|
||||||
|
|
||||||
|
class $AuthUserEntityTable extends i3.AuthUserEntity
|
||||||
|
with i0.TableInfo<$AuthUserEntityTable, i1.AuthUserEntityData> {
|
||||||
|
@override
|
||||||
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
|
final String? _alias;
|
||||||
|
$AuthUserEntityTable(this.attachedDatabase, [this._alias]);
|
||||||
|
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
|
||||||
|
'id',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _nameMeta = const i0.VerificationMeta(
|
||||||
|
'name',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
|
||||||
|
'name',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _emailMeta = const i0.VerificationMeta(
|
||||||
|
'email',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> email = i0.GeneratedColumn<String>(
|
||||||
|
'email',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _isAdminMeta = const i0.VerificationMeta(
|
||||||
|
'isAdmin',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<bool> isAdmin = i0.GeneratedColumn<bool>(
|
||||||
|
'is_admin',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||||
|
'CHECK ("is_admin" IN (0, 1))',
|
||||||
|
),
|
||||||
|
defaultValue: const i4.Constant(false),
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _hasProfileImageMeta =
|
||||||
|
const i0.VerificationMeta('hasProfileImage');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<bool> hasProfileImage =
|
||||||
|
i0.GeneratedColumn<bool>(
|
||||||
|
'has_profile_image',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||||
|
'CHECK ("has_profile_image" IN (0, 1))',
|
||||||
|
),
|
||||||
|
defaultValue: const i4.Constant(false),
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _profileChangedAtMeta =
|
||||||
|
const i0.VerificationMeta('profileChangedAt');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<DateTime> profileChangedAt =
|
||||||
|
i0.GeneratedColumn<DateTime>(
|
||||||
|
'profile_changed_at',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.dateTime,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: i4.currentDateAndTime,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumnWithTypeConverter<i2.AvatarColor, int>
|
||||||
|
avatarColor =
|
||||||
|
i0.GeneratedColumn<int>(
|
||||||
|
'avatar_color',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
).withConverter<i2.AvatarColor>(
|
||||||
|
i1.$AuthUserEntityTable.$converteravatarColor,
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _quotaSizeInBytesMeta =
|
||||||
|
const i0.VerificationMeta('quotaSizeInBytes');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<int> quotaSizeInBytes = i0.GeneratedColumn<int>(
|
||||||
|
'quota_size_in_bytes',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const i4.Constant(0),
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _quotaUsageInBytesMeta =
|
||||||
|
const i0.VerificationMeta('quotaUsageInBytes');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<int> quotaUsageInBytes =
|
||||||
|
i0.GeneratedColumn<int>(
|
||||||
|
'quota_usage_in_bytes',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const i4.Constant(0),
|
||||||
|
);
|
||||||
|
static const i0.VerificationMeta _pinCodeMeta = const i0.VerificationMeta(
|
||||||
|
'pinCode',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> pinCode = i0.GeneratedColumn<String>(
|
||||||
|
'pin_code',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
List<i0.GeneratedColumn> get $columns => [
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
isAdmin,
|
||||||
|
hasProfileImage,
|
||||||
|
profileChangedAt,
|
||||||
|
avatarColor,
|
||||||
|
quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes,
|
||||||
|
pinCode,
|
||||||
|
];
|
||||||
|
@override
|
||||||
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
|
@override
|
||||||
|
String get actualTableName => $name;
|
||||||
|
static const String $name = 'auth_user_entity';
|
||||||
|
@override
|
||||||
|
i0.VerificationContext validateIntegrity(
|
||||||
|
i0.Insertable<i1.AuthUserEntityData> instance, {
|
||||||
|
bool isInserting = false,
|
||||||
|
}) {
|
||||||
|
final context = i0.VerificationContext();
|
||||||
|
final data = instance.toColumns(true);
|
||||||
|
if (data.containsKey('id')) {
|
||||||
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_idMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('name')) {
|
||||||
|
context.handle(
|
||||||
|
_nameMeta,
|
||||||
|
name.isAcceptableOrUnknown(data['name']!, _nameMeta),
|
||||||
|
);
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_nameMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('email')) {
|
||||||
|
context.handle(
|
||||||
|
_emailMeta,
|
||||||
|
email.isAcceptableOrUnknown(data['email']!, _emailMeta),
|
||||||
|
);
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_emailMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('is_admin')) {
|
||||||
|
context.handle(
|
||||||
|
_isAdminMeta,
|
||||||
|
isAdmin.isAcceptableOrUnknown(data['is_admin']!, _isAdminMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('has_profile_image')) {
|
||||||
|
context.handle(
|
||||||
|
_hasProfileImageMeta,
|
||||||
|
hasProfileImage.isAcceptableOrUnknown(
|
||||||
|
data['has_profile_image']!,
|
||||||
|
_hasProfileImageMeta,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('profile_changed_at')) {
|
||||||
|
context.handle(
|
||||||
|
_profileChangedAtMeta,
|
||||||
|
profileChangedAt.isAcceptableOrUnknown(
|
||||||
|
data['profile_changed_at']!,
|
||||||
|
_profileChangedAtMeta,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('quota_size_in_bytes')) {
|
||||||
|
context.handle(
|
||||||
|
_quotaSizeInBytesMeta,
|
||||||
|
quotaSizeInBytes.isAcceptableOrUnknown(
|
||||||
|
data['quota_size_in_bytes']!,
|
||||||
|
_quotaSizeInBytesMeta,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('quota_usage_in_bytes')) {
|
||||||
|
context.handle(
|
||||||
|
_quotaUsageInBytesMeta,
|
||||||
|
quotaUsageInBytes.isAcceptableOrUnknown(
|
||||||
|
data['quota_usage_in_bytes']!,
|
||||||
|
_quotaUsageInBytesMeta,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (data.containsKey('pin_code')) {
|
||||||
|
context.handle(
|
||||||
|
_pinCodeMeta,
|
||||||
|
pinCode.isAcceptableOrUnknown(data['pin_code']!, _pinCodeMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
||||||
|
@override
|
||||||
|
i1.AuthUserEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
|
return i1.AuthUserEntityData(
|
||||||
|
id: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}id'],
|
||||||
|
)!,
|
||||||
|
name: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}name'],
|
||||||
|
)!,
|
||||||
|
email: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}email'],
|
||||||
|
)!,
|
||||||
|
isAdmin: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.bool,
|
||||||
|
data['${effectivePrefix}is_admin'],
|
||||||
|
)!,
|
||||||
|
hasProfileImage: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.bool,
|
||||||
|
data['${effectivePrefix}has_profile_image'],
|
||||||
|
)!,
|
||||||
|
profileChangedAt: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.dateTime,
|
||||||
|
data['${effectivePrefix}profile_changed_at'],
|
||||||
|
)!,
|
||||||
|
avatarColor: i1.$AuthUserEntityTable.$converteravatarColor.fromSql(
|
||||||
|
attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}avatar_color'],
|
||||||
|
)!,
|
||||||
|
),
|
||||||
|
quotaSizeInBytes: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}quota_size_in_bytes'],
|
||||||
|
)!,
|
||||||
|
quotaUsageInBytes: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}quota_usage_in_bytes'],
|
||||||
|
)!,
|
||||||
|
pinCode: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}pin_code'],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
$AuthUserEntityTable createAlias(String alias) {
|
||||||
|
return $AuthUserEntityTable(attachedDatabase, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
static i0.JsonTypeConverter2<i2.AvatarColor, int, int> $converteravatarColor =
|
||||||
|
const i0.EnumIndexConverter<i2.AvatarColor>(i2.AvatarColor.values);
|
||||||
|
@override
|
||||||
|
bool get withoutRowId => true;
|
||||||
|
@override
|
||||||
|
bool get isStrict => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthUserEntityData extends i0.DataClass
|
||||||
|
implements i0.Insertable<i1.AuthUserEntityData> {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
final String email;
|
||||||
|
final bool isAdmin;
|
||||||
|
final bool hasProfileImage;
|
||||||
|
final DateTime profileChangedAt;
|
||||||
|
final i2.AvatarColor avatarColor;
|
||||||
|
final int quotaSizeInBytes;
|
||||||
|
final int quotaUsageInBytes;
|
||||||
|
final String? pinCode;
|
||||||
|
const AuthUserEntityData({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.email,
|
||||||
|
required this.isAdmin,
|
||||||
|
required this.hasProfileImage,
|
||||||
|
required this.profileChangedAt,
|
||||||
|
required this.avatarColor,
|
||||||
|
required this.quotaSizeInBytes,
|
||||||
|
required this.quotaUsageInBytes,
|
||||||
|
this.pinCode,
|
||||||
|
});
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
map['id'] = i0.Variable<String>(id);
|
||||||
|
map['name'] = i0.Variable<String>(name);
|
||||||
|
map['email'] = i0.Variable<String>(email);
|
||||||
|
map['is_admin'] = i0.Variable<bool>(isAdmin);
|
||||||
|
map['has_profile_image'] = i0.Variable<bool>(hasProfileImage);
|
||||||
|
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt);
|
||||||
|
{
|
||||||
|
map['avatar_color'] = i0.Variable<int>(
|
||||||
|
i1.$AuthUserEntityTable.$converteravatarColor.toSql(avatarColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
map['quota_size_in_bytes'] = i0.Variable<int>(quotaSizeInBytes);
|
||||||
|
map['quota_usage_in_bytes'] = i0.Variable<int>(quotaUsageInBytes);
|
||||||
|
if (!nullToAbsent || pinCode != null) {
|
||||||
|
map['pin_code'] = i0.Variable<String>(pinCode);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory AuthUserEntityData.fromJson(
|
||||||
|
Map<String, dynamic> json, {
|
||||||
|
i0.ValueSerializer? serializer,
|
||||||
|
}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return AuthUserEntityData(
|
||||||
|
id: serializer.fromJson<String>(json['id']),
|
||||||
|
name: serializer.fromJson<String>(json['name']),
|
||||||
|
email: serializer.fromJson<String>(json['email']),
|
||||||
|
isAdmin: serializer.fromJson<bool>(json['isAdmin']),
|
||||||
|
hasProfileImage: serializer.fromJson<bool>(json['hasProfileImage']),
|
||||||
|
profileChangedAt: serializer.fromJson<DateTime>(json['profileChangedAt']),
|
||||||
|
avatarColor: i1.$AuthUserEntityTable.$converteravatarColor.fromJson(
|
||||||
|
serializer.fromJson<int>(json['avatarColor']),
|
||||||
|
),
|
||||||
|
quotaSizeInBytes: serializer.fromJson<int>(json['quotaSizeInBytes']),
|
||||||
|
quotaUsageInBytes: serializer.fromJson<int>(json['quotaUsageInBytes']),
|
||||||
|
pinCode: serializer.fromJson<String?>(json['pinCode']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'id': serializer.toJson<String>(id),
|
||||||
|
'name': serializer.toJson<String>(name),
|
||||||
|
'email': serializer.toJson<String>(email),
|
||||||
|
'isAdmin': serializer.toJson<bool>(isAdmin),
|
||||||
|
'hasProfileImage': serializer.toJson<bool>(hasProfileImage),
|
||||||
|
'profileChangedAt': serializer.toJson<DateTime>(profileChangedAt),
|
||||||
|
'avatarColor': serializer.toJson<int>(
|
||||||
|
i1.$AuthUserEntityTable.$converteravatarColor.toJson(avatarColor),
|
||||||
|
),
|
||||||
|
'quotaSizeInBytes': serializer.toJson<int>(quotaSizeInBytes),
|
||||||
|
'quotaUsageInBytes': serializer.toJson<int>(quotaUsageInBytes),
|
||||||
|
'pinCode': serializer.toJson<String?>(pinCode),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.AuthUserEntityData copyWith({
|
||||||
|
String? id,
|
||||||
|
String? name,
|
||||||
|
String? email,
|
||||||
|
bool? isAdmin,
|
||||||
|
bool? hasProfileImage,
|
||||||
|
DateTime? profileChangedAt,
|
||||||
|
i2.AvatarColor? avatarColor,
|
||||||
|
int? quotaSizeInBytes,
|
||||||
|
int? quotaUsageInBytes,
|
||||||
|
i0.Value<String?> pinCode = const i0.Value.absent(),
|
||||||
|
}) => i1.AuthUserEntityData(
|
||||||
|
id: id ?? this.id,
|
||||||
|
name: name ?? this.name,
|
||||||
|
email: email ?? this.email,
|
||||||
|
isAdmin: isAdmin ?? this.isAdmin,
|
||||||
|
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||||
|
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||||
|
avatarColor: avatarColor ?? this.avatarColor,
|
||||||
|
quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
|
||||||
|
pinCode: pinCode.present ? pinCode.value : this.pinCode,
|
||||||
|
);
|
||||||
|
AuthUserEntityData copyWithCompanion(i1.AuthUserEntityCompanion data) {
|
||||||
|
return AuthUserEntityData(
|
||||||
|
id: data.id.present ? data.id.value : this.id,
|
||||||
|
name: data.name.present ? data.name.value : this.name,
|
||||||
|
email: data.email.present ? data.email.value : this.email,
|
||||||
|
isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin,
|
||||||
|
hasProfileImage: data.hasProfileImage.present
|
||||||
|
? data.hasProfileImage.value
|
||||||
|
: this.hasProfileImage,
|
||||||
|
profileChangedAt: data.profileChangedAt.present
|
||||||
|
? data.profileChangedAt.value
|
||||||
|
: this.profileChangedAt,
|
||||||
|
avatarColor: data.avatarColor.present
|
||||||
|
? data.avatarColor.value
|
||||||
|
: this.avatarColor,
|
||||||
|
quotaSizeInBytes: data.quotaSizeInBytes.present
|
||||||
|
? data.quotaSizeInBytes.value
|
||||||
|
: this.quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes: data.quotaUsageInBytes.present
|
||||||
|
? data.quotaUsageInBytes.value
|
||||||
|
: this.quotaUsageInBytes,
|
||||||
|
pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('AuthUserEntityData(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('email: $email, ')
|
||||||
|
..write('isAdmin: $isAdmin, ')
|
||||||
|
..write('hasProfileImage: $hasProfileImage, ')
|
||||||
|
..write('profileChangedAt: $profileChangedAt, ')
|
||||||
|
..write('avatarColor: $avatarColor, ')
|
||||||
|
..write('quotaSizeInBytes: $quotaSizeInBytes, ')
|
||||||
|
..write('quotaUsageInBytes: $quotaUsageInBytes, ')
|
||||||
|
..write('pinCode: $pinCode')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
isAdmin,
|
||||||
|
hasProfileImage,
|
||||||
|
profileChangedAt,
|
||||||
|
avatarColor,
|
||||||
|
quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes,
|
||||||
|
pinCode,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is i1.AuthUserEntityData &&
|
||||||
|
other.id == this.id &&
|
||||||
|
other.name == this.name &&
|
||||||
|
other.email == this.email &&
|
||||||
|
other.isAdmin == this.isAdmin &&
|
||||||
|
other.hasProfileImage == this.hasProfileImage &&
|
||||||
|
other.profileChangedAt == this.profileChangedAt &&
|
||||||
|
other.avatarColor == this.avatarColor &&
|
||||||
|
other.quotaSizeInBytes == this.quotaSizeInBytes &&
|
||||||
|
other.quotaUsageInBytes == this.quotaUsageInBytes &&
|
||||||
|
other.pinCode == this.pinCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthUserEntityCompanion
|
||||||
|
extends i0.UpdateCompanion<i1.AuthUserEntityData> {
|
||||||
|
final i0.Value<String> id;
|
||||||
|
final i0.Value<String> name;
|
||||||
|
final i0.Value<String> email;
|
||||||
|
final i0.Value<bool> isAdmin;
|
||||||
|
final i0.Value<bool> hasProfileImage;
|
||||||
|
final i0.Value<DateTime> profileChangedAt;
|
||||||
|
final i0.Value<i2.AvatarColor> avatarColor;
|
||||||
|
final i0.Value<int> quotaSizeInBytes;
|
||||||
|
final i0.Value<int> quotaUsageInBytes;
|
||||||
|
final i0.Value<String?> pinCode;
|
||||||
|
const AuthUserEntityCompanion({
|
||||||
|
this.id = const i0.Value.absent(),
|
||||||
|
this.name = const i0.Value.absent(),
|
||||||
|
this.email = const i0.Value.absent(),
|
||||||
|
this.isAdmin = const i0.Value.absent(),
|
||||||
|
this.hasProfileImage = const i0.Value.absent(),
|
||||||
|
this.profileChangedAt = const i0.Value.absent(),
|
||||||
|
this.avatarColor = const i0.Value.absent(),
|
||||||
|
this.quotaSizeInBytes = const i0.Value.absent(),
|
||||||
|
this.quotaUsageInBytes = const i0.Value.absent(),
|
||||||
|
this.pinCode = const i0.Value.absent(),
|
||||||
|
});
|
||||||
|
AuthUserEntityCompanion.insert({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
required String email,
|
||||||
|
this.isAdmin = const i0.Value.absent(),
|
||||||
|
this.hasProfileImage = const i0.Value.absent(),
|
||||||
|
this.profileChangedAt = const i0.Value.absent(),
|
||||||
|
required i2.AvatarColor avatarColor,
|
||||||
|
this.quotaSizeInBytes = const i0.Value.absent(),
|
||||||
|
this.quotaUsageInBytes = const i0.Value.absent(),
|
||||||
|
this.pinCode = const i0.Value.absent(),
|
||||||
|
}) : id = i0.Value(id),
|
||||||
|
name = i0.Value(name),
|
||||||
|
email = i0.Value(email),
|
||||||
|
avatarColor = i0.Value(avatarColor);
|
||||||
|
static i0.Insertable<i1.AuthUserEntityData> custom({
|
||||||
|
i0.Expression<String>? id,
|
||||||
|
i0.Expression<String>? name,
|
||||||
|
i0.Expression<String>? email,
|
||||||
|
i0.Expression<bool>? isAdmin,
|
||||||
|
i0.Expression<bool>? hasProfileImage,
|
||||||
|
i0.Expression<DateTime>? profileChangedAt,
|
||||||
|
i0.Expression<int>? avatarColor,
|
||||||
|
i0.Expression<int>? quotaSizeInBytes,
|
||||||
|
i0.Expression<int>? quotaUsageInBytes,
|
||||||
|
i0.Expression<String>? pinCode,
|
||||||
|
}) {
|
||||||
|
return i0.RawValuesInsertable({
|
||||||
|
if (id != null) 'id': id,
|
||||||
|
if (name != null) 'name': name,
|
||||||
|
if (email != null) 'email': email,
|
||||||
|
if (isAdmin != null) 'is_admin': isAdmin,
|
||||||
|
if (hasProfileImage != null) 'has_profile_image': hasProfileImage,
|
||||||
|
if (profileChangedAt != null) 'profile_changed_at': profileChangedAt,
|
||||||
|
if (avatarColor != null) 'avatar_color': avatarColor,
|
||||||
|
if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes,
|
||||||
|
if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes,
|
||||||
|
if (pinCode != null) 'pin_code': pinCode,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.AuthUserEntityCompanion copyWith({
|
||||||
|
i0.Value<String>? id,
|
||||||
|
i0.Value<String>? name,
|
||||||
|
i0.Value<String>? email,
|
||||||
|
i0.Value<bool>? isAdmin,
|
||||||
|
i0.Value<bool>? hasProfileImage,
|
||||||
|
i0.Value<DateTime>? profileChangedAt,
|
||||||
|
i0.Value<i2.AvatarColor>? avatarColor,
|
||||||
|
i0.Value<int>? quotaSizeInBytes,
|
||||||
|
i0.Value<int>? quotaUsageInBytes,
|
||||||
|
i0.Value<String?>? pinCode,
|
||||||
|
}) {
|
||||||
|
return i1.AuthUserEntityCompanion(
|
||||||
|
id: id ?? this.id,
|
||||||
|
name: name ?? this.name,
|
||||||
|
email: email ?? this.email,
|
||||||
|
isAdmin: isAdmin ?? this.isAdmin,
|
||||||
|
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||||
|
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||||
|
avatarColor: avatarColor ?? this.avatarColor,
|
||||||
|
quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
|
||||||
|
pinCode: pinCode ?? this.pinCode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
if (id.present) {
|
||||||
|
map['id'] = i0.Variable<String>(id.value);
|
||||||
|
}
|
||||||
|
if (name.present) {
|
||||||
|
map['name'] = i0.Variable<String>(name.value);
|
||||||
|
}
|
||||||
|
if (email.present) {
|
||||||
|
map['email'] = i0.Variable<String>(email.value);
|
||||||
|
}
|
||||||
|
if (isAdmin.present) {
|
||||||
|
map['is_admin'] = i0.Variable<bool>(isAdmin.value);
|
||||||
|
}
|
||||||
|
if (hasProfileImage.present) {
|
||||||
|
map['has_profile_image'] = i0.Variable<bool>(hasProfileImage.value);
|
||||||
|
}
|
||||||
|
if (profileChangedAt.present) {
|
||||||
|
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt.value);
|
||||||
|
}
|
||||||
|
if (avatarColor.present) {
|
||||||
|
map['avatar_color'] = i0.Variable<int>(
|
||||||
|
i1.$AuthUserEntityTable.$converteravatarColor.toSql(avatarColor.value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (quotaSizeInBytes.present) {
|
||||||
|
map['quota_size_in_bytes'] = i0.Variable<int>(quotaSizeInBytes.value);
|
||||||
|
}
|
||||||
|
if (quotaUsageInBytes.present) {
|
||||||
|
map['quota_usage_in_bytes'] = i0.Variable<int>(quotaUsageInBytes.value);
|
||||||
|
}
|
||||||
|
if (pinCode.present) {
|
||||||
|
map['pin_code'] = i0.Variable<String>(pinCode.value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('AuthUserEntityCompanion(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('email: $email, ')
|
||||||
|
..write('isAdmin: $isAdmin, ')
|
||||||
|
..write('hasProfileImage: $hasProfileImage, ')
|
||||||
|
..write('profileChangedAt: $profileChangedAt, ')
|
||||||
|
..write('avatarColor: $avatarColor, ')
|
||||||
|
..write('quotaSizeInBytes: $quotaSizeInBytes, ')
|
||||||
|
..write('quotaUsageInBytes: $quotaUsageInBytes, ')
|
||||||
|
..write('pinCode: $pinCode')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
class LocalAlbumEntity extends Table with DriftDefaultsMixin {
|
class LocalAlbumEntity extends Table with DriftDefaultsMixin {
|
||||||
@@ -11,9 +13,26 @@ class LocalAlbumEntity extends Table with DriftDefaultsMixin {
|
|||||||
IntColumn get backupSelection => intEnum<BackupSelection>()();
|
IntColumn get backupSelection => intEnum<BackupSelection>()();
|
||||||
BoolColumn get isIosSharedAlbum => boolean().withDefault(const Constant(false))();
|
BoolColumn get isIosSharedAlbum => boolean().withDefault(const Constant(false))();
|
||||||
|
|
||||||
|
// // Linked album for putting assets to the remote album after finished uploading
|
||||||
|
TextColumn get linkedRemoteAlbumId =>
|
||||||
|
text().references(RemoteAlbumEntity, #id, onDelete: KeyAction.setNull).nullable()();
|
||||||
|
|
||||||
// Used for mark & sweep
|
// Used for mark & sweep
|
||||||
BoolColumn get marker_ => boolean().nullable()();
|
BoolColumn get marker_ => boolean().nullable()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {id};
|
Set<Column> get primaryKey => {id};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension LocalAlbumEntityDataHelper on LocalAlbumEntityData {
|
||||||
|
LocalAlbum toDto({int assetCount = 0}) {
|
||||||
|
return LocalAlbum(
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
updatedAt: updatedAt,
|
||||||
|
assetCount: assetCount,
|
||||||
|
backupSelection: backupSelection,
|
||||||
|
linkedRemoteAlbumId: linkedRemoteAlbumId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import 'package:immich_mobile/domain/models/album/local_album.model.dart' as i2;
|
|||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'
|
||||||
as i3;
|
as i3;
|
||||||
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
|
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart'
|
||||||
|
as i5;
|
||||||
|
import 'package:drift/internal/modular.dart' as i6;
|
||||||
|
|
||||||
typedef $$LocalAlbumEntityTableCreateCompanionBuilder =
|
typedef $$LocalAlbumEntityTableCreateCompanionBuilder =
|
||||||
i1.LocalAlbumEntityCompanion Function({
|
i1.LocalAlbumEntityCompanion Function({
|
||||||
@@ -15,6 +18,7 @@ typedef $$LocalAlbumEntityTableCreateCompanionBuilder =
|
|||||||
i0.Value<DateTime> updatedAt,
|
i0.Value<DateTime> updatedAt,
|
||||||
required i2.BackupSelection backupSelection,
|
required i2.BackupSelection backupSelection,
|
||||||
i0.Value<bool> isIosSharedAlbum,
|
i0.Value<bool> isIosSharedAlbum,
|
||||||
|
i0.Value<String?> linkedRemoteAlbumId,
|
||||||
i0.Value<bool?> marker_,
|
i0.Value<bool?> marker_,
|
||||||
});
|
});
|
||||||
typedef $$LocalAlbumEntityTableUpdateCompanionBuilder =
|
typedef $$LocalAlbumEntityTableUpdateCompanionBuilder =
|
||||||
@@ -24,9 +28,57 @@ typedef $$LocalAlbumEntityTableUpdateCompanionBuilder =
|
|||||||
i0.Value<DateTime> updatedAt,
|
i0.Value<DateTime> updatedAt,
|
||||||
i0.Value<i2.BackupSelection> backupSelection,
|
i0.Value<i2.BackupSelection> backupSelection,
|
||||||
i0.Value<bool> isIosSharedAlbum,
|
i0.Value<bool> isIosSharedAlbum,
|
||||||
|
i0.Value<String?> linkedRemoteAlbumId,
|
||||||
i0.Value<bool?> marker_,
|
i0.Value<bool?> marker_,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final class $$LocalAlbumEntityTableReferences
|
||||||
|
extends
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.$LocalAlbumEntityTable,
|
||||||
|
i1.LocalAlbumEntityData
|
||||||
|
> {
|
||||||
|
$$LocalAlbumEntityTableReferences(
|
||||||
|
super.$_db,
|
||||||
|
super.$_table,
|
||||||
|
super.$_typedResult,
|
||||||
|
);
|
||||||
|
|
||||||
|
static i5.$RemoteAlbumEntityTable _linkedRemoteAlbumIdTable(
|
||||||
|
i0.GeneratedDatabase db,
|
||||||
|
) => i6.ReadDatabaseContainer(db)
|
||||||
|
.resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity')
|
||||||
|
.createAlias(
|
||||||
|
i0.$_aliasNameGenerator(
|
||||||
|
i6.ReadDatabaseContainer(db)
|
||||||
|
.resultSet<i1.$LocalAlbumEntityTable>('local_album_entity')
|
||||||
|
.linkedRemoteAlbumId,
|
||||||
|
i6.ReadDatabaseContainer(
|
||||||
|
db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity').id,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
i5.$$RemoteAlbumEntityTableProcessedTableManager? get linkedRemoteAlbumId {
|
||||||
|
final $_column = $_itemColumn<String>('linked_remote_album_id');
|
||||||
|
if ($_column == null) return null;
|
||||||
|
final manager = i5
|
||||||
|
.$$RemoteAlbumEntityTableTableManager(
|
||||||
|
$_db,
|
||||||
|
i6.ReadDatabaseContainer(
|
||||||
|
$_db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
)
|
||||||
|
.filter((f) => f.id.sqlEquals($_column));
|
||||||
|
final item = $_typedResult.readTableOrNull(_linkedRemoteAlbumIdTable($_db));
|
||||||
|
if (item == null) return manager;
|
||||||
|
return i0.ProcessedTableManager(
|
||||||
|
manager.$state.copyWith(prefetchedData: [item]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class $$LocalAlbumEntityTableFilterComposer
|
class $$LocalAlbumEntityTableFilterComposer
|
||||||
extends i0.Composer<i0.GeneratedDatabase, i1.$LocalAlbumEntityTable> {
|
extends i0.Composer<i0.GeneratedDatabase, i1.$LocalAlbumEntityTable> {
|
||||||
$$LocalAlbumEntityTableFilterComposer({
|
$$LocalAlbumEntityTableFilterComposer({
|
||||||
@@ -66,6 +118,33 @@ class $$LocalAlbumEntityTableFilterComposer
|
|||||||
column: $table.marker_,
|
column: $table.marker_,
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
i5.$$RemoteAlbumEntityTableFilterComposer get linkedRemoteAlbumId {
|
||||||
|
final i5.$$RemoteAlbumEntityTableFilterComposer composer = $composerBuilder(
|
||||||
|
composer: this,
|
||||||
|
getCurrentColumn: (t) => t.linkedRemoteAlbumId,
|
||||||
|
referencedTable: i6.ReadDatabaseContainer(
|
||||||
|
$db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
getReferencedColumn: (t) => t.id,
|
||||||
|
builder:
|
||||||
|
(
|
||||||
|
joinBuilder, {
|
||||||
|
$addJoinBuilderToRootComposer,
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
}) => i5.$$RemoteAlbumEntityTableFilterComposer(
|
||||||
|
$db: $db,
|
||||||
|
$table: i6.ReadDatabaseContainer(
|
||||||
|
$db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||||
|
joinBuilder: joinBuilder,
|
||||||
|
$removeJoinBuilderFromRootComposer:
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return composer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$LocalAlbumEntityTableOrderingComposer
|
class $$LocalAlbumEntityTableOrderingComposer
|
||||||
@@ -106,6 +185,34 @@ class $$LocalAlbumEntityTableOrderingComposer
|
|||||||
column: $table.marker_,
|
column: $table.marker_,
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
i5.$$RemoteAlbumEntityTableOrderingComposer get linkedRemoteAlbumId {
|
||||||
|
final i5.$$RemoteAlbumEntityTableOrderingComposer composer =
|
||||||
|
$composerBuilder(
|
||||||
|
composer: this,
|
||||||
|
getCurrentColumn: (t) => t.linkedRemoteAlbumId,
|
||||||
|
referencedTable: i6.ReadDatabaseContainer(
|
||||||
|
$db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
getReferencedColumn: (t) => t.id,
|
||||||
|
builder:
|
||||||
|
(
|
||||||
|
joinBuilder, {
|
||||||
|
$addJoinBuilderToRootComposer,
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
}) => i5.$$RemoteAlbumEntityTableOrderingComposer(
|
||||||
|
$db: $db,
|
||||||
|
$table: i6.ReadDatabaseContainer(
|
||||||
|
$db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||||
|
joinBuilder: joinBuilder,
|
||||||
|
$removeJoinBuilderFromRootComposer:
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return composer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$LocalAlbumEntityTableAnnotationComposer
|
class $$LocalAlbumEntityTableAnnotationComposer
|
||||||
@@ -139,6 +246,34 @@ class $$LocalAlbumEntityTableAnnotationComposer
|
|||||||
|
|
||||||
i0.GeneratedColumn<bool> get marker_ =>
|
i0.GeneratedColumn<bool> get marker_ =>
|
||||||
$composableBuilder(column: $table.marker_, builder: (column) => column);
|
$composableBuilder(column: $table.marker_, builder: (column) => column);
|
||||||
|
|
||||||
|
i5.$$RemoteAlbumEntityTableAnnotationComposer get linkedRemoteAlbumId {
|
||||||
|
final i5.$$RemoteAlbumEntityTableAnnotationComposer composer =
|
||||||
|
$composerBuilder(
|
||||||
|
composer: this,
|
||||||
|
getCurrentColumn: (t) => t.linkedRemoteAlbumId,
|
||||||
|
referencedTable: i6.ReadDatabaseContainer(
|
||||||
|
$db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
getReferencedColumn: (t) => t.id,
|
||||||
|
builder:
|
||||||
|
(
|
||||||
|
joinBuilder, {
|
||||||
|
$addJoinBuilderToRootComposer,
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
}) => i5.$$RemoteAlbumEntityTableAnnotationComposer(
|
||||||
|
$db: $db,
|
||||||
|
$table: i6.ReadDatabaseContainer(
|
||||||
|
$db,
|
||||||
|
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity'),
|
||||||
|
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||||
|
joinBuilder: joinBuilder,
|
||||||
|
$removeJoinBuilderFromRootComposer:
|
||||||
|
$removeJoinBuilderFromRootComposer,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return composer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$LocalAlbumEntityTableTableManager
|
class $$LocalAlbumEntityTableTableManager
|
||||||
@@ -152,16 +287,9 @@ class $$LocalAlbumEntityTableTableManager
|
|||||||
i1.$$LocalAlbumEntityTableAnnotationComposer,
|
i1.$$LocalAlbumEntityTableAnnotationComposer,
|
||||||
$$LocalAlbumEntityTableCreateCompanionBuilder,
|
$$LocalAlbumEntityTableCreateCompanionBuilder,
|
||||||
$$LocalAlbumEntityTableUpdateCompanionBuilder,
|
$$LocalAlbumEntityTableUpdateCompanionBuilder,
|
||||||
(
|
(i1.LocalAlbumEntityData, i1.$$LocalAlbumEntityTableReferences),
|
||||||
i1.LocalAlbumEntityData,
|
|
||||||
i0.BaseReferences<
|
|
||||||
i0.GeneratedDatabase,
|
|
||||||
i1.$LocalAlbumEntityTable,
|
|
||||||
i1.LocalAlbumEntityData
|
|
||||||
>,
|
|
||||||
),
|
|
||||||
i1.LocalAlbumEntityData,
|
i1.LocalAlbumEntityData,
|
||||||
i0.PrefetchHooks Function()
|
i0.PrefetchHooks Function({bool linkedRemoteAlbumId})
|
||||||
> {
|
> {
|
||||||
$$LocalAlbumEntityTableTableManager(
|
$$LocalAlbumEntityTableTableManager(
|
||||||
i0.GeneratedDatabase db,
|
i0.GeneratedDatabase db,
|
||||||
@@ -187,6 +315,7 @@ class $$LocalAlbumEntityTableTableManager
|
|||||||
i0.Value<i2.BackupSelection> backupSelection =
|
i0.Value<i2.BackupSelection> backupSelection =
|
||||||
const i0.Value.absent(),
|
const i0.Value.absent(),
|
||||||
i0.Value<bool> isIosSharedAlbum = const i0.Value.absent(),
|
i0.Value<bool> isIosSharedAlbum = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> linkedRemoteAlbumId = const i0.Value.absent(),
|
||||||
i0.Value<bool?> marker_ = const i0.Value.absent(),
|
i0.Value<bool?> marker_ = const i0.Value.absent(),
|
||||||
}) => i1.LocalAlbumEntityCompanion(
|
}) => i1.LocalAlbumEntityCompanion(
|
||||||
id: id,
|
id: id,
|
||||||
@@ -194,6 +323,7 @@ class $$LocalAlbumEntityTableTableManager
|
|||||||
updatedAt: updatedAt,
|
updatedAt: updatedAt,
|
||||||
backupSelection: backupSelection,
|
backupSelection: backupSelection,
|
||||||
isIosSharedAlbum: isIosSharedAlbum,
|
isIosSharedAlbum: isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId: linkedRemoteAlbumId,
|
||||||
marker_: marker_,
|
marker_: marker_,
|
||||||
),
|
),
|
||||||
createCompanionCallback:
|
createCompanionCallback:
|
||||||
@@ -203,6 +333,7 @@ class $$LocalAlbumEntityTableTableManager
|
|||||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||||
required i2.BackupSelection backupSelection,
|
required i2.BackupSelection backupSelection,
|
||||||
i0.Value<bool> isIosSharedAlbum = const i0.Value.absent(),
|
i0.Value<bool> isIosSharedAlbum = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> linkedRemoteAlbumId = const i0.Value.absent(),
|
||||||
i0.Value<bool?> marker_ = const i0.Value.absent(),
|
i0.Value<bool?> marker_ = const i0.Value.absent(),
|
||||||
}) => i1.LocalAlbumEntityCompanion.insert(
|
}) => i1.LocalAlbumEntityCompanion.insert(
|
||||||
id: id,
|
id: id,
|
||||||
@@ -210,12 +341,60 @@ class $$LocalAlbumEntityTableTableManager
|
|||||||
updatedAt: updatedAt,
|
updatedAt: updatedAt,
|
||||||
backupSelection: backupSelection,
|
backupSelection: backupSelection,
|
||||||
isIosSharedAlbum: isIosSharedAlbum,
|
isIosSharedAlbum: isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId: linkedRemoteAlbumId,
|
||||||
marker_: marker_,
|
marker_: marker_,
|
||||||
),
|
),
|
||||||
withReferenceMapper: (p0) => p0
|
withReferenceMapper: (p0) => p0
|
||||||
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
.map(
|
||||||
|
(e) => (
|
||||||
|
e.readTable(table),
|
||||||
|
i1.$$LocalAlbumEntityTableReferences(db, table, e),
|
||||||
|
),
|
||||||
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
prefetchHooksCallback: null,
|
prefetchHooksCallback: ({linkedRemoteAlbumId = false}) {
|
||||||
|
return i0.PrefetchHooks(
|
||||||
|
db: db,
|
||||||
|
explicitlyWatchedTables: [],
|
||||||
|
addJoins:
|
||||||
|
<
|
||||||
|
T extends i0.TableManagerState<
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic,
|
||||||
|
dynamic
|
||||||
|
>
|
||||||
|
>(state) {
|
||||||
|
if (linkedRemoteAlbumId) {
|
||||||
|
state =
|
||||||
|
state.withJoin(
|
||||||
|
currentTable: table,
|
||||||
|
currentColumn: table.linkedRemoteAlbumId,
|
||||||
|
referencedTable: i1
|
||||||
|
.$$LocalAlbumEntityTableReferences
|
||||||
|
._linkedRemoteAlbumIdTable(db),
|
||||||
|
referencedColumn: i1
|
||||||
|
.$$LocalAlbumEntityTableReferences
|
||||||
|
._linkedRemoteAlbumIdTable(db)
|
||||||
|
.id,
|
||||||
|
)
|
||||||
|
as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
getPrefetchedDataCallback: (items) async {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -230,16 +409,9 @@ typedef $$LocalAlbumEntityTableProcessedTableManager =
|
|||||||
i1.$$LocalAlbumEntityTableAnnotationComposer,
|
i1.$$LocalAlbumEntityTableAnnotationComposer,
|
||||||
$$LocalAlbumEntityTableCreateCompanionBuilder,
|
$$LocalAlbumEntityTableCreateCompanionBuilder,
|
||||||
$$LocalAlbumEntityTableUpdateCompanionBuilder,
|
$$LocalAlbumEntityTableUpdateCompanionBuilder,
|
||||||
(
|
(i1.LocalAlbumEntityData, i1.$$LocalAlbumEntityTableReferences),
|
||||||
i1.LocalAlbumEntityData,
|
|
||||||
i0.BaseReferences<
|
|
||||||
i0.GeneratedDatabase,
|
|
||||||
i1.$LocalAlbumEntityTable,
|
|
||||||
i1.LocalAlbumEntityData
|
|
||||||
>,
|
|
||||||
),
|
|
||||||
i1.LocalAlbumEntityData,
|
i1.LocalAlbumEntityData,
|
||||||
i0.PrefetchHooks Function()
|
i0.PrefetchHooks Function({bool linkedRemoteAlbumId})
|
||||||
>;
|
>;
|
||||||
|
|
||||||
class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
|
class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
|
||||||
@@ -308,6 +480,20 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
|
|||||||
),
|
),
|
||||||
defaultValue: const i4.Constant(false),
|
defaultValue: const i4.Constant(false),
|
||||||
);
|
);
|
||||||
|
static const i0.VerificationMeta _linkedRemoteAlbumIdMeta =
|
||||||
|
const i0.VerificationMeta('linkedRemoteAlbumId');
|
||||||
|
@override
|
||||||
|
late final i0.GeneratedColumn<String> linkedRemoteAlbumId =
|
||||||
|
i0.GeneratedColumn<String>(
|
||||||
|
'linked_remote_album_id',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES remote_album_entity (id) ON DELETE SET NULL',
|
||||||
|
),
|
||||||
|
);
|
||||||
static const i0.VerificationMeta _marker_Meta = const i0.VerificationMeta(
|
static const i0.VerificationMeta _marker_Meta = const i0.VerificationMeta(
|
||||||
'marker_',
|
'marker_',
|
||||||
);
|
);
|
||||||
@@ -329,6 +515,7 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
|
|||||||
updatedAt,
|
updatedAt,
|
||||||
backupSelection,
|
backupSelection,
|
||||||
isIosSharedAlbum,
|
isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId,
|
||||||
marker_,
|
marker_,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
@@ -371,6 +558,15 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('linked_remote_album_id')) {
|
||||||
|
context.handle(
|
||||||
|
_linkedRemoteAlbumIdMeta,
|
||||||
|
linkedRemoteAlbumId.isAcceptableOrUnknown(
|
||||||
|
data['linked_remote_album_id']!,
|
||||||
|
_linkedRemoteAlbumIdMeta,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
if (data.containsKey('marker')) {
|
if (data.containsKey('marker')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_marker_Meta,
|
_marker_Meta,
|
||||||
@@ -412,6 +608,10 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
|
|||||||
i0.DriftSqlType.bool,
|
i0.DriftSqlType.bool,
|
||||||
data['${effectivePrefix}is_ios_shared_album'],
|
data['${effectivePrefix}is_ios_shared_album'],
|
||||||
)!,
|
)!,
|
||||||
|
linkedRemoteAlbumId: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}linked_remote_album_id'],
|
||||||
|
),
|
||||||
marker_: attachedDatabase.typeMapping.read(
|
marker_: attachedDatabase.typeMapping.read(
|
||||||
i0.DriftSqlType.bool,
|
i0.DriftSqlType.bool,
|
||||||
data['${effectivePrefix}marker'],
|
data['${effectivePrefix}marker'],
|
||||||
@@ -441,6 +641,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
final DateTime updatedAt;
|
final DateTime updatedAt;
|
||||||
final i2.BackupSelection backupSelection;
|
final i2.BackupSelection backupSelection;
|
||||||
final bool isIosSharedAlbum;
|
final bool isIosSharedAlbum;
|
||||||
|
final String? linkedRemoteAlbumId;
|
||||||
final bool? marker_;
|
final bool? marker_;
|
||||||
const LocalAlbumEntityData({
|
const LocalAlbumEntityData({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -448,6 +649,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
required this.updatedAt,
|
required this.updatedAt,
|
||||||
required this.backupSelection,
|
required this.backupSelection,
|
||||||
required this.isIosSharedAlbum,
|
required this.isIosSharedAlbum,
|
||||||
|
this.linkedRemoteAlbumId,
|
||||||
this.marker_,
|
this.marker_,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
@@ -464,6 +666,9 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
map['is_ios_shared_album'] = i0.Variable<bool>(isIosSharedAlbum);
|
map['is_ios_shared_album'] = i0.Variable<bool>(isIosSharedAlbum);
|
||||||
|
if (!nullToAbsent || linkedRemoteAlbumId != null) {
|
||||||
|
map['linked_remote_album_id'] = i0.Variable<String>(linkedRemoteAlbumId);
|
||||||
|
}
|
||||||
if (!nullToAbsent || marker_ != null) {
|
if (!nullToAbsent || marker_ != null) {
|
||||||
map['marker'] = i0.Variable<bool>(marker_);
|
map['marker'] = i0.Variable<bool>(marker_);
|
||||||
}
|
}
|
||||||
@@ -482,6 +687,9 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection
|
backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection
|
||||||
.fromJson(serializer.fromJson<int>(json['backupSelection'])),
|
.fromJson(serializer.fromJson<int>(json['backupSelection'])),
|
||||||
isIosSharedAlbum: serializer.fromJson<bool>(json['isIosSharedAlbum']),
|
isIosSharedAlbum: serializer.fromJson<bool>(json['isIosSharedAlbum']),
|
||||||
|
linkedRemoteAlbumId: serializer.fromJson<String?>(
|
||||||
|
json['linkedRemoteAlbumId'],
|
||||||
|
),
|
||||||
marker_: serializer.fromJson<bool?>(json['marker_']),
|
marker_: serializer.fromJson<bool?>(json['marker_']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -498,6 +706,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
'isIosSharedAlbum': serializer.toJson<bool>(isIosSharedAlbum),
|
'isIosSharedAlbum': serializer.toJson<bool>(isIosSharedAlbum),
|
||||||
|
'linkedRemoteAlbumId': serializer.toJson<String?>(linkedRemoteAlbumId),
|
||||||
'marker_': serializer.toJson<bool?>(marker_),
|
'marker_': serializer.toJson<bool?>(marker_),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -508,6 +717,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
DateTime? updatedAt,
|
DateTime? updatedAt,
|
||||||
i2.BackupSelection? backupSelection,
|
i2.BackupSelection? backupSelection,
|
||||||
bool? isIosSharedAlbum,
|
bool? isIosSharedAlbum,
|
||||||
|
i0.Value<String?> linkedRemoteAlbumId = const i0.Value.absent(),
|
||||||
i0.Value<bool?> marker_ = const i0.Value.absent(),
|
i0.Value<bool?> marker_ = const i0.Value.absent(),
|
||||||
}) => i1.LocalAlbumEntityData(
|
}) => i1.LocalAlbumEntityData(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
@@ -515,6 +725,9 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
updatedAt: updatedAt ?? this.updatedAt,
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
backupSelection: backupSelection ?? this.backupSelection,
|
backupSelection: backupSelection ?? this.backupSelection,
|
||||||
isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum,
|
isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId: linkedRemoteAlbumId.present
|
||||||
|
? linkedRemoteAlbumId.value
|
||||||
|
: this.linkedRemoteAlbumId,
|
||||||
marker_: marker_.present ? marker_.value : this.marker_,
|
marker_: marker_.present ? marker_.value : this.marker_,
|
||||||
);
|
);
|
||||||
LocalAlbumEntityData copyWithCompanion(i1.LocalAlbumEntityCompanion data) {
|
LocalAlbumEntityData copyWithCompanion(i1.LocalAlbumEntityCompanion data) {
|
||||||
@@ -528,6 +741,9 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
isIosSharedAlbum: data.isIosSharedAlbum.present
|
isIosSharedAlbum: data.isIosSharedAlbum.present
|
||||||
? data.isIosSharedAlbum.value
|
? data.isIosSharedAlbum.value
|
||||||
: this.isIosSharedAlbum,
|
: this.isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId: data.linkedRemoteAlbumId.present
|
||||||
|
? data.linkedRemoteAlbumId.value
|
||||||
|
: this.linkedRemoteAlbumId,
|
||||||
marker_: data.marker_.present ? data.marker_.value : this.marker_,
|
marker_: data.marker_.present ? data.marker_.value : this.marker_,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -540,6 +756,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
..write('updatedAt: $updatedAt, ')
|
..write('updatedAt: $updatedAt, ')
|
||||||
..write('backupSelection: $backupSelection, ')
|
..write('backupSelection: $backupSelection, ')
|
||||||
..write('isIosSharedAlbum: $isIosSharedAlbum, ')
|
..write('isIosSharedAlbum: $isIosSharedAlbum, ')
|
||||||
|
..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ')
|
||||||
..write('marker_: $marker_')
|
..write('marker_: $marker_')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
@@ -552,6 +769,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
updatedAt,
|
updatedAt,
|
||||||
backupSelection,
|
backupSelection,
|
||||||
isIosSharedAlbum,
|
isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId,
|
||||||
marker_,
|
marker_,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
@@ -563,6 +781,7 @@ class LocalAlbumEntityData extends i0.DataClass
|
|||||||
other.updatedAt == this.updatedAt &&
|
other.updatedAt == this.updatedAt &&
|
||||||
other.backupSelection == this.backupSelection &&
|
other.backupSelection == this.backupSelection &&
|
||||||
other.isIosSharedAlbum == this.isIosSharedAlbum &&
|
other.isIosSharedAlbum == this.isIosSharedAlbum &&
|
||||||
|
other.linkedRemoteAlbumId == this.linkedRemoteAlbumId &&
|
||||||
other.marker_ == this.marker_);
|
other.marker_ == this.marker_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,6 +792,7 @@ class LocalAlbumEntityCompanion
|
|||||||
final i0.Value<DateTime> updatedAt;
|
final i0.Value<DateTime> updatedAt;
|
||||||
final i0.Value<i2.BackupSelection> backupSelection;
|
final i0.Value<i2.BackupSelection> backupSelection;
|
||||||
final i0.Value<bool> isIosSharedAlbum;
|
final i0.Value<bool> isIosSharedAlbum;
|
||||||
|
final i0.Value<String?> linkedRemoteAlbumId;
|
||||||
final i0.Value<bool?> marker_;
|
final i0.Value<bool?> marker_;
|
||||||
const LocalAlbumEntityCompanion({
|
const LocalAlbumEntityCompanion({
|
||||||
this.id = const i0.Value.absent(),
|
this.id = const i0.Value.absent(),
|
||||||
@@ -580,6 +800,7 @@ class LocalAlbumEntityCompanion
|
|||||||
this.updatedAt = const i0.Value.absent(),
|
this.updatedAt = const i0.Value.absent(),
|
||||||
this.backupSelection = const i0.Value.absent(),
|
this.backupSelection = const i0.Value.absent(),
|
||||||
this.isIosSharedAlbum = const i0.Value.absent(),
|
this.isIosSharedAlbum = const i0.Value.absent(),
|
||||||
|
this.linkedRemoteAlbumId = const i0.Value.absent(),
|
||||||
this.marker_ = const i0.Value.absent(),
|
this.marker_ = const i0.Value.absent(),
|
||||||
});
|
});
|
||||||
LocalAlbumEntityCompanion.insert({
|
LocalAlbumEntityCompanion.insert({
|
||||||
@@ -588,6 +809,7 @@ class LocalAlbumEntityCompanion
|
|||||||
this.updatedAt = const i0.Value.absent(),
|
this.updatedAt = const i0.Value.absent(),
|
||||||
required i2.BackupSelection backupSelection,
|
required i2.BackupSelection backupSelection,
|
||||||
this.isIosSharedAlbum = const i0.Value.absent(),
|
this.isIosSharedAlbum = const i0.Value.absent(),
|
||||||
|
this.linkedRemoteAlbumId = const i0.Value.absent(),
|
||||||
this.marker_ = const i0.Value.absent(),
|
this.marker_ = const i0.Value.absent(),
|
||||||
}) : id = i0.Value(id),
|
}) : id = i0.Value(id),
|
||||||
name = i0.Value(name),
|
name = i0.Value(name),
|
||||||
@@ -598,6 +820,7 @@ class LocalAlbumEntityCompanion
|
|||||||
i0.Expression<DateTime>? updatedAt,
|
i0.Expression<DateTime>? updatedAt,
|
||||||
i0.Expression<int>? backupSelection,
|
i0.Expression<int>? backupSelection,
|
||||||
i0.Expression<bool>? isIosSharedAlbum,
|
i0.Expression<bool>? isIosSharedAlbum,
|
||||||
|
i0.Expression<String>? linkedRemoteAlbumId,
|
||||||
i0.Expression<bool>? marker_,
|
i0.Expression<bool>? marker_,
|
||||||
}) {
|
}) {
|
||||||
return i0.RawValuesInsertable({
|
return i0.RawValuesInsertable({
|
||||||
@@ -606,6 +829,8 @@ class LocalAlbumEntityCompanion
|
|||||||
if (updatedAt != null) 'updated_at': updatedAt,
|
if (updatedAt != null) 'updated_at': updatedAt,
|
||||||
if (backupSelection != null) 'backup_selection': backupSelection,
|
if (backupSelection != null) 'backup_selection': backupSelection,
|
||||||
if (isIosSharedAlbum != null) 'is_ios_shared_album': isIosSharedAlbum,
|
if (isIosSharedAlbum != null) 'is_ios_shared_album': isIosSharedAlbum,
|
||||||
|
if (linkedRemoteAlbumId != null)
|
||||||
|
'linked_remote_album_id': linkedRemoteAlbumId,
|
||||||
if (marker_ != null) 'marker': marker_,
|
if (marker_ != null) 'marker': marker_,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -616,6 +841,7 @@ class LocalAlbumEntityCompanion
|
|||||||
i0.Value<DateTime>? updatedAt,
|
i0.Value<DateTime>? updatedAt,
|
||||||
i0.Value<i2.BackupSelection>? backupSelection,
|
i0.Value<i2.BackupSelection>? backupSelection,
|
||||||
i0.Value<bool>? isIosSharedAlbum,
|
i0.Value<bool>? isIosSharedAlbum,
|
||||||
|
i0.Value<String?>? linkedRemoteAlbumId,
|
||||||
i0.Value<bool?>? marker_,
|
i0.Value<bool?>? marker_,
|
||||||
}) {
|
}) {
|
||||||
return i1.LocalAlbumEntityCompanion(
|
return i1.LocalAlbumEntityCompanion(
|
||||||
@@ -624,6 +850,7 @@ class LocalAlbumEntityCompanion
|
|||||||
updatedAt: updatedAt ?? this.updatedAt,
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
backupSelection: backupSelection ?? this.backupSelection,
|
backupSelection: backupSelection ?? this.backupSelection,
|
||||||
isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum,
|
isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum,
|
||||||
|
linkedRemoteAlbumId: linkedRemoteAlbumId ?? this.linkedRemoteAlbumId,
|
||||||
marker_: marker_ ?? this.marker_,
|
marker_: marker_ ?? this.marker_,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -650,6 +877,11 @@ class LocalAlbumEntityCompanion
|
|||||||
if (isIosSharedAlbum.present) {
|
if (isIosSharedAlbum.present) {
|
||||||
map['is_ios_shared_album'] = i0.Variable<bool>(isIosSharedAlbum.value);
|
map['is_ios_shared_album'] = i0.Variable<bool>(isIosSharedAlbum.value);
|
||||||
}
|
}
|
||||||
|
if (linkedRemoteAlbumId.present) {
|
||||||
|
map['linked_remote_album_id'] = i0.Variable<String>(
|
||||||
|
linkedRemoteAlbumId.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (marker_.present) {
|
if (marker_.present) {
|
||||||
map['marker'] = i0.Variable<bool>(marker_.value);
|
map['marker'] = i0.Variable<bool>(marker_.value);
|
||||||
}
|
}
|
||||||
@@ -664,6 +896,7 @@ class LocalAlbumEntityCompanion
|
|||||||
..write('updatedAt: $updatedAt, ')
|
..write('updatedAt: $updatedAt, ')
|
||||||
..write('backupSelection: $backupSelection, ')
|
..write('backupSelection: $backupSelection, ')
|
||||||
..write('isIosSharedAlbum: $isIosSharedAlbum, ')
|
..write('isIosSharedAlbum: $isIosSharedAlbum, ')
|
||||||
|
..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ')
|
||||||
..write('marker_: $marker_')
|
..write('marker_: $marker_')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
|
|||||||
Set<Column> get primaryKey => {id};
|
Set<Column> get primaryKey => {id};
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LocalAssetEntityDataDomainEx on LocalAssetEntityData {
|
extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData {
|
||||||
LocalAsset toDto() => LocalAsset(
|
LocalAsset toDto() => LocalAsset(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:drift/drift.dart' hide Index;
|
import 'package:drift/drift.dart' hide Index;
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
@@ -44,7 +43,7 @@ class User {
|
|||||||
|
|
||||||
static User fromDto(UserDto dto) => User(
|
static User fromDto(UserDto dto) => User(
|
||||||
id: dto.id,
|
id: dto.id,
|
||||||
updatedAt: dto.updatedAt,
|
updatedAt: dto.updatedAt ?? DateTime(2025),
|
||||||
email: dto.email,
|
email: dto.email,
|
||||||
name: dto.name,
|
name: dto.name,
|
||||||
isAdmin: dto.isAdmin,
|
isAdmin: dto.isAdmin,
|
||||||
@@ -81,13 +80,12 @@ class UserEntity extends Table with DriftDefaultsMixin {
|
|||||||
|
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get name => text()();
|
TextColumn get name => text()();
|
||||||
BoolColumn get isAdmin => boolean().withDefault(const Constant(false))();
|
|
||||||
TextColumn get email => text()();
|
TextColumn get email => text()();
|
||||||
|
|
||||||
|
// Profile image
|
||||||
BoolColumn get hasProfileImage => boolean().withDefault(const Constant(false))();
|
BoolColumn get hasProfileImage => boolean().withDefault(const Constant(false))();
|
||||||
DateTimeColumn get profileChangedAt => dateTime().withDefault(currentDateAndTime)();
|
DateTimeColumn get profileChangedAt => dateTime().withDefault(currentDateAndTime)();
|
||||||
|
IntColumn get avatarColor => intEnum<AvatarColor>().withDefault(const Constant(0))();
|
||||||
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {id};
|
Set<Column> get primaryKey => {id};
|
||||||
|
|||||||
@@ -3,28 +3,27 @@
|
|||||||
import 'package:drift/drift.dart' as i0;
|
import 'package:drift/drift.dart' as i0;
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
|
||||||
as i1;
|
as i1;
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i2;
|
import 'package:immich_mobile/domain/models/user.model.dart' as i2;
|
||||||
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i3;
|
||||||
|
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
|
||||||
|
|
||||||
typedef $$UserEntityTableCreateCompanionBuilder =
|
typedef $$UserEntityTableCreateCompanionBuilder =
|
||||||
i1.UserEntityCompanion Function({
|
i1.UserEntityCompanion Function({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
i0.Value<bool> isAdmin,
|
|
||||||
required String email,
|
required String email,
|
||||||
i0.Value<bool> hasProfileImage,
|
i0.Value<bool> hasProfileImage,
|
||||||
i0.Value<DateTime> profileChangedAt,
|
i0.Value<DateTime> profileChangedAt,
|
||||||
i0.Value<DateTime> updatedAt,
|
i0.Value<i2.AvatarColor> avatarColor,
|
||||||
});
|
});
|
||||||
typedef $$UserEntityTableUpdateCompanionBuilder =
|
typedef $$UserEntityTableUpdateCompanionBuilder =
|
||||||
i1.UserEntityCompanion Function({
|
i1.UserEntityCompanion Function({
|
||||||
i0.Value<String> id,
|
i0.Value<String> id,
|
||||||
i0.Value<String> name,
|
i0.Value<String> name,
|
||||||
i0.Value<bool> isAdmin,
|
|
||||||
i0.Value<String> email,
|
i0.Value<String> email,
|
||||||
i0.Value<bool> hasProfileImage,
|
i0.Value<bool> hasProfileImage,
|
||||||
i0.Value<DateTime> profileChangedAt,
|
i0.Value<DateTime> profileChangedAt,
|
||||||
i0.Value<DateTime> updatedAt,
|
i0.Value<i2.AvatarColor> avatarColor,
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$UserEntityTableFilterComposer
|
class $$UserEntityTableFilterComposer
|
||||||
@@ -46,11 +45,6 @@ class $$UserEntityTableFilterComposer
|
|||||||
builder: (column) => i0.ColumnFilters(column),
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
i0.ColumnFilters<bool> get isAdmin => $composableBuilder(
|
|
||||||
column: $table.isAdmin,
|
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
|
||||||
);
|
|
||||||
|
|
||||||
i0.ColumnFilters<String> get email => $composableBuilder(
|
i0.ColumnFilters<String> get email => $composableBuilder(
|
||||||
column: $table.email,
|
column: $table.email,
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
@@ -66,9 +60,10 @@ class $$UserEntityTableFilterComposer
|
|||||||
builder: (column) => i0.ColumnFilters(column),
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder(
|
i0.ColumnWithTypeConverterFilters<i2.AvatarColor, i2.AvatarColor, int>
|
||||||
column: $table.updatedAt,
|
get avatarColor => $composableBuilder(
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
column: $table.avatarColor,
|
||||||
|
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,11 +86,6 @@ class $$UserEntityTableOrderingComposer
|
|||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
i0.ColumnOrderings<bool> get isAdmin => $composableBuilder(
|
|
||||||
column: $table.isAdmin,
|
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
|
||||||
);
|
|
||||||
|
|
||||||
i0.ColumnOrderings<String> get email => $composableBuilder(
|
i0.ColumnOrderings<String> get email => $composableBuilder(
|
||||||
column: $table.email,
|
column: $table.email,
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
@@ -111,8 +101,8 @@ class $$UserEntityTableOrderingComposer
|
|||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
i0.ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
|
i0.ColumnOrderings<int> get avatarColor => $composableBuilder(
|
||||||
column: $table.updatedAt,
|
column: $table.avatarColor,
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -132,9 +122,6 @@ class $$UserEntityTableAnnotationComposer
|
|||||||
i0.GeneratedColumn<String> get name =>
|
i0.GeneratedColumn<String> get name =>
|
||||||
$composableBuilder(column: $table.name, builder: (column) => column);
|
$composableBuilder(column: $table.name, builder: (column) => column);
|
||||||
|
|
||||||
i0.GeneratedColumn<bool> get isAdmin =>
|
|
||||||
$composableBuilder(column: $table.isAdmin, builder: (column) => column);
|
|
||||||
|
|
||||||
i0.GeneratedColumn<String> get email =>
|
i0.GeneratedColumn<String> get email =>
|
||||||
$composableBuilder(column: $table.email, builder: (column) => column);
|
$composableBuilder(column: $table.email, builder: (column) => column);
|
||||||
|
|
||||||
@@ -148,8 +135,11 @@ class $$UserEntityTableAnnotationComposer
|
|||||||
builder: (column) => column,
|
builder: (column) => column,
|
||||||
);
|
);
|
||||||
|
|
||||||
i0.GeneratedColumn<DateTime> get updatedAt =>
|
i0.GeneratedColumnWithTypeConverter<i2.AvatarColor, int> get avatarColor =>
|
||||||
$composableBuilder(column: $table.updatedAt, builder: (column) => column);
|
$composableBuilder(
|
||||||
|
column: $table.avatarColor,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$UserEntityTableTableManager
|
class $$UserEntityTableTableManager
|
||||||
@@ -191,37 +181,33 @@ class $$UserEntityTableTableManager
|
|||||||
({
|
({
|
||||||
i0.Value<String> id = const i0.Value.absent(),
|
i0.Value<String> id = const i0.Value.absent(),
|
||||||
i0.Value<String> name = const i0.Value.absent(),
|
i0.Value<String> name = const i0.Value.absent(),
|
||||||
i0.Value<bool> isAdmin = const i0.Value.absent(),
|
|
||||||
i0.Value<String> email = const i0.Value.absent(),
|
i0.Value<String> email = const i0.Value.absent(),
|
||||||
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
||||||
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
||||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
i0.Value<i2.AvatarColor> avatarColor = const i0.Value.absent(),
|
||||||
}) => i1.UserEntityCompanion(
|
}) => i1.UserEntityCompanion(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
isAdmin: isAdmin,
|
|
||||||
email: email,
|
email: email,
|
||||||
hasProfileImage: hasProfileImage,
|
hasProfileImage: hasProfileImage,
|
||||||
profileChangedAt: profileChangedAt,
|
profileChangedAt: profileChangedAt,
|
||||||
updatedAt: updatedAt,
|
avatarColor: avatarColor,
|
||||||
),
|
),
|
||||||
createCompanionCallback:
|
createCompanionCallback:
|
||||||
({
|
({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
i0.Value<bool> isAdmin = const i0.Value.absent(),
|
|
||||||
required String email,
|
required String email,
|
||||||
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
||||||
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
||||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
i0.Value<i2.AvatarColor> avatarColor = const i0.Value.absent(),
|
||||||
}) => i1.UserEntityCompanion.insert(
|
}) => i1.UserEntityCompanion.insert(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
isAdmin: isAdmin,
|
|
||||||
email: email,
|
email: email,
|
||||||
hasProfileImage: hasProfileImage,
|
hasProfileImage: hasProfileImage,
|
||||||
profileChangedAt: profileChangedAt,
|
profileChangedAt: profileChangedAt,
|
||||||
updatedAt: updatedAt,
|
avatarColor: avatarColor,
|
||||||
),
|
),
|
||||||
withReferenceMapper: (p0) => p0
|
withReferenceMapper: (p0) => p0
|
||||||
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
||||||
@@ -253,7 +239,7 @@ typedef $$UserEntityTableProcessedTableManager =
|
|||||||
i0.PrefetchHooks Function()
|
i0.PrefetchHooks Function()
|
||||||
>;
|
>;
|
||||||
|
|
||||||
class $UserEntityTable extends i2.UserEntity
|
class $UserEntityTable extends i3.UserEntity
|
||||||
with i0.TableInfo<$UserEntityTable, i1.UserEntityData> {
|
with i0.TableInfo<$UserEntityTable, i1.UserEntityData> {
|
||||||
@override
|
@override
|
||||||
final i0.GeneratedDatabase attachedDatabase;
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
@@ -279,21 +265,6 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
type: i0.DriftSqlType.string,
|
type: i0.DriftSqlType.string,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
static const i0.VerificationMeta _isAdminMeta = const i0.VerificationMeta(
|
|
||||||
'isAdmin',
|
|
||||||
);
|
|
||||||
@override
|
|
||||||
late final i0.GeneratedColumn<bool> isAdmin = i0.GeneratedColumn<bool>(
|
|
||||||
'is_admin',
|
|
||||||
aliasedName,
|
|
||||||
false,
|
|
||||||
type: i0.DriftSqlType.bool,
|
|
||||||
requiredDuringInsert: false,
|
|
||||||
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
|
||||||
'CHECK ("is_admin" IN (0, 1))',
|
|
||||||
),
|
|
||||||
defaultValue: const i3.Constant(false),
|
|
||||||
);
|
|
||||||
static const i0.VerificationMeta _emailMeta = const i0.VerificationMeta(
|
static const i0.VerificationMeta _emailMeta = const i0.VerificationMeta(
|
||||||
'email',
|
'email',
|
||||||
);
|
);
|
||||||
@@ -318,7 +289,7 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||||
'CHECK ("has_profile_image" IN (0, 1))',
|
'CHECK ("has_profile_image" IN (0, 1))',
|
||||||
),
|
),
|
||||||
defaultValue: const i3.Constant(false),
|
defaultValue: const i4.Constant(false),
|
||||||
);
|
);
|
||||||
static const i0.VerificationMeta _profileChangedAtMeta =
|
static const i0.VerificationMeta _profileChangedAtMeta =
|
||||||
const i0.VerificationMeta('profileChangedAt');
|
const i0.VerificationMeta('profileChangedAt');
|
||||||
@@ -330,30 +301,26 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
false,
|
false,
|
||||||
type: i0.DriftSqlType.dateTime,
|
type: i0.DriftSqlType.dateTime,
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: i3.currentDateAndTime,
|
defaultValue: i4.currentDateAndTime,
|
||||||
);
|
);
|
||||||
static const i0.VerificationMeta _updatedAtMeta = const i0.VerificationMeta(
|
|
||||||
'updatedAt',
|
|
||||||
);
|
|
||||||
@override
|
@override
|
||||||
late final i0.GeneratedColumn<DateTime> updatedAt =
|
late final i0.GeneratedColumnWithTypeConverter<i2.AvatarColor, int>
|
||||||
i0.GeneratedColumn<DateTime>(
|
avatarColor = i0.GeneratedColumn<int>(
|
||||||
'updated_at',
|
'avatar_color',
|
||||||
aliasedName,
|
aliasedName,
|
||||||
false,
|
false,
|
||||||
type: i0.DriftSqlType.dateTime,
|
type: i0.DriftSqlType.int,
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: i3.currentDateAndTime,
|
defaultValue: const i4.Constant(0),
|
||||||
);
|
).withConverter<i2.AvatarColor>(i1.$UserEntityTable.$converteravatarColor);
|
||||||
@override
|
@override
|
||||||
List<i0.GeneratedColumn> get $columns => [
|
List<i0.GeneratedColumn> get $columns => [
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
isAdmin,
|
|
||||||
email,
|
email,
|
||||||
hasProfileImage,
|
hasProfileImage,
|
||||||
profileChangedAt,
|
profileChangedAt,
|
||||||
updatedAt,
|
avatarColor,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
@@ -380,12 +347,6 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_nameMeta);
|
context.missing(_nameMeta);
|
||||||
}
|
}
|
||||||
if (data.containsKey('is_admin')) {
|
|
||||||
context.handle(
|
|
||||||
_isAdminMeta,
|
|
||||||
isAdmin.isAcceptableOrUnknown(data['is_admin']!, _isAdminMeta),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (data.containsKey('email')) {
|
if (data.containsKey('email')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_emailMeta,
|
_emailMeta,
|
||||||
@@ -412,12 +373,6 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (data.containsKey('updated_at')) {
|
|
||||||
context.handle(
|
|
||||||
_updatedAtMeta,
|
|
||||||
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,10 +390,6 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
i0.DriftSqlType.string,
|
i0.DriftSqlType.string,
|
||||||
data['${effectivePrefix}name'],
|
data['${effectivePrefix}name'],
|
||||||
)!,
|
)!,
|
||||||
isAdmin: attachedDatabase.typeMapping.read(
|
|
||||||
i0.DriftSqlType.bool,
|
|
||||||
data['${effectivePrefix}is_admin'],
|
|
||||||
)!,
|
|
||||||
email: attachedDatabase.typeMapping.read(
|
email: attachedDatabase.typeMapping.read(
|
||||||
i0.DriftSqlType.string,
|
i0.DriftSqlType.string,
|
||||||
data['${effectivePrefix}email'],
|
data['${effectivePrefix}email'],
|
||||||
@@ -451,10 +402,12 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
i0.DriftSqlType.dateTime,
|
i0.DriftSqlType.dateTime,
|
||||||
data['${effectivePrefix}profile_changed_at'],
|
data['${effectivePrefix}profile_changed_at'],
|
||||||
)!,
|
)!,
|
||||||
updatedAt: attachedDatabase.typeMapping.read(
|
avatarColor: i1.$UserEntityTable.$converteravatarColor.fromSql(
|
||||||
i0.DriftSqlType.dateTime,
|
attachedDatabase.typeMapping.read(
|
||||||
data['${effectivePrefix}updated_at'],
|
i0.DriftSqlType.int,
|
||||||
)!,
|
data['${effectivePrefix}avatar_color'],
|
||||||
|
)!,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,6 +416,8 @@ class $UserEntityTable extends i2.UserEntity
|
|||||||
return $UserEntityTable(attachedDatabase, alias);
|
return $UserEntityTable(attachedDatabase, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static i0.JsonTypeConverter2<i2.AvatarColor, int, int> $converteravatarColor =
|
||||||
|
const i0.EnumIndexConverter<i2.AvatarColor>(i2.AvatarColor.values);
|
||||||
@override
|
@override
|
||||||
bool get withoutRowId => true;
|
bool get withoutRowId => true;
|
||||||
@override
|
@override
|
||||||
@@ -473,30 +428,31 @@ class UserEntityData extends i0.DataClass
|
|||||||
implements i0.Insertable<i1.UserEntityData> {
|
implements i0.Insertable<i1.UserEntityData> {
|
||||||
final String id;
|
final String id;
|
||||||
final String name;
|
final String name;
|
||||||
final bool isAdmin;
|
|
||||||
final String email;
|
final String email;
|
||||||
final bool hasProfileImage;
|
final bool hasProfileImage;
|
||||||
final DateTime profileChangedAt;
|
final DateTime profileChangedAt;
|
||||||
final DateTime updatedAt;
|
final i2.AvatarColor avatarColor;
|
||||||
const UserEntityData({
|
const UserEntityData({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.isAdmin,
|
|
||||||
required this.email,
|
required this.email,
|
||||||
required this.hasProfileImage,
|
required this.hasProfileImage,
|
||||||
required this.profileChangedAt,
|
required this.profileChangedAt,
|
||||||
required this.updatedAt,
|
required this.avatarColor,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
final map = <String, i0.Expression>{};
|
final map = <String, i0.Expression>{};
|
||||||
map['id'] = i0.Variable<String>(id);
|
map['id'] = i0.Variable<String>(id);
|
||||||
map['name'] = i0.Variable<String>(name);
|
map['name'] = i0.Variable<String>(name);
|
||||||
map['is_admin'] = i0.Variable<bool>(isAdmin);
|
|
||||||
map['email'] = i0.Variable<String>(email);
|
map['email'] = i0.Variable<String>(email);
|
||||||
map['has_profile_image'] = i0.Variable<bool>(hasProfileImage);
|
map['has_profile_image'] = i0.Variable<bool>(hasProfileImage);
|
||||||
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt);
|
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt);
|
||||||
map['updated_at'] = i0.Variable<DateTime>(updatedAt);
|
{
|
||||||
|
map['avatar_color'] = i0.Variable<int>(
|
||||||
|
i1.$UserEntityTable.$converteravatarColor.toSql(avatarColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,11 +464,12 @@ class UserEntityData extends i0.DataClass
|
|||||||
return UserEntityData(
|
return UserEntityData(
|
||||||
id: serializer.fromJson<String>(json['id']),
|
id: serializer.fromJson<String>(json['id']),
|
||||||
name: serializer.fromJson<String>(json['name']),
|
name: serializer.fromJson<String>(json['name']),
|
||||||
isAdmin: serializer.fromJson<bool>(json['isAdmin']),
|
|
||||||
email: serializer.fromJson<String>(json['email']),
|
email: serializer.fromJson<String>(json['email']),
|
||||||
hasProfileImage: serializer.fromJson<bool>(json['hasProfileImage']),
|
hasProfileImage: serializer.fromJson<bool>(json['hasProfileImage']),
|
||||||
profileChangedAt: serializer.fromJson<DateTime>(json['profileChangedAt']),
|
profileChangedAt: serializer.fromJson<DateTime>(json['profileChangedAt']),
|
||||||
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
avatarColor: i1.$UserEntityTable.$converteravatarColor.fromJson(
|
||||||
|
serializer.fromJson<int>(json['avatarColor']),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override
|
@override
|
||||||
@@ -521,36 +478,34 @@ class UserEntityData extends i0.DataClass
|
|||||||
return <String, dynamic>{
|
return <String, dynamic>{
|
||||||
'id': serializer.toJson<String>(id),
|
'id': serializer.toJson<String>(id),
|
||||||
'name': serializer.toJson<String>(name),
|
'name': serializer.toJson<String>(name),
|
||||||
'isAdmin': serializer.toJson<bool>(isAdmin),
|
|
||||||
'email': serializer.toJson<String>(email),
|
'email': serializer.toJson<String>(email),
|
||||||
'hasProfileImage': serializer.toJson<bool>(hasProfileImage),
|
'hasProfileImage': serializer.toJson<bool>(hasProfileImage),
|
||||||
'profileChangedAt': serializer.toJson<DateTime>(profileChangedAt),
|
'profileChangedAt': serializer.toJson<DateTime>(profileChangedAt),
|
||||||
'updatedAt': serializer.toJson<DateTime>(updatedAt),
|
'avatarColor': serializer.toJson<int>(
|
||||||
|
i1.$UserEntityTable.$converteravatarColor.toJson(avatarColor),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
i1.UserEntityData copyWith({
|
i1.UserEntityData copyWith({
|
||||||
String? id,
|
String? id,
|
||||||
String? name,
|
String? name,
|
||||||
bool? isAdmin,
|
|
||||||
String? email,
|
String? email,
|
||||||
bool? hasProfileImage,
|
bool? hasProfileImage,
|
||||||
DateTime? profileChangedAt,
|
DateTime? profileChangedAt,
|
||||||
DateTime? updatedAt,
|
i2.AvatarColor? avatarColor,
|
||||||
}) => i1.UserEntityData(
|
}) => i1.UserEntityData(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
name: name ?? this.name,
|
name: name ?? this.name,
|
||||||
isAdmin: isAdmin ?? this.isAdmin,
|
|
||||||
email: email ?? this.email,
|
email: email ?? this.email,
|
||||||
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||||
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||||
updatedAt: updatedAt ?? this.updatedAt,
|
avatarColor: avatarColor ?? this.avatarColor,
|
||||||
);
|
);
|
||||||
UserEntityData copyWithCompanion(i1.UserEntityCompanion data) {
|
UserEntityData copyWithCompanion(i1.UserEntityCompanion data) {
|
||||||
return UserEntityData(
|
return UserEntityData(
|
||||||
id: data.id.present ? data.id.value : this.id,
|
id: data.id.present ? data.id.value : this.id,
|
||||||
name: data.name.present ? data.name.value : this.name,
|
name: data.name.present ? data.name.value : this.name,
|
||||||
isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin,
|
|
||||||
email: data.email.present ? data.email.value : this.email,
|
email: data.email.present ? data.email.value : this.email,
|
||||||
hasProfileImage: data.hasProfileImage.present
|
hasProfileImage: data.hasProfileImage.present
|
||||||
? data.hasProfileImage.value
|
? data.hasProfileImage.value
|
||||||
@@ -558,7 +513,9 @@ class UserEntityData extends i0.DataClass
|
|||||||
profileChangedAt: data.profileChangedAt.present
|
profileChangedAt: data.profileChangedAt.present
|
||||||
? data.profileChangedAt.value
|
? data.profileChangedAt.value
|
||||||
: this.profileChangedAt,
|
: this.profileChangedAt,
|
||||||
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
|
avatarColor: data.avatarColor.present
|
||||||
|
? data.avatarColor.value
|
||||||
|
: this.avatarColor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,11 +524,10 @@ class UserEntityData extends i0.DataClass
|
|||||||
return (StringBuffer('UserEntityData(')
|
return (StringBuffer('UserEntityData(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('name: $name, ')
|
..write('name: $name, ')
|
||||||
..write('isAdmin: $isAdmin, ')
|
|
||||||
..write('email: $email, ')
|
..write('email: $email, ')
|
||||||
..write('hasProfileImage: $hasProfileImage, ')
|
..write('hasProfileImage: $hasProfileImage, ')
|
||||||
..write('profileChangedAt: $profileChangedAt, ')
|
..write('profileChangedAt: $profileChangedAt, ')
|
||||||
..write('updatedAt: $updatedAt')
|
..write('avatarColor: $avatarColor')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
@@ -580,11 +536,10 @@ class UserEntityData extends i0.DataClass
|
|||||||
int get hashCode => Object.hash(
|
int get hashCode => Object.hash(
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
isAdmin,
|
|
||||||
email,
|
email,
|
||||||
hasProfileImage,
|
hasProfileImage,
|
||||||
profileChangedAt,
|
profileChangedAt,
|
||||||
updatedAt,
|
avatarColor,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
@@ -592,78 +547,70 @@ class UserEntityData extends i0.DataClass
|
|||||||
(other is i1.UserEntityData &&
|
(other is i1.UserEntityData &&
|
||||||
other.id == this.id &&
|
other.id == this.id &&
|
||||||
other.name == this.name &&
|
other.name == this.name &&
|
||||||
other.isAdmin == this.isAdmin &&
|
|
||||||
other.email == this.email &&
|
other.email == this.email &&
|
||||||
other.hasProfileImage == this.hasProfileImage &&
|
other.hasProfileImage == this.hasProfileImage &&
|
||||||
other.profileChangedAt == this.profileChangedAt &&
|
other.profileChangedAt == this.profileChangedAt &&
|
||||||
other.updatedAt == this.updatedAt);
|
other.avatarColor == this.avatarColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
|
class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
|
||||||
final i0.Value<String> id;
|
final i0.Value<String> id;
|
||||||
final i0.Value<String> name;
|
final i0.Value<String> name;
|
||||||
final i0.Value<bool> isAdmin;
|
|
||||||
final i0.Value<String> email;
|
final i0.Value<String> email;
|
||||||
final i0.Value<bool> hasProfileImage;
|
final i0.Value<bool> hasProfileImage;
|
||||||
final i0.Value<DateTime> profileChangedAt;
|
final i0.Value<DateTime> profileChangedAt;
|
||||||
final i0.Value<DateTime> updatedAt;
|
final i0.Value<i2.AvatarColor> avatarColor;
|
||||||
const UserEntityCompanion({
|
const UserEntityCompanion({
|
||||||
this.id = const i0.Value.absent(),
|
this.id = const i0.Value.absent(),
|
||||||
this.name = const i0.Value.absent(),
|
this.name = const i0.Value.absent(),
|
||||||
this.isAdmin = const i0.Value.absent(),
|
|
||||||
this.email = const i0.Value.absent(),
|
this.email = const i0.Value.absent(),
|
||||||
this.hasProfileImage = const i0.Value.absent(),
|
this.hasProfileImage = const i0.Value.absent(),
|
||||||
this.profileChangedAt = const i0.Value.absent(),
|
this.profileChangedAt = const i0.Value.absent(),
|
||||||
this.updatedAt = const i0.Value.absent(),
|
this.avatarColor = const i0.Value.absent(),
|
||||||
});
|
});
|
||||||
UserEntityCompanion.insert({
|
UserEntityCompanion.insert({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
this.isAdmin = const i0.Value.absent(),
|
|
||||||
required String email,
|
required String email,
|
||||||
this.hasProfileImage = const i0.Value.absent(),
|
this.hasProfileImage = const i0.Value.absent(),
|
||||||
this.profileChangedAt = const i0.Value.absent(),
|
this.profileChangedAt = const i0.Value.absent(),
|
||||||
this.updatedAt = const i0.Value.absent(),
|
this.avatarColor = const i0.Value.absent(),
|
||||||
}) : id = i0.Value(id),
|
}) : id = i0.Value(id),
|
||||||
name = i0.Value(name),
|
name = i0.Value(name),
|
||||||
email = i0.Value(email);
|
email = i0.Value(email);
|
||||||
static i0.Insertable<i1.UserEntityData> custom({
|
static i0.Insertable<i1.UserEntityData> custom({
|
||||||
i0.Expression<String>? id,
|
i0.Expression<String>? id,
|
||||||
i0.Expression<String>? name,
|
i0.Expression<String>? name,
|
||||||
i0.Expression<bool>? isAdmin,
|
|
||||||
i0.Expression<String>? email,
|
i0.Expression<String>? email,
|
||||||
i0.Expression<bool>? hasProfileImage,
|
i0.Expression<bool>? hasProfileImage,
|
||||||
i0.Expression<DateTime>? profileChangedAt,
|
i0.Expression<DateTime>? profileChangedAt,
|
||||||
i0.Expression<DateTime>? updatedAt,
|
i0.Expression<int>? avatarColor,
|
||||||
}) {
|
}) {
|
||||||
return i0.RawValuesInsertable({
|
return i0.RawValuesInsertable({
|
||||||
if (id != null) 'id': id,
|
if (id != null) 'id': id,
|
||||||
if (name != null) 'name': name,
|
if (name != null) 'name': name,
|
||||||
if (isAdmin != null) 'is_admin': isAdmin,
|
|
||||||
if (email != null) 'email': email,
|
if (email != null) 'email': email,
|
||||||
if (hasProfileImage != null) 'has_profile_image': hasProfileImage,
|
if (hasProfileImage != null) 'has_profile_image': hasProfileImage,
|
||||||
if (profileChangedAt != null) 'profile_changed_at': profileChangedAt,
|
if (profileChangedAt != null) 'profile_changed_at': profileChangedAt,
|
||||||
if (updatedAt != null) 'updated_at': updatedAt,
|
if (avatarColor != null) 'avatar_color': avatarColor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
i1.UserEntityCompanion copyWith({
|
i1.UserEntityCompanion copyWith({
|
||||||
i0.Value<String>? id,
|
i0.Value<String>? id,
|
||||||
i0.Value<String>? name,
|
i0.Value<String>? name,
|
||||||
i0.Value<bool>? isAdmin,
|
|
||||||
i0.Value<String>? email,
|
i0.Value<String>? email,
|
||||||
i0.Value<bool>? hasProfileImage,
|
i0.Value<bool>? hasProfileImage,
|
||||||
i0.Value<DateTime>? profileChangedAt,
|
i0.Value<DateTime>? profileChangedAt,
|
||||||
i0.Value<DateTime>? updatedAt,
|
i0.Value<i2.AvatarColor>? avatarColor,
|
||||||
}) {
|
}) {
|
||||||
return i1.UserEntityCompanion(
|
return i1.UserEntityCompanion(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
name: name ?? this.name,
|
name: name ?? this.name,
|
||||||
isAdmin: isAdmin ?? this.isAdmin,
|
|
||||||
email: email ?? this.email,
|
email: email ?? this.email,
|
||||||
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||||
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||||
updatedAt: updatedAt ?? this.updatedAt,
|
avatarColor: avatarColor ?? this.avatarColor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,9 +623,6 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
|
|||||||
if (name.present) {
|
if (name.present) {
|
||||||
map['name'] = i0.Variable<String>(name.value);
|
map['name'] = i0.Variable<String>(name.value);
|
||||||
}
|
}
|
||||||
if (isAdmin.present) {
|
|
||||||
map['is_admin'] = i0.Variable<bool>(isAdmin.value);
|
|
||||||
}
|
|
||||||
if (email.present) {
|
if (email.present) {
|
||||||
map['email'] = i0.Variable<String>(email.value);
|
map['email'] = i0.Variable<String>(email.value);
|
||||||
}
|
}
|
||||||
@@ -688,8 +632,10 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
|
|||||||
if (profileChangedAt.present) {
|
if (profileChangedAt.present) {
|
||||||
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt.value);
|
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt.value);
|
||||||
}
|
}
|
||||||
if (updatedAt.present) {
|
if (avatarColor.present) {
|
||||||
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
|
map['avatar_color'] = i0.Variable<int>(
|
||||||
|
i1.$UserEntityTable.$converteravatarColor.toSql(avatarColor.value),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@@ -699,11 +645,10 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
|
|||||||
return (StringBuffer('UserEntityCompanion(')
|
return (StringBuffer('UserEntityCompanion(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('name: $name, ')
|
..write('name: $name, ')
|
||||||
..write('isAdmin: $isAdmin, ')
|
|
||||||
..write('email: $email, ')
|
..write('email: $email, ')
|
||||||
..write('hasProfileImage: $hasProfileImage, ')
|
..write('hasProfileImage: $hasProfileImage, ')
|
||||||
..write('profileChangedAt: $profileChangedAt, ')
|
..write('profileChangedAt: $profileChangedAt, ')
|
||||||
..write('updatedAt: $updatedAt')
|
..write('avatarColor: $avatarColor')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import 'package:drift/drift.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import "package:immich_mobile/utils/database.utils.dart";
|
|
||||||
|
|
||||||
final backupRepositoryProvider = Provider<DriftBackupRepository>(
|
final backupRepositoryProvider = Provider<DriftBackupRepository>(
|
||||||
(ref) => DriftBackupRepository(ref.watch(driftProvider)),
|
(ref) => DriftBackupRepository(ref.watch(driftProvider)),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:drift_flutter/drift_flutter.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart';
|
||||||
@@ -43,6 +44,7 @@ class IsarDatabaseRepository implements IDatabaseRepository {
|
|||||||
|
|
||||||
@DriftDatabase(
|
@DriftDatabase(
|
||||||
tables: [
|
tables: [
|
||||||
|
AuthUserEntity,
|
||||||
UserEntity,
|
UserEntity,
|
||||||
UserMetadataEntity,
|
UserMetadataEntity,
|
||||||
PartnerEntity,
|
PartnerEntity,
|
||||||
@@ -64,11 +66,17 @@ class IsarDatabaseRepository implements IDatabaseRepository {
|
|||||||
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
||||||
)
|
)
|
||||||
class Drift extends $Drift implements IDatabaseRepository {
|
class Drift extends $Drift implements IDatabaseRepository {
|
||||||
Drift([QueryExecutor? executor])
|
Drift({QueryExecutor? executor, bool shareAcrossIsolates = true})
|
||||||
: super(executor ?? driftDatabase(name: 'immich', native: const DriftNativeOptions(shareAcrossIsolates: true)));
|
: super(
|
||||||
|
executor ??
|
||||||
|
driftDatabase(
|
||||||
|
name: 'immich',
|
||||||
|
native: DriftNativeOptions(shareAcrossIsolates: shareAcrossIsolates),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 8;
|
int get schemaVersion => 10;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
@@ -123,6 +131,14 @@ class Drift extends $Drift implements IDatabaseRepository {
|
|||||||
from7To8: (m, v8) async {
|
from7To8: (m, v8) async {
|
||||||
await m.create(v8.storeEntity);
|
await m.create(v8.storeEntity);
|
||||||
},
|
},
|
||||||
|
from8To9: (m, v9) async {
|
||||||
|
await m.addColumn(v9.localAlbumEntity, v9.localAlbumEntity.linkedRemoteAlbumId);
|
||||||
|
},
|
||||||
|
from9To10: (m, v10) async {
|
||||||
|
await m.createTable(v10.authUserEntity);
|
||||||
|
await m.addColumn(v10.userEntity, v10.userEntity.avatarColor);
|
||||||
|
await m.alterTable(TableMigration(v10.userEntity));
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -138,7 +154,7 @@ class Drift extends $Drift implements IDatabaseRepository {
|
|||||||
await customStatement('PRAGMA foreign_keys = ON');
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
await customStatement('PRAGMA synchronous = NORMAL');
|
await customStatement('PRAGMA synchronous = NORMAL');
|
||||||
await customStatement('PRAGMA journal_mode = WAL');
|
await customStatement('PRAGMA journal_mode = WAL');
|
||||||
await customStatement('PRAGMA busy_timeout = 500');
|
await customStatement('PRAGMA busy_timeout = 30000');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,35 +9,37 @@ import 'package:immich_mobile/infrastructure/entities/stack.entity.drift.dart'
|
|||||||
as i3;
|
as i3;
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'
|
||||||
as i4;
|
as i4;
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'
|
|
||||||
as i5;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart'
|
|
||||||
as i6;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'
|
|
||||||
as i7;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'
|
|
||||||
as i8;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'
|
|
||||||
as i9;
|
|
||||||
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart'
|
||||||
|
as i5;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'
|
||||||
|
as i6;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart'
|
||||||
|
as i7;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart'
|
||||||
|
as i8;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'
|
||||||
|
as i9;
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'
|
||||||
as i10;
|
as i10;
|
||||||
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'
|
||||||
as i11;
|
as i11;
|
||||||
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart'
|
||||||
as i12;
|
as i12;
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart'
|
||||||
as i13;
|
as i13;
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'
|
||||||
as i14;
|
as i14;
|
||||||
import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'
|
||||||
as i15;
|
as i15;
|
||||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'
|
||||||
as i16;
|
as i16;
|
||||||
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'
|
||||||
as i17;
|
as i17;
|
||||||
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'
|
||||||
as i18;
|
as i18;
|
||||||
import 'package:drift/internal/modular.dart' as i19;
|
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
||||||
|
as i19;
|
||||||
|
import 'package:drift/internal/modular.dart' as i20;
|
||||||
|
|
||||||
abstract class $Drift extends i0.GeneratedDatabase {
|
abstract class $Drift extends i0.GeneratedDatabase {
|
||||||
$Drift(i0.QueryExecutor e) : super(e);
|
$Drift(i0.QueryExecutor e) : super(e);
|
||||||
@@ -48,33 +50,36 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
late final i3.$StackEntityTable stackEntity = i3.$StackEntityTable(this);
|
late final i3.$StackEntityTable stackEntity = i3.$StackEntityTable(this);
|
||||||
late final i4.$LocalAssetEntityTable localAssetEntity = i4
|
late final i4.$LocalAssetEntityTable localAssetEntity = i4
|
||||||
.$LocalAssetEntityTable(this);
|
.$LocalAssetEntityTable(this);
|
||||||
late final i5.$LocalAlbumEntityTable localAlbumEntity = i5
|
late final i5.$RemoteAlbumEntityTable remoteAlbumEntity = i5
|
||||||
|
.$RemoteAlbumEntityTable(this);
|
||||||
|
late final i6.$LocalAlbumEntityTable localAlbumEntity = i6
|
||||||
.$LocalAlbumEntityTable(this);
|
.$LocalAlbumEntityTable(this);
|
||||||
late final i6.$LocalAlbumAssetEntityTable localAlbumAssetEntity = i6
|
late final i7.$LocalAlbumAssetEntityTable localAlbumAssetEntity = i7
|
||||||
.$LocalAlbumAssetEntityTable(this);
|
.$LocalAlbumAssetEntityTable(this);
|
||||||
late final i7.$UserMetadataEntityTable userMetadataEntity = i7
|
late final i8.$AuthUserEntityTable authUserEntity = i8.$AuthUserEntityTable(
|
||||||
.$UserMetadataEntityTable(this);
|
|
||||||
late final i8.$PartnerEntityTable partnerEntity = i8.$PartnerEntityTable(
|
|
||||||
this,
|
this,
|
||||||
);
|
);
|
||||||
late final i9.$RemoteExifEntityTable remoteExifEntity = i9
|
late final i9.$UserMetadataEntityTable userMetadataEntity = i9
|
||||||
.$RemoteExifEntityTable(this);
|
.$UserMetadataEntityTable(this);
|
||||||
late final i10.$RemoteAlbumEntityTable remoteAlbumEntity = i10
|
late final i10.$PartnerEntityTable partnerEntity = i10.$PartnerEntityTable(
|
||||||
.$RemoteAlbumEntityTable(this);
|
|
||||||
late final i11.$RemoteAlbumAssetEntityTable remoteAlbumAssetEntity = i11
|
|
||||||
.$RemoteAlbumAssetEntityTable(this);
|
|
||||||
late final i12.$RemoteAlbumUserEntityTable remoteAlbumUserEntity = i12
|
|
||||||
.$RemoteAlbumUserEntityTable(this);
|
|
||||||
late final i13.$MemoryEntityTable memoryEntity = i13.$MemoryEntityTable(this);
|
|
||||||
late final i14.$MemoryAssetEntityTable memoryAssetEntity = i14
|
|
||||||
.$MemoryAssetEntityTable(this);
|
|
||||||
late final i15.$PersonEntityTable personEntity = i15.$PersonEntityTable(this);
|
|
||||||
late final i16.$AssetFaceEntityTable assetFaceEntity = i16
|
|
||||||
.$AssetFaceEntityTable(this);
|
|
||||||
late final i17.$StoreEntityTable storeEntity = i17.$StoreEntityTable(this);
|
|
||||||
i18.MergedAssetDrift get mergedAssetDrift => i19.ReadDatabaseContainer(
|
|
||||||
this,
|
this,
|
||||||
).accessor<i18.MergedAssetDrift>(i18.MergedAssetDrift.new);
|
);
|
||||||
|
late final i11.$RemoteExifEntityTable remoteExifEntity = i11
|
||||||
|
.$RemoteExifEntityTable(this);
|
||||||
|
late final i12.$RemoteAlbumAssetEntityTable remoteAlbumAssetEntity = i12
|
||||||
|
.$RemoteAlbumAssetEntityTable(this);
|
||||||
|
late final i13.$RemoteAlbumUserEntityTable remoteAlbumUserEntity = i13
|
||||||
|
.$RemoteAlbumUserEntityTable(this);
|
||||||
|
late final i14.$MemoryEntityTable memoryEntity = i14.$MemoryEntityTable(this);
|
||||||
|
late final i15.$MemoryAssetEntityTable memoryAssetEntity = i15
|
||||||
|
.$MemoryAssetEntityTable(this);
|
||||||
|
late final i16.$PersonEntityTable personEntity = i16.$PersonEntityTable(this);
|
||||||
|
late final i17.$AssetFaceEntityTable assetFaceEntity = i17
|
||||||
|
.$AssetFaceEntityTable(this);
|
||||||
|
late final i18.$StoreEntityTable storeEntity = i18.$StoreEntityTable(this);
|
||||||
|
i19.MergedAssetDrift get mergedAssetDrift => i20.ReadDatabaseContainer(
|
||||||
|
this,
|
||||||
|
).accessor<i19.MergedAssetDrift>(i19.MergedAssetDrift.new);
|
||||||
@override
|
@override
|
||||||
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
|
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
|
||||||
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
|
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
|
||||||
@@ -84,6 +89,7 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
remoteAssetEntity,
|
remoteAssetEntity,
|
||||||
stackEntity,
|
stackEntity,
|
||||||
localAssetEntity,
|
localAssetEntity,
|
||||||
|
remoteAlbumEntity,
|
||||||
localAlbumEntity,
|
localAlbumEntity,
|
||||||
localAlbumAssetEntity,
|
localAlbumAssetEntity,
|
||||||
i4.idxLocalAssetChecksum,
|
i4.idxLocalAssetChecksum,
|
||||||
@@ -91,10 +97,10 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
i2.uQRemoteAssetsOwnerChecksum,
|
i2.uQRemoteAssetsOwnerChecksum,
|
||||||
i2.uQRemoteAssetsOwnerLibraryChecksum,
|
i2.uQRemoteAssetsOwnerLibraryChecksum,
|
||||||
i2.idxRemoteAssetChecksum,
|
i2.idxRemoteAssetChecksum,
|
||||||
|
authUserEntity,
|
||||||
userMetadataEntity,
|
userMetadataEntity,
|
||||||
partnerEntity,
|
partnerEntity,
|
||||||
remoteExifEntity,
|
remoteExifEntity,
|
||||||
remoteAlbumEntity,
|
|
||||||
remoteAlbumAssetEntity,
|
remoteAlbumAssetEntity,
|
||||||
remoteAlbumUserEntity,
|
remoteAlbumUserEntity,
|
||||||
memoryEntity,
|
memoryEntity,
|
||||||
@@ -102,7 +108,7 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
personEntity,
|
personEntity,
|
||||||
assetFaceEntity,
|
assetFaceEntity,
|
||||||
storeEntity,
|
storeEntity,
|
||||||
i9.idxLatLng,
|
i11.idxLatLng,
|
||||||
];
|
];
|
||||||
@override
|
@override
|
||||||
i0.StreamQueryUpdateRules
|
i0.StreamQueryUpdateRules
|
||||||
@@ -123,6 +129,33 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
),
|
),
|
||||||
result: [i0.TableUpdate('stack_entity', kind: i0.UpdateKind.delete)],
|
result: [i0.TableUpdate('stack_entity', kind: i0.UpdateKind.delete)],
|
||||||
),
|
),
|
||||||
|
i0.WritePropagation(
|
||||||
|
on: i0.TableUpdateQuery.onTableName(
|
||||||
|
'user_entity',
|
||||||
|
limitUpdateKind: i0.UpdateKind.delete,
|
||||||
|
),
|
||||||
|
result: [
|
||||||
|
i0.TableUpdate('remote_album_entity', kind: i0.UpdateKind.delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
i0.WritePropagation(
|
||||||
|
on: i0.TableUpdateQuery.onTableName(
|
||||||
|
'remote_asset_entity',
|
||||||
|
limitUpdateKind: i0.UpdateKind.delete,
|
||||||
|
),
|
||||||
|
result: [
|
||||||
|
i0.TableUpdate('remote_album_entity', kind: i0.UpdateKind.update),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
i0.WritePropagation(
|
||||||
|
on: i0.TableUpdateQuery.onTableName(
|
||||||
|
'remote_album_entity',
|
||||||
|
limitUpdateKind: i0.UpdateKind.delete,
|
||||||
|
),
|
||||||
|
result: [
|
||||||
|
i0.TableUpdate('local_album_entity', kind: i0.UpdateKind.update),
|
||||||
|
],
|
||||||
|
),
|
||||||
i0.WritePropagation(
|
i0.WritePropagation(
|
||||||
on: i0.TableUpdateQuery.onTableName(
|
on: i0.TableUpdateQuery.onTableName(
|
||||||
'local_asset_entity',
|
'local_asset_entity',
|
||||||
@@ -173,24 +206,6 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
i0.TableUpdate('remote_exif_entity', kind: i0.UpdateKind.delete),
|
i0.TableUpdate('remote_exif_entity', kind: i0.UpdateKind.delete),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
i0.WritePropagation(
|
|
||||||
on: i0.TableUpdateQuery.onTableName(
|
|
||||||
'user_entity',
|
|
||||||
limitUpdateKind: i0.UpdateKind.delete,
|
|
||||||
),
|
|
||||||
result: [
|
|
||||||
i0.TableUpdate('remote_album_entity', kind: i0.UpdateKind.delete),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
i0.WritePropagation(
|
|
||||||
on: i0.TableUpdateQuery.onTableName(
|
|
||||||
'remote_asset_entity',
|
|
||||||
limitUpdateKind: i0.UpdateKind.delete,
|
|
||||||
),
|
|
||||||
result: [
|
|
||||||
i0.TableUpdate('remote_album_entity', kind: i0.UpdateKind.update),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
i0.WritePropagation(
|
i0.WritePropagation(
|
||||||
on: i0.TableUpdateQuery.onTableName(
|
on: i0.TableUpdateQuery.onTableName(
|
||||||
'remote_asset_entity',
|
'remote_asset_entity',
|
||||||
@@ -290,33 +305,35 @@ class $DriftManager {
|
|||||||
i3.$$StackEntityTableTableManager(_db, _db.stackEntity);
|
i3.$$StackEntityTableTableManager(_db, _db.stackEntity);
|
||||||
i4.$$LocalAssetEntityTableTableManager get localAssetEntity =>
|
i4.$$LocalAssetEntityTableTableManager get localAssetEntity =>
|
||||||
i4.$$LocalAssetEntityTableTableManager(_db, _db.localAssetEntity);
|
i4.$$LocalAssetEntityTableTableManager(_db, _db.localAssetEntity);
|
||||||
i5.$$LocalAlbumEntityTableTableManager get localAlbumEntity =>
|
i5.$$RemoteAlbumEntityTableTableManager get remoteAlbumEntity =>
|
||||||
i5.$$LocalAlbumEntityTableTableManager(_db, _db.localAlbumEntity);
|
i5.$$RemoteAlbumEntityTableTableManager(_db, _db.remoteAlbumEntity);
|
||||||
i6.$$LocalAlbumAssetEntityTableTableManager get localAlbumAssetEntity => i6
|
i6.$$LocalAlbumEntityTableTableManager get localAlbumEntity =>
|
||||||
|
i6.$$LocalAlbumEntityTableTableManager(_db, _db.localAlbumEntity);
|
||||||
|
i7.$$LocalAlbumAssetEntityTableTableManager get localAlbumAssetEntity => i7
|
||||||
.$$LocalAlbumAssetEntityTableTableManager(_db, _db.localAlbumAssetEntity);
|
.$$LocalAlbumAssetEntityTableTableManager(_db, _db.localAlbumAssetEntity);
|
||||||
i7.$$UserMetadataEntityTableTableManager get userMetadataEntity =>
|
i8.$$AuthUserEntityTableTableManager get authUserEntity =>
|
||||||
i7.$$UserMetadataEntityTableTableManager(_db, _db.userMetadataEntity);
|
i8.$$AuthUserEntityTableTableManager(_db, _db.authUserEntity);
|
||||||
i8.$$PartnerEntityTableTableManager get partnerEntity =>
|
i9.$$UserMetadataEntityTableTableManager get userMetadataEntity =>
|
||||||
i8.$$PartnerEntityTableTableManager(_db, _db.partnerEntity);
|
i9.$$UserMetadataEntityTableTableManager(_db, _db.userMetadataEntity);
|
||||||
i9.$$RemoteExifEntityTableTableManager get remoteExifEntity =>
|
i10.$$PartnerEntityTableTableManager get partnerEntity =>
|
||||||
i9.$$RemoteExifEntityTableTableManager(_db, _db.remoteExifEntity);
|
i10.$$PartnerEntityTableTableManager(_db, _db.partnerEntity);
|
||||||
i10.$$RemoteAlbumEntityTableTableManager get remoteAlbumEntity =>
|
i11.$$RemoteExifEntityTableTableManager get remoteExifEntity =>
|
||||||
i10.$$RemoteAlbumEntityTableTableManager(_db, _db.remoteAlbumEntity);
|
i11.$$RemoteExifEntityTableTableManager(_db, _db.remoteExifEntity);
|
||||||
i11.$$RemoteAlbumAssetEntityTableTableManager get remoteAlbumAssetEntity =>
|
i12.$$RemoteAlbumAssetEntityTableTableManager get remoteAlbumAssetEntity =>
|
||||||
i11.$$RemoteAlbumAssetEntityTableTableManager(
|
i12.$$RemoteAlbumAssetEntityTableTableManager(
|
||||||
_db,
|
_db,
|
||||||
_db.remoteAlbumAssetEntity,
|
_db.remoteAlbumAssetEntity,
|
||||||
);
|
);
|
||||||
i12.$$RemoteAlbumUserEntityTableTableManager get remoteAlbumUserEntity => i12
|
i13.$$RemoteAlbumUserEntityTableTableManager get remoteAlbumUserEntity => i13
|
||||||
.$$RemoteAlbumUserEntityTableTableManager(_db, _db.remoteAlbumUserEntity);
|
.$$RemoteAlbumUserEntityTableTableManager(_db, _db.remoteAlbumUserEntity);
|
||||||
i13.$$MemoryEntityTableTableManager get memoryEntity =>
|
i14.$$MemoryEntityTableTableManager get memoryEntity =>
|
||||||
i13.$$MemoryEntityTableTableManager(_db, _db.memoryEntity);
|
i14.$$MemoryEntityTableTableManager(_db, _db.memoryEntity);
|
||||||
i14.$$MemoryAssetEntityTableTableManager get memoryAssetEntity =>
|
i15.$$MemoryAssetEntityTableTableManager get memoryAssetEntity =>
|
||||||
i14.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity);
|
i15.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity);
|
||||||
i15.$$PersonEntityTableTableManager get personEntity =>
|
i16.$$PersonEntityTableTableManager get personEntity =>
|
||||||
i15.$$PersonEntityTableTableManager(_db, _db.personEntity);
|
i16.$$PersonEntityTableTableManager(_db, _db.personEntity);
|
||||||
i16.$$AssetFaceEntityTableTableManager get assetFaceEntity =>
|
i17.$$AssetFaceEntityTableTableManager get assetFaceEntity =>
|
||||||
i16.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
|
i17.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
|
||||||
i17.$$StoreEntityTableTableManager get storeEntity =>
|
i18.$$StoreEntityTableTableManager get storeEntity =>
|
||||||
i17.$$StoreEntityTableTableManager(_db, _db.storeEntity);
|
i18.$$StoreEntityTableTableManager(_db, _db.storeEntity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3435,6 +3435,841 @@ i1.GeneratedColumn<int> _column_89(String aliasedName) =>
|
|||||||
true,
|
true,
|
||||||
type: i1.DriftSqlType.int,
|
type: i1.DriftSqlType.int,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final class Schema9 extends i0.VersionedSchema {
|
||||||
|
Schema9({required super.database}) : super(version: 9);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
userEntity,
|
||||||
|
remoteAssetEntity,
|
||||||
|
stackEntity,
|
||||||
|
localAssetEntity,
|
||||||
|
remoteAlbumEntity,
|
||||||
|
localAlbumEntity,
|
||||||
|
localAlbumAssetEntity,
|
||||||
|
idxLocalAssetChecksum,
|
||||||
|
idxRemoteAssetOwnerChecksum,
|
||||||
|
uQRemoteAssetsOwnerChecksum,
|
||||||
|
uQRemoteAssetsOwnerLibraryChecksum,
|
||||||
|
idxRemoteAssetChecksum,
|
||||||
|
userMetadataEntity,
|
||||||
|
partnerEntity,
|
||||||
|
remoteExifEntity,
|
||||||
|
remoteAlbumAssetEntity,
|
||||||
|
remoteAlbumUserEntity,
|
||||||
|
memoryEntity,
|
||||||
|
memoryAssetEntity,
|
||||||
|
personEntity,
|
||||||
|
assetFaceEntity,
|
||||||
|
storeEntity,
|
||||||
|
idxLatLng,
|
||||||
|
];
|
||||||
|
late final Shape16 userEntity = Shape16(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'user_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_2,
|
||||||
|
_column_3,
|
||||||
|
_column_84,
|
||||||
|
_column_85,
|
||||||
|
_column_5,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape17 remoteAssetEntity = Shape17(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_1,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_0,
|
||||||
|
_column_13,
|
||||||
|
_column_14,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_18,
|
||||||
|
_column_19,
|
||||||
|
_column_20,
|
||||||
|
_column_21,
|
||||||
|
_column_86,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape3 stackEntity = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'stack_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [_column_0, _column_9, _column_5, _column_15, _column_75],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape2 localAssetEntity = Shape2(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'local_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_1,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_14,
|
||||||
|
_column_23,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape9 remoteAlbumEntity = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_album_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_56,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_15,
|
||||||
|
_column_57,
|
||||||
|
_column_58,
|
||||||
|
_column_59,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape19 localAlbumEntity = Shape19(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'local_album_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_5,
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_90,
|
||||||
|
_column_33,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape7 localAlbumAssetEntity = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'local_album_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
||||||
|
columns: [_column_34, _column_35],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxLocalAssetChecksum = i1.Index(
|
||||||
|
'idx_local_asset_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)',
|
||||||
|
);
|
||||||
|
final i1.Index idxRemoteAssetOwnerChecksum = i1.Index(
|
||||||
|
'idx_remote_asset_owner_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)',
|
||||||
|
);
|
||||||
|
final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index(
|
||||||
|
'UQ_remote_assets_owner_checksum',
|
||||||
|
'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)',
|
||||||
|
);
|
||||||
|
final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index(
|
||||||
|
'UQ_remote_assets_owner_library_checksum',
|
||||||
|
'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)',
|
||||||
|
);
|
||||||
|
final i1.Index idxRemoteAssetChecksum = i1.Index(
|
||||||
|
'idx_remote_asset_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)',
|
||||||
|
);
|
||||||
|
late final Shape4 userMetadataEntity = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'user_metadata_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(user_id, "key")'],
|
||||||
|
columns: [_column_25, _column_26, _column_27],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape5 partnerEntity = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'partner_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'],
|
||||||
|
columns: [_column_28, _column_29, _column_30],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape8 remoteExifEntity = Shape8(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_exif_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id)'],
|
||||||
|
columns: [
|
||||||
|
_column_36,
|
||||||
|
_column_37,
|
||||||
|
_column_38,
|
||||||
|
_column_39,
|
||||||
|
_column_40,
|
||||||
|
_column_41,
|
||||||
|
_column_11,
|
||||||
|
_column_10,
|
||||||
|
_column_42,
|
||||||
|
_column_43,
|
||||||
|
_column_44,
|
||||||
|
_column_45,
|
||||||
|
_column_46,
|
||||||
|
_column_47,
|
||||||
|
_column_48,
|
||||||
|
_column_49,
|
||||||
|
_column_50,
|
||||||
|
_column_51,
|
||||||
|
_column_52,
|
||||||
|
_column_53,
|
||||||
|
_column_54,
|
||||||
|
_column_55,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape7 remoteAlbumAssetEntity = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_album_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
||||||
|
columns: [_column_36, _column_60],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape10 remoteAlbumUserEntity = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_album_user_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(album_id, user_id)'],
|
||||||
|
columns: [_column_60, _column_25, _column_61],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape11 memoryEntity = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'memory_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_18,
|
||||||
|
_column_15,
|
||||||
|
_column_8,
|
||||||
|
_column_62,
|
||||||
|
_column_63,
|
||||||
|
_column_64,
|
||||||
|
_column_65,
|
||||||
|
_column_66,
|
||||||
|
_column_67,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape12 memoryAssetEntity = Shape12(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'memory_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'],
|
||||||
|
columns: [_column_36, _column_68],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape14 personEntity = Shape14(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'person_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_15,
|
||||||
|
_column_1,
|
||||||
|
_column_69,
|
||||||
|
_column_71,
|
||||||
|
_column_72,
|
||||||
|
_column_73,
|
||||||
|
_column_74,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape15 assetFaceEntity = Shape15(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'asset_face_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_36,
|
||||||
|
_column_76,
|
||||||
|
_column_77,
|
||||||
|
_column_78,
|
||||||
|
_column_79,
|
||||||
|
_column_80,
|
||||||
|
_column_81,
|
||||||
|
_column_82,
|
||||||
|
_column_83,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape18 storeEntity = Shape18(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'store_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [_column_87, _column_88, _column_89],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxLatLng = i1.Index(
|
||||||
|
'idx_lat_lng',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape19 extends i0.VersionedTable {
|
||||||
|
Shape19({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get name =>
|
||||||
|
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<DateTime> get updatedAt =>
|
||||||
|
columnsByName['updated_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<int> get backupSelection =>
|
||||||
|
columnsByName['backup_selection']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<bool> get isIosSharedAlbum =>
|
||||||
|
columnsByName['is_ios_shared_album']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<String> get linkedRemoteAlbumId =>
|
||||||
|
columnsByName['linked_remote_album_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<bool> get marker_ =>
|
||||||
|
columnsByName['marker']! as i1.GeneratedColumn<bool>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_90(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'linked_remote_album_id',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||||
|
'REFERENCES remote_album_entity (id) ON DELETE SET NULL',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final class Schema10 extends i0.VersionedSchema {
|
||||||
|
Schema10({required super.database}) : super(version: 10);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
userEntity,
|
||||||
|
remoteAssetEntity,
|
||||||
|
stackEntity,
|
||||||
|
localAssetEntity,
|
||||||
|
remoteAlbumEntity,
|
||||||
|
localAlbumEntity,
|
||||||
|
localAlbumAssetEntity,
|
||||||
|
idxLocalAssetChecksum,
|
||||||
|
idxRemoteAssetOwnerChecksum,
|
||||||
|
uQRemoteAssetsOwnerChecksum,
|
||||||
|
uQRemoteAssetsOwnerLibraryChecksum,
|
||||||
|
idxRemoteAssetChecksum,
|
||||||
|
authUserEntity,
|
||||||
|
userMetadataEntity,
|
||||||
|
partnerEntity,
|
||||||
|
remoteExifEntity,
|
||||||
|
remoteAlbumAssetEntity,
|
||||||
|
remoteAlbumUserEntity,
|
||||||
|
memoryEntity,
|
||||||
|
memoryAssetEntity,
|
||||||
|
personEntity,
|
||||||
|
assetFaceEntity,
|
||||||
|
storeEntity,
|
||||||
|
idxLatLng,
|
||||||
|
];
|
||||||
|
late final Shape20 userEntity = Shape20(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'user_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_3,
|
||||||
|
_column_84,
|
||||||
|
_column_85,
|
||||||
|
_column_91,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape17 remoteAssetEntity = Shape17(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_1,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_0,
|
||||||
|
_column_13,
|
||||||
|
_column_14,
|
||||||
|
_column_15,
|
||||||
|
_column_16,
|
||||||
|
_column_17,
|
||||||
|
_column_18,
|
||||||
|
_column_19,
|
||||||
|
_column_20,
|
||||||
|
_column_21,
|
||||||
|
_column_86,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape3 stackEntity = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'stack_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [_column_0, _column_9, _column_5, _column_15, _column_75],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape2 localAssetEntity = Shape2(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'local_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_1,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_0,
|
||||||
|
_column_22,
|
||||||
|
_column_14,
|
||||||
|
_column_23,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape9 remoteAlbumEntity = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_album_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_56,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_15,
|
||||||
|
_column_57,
|
||||||
|
_column_58,
|
||||||
|
_column_59,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape19 localAlbumEntity = Shape19(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'local_album_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_5,
|
||||||
|
_column_31,
|
||||||
|
_column_32,
|
||||||
|
_column_90,
|
||||||
|
_column_33,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape7 localAlbumAssetEntity = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'local_album_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
||||||
|
columns: [_column_34, _column_35],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxLocalAssetChecksum = i1.Index(
|
||||||
|
'idx_local_asset_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)',
|
||||||
|
);
|
||||||
|
final i1.Index idxRemoteAssetOwnerChecksum = i1.Index(
|
||||||
|
'idx_remote_asset_owner_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)',
|
||||||
|
);
|
||||||
|
final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index(
|
||||||
|
'UQ_remote_assets_owner_checksum',
|
||||||
|
'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)',
|
||||||
|
);
|
||||||
|
final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index(
|
||||||
|
'UQ_remote_assets_owner_library_checksum',
|
||||||
|
'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)',
|
||||||
|
);
|
||||||
|
final i1.Index idxRemoteAssetChecksum = i1.Index(
|
||||||
|
'idx_remote_asset_checksum',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)',
|
||||||
|
);
|
||||||
|
late final Shape21 authUserEntity = Shape21(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'auth_user_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_1,
|
||||||
|
_column_3,
|
||||||
|
_column_2,
|
||||||
|
_column_84,
|
||||||
|
_column_85,
|
||||||
|
_column_92,
|
||||||
|
_column_93,
|
||||||
|
_column_7,
|
||||||
|
_column_94,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape4 userMetadataEntity = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'user_metadata_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(user_id, "key")'],
|
||||||
|
columns: [_column_25, _column_26, _column_27],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape5 partnerEntity = Shape5(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'partner_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'],
|
||||||
|
columns: [_column_28, _column_29, _column_30],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape8 remoteExifEntity = Shape8(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_exif_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id)'],
|
||||||
|
columns: [
|
||||||
|
_column_36,
|
||||||
|
_column_37,
|
||||||
|
_column_38,
|
||||||
|
_column_39,
|
||||||
|
_column_40,
|
||||||
|
_column_41,
|
||||||
|
_column_11,
|
||||||
|
_column_10,
|
||||||
|
_column_42,
|
||||||
|
_column_43,
|
||||||
|
_column_44,
|
||||||
|
_column_45,
|
||||||
|
_column_46,
|
||||||
|
_column_47,
|
||||||
|
_column_48,
|
||||||
|
_column_49,
|
||||||
|
_column_50,
|
||||||
|
_column_51,
|
||||||
|
_column_52,
|
||||||
|
_column_53,
|
||||||
|
_column_54,
|
||||||
|
_column_55,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape7 remoteAlbumAssetEntity = Shape7(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_album_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
||||||
|
columns: [_column_36, _column_60],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape10 remoteAlbumUserEntity = Shape10(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'remote_album_user_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(album_id, user_id)'],
|
||||||
|
columns: [_column_60, _column_25, _column_61],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape11 memoryEntity = Shape11(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'memory_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_18,
|
||||||
|
_column_15,
|
||||||
|
_column_8,
|
||||||
|
_column_62,
|
||||||
|
_column_63,
|
||||||
|
_column_64,
|
||||||
|
_column_65,
|
||||||
|
_column_66,
|
||||||
|
_column_67,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape12 memoryAssetEntity = Shape12(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'memory_asset_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'],
|
||||||
|
columns: [_column_36, _column_68],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape14 personEntity = Shape14(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'person_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_9,
|
||||||
|
_column_5,
|
||||||
|
_column_15,
|
||||||
|
_column_1,
|
||||||
|
_column_69,
|
||||||
|
_column_71,
|
||||||
|
_column_72,
|
||||||
|
_column_73,
|
||||||
|
_column_74,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape15 assetFaceEntity = Shape15(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'asset_face_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_36,
|
||||||
|
_column_76,
|
||||||
|
_column_77,
|
||||||
|
_column_78,
|
||||||
|
_column_79,
|
||||||
|
_column_80,
|
||||||
|
_column_81,
|
||||||
|
_column_82,
|
||||||
|
_column_83,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape18 storeEntity = Shape18(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'store_entity',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: ['PRIMARY KEY(id)'],
|
||||||
|
columns: [_column_87, _column_88, _column_89],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxLatLng = i1.Index(
|
||||||
|
'idx_lat_lng',
|
||||||
|
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape20 extends i0.VersionedTable {
|
||||||
|
Shape20({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get name =>
|
||||||
|
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get email =>
|
||||||
|
columnsByName['email']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<bool> get hasProfileImage =>
|
||||||
|
columnsByName['has_profile_image']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<DateTime> get profileChangedAt =>
|
||||||
|
columnsByName['profile_changed_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<int> get avatarColor =>
|
||||||
|
columnsByName['avatar_color']! as i1.GeneratedColumn<int>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_91(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'avatar_color',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultValue: const CustomExpression('0'),
|
||||||
|
);
|
||||||
|
|
||||||
|
class Shape21 extends i0.VersionedTable {
|
||||||
|
Shape21({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get name =>
|
||||||
|
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get email =>
|
||||||
|
columnsByName['email']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<bool> get isAdmin =>
|
||||||
|
columnsByName['is_admin']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<bool> get hasProfileImage =>
|
||||||
|
columnsByName['has_profile_image']! as i1.GeneratedColumn<bool>;
|
||||||
|
i1.GeneratedColumn<DateTime> get profileChangedAt =>
|
||||||
|
columnsByName['profile_changed_at']! as i1.GeneratedColumn<DateTime>;
|
||||||
|
i1.GeneratedColumn<int> get avatarColor =>
|
||||||
|
columnsByName['avatar_color']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get quotaSizeInBytes =>
|
||||||
|
columnsByName['quota_size_in_bytes']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get quotaUsageInBytes =>
|
||||||
|
columnsByName['quota_usage_in_bytes']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get pinCode =>
|
||||||
|
columnsByName['pin_code']! as i1.GeneratedColumn<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_92(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'avatar_color',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<int> _column_93(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'quota_size_in_bytes',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
defaultValue: const CustomExpression('0'),
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_94(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'pin_code',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
);
|
||||||
i0.MigrationStepWithVersion migrationSteps({
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
@@ -3443,6 +4278,8 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
||||||
}) {
|
}) {
|
||||||
return (currentVersion, database) async {
|
return (currentVersion, database) async {
|
||||||
switch (currentVersion) {
|
switch (currentVersion) {
|
||||||
@@ -3481,6 +4318,16 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
final migrator = i1.Migrator(database, schema);
|
final migrator = i1.Migrator(database, schema);
|
||||||
await from7To8(migrator, schema);
|
await from7To8(migrator, schema);
|
||||||
return 8;
|
return 8;
|
||||||
|
case 8:
|
||||||
|
final schema = Schema9(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from8To9(migrator, schema);
|
||||||
|
return 9;
|
||||||
|
case 9:
|
||||||
|
final schema = Schema10(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from9To10(migrator, schema);
|
||||||
|
return 10;
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
}
|
}
|
||||||
@@ -3495,6 +4342,8 @@ i1.OnUpgrade stepByStep({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema10 schema) from9To10,
|
||||||
}) => i0.VersionedSchema.stepByStepHelper(
|
}) => i0.VersionedSchema.stepByStepHelper(
|
||||||
step: migrationSteps(
|
step: migrationSteps(
|
||||||
from1To2: from1To2,
|
from1To2: from1To2,
|
||||||
@@ -3504,5 +4353,7 @@ i1.OnUpgrade stepByStep({
|
|||||||
from5To6: from5To6,
|
from5To6: from5To6,
|
||||||
from6To7: from6To7,
|
from6To7: from6To7,
|
||||||
from7To8: from7To8,
|
from7To8: from7To8,
|
||||||
|
from8To9: from8To9,
|
||||||
|
from9To10: from9To10,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:immich_mobile/utils/database.utils.dart';
|
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
|
|
||||||
enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum, name, assetCount, newestAsset }
|
enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum, name, assetCount, newestAsset }
|
||||||
@@ -49,6 +50,13 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
|||||||
return query.map((row) => row.readTable(_db.localAlbumEntity).toDto(assetCount: row.read(assetCount) ?? 0)).get();
|
return query.map((row) => row.readTable(_db.localAlbumEntity).toDto(assetCount: row.read(assetCount) ?? 0)).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<LocalAlbum>> getBackupAlbums() async {
|
||||||
|
final query = _db.localAlbumEntity.select()
|
||||||
|
..where((row) => row.backupSelection.equalsValue(BackupSelection.selected));
|
||||||
|
|
||||||
|
return query.map((row) => row.toDto()).get();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> delete(String albumId) => transaction(() async {
|
Future<void> delete(String albumId) => transaction(() async {
|
||||||
// Remove all assets that are only in this particular album
|
// Remove all assets that are only in this particular album
|
||||||
// We cannot remove all assets in the album because they might be in other albums in iOS
|
// We cannot remove all assets in the album because they might be in other albums in iOS
|
||||||
@@ -335,4 +343,16 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
|
|||||||
Future<int> getCount() {
|
Future<int> getCount() {
|
||||||
return _db.managers.localAlbumEntity.count();
|
return _db.managers.localAlbumEntity.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future unlinkRemoteAlbum(String id) async {
|
||||||
|
return _db.localAlbumEntity.update()
|
||||||
|
..where((row) => row.id.equals(id))
|
||||||
|
..write(const LocalAlbumEntityCompanion(linkedRemoteAlbumId: Value(null)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future linkRemoteAlbum(String localAlbumId, String remoteAlbumId) async {
|
||||||
|
return _db.localAlbumEntity.update()
|
||||||
|
..where((row) => row.id.equals(localAlbumId))
|
||||||
|
..write(LocalAlbumEntityCompanion(linkedRemoteAlbumId: Value(remoteAlbumId)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ import 'logger_db.repository.drift.dart';
|
|||||||
|
|
||||||
@DriftDatabase(tables: [LogMessageEntity])
|
@DriftDatabase(tables: [LogMessageEntity])
|
||||||
class DriftLogger extends $DriftLogger implements IDatabaseRepository {
|
class DriftLogger extends $DriftLogger implements IDatabaseRepository {
|
||||||
DriftLogger([QueryExecutor? executor])
|
DriftLogger({QueryExecutor? executor, bool shareAcrossIsolates = true})
|
||||||
: super(
|
: super(
|
||||||
executor ?? driftDatabase(name: 'immich_logs', native: const DriftNativeOptions(shareAcrossIsolates: true)),
|
executor ??
|
||||||
|
driftDatabase(
|
||||||
|
name: 'immich_logs',
|
||||||
|
native: DriftNativeOptions(shareAcrossIsolates: shareAcrossIsolates),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -113,6 +113,15 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
|||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<RemoteAlbum?> getByName(String albumName, String ownerId) {
|
||||||
|
final query = _db.remoteAlbumEntity.select()
|
||||||
|
..where((row) => row.name.equals(albumName) & row.ownerId.equals(ownerId))
|
||||||
|
..orderBy([(row) => OrderingTerm.desc(row.createdAt)])
|
||||||
|
..limit(1);
|
||||||
|
|
||||||
|
return query.map((row) => row.toDto(ownerName: '', isShared: false)).getSingleOrNull();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> create(RemoteAlbum album, List<String> assetIds) async {
|
Future<void> create(RemoteAlbum album, List<String> assetIds) async {
|
||||||
await _db.transaction(() async {
|
await _db.transaction(() async {
|
||||||
final entity = RemoteAlbumEntityCompanion(
|
final entity = RemoteAlbumEntityCompanion(
|
||||||
@@ -193,14 +202,13 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
|||||||
id: user.id,
|
id: user.id,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
isAdmin: user.isAdmin,
|
|
||||||
updatedAt: user.updatedAt,
|
|
||||||
memoryEnabled: true,
|
memoryEnabled: true,
|
||||||
inTimeline: false,
|
inTimeline: false,
|
||||||
isPartnerSharedBy: false,
|
isPartnerSharedBy: false,
|
||||||
isPartnerSharedWith: false,
|
isPartnerSharedWith: false,
|
||||||
profileChangedAt: user.profileChangedAt,
|
profileChangedAt: user.profileChangedAt,
|
||||||
hasProfileImage: user.hasProfileImage,
|
hasProfileImage: user.hasProfileImage,
|
||||||
|
avatarColor: user.avatarColor,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.get();
|
.get();
|
||||||
@@ -321,6 +329,42 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
|||||||
Future<int> getCount() {
|
Future<int> getCount() {
|
||||||
return _db.managers.remoteAlbumEntity.count();
|
return _db.managers.remoteAlbumEntity.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<String>> getLinkedAssetIds(String userId, String localAlbumId, String remoteAlbumId) async {
|
||||||
|
// Find remote asset ids that:
|
||||||
|
// 1. Belong to the provided local album (via local_album_asset_entity)
|
||||||
|
// 2. Have been uploaded (i.e. a matching remote asset exists for the same checksum & owner)
|
||||||
|
// 3. Are NOT already in the remote album (remote_album_asset_entity)
|
||||||
|
final query = _db.remoteAssetEntity.selectOnly()
|
||||||
|
..addColumns([_db.remoteAssetEntity.id])
|
||||||
|
..join([
|
||||||
|
innerJoin(
|
||||||
|
_db.localAssetEntity,
|
||||||
|
_db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum),
|
||||||
|
useColumns: false,
|
||||||
|
),
|
||||||
|
innerJoin(
|
||||||
|
_db.localAlbumAssetEntity,
|
||||||
|
_db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id),
|
||||||
|
useColumns: false,
|
||||||
|
),
|
||||||
|
// Left join remote album assets to exclude those already in the remote album
|
||||||
|
leftOuterJoin(
|
||||||
|
_db.remoteAlbumAssetEntity,
|
||||||
|
_db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id) &
|
||||||
|
_db.remoteAlbumAssetEntity.albumId.equals(remoteAlbumId),
|
||||||
|
useColumns: false,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
..where(
|
||||||
|
_db.remoteAssetEntity.ownerId.equals(userId) &
|
||||||
|
_db.remoteAssetEntity.deletedAt.isNull() &
|
||||||
|
_db.localAlbumAssetEntity.albumId.equals(localAlbumId) &
|
||||||
|
_db.remoteAlbumAssetEntity.assetId.isNull(), // only those not yet linked
|
||||||
|
);
|
||||||
|
|
||||||
|
return query.map((row) => row.read(_db.remoteAssetEntity.id)!).get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on RemoteAlbumEntityData {
|
extension on RemoteAlbumEntityData {
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ class StorageRepository {
|
|||||||
file = await entity?.originFile;
|
file = await entity?.originFile;
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
log.warning("Cannot get file for asset $assetId");
|
log.warning("Cannot get file for asset $assetId");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final exists = await file.exists();
|
||||||
|
if (!exists) {
|
||||||
|
log.warning("File for asset $assetId does not exist");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
log.warning("Error getting file for asset $assetId", error, stackTrace);
|
log.warning("Error getting file for asset $assetId", error, stackTrace);
|
||||||
@@ -34,6 +41,13 @@ class StorageRepository {
|
|||||||
log.warning(
|
log.warning(
|
||||||
"Cannot get motion file for asset ${asset.id}, name: ${asset.name}, created on: ${asset.createdAt}",
|
"Cannot get motion file for asset ${asset.id}, name: ${asset.name}, created on: ${asset.createdAt}",
|
||||||
);
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final exists = await file.exists();
|
||||||
|
if (!exists) {
|
||||||
|
log.warning("Motion file for asset ${asset.id} does not exist");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
log.warning(
|
log.warning(
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo
|
|||||||
const (bool) => entity.intValue == 1,
|
const (bool) => entity.intValue == 1,
|
||||||
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
|
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
|
||||||
const (UserDto) =>
|
const (UserDto) =>
|
||||||
entity.stringValue == null ? null : await DriftUserRepository(_db).get(entity.stringValue!),
|
entity.stringValue == null ? null : await DriftAuthUserRepository(_db).get(entity.stringValue!),
|
||||||
_ => null,
|
_ => null,
|
||||||
}
|
}
|
||||||
as T?;
|
as T?;
|
||||||
@@ -184,7 +184,7 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo
|
|||||||
const (String) => (null, value as String),
|
const (String) => (null, value as String),
|
||||||
const (bool) => ((value as bool) ? 1 : 0, null),
|
const (bool) => ((value as bool) ? 1 : 0, null),
|
||||||
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
|
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
|
||||||
const (UserDto) => (null, (await DriftUserRepository(_db).upsert(value as UserDto)).id),
|
const (UserDto) => (null, (await DriftAuthUserRepository(_db).upsert(value as UserDto)).id),
|
||||||
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
|
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
|
||||||
};
|
};
|
||||||
return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue));
|
return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue));
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ class SyncApiRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> streamChanges(
|
Future<void> streamChanges(
|
||||||
Function(List<SyncEvent>, Function() abort) onData, {
|
Future<void> Function(List<SyncEvent>, Function() abort, Function() reset) onData, {
|
||||||
|
Function()? onReset,
|
||||||
int batchSize = kSyncEventBatchSize,
|
int batchSize = kSyncEventBatchSize,
|
||||||
http.Client? httpClient,
|
http.Client? httpClient,
|
||||||
}) async {
|
}) async {
|
||||||
@@ -37,6 +38,7 @@ class SyncApiRepository {
|
|||||||
request.body = jsonEncode(
|
request.body = jsonEncode(
|
||||||
SyncStreamDto(
|
SyncStreamDto(
|
||||||
types: [
|
types: [
|
||||||
|
SyncRequestType.authUsersV1,
|
||||||
SyncRequestType.usersV1,
|
SyncRequestType.usersV1,
|
||||||
SyncRequestType.assetsV1,
|
SyncRequestType.assetsV1,
|
||||||
SyncRequestType.assetExifsV1,
|
SyncRequestType.assetExifsV1,
|
||||||
@@ -69,6 +71,8 @@ class SyncApiRepository {
|
|||||||
shouldAbort = true;
|
shouldAbort = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final reset = onReset ?? () {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await client.send(request);
|
final response = await client.send(request);
|
||||||
|
|
||||||
@@ -91,12 +95,12 @@ class SyncApiRepository {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
await onData(_parseLines(lines), abort);
|
await onData(_parseLines(lines), abort, reset);
|
||||||
lines.clear();
|
lines.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lines.isNotEmpty && !shouldAbort) {
|
if (lines.isNotEmpty && !shouldAbort) {
|
||||||
await onData(_parseLines(lines), abort);
|
await onData(_parseLines(lines), abort, reset);
|
||||||
}
|
}
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe("Error processing stream", error, stack);
|
_logger.severe("Error processing stream", error, stack);
|
||||||
@@ -130,6 +134,7 @@ class SyncApiRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const _kResponseMap = <SyncEntityType, Function(Object)>{
|
const _kResponseMap = <SyncEntityType, Function(Object)>{
|
||||||
|
SyncEntityType.authUserV1: SyncAuthUserV1.fromJson,
|
||||||
SyncEntityType.userV1: SyncUserV1.fromJson,
|
SyncEntityType.userV1: SyncUserV1.fromJson,
|
||||||
SyncEntityType.userDeleteV1: SyncUserDeleteV1.fromJson,
|
SyncEntityType.userDeleteV1: SyncUserDeleteV1.fromJson,
|
||||||
SyncEntityType.partnerV1: SyncPartnerV1.fromJson,
|
SyncEntityType.partnerV1: SyncPartnerV1.fromJson,
|
||||||
@@ -156,7 +161,8 @@ const _kResponseMap = <SyncEntityType, Function(Object)>{
|
|||||||
SyncEntityType.albumToAssetV1: SyncAlbumToAssetV1.fromJson,
|
SyncEntityType.albumToAssetV1: SyncAlbumToAssetV1.fromJson,
|
||||||
SyncEntityType.albumToAssetBackfillV1: SyncAlbumToAssetV1.fromJson,
|
SyncEntityType.albumToAssetBackfillV1: SyncAlbumToAssetV1.fromJson,
|
||||||
SyncEntityType.albumToAssetDeleteV1: SyncAlbumToAssetDeleteV1.fromJson,
|
SyncEntityType.albumToAssetDeleteV1: SyncAlbumToAssetDeleteV1.fromJson,
|
||||||
SyncEntityType.syncAckV1: _SyncAckV1.fromJson,
|
SyncEntityType.syncAckV1: _SyncEmptyDto.fromJson,
|
||||||
|
SyncEntityType.syncResetV1: _SyncEmptyDto.fromJson,
|
||||||
SyncEntityType.memoryV1: SyncMemoryV1.fromJson,
|
SyncEntityType.memoryV1: SyncMemoryV1.fromJson,
|
||||||
SyncEntityType.memoryDeleteV1: SyncMemoryDeleteV1.fromJson,
|
SyncEntityType.memoryDeleteV1: SyncMemoryDeleteV1.fromJson,
|
||||||
SyncEntityType.memoryToAssetV1: SyncMemoryAssetV1.fromJson,
|
SyncEntityType.memoryToAssetV1: SyncMemoryAssetV1.fromJson,
|
||||||
@@ -172,8 +178,9 @@ const _kResponseMap = <SyncEntityType, Function(Object)>{
|
|||||||
SyncEntityType.personDeleteV1: SyncPersonDeleteV1.fromJson,
|
SyncEntityType.personDeleteV1: SyncPersonDeleteV1.fromJson,
|
||||||
SyncEntityType.assetFaceV1: SyncAssetFaceV1.fromJson,
|
SyncEntityType.assetFaceV1: SyncAssetFaceV1.fromJson,
|
||||||
SyncEntityType.assetFaceDeleteV1: SyncAssetFaceDeleteV1.fromJson,
|
SyncEntityType.assetFaceDeleteV1: SyncAssetFaceDeleteV1.fromJson,
|
||||||
|
SyncEntityType.syncCompleteV1: _SyncEmptyDto.fromJson,
|
||||||
};
|
};
|
||||||
|
|
||||||
class _SyncAckV1 {
|
class _SyncEmptyDto {
|
||||||
static _SyncAckV1? fromJson(dynamic _) => _SyncAckV1();
|
static _SyncEmptyDto? fromJson(dynamic _) => _SyncEmptyDto();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/memory.model.dart';
|
import 'package:immich_mobile/domain/models/memory.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart';
|
||||||
@@ -29,6 +32,65 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
|||||||
|
|
||||||
SyncStreamRepository(super.db) : _db = db;
|
SyncStreamRepository(super.db) : _db = db;
|
||||||
|
|
||||||
|
Future<void> reset() async {
|
||||||
|
_logger.fine("SyncResetV1 received. Resetting remote entities");
|
||||||
|
try {
|
||||||
|
await _db.exclusively(() async {
|
||||||
|
// foreign_keys PRAGMA is no-op within transactions
|
||||||
|
// https://www.sqlite.org/pragma.html#pragma_foreign_keys
|
||||||
|
await _db.customStatement('PRAGMA foreign_keys = OFF');
|
||||||
|
await transaction(() async {
|
||||||
|
await _db.assetFaceEntity.deleteAll();
|
||||||
|
await _db.memoryAssetEntity.deleteAll();
|
||||||
|
await _db.memoryEntity.deleteAll();
|
||||||
|
await _db.partnerEntity.deleteAll();
|
||||||
|
await _db.personEntity.deleteAll();
|
||||||
|
await _db.remoteAlbumAssetEntity.deleteAll();
|
||||||
|
await _db.remoteAlbumEntity.deleteAll();
|
||||||
|
await _db.remoteAlbumUserEntity.deleteAll();
|
||||||
|
await _db.remoteAssetEntity.deleteAll();
|
||||||
|
await _db.remoteExifEntity.deleteAll();
|
||||||
|
await _db.stackEntity.deleteAll();
|
||||||
|
await _db.userEntity.deleteAll();
|
||||||
|
await _db.userMetadataEntity.deleteAll();
|
||||||
|
});
|
||||||
|
await _db.customStatement('PRAGMA foreign_keys = ON');
|
||||||
|
});
|
||||||
|
} catch (error, stack) {
|
||||||
|
_logger.severe('Error: SyncResetV1', error, stack);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateAuthUsersV1(Iterable<SyncAuthUserV1> data) async {
|
||||||
|
try {
|
||||||
|
await _db.batch((batch) {
|
||||||
|
for (final user in data) {
|
||||||
|
final companion = AuthUserEntityCompanion(
|
||||||
|
name: Value(user.name),
|
||||||
|
email: Value(user.email),
|
||||||
|
hasProfileImage: Value(user.hasProfileImage),
|
||||||
|
profileChangedAt: Value(user.profileChangedAt),
|
||||||
|
avatarColor: Value(user.avatarColor?.toAvatarColor() ?? AvatarColor.primary),
|
||||||
|
isAdmin: Value(user.isAdmin),
|
||||||
|
pinCode: Value(user.pinCode),
|
||||||
|
quotaSizeInBytes: Value(user.quotaSizeInBytes ?? 0),
|
||||||
|
quotaUsageInBytes: Value(user.quotaUsageInBytes),
|
||||||
|
);
|
||||||
|
|
||||||
|
batch.insert(
|
||||||
|
_db.authUserEntity,
|
||||||
|
companion.copyWith(id: Value(user.id)),
|
||||||
|
onConflict: DoUpdate((_) => companion),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error, stack) {
|
||||||
|
_logger.severe('Error: SyncAuthUserV1', error, stack);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data) async {
|
Future<void> deleteUsersV1(Iterable<SyncUserDeleteV1> data) async {
|
||||||
try {
|
try {
|
||||||
await _db.userEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.userId)));
|
await _db.userEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.userId)));
|
||||||
@@ -47,6 +109,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
|||||||
email: Value(user.email),
|
email: Value(user.email),
|
||||||
hasProfileImage: Value(user.hasProfileImage),
|
hasProfileImage: Value(user.hasProfileImage),
|
||||||
profileChangedAt: Value(user.profileChangedAt),
|
profileChangedAt: Value(user.profileChangedAt),
|
||||||
|
avatarColor: Value(user.avatarColor?.toAvatarColor() ?? AvatarColor.primary),
|
||||||
);
|
);
|
||||||
|
|
||||||
batch.insert(_db.userEntity, companion.copyWith(id: Value(user.id)), onConflict: DoUpdate((_) => companion));
|
batch.insert(_db.userEntity, companion.copyWith(id: Value(user.id)), onConflict: DoUpdate((_) => companion));
|
||||||
@@ -573,3 +636,7 @@ extension on String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension on UserAvatarColor {
|
||||||
|
AvatarColor? toAvatarColor() => AvatarColor.values.firstWhereOrNull((c) => c.name == value);
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import 'package:drift/drift.dart';
|
|||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as entity;
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as entity;
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
@@ -68,12 +68,12 @@ class IsarUserRepository extends IsarDatabaseRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DriftUserRepository extends DriftDatabaseRepository {
|
class DriftAuthUserRepository extends DriftDatabaseRepository {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
const DriftUserRepository(super.db) : _db = db;
|
const DriftAuthUserRepository(super.db) : _db = db;
|
||||||
|
|
||||||
Future<UserDto?> get(String id) async {
|
Future<UserDto?> get(String id) async {
|
||||||
final user = await _db.managers.userEntity.filter((user) => user.id.equals(id)).getSingleOrNull();
|
final user = await _db.managers.authUserEntity.filter((user) => user.id.equals(id)).getSingleOrNull();
|
||||||
|
|
||||||
if (user == null) return null;
|
if (user == null) return null;
|
||||||
|
|
||||||
@@ -84,43 +84,30 @@ class DriftUserRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<UserDto> upsert(UserDto user) async {
|
Future<UserDto> upsert(UserDto user) async {
|
||||||
await _db.userEntity.insertOnConflictUpdate(
|
await _db.authUserEntity.insertOnConflictUpdate(
|
||||||
UserEntityCompanion(
|
AuthUserEntityCompanion(
|
||||||
id: Value(user.id),
|
id: Value(user.id),
|
||||||
isAdmin: Value(user.isAdmin),
|
|
||||||
updatedAt: Value(user.updatedAt),
|
|
||||||
name: Value(user.name),
|
name: Value(user.name),
|
||||||
email: Value(user.email),
|
email: Value(user.email),
|
||||||
hasProfileImage: Value(user.hasProfileImage),
|
hasProfileImage: Value(user.hasProfileImage),
|
||||||
profileChangedAt: Value(user.profileChangedAt),
|
profileChangedAt: Value(user.profileChangedAt),
|
||||||
|
isAdmin: Value(user.isAdmin),
|
||||||
|
quotaSizeInBytes: Value(user.quotaSizeInBytes),
|
||||||
|
quotaUsageInBytes: Value(user.quotaUsageInBytes),
|
||||||
|
avatarColor: Value(user.avatarColor),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<UserDto>> getAll() async {
|
|
||||||
final users = await _db.userEntity.select().get();
|
|
||||||
final List<UserDto> result = [];
|
|
||||||
|
|
||||||
for (final user in users) {
|
|
||||||
final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(user.id));
|
|
||||||
final metadata = await query.map((row) => row.toDto()).get();
|
|
||||||
result.add(user.toDto(metadata));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on UserEntityData {
|
extension on AuthUserEntityData {
|
||||||
UserDto toDto([List<UserMetadata>? metadata]) {
|
UserDto toDto([List<UserMetadata>? metadata]) {
|
||||||
AvatarColor avatarColor = AvatarColor.primary;
|
|
||||||
bool memoryEnabled = true;
|
bool memoryEnabled = true;
|
||||||
|
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
for (final meta in metadata) {
|
for (final meta in metadata) {
|
||||||
if (meta.key == UserMetadataKey.preferences && meta.preferences != null) {
|
if (meta.key == UserMetadataKey.preferences && meta.preferences != null) {
|
||||||
avatarColor = meta.preferences?.userAvatarColor ?? AvatarColor.primary;
|
|
||||||
memoryEnabled = meta.preferences?.memoriesEnabled ?? true;
|
memoryEnabled = meta.preferences?.memoriesEnabled ?? true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,12 +117,13 @@ extension on UserEntityData {
|
|||||||
id: id,
|
id: id,
|
||||||
email: email,
|
email: email,
|
||||||
name: name,
|
name: name,
|
||||||
isAdmin: isAdmin,
|
|
||||||
updatedAt: updatedAt,
|
|
||||||
profileChangedAt: profileChangedAt,
|
profileChangedAt: profileChangedAt,
|
||||||
hasProfileImage: hasProfileImage,
|
hasProfileImage: hasProfileImage,
|
||||||
avatarColor: avatarColor,
|
avatarColor: avatarColor,
|
||||||
memoryEnabled: memoryEnabled,
|
memoryEnabled: memoryEnabled,
|
||||||
|
isAdmin: isAdmin,
|
||||||
|
quotaSizeInBytes: quotaSizeInBytes,
|
||||||
|
quotaUsageInBytes: quotaUsageInBytes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user