mirror of
https://github.com/immich-app/immich.git
synced 2026-06-04 05:05:22 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b31ca6e75 |
@@ -15,7 +15,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
- ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- build_cache:/buildcache
|
- pnpm_store_server:/buildcache/pnpm-store
|
||||||
- ../packages/plugin-core:/build/plugins/immich-plugin-core
|
- ../packages/plugin-core:/build/plugins/immich-plugin-core
|
||||||
immich-web:
|
immich-web:
|
||||||
env_file: !reset []
|
env_file: !reset []
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
custom: ['https://buy.immich.app', 'https://immich.store']
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -79,7 +79,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -201,7 +201,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
actions: write
|
actions: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Check for breaking API changes
|
- name: Check for breaking API changes
|
||||||
uses: oasdiff/oasdiff-action/breaking@50e6a3413e5aa9c3ae4d8393c34745be44288b46 # v0.0.48
|
uses: oasdiff/oasdiff-action/breaking@6147a58e5d1249a12f42fc864ab791d571a30015 # v0.0.47
|
||||||
with:
|
with:
|
||||||
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
|
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
|
||||||
revision: open-api/immich-openapi-specs.json
|
revision: open-api/immich-openapi-specs.json
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
working-directory: ./packages/cli
|
working-directory: ./packages/cli
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -49,9 +49,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
env:
|
run: mise run ci-publish
|
||||||
NPM_TAG: ${{ github.event.release.prerelease && 'rc' || 'latest' }}
|
|
||||||
run: mise run ci-publish -- --tag "$NPM_TAG"
|
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
name: Docker
|
name: Docker
|
||||||
@@ -63,7 +61,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -75,13 +73,13 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
|
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -96,7 +94,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate docker image tags
|
- name: Generate docker image tags
|
||||||
id: metadata
|
id: metadata
|
||||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||||
with:
|
with:
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=false
|
latest=false
|
||||||
@@ -104,10 +102,10 @@ jobs:
|
|||||||
name=ghcr.io/${{ github.repository_owner }}/immich-cli
|
name=ghcr.io/${{ github.repository_owner }}/immich-cli
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,value=${{ steps.package-version.outputs.version }},enable=${{ github.event_name == 'release' }}
|
type=raw,value=${{ steps.package-version.outputs.version }},enable=${{ github.event_name == 'release' }}
|
||||||
type=raw,value=latest,enable=${{ github.event_name == 'release' && !github.event.release.prerelease }}
|
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
|
||||||
|
|
||||||
- name: Build and push image
|
- name: Build and push image
|
||||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
||||||
with:
|
with:
|
||||||
file: packages/cli/Dockerfile
|
file: packages/cli/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
needs: [get_body, should_run]
|
needs: [get_body, should_run]
|
||||||
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/immich-app/mdq:main@sha256:e73f60195b39748c4876f23e3e6cd22a68a9754acec8aef1fd6979fd52cd2c9f
|
image: ghcr.io/immich-app/mdq:main@sha256:0a8b8867773a0f8368061f47578603f438349f8f1f28b0e16105f481e5c794e0
|
||||||
outputs:
|
outputs:
|
||||||
checked: ${{ steps.get_checkbox.outputs.checked }}
|
checked: ${{ steps.get_checkbox.outputs.checked }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
|
uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -70,7 +70,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
|
uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -83,6 +83,6 @@ jobs:
|
|||||||
# ./location_of_script_within_repo/buildscript.sh
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
|
uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
||||||
with:
|
with:
|
||||||
category: '/language:${{matrix.language}}'
|
category: '/language:${{matrix.language}}'
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
||||||
steps:
|
steps:
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -90,7 +90,7 @@ jobs:
|
|||||||
suffix: ['']
|
suffix: ['']
|
||||||
steps:
|
steps:
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -132,7 +132,7 @@ jobs:
|
|||||||
suffixes: '-rocm'
|
suffixes: '-rocm'
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
runner-mapping: '{"linux/amd64": "pokedex-large"}'
|
runner-mapping: '{"linux/amd64": "pokedex-large"}'
|
||||||
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@db54dcf16fbb12c43479a23749ceea0ad1b4a704 # multi-runner-build-workflow-v3.0.0
|
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@5813c7c4f7016c748ae7ac5d5f684846649d4d20 # multi-runner-build-workflow-v2.4.0
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -147,7 +147,7 @@ jobs:
|
|||||||
platforms: ${{ matrix.platforms }}
|
platforms: ${{ matrix.platforms }}
|
||||||
runner-mapping: ${{ matrix.runner-mapping }}
|
runner-mapping: ${{ matrix.runner-mapping }}
|
||||||
suffixes: ${{ matrix.suffixes }}
|
suffixes: ${{ matrix.suffixes }}
|
||||||
dockerhub-push: ${{ github.event_name == 'release' && !github.event.release.prerelease }}
|
dockerhub-push: ${{ github.event_name == 'release' }}
|
||||||
build-args: |
|
build-args: |
|
||||||
DEVICE=${{ matrix.device }}
|
DEVICE=${{ matrix.device }}
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ jobs:
|
|||||||
name: Build and Push Server
|
name: Build and Push Server
|
||||||
needs: pre-job
|
needs: pre-job
|
||||||
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }}
|
||||||
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@db54dcf16fbb12c43479a23749ceea0ad1b4a704 # multi-runner-build-workflow-v3.0.0
|
uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@5813c7c4f7016c748ae7ac5d5f684846649d4d20 # multi-runner-build-workflow-v2.4.0
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -167,7 +167,7 @@ jobs:
|
|||||||
image: immich-server
|
image: immich-server
|
||||||
context: .
|
context: .
|
||||||
dockerfile: server/Dockerfile
|
dockerfile: server/Dockerfile
|
||||||
dockerhub-push: ${{ github.event_name == 'release' && !github.event.release.prerelease }}
|
dockerhub-push: ${{ github.event_name == 'release' }}
|
||||||
build-args: |
|
build-args: |
|
||||||
DEVICE=cpu
|
DEVICE=cpu
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
artifact: ${{ steps.get-artifact.outputs.result }}
|
artifact: ${{ steps.get-artifact.outputs.result }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -98,16 +98,9 @@ jobs:
|
|||||||
shouldDeploy: true
|
shouldDeploy: true
|
||||||
};
|
};
|
||||||
} else if (eventType == "release") {
|
} else if (eventType == "release") {
|
||||||
const tag = context.payload.workflow_run.head_branch;
|
|
||||||
const { data: release } = await github.rest.repos.getReleaseByTag({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
tag,
|
|
||||||
});
|
|
||||||
parameters = {
|
parameters = {
|
||||||
event: "release",
|
event: "release",
|
||||||
name: tag,
|
name: context.payload.workflow_run.head_branch,
|
||||||
prerelease: release.prerelease,
|
|
||||||
shouldDeploy: !isFork
|
shouldDeploy: !isFork
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -126,7 +119,7 @@ jobs:
|
|||||||
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -153,7 +146,6 @@ jobs:
|
|||||||
const parameters = JSON.parse(process.env.PARAM_JSON);
|
const parameters = JSON.parse(process.env.PARAM_JSON);
|
||||||
core.setOutput("event", parameters.event);
|
core.setOutput("event", parameters.event);
|
||||||
core.setOutput("name", parameters.name);
|
core.setOutput("name", parameters.name);
|
||||||
core.setOutput("prerelease", parameters.prerelease);
|
|
||||||
core.setOutput("shouldDeploy", parameters.shouldDeploy);
|
core.setOutput("shouldDeploy", parameters.shouldDeploy);
|
||||||
|
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
@@ -211,7 +203,7 @@ jobs:
|
|||||||
run: mise run //docs:deploy
|
run: mise run //docs:deploy
|
||||||
|
|
||||||
- name: Deploy Docs Release Domain
|
- name: Deploy Docs Release Domain
|
||||||
if: ${{ steps.parameters.outputs.event == 'release' && steps.parameters.outputs.prerelease != 'true' }}
|
if: ${{ steps.parameters.outputs.event == 'release' }}
|
||||||
env:
|
env:
|
||||||
TF_VAR_prefix_name: ${{ steps.parameters.outputs.name}}
|
TF_VAR_prefix_name: ${{ steps.parameters.outputs.name}}
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
permissions: {} # No job-level permissions are needed because it uses the app-token
|
permissions: {} # No job-level permissions are needed because it uses the app-token
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -137,7 +137,7 @@ jobs:
|
|||||||
github-token: ${{ steps.generate-token.outputs.token }}
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
tag_name: ${{ needs.bump_version.outputs.version }}
|
tag_name: ${{ needs.bump_version.outputs.version }}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -39,6 +39,4 @@ jobs:
|
|||||||
run: pnpm --filter @immich/sdk build
|
run: pnpm --filter @immich/sdk build
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
env:
|
run: pnpm --filter @immich/sdk publish --provenance --no-git-checks
|
||||||
NPM_TAG: ${{ github.event.release.prerelease && 'rc' || 'latest' }}
|
|
||||||
run: pnpm --filter @immich/sdk publish --provenance --no-git-checks --tag "$NPM_TAG"
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
working-directory: ./mobile
|
working-directory: ./mobile
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -72,6 +72,10 @@ jobs:
|
|||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
working-directory: ./mobile/packages/ui
|
working-directory: ./mobile/packages/ui
|
||||||
|
|
||||||
|
- name: Install dependencies for UI Showcase
|
||||||
|
run: flutter pub get
|
||||||
|
working-directory: ./mobile/packages/ui/showcase
|
||||||
|
|
||||||
- name: Generate translation files
|
- name: Generate translation files
|
||||||
run: mise //mobile:codegen:translation
|
run: mise //mobile:codegen:translation
|
||||||
|
|
||||||
|
|||||||
+19
-19
@@ -17,7 +17,7 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -102,7 +102,7 @@ jobs:
|
|||||||
working-directory: ./packages/cli
|
working-directory: ./packages/cli
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -133,7 +133,7 @@ jobs:
|
|||||||
working-directory: ./packages/cli
|
working-directory: ./packages/cli
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -177,7 +177,7 @@ jobs:
|
|||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -215,7 +215,7 @@ jobs:
|
|||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -243,7 +243,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -293,7 +293,7 @@ jobs:
|
|||||||
working-directory: ./e2e
|
working-directory: ./e2e
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -325,7 +325,7 @@ jobs:
|
|||||||
working-directory: ./server
|
working-directory: ./server
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -361,7 +361,7 @@ jobs:
|
|||||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -374,7 +374,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
@@ -438,7 +438,7 @@ jobs:
|
|||||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -451,7 +451,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
|
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
@@ -546,7 +546,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -583,7 +583,7 @@ jobs:
|
|||||||
working-directory: ./machine-learning
|
working-directory: ./machine-learning
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -613,7 +613,7 @@ jobs:
|
|||||||
working-directory: ./.github
|
working-directory: ./.github
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -643,7 +643,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -664,7 +664,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -722,7 +722,7 @@ jobs:
|
|||||||
- 5432:5432
|
- 5432:5432
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
should_run: ${{ steps.check.outputs.should_run }}
|
should_run: ${{ steps.check.outputs.should_run }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
||||||
steps:
|
steps:
|
||||||
- id: token
|
- id: token
|
||||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation
|
||||||
|
in our community a harassment-free experience for everyone, regardless
|
||||||
|
of age, body size, visible or invisible disability, ethnicity, sex
|
||||||
|
characteristics, gender identity and expression, level of experience,
|
||||||
|
education, socio-economic status, nationality, personal appearance,
|
||||||
|
race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open,
|
||||||
|
welcoming, diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for
|
||||||
|
our community include:
|
||||||
|
|
||||||
|
- Demonstrating empathy and kindness toward other people
|
||||||
|
- Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
- Giving and gracefully accepting constructive feedback
|
||||||
|
- Accepting responsibility and apologizing to those affected by our
|
||||||
|
mistakes, and learning from the experience
|
||||||
|
- Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
- The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
- Trolling, insulting or derogatory comments, and personal or
|
||||||
|
political attacks
|
||||||
|
- Public or private harassment
|
||||||
|
- Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
- Other conduct which could reasonably be considered inappropriate in
|
||||||
|
a professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our
|
||||||
|
standards of acceptable behavior and will take appropriate and fair
|
||||||
|
corrective action in response to any behavior that they deem
|
||||||
|
inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit,
|
||||||
|
or reject comments, commits, code, wiki edits, issues, and other
|
||||||
|
contributions that are not aligned to this Code of Conduct, and will
|
||||||
|
communicate reasons for moderation decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also
|
||||||
|
applies when an individual is officially representing the community in
|
||||||
|
public spaces. Examples of representing our community include using an
|
||||||
|
official e-mail address, posting via an official social media account,
|
||||||
|
or acting as an appointed representative at an online or offline
|
||||||
|
event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior
|
||||||
|
may be reported to the community leaders responsible for enforcement
|
||||||
|
at our Discord channel. All complaints
|
||||||
|
will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and
|
||||||
|
security of the reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in
|
||||||
|
determining the consequences for any action they deem in violation of
|
||||||
|
this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior
|
||||||
|
deemed unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders,
|
||||||
|
providing clarity around the nature of the violation and an
|
||||||
|
explanation of why the behavior was inappropriate. A public apology
|
||||||
|
may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued
|
||||||
|
behavior. No interaction with the people involved, including
|
||||||
|
unsolicited interaction with those enforcing the Code of Conduct, for
|
||||||
|
a specified period of time. This includes avoiding interactions in
|
||||||
|
community spaces as well as external channels like social
|
||||||
|
media. Violating these terms may lead to a temporary or permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards,
|
||||||
|
including sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or
|
||||||
|
public communication with the community for a specified period of
|
||||||
|
time. No public or private interaction with the people involved,
|
||||||
|
including unsolicited interaction with those enforcing the Code of
|
||||||
|
Conduct, is allowed during this period. Violating these terms may lead
|
||||||
|
to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of
|
||||||
|
community standards, including sustained inappropriate behavior,
|
||||||
|
harassment of an individual, or aggression toward or disparagement of
|
||||||
|
classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction
|
||||||
|
within the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor
|
||||||
|
Covenant][homepage], version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of
|
||||||
|
conduct enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the
|
||||||
|
FAQ at https://www.contributor-covenant.org/faq. Translations are
|
||||||
|
available at https://www.contributor-covenant.org/translations.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Please report security issues to `security@immich.app`
|
||||||
@@ -154,7 +154,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
@@ -85,7 +85,7 @@ services:
|
|||||||
container_name: immich_prometheus
|
container_name: immich_prometheus
|
||||||
ports:
|
ports:
|
||||||
- 9090:9090
|
- 9090:9090
|
||||||
image: prom/prometheus@sha256:69f5241418838263316593f7274a304b095c40bcf22e57272865da91bd60a8ac
|
image: prom/prometheus@sha256:e4254400b85610324913f0dc4acf92603d9984e7519414c5a12811aa6146acc3
|
||||||
volumes:
|
volumes:
|
||||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||||
- prometheus-data:/prometheus
|
- prometheus-data:/prometheus
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
user: '1000:1000'
|
user: '1000:1000'
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich_redis
|
container_name: immich_redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -109,24 +109,6 @@ mise //mobile:translation
|
|||||||
|
|
||||||
The mobile app asks you what backend to connect to. You can utilize the demo backend (https://demo.immich.app/) if you don't need to change server code or upload photos. Alternatively, you can run the server yourself per the instructions above.
|
The mobile app asks you what backend to connect to. You can utilize the demo backend (https://demo.immich.app/) if you don't need to change server code or upload photos. Alternatively, you can run the server yourself per the instructions above.
|
||||||
|
|
||||||
#### UI components and widget previews
|
|
||||||
|
|
||||||
Shared design-system widgets (buttons, inputs, forms) live in the
|
|
||||||
[`immich_ui` package](https://github.com/immich-app/immich/tree/main/mobile/packages/ui/)
|
|
||||||
under `mobile/packages/ui/`. Components are defined in `lib/src/components/`
|
|
||||||
and have matching previews in `lib/src/previews/`.
|
|
||||||
|
|
||||||
To inspect a component in isolation with a light/dark toggle and hot reload,
|
|
||||||
launch [Flutter's Widget Previewer](https://docs.flutter.dev/tools/widget-previewer):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd mobile/packages/ui
|
|
||||||
flutter widget-preview start
|
|
||||||
```
|
|
||||||
|
|
||||||
In VS Code or Android Studio with the Flutter plugin, the previewer
|
|
||||||
auto-starts when you open the **Flutter Widget Preview** tab in the sidebar.
|
|
||||||
|
|
||||||
## IDE setup
|
## IDE setup
|
||||||
|
|
||||||
### Lint / format extensions
|
### Lint / format extensions
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ services:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: immich-e2e-redis
|
container_name: immich-e2e-redis
|
||||||
image: docker.io/valkey/valkey:9@sha256:4963247afc4cd33c7d3b2d2816b9f7f8eeebab148d29056c2ca4d7cbc966f2d9
|
image: docker.io/valkey/valkey:9@sha256:8436e10bc65c94886a91d4415b6a6dfa9cb5a306fb3b996e5bb67cd2b4854193
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ describe('/server', () => {
|
|||||||
major: expect.any(Number),
|
major: expect.any(Number),
|
||||||
minor: expect.any(Number),
|
minor: expect.any(Number),
|
||||||
patch: expect.any(Number),
|
patch: expect.any(Number),
|
||||||
prerelease: null,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -116,7 +115,6 @@ describe('/server', () => {
|
|||||||
oauthAutoLaunch: false,
|
oauthAutoLaunch: false,
|
||||||
ocr: false,
|
ocr: false,
|
||||||
passwordLogin: true,
|
passwordLogin: true,
|
||||||
realtimeTranscoding: false,
|
|
||||||
search: true,
|
search: true,
|
||||||
sidecar: true,
|
sidecar: true,
|
||||||
trash: true,
|
trash: true,
|
||||||
@@ -141,7 +139,6 @@ describe('/server', () => {
|
|||||||
maintenanceMode: false,
|
maintenanceMode: false,
|
||||||
mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json',
|
mapDarkStyleUrl: 'https://tiles.immich.cloud/v1/style/dark.json',
|
||||||
mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json',
|
mapLightStyleUrl: 'https://tiles.immich.cloud/v1/style/light.json',
|
||||||
minFaces: 3,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,18 +21,18 @@ describe('/system-config', () => {
|
|||||||
const response1 = await request(app)
|
const response1 = await request(app)
|
||||||
.put('/system-config')
|
.put('/system-config')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ ...config, newVersionCheck: { enabled: false, channel: 'stable' } });
|
.send({ ...config, newVersionCheck: { enabled: false } });
|
||||||
|
|
||||||
expect(response1.status).toBe(200);
|
expect(response1.status).toBe(200);
|
||||||
expect(response1.body).toEqual({ ...config, newVersionCheck: { enabled: false, channel: 'stable' } });
|
expect(response1.body).toEqual({ ...config, newVersionCheck: { enabled: false } });
|
||||||
|
|
||||||
const response2 = await request(app)
|
const response2 = await request(app)
|
||||||
.put('/system-config')
|
.put('/system-config')
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`)
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
.send({ ...config, newVersionCheck: { enabled: true, channel: 'stable' } });
|
.send({ ...config, newVersionCheck: { enabled: true } });
|
||||||
|
|
||||||
expect(response2.status).toBe(200);
|
expect(response2.status).toBe(200);
|
||||||
expect(response2.body).toEqual({ ...config, newVersionCheck: { enabled: true, channel: 'stable' } });
|
expect(response2.body).toEqual({ ...config, newVersionCheck: { enabled: true } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reject an invalid config entry', async () => {
|
it('should reject an invalid config entry', async () => {
|
||||||
|
|||||||
@@ -230,21 +230,6 @@ describe('/users', () => {
|
|||||||
const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
|
const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
|
||||||
expect(after).toMatchObject({ download: { includeEmbeddedVideos: true } });
|
expect(after).toMatchObject({ download: { includeEmbeddedVideos: true } });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update minimum face count to display people', async () => {
|
|
||||||
const before = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
|
|
||||||
expect(before).toMatchObject({ people: { minimumFaces: 3 } });
|
|
||||||
|
|
||||||
const { status, body } = await request(app)
|
|
||||||
.put('/users/me/preferences')
|
|
||||||
.send({ people: { minimumFaces: 2 } })
|
|
||||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
||||||
expect(status).toBe(200);
|
|
||||||
expect(body).toMatchObject({ people: { minimumFaces: 2 } });
|
|
||||||
|
|
||||||
const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) });
|
|
||||||
expect(after).toMatchObject({ people: { minimumFaces: 2 } });
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GET /users/:id', () => {
|
describe('GET /users/:id', () => {
|
||||||
|
|||||||
@@ -305,8 +305,6 @@
|
|||||||
"refreshing_all_libraries": "Refreshing all libraries",
|
"refreshing_all_libraries": "Refreshing all libraries",
|
||||||
"registration": "Admin Registration",
|
"registration": "Admin Registration",
|
||||||
"registration_description": "Since you are the first user on the system, you will be assigned as the Admin and are responsible for administrative tasks, and additional users will be created by you.",
|
"registration_description": "Since you are the first user on the system, you will be assigned as the Admin and are responsible for administrative tasks, and additional users will be created by you.",
|
||||||
"release_channel_release_candidate": "Release candidate",
|
|
||||||
"release_channel_stable": "Stable",
|
|
||||||
"remove_failed_jobs": "Remove failed jobs",
|
"remove_failed_jobs": "Remove failed jobs",
|
||||||
"require_password_change_on_login": "Require user to change password on first login",
|
"require_password_change_on_login": "Require user to change password on first login",
|
||||||
"reset_settings_to_default": "Reset settings to default",
|
"reset_settings_to_default": "Reset settings to default",
|
||||||
@@ -401,10 +399,6 @@
|
|||||||
"transcoding_preferred_hardware_device_description": "Applies only to VAAPI and QSV. Sets the dri node used for hardware transcoding.",
|
"transcoding_preferred_hardware_device_description": "Applies only to VAAPI and QSV. Sets the dri node used for hardware transcoding.",
|
||||||
"transcoding_preset_preset": "Preset (-preset)",
|
"transcoding_preset_preset": "Preset (-preset)",
|
||||||
"transcoding_preset_preset_description": "Compression speed. Slower presets produce smaller files, and increase quality when targeting a certain bitrate. VP9 ignores speeds above 'faster'.",
|
"transcoding_preset_preset_description": "Compression speed. Slower presets produce smaller files, and increase quality when targeting a certain bitrate. VP9 ignores speeds above 'faster'.",
|
||||||
"transcoding_realtime": "Real-time Transcoding [EXPERIMENTAL]",
|
|
||||||
"transcoding_realtime_description": "Allows transcoding to be performed in real-time as the video is being streamed. Enables quality switching, but may cause higher playback latency and stuttering depending on server capabilities.",
|
|
||||||
"transcoding_realtime_enabled": "Enable real-time transcoding",
|
|
||||||
"transcoding_realtime_enabled_description": "If disabled, the server will refuse to start new real-time transcoding sessions.",
|
|
||||||
"transcoding_reference_frames": "Reference frames",
|
"transcoding_reference_frames": "Reference frames",
|
||||||
"transcoding_reference_frames_description": "The number of frames to reference when compressing a given frame. Higher values improve compression efficiency, but slow down encoding. 0 sets this value automatically.",
|
"transcoding_reference_frames_description": "The number of frames to reference when compressing a given frame. Higher values improve compression efficiency, but slow down encoding. 0 sets this value automatically.",
|
||||||
"transcoding_required_description": "Only videos not in an accepted format",
|
"transcoding_required_description": "Only videos not in an accepted format",
|
||||||
@@ -448,8 +442,6 @@
|
|||||||
"user_settings_description": "Manage user settings",
|
"user_settings_description": "Manage user settings",
|
||||||
"user_successfully_removed": "User {email} has been successfully removed.",
|
"user_successfully_removed": "User {email} has been successfully removed.",
|
||||||
"users_page_description": "Admin users page",
|
"users_page_description": "Admin users page",
|
||||||
"version_check_channel": "Release channel",
|
|
||||||
"version_check_channel_description": "Pick the release channel you want to get version announcements for",
|
|
||||||
"version_check_enabled_description": "Enable version check",
|
"version_check_enabled_description": "Enable version check",
|
||||||
"version_check_implications": "The version check feature relies on periodic communication with {server}",
|
"version_check_implications": "The version check feature relies on periodic communication with {server}",
|
||||||
"version_check_settings": "Version Check",
|
"version_check_settings": "Version Check",
|
||||||
@@ -1592,8 +1584,6 @@
|
|||||||
"merge_people_prompt": "Do you want to merge these people? This action is irreversible.",
|
"merge_people_prompt": "Do you want to merge these people? This action is irreversible.",
|
||||||
"merge_people_successfully": "Merge people successfully",
|
"merge_people_successfully": "Merge people successfully",
|
||||||
"merged_people_count": "Merged {count, plural, one {# person} other {# people}}",
|
"merged_people_count": "Merged {count, plural, one {# person} other {# people}}",
|
||||||
"minFaces": "Minimum faces",
|
|
||||||
"minFaces_description": "The minimum number of recognized faces for a person to be displayed",
|
|
||||||
"minimize": "Minimize",
|
"minimize": "Minimize",
|
||||||
"minute": "Minute",
|
"minute": "Minute",
|
||||||
"minutes": "Minutes",
|
"minutes": "Minutes",
|
||||||
@@ -2462,7 +2452,6 @@
|
|||||||
"video": "Video",
|
"video": "Video",
|
||||||
"video_hover_setting": "Play video thumbnail on hover",
|
"video_hover_setting": "Play video thumbnail on hover",
|
||||||
"video_hover_setting_description": "Play video thumbnail when mouse is hovering over item. Even when disabled, playback can be started by hovering over the play icon.",
|
"video_hover_setting_description": "Play video thumbnail when mouse is hovering over item. Even when disabled, playback can be started by hovering over the play icon.",
|
||||||
"video_quality": "Video quality",
|
|
||||||
"videos": "Videos",
|
"videos": "Videos",
|
||||||
"videos_count": "{count, plural, one {# Video} other {# Videos}}",
|
"videos_count": "{count, plural, one {# Video} other {# Videos}}",
|
||||||
"videos_only": "Videos only",
|
"videos_only": "Videos only",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
ARG DEVICE=cpu
|
ARG DEVICE=cpu
|
||||||
|
|
||||||
FROM python:3.11-bookworm@sha256:121d86b6d08752968a7dddbc708849e5f3a839bbff47f32212b46d2a1d842bab AS builder-cpu
|
FROM python:3.11-bookworm@sha256:970c99f886b839fc8829289040c1845dadaf2cae46b37acc7710333158ec29b4 AS builder-cpu
|
||||||
|
|
||||||
FROM python:3.13-slim-trixie@sha256:b04b5d7233d2ad9c379e22ea8927cd1378cd15c60d4ef876c065b25ea8fb3bf3 AS builder-openvino
|
FROM python:3.13-slim-trixie@sha256:d168b8d9eb761f4d3fe305ebd04aeb7e7f2de0297cec5fb2f8f6403244621664 AS builder-openvino
|
||||||
|
|
||||||
FROM builder-cpu AS builder-cuda
|
FROM builder-cpu AS builder-cuda
|
||||||
|
|
||||||
@@ -39,12 +39,12 @@ RUN --mount=type=cache,target=/root/.cache/uv \
|
|||||||
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
||||||
uv sync --frozen --extra ${DEVICE} --no-dev --no-editable --no-install-project --compile-bytecode --no-progress --active --link-mode copy
|
uv sync --frozen --extra ${DEVICE} --no-dev --no-editable --no-install-project --compile-bytecode --no-progress --active --link-mode copy
|
||||||
|
|
||||||
FROM python:3.11-slim-bookworm@sha256:8dca233de9f3d9bb410665f00a4da6dd06f331083137e0e98ccf227236fcc438 AS prod-cpu
|
FROM python:3.11-slim-bookworm@sha256:9c6f90801e6b68e772b7c0ca74260cbf7af9f320acec894e26fccdaccfbe3b47 AS prod-cpu
|
||||||
|
|
||||||
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 \
|
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 \
|
||||||
MACHINE_LEARNING_MODEL_ARENA=false
|
MACHINE_LEARNING_MODEL_ARENA=false
|
||||||
|
|
||||||
FROM python:3.13-slim-trixie@sha256:b04b5d7233d2ad9c379e22ea8927cd1378cd15c60d4ef876c065b25ea8fb3bf3 AS prod-openvino
|
FROM python:3.13-slim-trixie@sha256:d168b8d9eb761f4d3fe305ebd04aeb7e7f2de0297cec5fb2f8f6403244621664 AS prod-openvino
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
|
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ try:
|
|||||||
str(settings.http_keepalive_timeout_s),
|
str(settings.http_keepalive_timeout_s),
|
||||||
"--graceful-timeout",
|
"--graceful-timeout",
|
||||||
"10",
|
"10",
|
||||||
"--no-control-socket",
|
|
||||||
],
|
],
|
||||||
) as cmd:
|
) as cmd:
|
||||||
cmd.wait()
|
cmd.wait()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from zipfile import BadZipFile
|
|||||||
|
|
||||||
import orjson
|
import orjson
|
||||||
from fastapi import Depends, FastAPI, File, Form, HTTPException
|
from fastapi import Depends, FastAPI, File, Form, HTTPException
|
||||||
from fastapi.responses import PlainTextResponse
|
from fastapi.responses import ORJSONResponse, PlainTextResponse
|
||||||
from onnxruntime.capi.onnxruntime_pybind11_state import InvalidProtobuf, NoSuchFile
|
from onnxruntime.capi.onnxruntime_pybind11_state import InvalidProtobuf, NoSuchFile
|
||||||
from PIL.Image import Image
|
from PIL.Image import Image
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
@@ -32,7 +32,6 @@ from .schemas import (
|
|||||||
ModelIdentity,
|
ModelIdentity,
|
||||||
ModelTask,
|
ModelTask,
|
||||||
ModelType,
|
ModelType,
|
||||||
ORJSONResponse,
|
|
||||||
PipelineRequest,
|
PipelineRequest,
|
||||||
T,
|
T,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -89,9 +89,7 @@ class OpenClipTextualEncoder(BaseCLIPTextualEncoder):
|
|||||||
|
|
||||||
tokenizer: Tokenizer = Tokenizer.from_file(self.tokenizer_file_path.as_posix())
|
tokenizer: Tokenizer = Tokenizer.from_file(self.tokenizer_file_path.as_posix())
|
||||||
|
|
||||||
pad_id = tokenizer.token_to_id(pad_token)
|
pad_id: int = tokenizer.token_to_id(pad_token)
|
||||||
if pad_id is None:
|
|
||||||
raise ValueError(f"Pad token '{pad_token}' not found in tokenizer vocab")
|
|
||||||
tokenizer.enable_padding(length=context_length, pad_token=pad_token, pad_id=pad_id)
|
tokenizer.enable_padding(length=context_length, pad_token=pad_token, pad_id=pad_id)
|
||||||
tokenizer.enable_truncation(max_length=context_length)
|
tokenizer.enable_truncation(max_length=context_length)
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,9 @@ from typing import Any, Literal, Protocol, TypeGuard, TypeVar
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import numpy.typing as npt
|
import numpy.typing as npt
|
||||||
import orjson
|
|
||||||
from fastapi.responses import JSONResponse
|
|
||||||
from typing_extensions import TypedDict
|
from typing_extensions import TypedDict
|
||||||
|
|
||||||
|
|
||||||
class ORJSONResponse(JSONResponse):
|
|
||||||
def render(self, content: Any) -> bytes:
|
|
||||||
return orjson.dumps(content, option=orjson.OPT_SERIALIZE_NUMPY)
|
|
||||||
|
|
||||||
|
|
||||||
class StrEnum(str, Enum):
|
class StrEnum(str, Enum):
|
||||||
value: str
|
value: str
|
||||||
|
|
||||||
|
|||||||
Generated
+450
-498
File diff suppressed because it is too large
Load Diff
-3368
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
467DA6EAF83F3481F8BD94AB /* Pods_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AB817AA297EDEC88B23F3F6 /* Pods_ShareExtension.framework */; };
|
3B6A31FED0FC846D6BD69BBC /* Pods_ShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 357FC57E54FD0F51795CF28A /* Pods_ShareExtension.framework */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
B2EE00022E72CA15008B6CA7 /* PermissionApi.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2EE00012E72CA15008B6CA7 /* PermissionApi.g.swift */; };
|
B2EE00022E72CA15008B6CA7 /* PermissionApi.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2EE00012E72CA15008B6CA7 /* PermissionApi.g.swift */; };
|
||||||
B2EE00042E72CA15008B6CA7 /* PermissionApiImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2EE00032E72CA15008B6CA7 /* PermissionApiImpl.swift */; };
|
B2EE00042E72CA15008B6CA7 /* PermissionApiImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2EE00032E72CA15008B6CA7 /* PermissionApiImpl.swift */; };
|
||||||
B2BE315F2E5E5229006EEF88 /* BackgroundWorker.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2BE315E2E5E5229006EEF88 /* BackgroundWorker.g.swift */; };
|
B2BE315F2E5E5229006EEF88 /* BackgroundWorker.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2BE315E2E5E5229006EEF88 /* BackgroundWorker.g.swift */; };
|
||||||
D3BED739C0BC29BB32E18EB2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC499FBCE6B29B2DAFED7130 /* Pods_Runner.framework */; };
|
D218389C4A4C4693F141F7D1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */; };
|
||||||
F02538E92DFBCBDD008C3FA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
F02538E92DFBCBDD008C3FA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
F0B57D3A2DF764BD00DC5BCC /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */; };
|
F0B57D3A2DF764BD00DC5BCC /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */; };
|
||||||
F0B57D3C2DF764BD00DC5BCC /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */; };
|
F0B57D3C2DF764BD00DC5BCC /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */; };
|
||||||
@@ -85,18 +85,16 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
10B378D23F917891A0F23E33 /* Pods-ShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
2E3441B73560D0F6FD25E04F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
357FC57E54FD0F51795CF28A /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
614A7F5DC5DB09E89E4FCBE8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
571EAA93D77181C7C98C2EA6 /* Pods-ShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
681FBA560D5D2ADDE4F0B59E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
6D160F04A389B9FFBC557803 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
8AB817AA297EDEC88B23F3F6 /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
937632897A02DE9C249F20A6 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
97C146EE1CF9000F007C117D /* Immich-Debug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Immich-Debug.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
97C146EE1CF9000F007C117D /* Immich-Debug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Immich-Debug.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -105,6 +103,7 @@
|
|||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
A01DD6982F7F43B40049AB63 /* ImageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRequest.swift; sourceTree = "<group>"; };
|
A01DD6982F7F43B40049AB63 /* ImageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRequest.swift; sourceTree = "<group>"; };
|
||||||
|
B1FBA9EE014DE20271B0FE77 /* Pods-ShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
B21E34A92E5AFD210031FDB9 /* BackgroundWorkerApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorkerApiImpl.swift; sourceTree = "<group>"; };
|
B21E34A92E5AFD210031FDB9 /* BackgroundWorkerApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorkerApiImpl.swift; sourceTree = "<group>"; };
|
||||||
B21E34AB2E5B09100031FDB9 /* BackgroundWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorker.swift; sourceTree = "<group>"; };
|
B21E34AB2E5B09100031FDB9 /* BackgroundWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorker.swift; sourceTree = "<group>"; };
|
||||||
B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Connectivity.g.swift; sourceTree = "<group>"; };
|
B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Connectivity.g.swift; sourceTree = "<group>"; };
|
||||||
@@ -112,11 +111,12 @@
|
|||||||
B2EE00012E72CA15008B6CA7 /* PermissionApi.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionApi.g.swift; sourceTree = "<group>"; };
|
B2EE00012E72CA15008B6CA7 /* PermissionApi.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionApi.g.swift; sourceTree = "<group>"; };
|
||||||
B2EE00032E72CA15008B6CA7 /* PermissionApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionApiImpl.swift; sourceTree = "<group>"; };
|
B2EE00032E72CA15008B6CA7 /* PermissionApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionApiImpl.swift; sourceTree = "<group>"; };
|
||||||
B2BE315E2E5E5229006EEF88 /* BackgroundWorker.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorker.g.swift; sourceTree = "<group>"; };
|
B2BE315E2E5E5229006EEF88 /* BackgroundWorker.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorker.g.swift; sourceTree = "<group>"; };
|
||||||
C4A6A71F33CE37B3C913115C /* Pods-ShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
E0E99CDC17B3EB7FA8BA2332 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
CC499FBCE6B29B2DAFED7130 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
F0B57D382DF764BD00DC5BCC /* WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
F0B57D382DF764BD00DC5BCC /* WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||||
F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||||
|
F7101BB0391A314774615E89 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F8A35EA3C3E01BD66AFDE0E5 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
FA9973382CF6DF4B000EF859 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
FA9973382CF6DF4B000EF859 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
FAC6F8902D287C890078CB2F /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
FAC6F8902D287C890078CB2F /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
FAC6F8B12D287F120078CB2F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
FAC6F8B12D287F120078CB2F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
FEE084F82EC172460045228E /* SQLiteData in Frameworks */,
|
FEE084F82EC172460045228E /* SQLiteData in Frameworks */,
|
||||||
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */,
|
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */,
|
||||||
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */,
|
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */,
|
||||||
D3BED739C0BC29BB32E18EB2 /* Pods_Runner.framework in Frameworks */,
|
D218389C4A4C4693F141F7D1 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -216,7 +216,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
467DA6EAF83F3481F8BD94AB /* Pods_ShareExtension.framework in Frameworks */,
|
3B6A31FED0FC846D6BD69BBC /* Pods_ShareExtension.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -226,12 +226,12 @@
|
|||||||
0FB772A5B9601143383626CA /* Pods */ = {
|
0FB772A5B9601143383626CA /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
614A7F5DC5DB09E89E4FCBE8 /* Pods-Runner.debug.xcconfig */,
|
2E3441B73560D0F6FD25E04F /* Pods-Runner.debug.xcconfig */,
|
||||||
6D160F04A389B9FFBC557803 /* Pods-Runner.release.xcconfig */,
|
E0E99CDC17B3EB7FA8BA2332 /* Pods-Runner.release.xcconfig */,
|
||||||
681FBA560D5D2ADDE4F0B59E /* Pods-Runner.profile.xcconfig */,
|
F7101BB0391A314774615E89 /* Pods-Runner.profile.xcconfig */,
|
||||||
937632897A02DE9C249F20A6 /* Pods-ShareExtension.debug.xcconfig */,
|
F8A35EA3C3E01BD66AFDE0E5 /* Pods-ShareExtension.debug.xcconfig */,
|
||||||
10B378D23F917891A0F23E33 /* Pods-ShareExtension.release.xcconfig */,
|
571EAA93D77181C7C98C2EA6 /* Pods-ShareExtension.release.xcconfig */,
|
||||||
C4A6A71F33CE37B3C913115C /* Pods-ShareExtension.profile.xcconfig */,
|
B1FBA9EE014DE20271B0FE77 /* Pods-ShareExtension.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -239,10 +239,10 @@
|
|||||||
1754452DD81DA6620E279E51 /* Frameworks */ = {
|
1754452DD81DA6620E279E51 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */,
|
||||||
|
357FC57E54FD0F51795CF28A /* Pods_ShareExtension.framework */,
|
||||||
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */,
|
F0B57D392DF764BD00DC5BCC /* WidgetKit.framework */,
|
||||||
F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */,
|
F0B57D3B2DF764BD00DC5BCC /* SwiftUI.framework */,
|
||||||
CC499FBCE6B29B2DAFED7130 /* Pods_Runner.framework */,
|
|
||||||
8AB817AA297EDEC88B23F3F6 /* Pods_ShareExtension.framework */,
|
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -370,7 +370,7 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
BAEA01ACA3F5C9CD3D732370 /* [CP] Check Pods Manifest.lock */,
|
4044AF030EF7D8721844FFBA /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
@@ -378,8 +378,8 @@
|
|||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */,
|
FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
513DA7292DED6106813332F4 /* [CP] Embed Pods Frameworks */,
|
D218A34AEE62BC1EF119F5B0 /* [CP] Embed Pods Frameworks */,
|
||||||
2FA39DEC809D6D7C4A01EFCB /* [CP] Copy Pods Resources */,
|
6724EEB7D74949FA08581154 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -393,9 +393,6 @@
|
|||||||
FEE084F22EC172080045228E /* Schemas */,
|
FEE084F22EC172080045228E /* Schemas */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
packageProductDependencies = (
|
|
||||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
|
||||||
);
|
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
productReference = 97C146EE1CF9000F007C117D /* Immich-Debug.app */;
|
productReference = 97C146EE1CF9000F007C117D /* Immich-Debug.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
@@ -424,7 +421,7 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = FAC6F8A02D287C890078CB2F /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
buildConfigurationList = FAC6F8A02D287C890078CB2F /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
8EC9CF3E20AF32BF24D4F3E1 /* [CP] Check Pods Manifest.lock */,
|
3BEF3D71D97E337D921C0EB5 /* [CP] Check Pods Manifest.lock */,
|
||||||
FAC6F88C2D287C890078CB2F /* Sources */,
|
FAC6F88C2D287C890078CB2F /* Sources */,
|
||||||
FAC6F88D2D287C890078CB2F /* Frameworks */,
|
FAC6F88D2D287C890078CB2F /* Frameworks */,
|
||||||
FAC6F88E2D287C890078CB2F /* Resources */,
|
FAC6F88E2D287C890078CB2F /* Resources */,
|
||||||
@@ -473,7 +470,7 @@
|
|||||||
);
|
);
|
||||||
mainGroup = 97C146E51CF9000F007C117D;
|
mainGroup = 97C146E51CF9000F007C117D;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
|
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
|
||||||
FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */,
|
FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */,
|
||||||
FEE084F92EC1725A0045228E /* XCRemoteSwiftPackageReference "swift-http-structured-headers" */,
|
FEE084F92EC1725A0045228E /* XCRemoteSwiftPackageReference "swift-http-structured-headers" */,
|
||||||
);
|
);
|
||||||
@@ -520,23 +517,6 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
2FA39DEC809D6D7C4A01EFCB /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@@ -553,24 +533,7 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
};
|
};
|
||||||
513DA7292DED6106813332F4 /* [CP] Embed Pods Frameworks */ = {
|
3BEF3D71D97E337D921C0EB5 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
8EC9CF3E20AF32BF24D4F3E1 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
@@ -592,22 +555,7 @@
|
|||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
4044AF030EF7D8721844FFBA /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Run Script";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
|
|
||||||
};
|
|
||||||
BAEA01ACA3F5C9CD3D732370 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
@@ -629,6 +577,55 @@
|
|||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
|
6724EEB7D74949FA08581154 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Run Script";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
|
||||||
|
};
|
||||||
|
D218A34AEE62BC1EF119F5B0 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -1095,7 +1092,7 @@
|
|||||||
};
|
};
|
||||||
FAC6F89C2D287C890078CB2F /* Debug */ = {
|
FAC6F89C2D287C890078CB2F /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 937632897A02DE9C249F20A6 /* Pods-ShareExtension.debug.xcconfig */;
|
baseConfigurationReference = F8A35EA3C3E01BD66AFDE0E5 /* Pods-ShareExtension.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
@@ -1138,7 +1135,7 @@
|
|||||||
};
|
};
|
||||||
FAC6F89D2D287C890078CB2F /* Release */ = {
|
FAC6F89D2D287C890078CB2F /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 10B378D23F917891A0F23E33 /* Pods-ShareExtension.release.xcconfig */;
|
baseConfigurationReference = 571EAA93D77181C7C98C2EA6 /* Pods-ShareExtension.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
@@ -1178,7 +1175,7 @@
|
|||||||
};
|
};
|
||||||
FAC6F89E2D287C890078CB2F /* Profile */ = {
|
FAC6F89E2D287C890078CB2F /* Profile */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = C4A6A71F33CE37B3C913115C /* Pods-ShareExtension.profile.xcconfig */;
|
baseConfigurationReference = B1FBA9EE014DE20271B0FE77 /* Pods-ShareExtension.profile.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
@@ -1261,13 +1258,6 @@
|
|||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCLocalSwiftPackageReference section */
|
|
||||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
|
|
||||||
isa = XCLocalSwiftPackageReference;
|
|
||||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
|
||||||
};
|
|
||||||
/* End XCLocalSwiftPackageReference section */
|
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */ = {
|
FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
@@ -1288,10 +1278,6 @@
|
|||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = FlutterGeneratedPluginSwiftPackage;
|
|
||||||
};
|
|
||||||
FEE084F72EC172460045228E /* SQLiteData */ = {
|
FEE084F72EC172460045228E /* SQLiteData */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */;
|
package = FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/pointfreeco/combine-schedulers",
|
"location" : "https://github.com/pointfreeco/combine-schedulers",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6",
|
"revision" : "5928286acce13def418ec36d05a001a9641086f2",
|
||||||
"version" : "1.1.0"
|
"version" : "1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def get_version_from_pubspec
|
|||||||
pubspec = YAML.load_file(pubspec_path)
|
pubspec = YAML.load_file(pubspec_path)
|
||||||
|
|
||||||
version_string = pubspec['version']
|
version_string = pubspec['version']
|
||||||
version_string ? version_string.split('+').first.split('-').first : nil
|
version_string ? version_string.split('+').first : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Helper method to configure code signing for all targets
|
# Helper method to configure code signing for all targets
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import 'package:immich_mobile/domain/models/config/theme_config.dart';
|
|||||||
import 'package:immich_mobile/domain/models/config/timeline_config.dart';
|
import 'package:immich_mobile/domain/models/config/timeline_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/viewer_config.dart';
|
import 'package:immich_mobile/domain/models/config/viewer_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ class AppConfig {
|
|||||||
String toString() =>
|
String toString() =>
|
||||||
'AppConfig(logLevel: $logLevel, theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer, slideshow: $slideshow, album: $album, backup: $backup, network: $network)';
|
'AppConfig(logLevel: $logLevel, theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer, slideshow: $slideshow, album: $album, backup: $backup, network: $network)';
|
||||||
|
|
||||||
T read<T extends Object>(SettingsKey<T> key) =>
|
T read<T extends Object>(MetadataKey<T> key) =>
|
||||||
(switch (key) {
|
(switch (key) {
|
||||||
.logLevel => logLevel,
|
.logLevel => logLevel,
|
||||||
.themePrimaryColor => theme.primaryColor,
|
.themePrimaryColor => theme.primaryColor,
|
||||||
@@ -143,10 +143,10 @@ class AppConfig {
|
|||||||
})
|
})
|
||||||
as T;
|
as T;
|
||||||
|
|
||||||
factory AppConfig.fromEntries(Map<SettingsKey<Object>, Object> overrides) =>
|
factory AppConfig.fromEntries(Map<MetadataKey<Object>, Object> overrides) =>
|
||||||
overrides.entries.fold(const AppConfig(), (config, entry) => config.write(entry.key, entry.value));
|
overrides.entries.fold(const AppConfig(), (config, entry) => config.write(entry.key, entry.value));
|
||||||
|
|
||||||
AppConfig write<T extends Object>(SettingsKey<T> key, T value) {
|
AppConfig write<T extends Object>(MetadataKey<T> key, T value) {
|
||||||
return switch (key) {
|
return switch (key) {
|
||||||
.logLevel => copyWith(logLevel: value as LogLevel),
|
.logLevel => copyWith(logLevel: value as LogLevel),
|
||||||
.themePrimaryColor => copyWith(theme: theme.copyWith(primaryColor: value as ImmichColorPreset)),
|
.themePrimaryColor => copyWith(theme: theme.copyWith(primaryColor: value as ImmichColorPreset)),
|
||||||
|
|||||||
+18
-18
@@ -7,7 +7,7 @@ import 'package:immich_mobile/domain/models/log.model.dart';
|
|||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
||||||
|
|
||||||
enum SettingsKey<T extends Object> {
|
enum MetadataKey<T extends Object> {
|
||||||
// Theme
|
// Theme
|
||||||
themePrimaryColor<ImmichColorPreset>(codec: _EnumCodec(ImmichColorPreset.values)),
|
themePrimaryColor<ImmichColorPreset>(codec: _EnumCodec(ImmichColorPreset.values)),
|
||||||
themeMode<ThemeMode>(codec: _EnumCodec(ThemeMode.values)),
|
themeMode<ThemeMode>(codec: _EnumCodec(ThemeMode.values)),
|
||||||
@@ -73,24 +73,24 @@ enum SettingsKey<T extends Object> {
|
|||||||
slideshowLook<SlideshowLook>(codec: _EnumCodec(SlideshowLook.values)),
|
slideshowLook<SlideshowLook>(codec: _EnumCodec(SlideshowLook.values)),
|
||||||
slideshowDirection<SlideshowDirection>(codec: _EnumCodec(SlideshowDirection.values));
|
slideshowDirection<SlideshowDirection>(codec: _EnumCodec(SlideshowDirection.values));
|
||||||
|
|
||||||
final _SettingsCodec<T>? _codecOverride;
|
final _MetadataCodec<T>? _codecOverride;
|
||||||
|
|
||||||
const SettingsKey({_SettingsCodec<T>? codec}) : _codecOverride = codec;
|
const MetadataKey({_MetadataCodec<T>? codec}) : _codecOverride = codec;
|
||||||
|
|
||||||
_SettingsCodec<T> get _codec => _codecOverride ?? _SettingsCodec.forType(T);
|
_MetadataCodec<T> get _codec => _codecOverride ?? _MetadataCodec.forType(T);
|
||||||
|
|
||||||
String encode(T value) => _codec.encode(value);
|
String encode(T value) => _codec.encode(value);
|
||||||
|
|
||||||
T decode(String raw) => _codec.decode(raw);
|
T decode(String raw) => _codec.decode(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _SettingsCodec<T extends Object> {
|
sealed class _MetadataCodec<T extends Object> {
|
||||||
const _SettingsCodec();
|
const _MetadataCodec();
|
||||||
|
|
||||||
String encode(T value);
|
String encode(T value);
|
||||||
T decode(String raw);
|
T decode(String raw);
|
||||||
|
|
||||||
static const Map<Type, _SettingsCodec<Object>> _primitives = {
|
static const Map<Type, _MetadataCodec<Object>> _primitives = {
|
||||||
int: _PrimitiveCodec.integer,
|
int: _PrimitiveCodec.integer,
|
||||||
double: _PrimitiveCodec.real,
|
double: _PrimitiveCodec.real,
|
||||||
bool: _PrimitiveCodec.boolean,
|
bool: _PrimitiveCodec.boolean,
|
||||||
@@ -98,16 +98,16 @@ sealed class _SettingsCodec<T extends Object> {
|
|||||||
DateTime: _DateTimeCodec(),
|
DateTime: _DateTimeCodec(),
|
||||||
};
|
};
|
||||||
|
|
||||||
static _SettingsCodec<T> forType<T extends Object>(Type runtimeType) {
|
static _MetadataCodec<T> forType<T extends Object>(Type runtimeType) {
|
||||||
final codec = _primitives[runtimeType];
|
final codec = _primitives[runtimeType];
|
||||||
if (codec == null) {
|
if (codec == null) {
|
||||||
throw StateError('No primitive codec for $runtimeType. Provide an explicit codec when defining the SettingsKey.');
|
throw StateError('No primitive codec for $runtimeType. Provide an explicit codec when defining the MetadataKey.');
|
||||||
}
|
}
|
||||||
return codec as _SettingsCodec<T>;
|
return codec as _MetadataCodec<T>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class _EnumCodec<T extends Enum> extends _SettingsCodec<T> {
|
final class _EnumCodec<T extends Enum> extends _MetadataCodec<T> {
|
||||||
final List<T> values;
|
final List<T> values;
|
||||||
|
|
||||||
const _EnumCodec(this.values);
|
const _EnumCodec(this.values);
|
||||||
@@ -119,7 +119,7 @@ final class _EnumCodec<T extends Enum> extends _SettingsCodec<T> {
|
|||||||
T decode(String raw) => values.firstWhere((v) => v.name == raw);
|
T decode(String raw) => values.firstWhere((v) => v.name == raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
final class _DateTimeCodec extends _SettingsCodec<DateTime> {
|
final class _DateTimeCodec extends _MetadataCodec<DateTime> {
|
||||||
const _DateTimeCodec();
|
const _DateTimeCodec();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -129,9 +129,9 @@ final class _DateTimeCodec extends _SettingsCodec<DateTime> {
|
|||||||
DateTime decode(String raw) => DateTime.parse(raw);
|
DateTime decode(String raw) => DateTime.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
final class _MapCodec<K extends Object, V extends Object> extends _SettingsCodec<Map<K, V>> {
|
final class _MapCodec<K extends Object, V extends Object> extends _MetadataCodec<Map<K, V>> {
|
||||||
final _SettingsCodec<K> _keyCodec;
|
final _MetadataCodec<K> _keyCodec;
|
||||||
final _SettingsCodec<V> _valueCodec;
|
final _MetadataCodec<V> _valueCodec;
|
||||||
|
|
||||||
const _MapCodec(this._keyCodec, this._valueCodec);
|
const _MapCodec(this._keyCodec, this._valueCodec);
|
||||||
|
|
||||||
@@ -167,8 +167,8 @@ final class _MapCodec<K extends Object, V extends Object> extends _SettingsCodec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class _ListCodec<T extends Object> extends _SettingsCodec<List<T>> {
|
final class _ListCodec<T extends Object> extends _MetadataCodec<List<T>> {
|
||||||
final _SettingsCodec<T> _elementCodec;
|
final _MetadataCodec<T> _elementCodec;
|
||||||
|
|
||||||
const _ListCodec(this._elementCodec);
|
const _ListCodec(this._elementCodec);
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ final class _ListCodec<T extends Object> extends _SettingsCodec<List<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class _PrimitiveCodec<T extends Object> extends _SettingsCodec<T> {
|
final class _PrimitiveCodec<T extends Object> extends _MetadataCodec<T> {
|
||||||
final T Function(String) _parse;
|
final T Function(String) _parse;
|
||||||
|
|
||||||
const _PrimitiveCodec._(this._parse);
|
const _PrimitiveCodec._(this._parse);
|
||||||
@@ -11,7 +11,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
import 'package:immich_mobile/extensions/platform_extensions.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/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
||||||
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
|
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
@@ -39,7 +39,7 @@ class BackgroundWorkerFgService {
|
|||||||
_foregroundHostApi.saveNotificationMessage(title, body);
|
_foregroundHostApi.saveNotificationMessage(title, body);
|
||||||
|
|
||||||
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) {
|
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) {
|
||||||
final backup = SettingsRepository.instance.appConfig.backup;
|
final backup = MetadataRepository.instance.appConfig.backup;
|
||||||
return _foregroundHostApi.configure(
|
return _foregroundHostApi.configure(
|
||||||
BackgroundWorkerSettings(
|
BackgroundWorkerSettings(
|
||||||
minimumDelaySeconds: minimumDelaySeconds ?? backup.triggerDelay,
|
minimumDelaySeconds: minimumDelaySeconds ?? backup.triggerDelay,
|
||||||
@@ -67,7 +67,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
BackgroundWorkerFlutterApi.setUp(this);
|
BackgroundWorkerFlutterApi.setUp(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get _isBackupEnabled => SettingsRepository.instance.appConfig.backup.enabled;
|
bool get _isBackupEnabled => MetadataRepository.instance.appConfig.backup.enabled;
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:immich_mobile/constants/constants.dart';
|
import 'package:immich_mobile/constants/constants.dart';
|
||||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/log.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/log.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
@@ -12,10 +12,10 @@ import 'package:logging/logging.dart';
|
|||||||
///
|
///
|
||||||
/// It listens to Dart's [Logger.root], buffers logs in memory (optionally),
|
/// It listens to Dart's [Logger.root], buffers logs in memory (optionally),
|
||||||
/// writes them to a persistent [LogRepository], and manages log levels via
|
/// writes them to a persistent [LogRepository], and manages log levels via
|
||||||
/// [SettingsRepository].
|
/// [MetadataRepository].
|
||||||
class LogService {
|
class LogService {
|
||||||
final LogRepository _logRepository;
|
final LogRepository _logRepository;
|
||||||
final SettingsRepository _settingsRepository;
|
final MetadataRepository _metadataRepository;
|
||||||
|
|
||||||
final List<LogMessage> _msgBuffer = [];
|
final List<LogMessage> _msgBuffer = [];
|
||||||
|
|
||||||
@@ -38,12 +38,12 @@ class LogService {
|
|||||||
|
|
||||||
static Future<LogService> init({
|
static Future<LogService> init({
|
||||||
required LogRepository logRepository,
|
required LogRepository logRepository,
|
||||||
required SettingsRepository settingsRepository,
|
required MetadataRepository metadataRepository,
|
||||||
bool shouldBuffer = true,
|
bool shouldBuffer = true,
|
||||||
}) async {
|
}) async {
|
||||||
_instance ??= await create(
|
_instance ??= await create(
|
||||||
logRepository: logRepository,
|
logRepository: logRepository,
|
||||||
settingsRepository: settingsRepository,
|
metadataRepository: metadataRepository,
|
||||||
shouldBuffer: shouldBuffer,
|
shouldBuffer: shouldBuffer,
|
||||||
);
|
);
|
||||||
return _instance!;
|
return _instance!;
|
||||||
@@ -51,17 +51,17 @@ class LogService {
|
|||||||
|
|
||||||
static Future<LogService> create({
|
static Future<LogService> create({
|
||||||
required LogRepository logRepository,
|
required LogRepository logRepository,
|
||||||
required SettingsRepository settingsRepository,
|
required MetadataRepository metadataRepository,
|
||||||
bool shouldBuffer = true,
|
bool shouldBuffer = true,
|
||||||
}) async {
|
}) async {
|
||||||
final instance = LogService._(logRepository, settingsRepository, shouldBuffer);
|
final instance = LogService._(logRepository, metadataRepository, shouldBuffer);
|
||||||
await logRepository.truncate(limit: kLogTruncateLimit);
|
await logRepository.truncate(limit: kLogTruncateLimit);
|
||||||
final level = instance._settingsRepository.appConfig.logLevel;
|
final level = instance._metadataRepository.appConfig.logLevel;
|
||||||
Logger.root.level = Level.LEVELS.elementAtOrNull(level.index) ?? Level.INFO;
|
Logger.root.level = Level.LEVELS.elementAtOrNull(level.index) ?? Level.INFO;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogService._(this._logRepository, this._settingsRepository, this._shouldBuffer) {
|
LogService._(this._logRepository, this._metadataRepository, this._shouldBuffer) {
|
||||||
_logSubscription = Logger.root.onRecord.listen(_handleLogRecord);
|
_logSubscription = Logger.root.onRecord.listen(_handleLogRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ class LogService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setLogLevel(LogLevel level) async {
|
Future<void> setLogLevel(LogLevel level) async {
|
||||||
await _settingsRepository.write(SettingsKey.logLevel, level);
|
await _metadataRepository.write(MetadataKey.logLevel, level);
|
||||||
Logger.root.level = level.toLevel();
|
Logger.root.level = level.toLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,30 +192,43 @@ class RemoteAlbumService {
|
|||||||
required UserDto uploader,
|
required UserDto uploader,
|
||||||
required AlbumAssetCandidates candidates,
|
required AlbumAssetCandidates candidates,
|
||||||
UploadCallbacks uploadCallbacks = const UploadCallbacks(),
|
UploadCallbacks uploadCallbacks = const UploadCallbacks(),
|
||||||
Completer<void>? cancelToken,
|
|
||||||
}) async {
|
}) async {
|
||||||
int addedCount = 0;
|
int addedCount = 0;
|
||||||
if (candidates.remoteAssetIds.isNotEmpty) {
|
if (candidates.remoteAssetIds.isNotEmpty) {
|
||||||
addedCount += await addAssets(albumId: albumId, assetIds: candidates.remoteAssetIds);
|
addedCount += await addAssets(albumId: albumId, assetIds: candidates.remoteAssetIds);
|
||||||
}
|
}
|
||||||
if (candidates.localAssetsToUpload.isNotEmpty) {
|
if (candidates.localAssetsToUpload.isNotEmpty) {
|
||||||
addedCount += await _uploadAndAddLocals(
|
addedCount += await _uploadAndAddLocals(albumId, uploader, candidates.localAssetsToUpload, uploadCallbacks);
|
||||||
albumId,
|
|
||||||
uploader,
|
|
||||||
candidates.localAssetsToUpload,
|
|
||||||
uploadCallbacks,
|
|
||||||
cancelToken,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return addedCount;
|
return addedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an album, seeding it with already-remote asset IDs, then uploads
|
||||||
|
/// local-only assets and links each one as it finishes.
|
||||||
|
Future<RemoteAlbum> createAlbumWithAssets({
|
||||||
|
required String title,
|
||||||
|
required UserDto owner,
|
||||||
|
String? description,
|
||||||
|
AlbumAssetCandidates candidates = const AlbumAssetCandidates(remoteAssetIds: [], localAssetsToUpload: []),
|
||||||
|
UploadCallbacks uploadCallbacks = const UploadCallbacks(),
|
||||||
|
}) async {
|
||||||
|
final album = await createAlbum(
|
||||||
|
title: title,
|
||||||
|
owner: owner,
|
||||||
|
description: description,
|
||||||
|
assetIds: candidates.remoteAssetIds,
|
||||||
|
);
|
||||||
|
if (candidates.localAssetsToUpload.isNotEmpty) {
|
||||||
|
await _uploadAndAddLocals(album.id, owner, candidates.localAssetsToUpload, uploadCallbacks);
|
||||||
|
}
|
||||||
|
return album;
|
||||||
|
}
|
||||||
|
|
||||||
Future<int> _uploadAndAddLocals(
|
Future<int> _uploadAndAddLocals(
|
||||||
String albumId,
|
String albumId,
|
||||||
UserDto uploader,
|
UserDto uploader,
|
||||||
List<LocalAsset> localAssets,
|
List<LocalAsset> localAssets,
|
||||||
UploadCallbacks userCallbacks,
|
UploadCallbacks userCallbacks,
|
||||||
Completer<void>? cancelToken,
|
|
||||||
) async {
|
) async {
|
||||||
int addedCount = 0;
|
int addedCount = 0;
|
||||||
final pendingAdds = <Future<void>>[];
|
final pendingAdds = <Future<void>>[];
|
||||||
@@ -245,7 +258,7 @@ class RemoteAlbumService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pendingAdds.add(
|
pendingAdds.add(
|
||||||
linkUploadedAssetToAlbum(albumId, remoteId, uploader, source)
|
_linkUploadedAssetToAlbum(albumId, remoteId, uploader, source)
|
||||||
.then<void>((added) {
|
.then<void>((added) {
|
||||||
addedCount += added;
|
addedCount += added;
|
||||||
})
|
})
|
||||||
@@ -256,7 +269,7 @@ class RemoteAlbumService {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await _uploadService.uploadManual(localAssets, callbacks: wrappedCallbacks, cancelToken: cancelToken);
|
await _uploadService.uploadManual(localAssets, callbacks: wrappedCallbacks);
|
||||||
await Future.wait(pendingAdds);
|
await Future.wait(pendingAdds);
|
||||||
return addedCount;
|
return addedCount;
|
||||||
}
|
}
|
||||||
@@ -275,7 +288,7 @@ class RemoteAlbumService {
|
|||||||
/// `remote_asset_entity` row from the local source so the FK-protected
|
/// `remote_asset_entity` row from the local source so the FK-protected
|
||||||
/// junction insert succeeds. Sync overwrites the placeholder later with
|
/// junction insert succeeds. Sync overwrites the placeholder later with
|
||||||
/// the authoritative server data.
|
/// the authoritative server data.
|
||||||
Future<int> linkUploadedAssetToAlbum(String albumId, String remoteId, UserDto uploader, LocalAsset source) async {
|
Future<int> _linkUploadedAssetToAlbum(String albumId, String remoteId, UserDto uploader, LocalAsset source) async {
|
||||||
final result = await _albumApiRepository.addAssets(albumId, [remoteId]);
|
final result = await _albumApiRepository.addAssets(albumId, [remoteId]);
|
||||||
if (result.added.isEmpty) {
|
if (result.added.isEmpty) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|||||||
import 'package:immich_mobile/domain/models/events.model.dart';
|
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||||
import 'package:immich_mobile/utils/async_mutex.dart';
|
import 'package:immich_mobile/utils/async_mutex.dart';
|
||||||
|
|
||||||
@@ -39,12 +39,12 @@ enum TimelineOrigin {
|
|||||||
|
|
||||||
class TimelineFactory {
|
class TimelineFactory {
|
||||||
final DriftTimelineRepository _timelineRepository;
|
final DriftTimelineRepository _timelineRepository;
|
||||||
final SettingsRepository _settingsRepository;
|
final MetadataRepository _metadataRepository;
|
||||||
|
|
||||||
const TimelineFactory({required this._timelineRepository, required this._settingsRepository});
|
const TimelineFactory({required this._timelineRepository, required this._metadataRepository});
|
||||||
|
|
||||||
GroupAssetsBy get groupBy {
|
GroupAssetsBy get groupBy {
|
||||||
final group = _settingsRepository.appConfig.timeline.groupAssetsBy;
|
final group = _metadataRepository.appConfig.timeline.groupAssetsBy;
|
||||||
// We do not support auto grouping in the new timeline yet, fallback to day grouping
|
// We do not support auto grouping in the new timeline yet, fallback to day grouping
|
||||||
return group == GroupAssetsBy.auto ? GroupAssetsBy.day : group;
|
return group == GroupAssetsBy.auto ? GroupAssetsBy.day : group;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
|
||||||
class SettingsEntity extends Table with DriftDefaultsMixin {
|
class MetadataEntity extends Table with DriftDefaultsMixin {
|
||||||
const SettingsEntity();
|
const MetadataEntity();
|
||||||
|
|
||||||
TextColumn get key => text()();
|
TextColumn get key => text()();
|
||||||
|
|
||||||
@@ -14,5 +14,5 @@ class SettingsEntity extends Table with DriftDefaultsMixin {
|
|||||||
Set<Column> get primaryKey => {key};
|
Set<Column> get primaryKey => {key};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get tableName => "settings";
|
String get tableName => "metadata";
|
||||||
}
|
}
|
||||||
+74
-74
@@ -1,28 +1,28 @@
|
|||||||
// dart format width=80
|
// dart format width=80
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
import 'package:drift/drift.dart' as i0;
|
import 'package:drift/drift.dart' as i0;
|
||||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/metadata.entity.drift.dart'
|
||||||
as i1;
|
as i1;
|
||||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.dart'
|
import 'package:immich_mobile/infrastructure/entities/metadata.entity.dart'
|
||||||
as i2;
|
as i2;
|
||||||
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
|
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
|
||||||
|
|
||||||
typedef $$SettingsEntityTableCreateCompanionBuilder =
|
typedef $$MetadataEntityTableCreateCompanionBuilder =
|
||||||
i1.SettingsEntityCompanion Function({
|
i1.MetadataEntityCompanion Function({
|
||||||
required String key,
|
required String key,
|
||||||
required String value,
|
required String value,
|
||||||
i0.Value<DateTime> updatedAt,
|
i0.Value<DateTime> updatedAt,
|
||||||
});
|
});
|
||||||
typedef $$SettingsEntityTableUpdateCompanionBuilder =
|
typedef $$MetadataEntityTableUpdateCompanionBuilder =
|
||||||
i1.SettingsEntityCompanion Function({
|
i1.MetadataEntityCompanion Function({
|
||||||
i0.Value<String> key,
|
i0.Value<String> key,
|
||||||
i0.Value<String> value,
|
i0.Value<String> value,
|
||||||
i0.Value<DateTime> updatedAt,
|
i0.Value<DateTime> updatedAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
class $$SettingsEntityTableFilterComposer
|
class $$MetadataEntityTableFilterComposer
|
||||||
extends i0.Composer<i0.GeneratedDatabase, i1.$SettingsEntityTable> {
|
extends i0.Composer<i0.GeneratedDatabase, i1.$MetadataEntityTable> {
|
||||||
$$SettingsEntityTableFilterComposer({
|
$$MetadataEntityTableFilterComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
super.joinBuilder,
|
super.joinBuilder,
|
||||||
@@ -45,9 +45,9 @@ class $$SettingsEntityTableFilterComposer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SettingsEntityTableOrderingComposer
|
class $$MetadataEntityTableOrderingComposer
|
||||||
extends i0.Composer<i0.GeneratedDatabase, i1.$SettingsEntityTable> {
|
extends i0.Composer<i0.GeneratedDatabase, i1.$MetadataEntityTable> {
|
||||||
$$SettingsEntityTableOrderingComposer({
|
$$MetadataEntityTableOrderingComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
super.joinBuilder,
|
super.joinBuilder,
|
||||||
@@ -70,9 +70,9 @@ class $$SettingsEntityTableOrderingComposer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SettingsEntityTableAnnotationComposer
|
class $$MetadataEntityTableAnnotationComposer
|
||||||
extends i0.Composer<i0.GeneratedDatabase, i1.$SettingsEntityTable> {
|
extends i0.Composer<i0.GeneratedDatabase, i1.$MetadataEntityTable> {
|
||||||
$$SettingsEntityTableAnnotationComposer({
|
$$MetadataEntityTableAnnotationComposer({
|
||||||
required super.$db,
|
required super.$db,
|
||||||
required super.$table,
|
required super.$table,
|
||||||
super.joinBuilder,
|
super.joinBuilder,
|
||||||
@@ -89,47 +89,47 @@ class $$SettingsEntityTableAnnotationComposer
|
|||||||
$composableBuilder(column: $table.updatedAt, builder: (column) => column);
|
$composableBuilder(column: $table.updatedAt, builder: (column) => column);
|
||||||
}
|
}
|
||||||
|
|
||||||
class $$SettingsEntityTableTableManager
|
class $$MetadataEntityTableTableManager
|
||||||
extends
|
extends
|
||||||
i0.RootTableManager<
|
i0.RootTableManager<
|
||||||
i0.GeneratedDatabase,
|
i0.GeneratedDatabase,
|
||||||
i1.$SettingsEntityTable,
|
i1.$MetadataEntityTable,
|
||||||
i1.SettingsEntityData,
|
i1.MetadataEntityData,
|
||||||
i1.$$SettingsEntityTableFilterComposer,
|
i1.$$MetadataEntityTableFilterComposer,
|
||||||
i1.$$SettingsEntityTableOrderingComposer,
|
i1.$$MetadataEntityTableOrderingComposer,
|
||||||
i1.$$SettingsEntityTableAnnotationComposer,
|
i1.$$MetadataEntityTableAnnotationComposer,
|
||||||
$$SettingsEntityTableCreateCompanionBuilder,
|
$$MetadataEntityTableCreateCompanionBuilder,
|
||||||
$$SettingsEntityTableUpdateCompanionBuilder,
|
$$MetadataEntityTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
i1.SettingsEntityData,
|
i1.MetadataEntityData,
|
||||||
i0.BaseReferences<
|
i0.BaseReferences<
|
||||||
i0.GeneratedDatabase,
|
i0.GeneratedDatabase,
|
||||||
i1.$SettingsEntityTable,
|
i1.$MetadataEntityTable,
|
||||||
i1.SettingsEntityData
|
i1.MetadataEntityData
|
||||||
>,
|
>,
|
||||||
),
|
),
|
||||||
i1.SettingsEntityData,
|
i1.MetadataEntityData,
|
||||||
i0.PrefetchHooks Function()
|
i0.PrefetchHooks Function()
|
||||||
> {
|
> {
|
||||||
$$SettingsEntityTableTableManager(
|
$$MetadataEntityTableTableManager(
|
||||||
i0.GeneratedDatabase db,
|
i0.GeneratedDatabase db,
|
||||||
i1.$SettingsEntityTable table,
|
i1.$MetadataEntityTable table,
|
||||||
) : super(
|
) : super(
|
||||||
i0.TableManagerState(
|
i0.TableManagerState(
|
||||||
db: db,
|
db: db,
|
||||||
table: table,
|
table: table,
|
||||||
createFilteringComposer: () =>
|
createFilteringComposer: () =>
|
||||||
i1.$$SettingsEntityTableFilterComposer($db: db, $table: table),
|
i1.$$MetadataEntityTableFilterComposer($db: db, $table: table),
|
||||||
createOrderingComposer: () =>
|
createOrderingComposer: () =>
|
||||||
i1.$$SettingsEntityTableOrderingComposer($db: db, $table: table),
|
i1.$$MetadataEntityTableOrderingComposer($db: db, $table: table),
|
||||||
createComputedFieldComposer: () => i1
|
createComputedFieldComposer: () => i1
|
||||||
.$$SettingsEntityTableAnnotationComposer($db: db, $table: table),
|
.$$MetadataEntityTableAnnotationComposer($db: db, $table: table),
|
||||||
updateCompanionCallback:
|
updateCompanionCallback:
|
||||||
({
|
({
|
||||||
i0.Value<String> key = const i0.Value.absent(),
|
i0.Value<String> key = const i0.Value.absent(),
|
||||||
i0.Value<String> value = const i0.Value.absent(),
|
i0.Value<String> value = const i0.Value.absent(),
|
||||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||||
}) => i1.SettingsEntityCompanion(
|
}) => i1.MetadataEntityCompanion(
|
||||||
key: key,
|
key: key,
|
||||||
value: value,
|
value: value,
|
||||||
updatedAt: updatedAt,
|
updatedAt: updatedAt,
|
||||||
@@ -139,7 +139,7 @@ class $$SettingsEntityTableTableManager
|
|||||||
required String key,
|
required String key,
|
||||||
required String value,
|
required String value,
|
||||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||||
}) => i1.SettingsEntityCompanion.insert(
|
}) => i1.MetadataEntityCompanion.insert(
|
||||||
key: key,
|
key: key,
|
||||||
value: value,
|
value: value,
|
||||||
updatedAt: updatedAt,
|
updatedAt: updatedAt,
|
||||||
@@ -152,34 +152,34 @@ class $$SettingsEntityTableTableManager
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef $$SettingsEntityTableProcessedTableManager =
|
typedef $$MetadataEntityTableProcessedTableManager =
|
||||||
i0.ProcessedTableManager<
|
i0.ProcessedTableManager<
|
||||||
i0.GeneratedDatabase,
|
i0.GeneratedDatabase,
|
||||||
i1.$SettingsEntityTable,
|
i1.$MetadataEntityTable,
|
||||||
i1.SettingsEntityData,
|
i1.MetadataEntityData,
|
||||||
i1.$$SettingsEntityTableFilterComposer,
|
i1.$$MetadataEntityTableFilterComposer,
|
||||||
i1.$$SettingsEntityTableOrderingComposer,
|
i1.$$MetadataEntityTableOrderingComposer,
|
||||||
i1.$$SettingsEntityTableAnnotationComposer,
|
i1.$$MetadataEntityTableAnnotationComposer,
|
||||||
$$SettingsEntityTableCreateCompanionBuilder,
|
$$MetadataEntityTableCreateCompanionBuilder,
|
||||||
$$SettingsEntityTableUpdateCompanionBuilder,
|
$$MetadataEntityTableUpdateCompanionBuilder,
|
||||||
(
|
(
|
||||||
i1.SettingsEntityData,
|
i1.MetadataEntityData,
|
||||||
i0.BaseReferences<
|
i0.BaseReferences<
|
||||||
i0.GeneratedDatabase,
|
i0.GeneratedDatabase,
|
||||||
i1.$SettingsEntityTable,
|
i1.$MetadataEntityTable,
|
||||||
i1.SettingsEntityData
|
i1.MetadataEntityData
|
||||||
>,
|
>,
|
||||||
),
|
),
|
||||||
i1.SettingsEntityData,
|
i1.MetadataEntityData,
|
||||||
i0.PrefetchHooks Function()
|
i0.PrefetchHooks Function()
|
||||||
>;
|
>;
|
||||||
|
|
||||||
class $SettingsEntityTable extends i2.SettingsEntity
|
class $MetadataEntityTable extends i2.MetadataEntity
|
||||||
with i0.TableInfo<$SettingsEntityTable, i1.SettingsEntityData> {
|
with i0.TableInfo<$MetadataEntityTable, i1.MetadataEntityData> {
|
||||||
@override
|
@override
|
||||||
final i0.GeneratedDatabase attachedDatabase;
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
final String? _alias;
|
final String? _alias;
|
||||||
$SettingsEntityTable(this.attachedDatabase, [this._alias]);
|
$MetadataEntityTable(this.attachedDatabase, [this._alias]);
|
||||||
static const i0.VerificationMeta _keyMeta = const i0.VerificationMeta('key');
|
static const i0.VerificationMeta _keyMeta = const i0.VerificationMeta('key');
|
||||||
@override
|
@override
|
||||||
late final i0.GeneratedColumn<String> key = i0.GeneratedColumn<String>(
|
late final i0.GeneratedColumn<String> key = i0.GeneratedColumn<String>(
|
||||||
@@ -219,10 +219,10 @@ class $SettingsEntityTable extends i2.SettingsEntity
|
|||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
@override
|
@override
|
||||||
String get actualTableName => $name;
|
String get actualTableName => $name;
|
||||||
static const String $name = 'settings';
|
static const String $name = 'metadata';
|
||||||
@override
|
@override
|
||||||
i0.VerificationContext validateIntegrity(
|
i0.VerificationContext validateIntegrity(
|
||||||
i0.Insertable<i1.SettingsEntityData> instance, {
|
i0.Insertable<i1.MetadataEntityData> instance, {
|
||||||
bool isInserting = false,
|
bool isInserting = false,
|
||||||
}) {
|
}) {
|
||||||
final context = i0.VerificationContext();
|
final context = i0.VerificationContext();
|
||||||
@@ -255,9 +255,9 @@ class $SettingsEntityTable extends i2.SettingsEntity
|
|||||||
@override
|
@override
|
||||||
Set<i0.GeneratedColumn> get $primaryKey => {key};
|
Set<i0.GeneratedColumn> get $primaryKey => {key};
|
||||||
@override
|
@override
|
||||||
i1.SettingsEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
i1.MetadataEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
return i1.SettingsEntityData(
|
return i1.MetadataEntityData(
|
||||||
key: attachedDatabase.typeMapping.read(
|
key: attachedDatabase.typeMapping.read(
|
||||||
i0.DriftSqlType.string,
|
i0.DriftSqlType.string,
|
||||||
data['${effectivePrefix}key'],
|
data['${effectivePrefix}key'],
|
||||||
@@ -274,8 +274,8 @@ class $SettingsEntityTable extends i2.SettingsEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
$SettingsEntityTable createAlias(String alias) {
|
$MetadataEntityTable createAlias(String alias) {
|
||||||
return $SettingsEntityTable(attachedDatabase, alias);
|
return $MetadataEntityTable(attachedDatabase, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -284,12 +284,12 @@ class $SettingsEntityTable extends i2.SettingsEntity
|
|||||||
bool get isStrict => true;
|
bool get isStrict => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsEntityData extends i0.DataClass
|
class MetadataEntityData extends i0.DataClass
|
||||||
implements i0.Insertable<i1.SettingsEntityData> {
|
implements i0.Insertable<i1.MetadataEntityData> {
|
||||||
final String key;
|
final String key;
|
||||||
final String value;
|
final String value;
|
||||||
final DateTime updatedAt;
|
final DateTime updatedAt;
|
||||||
const SettingsEntityData({
|
const MetadataEntityData({
|
||||||
required this.key,
|
required this.key,
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.updatedAt,
|
required this.updatedAt,
|
||||||
@@ -303,12 +303,12 @@ class SettingsEntityData extends i0.DataClass
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
factory SettingsEntityData.fromJson(
|
factory MetadataEntityData.fromJson(
|
||||||
Map<String, dynamic> json, {
|
Map<String, dynamic> json, {
|
||||||
i0.ValueSerializer? serializer,
|
i0.ValueSerializer? serializer,
|
||||||
}) {
|
}) {
|
||||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
return SettingsEntityData(
|
return MetadataEntityData(
|
||||||
key: serializer.fromJson<String>(json['key']),
|
key: serializer.fromJson<String>(json['key']),
|
||||||
value: serializer.fromJson<String>(json['value']),
|
value: serializer.fromJson<String>(json['value']),
|
||||||
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
||||||
@@ -324,17 +324,17 @@ class SettingsEntityData extends i0.DataClass
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
i1.SettingsEntityData copyWith({
|
i1.MetadataEntityData copyWith({
|
||||||
String? key,
|
String? key,
|
||||||
String? value,
|
String? value,
|
||||||
DateTime? updatedAt,
|
DateTime? updatedAt,
|
||||||
}) => i1.SettingsEntityData(
|
}) => i1.MetadataEntityData(
|
||||||
key: key ?? this.key,
|
key: key ?? this.key,
|
||||||
value: value ?? this.value,
|
value: value ?? this.value,
|
||||||
updatedAt: updatedAt ?? this.updatedAt,
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
);
|
);
|
||||||
SettingsEntityData copyWithCompanion(i1.SettingsEntityCompanion data) {
|
MetadataEntityData copyWithCompanion(i1.MetadataEntityCompanion data) {
|
||||||
return SettingsEntityData(
|
return MetadataEntityData(
|
||||||
key: data.key.present ? data.key.value : this.key,
|
key: data.key.present ? data.key.value : this.key,
|
||||||
value: data.value.present ? data.value.value : this.value,
|
value: data.value.present ? data.value.value : this.value,
|
||||||
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
|
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
|
||||||
@@ -343,7 +343,7 @@ class SettingsEntityData extends i0.DataClass
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('SettingsEntityData(')
|
return (StringBuffer('MetadataEntityData(')
|
||||||
..write('key: $key, ')
|
..write('key: $key, ')
|
||||||
..write('value: $value, ')
|
..write('value: $value, ')
|
||||||
..write('updatedAt: $updatedAt')
|
..write('updatedAt: $updatedAt')
|
||||||
@@ -356,29 +356,29 @@ class SettingsEntityData extends i0.DataClass
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
(other is i1.SettingsEntityData &&
|
(other is i1.MetadataEntityData &&
|
||||||
other.key == this.key &&
|
other.key == this.key &&
|
||||||
other.value == this.value &&
|
other.value == this.value &&
|
||||||
other.updatedAt == this.updatedAt);
|
other.updatedAt == this.updatedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsEntityCompanion
|
class MetadataEntityCompanion
|
||||||
extends i0.UpdateCompanion<i1.SettingsEntityData> {
|
extends i0.UpdateCompanion<i1.MetadataEntityData> {
|
||||||
final i0.Value<String> key;
|
final i0.Value<String> key;
|
||||||
final i0.Value<String> value;
|
final i0.Value<String> value;
|
||||||
final i0.Value<DateTime> updatedAt;
|
final i0.Value<DateTime> updatedAt;
|
||||||
const SettingsEntityCompanion({
|
const MetadataEntityCompanion({
|
||||||
this.key = const i0.Value.absent(),
|
this.key = const i0.Value.absent(),
|
||||||
this.value = const i0.Value.absent(),
|
this.value = const i0.Value.absent(),
|
||||||
this.updatedAt = const i0.Value.absent(),
|
this.updatedAt = const i0.Value.absent(),
|
||||||
});
|
});
|
||||||
SettingsEntityCompanion.insert({
|
MetadataEntityCompanion.insert({
|
||||||
required String key,
|
required String key,
|
||||||
required String value,
|
required String value,
|
||||||
this.updatedAt = const i0.Value.absent(),
|
this.updatedAt = const i0.Value.absent(),
|
||||||
}) : key = i0.Value(key),
|
}) : key = i0.Value(key),
|
||||||
value = i0.Value(value);
|
value = i0.Value(value);
|
||||||
static i0.Insertable<i1.SettingsEntityData> custom({
|
static i0.Insertable<i1.MetadataEntityData> custom({
|
||||||
i0.Expression<String>? key,
|
i0.Expression<String>? key,
|
||||||
i0.Expression<String>? value,
|
i0.Expression<String>? value,
|
||||||
i0.Expression<DateTime>? updatedAt,
|
i0.Expression<DateTime>? updatedAt,
|
||||||
@@ -390,12 +390,12 @@ class SettingsEntityCompanion
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
i1.SettingsEntityCompanion copyWith({
|
i1.MetadataEntityCompanion copyWith({
|
||||||
i0.Value<String>? key,
|
i0.Value<String>? key,
|
||||||
i0.Value<String>? value,
|
i0.Value<String>? value,
|
||||||
i0.Value<DateTime>? updatedAt,
|
i0.Value<DateTime>? updatedAt,
|
||||||
}) {
|
}) {
|
||||||
return i1.SettingsEntityCompanion(
|
return i1.MetadataEntityCompanion(
|
||||||
key: key ?? this.key,
|
key: key ?? this.key,
|
||||||
value: value ?? this.value,
|
value: value ?? this.value,
|
||||||
updatedAt: updatedAt ?? this.updatedAt,
|
updatedAt: updatedAt ?? this.updatedAt,
|
||||||
@@ -419,7 +419,7 @@ class SettingsEntityCompanion
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('SettingsEntityCompanion(')
|
return (StringBuffer('MetadataEntityCompanion(')
|
||||||
..write('key: $key, ')
|
..write('key: $key, ')
|
||||||
..write('value: $value, ')
|
..write('value: $value, ')
|
||||||
..write('updatedAt: $updatedAt')
|
..write('updatedAt: $updatedAt')
|
||||||
@@ -13,7 +13,7 @@ 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/entities/memory.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/memory.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/metadata.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/person.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/person.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart';
|
||||||
@@ -55,7 +55,7 @@ import 'package:logging/logging.dart';
|
|||||||
StoreEntity,
|
StoreEntity,
|
||||||
TrashedLocalAssetEntity,
|
TrashedLocalAssetEntity,
|
||||||
AssetEditEntity,
|
AssetEditEntity,
|
||||||
SettingsEntity,
|
MetadataEntity,
|
||||||
],
|
],
|
||||||
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
|
||||||
)
|
)
|
||||||
@@ -98,7 +98,7 @@ class Drift extends $Drift {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 27;
|
int get schemaVersion => 26;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
@@ -276,9 +276,6 @@ class Drift extends $Drift {
|
|||||||
from25To26: (m, v26) async {
|
from25To26: (m, v26) async {
|
||||||
await m.addColumn(v26.remoteAssetEntity, v26.remoteAssetEntity.uploadedAt);
|
await m.addColumn(v26.remoteAssetEntity, v26.remoteAssetEntity.uploadedAt);
|
||||||
},
|
},
|
||||||
from26To27: (m, v27) async {
|
|
||||||
await customStatement('ALTER TABLE metadata RENAME TO settings');
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity
|
|||||||
as i20;
|
as i20;
|
||||||
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.drift.dart'
|
||||||
as i21;
|
as i21;
|
||||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/metadata.entity.drift.dart'
|
||||||
as i22;
|
as i22;
|
||||||
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
||||||
as i23;
|
as i23;
|
||||||
@@ -91,7 +91,7 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
.$TrashedLocalAssetEntityTable(this);
|
.$TrashedLocalAssetEntityTable(this);
|
||||||
late final i21.$AssetEditEntityTable assetEditEntity = i21
|
late final i21.$AssetEditEntityTable assetEditEntity = i21
|
||||||
.$AssetEditEntityTable(this);
|
.$AssetEditEntityTable(this);
|
||||||
late final i22.$SettingsEntityTable settingsEntity = i22.$SettingsEntityTable(
|
late final i22.$MetadataEntityTable metadataEntity = i22.$MetadataEntityTable(
|
||||||
this,
|
this,
|
||||||
);
|
);
|
||||||
i23.MergedAssetDrift get mergedAssetDrift => i24.ReadDatabaseContainer(
|
i23.MergedAssetDrift get mergedAssetDrift => i24.ReadDatabaseContainer(
|
||||||
@@ -132,7 +132,7 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
|||||||
storeEntity,
|
storeEntity,
|
||||||
trashedLocalAssetEntity,
|
trashedLocalAssetEntity,
|
||||||
assetEditEntity,
|
assetEditEntity,
|
||||||
settingsEntity,
|
metadataEntity,
|
||||||
i10.idxPartnerSharedWithId,
|
i10.idxPartnerSharedWithId,
|
||||||
i11.idxLatLng,
|
i11.idxLatLng,
|
||||||
i11.idxRemoteExifCity,
|
i11.idxRemoteExifCity,
|
||||||
@@ -395,6 +395,6 @@ class $DriftManager {
|
|||||||
);
|
);
|
||||||
i21.$$AssetEditEntityTableTableManager get assetEditEntity =>
|
i21.$$AssetEditEntityTableTableManager get assetEditEntity =>
|
||||||
i21.$$AssetEditEntityTableTableManager(_db, _db.assetEditEntity);
|
i21.$$AssetEditEntityTableTableManager(_db, _db.assetEditEntity);
|
||||||
i22.$$SettingsEntityTableTableManager get settingsEntity =>
|
i22.$$MetadataEntityTableTableManager get metadataEntity =>
|
||||||
i22.$$SettingsEntityTableTableManager(_db, _db.settingsEntity);
|
i22.$$MetadataEntityTableTableManager(_db, _db.metadataEntity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13539,550 +13539,6 @@ i1.GeneratedColumn<String> _column_212(String aliasedName) =>
|
|||||||
type: i1.DriftSqlType.string,
|
type: i1.DriftSqlType.string,
|
||||||
$customConstraints: 'NULL',
|
$customConstraints: 'NULL',
|
||||||
);
|
);
|
||||||
|
|
||||||
final class Schema27 extends i0.VersionedSchema {
|
|
||||||
Schema27({required super.database}) : super(version: 27);
|
|
||||||
@override
|
|
||||||
late final List<i1.DatabaseSchemaEntity> entities = [
|
|
||||||
userEntity,
|
|
||||||
remoteAssetEntity,
|
|
||||||
stackEntity,
|
|
||||||
localAssetEntity,
|
|
||||||
remoteAlbumEntity,
|
|
||||||
localAlbumEntity,
|
|
||||||
localAlbumAssetEntity,
|
|
||||||
idxLocalAlbumAssetAlbumAsset,
|
|
||||||
idxLocalAssetChecksum,
|
|
||||||
idxLocalAssetCloudId,
|
|
||||||
idxStackPrimaryAssetId,
|
|
||||||
uQRemoteAssetsOwnerChecksum,
|
|
||||||
uQRemoteAssetsOwnerLibraryChecksum,
|
|
||||||
idxRemoteAssetChecksum,
|
|
||||||
idxRemoteAssetStackId,
|
|
||||||
idxRemoteAssetOwnerVisibilityDeletedCreated,
|
|
||||||
authUserEntity,
|
|
||||||
userMetadataEntity,
|
|
||||||
partnerEntity,
|
|
||||||
remoteExifEntity,
|
|
||||||
remoteAlbumAssetEntity,
|
|
||||||
remoteAlbumUserEntity,
|
|
||||||
remoteAssetCloudIdEntity,
|
|
||||||
memoryEntity,
|
|
||||||
memoryAssetEntity,
|
|
||||||
personEntity,
|
|
||||||
assetFaceEntity,
|
|
||||||
storeEntity,
|
|
||||||
trashedLocalAssetEntity,
|
|
||||||
assetEditEntity,
|
|
||||||
settings,
|
|
||||||
idxPartnerSharedWithId,
|
|
||||||
idxLatLng,
|
|
||||||
idxRemoteExifCity,
|
|
||||||
idxRemoteAlbumAssetAlbumAsset,
|
|
||||||
idxRemoteAssetCloudId,
|
|
||||||
idxPersonOwnerId,
|
|
||||||
idxAssetFacePersonId,
|
|
||||||
idxAssetFaceAssetId,
|
|
||||||
idxAssetFaceVisiblePerson,
|
|
||||||
idxTrashedLocalAssetChecksum,
|
|
||||||
idxTrashedLocalAssetAlbum,
|
|
||||||
idxAssetEditAssetId,
|
|
||||||
];
|
|
||||||
late final Shape33 userEntity = Shape33(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'user_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_108,
|
|
||||||
_column_109,
|
|
||||||
_column_110,
|
|
||||||
_column_111,
|
|
||||||
_column_112,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape50 remoteAssetEntity = Shape50(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'remote_asset_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_108,
|
|
||||||
_column_113,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_116,
|
|
||||||
_column_117,
|
|
||||||
_column_118,
|
|
||||||
_column_107,
|
|
||||||
_column_119,
|
|
||||||
_column_120,
|
|
||||||
_column_121,
|
|
||||||
_column_122,
|
|
||||||
_column_123,
|
|
||||||
_column_124,
|
|
||||||
_column_212,
|
|
||||||
_column_125,
|
|
||||||
_column_126,
|
|
||||||
_column_127,
|
|
||||||
_column_128,
|
|
||||||
_column_129,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape35 stackEntity = Shape35(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'stack_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_121,
|
|
||||||
_column_130,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape36 localAssetEntity = Shape36(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'local_asset_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_108,
|
|
||||||
_column_113,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_116,
|
|
||||||
_column_117,
|
|
||||||
_column_118,
|
|
||||||
_column_107,
|
|
||||||
_column_131,
|
|
||||||
_column_120,
|
|
||||||
_column_132,
|
|
||||||
_column_133,
|
|
||||||
_column_134,
|
|
||||||
_column_135,
|
|
||||||
_column_136,
|
|
||||||
_column_137,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape48 remoteAlbumEntity = Shape48(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'remote_album_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_108,
|
|
||||||
_column_138,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_139,
|
|
||||||
_column_140,
|
|
||||||
_column_141,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape38 localAlbumEntity = Shape38(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'local_album_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_108,
|
|
||||||
_column_115,
|
|
||||||
_column_142,
|
|
||||||
_column_143,
|
|
||||||
_column_144,
|
|
||||||
_column_145,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape39 localAlbumAssetEntity = Shape39(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'local_album_asset_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(asset_id, album_id)'],
|
|
||||||
columns: [_column_146, _column_147, _column_145],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
final i1.Index idxLocalAlbumAssetAlbumAsset = i1.Index(
|
|
||||||
'idx_local_album_asset_album_asset',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_local_album_asset_album_asset ON local_album_asset_entity (album_id, asset_id)',
|
|
||||||
);
|
|
||||||
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 idxLocalAssetCloudId = i1.Index(
|
|
||||||
'idx_local_asset_cloud_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_local_asset_cloud_id ON local_asset_entity (i_cloud_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxStackPrimaryAssetId = i1.Index(
|
|
||||||
'idx_stack_primary_asset_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_stack_primary_asset_id ON stack_entity (primary_asset_id)',
|
|
||||||
);
|
|
||||||
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)',
|
|
||||||
);
|
|
||||||
final i1.Index idxRemoteAssetStackId = i1.Index(
|
|
||||||
'idx_remote_asset_stack_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_stack_id ON remote_asset_entity (stack_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxRemoteAssetOwnerVisibilityDeletedCreated = i1.Index(
|
|
||||||
'idx_remote_asset_owner_visibility_deleted_created',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_visibility_deleted_created ON remote_asset_entity (owner_id, visibility, deleted_at, created_at DESC)',
|
|
||||||
);
|
|
||||||
late final Shape40 authUserEntity = Shape40(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'auth_user_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_108,
|
|
||||||
_column_109,
|
|
||||||
_column_148,
|
|
||||||
_column_110,
|
|
||||||
_column_111,
|
|
||||||
_column_149,
|
|
||||||
_column_150,
|
|
||||||
_column_151,
|
|
||||||
_column_152,
|
|
||||||
],
|
|
||||||
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_153, _column_154, _column_155],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape41 partnerEntity = Shape41(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'partner_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'],
|
|
||||||
columns: [_column_156, _column_157, _column_158],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape42 remoteExifEntity = Shape42(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'remote_exif_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(asset_id)'],
|
|
||||||
columns: [
|
|
||||||
_column_159,
|
|
||||||
_column_160,
|
|
||||||
_column_161,
|
|
||||||
_column_162,
|
|
||||||
_column_163,
|
|
||||||
_column_164,
|
|
||||||
_column_117,
|
|
||||||
_column_116,
|
|
||||||
_column_165,
|
|
||||||
_column_166,
|
|
||||||
_column_167,
|
|
||||||
_column_168,
|
|
||||||
_column_135,
|
|
||||||
_column_136,
|
|
||||||
_column_169,
|
|
||||||
_column_170,
|
|
||||||
_column_171,
|
|
||||||
_column_172,
|
|
||||||
_column_173,
|
|
||||||
_column_174,
|
|
||||||
_column_175,
|
|
||||||
_column_176,
|
|
||||||
],
|
|
||||||
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_159, _column_177],
|
|
||||||
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_177, _column_153, _column_178],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape43 remoteAssetCloudIdEntity = Shape43(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'remote_asset_cloud_id_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(asset_id)'],
|
|
||||||
columns: [
|
|
||||||
_column_159,
|
|
||||||
_column_179,
|
|
||||||
_column_180,
|
|
||||||
_column_134,
|
|
||||||
_column_135,
|
|
||||||
_column_136,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape44 memoryEntity = Shape44(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'memory_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_124,
|
|
||||||
_column_121,
|
|
||||||
_column_113,
|
|
||||||
_column_181,
|
|
||||||
_column_182,
|
|
||||||
_column_183,
|
|
||||||
_column_184,
|
|
||||||
_column_185,
|
|
||||||
_column_186,
|
|
||||||
],
|
|
||||||
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_159, _column_187],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape45 personEntity = Shape45(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'person_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_121,
|
|
||||||
_column_108,
|
|
||||||
_column_188,
|
|
||||||
_column_189,
|
|
||||||
_column_190,
|
|
||||||
_column_191,
|
|
||||||
_column_192,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape46 assetFaceEntity = Shape46(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'asset_face_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_159,
|
|
||||||
_column_193,
|
|
||||||
_column_194,
|
|
||||||
_column_195,
|
|
||||||
_column_196,
|
|
||||||
_column_197,
|
|
||||||
_column_198,
|
|
||||||
_column_199,
|
|
||||||
_column_200,
|
|
||||||
_column_201,
|
|
||||||
_column_124,
|
|
||||||
],
|
|
||||||
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_202, _column_203, _column_204],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape47 trashedLocalAssetEntity = Shape47(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'trashed_local_asset_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id, album_id)'],
|
|
||||||
columns: [
|
|
||||||
_column_108,
|
|
||||||
_column_113,
|
|
||||||
_column_114,
|
|
||||||
_column_115,
|
|
||||||
_column_116,
|
|
||||||
_column_117,
|
|
||||||
_column_118,
|
|
||||||
_column_107,
|
|
||||||
_column_205,
|
|
||||||
_column_131,
|
|
||||||
_column_120,
|
|
||||||
_column_132,
|
|
||||||
_column_206,
|
|
||||||
_column_137,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape32 assetEditEntity = Shape32(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'asset_edit_entity',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY(id)'],
|
|
||||||
columns: [
|
|
||||||
_column_107,
|
|
||||||
_column_159,
|
|
||||||
_column_207,
|
|
||||||
_column_208,
|
|
||||||
_column_209,
|
|
||||||
],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
late final Shape49 settings = Shape49(
|
|
||||||
source: i0.VersionedTable(
|
|
||||||
entityName: 'settings',
|
|
||||||
withoutRowId: true,
|
|
||||||
isStrict: true,
|
|
||||||
tableConstraints: ['PRIMARY KEY("key")'],
|
|
||||||
columns: [_column_210, _column_211, _column_115],
|
|
||||||
attachedDatabase: database,
|
|
||||||
),
|
|
||||||
alias: null,
|
|
||||||
);
|
|
||||||
final i1.Index idxPartnerSharedWithId = i1.Index(
|
|
||||||
'idx_partner_shared_with_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_partner_shared_with_id ON partner_entity (shared_with_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxLatLng = i1.Index(
|
|
||||||
'idx_lat_lng',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)',
|
|
||||||
);
|
|
||||||
final i1.Index idxRemoteExifCity = i1.Index(
|
|
||||||
'idx_remote_exif_city',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_remote_exif_city ON remote_exif_entity (city) WHERE city IS NOT NULL',
|
|
||||||
);
|
|
||||||
final i1.Index idxRemoteAlbumAssetAlbumAsset = i1.Index(
|
|
||||||
'idx_remote_album_asset_album_asset',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_remote_album_asset_album_asset ON remote_album_asset_entity (album_id, asset_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxRemoteAssetCloudId = i1.Index(
|
|
||||||
'idx_remote_asset_cloud_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_remote_asset_cloud_id ON remote_asset_cloud_id_entity (cloud_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxPersonOwnerId = i1.Index(
|
|
||||||
'idx_person_owner_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_person_owner_id ON person_entity (owner_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxAssetFacePersonId = i1.Index(
|
|
||||||
'idx_asset_face_person_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_asset_face_person_id ON asset_face_entity (person_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxAssetFaceAssetId = i1.Index(
|
|
||||||
'idx_asset_face_asset_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_asset_face_asset_id ON asset_face_entity (asset_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxAssetFaceVisiblePerson = i1.Index(
|
|
||||||
'idx_asset_face_visible_person',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_asset_face_visible_person ON asset_face_entity (person_id, asset_id) WHERE is_visible = 1 AND deleted_at IS NULL',
|
|
||||||
);
|
|
||||||
final i1.Index idxTrashedLocalAssetChecksum = i1.Index(
|
|
||||||
'idx_trashed_local_asset_checksum',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)',
|
|
||||||
);
|
|
||||||
final i1.Index idxTrashedLocalAssetAlbum = i1.Index(
|
|
||||||
'idx_trashed_local_asset_album',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)',
|
|
||||||
);
|
|
||||||
final i1.Index idxAssetEditAssetId = i1.Index(
|
|
||||||
'idx_asset_edit_asset_id',
|
|
||||||
'CREATE INDEX IF NOT EXISTS idx_asset_edit_asset_id ON asset_edit_entity (asset_id)',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
@@ -14109,7 +13565,6 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema24 schema) from23To24,
|
required Future<void> Function(i1.Migrator m, Schema24 schema) from23To24,
|
||||||
required Future<void> Function(i1.Migrator m, Schema25 schema) from24To25,
|
required Future<void> Function(i1.Migrator m, Schema25 schema) from24To25,
|
||||||
required Future<void> Function(i1.Migrator m, Schema26 schema) from25To26,
|
required Future<void> Function(i1.Migrator m, Schema26 schema) from25To26,
|
||||||
required Future<void> Function(i1.Migrator m, Schema27 schema) from26To27,
|
|
||||||
}) {
|
}) {
|
||||||
return (currentVersion, database) async {
|
return (currentVersion, database) async {
|
||||||
switch (currentVersion) {
|
switch (currentVersion) {
|
||||||
@@ -14238,11 +13693,6 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
final migrator = i1.Migrator(database, schema);
|
final migrator = i1.Migrator(database, schema);
|
||||||
await from25To26(migrator, schema);
|
await from25To26(migrator, schema);
|
||||||
return 26;
|
return 26;
|
||||||
case 26:
|
|
||||||
final schema = Schema27(database: database);
|
|
||||||
final migrator = i1.Migrator(database, schema);
|
|
||||||
await from26To27(migrator, schema);
|
|
||||||
return 27;
|
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
}
|
}
|
||||||
@@ -14275,7 +13725,6 @@ i1.OnUpgrade stepByStep({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema24 schema) from23To24,
|
required Future<void> Function(i1.Migrator m, Schema24 schema) from23To24,
|
||||||
required Future<void> Function(i1.Migrator m, Schema25 schema) from24To25,
|
required Future<void> Function(i1.Migrator m, Schema25 schema) from24To25,
|
||||||
required Future<void> Function(i1.Migrator m, Schema26 schema) from25To26,
|
required Future<void> Function(i1.Migrator m, Schema26 schema) from25To26,
|
||||||
required Future<void> Function(i1.Migrator m, Schema27 schema) from26To27,
|
|
||||||
}) => i0.VersionedSchema.stepByStepHelper(
|
}) => i0.VersionedSchema.stepByStepHelper(
|
||||||
step: migrationSteps(
|
step: migrationSteps(
|
||||||
from1To2: from1To2,
|
from1To2: from1To2,
|
||||||
@@ -14303,6 +13752,5 @@ i1.OnUpgrade stepByStep({
|
|||||||
from23To24: from23To24,
|
from23To24: from23To24,
|
||||||
from24To25: from24To25,
|
from24To25: from24To25,
|
||||||
from25To26: from25To26,
|
from25To26: from25To26,
|
||||||
from26To27: from26To27,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
+18
-18
@@ -1,21 +1,21 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/metadata.entity.drift.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||||
|
|
||||||
class SettingsRepository extends DriftDatabaseRepository {
|
class MetadataRepository extends DriftDatabaseRepository {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
|
|
||||||
SettingsRepository._(this._db) : super(_db);
|
MetadataRepository._(this._db) : super(_db);
|
||||||
|
|
||||||
static SettingsRepository? _instance;
|
static MetadataRepository? _instance;
|
||||||
|
|
||||||
static SettingsRepository get instance {
|
static MetadataRepository get instance {
|
||||||
final instance = _instance;
|
final instance = _instance;
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
throw StateError('SettingsRepository not initialized. Call ensureInitialized() first');
|
throw StateError('MetadataRepository not initialized. Call ensureInitialized() first');
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@@ -23,31 +23,31 @@ class SettingsRepository extends DriftDatabaseRepository {
|
|||||||
AppConfig _appConfig = const .new();
|
AppConfig _appConfig = const .new();
|
||||||
AppConfig get appConfig => _appConfig;
|
AppConfig get appConfig => _appConfig;
|
||||||
|
|
||||||
static Future<SettingsRepository> ensureInitialized(Drift db) async {
|
static Future<MetadataRepository> ensureInitialized(Drift db) async {
|
||||||
if (_instance == null) {
|
if (_instance == null) {
|
||||||
final instance = SettingsRepository._(db);
|
final instance = MetadataRepository._(db);
|
||||||
await instance.refresh();
|
await instance.refresh();
|
||||||
_instance = instance;
|
_instance = instance;
|
||||||
}
|
}
|
||||||
return _instance!;
|
return _instance!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refresh() async => _applyOverrides(await _db.select(_db.settingsEntity).get());
|
Future<void> refresh() async => _applyOverrides(await _db.select(_db.metadataEntity).get());
|
||||||
|
|
||||||
Future<void> clear(Iterable<SettingsKey> keys) async {
|
Future<void> clear(Iterable<MetadataKey> keys) async {
|
||||||
if (keys.isEmpty) {
|
if (keys.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final names = keys.map((key) => key.name).toList();
|
final names = keys.map((key) => key.name).toList();
|
||||||
await (_db.delete(_db.settingsEntity)..where((row) => row.key.isIn(names))).go();
|
await (_db.delete(_db.metadataEntity)..where((row) => row.key.isIn(names))).go();
|
||||||
|
|
||||||
for (final key in keys) {
|
for (final key in keys) {
|
||||||
_appConfig = _appConfig.write(key, defaultConfig.read(key));
|
_appConfig = _appConfig.write(key, defaultConfig.read(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> write<T extends Object, U extends T>(SettingsKey<T> key, U value) async {
|
Future<void> write<T extends Object, U extends T>(MetadataKey<T> key, U value) async {
|
||||||
if (value == _appConfig.read(key)) {
|
if (value == _appConfig.read(key)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -57,22 +57,22 @@ class SettingsRepository extends DriftDatabaseRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _db
|
await _db
|
||||||
.into(_db.settingsEntity)
|
.into(_db.metadataEntity)
|
||||||
.insertOnConflictUpdate(
|
.insertOnConflictUpdate(
|
||||||
SettingsEntityCompanion.insert(key: key.name, value: key.encode(value), updatedAt: Value(DateTime.now())),
|
MetadataEntityCompanion.insert(key: key.name, value: key.encode(value), updatedAt: Value(DateTime.now())),
|
||||||
);
|
);
|
||||||
_appConfig = _appConfig.write(key, value);
|
_appConfig = _appConfig.write(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<AppConfig> watchConfig() => _db.select(_db.settingsEntity).watch().map((rows) {
|
Stream<AppConfig> watchConfig() => _db.select(_db.metadataEntity).watch().map((rows) {
|
||||||
_applyOverrides(rows);
|
_applyOverrides(rows);
|
||||||
return _appConfig;
|
return _appConfig;
|
||||||
});
|
});
|
||||||
|
|
||||||
void _applyOverrides(List<SettingsEntityData> rows) {
|
void _applyOverrides(List<MetadataEntityData> rows) {
|
||||||
_appConfig = AppConfig.fromEntries(
|
_appConfig = AppConfig.fromEntries(
|
||||||
rows.fold({}, (overrides, row) {
|
rows.fold({}, (overrides, row) {
|
||||||
final metadataKey = SettingsKey.values.firstWhereOrNull((key) => key.name == row.key);
|
final metadataKey = MetadataKey.values.firstWhereOrNull((key) => key.name == row.key);
|
||||||
if (metadataKey == null) {
|
if (metadataKey == null) {
|
||||||
return overrides;
|
return overrides;
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
|
|||||||
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
|
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.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/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||||
import 'package:immich_mobile/providers/locale_provider.dart';
|
import 'package:immich_mobile/providers/locale_provider.dart';
|
||||||
import 'package:immich_mobile/providers/routes.provider.dart';
|
import 'package:immich_mobile/providers/routes.provider.dart';
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ import 'package:immich_mobile/utils/semver.dart';
|
|||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class ServerVersion extends SemVer {
|
class ServerVersion extends SemVer {
|
||||||
const ServerVersion({required super.major, required super.minor, required super.patch, super.prerelease});
|
const ServerVersion({required super.major, required super.minor, required super.patch});
|
||||||
|
|
||||||
ServerVersion.fromDto(ServerVersionResponseDto dto)
|
@override
|
||||||
: super(major: dto.major, minor: dto.minor, patch: dto.patch_, prerelease: dto.prerelease);
|
String toString() {
|
||||||
|
return 'ServerVersion(major: $major, minor: $minor, patch: $patch)';
|
||||||
|
}
|
||||||
|
|
||||||
bool isAtLeast({int major = 0, int minor = 0, int patch = 0, int? prerelease}) {
|
ServerVersion.fromDto(ServerVersionResponseDto dto) : super(major: dto.major, minor: dto.minor, patch: dto.patch_);
|
||||||
return this >= SemVer(major: major, minor: minor, patch: patch, prerelease: prerelease);
|
|
||||||
|
bool isAtLeast({int major = 0, int minor = 0, int patch = 0}) {
|
||||||
|
return this >= SemVer(major: major, minor: minor, patch: patch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
|||||||
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart';
|
import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart';
|
||||||
@@ -103,7 +103,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isBackupEnabled = SettingsRepository.instance.appConfig.backup.enabled;
|
final isBackupEnabled = MetadataRepository.instance.appConfig.backup.enabled;
|
||||||
await ref.read(driftBackupProvider.notifier).getBackupStatus(user.id);
|
await ref.read(driftBackupProvider.notifier).getBackupStatus(user.id);
|
||||||
final currentTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
|
final currentTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
|
||||||
final totalChanged = currentTotalAssetCount != _initialTotalAssetCount;
|
final totalChanged = currentTotalAssetCount != _initialTotalAssetCount;
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import 'package:auto_route/auto_route.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/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart';
|
import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@@ -27,7 +27,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
|||||||
// There is an issue with Flutter where the pop event
|
// There is an issue with Flutter where the pop event
|
||||||
// can be triggered multiple times, so we guard it with _hasPopped
|
// can be triggered multiple times, so we guard it with _hasPopped
|
||||||
|
|
||||||
final currentBackup = ref.read(appConfigProvider).backup;
|
final currentBackup = ref.read(metadataProvider).appConfig.backup;
|
||||||
final currentCellularForVideos = currentBackup.useCellularForVideos;
|
final currentCellularForVideos = currentBackup.useCellularForVideos;
|
||||||
final currentCellularForPhotos = currentBackup.useCellularForPhotos;
|
final currentCellularForPhotos = currentBackup.useCellularForPhotos;
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
||||||
final isBackupEnabled = SettingsRepository.instance.appConfig.backup.enabled;
|
final isBackupEnabled = MetadataRepository.instance.appConfig.backup.enabled;
|
||||||
if (!isBackupEnabled) {
|
if (!isBackupEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/generated/translations.g.dart';
|
import 'package:immich_mobile/generated/translations.g.dart';
|
||||||
import 'package:immich_mobile/providers/api.provider.dart';
|
import 'package:immich_mobile/providers/api.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
|
|
||||||
class SettingsHeader {
|
class SettingsHeader {
|
||||||
String key = "";
|
String key = "";
|
||||||
@@ -21,7 +22,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
|
|||||||
final headers = useState<List<SettingsHeader>>([]);
|
final headers = useState<List<SettingsHeader>>([]);
|
||||||
final setInitialHeaders = useState(false);
|
final setInitialHeaders = useState(false);
|
||||||
|
|
||||||
final storedHeaders = ref.read(appConfigProvider).network.customHeaders;
|
final storedHeaders = ref.read(metadataProvider).appConfig.network.customHeaders;
|
||||||
if (!setInitialHeaders.value) {
|
if (!setInitialHeaders.value) {
|
||||||
storedHeaders.forEach((k, v) {
|
storedHeaders.forEach((k, v) {
|
||||||
final header = SettingsHeader();
|
final header = SettingsHeader();
|
||||||
@@ -93,7 +94,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
|
|||||||
headersMap[key] = value;
|
headersMap[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ref.read(settingsProvider).write(.networkCustomHeaders, headersMap);
|
await ref.read(metadataProvider).write(MetadataKey.networkCustomHeaders, headersMap);
|
||||||
await ref.read(apiServiceProvider).updateHeaders();
|
await ref.read(apiServiceProvider).updateHeaders();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import 'package:immich_mobile/domain/models/store.model.dart';
|
|||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||||
import 'package:immich_mobile/generated/translations.g.dart';
|
import 'package:immich_mobile/generated/translations.g.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
@@ -341,7 +341,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||||||
await backgroundManager.hashAssets();
|
await backgroundManager.hashAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SettingsRepository.instance.appConfig.backup.syncAlbums) {
|
if (MetadataRepository.instance.appConfig.backup.syncAlbums) {
|
||||||
await backgroundManager.syncLinkedAlbum();
|
await backgroundManager.syncLinkedAlbum();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -370,7 +370,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
||||||
final isEnableBackup = SettingsRepository.instance.appConfig.backup.enabled;
|
final isEnableBackup = MetadataRepository.instance.appConfig.backup.enabled;
|
||||||
|
|
||||||
if (isEnableBackup) {
|
if (isEnableBackup) {
|
||||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.wid
|
|||||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_bu
|
|||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/routes.provider.dart';
|
import 'package:immich_mobile/providers/routes.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
@@ -143,18 +142,13 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result = await ref.read(actionProvider.notifier).addToAlbum(ActionSource.viewer, album);
|
final addedCount = await ref.read(remoteAlbumProvider.notifier).addAssets(album.id, [latest.remoteId!]);
|
||||||
|
|
||||||
if (!context.mounted) {
|
if (!context.mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.success) {
|
if (addedCount == 0) {
|
||||||
ImmichToast.show(context: context, msg: 'scaffold_body_error_occurred'.tr(), toastType: ToastType.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.count == 0) {
|
|
||||||
ImmichToast.show(
|
ImmichToast.show(
|
||||||
context: context,
|
context: context,
|
||||||
msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}),
|
msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name}),
|
||||||
@@ -165,7 +159,7 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
|
|||||||
msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Refresh the "Appears in" list on the asset's info panel.
|
// Invalidate using the asset's remote ID to refresh the "Appears in" list
|
||||||
ref.invalidate(albumsContainingAssetProvider(latest.remoteId!));
|
ref.invalidate(albumsContainingAssetProvider(latest.remoteId!));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.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/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
@@ -14,11 +15,12 @@ import 'package:immich_mobile/models/albums/album_search.model.dart';
|
|||||||
import 'package:immich_mobile/presentation/widgets/album/album_tile.dart';
|
import 'package:immich_mobile/presentation/widgets/album/album_tile.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/album/new_album_name_modal.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/album/new_album_name_modal.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
@@ -56,7 +58,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
final albumConfig = ref.read(appConfigProvider).album;
|
final albumConfig = ref.read(metadataProvider).appConfig.album;
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
sort = AlbumSort(mode: albumConfig.sortMode, isReverse: albumConfig.isReverse);
|
sort = AlbumSort(mode: albumConfig.sortMode, isReverse: albumConfig.isReverse);
|
||||||
@@ -92,7 +94,7 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
isGrid = !isGrid;
|
isGrid = !isGrid;
|
||||||
});
|
});
|
||||||
ref.read(settingsProvider).write(.albumIsGrid, isGrid);
|
ref.read(metadataProvider).write(MetadataKey.albumIsGrid, isGrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeFilter(QuickFilterMode mode) {
|
void changeFilter(QuickFilterMode mode) {
|
||||||
@@ -108,9 +110,9 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
|
|||||||
this.sort = sort;
|
this.sort = sort;
|
||||||
});
|
});
|
||||||
|
|
||||||
final metadata = ref.read(settingsProvider);
|
final metadata = ref.read(metadataProvider);
|
||||||
await metadata.write(.albumSortMode, sort.mode);
|
await metadata.write(MetadataKey.albumSortMode, sort.mode);
|
||||||
await metadata.write(.albumIsReverse, sort.isReverse);
|
await metadata.write(MetadataKey.albumIsReverse, sort.isReverse);
|
||||||
|
|
||||||
await sortAlbums();
|
await sortAlbums();
|
||||||
}
|
}
|
||||||
@@ -745,10 +747,12 @@ class AddToAlbumHeader extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
Future<void> onCreateAlbum() async {
|
Future<void> onCreateAlbum() async {
|
||||||
final selectedAssets = ref.read(multiSelectProvider).selectedAssets;
|
|
||||||
final newAlbum = await ref
|
final newAlbum = await ref
|
||||||
.read(remoteAlbumProvider.notifier)
|
.read(remoteAlbumProvider.notifier)
|
||||||
.createAlbumWithAssets(title: "Untitled Album", assets: selectedAssets);
|
.createAlbum(
|
||||||
|
title: "Untitled Album",
|
||||||
|
assetIds: ref.read(multiSelectProvider).selectedAssets.map((e) => (e as RemoteAsset).id).toList(),
|
||||||
|
);
|
||||||
|
|
||||||
if (newAlbum == null) {
|
if (newAlbum == null) {
|
||||||
ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr());
|
ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr());
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||||
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
|
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
|
|
||||||
|
|
||||||
/// Pinned banner sliver that surfaces in-flight album uploads directly under
|
/// Pinned banner sliver that surfaces in-flight album uploads directly under
|
||||||
/// the album app bar. Renders nothing while the queue is empty. Tapping the
|
/// the album app bar. Renders nothing while the queue is empty. Tapping the
|
||||||
@@ -166,8 +165,6 @@ class _PendingUploadsSheet extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final failedCount = pending.where((p) => p.failed).length;
|
final failedCount = pending.where((p) => p.failed).length;
|
||||||
final inFlightCount = pending.length - failedCount;
|
|
||||||
final canAbort = inFlightCount > 0 && ref.watch(manualUploadCancelTokenProvider) != null;
|
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -186,21 +183,7 @@ class _PendingUploadsSheet extends ConsumerWidget {
|
|||||||
style: context.textTheme.titleMedium,
|
style: context.textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (canAbort)
|
if (failedCount > 0)
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
final cancelToken = ref.read(manualUploadCancelTokenProvider);
|
|
||||||
if (cancelToken != null && !cancelToken.isCompleted) {
|
|
||||||
cancelToken.complete();
|
|
||||||
}
|
|
||||||
ref.read(manualUploadCancelTokenProvider.notifier).state = null;
|
|
||||||
ref.read(pendingAlbumUploadsProvider(albumId).notifier).clear();
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.stop_circle_outlined, size: 18),
|
|
||||||
label: Text('cancel'.t(context: context)),
|
|
||||||
style: TextButton.styleFrom(foregroundColor: context.colorScheme.error),
|
|
||||||
)
|
|
||||||
else if (failedCount > 0)
|
|
||||||
TextButton.icon(
|
TextButton.icon(
|
||||||
onPressed: () => ref.read(pendingAlbumUploadsProvider(albumId).notifier).clearFailed(),
|
onPressed: () => ref.read(pendingAlbumUploadsProvider(albumId).notifier).clearFailed(),
|
||||||
icon: const Icon(Icons.clear_rounded, size: 18),
|
icon: const Icon(Icons.clear_rounded, size: 18),
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
|||||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
||||||
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
||||||
@@ -241,7 +241,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final tapToNavigate = ref.read(appConfigProvider).viewer.tapToNavigate;
|
final tapToNavigate = ref.read(metadataProvider).appConfig.viewer.tapToNavigate;
|
||||||
if (!tapToNavigate) {
|
if (!tapToNavigate) {
|
||||||
_viewer.toggleControls();
|
_viewer.toggleControls();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -63,19 +63,16 @@ class SheetTile extends ConsumerWidget {
|
|||||||
subtitleWidget = null;
|
subtitleWidget = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Material(
|
return ListTile(
|
||||||
type: MaterialType.transparency,
|
dense: true,
|
||||||
child: ListTile(
|
visualDensity: VisualDensity.compact,
|
||||||
dense: true,
|
title: GestureDetector(onLongPress: () => copyTitle(context, ref), child: titleWidget),
|
||||||
visualDensity: VisualDensity.compact,
|
titleAlignment: ListTileTitleAlignment.center,
|
||||||
title: GestureDetector(onLongPress: () => copyTitle(context, ref), child: titleWidget),
|
leading: leading,
|
||||||
titleAlignment: ListTileTitleAlignment.center,
|
trailing: trailing,
|
||||||
leading: leading,
|
contentPadding: leading == null ? null : const EdgeInsets.only(left: 25),
|
||||||
trailing: trailing,
|
subtitle: subtitleWidget,
|
||||||
contentPadding: leading == null ? null : const EdgeInsets.only(left: 25),
|
onTap: onTap,
|
||||||
subtitle: subtitleWidget,
|
|
||||||
onTap: onTap,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.pro
|
|||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
|
||||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:native_video_player/native_video_player.dart';
|
import 'package:native_video_player/native_video_player.dart';
|
||||||
@@ -128,7 +128,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
|
|||||||
final remoteId = (videoAsset as RemoteAsset).id;
|
final remoteId = (videoAsset as RemoteAsset).id;
|
||||||
|
|
||||||
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
||||||
final isOriginalVideo = ref.read(appConfigProvider).viewer.loadOriginalVideo;
|
final isOriginalVideo = ref.read(metadataProvider).appConfig.viewer.loadOriginalVideo;
|
||||||
final String postfixUrl = isOriginalVideo ? 'original' : 'video/playback';
|
final String postfixUrl = isOriginalVideo ? 'original' : 'video/playback';
|
||||||
final String videoUrl = videoAsset.livePhotoVideoId != null
|
final String videoUrl = videoAsset.livePhotoVideoId != null
|
||||||
? '$serverEndpoint/assets/${videoAsset.livePhotoVideoId}/$postfixUrl'
|
? '$serverEndpoint/assets/${videoAsset.livePhotoVideoId}/$postfixUrl'
|
||||||
@@ -161,7 +161,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final autoPlayVideo = ref.read(appConfigProvider).viewer.autoPlayVideo;
|
final autoPlayVideo = ref.read(metadataProvider).appConfig.viewer.autoPlayVideo;
|
||||||
if (autoPlayVideo || widget.asset.isMotionPhoto) {
|
if (autoPlayVideo || widget.asset.isMotionPhoto) {
|
||||||
await _notifier.play();
|
await _notifier.play();
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _notifier.load(source);
|
await _notifier.load(source);
|
||||||
final loopVideo = ref.read(appConfigProvider).viewer.loopVideo;
|
final loopVideo = ref.read(metadataProvider).appConfig.viewer.loopVideo;
|
||||||
await _notifier.setLoop(!widget.asset.isMotionPhoto && loopVideo);
|
await _notifier.setLoop(!widget.asset.isMotionPhoto && loopVideo);
|
||||||
await _notifier.setVolume(1);
|
await _notifier.setVolume(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.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/setting.model.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||||
@@ -33,7 +34,7 @@ class ViewerKebabMenu extends ConsumerWidget {
|
|||||||
final isInLockedView = ref.watch(inLockedViewProvider);
|
final isInLockedView = ref.watch(inLockedViewProvider);
|
||||||
final currentAlbum = ref.watch(currentRemoteAlbumProvider);
|
final currentAlbum = ref.watch(currentRemoteAlbumProvider);
|
||||||
final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive;
|
final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive;
|
||||||
final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(.advancedTroubleshooting);
|
final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(Setting.advancedTroubleshooting);
|
||||||
|
|
||||||
final actionContext = ActionButtonContext(
|
final actionContext = ActionButtonContext(
|
||||||
asset: asset,
|
asset: asset,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
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/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
|
|
||||||
class BackupToggleButton extends ConsumerStatefulWidget {
|
class BackupToggleButton extends ConsumerStatefulWidget {
|
||||||
final VoidCallback onStart;
|
final VoidCallback onStart;
|
||||||
@@ -30,7 +31,7 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
|
|||||||
end: 1,
|
end: 1,
|
||||||
).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut));
|
).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut));
|
||||||
|
|
||||||
_isEnabled = ref.read(appConfigProvider).backup.enabled;
|
_isEnabled = ref.read(metadataProvider).appConfig.backup.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -40,7 +41,7 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onToggle(bool value) async {
|
Future<void> _onToggle(bool value) async {
|
||||||
await ref.read(settingsProvider).write(.backupEnabled, value);
|
await ref.read(metadataProvider).write(MetadataKey.backupEnabled, value);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isEnabled = value;
|
_isEnabled = value;
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.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/setting.model.dart';
|
import 'package:immich_mobile/domain/models/setting.model.dart';
|
||||||
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/bulk_tag_assets_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/bulk_tag_assets_action_button.widget.dart';
|
||||||
@@ -23,7 +25,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action
|
|||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/setting.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/setting.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||||
@@ -61,23 +63,37 @@ class _GeneralBottomSheetState extends ConsumerState<GeneralBottomSheet> {
|
|||||||
userMetadataPreferencesProvider.select((value) => value.valueOrNull?.tagsEnabled ?? false),
|
userMetadataPreferencesProvider.select((value) => value.valueOrNull?.tagsEnabled ?? false),
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> addToAlbum(RemoteAlbum album) async {
|
Future<void> addAssetsToAlbum(RemoteAlbum album) async {
|
||||||
final result = await ref.read(actionProvider.notifier).addToAlbum(ActionSource.timeline, album);
|
final selectedAssets = multiselect.selectedAssets;
|
||||||
|
if (selectedAssets.isEmpty) {
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.success) {
|
final remoteAssets = selectedAssets.whereType<RemoteAsset>();
|
||||||
ImmichToast.show(context: context, msg: 'scaffold_body_error_occurred'.tr(), toastType: ToastType.error);
|
final addedCount = await ref
|
||||||
return;
|
.read(remoteAlbumProvider.notifier)
|
||||||
|
.addAssets(album.id, remoteAssets.map((e) => e.id).toList());
|
||||||
|
|
||||||
|
if (selectedAssets.length != remoteAssets.length) {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: 'add_to_album_bottom_sheet_some_local_assets'.t(context: context),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ImmichToast.show(
|
|
||||||
context: context,
|
if (addedCount != remoteAssets.length) {
|
||||||
msg: result.count == 0
|
ImmichToast.show(
|
||||||
? 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name})
|
context: context,
|
||||||
: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {"album": album.name}),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {"album": album.name}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ref.read(multiSelectProvider.notifier).reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onKeyboardExpand() {
|
Future<void> onKeyboardExpand() {
|
||||||
@@ -115,10 +131,12 @@ class _GeneralBottomSheetState extends ConsumerState<GeneralBottomSheet> {
|
|||||||
const DeleteLocalActionButton(source: ActionSource.timeline),
|
const DeleteLocalActionButton(source: ActionSource.timeline),
|
||||||
if (multiselect.onlyLocal) const UploadActionButton(source: ActionSource.timeline),
|
if (multiselect.onlyLocal) const UploadActionButton(source: ActionSource.timeline),
|
||||||
],
|
],
|
||||||
slivers: [
|
slivers: multiselect.hasRemote
|
||||||
const AddToAlbumHeader(),
|
? [
|
||||||
AlbumSelector(onAlbumSelected: addToAlbum, onKeyboardExpanded: onKeyboardExpand),
|
const AddToAlbumHeader(),
|
||||||
],
|
AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +1,25 @@
|
|||||||
import 'package:easy_localization/easy_localization.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/enums.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
|
||||||
|
|
||||||
class LocalAlbumBottomSheet extends ConsumerStatefulWidget {
|
class LocalAlbumBottomSheet extends ConsumerWidget {
|
||||||
const LocalAlbumBottomSheet({super.key});
|
const LocalAlbumBottomSheet({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<LocalAlbumBottomSheet> createState() => _LocalAlbumBottomSheetState();
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
}
|
return const BaseBottomSheet(
|
||||||
|
|
||||||
class _LocalAlbumBottomSheetState extends ConsumerState<LocalAlbumBottomSheet> {
|
|
||||||
late final DraggableScrollableController sheetController;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
sheetController = DraggableScrollableController();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
sheetController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Future<void> addToAlbum(RemoteAlbum album) async {
|
|
||||||
final result = await ref.read(actionProvider.notifier).addToAlbum(ActionSource.timeline, album);
|
|
||||||
|
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result.success) {
|
|
||||||
ImmichToast.show(context: context, msg: 'scaffold_body_error_occurred'.tr(), toastType: ToastType.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmichToast.show(
|
|
||||||
context: context,
|
|
||||||
msg: result.count == 0
|
|
||||||
? 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {'album': album.name})
|
|
||||||
: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> onKeyboardExpand() {
|
|
||||||
return sheetController.animateTo(0.85, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
return BaseBottomSheet(
|
|
||||||
controller: sheetController,
|
|
||||||
initialChildSize: 0.25,
|
initialChildSize: 0.25,
|
||||||
maxChildSize: 0.85,
|
maxChildSize: 0.4,
|
||||||
shouldCloseOnMinExtent: false,
|
shouldCloseOnMinExtent: false,
|
||||||
actions: const [
|
actions: [
|
||||||
ShareActionButton(source: ActionSource.timeline),
|
ShareActionButton(source: ActionSource.timeline),
|
||||||
DeleteLocalActionButton(source: ActionSource.timeline),
|
DeleteLocalActionButton(source: ActionSource.timeline),
|
||||||
UploadActionButton(source: ActionSource.timeline),
|
UploadActionButton(source: ActionSource.timeline),
|
||||||
],
|
],
|
||||||
slivers: [
|
|
||||||
const AddToAlbumHeader(),
|
|
||||||
AlbumSelector(onAlbumSelected: addToAlbum, onKeyboardExpanded: onKeyboardExpand),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-16
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.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/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
|
||||||
@@ -20,7 +21,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_b
|
|||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
@@ -55,28 +56,29 @@ class _RemoteAlbumBottomSheetState extends ConsumerState<RemoteAlbumBottomSheet>
|
|||||||
final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));
|
final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));
|
||||||
final ownsAlbum = ref.watch(currentUserProvider)?.id == widget.album.ownerId;
|
final ownsAlbum = ref.watch(currentUserProvider)?.id == widget.album.ownerId;
|
||||||
|
|
||||||
Future<void> addToAlbum(RemoteAlbum album) async {
|
Future<void> addAssetsToAlbum(RemoteAlbum album) async {
|
||||||
final result = await ref.read(actionProvider.notifier).addToAlbum(ActionSource.timeline, album);
|
final selectedAssets = multiselect.selectedAssets;
|
||||||
|
if (selectedAssets.isEmpty) {
|
||||||
if (!context.mounted) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.success) {
|
final addedCount = await ref
|
||||||
|
.read(remoteAlbumProvider.notifier)
|
||||||
|
.addAssets(album.id, selectedAssets.map((e) => (e as RemoteAsset).id).toList());
|
||||||
|
|
||||||
|
if (addedCount != selectedAssets.length) {
|
||||||
ImmichToast.show(
|
ImmichToast.show(
|
||||||
context: context,
|
context: context,
|
||||||
msg: 'scaffold_body_error_occurred'.t(context: context),
|
msg: 'add_to_album_bottom_sheet_already_exists'.t(context: context, args: {"album": album.name}),
|
||||||
toastType: ToastType.error,
|
);
|
||||||
|
} else {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: 'add_to_album_bottom_sheet_added'.t(context: context, args: {"album": album.name}),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmichToast.show(
|
ref.read(multiSelectProvider.notifier).reset();
|
||||||
context: context,
|
|
||||||
msg: result.count == 0
|
|
||||||
? 'add_to_album_bottom_sheet_already_exists'.t(context: context, args: {"album": album.name})
|
|
||||||
: 'add_to_album_bottom_sheet_added'.t(context: context, args: {"album": album.name}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onKeyboardExpand() {
|
Future<void> onKeyboardExpand() {
|
||||||
@@ -116,7 +118,10 @@ class _RemoteAlbumBottomSheetState extends ConsumerState<RemoteAlbumBottomSheet>
|
|||||||
SetAlbumCoverActionButton(source: ActionSource.timeline, albumId: widget.album.id),
|
SetAlbumCoverActionButton(source: ActionSource.timeline, albumId: widget.album.id),
|
||||||
],
|
],
|
||||||
slivers: ownsAlbum
|
slivers: ownsAlbum
|
||||||
? [const AddToAlbumHeader(), AlbumSelector(onAlbumSelected: addToAlbum, onKeyboardExpanded: onKeyboardExpand)]
|
? [
|
||||||
|
const AddToAlbumHeader(),
|
||||||
|
AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand),
|
||||||
|
]
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import 'package:async/async.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.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/loaders/image_request.dart';
|
import 'package:immich_mobile/infrastructure/loaders/image_request.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/local_image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/local_image_provider.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
||||||
@@ -189,5 +189,5 @@ ImageProvider? getThumbnailImageProvider(BaseAsset asset, {Size size = kThumbnai
|
|||||||
|
|
||||||
bool _shouldUseLocalAsset(BaseAsset asset) =>
|
bool _shouldUseLocalAsset(BaseAsset asset) =>
|
||||||
asset.hasLocal &&
|
asset.hasLocal &&
|
||||||
(!asset.hasRemote || !SettingsRepository.instance.appConfig.image.preferRemote) &&
|
(!asset.hasRemote || !MetadataRepository.instance.appConfig.image.preferRemote) &&
|
||||||
!asset.isEdited;
|
!asset.isEdited;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.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/loaders/image_request.dart';
|
import 'package:immich_mobile/infrastructure/loaders/image_request.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/animated_image_stream_completer.dart';
|
import 'package:immich_mobile/presentation/widgets/images/animated_image_stream_completer.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart';
|
import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart';
|
||||||
@@ -104,7 +104,7 @@ class LocalFullImageProvider extends CancellableImageProvider<LocalFullImageProv
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final loadOriginal = SettingsRepository.instance.appConfig.image.loadOriginal;
|
final loadOriginal = MetadataRepository.instance.appConfig.image.loadOriginal;
|
||||||
final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
|
final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
|
||||||
var request = this.request = LocalImageRequest(
|
var request = this.request = LocalImageRequest(
|
||||||
localId: key.id,
|
localId: key.id,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.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/loaders/image_request.dart';
|
import 'package:immich_mobile/infrastructure/loaders/image_request.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/animated_image_stream_completer.dart';
|
import 'package:immich_mobile/presentation/widgets/images/animated_image_stream_completer.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart';
|
import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart';
|
||||||
@@ -122,7 +122,7 @@ class RemoteFullImageProvider extends CancellableImageProvider<RemoteFullImagePr
|
|||||||
edited: key.edited,
|
edited: key.edited,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final loadOriginal = assetType == AssetType.image && SettingsRepository.instance.appConfig.image.loadOriginal;
|
final loadOriginal = assetType == AssetType.image && MetadataRepository.instance.appConfig.image.loadOriginal;
|
||||||
yield* loadRequest(previewRequest, decode, isFinal: !loadOriginal);
|
yield* loadRequest(previewRequest, decode, isFinal: !loadOriginal);
|
||||||
|
|
||||||
if (!loadOriginal) {
|
if (!loadOriginal) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'
|
|||||||
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
|
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||||
|
|
||||||
class ThumbnailTile extends ConsumerStatefulWidget {
|
class ThumbnailTile extends ConsumerStatefulWidget {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
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/domain/models/events.model.dart';
|
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/map.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/map.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/map/map_state.provider.dart';
|
import 'package:immich_mobile/providers/map/map_state.provider.dart';
|
||||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||||
|
|
||||||
@@ -80,25 +81,25 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void switchFavoriteOnly(bool isFavoriteOnly) {
|
void switchFavoriteOnly(bool isFavoriteOnly) {
|
||||||
ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly);
|
ref.read(metadataProvider).write(MetadataKey.mapShowFavoriteOnly, isFavoriteOnly);
|
||||||
state = state.copyWith(onlyFavorites: isFavoriteOnly);
|
state = state.copyWith(onlyFavorites: isFavoriteOnly);
|
||||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchIncludeArchived(bool isIncludeArchived) {
|
void switchIncludeArchived(bool isIncludeArchived) {
|
||||||
ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived);
|
ref.read(metadataProvider).write(MetadataKey.mapIncludeArchived, isIncludeArchived);
|
||||||
state = state.copyWith(includeArchived: isIncludeArchived);
|
state = state.copyWith(includeArchived: isIncludeArchived);
|
||||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchWithPartners(bool isWithPartners) {
|
void switchWithPartners(bool isWithPartners) {
|
||||||
ref.read(settingsProvider).write(.mapWithPartners, isWithPartners);
|
ref.read(metadataProvider).write(MetadataKey.mapWithPartners, isWithPartners);
|
||||||
state = state.copyWith(withPartners: isWithPartners);
|
state = state.copyWith(withPartners: isWithPartners);
|
||||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRelativeTime(int relativeDays) {
|
void setRelativeTime(int relativeDays) {
|
||||||
ref.read(settingsProvider).write(.mapRelativeDate, relativeDays);
|
ref.read(metadataProvider).write(MetadataKey.mapRelativeDate, relativeDays);
|
||||||
state = state.copyWith(relativeDays: relativeDays);
|
state = state.copyWith(relativeDays: relativeDays);
|
||||||
EventStream.shared.emit(const MapMarkerReloadEvent());
|
EventStream.shared.emit(const MapMarkerReloadEvent());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:immich_mobile/domain/models/timeline.model.dart';
|
|||||||
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/timeline/fixed/segment_builder.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/fixed/segment_builder.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||||
|
|
||||||
class TimelineArgs {
|
class TimelineArgs {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.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/events.model.dart';
|
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
@@ -21,7 +22,7 @@ import 'package:immich_mobile/presentation/widgets/timeline/scrubber.widget.dart
|
|||||||
import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline_drag_region.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/timeline_drag_region.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||||
@@ -458,7 +459,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> {
|
|||||||
_restoreAssetIndex = targetAssetIndex;
|
_restoreAssetIndex = targetAssetIndex;
|
||||||
});
|
});
|
||||||
|
|
||||||
ref.read(settingsProvider).write(.timelineTilesPerRow, _perRow);
|
ref.read(metadataProvider).write(MetadataKey.timelineTilesPerRow, _perRow);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -67,11 +67,6 @@ class AlbumPendingUploadsNotifier extends AutoDisposeFamilyNotifier<List<Pending
|
|||||||
_syncKeepAlive();
|
_syncKeepAlive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
|
||||||
state = const [];
|
|
||||||
_syncKeepAlive();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _syncKeepAlive() {
|
void _syncKeepAlive() {
|
||||||
if (state.isEmpty) {
|
if (state.isEmpty) {
|
||||||
_keepAliveLink?.close();
|
_keepAliveLink?.close();
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import 'package:immich_mobile/providers/auth.provider.dart';
|
|||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
|
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/notification_permission.provider.dart';
|
import 'package:immich_mobile/providers/notification_permission.provider.dart';
|
||||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||||
@@ -107,7 +107,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
|||||||
await Future.delayed(const Duration(milliseconds: 500));
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
|
||||||
final backgroundManager = _ref.read(backgroundSyncProvider);
|
final backgroundManager = _ref.read(backgroundSyncProvider);
|
||||||
final isAlbumLinkedSyncEnable = _ref.read(appConfigProvider).backup.syncAlbums;
|
final isAlbumLinkedSyncEnable = _ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bool syncSuccess = false;
|
bool syncSuccess = false;
|
||||||
@@ -137,7 +137,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resumeBackup() async {
|
Future<void> _resumeBackup() async {
|
||||||
final isEnableBackup = _ref.read(appConfigProvider).backup.enabled;
|
final isEnableBackup = _ref.read(metadataProvider).appConfig.backup.enabled;
|
||||||
|
|
||||||
if (isEnableBackup) {
|
if (isEnableBackup) {
|
||||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:convert';
|
|||||||
import 'package:flutter_udid/flutter_udid.dart';
|
import 'package:flutter_udid/flutter_udid.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/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||||
@@ -10,7 +11,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/models/auth/auth_state.model.dart';
|
import 'package:immich_mobile/models/auth/auth_state.model.dart';
|
||||||
import 'package:immich_mobile/models/auth/login_response.model.dart';
|
import 'package:immich_mobile/models/auth/login_response.model.dart';
|
||||||
import 'package:immich_mobile/providers/api.provider.dart';
|
import 'package:immich_mobile/providers/api.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/services/auth.service.dart';
|
import 'package:immich_mobile/services/auth.service.dart';
|
||||||
@@ -129,7 +130,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
|||||||
await _apiService.updateHeaders();
|
await _apiService.updateHeaders();
|
||||||
|
|
||||||
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
||||||
final headerMap = _ref.read(appConfigProvider).network.customHeaders;
|
final headerMap = _ref.read(metadataProvider).appConfig.network.customHeaders;
|
||||||
final customHeaders = headerMap.isEmpty ? null : jsonEncode(headerMap);
|
final customHeaders = headerMap.isEmpty ? null : jsonEncode(headerMap);
|
||||||
await _widgetService.writeCredentials(serverEndpoint, accessToken, customHeaders);
|
await _widgetService.writeCredentials(serverEndpoint, accessToken, customHeaders);
|
||||||
|
|
||||||
@@ -178,19 +179,19 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveWifiName(String wifiName) async {
|
Future<void> saveWifiName(String wifiName) async {
|
||||||
await _ref.read(settingsProvider).write(.networkPreferredWifiName, wifiName);
|
await _ref.read(metadataProvider).write(MetadataKey.networkPreferredWifiName, wifiName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveLocalEndpoint(String url) async {
|
Future<void> saveLocalEndpoint(String url) async {
|
||||||
await _ref.read(settingsProvider).write(.networkLocalEndpoint, url);
|
await _ref.read(metadataProvider).write(MetadataKey.networkLocalEndpoint, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? getSavedWifiName() {
|
String? getSavedWifiName() {
|
||||||
return _ref.read(appConfigProvider).network.preferredWifiName;
|
return _ref.read(metadataProvider).appConfig.network.preferredWifiName;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? getSavedLocalEndpoint() {
|
String? getSavedLocalEndpoint() {
|
||||||
return _ref.read(appConfigProvider).network.localEndpoint;
|
return _ref.read(metadataProvider).appConfig.network.localEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current server endpoint (with /api) URL from the store
|
/// Returns the current server endpoint (with /api) URL from the store
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.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/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/services/cleanup.service.dart';
|
import 'package:immich_mobile/services/cleanup.service.dart';
|
||||||
|
|
||||||
@@ -54,21 +54,21 @@ final cleanupProvider = StateNotifierProvider<CleanupNotifier, CleanupState>((re
|
|||||||
return CleanupNotifier(
|
return CleanupNotifier(
|
||||||
ref.watch(cleanupServiceProvider),
|
ref.watch(cleanupServiceProvider),
|
||||||
ref.watch(currentUserProvider)?.id,
|
ref.watch(currentUserProvider)?.id,
|
||||||
ref.watch(settingsProvider),
|
ref.watch(metadataProvider),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
class CleanupNotifier extends StateNotifier<CleanupState> {
|
class CleanupNotifier extends StateNotifier<CleanupState> {
|
||||||
final CleanupService _cleanupService;
|
final CleanupService _cleanupService;
|
||||||
final String? _userId;
|
final String? _userId;
|
||||||
final SettingsRepository _settingsRepository;
|
final MetadataRepository _metadataRepository;
|
||||||
|
|
||||||
CleanupNotifier(this._cleanupService, this._userId, this._settingsRepository) : super(const CleanupState()) {
|
CleanupNotifier(this._cleanupService, this._userId, this._metadataRepository) : super(const CleanupState()) {
|
||||||
_loadPersistedSettings();
|
_loadPersistedSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _loadPersistedSettings() {
|
void _loadPersistedSettings() {
|
||||||
final cleanup = _settingsRepository.appConfig.cleanup;
|
final cleanup = _metadataRepository.appConfig.cleanup;
|
||||||
final keepFavorites = cleanup.keepFavorites;
|
final keepFavorites = cleanup.keepFavorites;
|
||||||
final keepMediaType = cleanup.keepMediaType;
|
final keepMediaType = cleanup.keepMediaType;
|
||||||
final keepAlbumIds = cleanup.keepAlbumIds.toSet();
|
final keepAlbumIds = cleanup.keepAlbumIds.toSet();
|
||||||
@@ -87,18 +87,18 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
|
|||||||
state = state.copyWith(selectedDate: date, assetsToDelete: []);
|
state = state.copyWith(selectedDate: date, assetsToDelete: []);
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
final daysAgo = DateTime.now().difference(date).inDays;
|
final daysAgo = DateTime.now().difference(date).inDays;
|
||||||
_settingsRepository.write(.cleanupCutoffDaysAgo, daysAgo);
|
_metadataRepository.write(.cleanupCutoffDaysAgo, daysAgo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKeepMediaType(AssetKeepType keepMediaType) {
|
void setKeepMediaType(AssetKeepType keepMediaType) {
|
||||||
state = state.copyWith(keepMediaType: keepMediaType, assetsToDelete: []);
|
state = state.copyWith(keepMediaType: keepMediaType, assetsToDelete: []);
|
||||||
_settingsRepository.write(.cleanupKeepMediaType, keepMediaType);
|
_metadataRepository.write(.cleanupKeepMediaType, keepMediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKeepFavorites(bool keepFavorites) {
|
void setKeepFavorites(bool keepFavorites) {
|
||||||
state = state.copyWith(keepFavorites: keepFavorites, assetsToDelete: []);
|
state = state.copyWith(keepFavorites: keepFavorites, assetsToDelete: []);
|
||||||
_settingsRepository.write(.cleanupKeepFavorites, keepFavorites);
|
_metadataRepository.write(.cleanupKeepFavorites, keepFavorites);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleKeepAlbum(String albumId) {
|
void toggleKeepAlbum(String albumId) {
|
||||||
@@ -118,7 +118,7 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _persistExcludedAlbumIds(Set<String> albumIds) {
|
void _persistExcludedAlbumIds(Set<String> albumIds) {
|
||||||
_settingsRepository.write(.cleanupKeepAlbumIds, albumIds.toList());
|
_metadataRepository.write(.cleanupKeepAlbumIds, albumIds.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanupStaleAlbumIds(Set<String> existingAlbumIds) {
|
void cleanupStaleAlbumIds(Set<String> existingAlbumIds) {
|
||||||
@@ -131,7 +131,7 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void applyDefaultAlbumSelections(List<(String id, String name)> albums) {
|
void applyDefaultAlbumSelections(List<(String id, String name)> albums) {
|
||||||
final isInitialized = _settingsRepository.appConfig.cleanup.defaultsInitialized;
|
final isInitialized = _metadataRepository.appConfig.cleanup.defaultsInitialized;
|
||||||
if (isInitialized) {
|
if (isInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ class CleanupNotifier extends StateNotifier<CleanupState> {
|
|||||||
_persistExcludedAlbumIds(keepAlbumIds);
|
_persistExcludedAlbumIds(keepAlbumIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
_settingsRepository.write(.cleanupDefaultsInitialized, true);
|
_metadataRepository.write(.cleanupDefaultsInitialized, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> scanAssets() async {
|
Future<void> scanAssets() async {
|
||||||
|
|||||||
@@ -5,15 +5,12 @@ 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/enums.dart';
|
import 'package:immich_mobile/constants/enums.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/asset_edit.model.dart';
|
import 'package:immich_mobile/domain/models/asset_edit.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/asset.service.dart';
|
import 'package:immich_mobile/domain/services/asset.service.dart';
|
||||||
import 'package:immich_mobile/domain/services/remote_album.service.dart';
|
|
||||||
import 'package:immich_mobile/models/download/livephotos_medatada.model.dart';
|
import 'package:immich_mobile/models/download/livephotos_medatada.model.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
|
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart' show assetExifProvider;
|
import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart' show assetExifProvider;
|
||||||
import 'package:immich_mobile/providers/infrastructure/tag.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/tag.provider.dart';
|
||||||
@@ -376,52 +373,6 @@ class ActionNotifier extends Notifier<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ActionResult> addToAlbum(ActionSource source, RemoteAlbum album) async {
|
|
||||||
final selected = _getAssets(source).toList(growable: false);
|
|
||||||
if (selected.isEmpty) {
|
|
||||||
return const ActionResult(count: 0, success: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
final candidates = RemoteAlbumService.categorizeCandidates(selected);
|
|
||||||
final remoteIds = candidates.remoteAssetIds;
|
|
||||||
final localAssets = candidates.localAssetsToUpload;
|
|
||||||
final albumNotifier = ref.read(remoteAlbumProvider.notifier);
|
|
||||||
|
|
||||||
int addedRemote = 0;
|
|
||||||
if (remoteIds.isNotEmpty) {
|
|
||||||
try {
|
|
||||||
addedRemote = await albumNotifier.addAssets(album.id, remoteIds);
|
|
||||||
} catch (error, stack) {
|
|
||||||
_logger.severe('Failed to add assets to album ${album.id}', error, stack);
|
|
||||||
return ActionResult(count: 0, success: false, error: error.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep the selection available for retry if the remote add fails. Once the
|
|
||||||
// album mutation succeeds, clear timeline selection so upload overlays can render.
|
|
||||||
if (source == ActionSource.timeline) {
|
|
||||||
ref.read(multiSelectProvider.notifier).reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localAssets.isEmpty) {
|
|
||||||
return ActionResult(count: addedRemote, success: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
final uploadResult = await upload(
|
|
||||||
source,
|
|
||||||
assets: localAssets,
|
|
||||||
onAssetUploaded: (asset, remoteId) async {
|
|
||||||
await albumNotifier.linkUploadedAssetToAlbum(album.id, asset, remoteId);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return ActionResult(
|
|
||||||
count: addedRemote + uploadResult.count,
|
|
||||||
success: uploadResult.success,
|
|
||||||
error: uploadResult.error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<ActionResult> removeFromAlbum(ActionSource source, String albumId) async {
|
Future<ActionResult> removeFromAlbum(ActionSource source, String albumId) async {
|
||||||
final ids = _getRemoteIdsForSource(source);
|
final ids = _getRemoteIdsForSource(source);
|
||||||
try {
|
try {
|
||||||
@@ -544,16 +495,8 @@ class ActionNotifier extends Notifier<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ActionResult> upload(
|
Future<ActionResult> upload(ActionSource source, {List<LocalAsset>? assets}) async {
|
||||||
ActionSource source, {
|
|
||||||
List<LocalAsset>? assets,
|
|
||||||
FutureOr<void> Function(LocalAsset asset, String remoteId)? onAssetUploaded,
|
|
||||||
}) async {
|
|
||||||
final assetsToUpload = assets ?? _getAssets(source).whereType<LocalAsset>().toList();
|
final assetsToUpload = assets ?? _getAssets(source).whereType<LocalAsset>().toList();
|
||||||
final assetById = {for (final a in assetsToUpload) a.id: a};
|
|
||||||
final uploadedAssetIds = <String>{};
|
|
||||||
final failedAssetIds = <String>{};
|
|
||||||
final postUploadTasks = <Future<void>>[];
|
|
||||||
|
|
||||||
final progressNotifier = ref.read(assetUploadProgressProvider.notifier);
|
final progressNotifier = ref.read(assetUploadProgressProvider.notifier);
|
||||||
final cancelToken = Completer<void>();
|
final cancelToken = Completer<void>();
|
||||||
@@ -575,43 +518,16 @@ class ActionNotifier extends Notifier<void> {
|
|||||||
},
|
},
|
||||||
onSuccess: (localAssetId, remoteAssetId) {
|
onSuccess: (localAssetId, remoteAssetId) {
|
||||||
progressNotifier.remove(localAssetId);
|
progressNotifier.remove(localAssetId);
|
||||||
uploadedAssetIds.add(localAssetId);
|
|
||||||
final asset = assetById[localAssetId];
|
|
||||||
final callback = onAssetUploaded;
|
|
||||||
if (asset != null && callback != null) {
|
|
||||||
postUploadTasks.add(
|
|
||||||
Future.sync(() => callback(asset, remoteAssetId)).catchError((Object error, StackTrace stack) {
|
|
||||||
failedAssetIds.add(localAssetId);
|
|
||||||
progressNotifier.setError(localAssetId);
|
|
||||||
_logger.warning('Post-upload callback failed for $localAssetId', error, stack);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onError: (localAssetId, errorMessage) {
|
onError: (localAssetId, errorMessage) {
|
||||||
failedAssetIds.add(localAssetId);
|
|
||||||
progressNotifier.setError(localAssetId);
|
progressNotifier.setError(localAssetId);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
return ActionResult(count: assetsToUpload.length, success: true);
|
||||||
await Future.wait(postUploadTasks);
|
|
||||||
final successCount = uploadedAssetIds.difference(failedAssetIds).length;
|
|
||||||
final isSuccess = successCount == assetsToUpload.length && failedAssetIds.isEmpty;
|
|
||||||
|
|
||||||
return ActionResult(
|
|
||||||
count: successCount,
|
|
||||||
success: isSuccess,
|
|
||||||
error: isSuccess ? null : 'Failed to upload ${assetsToUpload.length - successCount} assets',
|
|
||||||
);
|
|
||||||
} catch (error, stack) {
|
} catch (error, stack) {
|
||||||
_logger.severe('Failed manually upload assets', error, stack);
|
_logger.severe('Failed manually upload assets', error, stack);
|
||||||
|
return ActionResult(count: assetsToUpload.length, success: false, error: error.toString());
|
||||||
return ActionResult(
|
|
||||||
count: uploadedAssetIds.difference(failedAssetIds).length,
|
|
||||||
success: false,
|
|
||||||
error: error.toString(),
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
ref.read(manualUploadCancelTokenProvider.notifier).state = null;
|
ref.read(manualUploadCancelTokenProvider.notifier).state = null;
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
|||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
|
|
||||||
final settingsProvider = Provider.autoDispose<SettingsRepository>((_) => SettingsRepository.instance);
|
final metadataProvider = Provider.autoDispose<MetadataRepository>((_) => MetadataRepository.instance);
|
||||||
|
|
||||||
final appConfigProvider = Provider.autoDispose<AppConfig>((ref) {
|
final appConfigProvider = Provider.autoDispose<AppConfig>((ref) {
|
||||||
final repo = ref.watch(settingsProvider);
|
final repo = ref.watch(metadataProvider);
|
||||||
final subscription = repo.watchConfig().listen((event) => ref.state = event);
|
final subscription = repo.watchConfig().listen((event) => ref.state = event);
|
||||||
ref.onDispose(subscription.cancel);
|
ref.onDispose(subscription.cancel);
|
||||||
return repo.appConfig;
|
return repo.appConfig;
|
||||||
@@ -9,7 +9,6 @@ import 'package:immich_mobile/domain/services/remote_album.service.dart';
|
|||||||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
||||||
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
||||||
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
|
import 'package:immich_mobile/providers/album/pending_album_uploads.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/asset_upload_progress.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||||
@@ -208,22 +207,6 @@ class RemoteAlbumNotifier extends Notifier<RemoteAlbumState> {
|
|||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Links a freshly-uploaded local asset to an album using its new remote ID,
|
|
||||||
/// upserting a placeholder remote asset row so the local DB join survives
|
|
||||||
/// until the next sync catches up.
|
|
||||||
Future<int> linkUploadedAssetToAlbum(String albumId, LocalAsset source, String remoteId) async {
|
|
||||||
final currentUser = ref.read(currentUserProvider);
|
|
||||||
if (currentUser == null) {
|
|
||||||
throw Exception('User not logged in');
|
|
||||||
}
|
|
||||||
|
|
||||||
final added = await _remoteAlbumService.linkUploadedAssetToAlbum(albumId, remoteId, currentUser, source);
|
|
||||||
if (added > 0) {
|
|
||||||
await _refreshAlbumInState(albumId);
|
|
||||||
}
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds a heterogeneous asset selection to an album. Already-remote assets
|
/// Adds a heterogeneous asset selection to an album. Already-remote assets
|
||||||
/// are linked immediately; local-only assets are queued in
|
/// are linked immediately; local-only assets are queued in
|
||||||
/// [pendingAlbumUploadsProvider] (so the album page can show them with
|
/// [pendingAlbumUploadsProvider] (so the album page can show them with
|
||||||
@@ -238,18 +221,11 @@ class RemoteAlbumNotifier extends Notifier<RemoteAlbumState> {
|
|||||||
final pendingNotifier = ref.read(pendingAlbumUploadsProvider(albumId).notifier);
|
final pendingNotifier = ref.read(pendingAlbumUploadsProvider(albumId).notifier);
|
||||||
pendingNotifier.enqueue(candidates.localAssetsToUpload);
|
pendingNotifier.enqueue(candidates.localAssetsToUpload);
|
||||||
|
|
||||||
Completer<void>? cancelToken;
|
|
||||||
if (candidates.localAssetsToUpload.isNotEmpty) {
|
|
||||||
cancelToken = Completer<void>();
|
|
||||||
ref.read(manualUploadCancelTokenProvider.notifier).state = cancelToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final added = await _remoteAlbumService.addAssetsToAlbum(
|
final added = await _remoteAlbumService.addAssetsToAlbum(
|
||||||
albumId: albumId,
|
albumId: albumId,
|
||||||
uploader: currentUser,
|
uploader: currentUser,
|
||||||
candidates: candidates,
|
candidates: candidates,
|
||||||
cancelToken: cancelToken,
|
|
||||||
uploadCallbacks: UploadCallbacks(
|
uploadCallbacks: UploadCallbacks(
|
||||||
onProgress: (localAssetId, _, bytes, totalBytes) {
|
onProgress: (localAssetId, _, bytes, totalBytes) {
|
||||||
final progress = totalBytes > 0 ? bytes / totalBytes : 0.0;
|
final progress = totalBytes > 0 ? bytes / totalBytes : 0.0;
|
||||||
@@ -269,15 +245,6 @@ class RemoteAlbumNotifier extends Notifier<RemoteAlbumState> {
|
|||||||
}
|
}
|
||||||
_logger.severe('Failed to add assets to album $albumId', error, stack);
|
_logger.severe('Failed to add assets to album $albumId', error, stack);
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
|
||||||
if (cancelToken != null) {
|
|
||||||
if (cancelToken.isCompleted) {
|
|
||||||
pendingNotifier.clear();
|
|
||||||
}
|
|
||||||
if (ref.read(manualUploadCancelTokenProvider) == cancelToken) {
|
|
||||||
ref.read(manualUploadCancelTokenProvider.notifier).state = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:immich_mobile/domain/services/timeline.service.dart';
|
|||||||
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart';
|
import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
|
||||||
final timelineRepositoryProvider = Provider<DriftTimelineRepository>(
|
final timelineRepositoryProvider = Provider<DriftTimelineRepository>(
|
||||||
@@ -29,7 +29,7 @@ final timelineServiceProvider = Provider<TimelineService>(
|
|||||||
final timelineFactoryProvider = Provider<TimelineFactory>(
|
final timelineFactoryProvider = Provider<TimelineFactory>(
|
||||||
(ref) => TimelineFactory(
|
(ref) => TimelineFactory(
|
||||||
timelineRepository: ref.watch(timelineRepositoryProvider),
|
timelineRepository: ref.watch(timelineRepositoryProvider),
|
||||||
settingsRepository: ref.watch(settingsProvider),
|
metadataRepository: ref.watch(metadataProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
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/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/models/map/map_state.model.dart';
|
import 'package:immich_mobile/models/map/map_state.model.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||||
|
|
||||||
final mapStateNotifierProvider = NotifierProvider<MapStateNotifier, MapState>(MapStateNotifier.new);
|
final mapStateNotifierProvider = NotifierProvider<MapStateNotifier, MapState>(MapStateNotifier.new);
|
||||||
@@ -26,12 +27,12 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void switchTheme(ThemeMode mode) {
|
void switchTheme(ThemeMode mode) {
|
||||||
ref.read(settingsProvider).write(.mapThemeMode, mode);
|
ref.read(metadataProvider).write(MetadataKey.mapThemeMode, mode);
|
||||||
state = state.copyWith(themeMode: mode);
|
state = state.copyWith(themeMode: mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchFavoriteOnly(bool isFavoriteOnly) {
|
void switchFavoriteOnly(bool isFavoriteOnly) {
|
||||||
ref.read(settingsProvider).write(.mapShowFavoriteOnly, isFavoriteOnly);
|
ref.read(metadataProvider).write(MetadataKey.mapShowFavoriteOnly, isFavoriteOnly);
|
||||||
state = state.copyWith(showFavoriteOnly: isFavoriteOnly, shouldRefetchMarkers: true);
|
state = state.copyWith(showFavoriteOnly: isFavoriteOnly, shouldRefetchMarkers: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,17 +41,17 @@ class MapStateNotifier extends Notifier<MapState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void switchIncludeArchived(bool isIncludeArchived) {
|
void switchIncludeArchived(bool isIncludeArchived) {
|
||||||
ref.read(settingsProvider).write(.mapIncludeArchived, isIncludeArchived);
|
ref.read(metadataProvider).write(MetadataKey.mapIncludeArchived, isIncludeArchived);
|
||||||
state = state.copyWith(includeArchived: isIncludeArchived, shouldRefetchMarkers: true);
|
state = state.copyWith(includeArchived: isIncludeArchived, shouldRefetchMarkers: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchWithPartners(bool isWithPartners) {
|
void switchWithPartners(bool isWithPartners) {
|
||||||
ref.read(settingsProvider).write(.mapWithPartners, isWithPartners);
|
ref.read(metadataProvider).write(MetadataKey.mapWithPartners, isWithPartners);
|
||||||
state = state.copyWith(withPartners: isWithPartners, shouldRefetchMarkers: true);
|
state = state.copyWith(withPartners: isWithPartners, shouldRefetchMarkers: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRelativeTime(int relativeTime) {
|
void setRelativeTime(int relativeTime) {
|
||||||
ref.read(settingsProvider).write(.mapRelativeDate, relativeTime);
|
ref.read(metadataProvider).write(MetadataKey.mapRelativeDate, relativeTime);
|
||||||
state = state.copyWith(relativeTime: relativeTime, shouldRefetchMarkers: true);
|
state = state.copyWith(relativeTime: relativeTime, shouldRefetchMarkers: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/theme/color_scheme.dart';
|
import 'package:immich_mobile/theme/color_scheme.dart';
|
||||||
import 'package:immich_mobile/theme/dynamic_theme.dart';
|
import 'package:immich_mobile/theme/dynamic_theme.dart';
|
||||||
import 'package:immich_mobile/theme/theme_data.dart';
|
import 'package:immich_mobile/theme/theme_data.dart';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:immich_mobile/infrastructure/repositories/network.repository.dar
|
|||||||
import 'package:immich_mobile/models/server_info/server_version.model.dart';
|
import 'package:immich_mobile/models/server_info/server_version.model.dart';
|
||||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||||
import 'package:immich_mobile/utils/debounce.dart';
|
import 'package:immich_mobile/utils/debounce.dart';
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
@@ -193,7 +193,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isSyncAlbumEnabled = _ref.read(appConfigProvider).backup.syncAlbums;
|
final isSyncAlbumEnabled = _ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
||||||
try {
|
try {
|
||||||
unawaited(
|
unawaited(
|
||||||
_ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) {
|
_ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) {
|
||||||
@@ -214,7 +214,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isSyncAlbumEnabled = _ref.read(appConfigProvider).backup.syncAlbums;
|
final isSyncAlbumEnabled = _ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
||||||
try {
|
try {
|
||||||
unawaited(
|
unawaited(
|
||||||
_ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) {
|
_ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) {
|
||||||
|
|||||||
@@ -1,40 +1,38 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/config/app_config.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/settings.repository.dart';
|
|
||||||
import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart';
|
||||||
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
|
|
||||||
final authRepositoryProvider = Provider<AuthRepository>(
|
final authRepositoryProvider = Provider<AuthRepository>(
|
||||||
(ref) => AuthRepository(ref.watch(driftProvider), ref.watch(settingsProvider)),
|
(ref) => AuthRepository(ref.watch(driftProvider), ref.watch(appConfigProvider)),
|
||||||
);
|
);
|
||||||
|
|
||||||
class AuthRepository {
|
class AuthRepository {
|
||||||
final Drift _drift;
|
final Drift _drift;
|
||||||
final SettingsRepository _settings;
|
final AppConfig _config;
|
||||||
|
|
||||||
const AuthRepository(this._drift, this._settings);
|
const AuthRepository(this._drift, this._config);
|
||||||
|
|
||||||
Future<void> clearLocalData() async {
|
Future<void> clearLocalData() async {
|
||||||
await SyncStreamRepository(_drift).reset();
|
await SyncStreamRepository(_drift).reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getEndpointSwitchingFeature() {
|
bool getEndpointSwitchingFeature() {
|
||||||
return _settings.appConfig.network.autoEndpointSwitching;
|
return _config.network.autoEndpointSwitching;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? getPreferredWifiName() {
|
String? getPreferredWifiName() {
|
||||||
return _settings.appConfig.network.preferredWifiName;
|
return _config.network.preferredWifiName;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? getLocalEndpoint() {
|
String? getLocalEndpoint() {
|
||||||
return _settings.appConfig.network.localEndpoint;
|
return _config.network.localEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AuxilaryEndpoint> getExternalEndpointList() {
|
List<AuxilaryEndpoint> getExternalEndpointList() {
|
||||||
return _settings.appConfig.network.externalEndpointList
|
return _config.network.externalEndpointList.map((url) => AuxilaryEndpoint(url: url, status: .valid)).toList();
|
||||||
.map((url) => AuxilaryEndpoint(url: url, status: .valid))
|
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'dart:io';
|
|||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||||
import 'package:immich_mobile/utils/debug_print.dart';
|
import 'package:immich_mobile/utils/debug_print.dart';
|
||||||
import 'package:immich_mobile/utils/url_helper.dart';
|
import 'package:immich_mobile/utils/url_helper.dart';
|
||||||
@@ -177,7 +177,7 @@ class ApiService {
|
|||||||
if (serverEndpoint != null && serverEndpoint.isNotEmpty) {
|
if (serverEndpoint != null && serverEndpoint.isNotEmpty) {
|
||||||
urls.add(serverEndpoint);
|
urls.add(serverEndpoint);
|
||||||
}
|
}
|
||||||
final network = SettingsRepository.instance.appConfig.network;
|
final network = MetadataRepository.instance.appConfig.network;
|
||||||
final localEndpoint = network.localEndpoint;
|
final localEndpoint = network.localEndpoint;
|
||||||
if (localEndpoint.isNotEmpty) {
|
if (localEndpoint.isNotEmpty) {
|
||||||
urls.add(localEndpoint);
|
urls.add(localEndpoint);
|
||||||
@@ -191,7 +191,7 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, String> getRequestHeaders() {
|
static Map<String, String> getRequestHeaders() {
|
||||||
return SettingsRepository.instance.appConfig.network.customHeaders;
|
return MetadataRepository.instance.appConfig.network.customHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiClient get apiClient => _apiClient;
|
ApiClient get apiClient => _apiClient;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/domain/utils/background_sync.dart';
|
import 'package:immich_mobile/domain/utils/background_sync.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||||
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
||||||
import 'package:immich_mobile/models/auth/login_response.model.dart';
|
import 'package:immich_mobile/models/auth/login_response.model.dart';
|
||||||
@@ -100,7 +100,7 @@ class AuthService {
|
|||||||
_log.severe("Error clearing local data", error, stackTrace);
|
_log.severe("Error clearing local data", error, stackTrace);
|
||||||
});
|
});
|
||||||
|
|
||||||
await SettingsRepository.instance.write(SettingsKey.backupEnabled, false);
|
await MetadataRepository.instance.write(MetadataKey.backupEnabled, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ class AuthService {
|
|||||||
_authRepository.clearLocalData(),
|
_authRepository.clearLocalData(),
|
||||||
Store.delete(StoreKey.currentUser),
|
Store.delete(StoreKey.currentUser),
|
||||||
Store.delete(StoreKey.accessToken),
|
Store.delete(StoreKey.accessToken),
|
||||||
SettingsRepository.instance.clear(const [
|
MetadataRepository.instance.clear(const [
|
||||||
.networkAutoEndpointSwitching,
|
.networkAutoEndpointSwitching,
|
||||||
.networkPreferredWifiName,
|
.networkPreferredWifiName,
|
||||||
.networkLocalEndpoint,
|
.networkLocalEndpoint,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
@@ -359,7 +359,7 @@ class BackgroundUploadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _shouldRequireWiFi(LocalAsset asset) {
|
bool _shouldRequireWiFi(LocalAsset asset) {
|
||||||
final backup = SettingsRepository.instance.appConfig.backup;
|
final backup = MetadataRepository.instance.appConfig.backup;
|
||||||
if (asset.isVideo && backup.useCellularForVideos) {
|
if (asset.isVideo && backup.useCellularForVideos) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import 'package:immich_mobile/extensions/network_capability_extensions.dart';
|
|||||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
import 'package:immich_mobile/platform/connectivity_api.g.dart';
|
import 'package:immich_mobile/platform/connectivity_api.g.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||||
@@ -451,7 +451,7 @@ class ForegroundUploadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _shouldRequireWiFi(LocalAsset asset) {
|
bool _shouldRequireWiFi(LocalAsset asset) {
|
||||||
final backup = SettingsRepository.instance.appConfig.backup;
|
final backup = MetadataRepository.instance.appConfig.backup;
|
||||||
if (asset.isVideo && backup.useCellularForVideos) {
|
if (asset.isVideo && backup.useCellularForVideos) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:immich_mobile/extensions/translate_extensions.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/log.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/log.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/infrastructure/repositories/settings.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart';
|
import 'package:photo_manager/photo_manager.dart';
|
||||||
@@ -49,11 +49,11 @@ abstract final class Bootstrap {
|
|||||||
|
|
||||||
await StoreService.init(storeRepository: storeRepo, listenUpdates: listenStoreUpdates);
|
await StoreService.init(storeRepository: storeRepo, listenUpdates: listenStoreUpdates);
|
||||||
|
|
||||||
final settingsRepo = await SettingsRepository.ensureInitialized(drift);
|
final metadataRepo = await MetadataRepository.ensureInitialized(drift);
|
||||||
|
|
||||||
await LogService.init(
|
await LogService.init(
|
||||||
logRepository: LogRepository(logDb),
|
logRepository: LogRepository(logDb),
|
||||||
settingsRepository: settingsRepo,
|
metadataRepository: metadataRepo,
|
||||||
shouldBuffer: shouldBufferLogs,
|
shouldBuffer: shouldBufferLogs,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import 'package:immich_mobile/constants/colors.dart';
|
|||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
import 'package:immich_mobile/domain/models/metadata_key.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.drift.dart';
|
import 'package:immich_mobile/infrastructure/entities/metadata.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/network.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||||
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
||||||
@@ -74,65 +74,65 @@ Future<void> _migrateTo25() async {
|
|||||||
|
|
||||||
Future<void> _migrateTo26(Drift drift) async {
|
Future<void> _migrateTo26(Drift drift) async {
|
||||||
final migrator = _StoreMigrator(drift);
|
final migrator = _StoreMigrator(drift);
|
||||||
await migrator.migrateEnumIndex(StoreKey.legacyLogLevel, SettingsKey.logLevel, LogLevel.values);
|
await migrator.migrateEnumIndex(StoreKey.legacyLogLevel, MetadataKey.logLevel, LogLevel.values);
|
||||||
// Theme
|
// Theme
|
||||||
await migrator.migrateEnumName(StoreKey.legacyThemeMode, SettingsKey.themeMode, ThemeMode.values);
|
await migrator.migrateEnumName(StoreKey.legacyThemeMode, MetadataKey.themeMode, ThemeMode.values);
|
||||||
await migrator.migrateEnumName(StoreKey.legacyPrimaryColor, SettingsKey.themePrimaryColor, ImmichColorPreset.values);
|
await migrator.migrateEnumName(StoreKey.legacyPrimaryColor, MetadataKey.themePrimaryColor, ImmichColorPreset.values);
|
||||||
await migrator.migrateBool(StoreKey.legacyDynamicTheme, SettingsKey.themeDynamic);
|
await migrator.migrateBool(StoreKey.legacyDynamicTheme, MetadataKey.themeDynamic);
|
||||||
await migrator.migrateBool(StoreKey.legacyColorfulInterface, SettingsKey.themeColorfulInterface);
|
await migrator.migrateBool(StoreKey.legacyColorfulInterface, MetadataKey.themeColorfulInterface);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
final cleanupKeepAlbumIds = await migrator.readLegacyStoreString(StoreKey.legacyCleanupKeepAlbumIds.id);
|
final cleanupKeepAlbumIds = await migrator.readLegacyStoreString(StoreKey.legacyCleanupKeepAlbumIds.id);
|
||||||
if (cleanupKeepAlbumIds != null) {
|
if (cleanupKeepAlbumIds != null) {
|
||||||
final ids = cleanupKeepAlbumIds.split(',').where((id) => id.isNotEmpty).toList();
|
final ids = cleanupKeepAlbumIds.split(',').where((id) => id.isNotEmpty).toList();
|
||||||
migrator.stage(StoreKey.legacyCleanupKeepAlbumIds, SettingsKey.cleanupKeepAlbumIds, ids);
|
migrator.stage(StoreKey.legacyCleanupKeepAlbumIds, MetadataKey.cleanupKeepAlbumIds, ids);
|
||||||
}
|
}
|
||||||
await migrator.migrateBool(StoreKey.legacyCleanupKeepFavorites, SettingsKey.cleanupKeepFavorites);
|
await migrator.migrateBool(StoreKey.legacyCleanupKeepFavorites, MetadataKey.cleanupKeepFavorites);
|
||||||
await migrator.migrateEnumIndex(
|
await migrator.migrateEnumIndex(
|
||||||
StoreKey.legacyCleanupKeepMediaType,
|
StoreKey.legacyCleanupKeepMediaType,
|
||||||
SettingsKey.cleanupKeepMediaType,
|
MetadataKey.cleanupKeepMediaType,
|
||||||
AssetKeepType.values,
|
AssetKeepType.values,
|
||||||
);
|
);
|
||||||
await migrator.migrateInt(StoreKey.legacyCleanupCutoffDaysAgo, SettingsKey.cleanupCutoffDaysAgo);
|
await migrator.migrateInt(StoreKey.legacyCleanupCutoffDaysAgo, MetadataKey.cleanupCutoffDaysAgo);
|
||||||
await migrator.migrateBool(StoreKey.legacyCleanupDefaultsInitialized, SettingsKey.cleanupDefaultsInitialized);
|
await migrator.migrateBool(StoreKey.legacyCleanupDefaultsInitialized, MetadataKey.cleanupDefaultsInitialized);
|
||||||
// Map
|
// Map
|
||||||
await migrator.migrateBool(StoreKey.legacyMapShowFavoriteOnly, SettingsKey.mapShowFavoriteOnly);
|
await migrator.migrateBool(StoreKey.legacyMapShowFavoriteOnly, MetadataKey.mapShowFavoriteOnly);
|
||||||
await migrator.migrateInt(StoreKey.legacyMapRelativeDate, SettingsKey.mapRelativeDate);
|
await migrator.migrateInt(StoreKey.legacyMapRelativeDate, MetadataKey.mapRelativeDate);
|
||||||
await migrator.migrateBool(StoreKey.legacyMapIncludeArchived, SettingsKey.mapIncludeArchived);
|
await migrator.migrateBool(StoreKey.legacyMapIncludeArchived, MetadataKey.mapIncludeArchived);
|
||||||
await migrator.migrateEnumIndex(StoreKey.legacyMapThemeMode, SettingsKey.mapThemeMode, ThemeMode.values);
|
await migrator.migrateEnumIndex(StoreKey.legacyMapThemeMode, MetadataKey.mapThemeMode, ThemeMode.values);
|
||||||
await migrator.migrateBool(StoreKey.legacyMapwithPartners, SettingsKey.mapWithPartners);
|
await migrator.migrateBool(StoreKey.legacyMapwithPartners, MetadataKey.mapWithPartners);
|
||||||
// Timeline
|
// Timeline
|
||||||
await migrator.migrateInt(StoreKey.legacyTilesPerRow, SettingsKey.timelineTilesPerRow);
|
await migrator.migrateInt(StoreKey.legacyTilesPerRow, MetadataKey.timelineTilesPerRow);
|
||||||
await migrator.migrateEnumIndex(
|
await migrator.migrateEnumIndex(
|
||||||
StoreKey.legacyGroupAssetsBy,
|
StoreKey.legacyGroupAssetsBy,
|
||||||
SettingsKey.timelineGroupAssetsBy,
|
MetadataKey.timelineGroupAssetsBy,
|
||||||
GroupAssetsBy.values,
|
GroupAssetsBy.values,
|
||||||
);
|
);
|
||||||
await migrator.migrateBool(StoreKey.legacyStorageIndicator, SettingsKey.timelineStorageIndicator);
|
await migrator.migrateBool(StoreKey.legacyStorageIndicator, MetadataKey.timelineStorageIndicator);
|
||||||
// Image
|
// Image
|
||||||
await migrator.migrateBool(StoreKey.legacyPreferRemoteImage, SettingsKey.imagePreferRemote);
|
await migrator.migrateBool(StoreKey.legacyPreferRemoteImage, MetadataKey.imagePreferRemote);
|
||||||
await migrator.migrateBool(StoreKey.legacyLoadOriginal, SettingsKey.imageLoadOriginal);
|
await migrator.migrateBool(StoreKey.legacyLoadOriginal, MetadataKey.imageLoadOriginal);
|
||||||
// Viewer
|
// Viewer
|
||||||
await migrator.migrateBool(StoreKey.legacyLoopVideo, SettingsKey.viewerLoopVideo);
|
await migrator.migrateBool(StoreKey.legacyLoopVideo, MetadataKey.viewerLoopVideo);
|
||||||
await migrator.migrateBool(StoreKey.legacyLoadOriginalVideo, SettingsKey.viewerLoadOriginalVideo);
|
await migrator.migrateBool(StoreKey.legacyLoadOriginalVideo, MetadataKey.viewerLoadOriginalVideo);
|
||||||
await migrator.migrateBool(StoreKey.legacyAutoPlayVideo, SettingsKey.viewerAutoPlayVideo);
|
await migrator.migrateBool(StoreKey.legacyAutoPlayVideo, MetadataKey.viewerAutoPlayVideo);
|
||||||
await migrator.migrateBool(StoreKey.legacyTapToNavigate, SettingsKey.viewerTapToNavigate);
|
await migrator.migrateBool(StoreKey.legacyTapToNavigate, MetadataKey.viewerTapToNavigate);
|
||||||
// Network
|
// Network
|
||||||
await migrator.migrateBool(StoreKey.legacyAutoEndpointSwitching, SettingsKey.networkAutoEndpointSwitching);
|
await migrator.migrateBool(StoreKey.legacyAutoEndpointSwitching, MetadataKey.networkAutoEndpointSwitching);
|
||||||
await migrator.migrateString(StoreKey.legacyPreferredWifiName, SettingsKey.networkPreferredWifiName);
|
await migrator.migrateString(StoreKey.legacyPreferredWifiName, MetadataKey.networkPreferredWifiName);
|
||||||
await migrator.migrateString(StoreKey.legacyLocalEndpoint, SettingsKey.networkLocalEndpoint);
|
await migrator.migrateString(StoreKey.legacyLocalEndpoint, MetadataKey.networkLocalEndpoint);
|
||||||
await _migrateExternalEndpointList(migrator);
|
await _migrateExternalEndpointList(migrator);
|
||||||
await _migrateCustomHeaders(migrator);
|
await _migrateCustomHeaders(migrator);
|
||||||
// Album
|
// Album
|
||||||
await _migrateAlbumSortMode(migrator);
|
await _migrateAlbumSortMode(migrator);
|
||||||
await migrator.migrateBool(StoreKey.legacySelectedAlbumSortReverse, SettingsKey.albumIsReverse);
|
await migrator.migrateBool(StoreKey.legacySelectedAlbumSortReverse, MetadataKey.albumIsReverse);
|
||||||
await migrator.migrateBool(StoreKey.legacyAlbumGridView, SettingsKey.albumIsGrid);
|
await migrator.migrateBool(StoreKey.legacyAlbumGridView, MetadataKey.albumIsGrid);
|
||||||
// Backup
|
// Backup
|
||||||
await migrator.migrateBool(StoreKey.legacyEnableBackup, SettingsKey.backupEnabled);
|
await migrator.migrateBool(StoreKey.legacyEnableBackup, MetadataKey.backupEnabled);
|
||||||
await migrator.migrateBool(StoreKey.legacyUseWifiForUploadVideos, SettingsKey.backupUseCellularForVideos);
|
await migrator.migrateBool(StoreKey.legacyUseWifiForUploadVideos, MetadataKey.backupUseCellularForVideos);
|
||||||
await migrator.migrateBool(StoreKey.legacyUseWifiForUploadPhotos, SettingsKey.backupUseCellularForPhotos);
|
await migrator.migrateBool(StoreKey.legacyUseWifiForUploadPhotos, MetadataKey.backupUseCellularForPhotos);
|
||||||
await migrator.migrateBool(StoreKey.legacyBackupRequireCharging, SettingsKey.backupRequireCharging);
|
await migrator.migrateBool(StoreKey.legacyBackupRequireCharging, MetadataKey.backupRequireCharging);
|
||||||
await migrator.migrateInt(StoreKey.legacyBackupTriggerDelay, SettingsKey.backupTriggerDelay);
|
await migrator.migrateInt(StoreKey.legacyBackupTriggerDelay, MetadataKey.backupTriggerDelay);
|
||||||
await migrator.migrateBool(StoreKey.legacySyncAlbums, SettingsKey.backupSyncAlbums);
|
await migrator.migrateBool(StoreKey.legacySyncAlbums, MetadataKey.backupSyncAlbums);
|
||||||
await migrator.complete();
|
await migrator.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ Future<void> _migrateAlbumSortMode(_StoreMigrator migrator) async {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
migrator.stage(StoreKey.legacySelectedAlbumSortOrder, SettingsKey.albumSortMode, mode);
|
migrator.stage(StoreKey.legacySelectedAlbumSortOrder, MetadataKey.albumSortMode, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _migrateExternalEndpointList(_StoreMigrator migrator) async {
|
Future<void> _migrateExternalEndpointList(_StoreMigrator migrator) async {
|
||||||
@@ -167,7 +167,7 @@ Future<void> _migrateExternalEndpointList(_StoreMigrator migrator) async {
|
|||||||
// ignore invalid entries
|
// ignore invalid entries
|
||||||
}
|
}
|
||||||
|
|
||||||
migrator.stage(StoreKey.legacyExternalEndpointList, SettingsKey.networkExternalEndpointList, urls);
|
migrator.stage(StoreKey.legacyExternalEndpointList, MetadataKey.networkExternalEndpointList, urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _migrateCustomHeaders(_StoreMigrator migrator) async {
|
Future<void> _migrateCustomHeaders(_StoreMigrator migrator) async {
|
||||||
@@ -190,17 +190,17 @@ Future<void> _migrateCustomHeaders(_StoreMigrator migrator) async {
|
|||||||
// ignore invalid entries
|
// ignore invalid entries
|
||||||
}
|
}
|
||||||
|
|
||||||
migrator.stage(StoreKey.legacyCustomHeaders, SettingsKey.networkCustomHeaders, headers);
|
migrator.stage(StoreKey.legacyCustomHeaders, MetadataKey.networkCustomHeaders, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StoreMigrator {
|
class _StoreMigrator {
|
||||||
final Drift _db;
|
final Drift _db;
|
||||||
final Map<SettingsKey<Object>, Object> _cache = {};
|
final Map<MetadataKey<Object>, Object> _cache = {};
|
||||||
final List<int> _migratedStoreIds = [];
|
final List<int> _migratedStoreIds = [];
|
||||||
|
|
||||||
_StoreMigrator(this._db);
|
_StoreMigrator(this._db);
|
||||||
|
|
||||||
Future<void> migrateEnumIndex<T extends Enum>(StoreKey<int> legacyKey, SettingsKey<T> newKey, List<T> values) async {
|
Future<void> migrateEnumIndex<T extends Enum>(StoreKey<int> legacyKey, MetadataKey<T> newKey, List<T> values) async {
|
||||||
final index = await readLegacyStoreInt(legacyKey.id);
|
final index = await readLegacyStoreInt(legacyKey.id);
|
||||||
if (index == null) {
|
if (index == null) {
|
||||||
return;
|
return;
|
||||||
@@ -217,7 +217,7 @@ class _StoreMigrator {
|
|||||||
|
|
||||||
Future<void> migrateEnumName<T extends Enum>(
|
Future<void> migrateEnumName<T extends Enum>(
|
||||||
StoreKey<String> legacyKey,
|
StoreKey<String> legacyKey,
|
||||||
SettingsKey<T> newKey,
|
MetadataKey<T> newKey,
|
||||||
List<T> values,
|
List<T> values,
|
||||||
) async {
|
) async {
|
||||||
final name = await readLegacyStoreString(legacyKey.id);
|
final name = await readLegacyStoreString(legacyKey.id);
|
||||||
@@ -234,7 +234,7 @@ class _StoreMigrator {
|
|||||||
_migratedStoreIds.add(legacyKey.id);
|
_migratedStoreIds.add(legacyKey.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrateBool(StoreKey<bool> legacyKey, SettingsKey<bool> newKey) async {
|
Future<void> migrateBool(StoreKey<bool> legacyKey, MetadataKey<bool> newKey) async {
|
||||||
final intValue = await readLegacyStoreInt(legacyKey.id);
|
final intValue = await readLegacyStoreInt(legacyKey.id);
|
||||||
if (intValue == null) {
|
if (intValue == null) {
|
||||||
return;
|
return;
|
||||||
@@ -245,7 +245,7 @@ class _StoreMigrator {
|
|||||||
_migratedStoreIds.add(legacyKey.id);
|
_migratedStoreIds.add(legacyKey.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrateInt(StoreKey<int> legacyKey, SettingsKey<int> newKey) async {
|
Future<void> migrateInt(StoreKey<int> legacyKey, MetadataKey<int> newKey) async {
|
||||||
final intValue = await readLegacyStoreInt(legacyKey.id);
|
final intValue = await readLegacyStoreInt(legacyKey.id);
|
||||||
if (intValue == null) {
|
if (intValue == null) {
|
||||||
return;
|
return;
|
||||||
@@ -255,7 +255,7 @@ class _StoreMigrator {
|
|||||||
_migratedStoreIds.add(legacyKey.id);
|
_migratedStoreIds.add(legacyKey.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> migrateString(StoreKey<String> legacyKey, SettingsKey<String> newKey) async {
|
Future<void> migrateString(StoreKey<String> legacyKey, MetadataKey<String> newKey) async {
|
||||||
final value = await readLegacyStoreString(legacyKey.id);
|
final value = await readLegacyStoreString(legacyKey.id);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return;
|
return;
|
||||||
@@ -265,7 +265,7 @@ class _StoreMigrator {
|
|||||||
_migratedStoreIds.add(legacyKey.id);
|
_migratedStoreIds.add(legacyKey.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stage<T extends Object>(StoreKey legacyKey, SettingsKey<T> newKey, T value) {
|
void stage<T extends Object>(StoreKey legacyKey, MetadataKey<T> newKey, T value) {
|
||||||
_cache[newKey] = value;
|
_cache[newKey] = value;
|
||||||
_migratedStoreIds.add(legacyKey.id);
|
_migratedStoreIds.add(legacyKey.id);
|
||||||
}
|
}
|
||||||
@@ -277,8 +277,8 @@ class _StoreMigrator {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
batch.insert(
|
batch.insert(
|
||||||
_db.settingsEntity,
|
_db.metadataEntity,
|
||||||
SettingsEntityCompanion(key: Value(entry.key.name), value: Value(entry.key.encode(entry.value))),
|
MetadataEntityCompanion(key: Value(entry.key.name), value: Value(entry.key.encode(entry.value))),
|
||||||
mode: InsertMode.insertOrReplace,
|
mode: InsertMode.insertOrReplace,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,36 @@
|
|||||||
enum SemVerType { major, minor, patch, prerelease }
|
enum SemVerType { major, minor, patch }
|
||||||
|
|
||||||
class SemVer {
|
class SemVer {
|
||||||
final int major;
|
final int major;
|
||||||
final int minor;
|
final int minor;
|
||||||
final int patch;
|
final int patch;
|
||||||
final int? prerelease;
|
|
||||||
|
|
||||||
const SemVer({required this.major, required this.minor, required this.patch, this.prerelease});
|
const SemVer({required this.major, required this.minor, required this.patch});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return '$major.$minor.$patch${prerelease == null ? '' : '-rc.$prerelease'}';
|
return '$major.$minor.$patch';
|
||||||
}
|
}
|
||||||
|
|
||||||
SemVer copyWith({int? major, int? minor, int? patch, int? prerelease}) {
|
SemVer copyWith({int? major, int? minor, int? patch}) {
|
||||||
return SemVer(
|
return SemVer(major: major ?? this.major, minor: minor ?? this.minor, patch: patch ?? this.patch);
|
||||||
major: major ?? this.major,
|
|
||||||
minor: minor ?? this.minor,
|
|
||||||
patch: patch ?? this.patch,
|
|
||||||
prerelease: prerelease ?? this.prerelease,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final _pattern = RegExp(r'^v?(\d+)\.(\d+)\.(\d+)(?:-rc\.(\d+))?(?:[-+].*)?$', caseSensitive: false);
|
|
||||||
|
|
||||||
factory SemVer.fromString(String version) {
|
factory SemVer.fromString(String version) {
|
||||||
final match = _pattern.firstMatch(version);
|
if (version.toLowerCase().startsWith("v")) {
|
||||||
if (match == null) {
|
version = version.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final parts = version.split("-")[0].split('.');
|
||||||
|
if (parts.length != 3) {
|
||||||
throw FormatException('Invalid semantic version string: $version');
|
throw FormatException('Invalid semantic version string: $version');
|
||||||
}
|
}
|
||||||
|
|
||||||
final prerelease = match.group(4);
|
try {
|
||||||
return SemVer(
|
return SemVer(major: int.parse(parts[0]), minor: int.parse(parts[1]), patch: int.parse(parts[2]));
|
||||||
major: int.parse(match.group(1)!),
|
} catch (e) {
|
||||||
minor: int.parse(match.group(2)!),
|
throw FormatException('Invalid semantic version string: $version');
|
||||||
patch: int.parse(match.group(3)!),
|
}
|
||||||
prerelease: prerelease == null ? null : int.parse(prerelease),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator >(SemVer other) {
|
bool operator >(SemVer other) {
|
||||||
@@ -46,10 +40,7 @@ class SemVer {
|
|||||||
if (minor != other.minor) {
|
if (minor != other.minor) {
|
||||||
return minor > other.minor;
|
return minor > other.minor;
|
||||||
}
|
}
|
||||||
if (patch != other.patch) {
|
return patch > other.patch;
|
||||||
return patch > other.patch;
|
|
||||||
}
|
|
||||||
return _comparePrerelease(other) > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator <(SemVer other) {
|
bool operator <(SemVer other) {
|
||||||
@@ -59,23 +50,7 @@ class SemVer {
|
|||||||
if (minor != other.minor) {
|
if (minor != other.minor) {
|
||||||
return minor < other.minor;
|
return minor < other.minor;
|
||||||
}
|
}
|
||||||
if (patch != other.patch) {
|
return patch < other.patch;
|
||||||
return patch < other.patch;
|
|
||||||
}
|
|
||||||
return _comparePrerelease(other) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _comparePrerelease(SemVer other) {
|
|
||||||
if (prerelease == other.prerelease) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (prerelease == null) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (other.prerelease == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return prerelease!.compareTo(other.prerelease!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator >=(SemVer other) {
|
bool operator >=(SemVer other) {
|
||||||
@@ -92,11 +67,7 @@ class SemVer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return other is SemVer &&
|
return other is SemVer && other.major == major && other.minor == minor && other.patch == patch;
|
||||||
other.major == major &&
|
|
||||||
other.minor == minor &&
|
|
||||||
other.patch == patch &&
|
|
||||||
other.prerelease == prerelease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SemVerType? differenceType(SemVer other) {
|
SemVerType? differenceType(SemVer other) {
|
||||||
@@ -109,13 +80,10 @@ class SemVer {
|
|||||||
if (patch != other.patch) {
|
if (patch != other.patch) {
|
||||||
return SemVerType.patch;
|
return SemVerType.patch;
|
||||||
}
|
}
|
||||||
if (prerelease != other.prerelease) {
|
|
||||||
return SemVerType.prerelease;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => major.hashCode ^ minor.hashCode ^ patch.hashCode ^ prerelease.hashCode;
|
int get hashCode => major.hashCode ^ minor.hashCode ^ patch.hashCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||||||
divider,
|
divider,
|
||||||
_ServerInfoItem(
|
_ServerInfoItem(
|
||||||
label: "server_version".tr(),
|
label: "server_version".tr(),
|
||||||
text: serverInfoState.serverVersion.major > 0 ? "${serverInfoState.serverVersion}" : "--",
|
text: serverInfoState.serverVersion.major > 0
|
||||||
|
? "${serverInfoState.serverVersion.major}.${serverInfoState.serverVersion.minor}.${serverInfoState.serverVersion.patch}"
|
||||||
|
: "--",
|
||||||
),
|
),
|
||||||
divider,
|
divider,
|
||||||
_ServerInfoItem(label: "server_info_box_server_url".tr(), text: getServerUrl() ?? '--', tooltip: true),
|
_ServerInfoItem(label: "server_info_box_server_url".tr(), text: getServerUrl() ?? '--', tooltip: true),
|
||||||
@@ -58,7 +60,9 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||||||
divider,
|
divider,
|
||||||
_ServerInfoItem(
|
_ServerInfoItem(
|
||||||
label: "latest_version".tr(),
|
label: "latest_version".tr(),
|
||||||
text: serverInfoState.latestVersion!.major > 0 ? "${serverInfoState.latestVersion!}" : "--",
|
text: serverInfoState.latestVersion!.major > 0
|
||||||
|
? "${serverInfoState.latestVersion!.major}.${serverInfoState.latestVersion!.minor}.${serverInfoState.latestVersion!.patch}"
|
||||||
|
: "--",
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
icon: serverInfoState.versionStatus == VersionStatus.serverOutOfDate
|
icon: serverInfoState.versionStatus == VersionStatus.serverOutOfDate
|
||||||
? const Icon(Icons.info, color: Color.fromARGB(255, 243, 188, 106), size: 12)
|
? const Icon(Icons.info, color: Color.fromARGB(255, 243, 188, 106), size: 12)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user