mirror of
https://github.com/immich-app/immich.git
synced 2026-05-22 15:42:32 -04:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 04e179c7d6 | |||
| 398f613724 | |||
| 54d7b0feb9 | |||
| 05334569e3 | |||
| c72ad193fa | |||
| 6f8fb9e42b | |||
| 746599319b | |||
| 62578cfad5 | |||
| 4d886ba0ad | |||
| 3005ff0cc4 | |||
| 9ea4a03f21 | |||
| 69143a53b7 | |||
| 86255f8c31 | |||
| b3b651aec0 | |||
| 5e4b64670c | |||
| dd7a51a2d9 | |||
| 646b8249ca | |||
| 352c129d92 | |||
| 3ac91797e8 | |||
| a7d634bacd | |||
| 11cf9ffd85 | |||
| 220891d533 |
@@ -91,7 +91,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -159,14 +159,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Comment APK download link on PR
|
- name: Comment APK download link on PR
|
||||||
if: ${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork }}
|
if: ${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork }}
|
||||||
uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
env:
|
env:
|
||||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
APK_URL: ${{ steps.upload-apk.outputs.artifact-url }}
|
APK_URL: ${{ steps.upload-apk.outputs.artifact-url }}
|
||||||
with:
|
with:
|
||||||
id: mobile-android-apk
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
token: ${{ steps.token.outputs.token }}
|
message-id: 'mobile-android-apk'
|
||||||
body: |
|
message: |
|
||||||
📱 **Android release APK (universal)** — `${{ env.HEAD_SHA }}`
|
📱 **Android release APK (universal)** — `${{ env.HEAD_SHA }}`
|
||||||
|
|
||||||
Download: ${{ env.APK_URL }}
|
Download: ${{ env.APK_URL }}
|
||||||
@@ -216,7 +216,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -230,12 +230,8 @@ jobs:
|
|||||||
- name: Generate platform APIs
|
- name: Generate platform APIs
|
||||||
run: mise //mobile:codegen:pigeon
|
run: mise //mobile:codegen:pigeon
|
||||||
|
|
||||||
- name: Resolve iOS Swift Packages
|
|
||||||
working-directory: ./mobile
|
|
||||||
run: flutter build ios --config-only --no-codesign
|
|
||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
uses: ruby/setup-ruby@6aaa311d81eba98ae12eaffbcb63296ace0efcde # v1.307.0
|
uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
|
||||||
with:
|
with:
|
||||||
ruby-version: '3.3'
|
ruby-version: '3.3'
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
@@ -292,6 +288,7 @@ jobs:
|
|||||||
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
|
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
|
||||||
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
|
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
|
||||||
ENVIRONMENT: ${{ inputs.environment || 'development' }}
|
ENVIRONMENT: ${{ inputs.environment || 'development' }}
|
||||||
|
BUNDLE_ID_SUFFIX: ${{ inputs.environment == 'production' && '' || 'development' }}
|
||||||
GITHUB_REF: ${{ github.ref }}
|
GITHUB_REF: ${{ github.ref }}
|
||||||
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 120
|
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 120
|
||||||
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 6
|
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 6
|
||||||
|
|||||||
@@ -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@6147a58e5d1249a12f42fc864ab791d571a30015 # v0.0.47
|
uses: oasdiff/oasdiff-action/breaking@26ccb332c67a45ca649de9faf60552ef1b8260d9 # v0.0.46
|
||||||
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
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
|||||||
@@ -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@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4
|
uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||||
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@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4
|
uses: github/codeql-action/autobuild@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||||
|
|
||||||
# ℹ️ 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@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4
|
uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
|
||||||
with:
|
with:
|
||||||
category: '/language:${{matrix.language}}'
|
category: '/language:${{matrix.language}}'
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -213,11 +213,12 @@ jobs:
|
|||||||
run: 'mise run //deployment:tf apply'
|
run: 'mise run //deployment:tf apply'
|
||||||
|
|
||||||
- name: Comment
|
- name: Comment
|
||||||
uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
uses: actions-cool/maintain-one-comment@909842216bc8e8658364c572ec52100f4c2cc50a # v3.3.0
|
||||||
if: ${{ steps.parameters.outputs.event == 'pr' }}
|
if: ${{ steps.parameters.outputs.event == 'pr' }}
|
||||||
with:
|
with:
|
||||||
id: docs-pr-url
|
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
number: ${{ fromJson(needs.checks.outputs.parameters).pr_number }}
|
number: ${{ fromJson(needs.checks.outputs.parameters).pr_number }}
|
||||||
body: |
|
body: |
|
||||||
📖 Documentation deployed to [${{ steps.docs-output.outputs.subdomain }}](https://${{ steps.docs-output.outputs.subdomain }})
|
📖 Documentation deployed to [${{ steps.docs-output.outputs.subdomain }}](https://${{ steps.docs-output.outputs.subdomain }})
|
||||||
|
emojis: 'rocket'
|
||||||
|
body-include: '<!-- Docs PR URL -->'
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -44,8 +44,9 @@ jobs:
|
|||||||
run: 'mise run //deployment:tf destroy -- -refresh=false'
|
run: 'mise run //deployment:tf destroy -- -refresh=false'
|
||||||
|
|
||||||
- name: Comment
|
- name: Comment
|
||||||
uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
uses: actions-cool/maintain-one-comment@909842216bc8e8658364c572ec52100f4c2cc50a # v3.3.0
|
||||||
with:
|
with:
|
||||||
id: docs-pr-url
|
|
||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
number: ${{ github.event.number }}
|
||||||
delete: true
|
delete: true
|
||||||
|
body-include: '<!-- Docs PR URL -->'
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate_token
|
id: generate_token
|
||||||
if: ${{ inputs.skip != true }}
|
if: ${{ inputs.skip != true }}
|
||||||
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
||||||
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 }}
|
||||||
|
|||||||
@@ -13,4 +13,3 @@ jobs:
|
|||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
security-events: write
|
security-events: write
|
||||||
secrets: inherit
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
ref: main
|
ref: main
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
id: generate-token
|
id: generate-token
|
||||||
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
||||||
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,11 +19,11 @@ jobs:
|
|||||||
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 }}
|
||||||
|
|
||||||
- uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
- uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
with:
|
with:
|
||||||
id: preview-status
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
token: ${{ steps.token.outputs.token }}
|
message-id: 'preview-status'
|
||||||
body: 'Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.build/'
|
message: 'Deploying preview environment to https://pr-${{ github.event.pull_request.number }}.preview.internal.immich.build/'
|
||||||
|
|
||||||
remove-label:
|
remove-label:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -48,16 +48,16 @@ jobs:
|
|||||||
name: 'preview'
|
name: 'preview'
|
||||||
})
|
})
|
||||||
|
|
||||||
- uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
- uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
if: ${{ github.event.pull_request.head.repo.fork }}
|
if: ${{ github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
id: preview-status
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
token: ${{ steps.token.outputs.token }}
|
message-id: 'preview-status'
|
||||||
body: 'PRs from forks cannot have preview environments.'
|
message: 'PRs from forks cannot have preview environments.'
|
||||||
|
|
||||||
- uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
- uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||||
with:
|
with:
|
||||||
id: preview-status
|
github-token: ${{ steps.token.outputs.token }}
|
||||||
token: ${{ steps.token.outputs.token }}
|
message-id: 'preview-status'
|
||||||
body: 'Preview environment has been removed.'
|
message: 'Preview environment has been removed.'
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
|||||||
+13
-20
@@ -30,32 +30,25 @@ jobs:
|
|||||||
filters: |
|
filters: |
|
||||||
i18n:
|
i18n:
|
||||||
- 'i18n/**'
|
- 'i18n/**'
|
||||||
- 'mise.toml'
|
|
||||||
web:
|
web:
|
||||||
- 'web/**'
|
- 'web/**'
|
||||||
- 'i18n/**'
|
- 'i18n/**'
|
||||||
- 'packages/sdk/**'
|
- 'packages/sdk/**'
|
||||||
- 'pnpm-lock.yaml'
|
- 'pnpm-lock.yaml'
|
||||||
- 'mise.toml'
|
|
||||||
server:
|
server:
|
||||||
- 'server/**'
|
- 'server/**'
|
||||||
- 'pnpm-lock.yaml'
|
- 'pnpm-lock.yaml'
|
||||||
- 'mise.toml'
|
|
||||||
cli:
|
cli:
|
||||||
- 'packages/cli/**'
|
- 'packages/cli/**'
|
||||||
- 'packages/sdk/**'
|
- 'packages/sdk/**'
|
||||||
- 'pnpm-lock.yaml'
|
- 'pnpm-lock.yaml'
|
||||||
- 'mise.toml'
|
|
||||||
e2e:
|
e2e:
|
||||||
- 'e2e/**'
|
- 'e2e/**'
|
||||||
- 'pnpm-lock.yaml'
|
- 'pnpm-lock.yaml'
|
||||||
- 'mise.toml'
|
|
||||||
mobile:
|
mobile:
|
||||||
- 'mobile/**'
|
- 'mobile/**'
|
||||||
- 'mise.toml'
|
|
||||||
machine-learning:
|
machine-learning:
|
||||||
- 'machine-learning/**'
|
- 'machine-learning/**'
|
||||||
- 'mise.toml'
|
|
||||||
.github:
|
.github:
|
||||||
- '.github/**'
|
- '.github/**'
|
||||||
force-filters: |
|
force-filters: |
|
||||||
@@ -83,7 +76,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -114,7 +107,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -145,7 +138,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -189,7 +182,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -227,7 +220,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -255,7 +248,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -305,7 +298,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -338,7 +331,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -557,7 +550,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -594,7 +587,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -625,7 +618,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -676,7 +669,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
@@ -734,7 +727,7 @@ jobs:
|
|||||||
token: ${{ steps.token.outputs.token }}
|
token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
- name: Setup Mise
|
- name: Setup Mise
|
||||||
uses: immich-app/devtools/actions/use-mise@7b8610a904d57da241e4ddba17fa62b62b15aed4 # use-mise-action-v2.0.2
|
uses: immich-app/devtools/actions/use-mise@cf6e190bacde3d7bda59372a786b36ac7d01536a # use-mise-action-v2.0.1
|
||||||
with:
|
with:
|
||||||
github_token: ${{ steps.token.outputs.token }}
|
github_token: ${{ steps.token.outputs.token }}
|
||||||
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
|
||||||
|
|
||||||
[[tools.opentofu]]
|
|
||||||
version = "1.11.6"
|
|
||||||
backend = "aqua:opentofu/opentofu"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:d4f2ab15776925864b049bb329d69682851de6f5204f256e9fa86d07a0308850"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:d4f2ab15776925864b049bb329d69682851de6f5204f256e9fa86d07a0308850"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:02800fafa2753a9f50c38483e2fdf5bc353fd62895eb9e25eec9a5145df3a69e"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:02800fafa2753a9f50c38483e2fdf5bc353fd62895eb9e25eec9a5145df3a69e"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:62d7fa8539e13b444827aa0a3b90c5972da5c47e8f8882d9dcf2e430e78840c1"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_darwin_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:1408cdef1c380f914565e6b4bb70794c6b163f195fcb233357f3d6c5745906b6"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_darwin_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:27323f70c875b8251bfd7e61a4cffc3ebff4e56ed1e611b955016f0c7077367e"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_windows_amd64.tar.gz"
|
|
||||||
|
|
||||||
[[tools.terragrunt]]
|
|
||||||
version = "1.0.3"
|
|
||||||
backend = "aqua:gruntwork-io/terragrunt"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:e5b60ab05b5214db694e6bc215d8124fb626e277cdb56b86f6147ae110d510fe"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:e5b60ab05b5214db694e6bc215d8124fb626e277cdb56b86f6147ae110d510fe"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:6d48049baf82e0bf9c804368dc85cbfeadc10955e33777e9e8de3e020b94b073"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:6d48049baf82e0bf9c804368dc85cbfeadc10955e33777e9e8de3e020b94b073"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:aacb5be2ca5475300cbce246dfbd8a45eb47510fbaa70fab8561c49ef5db03aa"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_darwin_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:3133c2251e191aede8e3dd2a5b3aee2e91c5f08f88f117aee40eed9a24c8ef6b"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_darwin_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:183b2745b4e04980a6bfa4450ff81956a12596ca22d70f7aaa793980f5b036db"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_windows_amd64.exe.tar.gz"
|
|
||||||
@@ -10,6 +10,7 @@ const config = {
|
|||||||
url: 'https://docs.immich.app',
|
url: 'https://docs.immich.app',
|
||||||
baseUrl: '/',
|
baseUrl: '/',
|
||||||
onBrokenLinks: 'throw',
|
onBrokenLinks: 'throw',
|
||||||
|
onBrokenMarkdownLinks: 'warn',
|
||||||
favicon: 'img/favicon.png',
|
favicon: 'img/favicon.png',
|
||||||
|
|
||||||
// GitHub pages deployment config.
|
// GitHub pages deployment config.
|
||||||
@@ -28,9 +29,6 @@ const config = {
|
|||||||
// Mermaid diagrams
|
// Mermaid diagrams
|
||||||
markdown: {
|
markdown: {
|
||||||
mermaid: true,
|
mermaid: true,
|
||||||
hooks: {
|
|
||||||
onBrokenMarkdownLinks: 'warn',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
themes: ['@docusaurus/theme-mermaid'],
|
themes: ['@docusaurus/theme-mermaid'],
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
|
||||||
|
|
||||||
[[tools.wrangler]]
|
|
||||||
version = "4.66.0"
|
|
||||||
backend = "npm:wrangler"
|
|
||||||
+1
-1
@@ -28,4 +28,4 @@ run = "prettier --write ."
|
|||||||
run = "wrangler pages deploy build --project-name=${PROJECT_NAME} --branch=${BRANCH_NAME}"
|
run = "wrangler pages deploy build --project-name=${PROJECT_NAME} --branch=${BRANCH_NAME}"
|
||||||
|
|
||||||
[tools]
|
[tools]
|
||||||
wrangler = "4.91.0"
|
wrangler = "4.66.0"
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@
|
|||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.44.1",
|
||||||
"@socket.io/component-emitter": "^3.1.2",
|
"@socket.io/component-emitter": "^3.1.2",
|
||||||
"@types/luxon": "^3.4.2",
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^24.12.4",
|
"@types/node": "^24.12.2",
|
||||||
"@types/pg": "^8.15.1",
|
"@types/pg": "^8.15.1",
|
||||||
"@types/pngjs": "^6.0.4",
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/supertest": "^7.0.0",
|
"@types/supertest": "^7.0.0",
|
||||||
|
|||||||
@@ -976,6 +976,7 @@
|
|||||||
"downloading_asset_filename": "Downloading asset {filename}",
|
"downloading_asset_filename": "Downloading asset {filename}",
|
||||||
"downloading_from_icloud": "Downloading from iCloud",
|
"downloading_from_icloud": "Downloading from iCloud",
|
||||||
"downloading_media": "Downloading media",
|
"downloading_media": "Downloading media",
|
||||||
|
"drag_to_reorder": "Drag to reorder",
|
||||||
"drop_files_to_upload": "Drop files anywhere to upload",
|
"drop_files_to_upload": "Drop files anywhere to upload",
|
||||||
"duplicates": "Duplicates",
|
"duplicates": "Duplicates",
|
||||||
"duplicates_description": "Resolve each group by indicating which, if any, are duplicates.",
|
"duplicates_description": "Resolve each group by indicating which, if any, are duplicates.",
|
||||||
@@ -2254,6 +2255,7 @@
|
|||||||
"step_delete_confirm": "Are you sure you want to delete this step?",
|
"step_delete_confirm": "Are you sure you want to delete this step?",
|
||||||
"step_details": "Step details",
|
"step_details": "Step details",
|
||||||
"steps": "Steps",
|
"steps": "Steps",
|
||||||
|
"steps_count": "{count, plural, one {# step} other {# steps}}",
|
||||||
"stop_casting": "Stop casting",
|
"stop_casting": "Stop casting",
|
||||||
"stop_motion_photo": "Stop Motion Photo",
|
"stop_motion_photo": "Stop Motion Photo",
|
||||||
"stop_photo_sharing": "Stop sharing your photos?",
|
"stop_photo_sharing": "Stop sharing your photos?",
|
||||||
@@ -2415,6 +2417,7 @@
|
|||||||
"use_browser_locale_description": "Format dates, times, and numbers based on your browser locale",
|
"use_browser_locale_description": "Format dates, times, and numbers based on your browser locale",
|
||||||
"use_current_connection": "Use current connection",
|
"use_current_connection": "Use current connection",
|
||||||
"use_custom_date_range": "Use custom date range instead",
|
"use_custom_date_range": "Use custom date range instead",
|
||||||
|
"use_template": "Use template",
|
||||||
"user": "User",
|
"user": "User",
|
||||||
"user_has_been_deleted": "This user has been deleted.",
|
"user_has_been_deleted": "This user has been deleted.",
|
||||||
"user_id": "User ID",
|
"user_id": "User ID",
|
||||||
@@ -2476,6 +2479,7 @@
|
|||||||
"week": "Week",
|
"week": "Week",
|
||||||
"welcome": "Welcome",
|
"welcome": "Welcome",
|
||||||
"welcome_to_immich": "Welcome to Immich",
|
"welcome_to_immich": "Welcome to Immich",
|
||||||
|
"when": "When",
|
||||||
"width": "Width",
|
"width": "Width",
|
||||||
"wifi_name": "Wi-Fi Name",
|
"wifi_name": "Wi-Fi Name",
|
||||||
"workflow": "Workflow",
|
"workflow": "Workflow",
|
||||||
@@ -2488,6 +2492,7 @@
|
|||||||
"workflow_name": "Workflow name",
|
"workflow_name": "Workflow name",
|
||||||
"workflow_navigation_prompt": "Are you sure you want to leave without saving your changes?",
|
"workflow_navigation_prompt": "Are you sure you want to leave without saving your changes?",
|
||||||
"workflow_summary": "Workflow summary",
|
"workflow_summary": "Workflow summary",
|
||||||
|
"workflow_templates": "Workflow templates",
|
||||||
"workflow_update_success": "Workflow updated successfully",
|
"workflow_update_success": "Workflow updated successfully",
|
||||||
"workflow_updated": "Workflow updated",
|
"workflow_updated": "Workflow updated",
|
||||||
"workflows": "Workflows",
|
"workflows": "Workflows",
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
|
||||||
|
|
||||||
[[tools.python]]
|
|
||||||
version = "3.11.15"
|
|
||||||
backend = "core:python"
|
|
||||||
|
|
||||||
[tools.python."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:243f794278eff6adba96ed3677ec6877175df84c25f140e17f09f9be82d0f12a"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[tools.python."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:52b4c52094ff8b383a45c694acf4c5c0e883152be6d5229a35a8186ce907c6eb"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-aarch64-unknown-linux-musl-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[tools.python."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:171dffd8c0f66e8a0725364a7428015b22fc18dd298b24f541392e17dd0e561f"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[tools.python."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:2ac90fef8917ebd14826a6d667593a06cf0ae5f745ba9b1147dc086dd35f5284"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-x86_64-unknown-linux-musl-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[tools.python."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:fdfc363b538662eb7441a14e06f72c4a992c56af7f401f5730ea5081f8f8ad6e"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-aarch64-apple-darwin-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[tools.python."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:5f1eb247cbca2c0ad5ccbf6d299a4f54b31b5c63b492d74c3531dc4344a42f88"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-x86_64-apple-darwin-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[tools.python."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:756d7f148498b8822f6aedf44a020613576f09983161f346ad36dcef6238cdc3"
|
|
||||||
url = "https://github.com/astral-sh/python-build-standalone/releases/download/20260510/cpython-3.11.15+20260510-x86_64-pc-windows-msvc-install_only_stripped.tar.gz"
|
|
||||||
provenance = "github-attestations"
|
|
||||||
|
|
||||||
[[tools.uv]]
|
|
||||||
version = "0.8.15"
|
|
||||||
backend = "aqua:astral-sh/uv"
|
|
||||||
|
|
||||||
[tools.uv."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:23ea21a05c62c4c307ce691f29bff2f15c94c4f07f2b83d9b356f0664bc8b3a2"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-aarch64-unknown-linux-musl.tar.gz"
|
|
||||||
|
|
||||||
[tools.uv."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:23ea21a05c62c4c307ce691f29bff2f15c94c4f07f2b83d9b356f0664bc8b3a2"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-aarch64-unknown-linux-musl.tar.gz"
|
|
||||||
|
|
||||||
[tools.uv."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:d0fec58f3124e05e0a1af0f6541abfce4333253cdaf23c7b6bb2e6128bf138ea"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-x86_64-unknown-linux-musl.tar.gz"
|
|
||||||
|
|
||||||
[tools.uv."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:d0fec58f3124e05e0a1af0f6541abfce4333253cdaf23c7b6bb2e6128bf138ea"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-x86_64-unknown-linux-musl.tar.gz"
|
|
||||||
|
|
||||||
[tools.uv."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:103367962c5cb00bf7370d84cbaa3fec5a9807be9cc833ea9d8eea400c119fa2"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-aarch64-apple-darwin.tar.gz"
|
|
||||||
|
|
||||||
[tools.uv."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:2bbef70982e97dfc36454de173f35ec1a5e83ae11e3885df6a50db3fd76171cb"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-x86_64-apple-darwin.tar.gz"
|
|
||||||
|
|
||||||
[tools.uv."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:459d95892a5cc5c21779532f4f41b9238594b79e312a5142da2148ecfa10e705"
|
|
||||||
url = "https://github.com/astral-sh/uv/releases/download/0.8.15/uv-x86_64-pc-windows-msvc.zip"
|
|
||||||
@@ -1,354 +0,0 @@
|
|||||||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
|
||||||
|
|
||||||
[[tools."aqua:flutter/flutter"]]
|
|
||||||
version = "3.44.0"
|
|
||||||
backend = "aqua:flutter/flutter"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.linux-arm64"]
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.linux-arm64-musl"]
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.linux-x64"]
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.linux-x64-musl"]
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.macos-arm64"]
|
|
||||||
checksum = "blake3:fb03aa5d9790205c948922ec3f0751c16e4575b09d6ae9dd4fbeb664a69f0e00"
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_arm64_3.44.0-stable.zip"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.macos-x64"]
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_3.44.0-stable.zip"
|
|
||||||
|
|
||||||
[tools."aqua:flutter/flutter"."platforms.windows-x64"]
|
|
||||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.44.0-stable.zip"
|
|
||||||
|
|
||||||
[[tools.flutter]]
|
|
||||||
version = "3.41.9-stable"
|
|
||||||
backend = "asdf:flutter"
|
|
||||||
|
|
||||||
[[tools."github:CQLabs/homebrew-dcm"]]
|
|
||||||
version = "1.37.0"
|
|
||||||
backend = "github:CQLabs/homebrew-dcm"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:253da2512b149913dfe345bf9a62a79acb2d730f66e71162ba4a92dfc4224b82"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-arm-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543838"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:253da2512b149913dfe345bf9a62a79acb2d730f66e71162ba4a92dfc4224b82"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-arm-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543838"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:477e086d4099c12f21e5ccd83b005d5fb945dd4cac4fd127fd9a08d7649af1cf"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-x64-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543797"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:477e086d4099c12f21e5ccd83b005d5fb945dd4cac4fd127fd9a08d7649af1cf"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-linux-x64-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543797"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:30bede64367d09067093cc57af6ec9496d7717898138ded5cb98a16ac8dd9d93"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-macos-arm-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543757"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:e56cb99872be7445a4de1d37e5438ca70e3bcd83be7a2b9b385e3538881f8068"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-macos-x64-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543727"
|
|
||||||
|
|
||||||
[tools."github:CQLabs/homebrew-dcm"."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:f133470daa3fb0427f039b424392af7e917d7e7db6b556aa2a968ab0e31587da"
|
|
||||||
url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.37.0/dcm-windows-release.zip"
|
|
||||||
url_api = "https://api.github.com/repos/CQLabs/homebrew-dcm/releases/assets/404543660"
|
|
||||||
|
|
||||||
[[tools."github:extism/cli"]]
|
|
||||||
version = "1.6.3"
|
|
||||||
backend = "github:extism/cli"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:d92f830c9be39637569feacb04e9750c28848df6d9a219db94152a9b4eb9452b"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-linux-arm64.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694030"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:d92f830c9be39637569feacb04e9750c28848df6d9a219db94152a9b4eb9452b"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-linux-arm64.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694030"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:34e7ae9bfded6e2c32dee83f70a4e50d34f9d3e80d1762b09625fe82e214d02d"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-linux-amd64.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694025"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:34e7ae9bfded6e2c32dee83f70a4e50d34f9d3e80d1762b09625fe82e214d02d"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-linux-amd64.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694025"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:b4ddbc575b5ac000115247f781723f9b9f284ed87b29c600539d72161b5b29fc"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-darwin-arm64.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694029"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:9a2f71b6e6009685a622cc3084e52d2a1a8e23c98d29ffa72e666e9dc699855f"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-darwin-amd64.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694026"
|
|
||||||
|
|
||||||
[tools."github:extism/cli"."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:47e4ed2782445b2b08a4d1ac127211588f8b4d1fc25fd6481d4cb65151b5213c"
|
|
||||||
url = "https://github.com/extism/cli/releases/download/v1.6.3/extism-v1.6.3-windows-amd64.zip"
|
|
||||||
url_api = "https://api.github.com/repos/extism/cli/releases/assets/275694035"
|
|
||||||
|
|
||||||
[[tools."github:extism/js-pdk"]]
|
|
||||||
version = "1.6.0"
|
|
||||||
backend = "github:extism/js-pdk"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:15a186250e68d6bff4ec839fff275d45a90e383a69209dcc1239eb9e3aee6e1b"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-aarch64-linux-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353223214"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:15a186250e68d6bff4ec839fff275d45a90e383a69209dcc1239eb9e3aee6e1b"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-aarch64-linux-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353223214"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:4ded271ccf465031ccd0dc35e7a140e134d7f30721671cc4a8e1ff805d4aad68"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-x86_64-linux-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353223119"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:4ded271ccf465031ccd0dc35e7a140e134d7f30721671cc4a8e1ff805d4aad68"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-x86_64-linux-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353223119"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:548e25bda3971a07c32d78a249135cf8cb7b3eede101e878e06e53e01ac2e0ce"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-aarch64-macos-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353223215"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:d85a875c2a071f0c29fe572764c52c3a499f157ab7f9efac8939a4364390e29b"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-x86_64-macos-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353223239"
|
|
||||||
|
|
||||||
[tools."github:extism/js-pdk"."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:97b7b746141e4777e1ca2b76febdeb16dc9d314ff6a4257df05a476b67228acc"
|
|
||||||
url = "https://github.com/extism/js-pdk/releases/download/v1.6.0/extism-js-x86_64-windows-v1.6.0.gz"
|
|
||||||
url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353224133"
|
|
||||||
|
|
||||||
[[tools."github:jellyfin/jellyfin-ffmpeg"]]
|
|
||||||
version = "7.1.3-6"
|
|
||||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:bea03c670e8cc5bfe9edc0c5d624d4735421610cef5e808db93e7d8596952886"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linuxarm64-gpl.tar.xz"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048876"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:bea03c670e8cc5bfe9edc0c5d624d4735421610cef5e808db93e7d8596952886"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linuxarm64-gpl.tar.xz"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048876"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:39e99a7927468a6abec5f65d00f55010e8ff2ae3c2605294f179c94f6ae21af2"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linux64-gpl.tar.xz"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048879"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:39e99a7927468a6abec5f65d00f55010e8ff2ae3c2605294f179c94f6ae21af2"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_linux64-gpl.tar.xz"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409048879"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:e024d5e78d5414e75f0181036cd21373fafb9270c72894dfd7dbda2572439820"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_macarm64-gpl.tar.xz"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995838"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:066ede9774aaae97a18098aaeea8b7e0d286653eb8618f640476e99c59a536c2"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_mac64-gpl.tar.xz"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/408995889"
|
|
||||||
|
|
||||||
[tools."github:jellyfin/jellyfin-ffmpeg"."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:7b7168149689610296f3a187c717056ce0786cc125a31caf28056737e9ba1cc1"
|
|
||||||
url = "https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v7.1.3-6/jellyfin-ffmpeg_7.1.3-6_portable_win64-clang-gpl.zip"
|
|
||||||
url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets/409036094"
|
|
||||||
|
|
||||||
[[tools."github:webassembly/binaryen"]]
|
|
||||||
version = "version_124"
|
|
||||||
backend = "github:webassembly/binaryen"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:6291bd9a57d8e046f3bc099a4db386c147433a87f71c783a901c5b1792e38de3"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-aarch64-linux.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288927659"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:6291bd9a57d8e046f3bc099a4db386c147433a87f71c783a901c5b1792e38de3"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-aarch64-linux.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288927659"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:0290c3779fedf592b8da0ded3032ff55c41a2b7bfa2d6bf7b7bac6f0e6e28963"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-x86_64-linux.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288926769"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:0290c3779fedf592b8da0ded3032ff55c41a2b7bfa2d6bf7b7bac6f0e6e28963"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-x86_64-linux.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288926769"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:86a2c960ff62c6d2ea6009d1f89745c22c70100d394a095eab45eb941bdaa24c"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-arm64-macos.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288926134"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:b389bb0731758d86c3cb266d01d28a12725c23bd3cabc3df34faa162af0887e9"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-x86_64-macos.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288926135"
|
|
||||||
|
|
||||||
[tools."github:webassembly/binaryen"."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:b5e1d2a1ad3c03229ddc89823848f4a1c11f9c6402a51fa26f0aaa5f1d7a2203"
|
|
||||||
url = "https://github.com/WebAssembly/binaryen/releases/download/version_124/binaryen-version_124-x86_64-windows.tar.gz"
|
|
||||||
url_api = "https://api.github.com/repos/WebAssembly/binaryen/releases/assets/288925833"
|
|
||||||
|
|
||||||
[[tools.java]]
|
|
||||||
version = "21.0.2"
|
|
||||||
backend = "core:java"
|
|
||||||
|
|
||||||
[tools.java."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:08db1392a48d4eb5ea5315cf8f18b89dbaf36cda663ba882cf03c704c9257ec2"
|
|
||||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-aarch64_bin.tar.gz"
|
|
||||||
|
|
||||||
[tools.java."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:a2def047a73941e01a73739f92755f86b895811afb1f91243db214cff5bdac3f"
|
|
||||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz"
|
|
||||||
|
|
||||||
[tools.java."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:b3d588e16ec1e0ef9805d8a696591bd518a5cea62567da8f53b5ce32d11d22e4"
|
|
||||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_macos-aarch64_bin.tar.gz"
|
|
||||||
|
|
||||||
[tools.java."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:8fd09e15dc406387a0aba70bf5d99692874e999bf9cd9208b452b5d76ac922d3"
|
|
||||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_macos-x64_bin.tar.gz"
|
|
||||||
|
|
||||||
[tools.java."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882664"
|
|
||||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip"
|
|
||||||
|
|
||||||
[[tools.node]]
|
|
||||||
version = "24.15.0"
|
|
||||||
backend = "core:node"
|
|
||||||
|
|
||||||
[tools.node."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:73afc234d558c24919875f51c2d1ea002a2ada4ea6f83601a383869fefa64eed"
|
|
||||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-linux-arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.node."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:31e98aa960a067da91edffd5d93bc46657b5d2a8029612c359f5f2ac0060152a"
|
|
||||||
url = "https://unofficial-builds.nodejs.org/download/release/v24.15.0/node-v24.15.0-linux-arm64-musl.tar.gz"
|
|
||||||
|
|
||||||
[tools.node."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:44836872d9aec49f1e6b52a9a922872db9a2b02d235a616a5681b6a85fec8d89"
|
|
||||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-linux-x64.tar.gz"
|
|
||||||
|
|
||||||
[tools.node."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:f55af5bd489c5347b113ca6594cae00a54b30ba57ac5875324311bfc6f4762e3"
|
|
||||||
url = "https://unofficial-builds.nodejs.org/download/release/v24.15.0/node-v24.15.0-linux-x64-musl.tar.gz"
|
|
||||||
|
|
||||||
[tools.node."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:372331b969779ab5d15b949884fc6eaf88d5afe87bde8ba881d6400b9100ffc4"
|
|
||||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-darwin-arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.node."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:ffd5ee293467927f3ee731a553eb88fd1f48cf74eebc2d74a6babe4af228673b"
|
|
||||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-darwin-x64.tar.gz"
|
|
||||||
|
|
||||||
[tools.node."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:cc5149eabd53779ce1e7bdc5401643622d0c7e6800ade18928a767e940bb0e62"
|
|
||||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-win-x64.zip"
|
|
||||||
|
|
||||||
[[tools."npm:oazapfts"]]
|
|
||||||
version = "7.5.0"
|
|
||||||
backend = "npm:oazapfts"
|
|
||||||
|
|
||||||
[[tools.opentofu]]
|
|
||||||
version = "1.11.6"
|
|
||||||
backend = "aqua:opentofu/opentofu"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:d4f2ab15776925864b049bb329d69682851de6f5204f256e9fa86d07a0308850"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:d4f2ab15776925864b049bb329d69682851de6f5204f256e9fa86d07a0308850"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:02800fafa2753a9f50c38483e2fdf5bc353fd62895eb9e25eec9a5145df3a69e"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:02800fafa2753a9f50c38483e2fdf5bc353fd62895eb9e25eec9a5145df3a69e"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:62d7fa8539e13b444827aa0a3b90c5972da5c47e8f8882d9dcf2e430e78840c1"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_darwin_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:1408cdef1c380f914565e6b4bb70794c6b163f195fcb233357f3d6c5745906b6"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_darwin_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.opentofu."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:27323f70c875b8251bfd7e61a4cffc3ebff4e56ed1e611b955016f0c7077367e"
|
|
||||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.6_windows_amd64.tar.gz"
|
|
||||||
|
|
||||||
[[tools.pnpm]]
|
|
||||||
version = "10.33.4"
|
|
||||||
backend = "aqua:pnpm/pnpm"
|
|
||||||
|
|
||||||
[[tools.terragrunt]]
|
|
||||||
version = "1.0.3"
|
|
||||||
backend = "aqua:gruntwork-io/terragrunt"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-arm64"]
|
|
||||||
checksum = "sha256:e5b60ab05b5214db694e6bc215d8124fb626e277cdb56b86f6147ae110d510fe"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-arm64-musl"]
|
|
||||||
checksum = "sha256:e5b60ab05b5214db694e6bc215d8124fb626e277cdb56b86f6147ae110d510fe"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-x64"]
|
|
||||||
checksum = "sha256:6d48049baf82e0bf9c804368dc85cbfeadc10955e33777e9e8de3e020b94b073"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.linux-x64-musl"]
|
|
||||||
checksum = "sha256:6d48049baf82e0bf9c804368dc85cbfeadc10955e33777e9e8de3e020b94b073"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_linux_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.macos-arm64"]
|
|
||||||
checksum = "sha256:aacb5be2ca5475300cbce246dfbd8a45eb47510fbaa70fab8561c49ef5db03aa"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_darwin_arm64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.macos-x64"]
|
|
||||||
checksum = "sha256:3133c2251e191aede8e3dd2a5b3aee2e91c5f08f88f117aee40eed9a24c8ef6b"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_darwin_amd64.tar.gz"
|
|
||||||
|
|
||||||
[tools.terragrunt."platforms.windows-x64"]
|
|
||||||
checksum = "sha256:183b2745b4e04980a6bfa4450ff81956a12596ca22d70f7aaa793980f5b036db"
|
|
||||||
url = "https://github.com/gruntwork-io/terragrunt/releases/download/v1.0.3/terragrunt_windows_amd64.exe.tar.gz"
|
|
||||||
@@ -16,8 +16,8 @@ config_roots = [
|
|||||||
|
|
||||||
[tools]
|
[tools]
|
||||||
node = "24.15.0"
|
node = "24.15.0"
|
||||||
"aqua:flutter/flutter" = "3.44.0"
|
flutter = "3.41.9"
|
||||||
pnpm = "10.33.4"
|
pnpm = "10.33.1"
|
||||||
terragrunt = "1.0.3"
|
terragrunt = "1.0.3"
|
||||||
opentofu = "1.11.6"
|
opentofu = "1.11.6"
|
||||||
java = "21.0.2"
|
java = "21.0.2"
|
||||||
@@ -50,12 +50,11 @@ macos-arm64 = { asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz"
|
|||||||
[settings]
|
[settings]
|
||||||
experimental = true
|
experimental = true
|
||||||
pin = true
|
pin = true
|
||||||
lockfile = true
|
|
||||||
|
|
||||||
[tasks.plugins]
|
[tasks.plugins]
|
||||||
run = [
|
run = [
|
||||||
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core install --frozen-lockfile",
|
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core install --frozen-lockfile",
|
||||||
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core build",
|
"pnpm --filter @immich/plugin-sdk --filter @immich/plugin-core build"
|
||||||
]
|
]
|
||||||
|
|
||||||
[tasks.open-api-typescript]
|
[tasks.open-api-typescript]
|
||||||
@@ -77,8 +76,8 @@ run = [
|
|||||||
{ task = "//server:install" },
|
{ task = "//server:install" },
|
||||||
{ task = "//server:build" },
|
{ task = "//server:build" },
|
||||||
{ task = "//server:sync-open-api" },
|
{ task = "//server:sync-open-api" },
|
||||||
{ task = ":open-api-typescript" },
|
{ task = ":open-api-typescript"},
|
||||||
{ task = ":open-api-dart" },
|
{ task = ":open-api-dart"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[tasks.sql]
|
[tasks.sql]
|
||||||
|
|||||||
Vendored
+1
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"dart.flutterSdkPath": ".fvm/versions/3.41.9",
|
||||||
"dart.lineLength": 120,
|
"dart.lineLength": 120,
|
||||||
"[dart]": {
|
"[dart]": {
|
||||||
"editor.rulers": [
|
"editor.rulers": [
|
||||||
|
|||||||
@@ -89,13 +89,6 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
constraints {
|
|
||||||
implementation("androidx.glance:glance-appwidget") {
|
|
||||||
version { strictly libs.versions.glance.get() }
|
|
||||||
because 'home_widget requests 1.+ which can resolve to pre-releases incompatible with our compileSdk/AGP'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implementation libs.okhttp
|
implementation libs.okhttp
|
||||||
implementation libs.cronet.embedded
|
implementation libs.cronet.embedded
|
||||||
implementation libs.media3.datasource.okhttp
|
implementation libs.media3.datasource.okhttp
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import app.alextran.immich.images.LocalImageApi
|
|||||||
import app.alextran.immich.images.LocalImagesImpl
|
import app.alextran.immich.images.LocalImagesImpl
|
||||||
import app.alextran.immich.images.RemoteImageApi
|
import app.alextran.immich.images.RemoteImageApi
|
||||||
import app.alextran.immich.images.RemoteImagesImpl
|
import app.alextran.immich.images.RemoteImagesImpl
|
||||||
import app.alextran.immich.permission.PermissionApi
|
|
||||||
import app.alextran.immich.permission.PermissionApiImpl
|
|
||||||
import app.alextran.immich.sync.NativeSyncApi
|
import app.alextran.immich.sync.NativeSyncApi
|
||||||
import app.alextran.immich.sync.NativeSyncApiImpl26
|
import app.alextran.immich.sync.NativeSyncApiImpl26
|
||||||
import app.alextran.immich.sync.NativeSyncApiImpl30
|
import app.alextran.immich.sync.NativeSyncApiImpl30
|
||||||
@@ -46,9 +44,7 @@ class MainActivity : FlutterFragmentActivity() {
|
|||||||
} else {
|
} else {
|
||||||
NativeSyncApiImpl30(ctx)
|
NativeSyncApiImpl30(ctx)
|
||||||
}
|
}
|
||||||
val permissionApiImpl = PermissionApiImpl(ctx)
|
|
||||||
NativeSyncApi.setUp(messenger, nativeSyncApiImpl)
|
NativeSyncApi.setUp(messenger, nativeSyncApiImpl)
|
||||||
PermissionApi.setUp(messenger, permissionApiImpl)
|
|
||||||
LocalImageApi.setUp(messenger, LocalImagesImpl(ctx))
|
LocalImageApi.setUp(messenger, LocalImagesImpl(ctx))
|
||||||
RemoteImageApi.setUp(messenger, RemoteImagesImpl(ctx))
|
RemoteImageApi.setUp(messenger, RemoteImagesImpl(ctx))
|
||||||
|
|
||||||
@@ -57,7 +53,6 @@ class MainActivity : FlutterFragmentActivity() {
|
|||||||
|
|
||||||
flutterEngine.plugins.add(backgroundEngineLockImpl)
|
flutterEngine.plugins.add(backgroundEngineLockImpl)
|
||||||
flutterEngine.plugins.add(nativeSyncApiImpl)
|
flutterEngine.plugins.add(nativeSyncApiImpl)
|
||||||
flutterEngine.plugins.add(permissionApiImpl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelPlugins(flutterEngine: FlutterEngine) {
|
fun cancelPlugins(flutterEngine: FlutterEngine) {
|
||||||
@@ -65,8 +60,6 @@ class MainActivity : FlutterFragmentActivity() {
|
|||||||
flutterEngine.plugins.get(NativeSyncApiImpl26::class.java) as ImmichPlugin?
|
flutterEngine.plugins.get(NativeSyncApiImpl26::class.java) as ImmichPlugin?
|
||||||
?: flutterEngine.plugins.get(NativeSyncApiImpl30::class.java) as ImmichPlugin?
|
?: flutterEngine.plugins.get(NativeSyncApiImpl30::class.java) as ImmichPlugin?
|
||||||
nativeApi?.detachFromEngine()
|
nativeApi?.detachFromEngine()
|
||||||
val permissionApi = flutterEngine.plugins.get(PermissionApiImpl::class.java) as ImmichPlugin?
|
|
||||||
permissionApi?.detachFromEngine()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,7 +315,6 @@ interface NetworkApi {
|
|||||||
fun hasCertificate(): Boolean
|
fun hasCertificate(): Boolean
|
||||||
fun getClientPointer(): Long
|
fun getClientPointer(): Long
|
||||||
fun setRequestHeaders(headers: Map<String, String>, serverUrls: List<String>, token: String?)
|
fun setRequestHeaders(headers: Map<String, String>, serverUrls: List<String>, token: String?)
|
||||||
fun getAppGroupId(): String
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by NetworkApi. */
|
/** The codec used by NetworkApi. */
|
||||||
@@ -431,21 +430,6 @@ interface NetworkApi {
|
|||||||
channel.setMessageHandler(null)
|
channel.setMessageHandler(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run {
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.getAppGroupId$separatedMessageChannelSuffix", codec)
|
|
||||||
if (api != null) {
|
|
||||||
channel.setMessageHandler { _, reply ->
|
|
||||||
val wrapped: List<Any?> = try {
|
|
||||||
listOf(api.getAppGroupId())
|
|
||||||
} catch (exception: Throwable) {
|
|
||||||
NetworkPigeonUtils.wrapError(exception)
|
|
||||||
}
|
|
||||||
reply.reply(wrapped)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.setMessageHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class NetworkApiPlugin : FlutterPlugin, ActivityAware {
|
|||||||
private var networkApi: NetworkApiImpl? = null
|
private var networkApi: NetworkApiImpl? = null
|
||||||
|
|
||||||
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||||
networkApi = NetworkApiImpl(binding.applicationContext)
|
networkApi = NetworkApiImpl()
|
||||||
NetworkApi.setUp(binding.binaryMessenger, networkApi)
|
NetworkApi.setUp(binding.binaryMessenger, networkApi)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,11 +39,9 @@ class NetworkApiPlugin : FlutterPlugin, ActivityAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NetworkApiImpl(private val context: Context) : NetworkApi {
|
private class NetworkApiImpl : NetworkApi {
|
||||||
var activity: Activity? = null
|
var activity: Activity? = null
|
||||||
|
|
||||||
override fun getAppGroupId(): String = context.packageName
|
|
||||||
|
|
||||||
override fun addCertificate(clientData: ClientCertData, callback: (Result<Unit>) -> Unit) {
|
override fun addCertificate(clientData: ClientCertData, callback: (Result<Unit>) -> Unit) {
|
||||||
try {
|
try {
|
||||||
HttpClientManager.setKeyEntry(clientData.data, clientData.password.toCharArray())
|
HttpClientManager.setKeyEntry(clientData.data, clientData.password.toCharArray())
|
||||||
|
|||||||
-96
@@ -1,96 +0,0 @@
|
|||||||
package app.alextran.immich.permission
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import android.provider.Settings
|
|
||||||
import androidx.core.net.toUri
|
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
|
||||||
import io.flutter.plugin.common.PluginRegistry
|
|
||||||
|
|
||||||
class ManageMediaPermissionDelegate(
|
|
||||||
context: Context,
|
|
||||||
private val requestCode: Int = 1003,
|
|
||||||
) : PluginRegistry.ActivityResultListener {
|
|
||||||
private val ctx = context.applicationContext
|
|
||||||
private var activityBinding: ActivityPluginBinding? = null
|
|
||||||
private var pendingResult: ((Result<Boolean>) -> Unit)? = null
|
|
||||||
|
|
||||||
fun hasManageMediaPermission(): Boolean {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
||||||
MediaStore.canManageMedia(ctx)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requestManageMediaPermission(callback: (Result<Boolean>) -> Unit) {
|
|
||||||
if (hasManageMediaPermission()) {
|
|
||||||
callback(Result.success(true))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
openManageMediaPermissionSettings(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun manageMediaPermission(callback: (Result<Boolean>) -> Unit) {
|
|
||||||
openManageMediaPermissionSettings(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openManageMediaPermissionSettings(callback: (Result<Boolean>) -> Unit) {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
||||||
callback(Result.success(false))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val activity = activityBinding?.activity
|
|
||||||
if (activity == null) {
|
|
||||||
callback(Result.failure(FlutterError("NO_ACTIVITY", "Activity not available", null)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pendingResult = callback
|
|
||||||
val intent = Intent(Settings.ACTION_REQUEST_MANAGE_MEDIA).apply {
|
|
||||||
data = "package:${activity.packageName}".toUri()
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
activity.startActivityForResult(intent, requestCode)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
pendingResult = null
|
|
||||||
callback(
|
|
||||||
Result.failure(
|
|
||||||
FlutterError("ACTIVITY_LAUNCH_FAILED", "Failed to launch MANAGE_MEDIA settings", e.toString())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
|
||||||
activityBinding = binding
|
|
||||||
binding.addActivityResultListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDetachedFromActivity() {
|
|
||||||
failPending("ACTIVITY_DETACHED", "Activity detached before MANAGE_MEDIA result")
|
|
||||||
activityBinding?.removeActivityResultListener(this)
|
|
||||||
activityBinding = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
|
|
||||||
if (requestCode == this.requestCode) {
|
|
||||||
val callback = pendingResult
|
|
||||||
pendingResult = null
|
|
||||||
callback?.invoke(Result.success(hasManageMediaPermission()))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun failPending(code: String, message: String) {
|
|
||||||
val callback = pendingResult ?: return
|
|
||||||
pendingResult = null
|
|
||||||
callback(Result.failure(FlutterError(code, message, null)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-128
@@ -1,128 +0,0 @@
|
|||||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
|
||||||
// See also: https://pub.dev/packages/pigeon
|
|
||||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
|
||||||
|
|
||||||
package app.alextran.immich.permission
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import io.flutter.plugin.common.BasicMessageChannel
|
|
||||||
import io.flutter.plugin.common.BinaryMessenger
|
|
||||||
import io.flutter.plugin.common.EventChannel
|
|
||||||
import io.flutter.plugin.common.MessageCodec
|
|
||||||
import io.flutter.plugin.common.StandardMethodCodec
|
|
||||||
import io.flutter.plugin.common.StandardMessageCodec
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
private object PermissionApiPigeonUtils {
|
|
||||||
|
|
||||||
fun wrapResult(result: Any?): List<Any?> {
|
|
||||||
return listOf(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun wrapError(exception: Throwable): List<Any?> {
|
|
||||||
return if (exception is FlutterError) {
|
|
||||||
listOf(
|
|
||||||
exception.code,
|
|
||||||
exception.message,
|
|
||||||
exception.details
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
listOf(
|
|
||||||
exception.javaClass.simpleName,
|
|
||||||
exception.toString(),
|
|
||||||
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
|
||||||
* @property code The error code.
|
|
||||||
* @property message The error message.
|
|
||||||
* @property details The error details. Must be a datatype supported by the api codec.
|
|
||||||
*/
|
|
||||||
class FlutterError (
|
|
||||||
val code: String,
|
|
||||||
override val message: String? = null,
|
|
||||||
val details: Any? = null
|
|
||||||
) : RuntimeException()
|
|
||||||
private open class PermissionApiPigeonCodec : StandardMessageCodec() {
|
|
||||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
|
||||||
return super.readValueOfType(type, buffer)
|
|
||||||
}
|
|
||||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
|
||||||
super.writeValue(stream, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
|
||||||
interface PermissionApi {
|
|
||||||
fun hasManageMediaPermission(): Boolean
|
|
||||||
fun requestManageMediaPermission(callback: (Result<Boolean>) -> Unit)
|
|
||||||
fun manageMediaPermission(callback: (Result<Boolean>) -> Unit)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/** The codec used by PermissionApi. */
|
|
||||||
val codec: MessageCodec<Any?> by lazy {
|
|
||||||
PermissionApiPigeonCodec()
|
|
||||||
}
|
|
||||||
/** Sets up an instance of `PermissionApi` to handle messages through the `binaryMessenger`. */
|
|
||||||
@JvmOverloads
|
|
||||||
fun setUp(binaryMessenger: BinaryMessenger, api: PermissionApi?, messageChannelSuffix: String = "") {
|
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
|
||||||
run {
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.PermissionApi.hasManageMediaPermission$separatedMessageChannelSuffix", codec)
|
|
||||||
if (api != null) {
|
|
||||||
channel.setMessageHandler { _, reply ->
|
|
||||||
val wrapped: List<Any?> = try {
|
|
||||||
listOf(api.hasManageMediaPermission())
|
|
||||||
} catch (exception: Throwable) {
|
|
||||||
PermissionApiPigeonUtils.wrapError(exception)
|
|
||||||
}
|
|
||||||
reply.reply(wrapped)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.setMessageHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
run {
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.PermissionApi.requestManageMediaPermission$separatedMessageChannelSuffix", codec)
|
|
||||||
if (api != null) {
|
|
||||||
channel.setMessageHandler { _, reply ->
|
|
||||||
api.requestManageMediaPermission{ result: Result<Boolean> ->
|
|
||||||
val error = result.exceptionOrNull()
|
|
||||||
if (error != null) {
|
|
||||||
reply.reply(PermissionApiPigeonUtils.wrapError(error))
|
|
||||||
} else {
|
|
||||||
val data = result.getOrNull()
|
|
||||||
reply.reply(PermissionApiPigeonUtils.wrapResult(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.setMessageHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
run {
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.PermissionApi.manageMediaPermission$separatedMessageChannelSuffix", codec)
|
|
||||||
if (api != null) {
|
|
||||||
channel.setMessageHandler { _, reply ->
|
|
||||||
api.manageMediaPermission{ result: Result<Boolean> ->
|
|
||||||
val error = result.exceptionOrNull()
|
|
||||||
if (error != null) {
|
|
||||||
reply.reply(PermissionApiPigeonUtils.wrapError(error))
|
|
||||||
} else {
|
|
||||||
val data = result.getOrNull()
|
|
||||||
reply.reply(PermissionApiPigeonUtils.wrapResult(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.setMessageHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
package app.alextran.immich.permission
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import app.alextran.immich.core.ImmichPlugin
|
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
|
||||||
|
|
||||||
class PermissionApiImpl(context: Context) : ImmichPlugin(), PermissionApi, ActivityAware {
|
|
||||||
private val manageMediaPermissionDelegate = ManageMediaPermissionDelegate(context)
|
|
||||||
|
|
||||||
override fun hasManageMediaPermission(): Boolean =
|
|
||||||
manageMediaPermissionDelegate.hasManageMediaPermission()
|
|
||||||
|
|
||||||
override fun requestManageMediaPermission(callback: (Result<Boolean>) -> Unit) {
|
|
||||||
manageMediaPermissionDelegate.requestManageMediaPermission { completeWhenActive(callback, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun manageMediaPermission(callback: (Result<Boolean>) -> Unit) {
|
|
||||||
manageMediaPermissionDelegate.manageMediaPermission { completeWhenActive(callback, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
|
||||||
manageMediaPermissionDelegate.onAttachedToActivity(binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromActivityForConfigChanges() {
|
|
||||||
manageMediaPermissionDelegate.onDetachedFromActivity()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
|
|
||||||
manageMediaPermissionDelegate.onAttachedToActivity(binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromActivity() {
|
|
||||||
manageMediaPermissionDelegate.onDetachedFromActivity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
package app.alextran.immich.sync
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.content.ContentUris
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
|
||||||
import io.flutter.plugin.common.PluginRegistry
|
|
||||||
|
|
||||||
class MediaTrashDelegate(
|
|
||||||
context: Context,
|
|
||||||
private val trashRequestCode: Int = 1002,
|
|
||||||
) : PluginRegistry.ActivityResultListener {
|
|
||||||
private val ctx = context.applicationContext
|
|
||||||
private var activityBinding: ActivityPluginBinding? = null
|
|
||||||
private var pendingResult: ((Result<Boolean>) -> Unit)? = null
|
|
||||||
|
|
||||||
private fun hasManageMediaPermission(): Boolean {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
||||||
MediaStore.canManageMedia(ctx)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun restoreFromTrashById(mediaId: String, type: Long, callback: (Result<Boolean>) -> Unit) {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || !hasManageMediaPermission()) {
|
|
||||||
callback(Result.failure(FlutterError("PERMISSION_DENIED", "Media permission required", null)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val id = mediaId.toLongOrNull()
|
|
||||||
if (id == null) {
|
|
||||||
callback(Result.failure(FlutterError("INVALID_ID", "The file id is not a valid number: $mediaId", null)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isInTrash(id)) {
|
|
||||||
callback(Result.failure(FlutterError("TRASH_NOT_FOUND", "Item with id=$id not found in trash", null)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreUri(ContentUris.withAppendedId(contentUriForType(type.toInt()), id), callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
|
||||||
private fun restoreUri(
|
|
||||||
contentUri: Uri,
|
|
||||||
callback: (Result<Boolean>) -> Unit,
|
|
||||||
) {
|
|
||||||
val activity = activityBinding?.activity
|
|
||||||
if (activity == null) {
|
|
||||||
callback(Result.failure(FlutterError("NO_ACTIVITY", "Activity not available", null)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val pendingIntent = MediaStore.createTrashRequest(ctx.contentResolver, listOf(contentUri), false)
|
|
||||||
pendingResult = callback
|
|
||||||
activity.startIntentSenderForResult(
|
|
||||||
pendingIntent.intentSender,
|
|
||||||
trashRequestCode,
|
|
||||||
null,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
pendingResult = null
|
|
||||||
callback(
|
|
||||||
Result.failure(
|
|
||||||
FlutterError("TRASH_ERROR", "Error creating or starting trash request", e.toString())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
|
||||||
private fun isInTrash(id: Long): Boolean {
|
|
||||||
val filesUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
|
||||||
val args = Bundle().apply {
|
|
||||||
putString(ContentResolver.QUERY_ARG_SQL_SELECTION, "${MediaStore.Files.FileColumns._ID}=?")
|
|
||||||
putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(id.toString()))
|
|
||||||
putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY)
|
|
||||||
putInt(ContentResolver.QUERY_ARG_LIMIT, 1)
|
|
||||||
}
|
|
||||||
return ctx.contentResolver.query(filesUri, arrayOf(MediaStore.Files.FileColumns._ID), args, null)
|
|
||||||
?.use { it.moveToFirst() } == true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun contentUriForType(type: Int): Uri =
|
|
||||||
when (type) {
|
|
||||||
// Same order as AssetType from Dart.
|
|
||||||
1 -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
|
||||||
2 -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
|
||||||
3 -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
|
|
||||||
else -> MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
|
||||||
activityBinding = binding
|
|
||||||
binding.addActivityResultListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDetachedFromActivity() {
|
|
||||||
failPending("ACTIVITY_DETACHED", "Activity detached before trash result")
|
|
||||||
activityBinding?.removeActivityResultListener(this)
|
|
||||||
activityBinding = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
|
|
||||||
if (requestCode == trashRequestCode) {
|
|
||||||
val callback = pendingResult
|
|
||||||
pendingResult = null
|
|
||||||
callback?.invoke(Result.success(resultCode == Activity.RESULT_OK))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun failPending(code: String, message: String) {
|
|
||||||
val callback = pendingResult ?: return
|
|
||||||
pendingResult = null
|
|
||||||
callback(Result.failure(FlutterError(code, message, null)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -553,7 +553,6 @@ interface NativeSyncApi {
|
|||||||
fun hashAssets(assetIds: List<String>, allowNetworkAccess: Boolean, callback: (Result<List<HashResult>>) -> Unit)
|
fun hashAssets(assetIds: List<String>, allowNetworkAccess: Boolean, callback: (Result<List<HashResult>>) -> Unit)
|
||||||
fun cancelHashing()
|
fun cancelHashing()
|
||||||
fun getTrashedAssets(): Map<String, List<PlatformAsset>>
|
fun getTrashedAssets(): Map<String, List<PlatformAsset>>
|
||||||
fun restoreFromTrashById(mediaId: String, type: Long, callback: (Result<Boolean>) -> Unit)
|
|
||||||
fun getCloudIdForAssetIds(assetIds: List<String>): List<CloudIdResult>
|
fun getCloudIdForAssetIds(assetIds: List<String>): List<CloudIdResult>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -748,27 +747,6 @@ interface NativeSyncApi {
|
|||||||
channel.setMessageHandler(null)
|
channel.setMessageHandler(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run {
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.restoreFromTrashById$separatedMessageChannelSuffix", codec)
|
|
||||||
if (api != null) {
|
|
||||||
channel.setMessageHandler { message, reply ->
|
|
||||||
val args = message as List<Any?>
|
|
||||||
val mediaIdArg = args[0] as String
|
|
||||||
val typeArg = args[1] as Long
|
|
||||||
api.restoreFromTrashById(mediaIdArg, typeArg) { result: Result<Boolean> ->
|
|
||||||
val error = result.exceptionOrNull()
|
|
||||||
if (error != null) {
|
|
||||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
|
||||||
} else {
|
|
||||||
val data = result.getOrNull()
|
|
||||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
channel.setMessageHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
run {
|
run {
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds$separatedMessageChannelSuffix", codec, taskQueue)
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds$separatedMessageChannelSuffix", codec, taskQueue)
|
||||||
if (api != null) {
|
if (api != null) {
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import com.bumptech.glide.Glide
|
|||||||
import com.bumptech.glide.load.ImageHeaderParser
|
import com.bumptech.glide.load.ImageHeaderParser
|
||||||
import com.bumptech.glide.load.ImageHeaderParserUtils
|
import com.bumptech.glide.load.ImageHeaderParserUtils
|
||||||
import com.bumptech.glide.load.resource.bitmap.DefaultImageHeaderParser
|
import com.bumptech.glide.load.resource.bitmap.DefaultImageHeaderParser
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
@@ -41,11 +39,10 @@ sealed class AssetResult {
|
|||||||
private const val TAG = "NativeSyncApiImplBase"
|
private const val TAG = "NativeSyncApiImplBase"
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAware {
|
open class NativeSyncApiImplBase(context: Context) : ImmichPlugin() {
|
||||||
private val ctx: Context = context.applicationContext
|
private val ctx: Context = context.applicationContext
|
||||||
|
|
||||||
private var hashTask: Job? = null
|
private var hashTask: Job? = null
|
||||||
private val mediaTrashDelegate = MediaTrashDelegate(ctx)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MAX_CONCURRENT_HASH_OPERATIONS = 16
|
private const val MAX_CONCURRENT_HASH_OPERATIONS = 16
|
||||||
@@ -451,26 +448,6 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
|
|||||||
hashTask = null
|
hashTask = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restoreFromTrashById(mediaId: String, type: Long, callback: (Result<Boolean>) -> Unit) {
|
|
||||||
mediaTrashDelegate.restoreFromTrashById(mediaId, type) { completeWhenActive(callback, it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
|
||||||
mediaTrashDelegate.onAttachedToActivity(binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromActivityForConfigChanges() {
|
|
||||||
mediaTrashDelegate.onDetachedFromActivity()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
|
|
||||||
mediaTrashDelegate.onAttachedToActivity(binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromActivity() {
|
|
||||||
mediaTrashDelegate.onDetachedFromActivity()
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method is only implemented on iOS; on Android, we do not have a concept of cloud IDs
|
// This method is only implemented on iOS; on Android, we do not have a concept of cloud IDs
|
||||||
@Suppress("unused", "UNUSED_PARAMETER")
|
@Suppress("unused", "UNUSED_PARAMETER")
|
||||||
fun getCloudIdForAssetIds(assetIds: List<String>): List<CloudIdResult> {
|
fun getCloudIdForAssetIds(assetIds: List<String>): List<CloudIdResult> {
|
||||||
|
|||||||
@@ -5,7 +5,3 @@ android.nonTransitiveRClass=false
|
|||||||
android.nonFinalResIds=false
|
android.nonFinalResIds=false
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
# This builtInKotlin flag was added automatically by Flutter migrator
|
|
||||||
android.builtInKotlin=false
|
|
||||||
# This newDsl flag was added automatically by Flutter migrator
|
|
||||||
android.newDsl=false
|
|
||||||
|
|||||||
@@ -1,23 +1,58 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- background_downloader (0.0.1):
|
||||||
|
- Flutter
|
||||||
- bonsoir_darwin (0.0.1):
|
- bonsoir_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- connectivity_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
- cupertino_http (0.0.1):
|
- cupertino_http (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- device_info_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_local_notifications (0.0.1):
|
- flutter_local_notifications (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- flutter_native_splash (2.4.3):
|
||||||
|
- Flutter
|
||||||
- flutter_secure_storage (6.0.0):
|
- flutter_secure_storage (6.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- flutter_udid (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- KeychainAccess
|
||||||
|
- flutter_web_auth_2 (5.0.0):
|
||||||
|
- Flutter
|
||||||
- fluttertoast (0.0.2):
|
- fluttertoast (0.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- geolocator_apple (1.2.0):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- home_widget (0.0.1):
|
- home_widget (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- image_picker_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- integration_test (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- KeychainAccess (4.2.2)
|
||||||
|
- local_auth_darwin (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- MapLibre (6.14.0)
|
||||||
|
- maplibre_gl (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- MapLibre (= 6.14.0)
|
||||||
- native_video_player (1.0.0):
|
- native_video_player (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- network_info_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- package_info_plus (0.4.5):
|
||||||
|
- Flutter
|
||||||
- permission_handler_apple (9.3.0):
|
- permission_handler_apple (9.3.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- photo_manager (3.9.0):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- share_handler_ios (0.0.14):
|
- share_handler_ios (0.0.14):
|
||||||
- Flutter
|
- Flutter
|
||||||
- share_handler_ios/share_handler_ios_models (= 0.0.14)
|
- share_handler_ios/share_handler_ios_models (= 0.0.14)
|
||||||
@@ -26,56 +61,144 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- share_handler_ios_models
|
- share_handler_ios_models
|
||||||
- share_handler_ios_models (0.0.9)
|
- share_handler_ios_models (0.0.9)
|
||||||
|
- share_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- shared_preferences_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
|
- url_launcher_ios (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- wakelock_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- background_downloader (from `.symlinks/plugins/background_downloader/ios`)
|
||||||
- bonsoir_darwin (from `.symlinks/plugins/bonsoir_darwin/darwin`)
|
- bonsoir_darwin (from `.symlinks/plugins/bonsoir_darwin/darwin`)
|
||||||
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- cupertino_http (from `.symlinks/plugins/cupertino_http/darwin`)
|
- cupertino_http (from `.symlinks/plugins/cupertino_http/darwin`)
|
||||||
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
|
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
||||||
|
- flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||||
|
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
|
||||||
- home_widget (from `.symlinks/plugins/home_widget/ios`)
|
- home_widget (from `.symlinks/plugins/home_widget/ios`)
|
||||||
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
|
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||||
|
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||||
|
- maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`)
|
||||||
- native_video_player (from `.symlinks/plugins/native_video_player/ios`)
|
- native_video_player (from `.symlinks/plugins/native_video_player/ios`)
|
||||||
|
- network_info_plus (from `.symlinks/plugins/network_info_plus/ios`)
|
||||||
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
|
- photo_manager (from `.symlinks/plugins/photo_manager/darwin`)
|
||||||
- share_handler_ios (from `.symlinks/plugins/share_handler_ios/ios`)
|
- share_handler_ios (from `.symlinks/plugins/share_handler_ios/ios`)
|
||||||
- share_handler_ios_models (from `.symlinks/plugins/share_handler_ios/ios/Models`)
|
- share_handler_ios_models (from `.symlinks/plugins/share_handler_ios/ios/Models`)
|
||||||
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- KeychainAccess
|
||||||
|
- MapLibre
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
background_downloader:
|
||||||
|
:path: ".symlinks/plugins/background_downloader/ios"
|
||||||
bonsoir_darwin:
|
bonsoir_darwin:
|
||||||
:path: ".symlinks/plugins/bonsoir_darwin/darwin"
|
:path: ".symlinks/plugins/bonsoir_darwin/darwin"
|
||||||
|
connectivity_plus:
|
||||||
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
cupertino_http:
|
cupertino_http:
|
||||||
:path: ".symlinks/plugins/cupertino_http/darwin"
|
:path: ".symlinks/plugins/cupertino_http/darwin"
|
||||||
|
device_info_plus:
|
||||||
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_local_notifications:
|
flutter_local_notifications:
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
|
flutter_native_splash:
|
||||||
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||||
|
flutter_udid:
|
||||||
|
:path: ".symlinks/plugins/flutter_udid/ios"
|
||||||
|
flutter_web_auth_2:
|
||||||
|
:path: ".symlinks/plugins/flutter_web_auth_2/ios"
|
||||||
fluttertoast:
|
fluttertoast:
|
||||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||||
|
geolocator_apple:
|
||||||
|
:path: ".symlinks/plugins/geolocator_apple/darwin"
|
||||||
home_widget:
|
home_widget:
|
||||||
:path: ".symlinks/plugins/home_widget/ios"
|
:path: ".symlinks/plugins/home_widget/ios"
|
||||||
|
image_picker_ios:
|
||||||
|
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||||
|
integration_test:
|
||||||
|
:path: ".symlinks/plugins/integration_test/ios"
|
||||||
|
local_auth_darwin:
|
||||||
|
:path: ".symlinks/plugins/local_auth_darwin/darwin"
|
||||||
|
maplibre_gl:
|
||||||
|
:path: ".symlinks/plugins/maplibre_gl/ios"
|
||||||
native_video_player:
|
native_video_player:
|
||||||
:path: ".symlinks/plugins/native_video_player/ios"
|
:path: ".symlinks/plugins/native_video_player/ios"
|
||||||
|
network_info_plus:
|
||||||
|
:path: ".symlinks/plugins/network_info_plus/ios"
|
||||||
|
package_info_plus:
|
||||||
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
|
photo_manager:
|
||||||
|
:path: ".symlinks/plugins/photo_manager/darwin"
|
||||||
share_handler_ios:
|
share_handler_ios:
|
||||||
:path: ".symlinks/plugins/share_handler_ios/ios"
|
:path: ".symlinks/plugins/share_handler_ios/ios"
|
||||||
share_handler_ios_models:
|
share_handler_ios_models:
|
||||||
:path: ".symlinks/plugins/share_handler_ios/ios/Models"
|
:path: ".symlinks/plugins/share_handler_ios/ios/Models"
|
||||||
|
share_plus:
|
||||||
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
|
url_launcher_ios:
|
||||||
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
wakelock_plus:
|
||||||
|
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
background_downloader: 50e91d979067b82081aba359d7d916b3ba5fadad
|
||||||
bonsoir_darwin: 29c7ccf356646118844721f36e1de4b61f6cbd0e
|
bonsoir_darwin: 29c7ccf356646118844721f36e1de4b61f6cbd0e
|
||||||
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
|
cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c
|
||||||
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
||||||
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
|
flutter_udid: 92a5d31fe0526b7b6002a2318df702e12e7eb300
|
||||||
|
flutter_web_auth_2: 646fc9df97a01c59e5eea99b237da2c6360f8439
|
||||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||||
|
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
|
||||||
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
|
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
|
||||||
|
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||||
|
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
|
||||||
|
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
|
||||||
|
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
|
||||||
|
MapLibre: 69e572367f4ef6287e18246cfafc39c80cdcabcd
|
||||||
|
maplibre_gl: 3c924e44725147b03dda33430ad216005b40555f
|
||||||
native_video_player: b65c58951ede2f93d103a25366bdebca95081265
|
native_video_player: b65c58951ede2f93d103a25366bdebca95081265
|
||||||
|
network_info_plus: cf61925ab5205dce05a4f0895989afdb6aade5fc
|
||||||
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||||
|
photo_manager: 25fd77df14f4f0ba5ef99e2c61814dde77e2bceb
|
||||||
share_handler_ios: e2244e990f826b2c8eaa291ac3831569438ba0fb
|
share_handler_ios: e2244e990f826b2c8eaa291ac3831569438ba0fb
|
||||||
share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871
|
share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871
|
||||||
|
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||||
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
|
|
||||||
PODFILE CHECKSUM: 938abbae4114b9c2140c550a2a0d8f7c674f5dfe
|
PODFILE CHECKSUM: 938abbae4114b9c2140c550a2a0d8f7c674f5dfe
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
B21E34AC2E5B09190031FDB9 /* BackgroundWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B21E34AB2E5B09100031FDB9 /* BackgroundWorker.swift */; };
|
B21E34AC2E5B09190031FDB9 /* BackgroundWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B21E34AB2E5B09100031FDB9 /* BackgroundWorker.swift */; };
|
||||||
B25D377A2E72CA15008B6CA7 /* Connectivity.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */; };
|
B25D377A2E72CA15008B6CA7 /* Connectivity.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */; };
|
||||||
B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.swift */; };
|
B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.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 */; };
|
|
||||||
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 */; };
|
||||||
D218389C4A4C4693F141F7D1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 886774DBDDE6B35BF2B4F2CD /* 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 */; };
|
||||||
@@ -39,7 +37,6 @@
|
|||||||
FEE084F82EC172460045228E /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084F72EC172460045228E /* SQLiteData */; };
|
FEE084F82EC172460045228E /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084F72EC172460045228E /* SQLiteData */; };
|
||||||
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084FA2EC1725A0045228E /* RawStructuredFieldValues */; };
|
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084FA2EC1725A0045228E /* RawStructuredFieldValues */; };
|
||||||
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084FC2EC1725A0045228E /* StructuredFieldValues */; };
|
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084FC2EC1725A0045228E /* StructuredFieldValues */; };
|
||||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -108,8 +105,6 @@
|
|||||||
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>"; };
|
||||||
B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityApiImpl.swift; sourceTree = "<group>"; };
|
B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityApiImpl.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>"; };
|
|
||||||
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>"; };
|
||||||
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>"; };
|
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>"; };
|
||||||
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; };
|
||||||
@@ -130,7 +125,6 @@
|
|||||||
FE5499F72F1198DE006016CB /* RemoteImagesImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteImagesImpl.swift; sourceTree = "<group>"; };
|
FE5499F72F1198DE006016CB /* RemoteImagesImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteImagesImpl.swift; sourceTree = "<group>"; };
|
||||||
FE5FE4AD2F30FBC000A71243 /* ImageProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProcessing.swift; sourceTree = "<group>"; };
|
FE5FE4AD2F30FBC000A71243 /* ImageProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProcessing.swift; sourceTree = "<group>"; };
|
||||||
FEAFA8722E4D42F4001E47FE /* Thumbhash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbhash.swift; sourceTree = "<group>"; };
|
FEAFA8722E4D42F4001E47FE /* Thumbhash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbhash.swift; sourceTree = "<group>"; };
|
||||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
@@ -195,7 +189,6 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
|
||||||
FEE084F82EC172460045228E /* SQLiteData in Frameworks */,
|
FEE084F82EC172460045228E /* SQLiteData in Frameworks */,
|
||||||
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */,
|
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */,
|
||||||
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */,
|
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */,
|
||||||
@@ -250,7 +243,6 @@
|
|||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
|
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
@@ -291,7 +283,6 @@
|
|||||||
B25D37792E72CA15008B6CA7 /* Connectivity */,
|
B25D37792E72CA15008B6CA7 /* Connectivity */,
|
||||||
B21E34A62E5AF9760031FDB9 /* Background */,
|
B21E34A62E5AF9760031FDB9 /* Background */,
|
||||||
B2CF7F8C2DDE4EBB00744BF6 /* Sync */,
|
B2CF7F8C2DDE4EBB00744BF6 /* Sync */,
|
||||||
B2EE00052E72CA15008B6CA7 /* Permission */,
|
|
||||||
FA9973382CF6DF4B000EF859 /* Runner.entitlements */,
|
FA9973382CF6DF4B000EF859 /* Runner.entitlements */,
|
||||||
FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */,
|
FAC7416727DB9F5500C668D8 /* RunnerProfile.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
@@ -326,15 +317,6 @@
|
|||||||
path = Connectivity;
|
path = Connectivity;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
B2EE00052E72CA15008B6CA7 /* Permission */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
B2EE00032E72CA15008B6CA7 /* PermissionApiImpl.swift */,
|
|
||||||
B2EE00012E72CA15008B6CA7 /* PermissionApi.g.swift */,
|
|
||||||
);
|
|
||||||
path = Permission;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
FAC6F8B62D287F120078CB2F /* ShareExtension */ = {
|
FAC6F8B62D287F120078CB2F /* ShareExtension */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -364,9 +346,6 @@
|
|||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
packageProductDependencies = (
|
|
||||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
|
||||||
);
|
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
@@ -470,7 +449,6 @@
|
|||||||
);
|
);
|
||||||
mainGroup = 97C146E51CF9000F007C117D;
|
mainGroup = 97C146E51CF9000F007C117D;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
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" */,
|
||||||
);
|
);
|
||||||
@@ -641,8 +619,6 @@
|
|||||||
FE5499F42F1197D8006016CB /* RemoteImages.g.swift in Sources */,
|
FE5499F42F1197D8006016CB /* RemoteImages.g.swift in Sources */,
|
||||||
FE5FE4AE2F30FBC000A71243 /* ImageProcessing.swift in Sources */,
|
FE5FE4AE2F30FBC000A71243 /* ImageProcessing.swift in Sources */,
|
||||||
B25D377A2E72CA15008B6CA7 /* Connectivity.g.swift in Sources */,
|
B25D377A2E72CA15008B6CA7 /* Connectivity.g.swift in Sources */,
|
||||||
B2EE00022E72CA15008B6CA7 /* PermissionApi.g.swift in Sources */,
|
|
||||||
B2EE00042E72CA15008B6CA7 /* PermissionApiImpl.swift in Sources */,
|
|
||||||
FE5499F82F1198E2006016CB /* RemoteImagesImpl.swift in Sources */,
|
FE5499F82F1198E2006016CB /* RemoteImagesImpl.swift in Sources */,
|
||||||
FEAFA8732E4D42F4001E47FE /* Thumbhash.swift in Sources */,
|
FEAFA8732E4D42F4001E47FE /* Thumbhash.swift in Sources */,
|
||||||
B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */,
|
B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */,
|
||||||
@@ -742,7 +718,6 @@
|
|||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share.profile;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
@@ -775,6 +750,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 240;
|
CURRENT_PROJECT_VERSION = 240;
|
||||||
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -825,7 +801,6 @@
|
|||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share.debug;
|
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
@@ -885,7 +860,6 @@
|
|||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
@@ -920,6 +894,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 240;
|
CURRENT_PROJECT_VERSION = 240;
|
||||||
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -949,6 +924,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 240;
|
CURRENT_PROJECT_VERSION = 240;
|
||||||
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -1104,6 +1080,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 240;
|
CURRENT_PROJECT_VERSION = 240;
|
||||||
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -1147,6 +1124,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 240;
|
CURRENT_PROJECT_VERSION = 240;
|
||||||
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -1187,6 +1165,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 240;
|
CURRENT_PROJECT_VERSION = 240;
|
||||||
|
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
@@ -1293,17 +1272,7 @@
|
|||||||
package = FEE084F92EC1725A0045228E /* XCRemoteSwiftPackageReference "swift-http-structured-headers" */;
|
package = FEE084F92EC1725A0045228E /* XCRemoteSwiftPackageReference "swift-http-structured-headers" */;
|
||||||
productName = StructuredFieldValues;
|
productName = StructuredFieldValues;
|
||||||
};
|
};
|
||||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
productName = FlutterGeneratedPluginSwiftPackage;
|
|
||||||
};
|
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
/* Begin XCLocalSwiftPackageReference section */
|
|
||||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
|
|
||||||
isa = XCLocalSwiftPackageReference;
|
|
||||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
|
||||||
};
|
|
||||||
/* End XCLocalSwiftPackageReference section */
|
|
||||||
};
|
};
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-19
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"originHash" : "9be33bfaa68721646604aefff3cabbdaf9a193da192aae024c265065671f6c49",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "combine-schedulers",
|
"identity" : "combine-schedulers",
|
||||||
@@ -18,24 +19,6 @@
|
|||||||
"version" : "7.8.0"
|
"version" : "7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"identity" : "keychainaccess",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/kishikawakatsumi/KeychainAccess",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "84e546727d66f1adc5439debad16270d0fdd04e7",
|
|
||||||
"version" : "4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "maplibre-gl-native-distribution",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/maplibre/maplibre-gl-native-distribution.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "60d9bb85c94ce6e7fc4406cd32529fd12bdb7809",
|
|
||||||
"version" : "6.14.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"identity" : "sqlite-data",
|
"identity" : "sqlite-data",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@@ -163,5 +146,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version" : 2
|
"version" : 3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,24 +5,6 @@
|
|||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
buildImplicitDependencies = "YES">
|
buildImplicitDependencies = "YES">
|
||||||
<PreActions>
|
|
||||||
<ExecutionAction
|
|
||||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
|
||||||
<ActionContent
|
|
||||||
title = "Run Prepare Flutter Framework Script"
|
|
||||||
scriptText = "/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare ">
|
|
||||||
<EnvironmentBuildable>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Immich.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</EnvironmentBuildable>
|
|
||||||
</ActionContent>
|
|
||||||
</ExecutionAction>
|
|
||||||
</PreActions>
|
|
||||||
<BuildActionEntries>
|
<BuildActionEntries>
|
||||||
<BuildActionEntry
|
<BuildActionEntry
|
||||||
buildForTesting = "YES"
|
buildForTesting = "YES"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"originHash" : "9be33bfaa68721646604aefff3cabbdaf9a193da192aae024c265065671f6c49",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "combine-schedulers",
|
"identity" : "combine-schedulers",
|
||||||
@@ -18,24 +19,6 @@
|
|||||||
"version" : "7.9.0"
|
"version" : "7.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"identity" : "keychainaccess",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/kishikawakatsumi/KeychainAccess",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "84e546727d66f1adc5439debad16270d0fdd04e7",
|
|
||||||
"version" : "4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "maplibre-gl-native-distribution",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/maplibre/maplibre-gl-native-distribution.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "60d9bb85c94ce6e7fc4406cd32529fd12bdb7809",
|
|
||||||
"version" : "6.14.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"identity" : "sqlite-data",
|
"identity" : "sqlite-data",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@@ -163,5 +146,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version" : 2
|
"version" : 3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import native_video_player
|
|||||||
|
|
||||||
public static func registerPlugins(with registry: FlutterPluginRegistry, messenger: FlutterBinaryMessenger) {
|
public static func registerPlugins(with registry: FlutterPluginRegistry, messenger: FlutterBinaryMessenger) {
|
||||||
NativeSyncApiImpl.register(with: registry.registrar(forPlugin: NativeSyncApiImpl.name)!)
|
NativeSyncApiImpl.register(with: registry.registrar(forPlugin: NativeSyncApiImpl.name)!)
|
||||||
PermissionApiSetup.setUp(binaryMessenger: messenger, api: PermissionApiImpl())
|
|
||||||
LocalImageApiSetup.setUp(binaryMessenger: messenger, api: LocalImageApiImpl())
|
LocalImageApiSetup.setUp(binaryMessenger: messenger, api: LocalImageApiImpl())
|
||||||
RemoteImageApiSetup.setUp(binaryMessenger: messenger, api: RemoteImageApiImpl())
|
RemoteImageApiSetup.setUp(binaryMessenger: messenger, api: RemoteImageApiImpl())
|
||||||
BackgroundWorkerFgHostApiSetup.setUp(binaryMessenger: messenger, api: BackgroundWorkerApiImpl())
|
BackgroundWorkerFgHostApiSetup.setUp(binaryMessenger: messenger, api: BackgroundWorkerApiImpl())
|
||||||
|
|||||||
Generated
-14
@@ -288,7 +288,6 @@ protocol NetworkApi {
|
|||||||
func hasCertificate() throws -> Bool
|
func hasCertificate() throws -> Bool
|
||||||
func getClientPointer() throws -> Int64
|
func getClientPointer() throws -> Int64
|
||||||
func setRequestHeaders(headers: [String: String], serverUrls: [String], token: String?) throws
|
func setRequestHeaders(headers: [String: String], serverUrls: [String], token: String?) throws
|
||||||
func getAppGroupId() throws -> String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||||
@@ -389,18 +388,5 @@ class NetworkApiSetup {
|
|||||||
} else {
|
} else {
|
||||||
setRequestHeadersChannel.setMessageHandler(nil)
|
setRequestHeadersChannel.setMessageHandler(nil)
|
||||||
}
|
}
|
||||||
let getAppGroupIdChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.getAppGroupId\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
if let api = api {
|
|
||||||
getAppGroupIdChannel.setMessageHandler { _, reply in
|
|
||||||
do {
|
|
||||||
let result = try api.getAppGroupId()
|
|
||||||
reply(wrapResult(result))
|
|
||||||
} catch {
|
|
||||||
reply(wrapError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
getAppGroupIdChannel.setMessageHandler(nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,10 +61,6 @@ class NetworkApiImpl: NetworkApi {
|
|||||||
return Int64(Int(bitPattern: pointer))
|
return Int64(Int(bitPattern: pointer))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAppGroupId() throws -> String {
|
|
||||||
return Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as! String
|
|
||||||
}
|
|
||||||
|
|
||||||
func setRequestHeaders(headers: [String : String], serverUrls: [String], token: String?) throws {
|
func setRequestHeaders(headers: [String : String], serverUrls: [String], token: String?) throws {
|
||||||
URLSessionManager.setServerUrls(serverUrls)
|
URLSessionManager.setServerUrls(serverUrls)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import native_video_player
|
|||||||
let CLIENT_CERT_LABEL = "app.alextran.immich.client_identity"
|
let CLIENT_CERT_LABEL = "app.alextran.immich.client_identity"
|
||||||
let HEADERS_KEY = "immich.request_headers"
|
let HEADERS_KEY = "immich.request_headers"
|
||||||
let SERVER_URLS_KEY = "immich.server_urls"
|
let SERVER_URLS_KEY = "immich.server_urls"
|
||||||
let APP_GROUP = Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as! String
|
let APP_GROUP = "group.app.immich.share"
|
||||||
let COOKIE_EXPIRY_DAYS: TimeInterval = 400
|
let COOKIE_EXPIRY_DAYS: TimeInterval = 400
|
||||||
|
|
||||||
enum AuthCookie: CaseIterable {
|
enum AuthCookie: CaseIterable {
|
||||||
|
|||||||
-106
@@ -1,106 +0,0 @@
|
|||||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
|
||||||
// See also: https://pub.dev/packages/pigeon
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
import Flutter
|
|
||||||
#elseif os(macOS)
|
|
||||||
import FlutterMacOS
|
|
||||||
#else
|
|
||||||
#error("Unsupported platform.")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private func wrapResult(_ result: Any?) -> [Any?] {
|
|
||||||
return [result]
|
|
||||||
}
|
|
||||||
|
|
||||||
private func wrapError(_ error: Any) -> [Any?] {
|
|
||||||
if let pigeonError = error as? PigeonError {
|
|
||||||
return [
|
|
||||||
pigeonError.code,
|
|
||||||
pigeonError.message,
|
|
||||||
pigeonError.details,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
if let flutterError = error as? FlutterError {
|
|
||||||
return [
|
|
||||||
flutterError.code,
|
|
||||||
flutterError.message,
|
|
||||||
flutterError.details,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
"\(error)",
|
|
||||||
"\(Swift.type(of: error))",
|
|
||||||
"Stacktrace: \(Thread.callStackSymbols)",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
private func isNullish(_ value: Any?) -> Bool {
|
|
||||||
return value is NSNull || value == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
private func nilOrValue<T>(_ value: Any?) -> T? {
|
|
||||||
if value is NSNull { return nil }
|
|
||||||
return value as! T?
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
|
||||||
protocol PermissionApi {
|
|
||||||
func hasManageMediaPermission() throws -> Bool
|
|
||||||
func requestManageMediaPermission(completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
func manageMediaPermission(completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
|
||||||
class PermissionApiSetup {
|
|
||||||
static var codec: FlutterStandardMessageCodec { FlutterStandardMessageCodec.sharedInstance() }
|
|
||||||
/// Sets up an instance of `PermissionApi` to handle messages through the `binaryMessenger`.
|
|
||||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: PermissionApi?, messageChannelSuffix: String = "") {
|
|
||||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
|
||||||
let hasManageMediaPermissionChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.PermissionApi.hasManageMediaPermission\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
if let api = api {
|
|
||||||
hasManageMediaPermissionChannel.setMessageHandler { _, reply in
|
|
||||||
do {
|
|
||||||
let result = try api.hasManageMediaPermission()
|
|
||||||
reply(wrapResult(result))
|
|
||||||
} catch {
|
|
||||||
reply(wrapError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hasManageMediaPermissionChannel.setMessageHandler(nil)
|
|
||||||
}
|
|
||||||
let requestManageMediaPermissionChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.PermissionApi.requestManageMediaPermission\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
if let api = api {
|
|
||||||
requestManageMediaPermissionChannel.setMessageHandler { _, reply in
|
|
||||||
api.requestManageMediaPermission { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let res):
|
|
||||||
reply(wrapResult(res))
|
|
||||||
case .failure(let error):
|
|
||||||
reply(wrapError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
requestManageMediaPermissionChannel.setMessageHandler(nil)
|
|
||||||
}
|
|
||||||
let manageMediaPermissionChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.PermissionApi.manageMediaPermission\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
if let api = api {
|
|
||||||
manageMediaPermissionChannel.setMessageHandler { _, reply in
|
|
||||||
api.manageMediaPermission { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let res):
|
|
||||||
reply(wrapResult(res))
|
|
||||||
case .failure(let error):
|
|
||||||
reply(wrapError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
manageMediaPermissionChannel.setMessageHandler(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
class PermissionApiImpl: PermissionApi {
|
|
||||||
func hasManageMediaPermission() throws -> Bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func requestManageMediaPermission(completion: @escaping (Result<Bool, Error>) -> Void) {
|
|
||||||
completion(.success(false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func manageMediaPermission(completion: @escaping (Result<Bool, Error>) -> Void) {
|
|
||||||
completion(.success(false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(CUSTOM_GROUP_ID)</string>
|
<string>group.app.immich.share</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(CUSTOM_GROUP_ID)</string>
|
<string>group.app.immich.share</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
Generated
-19
@@ -537,7 +537,6 @@ protocol NativeSyncApi {
|
|||||||
func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void)
|
func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void)
|
||||||
func cancelHashing() throws
|
func cancelHashing() throws
|
||||||
func getTrashedAssets() throws -> [String: [PlatformAsset]]
|
func getTrashedAssets() throws -> [String: [PlatformAsset]]
|
||||||
func restoreFromTrashById(mediaId: String, type: Int64, completion: @escaping (Result<Bool, Error>) -> Void)
|
|
||||||
func getCloudIdForAssetIds(assetIds: [String]) throws -> [CloudIdResult]
|
func getCloudIdForAssetIds(assetIds: [String]) throws -> [CloudIdResult]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,24 +721,6 @@ class NativeSyncApiSetup {
|
|||||||
} else {
|
} else {
|
||||||
getTrashedAssetsChannel.setMessageHandler(nil)
|
getTrashedAssetsChannel.setMessageHandler(nil)
|
||||||
}
|
}
|
||||||
let restoreFromTrashByIdChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.restoreFromTrashById\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
|
||||||
if let api = api {
|
|
||||||
restoreFromTrashByIdChannel.setMessageHandler { message, reply in
|
|
||||||
let args = message as! [Any?]
|
|
||||||
let mediaIdArg = args[0] as! String
|
|
||||||
let typeArg = args[1] as! Int64
|
|
||||||
api.restoreFromTrashById(mediaId: mediaIdArg, type: typeArg) { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let res):
|
|
||||||
reply(wrapResult(res))
|
|
||||||
case .failure(let error):
|
|
||||||
reply(wrapError(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
restoreFromTrashByIdChannel.setMessageHandler(nil)
|
|
||||||
}
|
|
||||||
let getCloudIdForAssetIdsChannel = taskQueue == nil
|
let getCloudIdForAssetIdsChannel = taskQueue == nil
|
||||||
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||||
|
|||||||
@@ -382,10 +382,6 @@ class NativeSyncApiImpl: ImmichPlugin, NativeSyncApi, FlutterPlugin {
|
|||||||
func getTrashedAssets() throws -> [String: [PlatformAsset]] {
|
func getTrashedAssets() throws -> [String: [PlatformAsset]] {
|
||||||
throw PigeonError(code: "UNSUPPORTED_OS", message: "This feature not supported on iOS.", details: nil)
|
throw PigeonError(code: "UNSUPPORTED_OS", message: "This feature not supported on iOS.", details: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreFromTrashById(mediaId: String, type: Int64, completion: @escaping (Result<Bool, Error>) -> Void) {
|
|
||||||
completion(.success(false))
|
|
||||||
}
|
|
||||||
|
|
||||||
private func getAssetsFromAlbum(in album: PHAssetCollection, options: PHFetchOptions) -> PHFetchResult<PHAsset> {
|
private func getAssetsFromAlbum(in album: PHAssetCollection, options: PHFetchOptions) -> PHFetchResult<PHAsset> {
|
||||||
// Ensure to actually getting all assets for the Recents album
|
// Ensure to actually getting all assets for the Recents album
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(CUSTOM_GROUP_ID)</string>
|
<string>group.app.immich.share</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -2,7 +2,7 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import WidgetKit
|
import WidgetKit
|
||||||
|
|
||||||
let IMMICH_SHARE_GROUP = Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as! String
|
let IMMICH_SHARE_GROUP = "group.app.immich.share"
|
||||||
|
|
||||||
enum WidgetError: Error, Codable {
|
enum WidgetError: Error, Codable {
|
||||||
case noLogin
|
case noLogin
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>AppGroupId</key>
|
|
||||||
<string>$(CUSTOM_GROUP_ID)</string>
|
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(CUSTOM_GROUP_ID)</string>
|
<string>group.app.immich.share</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -21,7 +21,6 @@ platform :ios do
|
|||||||
CODE_SIGN_IDENTITY = "Apple Distribution: FUTO Holdings, Inc. (#{TEAM_ID})"
|
CODE_SIGN_IDENTITY = "Apple Distribution: FUTO Holdings, Inc. (#{TEAM_ID})"
|
||||||
BASE_BUNDLE_ID = "app.alextran.immich"
|
BASE_BUNDLE_ID = "app.alextran.immich"
|
||||||
DEV_BUNDLE_ID = "tech.futo.immich.testflight"
|
DEV_BUNDLE_ID = "tech.futo.immich.testflight"
|
||||||
DEV_GROUP_ID = "group.app.immich.share.testflight"
|
|
||||||
|
|
||||||
# Helper method to get App Store Connect API key
|
# Helper method to get App Store Connect API key
|
||||||
def get_api_key
|
def get_api_key
|
||||||
@@ -34,13 +33,6 @@ platform :ios do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Helper method to assemble xcargs with optional CUSTOM_GROUP_ID override
|
|
||||||
def build_xcargs(group_id: nil)
|
|
||||||
args = "-skipMacroValidation CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual"
|
|
||||||
args += " CUSTOM_GROUP_ID='#{group_id}'" if group_id
|
|
||||||
args
|
|
||||||
end
|
|
||||||
|
|
||||||
# Helper method to get version from pubspec.yaml
|
# Helper method to get version from pubspec.yaml
|
||||||
def get_version_from_pubspec
|
def get_version_from_pubspec
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
@@ -97,8 +89,7 @@ end
|
|||||||
version_number: nil,
|
version_number: nil,
|
||||||
profile_name_main:,
|
profile_name_main:,
|
||||||
profile_name_share:,
|
profile_name_share:,
|
||||||
profile_name_widget:,
|
profile_name_widget:
|
||||||
group_id: nil
|
|
||||||
)
|
)
|
||||||
app_identifier = base_bundle_id
|
app_identifier = base_bundle_id
|
||||||
|
|
||||||
@@ -106,7 +97,7 @@ end
|
|||||||
if version_number
|
if version_number
|
||||||
increment_version_number(version_number: version_number)
|
increment_version_number(version_number: version_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Increment build number
|
# Increment build number
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number(
|
build_number: latest_testflight_build_number(
|
||||||
@@ -115,14 +106,14 @@ end
|
|||||||
) + 1,
|
) + 1,
|
||||||
xcodeproj: "./Runner.xcodeproj"
|
xcodeproj: "./Runner.xcodeproj"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build the app
|
# Build the app
|
||||||
build_app(
|
build_app(
|
||||||
scheme: "Runner",
|
scheme: "Runner",
|
||||||
workspace: "Runner.xcworkspace",
|
workspace: "Runner.xcworkspace",
|
||||||
configuration: configuration,
|
configuration: configuration,
|
||||||
export_method: "app-store",
|
export_method: "app-store",
|
||||||
xcargs: build_xcargs(group_id: group_id),
|
xcargs: "-skipMacroValidation CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual",
|
||||||
export_options: {
|
export_options: {
|
||||||
provisioningProfiles: {
|
provisioningProfiles: {
|
||||||
"#{app_identifier}" => profile_name_main,
|
"#{app_identifier}" => profile_name_main,
|
||||||
@@ -174,8 +165,7 @@ end
|
|||||||
distribute_external: false,
|
distribute_external: false,
|
||||||
profile_name_main: main_profile_name,
|
profile_name_main: main_profile_name,
|
||||||
profile_name_share: share_profile_name,
|
profile_name_share: share_profile_name,
|
||||||
profile_name_widget: widget_profile_name,
|
profile_name_widget: widget_profile_name
|
||||||
group_id: DEV_GROUP_ID
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -284,7 +274,7 @@ end
|
|||||||
configuration: "Release",
|
configuration: "Release",
|
||||||
export_method: "app-store",
|
export_method: "app-store",
|
||||||
skip_package_ipa: true,
|
skip_package_ipa: true,
|
||||||
xcargs: build_xcargs(group_id: DEV_GROUP_ID),
|
xcargs: "-skipMacroValidation CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual",
|
||||||
export_options: {
|
export_options: {
|
||||||
provisioningProfiles: {
|
provisioningProfiles: {
|
||||||
DEV_BUNDLE_ID => main_profile_name,
|
DEV_BUNDLE_ID => main_profile_name,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const int kTimelineAssetLoadBatchSize = 1024;
|
|||||||
const int kTimelineAssetLoadOppositeSize = 64;
|
const int kTimelineAssetLoadOppositeSize = 64;
|
||||||
|
|
||||||
// Widget keys
|
// Widget keys
|
||||||
|
const String appShareGroupId = "group.app.immich.share";
|
||||||
const String kWidgetAuthToken = "widget_auth_token";
|
const String kWidgetAuthToken = "widget_auth_token";
|
||||||
const String kWidgetServerEndpoint = "widget_server_url";
|
const String kWidgetServerEndpoint = "widget_server_url";
|
||||||
const String kWidgetCustomHeaders = "widget_custom_headers";
|
const String kWidgetCustomHeaders = "widget_custom_headers";
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:immich_mobile/domain/models/config/album_config.dart';
|
import 'package:immich_mobile/domain/models/config/album_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/backup_config.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/config/cleanup_config.dart';
|
import 'package:immich_mobile/domain/models/config/cleanup_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/image_config.dart';
|
import 'package:immich_mobile/domain/models/config/image_config.dart';
|
||||||
import 'package:immich_mobile/domain/models/config/map_config.dart';
|
import 'package:immich_mobile/domain/models/config/map_config.dart';
|
||||||
@@ -17,7 +16,6 @@ class AppConfig {
|
|||||||
final ViewerConfig viewer;
|
final ViewerConfig viewer;
|
||||||
final SlideshowConfig slideshow;
|
final SlideshowConfig slideshow;
|
||||||
final AlbumConfig album;
|
final AlbumConfig album;
|
||||||
final BackupConfig backup;
|
|
||||||
|
|
||||||
const AppConfig({
|
const AppConfig({
|
||||||
this.theme = const .new(),
|
this.theme = const .new(),
|
||||||
@@ -28,7 +26,6 @@ class AppConfig {
|
|||||||
this.viewer = const .new(),
|
this.viewer = const .new(),
|
||||||
this.slideshow = const .new(),
|
this.slideshow = const .new(),
|
||||||
this.album = const .new(),
|
this.album = const .new(),
|
||||||
this.backup = const .new(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AppConfig copyWith({
|
AppConfig copyWith({
|
||||||
@@ -40,7 +37,6 @@ class AppConfig {
|
|||||||
ViewerConfig? viewer,
|
ViewerConfig? viewer,
|
||||||
SlideshowConfig? slideshow,
|
SlideshowConfig? slideshow,
|
||||||
AlbumConfig? album,
|
AlbumConfig? album,
|
||||||
BackupConfig? backup,
|
|
||||||
}) => .new(
|
}) => .new(
|
||||||
theme: theme ?? this.theme,
|
theme: theme ?? this.theme,
|
||||||
cleanup: cleanup ?? this.cleanup,
|
cleanup: cleanup ?? this.cleanup,
|
||||||
@@ -50,7 +46,6 @@ class AppConfig {
|
|||||||
viewer: viewer ?? this.viewer,
|
viewer: viewer ?? this.viewer,
|
||||||
slideshow: slideshow ?? this.slideshow,
|
slideshow: slideshow ?? this.slideshow,
|
||||||
album: album ?? this.album,
|
album: album ?? this.album,
|
||||||
backup: backup ?? this.backup,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -64,13 +59,12 @@ class AppConfig {
|
|||||||
other.image == image &&
|
other.image == image &&
|
||||||
other.viewer == viewer &&
|
other.viewer == viewer &&
|
||||||
other.slideshow == slideshow &&
|
other.slideshow == slideshow &&
|
||||||
other.album == album &&
|
other.album == album);
|
||||||
other.backup == backup);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(theme, cleanup, map, timeline, image, viewer, slideshow, album, backup);
|
int get hashCode => Object.hash(theme, cleanup, map, timeline, image, viewer, slideshow, album);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'AppConfig(theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer, slideshow: $slideshow, album: $album, backup: $backup)';
|
'AppConfig(theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer, slideshow: $slideshow, album: $album)';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
class BackupConfig {
|
|
||||||
final bool enabled;
|
|
||||||
final bool useCellularForVideos;
|
|
||||||
final bool useCellularForPhotos;
|
|
||||||
final bool requireCharging;
|
|
||||||
final int triggerDelay;
|
|
||||||
final bool syncAlbums;
|
|
||||||
|
|
||||||
const BackupConfig({
|
|
||||||
this.enabled = false,
|
|
||||||
this.useCellularForVideos = false,
|
|
||||||
this.useCellularForPhotos = false,
|
|
||||||
this.requireCharging = false,
|
|
||||||
this.triggerDelay = 30,
|
|
||||||
this.syncAlbums = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
BackupConfig copyWith({
|
|
||||||
bool? enabled,
|
|
||||||
bool? useCellularForVideos,
|
|
||||||
bool? useCellularForPhotos,
|
|
||||||
bool? requireCharging,
|
|
||||||
int? triggerDelay,
|
|
||||||
bool? syncAlbums,
|
|
||||||
}) => BackupConfig(
|
|
||||||
enabled: enabled ?? this.enabled,
|
|
||||||
useCellularForVideos: useCellularForVideos ?? this.useCellularForVideos,
|
|
||||||
useCellularForPhotos: useCellularForPhotos ?? this.useCellularForPhotos,
|
|
||||||
requireCharging: requireCharging ?? this.requireCharging,
|
|
||||||
triggerDelay: triggerDelay ?? this.triggerDelay,
|
|
||||||
syncAlbums: syncAlbums ?? this.syncAlbums,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
identical(this, other) ||
|
|
||||||
(other is BackupConfig &&
|
|
||||||
other.enabled == enabled &&
|
|
||||||
other.useCellularForVideos == useCellularForVideos &&
|
|
||||||
other.useCellularForPhotos == useCellularForPhotos &&
|
|
||||||
other.requireCharging == requireCharging &&
|
|
||||||
other.triggerDelay == triggerDelay &&
|
|
||||||
other.syncAlbums == syncAlbums);
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode =>
|
|
||||||
Object.hash(enabled, useCellularForVideos, useCellularForPhotos, requireCharging, triggerDelay, syncAlbums);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() =>
|
|
||||||
'BackupConfig(enabled: $enabled, useCellularForVideos: $useCellularForVideos, useCellularForPhotos: $useCellularForPhotos, requireCharging: $requireCharging, triggerDelay: $triggerDelay, syncAlbums: $syncAlbums)';
|
|
||||||
}
|
|
||||||
@@ -62,14 +62,6 @@ enum MetadataKey<T extends Object> {
|
|||||||
albumIsReverse<bool>(.appConfig, 'album.isReverse', true),
|
albumIsReverse<bool>(.appConfig, 'album.isReverse', true),
|
||||||
albumIsGrid<bool>(.appConfig, 'album.isGrid', false),
|
albumIsGrid<bool>(.appConfig, 'album.isGrid', false),
|
||||||
|
|
||||||
// Backup
|
|
||||||
backupEnabled<bool>(.appConfig, 'backup.enabled', false),
|
|
||||||
backupUseCellularForVideos<bool>(.appConfig, 'backup.useCellularForVideos', false),
|
|
||||||
backupUseCellularForPhotos<bool>(.appConfig, 'backup.useCellularForPhotos', false),
|
|
||||||
backupRequireCharging<bool>(.appConfig, 'backup.requireCharging', false),
|
|
||||||
backupTriggerDelay<int>(.appConfig, 'backup.triggerDelay', 30),
|
|
||||||
backupSyncAlbums<bool>(.appConfig, 'backup.syncAlbums', false),
|
|
||||||
|
|
||||||
// Timeline
|
// Timeline
|
||||||
timelineTilesPerRow<int>(.appConfig, 'timeline.tilesPerRow', 4),
|
timelineTilesPerRow<int>(.appConfig, 'timeline.tilesPerRow', 4),
|
||||||
timelineGroupAssetsBy<GroupAssetsBy>(
|
timelineGroupAssetsBy<GroupAssetsBy>(
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
|
||||||
enum Setting<T> {
|
enum Setting<T> {
|
||||||
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, false);
|
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, false),
|
||||||
|
enableBackup<bool>(StoreKey.enableBackup, false);
|
||||||
|
|
||||||
const Setting(this.storeKey, this.defaultValue);
|
const Setting(this.storeKey, this.defaultValue);
|
||||||
|
|
||||||
|
|||||||
@@ -6,25 +6,26 @@ enum StoreKey<T> {
|
|||||||
version<int>._(0),
|
version<int>._(0),
|
||||||
currentUser<UserDto>._(2),
|
currentUser<UserDto>._(2),
|
||||||
deviceId<String>._(4),
|
deviceId<String>._(4),
|
||||||
|
backupRequireCharging<bool>._(7),
|
||||||
|
backupTriggerDelay<int>._(8),
|
||||||
serverUrl<String>._(10),
|
serverUrl<String>._(10),
|
||||||
accessToken<String>._(11),
|
accessToken<String>._(11),
|
||||||
serverEndpoint<String>._(12),
|
serverEndpoint<String>._(12),
|
||||||
advancedTroubleshooting<bool>._(114),
|
advancedTroubleshooting<bool>._(114),
|
||||||
enableHapticFeedback<bool>._(126),
|
enableHapticFeedback<bool>._(126),
|
||||||
|
syncAlbums<bool>._(131),
|
||||||
|
|
||||||
manageLocalMediaAndroid<bool>._(137),
|
manageLocalMediaAndroid<bool>._(137),
|
||||||
// Read-only Mode settings
|
// Read-only Mode settings
|
||||||
readonlyModeEnabled<bool>._(138),
|
readonlyModeEnabled<bool>._(138),
|
||||||
|
|
||||||
|
// Experimental stuff
|
||||||
|
enableBackup<bool>._(1003),
|
||||||
|
useWifiForUploadVideos<bool>._(1004),
|
||||||
|
useWifiForUploadPhotos<bool>._(1005),
|
||||||
syncMigrationStatus<String>._(1013),
|
syncMigrationStatus<String>._(1013),
|
||||||
|
|
||||||
// Legacy keys that have been migrated to the new metadata store
|
// Legacy keys that have been migrated to the new metadata store
|
||||||
legacyBackupRequireCharging<bool>._(7),
|
|
||||||
legacyBackupTriggerDelay<int>._(8),
|
|
||||||
legacySyncAlbums<bool>._(131),
|
|
||||||
legacyEnableBackup<bool>._(1003),
|
|
||||||
legacyUseWifiForUploadVideos<bool>._(1004),
|
|
||||||
legacyUseWifiForUploadPhotos<bool>._(1005),
|
|
||||||
legacySelectedAlbumSortOrder<int>._(113),
|
legacySelectedAlbumSortOrder<int>._(113),
|
||||||
legacySelectedAlbumSortReverse<bool>._(123),
|
legacySelectedAlbumSortReverse<bool>._(123),
|
||||||
legacyAlbumGridView<bool>._(140),
|
legacyAlbumGridView<bool>._(140),
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ class AssetService {
|
|||||||
final RemoteAssetRepository _remoteAssetRepository;
|
final RemoteAssetRepository _remoteAssetRepository;
|
||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
|
|
||||||
const AssetService({required this._remoteAssetRepository, required this._localAssetRepository});
|
const AssetService({
|
||||||
|
required RemoteAssetRepository remoteAssetRepository,
|
||||||
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
|
}) : _remoteAssetRepository = remoteAssetRepository,
|
||||||
|
_localAssetRepository = localAssetRepository;
|
||||||
|
|
||||||
Future<BaseAsset?> getAsset(BaseAsset asset) {
|
Future<BaseAsset?> getAsset(BaseAsset asset) {
|
||||||
final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id;
|
final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id;
|
||||||
|
|||||||
@@ -11,14 +11,15 @@ 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/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/app_settings.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/infrastructure/db.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart' show nativeSyncApiProvider;
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart' show nativeSyncApiProvider;
|
||||||
import 'package:immich_mobile/providers/user.provider.dart';
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:immich_mobile/services/auth.service.dart';
|
import 'package:immich_mobile/services/auth.service.dart';
|
||||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||||
import 'package:immich_mobile/services/localization.service.dart';
|
import 'package:immich_mobile/services/localization.service.dart';
|
||||||
@@ -38,15 +39,16 @@ class BackgroundWorkerFgService {
|
|||||||
Future<void> saveNotificationMessage(String title, String body) =>
|
Future<void> saveNotificationMessage(String title, String body) =>
|
||||||
_foregroundHostApi.saveNotificationMessage(title, body);
|
_foregroundHostApi.saveNotificationMessage(title, body);
|
||||||
|
|
||||||
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) {
|
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) => _foregroundHostApi.configure(
|
||||||
final backup = MetadataRepository.instance.appConfig.backup;
|
BackgroundWorkerSettings(
|
||||||
return _foregroundHostApi.configure(
|
minimumDelaySeconds:
|
||||||
BackgroundWorkerSettings(
|
minimumDelaySeconds ??
|
||||||
minimumDelaySeconds: minimumDelaySeconds ?? backup.triggerDelay,
|
Store.get(AppSettingsEnum.backupTriggerDelay.storeKey, AppSettingsEnum.backupTriggerDelay.defaultValue),
|
||||||
requiresCharging: requireCharging ?? backup.requireCharging,
|
requiresCharging:
|
||||||
),
|
requireCharging ??
|
||||||
);
|
Store.get(AppSettingsEnum.backupRequireCharging.storeKey, AppSettingsEnum.backupRequireCharging.defaultValue),
|
||||||
}
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> disable() => _foregroundHostApi.disable();
|
Future<void> disable() => _foregroundHostApi.disable();
|
||||||
}
|
}
|
||||||
@@ -61,13 +63,15 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
|||||||
|
|
||||||
bool _isCleanedUp = false;
|
bool _isCleanedUp = false;
|
||||||
|
|
||||||
BackgroundWorkerBgService({required this._drift, required this._driftLogger})
|
BackgroundWorkerBgService({required Drift drift, required DriftLogger driftLogger})
|
||||||
: _backgroundHostApi = BackgroundWorkerBgHostApi() {
|
: _drift = drift,
|
||||||
_ref = ProviderContainer(overrides: [driftProvider.overrideWith(driftOverride(_drift))]);
|
_driftLogger = driftLogger,
|
||||||
|
_backgroundHostApi = BackgroundWorkerBgHostApi() {
|
||||||
|
_ref = ProviderContainer(overrides: [driftProvider.overrideWith(driftOverride(drift))]);
|
||||||
BackgroundWorkerFlutterApi.setUp(this);
|
BackgroundWorkerFlutterApi.setUp(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get _isBackupEnabled => MetadataRepository.instance.appConfig.backup.enabled;
|
bool get _isBackupEnabled => _ref?.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup) ?? false;
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -21,13 +21,18 @@ class HashService {
|
|||||||
final _log = Logger('HashService');
|
final _log = Logger('HashService');
|
||||||
|
|
||||||
HashService({
|
HashService({
|
||||||
required this._localAlbumRepository,
|
required DriftLocalAlbumRepository localAlbumRepository,
|
||||||
required this._localAssetRepository,
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
required this._trashedLocalAssetRepository,
|
required DriftTrashedLocalAssetRepository trashedLocalAssetRepository,
|
||||||
required this._nativeSyncApi,
|
required NativeSyncApi nativeSyncApi,
|
||||||
this._cancelChecker,
|
bool Function()? cancelChecker,
|
||||||
int? batchSize,
|
int? batchSize,
|
||||||
}) : _batchSize = batchSize ?? kBatchHashFileLimit;
|
}) : _localAlbumRepository = localAlbumRepository,
|
||||||
|
_localAssetRepository = localAssetRepository,
|
||||||
|
_trashedLocalAssetRepository = trashedLocalAssetRepository,
|
||||||
|
_cancelChecker = cancelChecker,
|
||||||
|
_nativeSyncApi = nativeSyncApi,
|
||||||
|
_batchSize = batchSize ?? kBatchHashFileLimit;
|
||||||
|
|
||||||
bool get isCancelled => _cancelChecker?.call() ?? false;
|
bool get isCancelled => _cancelChecker?.call() ?? false;
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ 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/local_album.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/permission.repository.dart';
|
|
||||||
import 'package:immich_mobile/utils/datetime_helpers.dart';
|
import 'package:immich_mobile/utils/datetime_helpers.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@@ -23,24 +23,29 @@ class LocalSyncService {
|
|||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
final NativeSyncApi _nativeSyncApi;
|
final NativeSyncApi _nativeSyncApi;
|
||||||
final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository;
|
final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository;
|
||||||
final AssetMediaRepository _assetMediaRepository;
|
final LocalFilesManagerRepository _localFilesManager;
|
||||||
final IPermissionRepository _permissionRepository;
|
final StorageRepository _storageRepository;
|
||||||
final Logger _log = Logger("DeviceSyncService");
|
final Logger _log = Logger("DeviceSyncService");
|
||||||
|
|
||||||
LocalSyncService({
|
LocalSyncService({
|
||||||
required this._localAlbumRepository,
|
required DriftLocalAlbumRepository localAlbumRepository,
|
||||||
required this._localAssetRepository,
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
required this._nativeSyncApi,
|
required DriftTrashedLocalAssetRepository trashedLocalAssetRepository,
|
||||||
required this._trashedLocalAssetRepository,
|
required LocalFilesManagerRepository localFilesManager,
|
||||||
required this._assetMediaRepository,
|
required StorageRepository storageRepository,
|
||||||
required this._permissionRepository,
|
required NativeSyncApi nativeSyncApi,
|
||||||
});
|
}) : _localAlbumRepository = localAlbumRepository,
|
||||||
|
_localAssetRepository = localAssetRepository,
|
||||||
|
_trashedLocalAssetRepository = trashedLocalAssetRepository,
|
||||||
|
_localFilesManager = localFilesManager,
|
||||||
|
_storageRepository = storageRepository,
|
||||||
|
_nativeSyncApi = nativeSyncApi;
|
||||||
|
|
||||||
Future<void> sync({bool full = false}) async {
|
Future<void> sync({bool full = false}) async {
|
||||||
final Stopwatch stopwatch = Stopwatch()..start();
|
final Stopwatch stopwatch = Stopwatch()..start();
|
||||||
try {
|
try {
|
||||||
if (CurrentPlatform.isAndroid && Store.get(StoreKey.manageLocalMediaAndroid, false)) {
|
if (CurrentPlatform.isAndroid && Store.get(StoreKey.manageLocalMediaAndroid, false)) {
|
||||||
final hasPermission = await _permissionRepository.hasManageMediaPermission();
|
final hasPermission = await _localFilesManager.hasManageMediaPermission();
|
||||||
if (hasPermission) {
|
if (hasPermission) {
|
||||||
await _syncTrashedAssets();
|
await _syncTrashedAssets();
|
||||||
} else {
|
} else {
|
||||||
@@ -368,7 +373,7 @@ class LocalSyncService {
|
|||||||
|
|
||||||
final assetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
final assetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
||||||
if (assetsToRestore.isNotEmpty) {
|
if (assetsToRestore.isNotEmpty) {
|
||||||
final restoredIds = await _assetMediaRepository.restoreAssetsFromTrash(assetsToRestore);
|
final restoredIds = await _localFilesManager.restoreAssetsFromTrash(assetsToRestore);
|
||||||
await _trashedLocalAssetRepository.applyRestoredAssets(restoredIds);
|
await _trashedLocalAssetRepository.applyRestoredAssets(restoredIds);
|
||||||
} else {
|
} else {
|
||||||
_log.info("syncTrashedAssets, No remote assets found for restoration");
|
_log.info("syncTrashedAssets, No remote assets found for restoration");
|
||||||
@@ -376,15 +381,15 @@ class LocalSyncService {
|
|||||||
|
|
||||||
final localAssetsToTrash = await _trashedLocalAssetRepository.getToTrash();
|
final localAssetsToTrash = await _trashedLocalAssetRepository.getToTrash();
|
||||||
if (localAssetsToTrash.isNotEmpty) {
|
if (localAssetsToTrash.isNotEmpty) {
|
||||||
final localIds = localAssetsToTrash.values.expand((assets) => assets).map((asset) => asset.id).toList();
|
final mediaUrls = await Future.wait(
|
||||||
_log.info("Moving to trash ${localIds.join(", ")} assets");
|
localAssetsToTrash.values
|
||||||
final movedIds = await _assetMediaRepository.deleteAll(localIds);
|
.expand((e) => e)
|
||||||
if (movedIds.isNotEmpty) {
|
.map((localAsset) => _storageRepository.getAssetEntityForAsset(localAsset).then((e) => e?.getMediaUrl())),
|
||||||
final movedAssetsByAlbum = localAssetsToTrash.map(
|
);
|
||||||
(albumId, assets) => MapEntry(albumId, assets.where((asset) => movedIds.contains(asset.id)).toList()),
|
_log.info("Moving to trash ${mediaUrls.join(", ")} assets");
|
||||||
)..removeWhere((_, assets) => assets.isEmpty);
|
final result = await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList());
|
||||||
|
if (result) {
|
||||||
await _trashedLocalAssetRepository.trashLocalAsset(movedAssetsByAlbum);
|
await _trashedLocalAssetRepository.trashLocalAsset(localAssetsToTrash);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_log.info("syncTrashedAssets, No assets found in backup-enabled albums for move to trash");
|
_log.info("syncTrashedAssets, No assets found in backup-enabled albums for move to trash");
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ typedef MapQuery = ({MapMarkerSource markerSource});
|
|||||||
class MapFactory {
|
class MapFactory {
|
||||||
final DriftMapRepository _mapRepository;
|
final DriftMapRepository _mapRepository;
|
||||||
|
|
||||||
const MapFactory({required this._mapRepository});
|
const MapFactory({required DriftMapRepository mapRepository}) : _mapRepository = mapRepository;
|
||||||
|
|
||||||
MapService remote(List<String> ownerIds, TimelineMapOptions options) =>
|
MapService remote(List<String> ownerIds, TimelineMapOptions options) =>
|
||||||
MapService(_mapRepository.remote(ownerIds, options));
|
MapService(_mapRepository.remote(ownerIds, options));
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ final AppSetting = SettingsService(storeService: StoreService.I);
|
|||||||
class SettingsService {
|
class SettingsService {
|
||||||
final StoreService _storeService;
|
final StoreService _storeService;
|
||||||
|
|
||||||
const SettingsService({required this._storeService});
|
const SettingsService({required StoreService storeService}) : _storeService = storeService;
|
||||||
|
|
||||||
T get<T>(Setting<T> setting) => _storeService.get(setting.storeKey, setting.defaultValue);
|
T get<T>(Setting<T> setting) => _storeService.get(setting.storeKey, setting.defaultValue);
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import 'package:immich_mobile/domain/models/sync_event.model.dart';
|
|||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
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/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/sync_api.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/sync_api.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/sync_migration.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/sync_migration.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/infrastructure/repositories/trashed_local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/permission.repository.dart';
|
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/utils/semver.dart';
|
import 'package:immich_mobile/utils/semver.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@@ -34,23 +34,31 @@ class SyncStreamService {
|
|||||||
final SyncStreamRepository _syncStreamRepository;
|
final SyncStreamRepository _syncStreamRepository;
|
||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository;
|
final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository;
|
||||||
final AssetMediaRepository _assetMediaRepository;
|
final LocalFilesManagerRepository _localFilesManager;
|
||||||
final IPermissionRepository _permissionRepository;
|
final StorageRepository _storageRepository;
|
||||||
final SyncMigrationRepository _syncMigrationRepository;
|
final SyncMigrationRepository _syncMigrationRepository;
|
||||||
final ApiService _api;
|
final ApiService _api;
|
||||||
final bool Function()? _cancelChecker;
|
final bool Function()? _cancelChecker;
|
||||||
|
|
||||||
SyncStreamService({
|
SyncStreamService({
|
||||||
required this._syncApiRepository,
|
required SyncApiRepository syncApiRepository,
|
||||||
required this._syncStreamRepository,
|
required SyncStreamRepository syncStreamRepository,
|
||||||
required this._localAssetRepository,
|
required DriftLocalAssetRepository localAssetRepository,
|
||||||
required this._trashedLocalAssetRepository,
|
required DriftTrashedLocalAssetRepository trashedLocalAssetRepository,
|
||||||
required this._assetMediaRepository,
|
required LocalFilesManagerRepository localFilesManager,
|
||||||
required this._permissionRepository,
|
required StorageRepository storageRepository,
|
||||||
required this._syncMigrationRepository,
|
required SyncMigrationRepository syncMigrationRepository,
|
||||||
required this._api,
|
required ApiService api,
|
||||||
this._cancelChecker,
|
bool Function()? cancelChecker,
|
||||||
});
|
}) : _syncApiRepository = syncApiRepository,
|
||||||
|
_syncStreamRepository = syncStreamRepository,
|
||||||
|
_localAssetRepository = localAssetRepository,
|
||||||
|
_trashedLocalAssetRepository = trashedLocalAssetRepository,
|
||||||
|
_localFilesManager = localFilesManager,
|
||||||
|
_storageRepository = storageRepository,
|
||||||
|
_syncMigrationRepository = syncMigrationRepository,
|
||||||
|
_api = api,
|
||||||
|
_cancelChecker = cancelChecker;
|
||||||
|
|
||||||
bool get isCancelled => _cancelChecker?.call() ?? false;
|
bool get isCancelled => _cancelChecker?.call() ?? false;
|
||||||
|
|
||||||
@@ -492,22 +500,22 @@ class SyncStreamService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _trashLocalAssets(Map<String, List<LocalAsset>> localAssetsToTrash) async {
|
Future<void> _trashLocalAssets(Map<String, List<LocalAsset>> localAssetsToTrash) async {
|
||||||
final localIds = localAssetsToTrash.values.expand((assets) => assets).map((asset) => asset.id).toList();
|
final mediaUrls = await Future.wait(
|
||||||
_logger.info("Moving to trash ${localIds.join(", ")} assets");
|
localAssetsToTrash.values
|
||||||
final movedIds = await _assetMediaRepository.deleteAll(localIds);
|
.expand((e) => e)
|
||||||
if (movedIds.isNotEmpty) {
|
.map((localAsset) => _storageRepository.getAssetEntityForAsset(localAsset).then((e) => e?.getMediaUrl())),
|
||||||
final movedAssetsByAlbum = localAssetsToTrash.map(
|
);
|
||||||
(albumId, assets) => MapEntry(albumId, assets.where((asset) => movedIds.contains(asset.id)).toList()),
|
_logger.info("Moving to trash ${mediaUrls.join(", ")} assets");
|
||||||
)..removeWhere((_, assets) => assets.isEmpty);
|
final result = await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList());
|
||||||
|
if (result) {
|
||||||
await _trashedLocalAssetRepository.trashLocalAsset(movedAssetsByAlbum);
|
await _trashedLocalAssetRepository.trashLocalAsset(localAssetsToTrash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _applyRemoteRestoreToLocal() async {
|
Future<void> _applyRemoteRestoreToLocal() async {
|
||||||
final assetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
final assetsToRestore = await _trashedLocalAssetRepository.getToRestore();
|
||||||
if (assetsToRestore.isNotEmpty) {
|
if (assetsToRestore.isNotEmpty) {
|
||||||
final restoredIds = await _assetMediaRepository.restoreAssetsFromTrash(assetsToRestore);
|
final restoredIds = await _localFilesManager.restoreAssetsFromTrash(assetsToRestore);
|
||||||
await _trashedLocalAssetRepository.applyRestoredAssets(restoredIds);
|
await _trashedLocalAssetRepository.applyRestoredAssets(restoredIds);
|
||||||
} else {
|
} else {
|
||||||
_logger.info("No remote assets found for restoration");
|
_logger.info("No remote assets found for restoration");
|
||||||
@@ -515,7 +523,7 @@ class SyncStreamService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _syncAssetTrashStatus(List<String> remoteIds) async {
|
Future<void> _syncAssetTrashStatus(List<String> remoteIds) async {
|
||||||
if (!(await _permissionRepository.hasManageMediaPermission())) {
|
if (!(await _localFilesManager.hasManageMediaPermission())) {
|
||||||
_logger.warning("Syncing asset trash status cannot proceed because MANAGE_MEDIA permission is missing");
|
_logger.warning("Syncing asset trash status cannot proceed because MANAGE_MEDIA permission is missing");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -525,7 +533,7 @@ class SyncStreamService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _syncAssetDeletion(List<String> remoteIds) async {
|
Future<void> _syncAssetDeletion(List<String> remoteIds) async {
|
||||||
if (!(await _permissionRepository.hasManageMediaPermission())) {
|
if (!(await _localFilesManager.hasManageMediaPermission())) {
|
||||||
_logger.warning("Syncing asset deletion cannot proceed because MANAGE_MEDIA permission is missing");
|
_logger.warning("Syncing asset deletion cannot proceed because MANAGE_MEDIA permission is missing");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,11 @@ class TimelineFactory {
|
|||||||
final DriftTimelineRepository _timelineRepository;
|
final DriftTimelineRepository _timelineRepository;
|
||||||
final MetadataRepository _metadataRepository;
|
final MetadataRepository _metadataRepository;
|
||||||
|
|
||||||
const TimelineFactory({required this._timelineRepository, required this._metadataRepository});
|
const TimelineFactory({
|
||||||
|
required DriftTimelineRepository timelineRepository,
|
||||||
|
required MetadataRepository metadataRepository,
|
||||||
|
}) : _timelineRepository = timelineRepository,
|
||||||
|
_metadataRepository = metadataRepository;
|
||||||
|
|
||||||
GroupAssetsBy get groupBy {
|
GroupAssetsBy get groupBy {
|
||||||
final group = _metadataRepository.appConfig.timeline.groupAssetsBy;
|
final group = _metadataRepository.appConfig.timeline.groupAssetsBy;
|
||||||
@@ -104,7 +108,12 @@ class TimelineService {
|
|||||||
TimelineService(TimelineQuery query)
|
TimelineService(TimelineQuery query)
|
||||||
: this._(assetSource: query.assetSource, bucketSource: query.bucketSource, origin: query.origin);
|
: this._(assetSource: query.assetSource, bucketSource: query.bucketSource, origin: query.origin);
|
||||||
|
|
||||||
TimelineService._({required this._assetSource, required this._bucketSource, required this.origin}) {
|
TimelineService._({
|
||||||
|
required TimelineAssetSource assetSource,
|
||||||
|
required TimelineBucketSource bucketSource,
|
||||||
|
required this.origin,
|
||||||
|
}) : _assetSource = assetSource,
|
||||||
|
_bucketSource = bucketSource {
|
||||||
_bucketSubscription = _bucketSource().listen((buckets) {
|
_bucketSubscription = _bucketSource().listen((buckets) {
|
||||||
_mutex.run(() async {
|
_mutex.run(() async {
|
||||||
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
|
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ class UserService {
|
|||||||
final UserApiRepository _userApiRepository;
|
final UserApiRepository _userApiRepository;
|
||||||
final StoreService _storeService;
|
final StoreService _storeService;
|
||||||
|
|
||||||
UserService({required this._userApiRepository, required this._storeService});
|
UserService({required UserApiRepository userApiRepository, required StoreService storeService})
|
||||||
|
: _userApiRepository = userApiRepository,
|
||||||
|
_storeService = storeService;
|
||||||
|
|
||||||
UserDto getMyUser() {
|
UserDto getMyUser() {
|
||||||
return _storeService.get(StoreKey.currentUser);
|
return _storeService.get(StoreKey.currentUser);
|
||||||
|
|||||||
@@ -152,14 +152,6 @@ extension<T extends Object> on MetadataDomain<T> {
|
|||||||
isReverse: repo._read(.albumIsReverse),
|
isReverse: repo._read(.albumIsReverse),
|
||||||
isGrid: repo._read(.albumIsGrid),
|
isGrid: repo._read(.albumIsGrid),
|
||||||
),
|
),
|
||||||
backup: .new(
|
|
||||||
enabled: repo._read(.backupEnabled),
|
|
||||||
useCellularForVideos: repo._read(.backupUseCellularForVideos),
|
|
||||||
useCellularForPhotos: repo._read(.backupUseCellularForPhotos),
|
|
||||||
requireCharging: repo._read(.backupRequireCharging),
|
|
||||||
triggerDelay: repo._read(.backupTriggerDelay),
|
|
||||||
syncAlbums: repo._read(.backupSyncAlbums),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
case .systemConfig:
|
case .systemConfig:
|
||||||
repo._systemConfig = .new(
|
repo._systemConfig = .new(
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ 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/metadata.repository.dart';
|
import 'package:immich_mobile/providers/app_settings.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/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/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/services/app_settings.service.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';
|
||||||
import 'package:immich_mobile/widgets/common/search_field.dart';
|
import 'package:immich_mobile/widgets/common/search_field.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@@ -43,7 +43,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
|||||||
_searchController = TextEditingController();
|
_searchController = TextEditingController();
|
||||||
_searchFocusNode = FocusNode();
|
_searchFocusNode = FocusNode();
|
||||||
|
|
||||||
_enableSyncUploadAlbum.value = ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
_enableSyncUploadAlbum.value = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums);
|
||||||
ref.read(backupAlbumProvider.notifier).getAll();
|
ref.read(backupAlbumProvider.notifier).getAll();
|
||||||
|
|
||||||
_initialTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
|
_initialTotalAssetCount = ref.read(driftBackupProvider.select((p) => p.totalCount));
|
||||||
@@ -55,7 +55,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final enableSyncUploadAlbum = ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
final enableSyncUploadAlbum = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums);
|
||||||
final selectedAlbums = ref
|
final selectedAlbums = ref
|
||||||
.read(backupAlbumProvider)
|
.read(backupAlbumProvider)
|
||||||
.where((a) => a.backupSelection == BackupSelection.selected)
|
.where((a) => a.backupSelection == BackupSelection.selected)
|
||||||
@@ -103,7 +103,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isBackupEnabled = MetadataRepository.instance.appConfig.backup.enabled;
|
final isBackupEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
||||||
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;
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ import 'dart:async';
|
|||||||
import 'package:auto_route/auto_route.dart';
|
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/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/metadata.repository.dart';
|
import 'package:immich_mobile/providers/app_settings.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/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/app_settings.service.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';
|
||||||
|
|
||||||
@@ -19,20 +21,18 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
bool hasPopped = false;
|
bool hasPopped = false;
|
||||||
final previousBackup = ref.read(metadataProvider).appConfig.backup;
|
final previousWifiReqForVideos = Store.tryGet(StoreKey.useWifiForUploadVideos) ?? false;
|
||||||
final previousCellularForVideos = previousBackup.useCellularForVideos;
|
final previousWifiReqForPhotos = Store.tryGet(StoreKey.useWifiForUploadPhotos) ?? false;
|
||||||
final previousCellularForPhotos = previousBackup.useCellularForPhotos;
|
|
||||||
return PopScope(
|
return PopScope(
|
||||||
onPopInvokedWithResult: (didPop, result) async {
|
onPopInvokedWithResult: (didPop, result) async {
|
||||||
// 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(metadataProvider).appConfig.backup;
|
final currentWifiReqForVideos = Store.tryGet(StoreKey.useWifiForUploadVideos) ?? false;
|
||||||
final currentCellularForVideos = currentBackup.useCellularForVideos;
|
final currentWifiReqForPhotos = Store.tryGet(StoreKey.useWifiForUploadPhotos) ?? false;
|
||||||
final currentCellularForPhotos = currentBackup.useCellularForPhotos;
|
|
||||||
|
|
||||||
if (currentCellularForVideos == previousCellularForVideos &&
|
if (currentWifiReqForVideos == previousWifiReqForVideos &&
|
||||||
currentCellularForPhotos == previousCellularForPhotos) {
|
currentWifiReqForPhotos == previousWifiReqForPhotos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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 = MetadataRepository.instance.appConfig.backup.enabled;
|
final isBackupEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
||||||
if (!isBackupEnabled) {
|
if (!isBackupEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ 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/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 +340,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||||||
await backgroundManager.hashAssets();
|
await backgroundManager.hashAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MetadataRepository.instance.appConfig.backup.syncAlbums) {
|
if (Store.get(StoreKey.syncAlbums, false)) {
|
||||||
await backgroundManager.syncLinkedAlbum();
|
await backgroundManager.syncLinkedAlbum();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -370,7 +369,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
||||||
final isEnableBackup = MetadataRepository.instance.appConfig.backup.enabled;
|
final isEnableBackup = Store.get(StoreKey.enableBackup, false);
|
||||||
|
|
||||||
if (isEnableBackup) {
|
if (isEnableBackup) {
|
||||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||||
|
|||||||
-19
@@ -654,25 +654,6 @@ class NativeSyncApi {
|
|||||||
return (pigeonVar_replyValue! as Map<Object?, Object?>).cast<String, List<PlatformAsset>>();
|
return (pigeonVar_replyValue! as Map<Object?, Object?>).cast<String, List<PlatformAsset>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> restoreFromTrashById(String mediaId, int type) async {
|
|
||||||
final pigeonVar_channelName =
|
|
||||||
'dev.flutter.pigeon.immich_mobile.NativeSyncApi.restoreFromTrashById$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
pigeonVar_channelName,
|
|
||||||
pigeonChannelCodec,
|
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
|
||||||
);
|
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[mediaId, type]);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
|
||||||
pigeonVar_replyList,
|
|
||||||
pigeonVar_channelName,
|
|
||||||
isNullValid: false,
|
|
||||||
);
|
|
||||||
return pigeonVar_replyValue! as bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<CloudIdResult>> getCloudIdForAssetIds(List<String> assetIds) async {
|
Future<List<CloudIdResult>> getCloudIdForAssetIds(List<String> assetIds) async {
|
||||||
final pigeonVar_channelName =
|
final pigeonVar_channelName =
|
||||||
'dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds$pigeonVar_messageChannelSuffix';
|
'dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds$pigeonVar_messageChannelSuffix';
|
||||||
|
|||||||
Generated
-19
@@ -309,23 +309,4 @@ class NetworkApi {
|
|||||||
|
|
||||||
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
|
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getAppGroupId() async {
|
|
||||||
final pigeonVar_channelName =
|
|
||||||
'dev.flutter.pigeon.immich_mobile.NetworkApi.getAppGroupId$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
pigeonVar_channelName,
|
|
||||||
pigeonChannelCodec,
|
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
|
||||||
);
|
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
|
||||||
pigeonVar_replyList,
|
|
||||||
pigeonVar_channelName,
|
|
||||||
isNullValid: false,
|
|
||||||
);
|
|
||||||
return pigeonVar_replyValue! as String;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-119
@@ -1,119 +0,0 @@
|
|||||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
|
||||||
// See also: https://pub.dev/packages/pigeon
|
|
||||||
// ignore_for_file: unused_import, unused_shown_name
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:typed_data' show Float64List, Int32List, Int64List;
|
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
|
|
||||||
|
|
||||||
Object? _extractReplyValueOrThrow(List<Object?>? replyList, String channelName, {required bool isNullValid}) {
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel: "$channelName".',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(code: replyList[0]! as String, message: replyList[1] as String?, details: replyList[2]);
|
|
||||||
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'null-error',
|
|
||||||
message: 'Host platform returned null value for non-null return value.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return replyList.firstOrNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
|
||||||
const _PigeonCodec();
|
|
||||||
@override
|
|
||||||
void writeValue(WriteBuffer buffer, Object? value) {
|
|
||||||
if (value is int) {
|
|
||||||
buffer.putUint8(4);
|
|
||||||
buffer.putInt64(value);
|
|
||||||
} else {
|
|
||||||
super.writeValue(buffer, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
|
||||||
switch (type) {
|
|
||||||
default:
|
|
||||||
return super.readValueOfType(type, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PermissionApi {
|
|
||||||
/// Constructor for [PermissionApi]. The [binaryMessenger] named argument is
|
|
||||||
/// available for dependency injection. If it is left null, the default
|
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
|
||||||
PermissionApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
|
||||||
: pigeonVar_binaryMessenger = binaryMessenger,
|
|
||||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
|
||||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
|
||||||
|
|
||||||
final String pigeonVar_messageChannelSuffix;
|
|
||||||
|
|
||||||
Future<bool> hasManageMediaPermission() async {
|
|
||||||
final pigeonVar_channelName =
|
|
||||||
'dev.flutter.pigeon.immich_mobile.PermissionApi.hasManageMediaPermission$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
pigeonVar_channelName,
|
|
||||||
pigeonChannelCodec,
|
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
|
||||||
);
|
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
|
||||||
pigeonVar_replyList,
|
|
||||||
pigeonVar_channelName,
|
|
||||||
isNullValid: false,
|
|
||||||
);
|
|
||||||
return pigeonVar_replyValue! as bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> requestManageMediaPermission() async {
|
|
||||||
final pigeonVar_channelName =
|
|
||||||
'dev.flutter.pigeon.immich_mobile.PermissionApi.requestManageMediaPermission$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
pigeonVar_channelName,
|
|
||||||
pigeonChannelCodec,
|
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
|
||||||
);
|
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
|
||||||
pigeonVar_replyList,
|
|
||||||
pigeonVar_channelName,
|
|
||||||
isNullValid: false,
|
|
||||||
);
|
|
||||||
return pigeonVar_replyValue! as bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> manageMediaPermission() async {
|
|
||||||
final pigeonVar_channelName =
|
|
||||||
'dev.flutter.pigeon.immich_mobile.PermissionApi.manageMediaPermission$pigeonVar_messageChannelSuffix';
|
|
||||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
pigeonVar_channelName,
|
|
||||||
pigeonChannelCodec,
|
|
||||||
binaryMessenger: pigeonVar_binaryMessenger,
|
|
||||||
);
|
|
||||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
|
||||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
|
||||||
|
|
||||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
|
||||||
pigeonVar_replyList,
|
|
||||||
pigeonVar_channelName,
|
|
||||||
isNullValid: false,
|
|
||||||
);
|
|
||||||
return pigeonVar_replyValue! as bool;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +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/app_settings.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/metadata.provider.dart';
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
|
|
||||||
class BackupToggleButton extends ConsumerStatefulWidget {
|
class BackupToggleButton extends ConsumerStatefulWidget {
|
||||||
final VoidCallback onStart;
|
final VoidCallback onStart;
|
||||||
@@ -31,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(metadataProvider).appConfig.backup.enabled;
|
_isEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -41,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(metadataProvider).write(MetadataKey.backupEnabled, value);
|
await ref.read(appSettingsServiceProvider).setSetting(AppSettingsEnum.enableBackup, value);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isEnabled = value;
|
_isEnabled = value;
|
||||||
|
|||||||
@@ -296,12 +296,16 @@ class _ThumbnailRenderBox extends RenderBox {
|
|||||||
bool isRepaintBoundary = true;
|
bool isRepaintBoundary = true;
|
||||||
|
|
||||||
_ThumbnailRenderBox({
|
_ThumbnailRenderBox({
|
||||||
required this._image,
|
required ui.Image? image,
|
||||||
required this._previousImage,
|
required ui.Image? previousImage,
|
||||||
required this._fadeValue,
|
required double fadeValue,
|
||||||
required this._fit,
|
required BoxFit fit,
|
||||||
required this._placeholderGradient,
|
required Gradient placeholderGradient,
|
||||||
});
|
}) : _image = image,
|
||||||
|
_previousImage = previousImage,
|
||||||
|
_fadeValue = fadeValue,
|
||||||
|
_fit = fit,
|
||||||
|
_placeholderGradient = placeholderGradient;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void paint(PaintingContext context, Offset offset) {
|
void paint(PaintingContext context, Offset offset) {
|
||||||
|
|||||||
@@ -62,11 +62,14 @@ class RenderFixedRow extends RenderBox
|
|||||||
RenderBoxContainerDefaultsMixin<RenderBox, _RowParentData> {
|
RenderBoxContainerDefaultsMixin<RenderBox, _RowParentData> {
|
||||||
RenderFixedRow({
|
RenderFixedRow({
|
||||||
List<RenderBox>? children,
|
List<RenderBox>? children,
|
||||||
required this._height,
|
required double height,
|
||||||
required this._widths,
|
required List<double> widths,
|
||||||
required this._spacing,
|
required double spacing,
|
||||||
required this._textDirection,
|
required TextDirection textDirection,
|
||||||
}) {
|
}) : _height = height,
|
||||||
|
_widths = widths,
|
||||||
|
_spacing = spacing,
|
||||||
|
_textDirection = textDirection {
|
||||||
addAll(children);
|
addAll(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -578,7 +578,9 @@ class _SlideFadeTransition extends StatelessWidget {
|
|||||||
final Animation<double> _animation;
|
final Animation<double> _animation;
|
||||||
final Widget _child;
|
final Widget _child;
|
||||||
|
|
||||||
const _SlideFadeTransition({required this._animation, required this._child});
|
const _SlideFadeTransition({required Animation<double> animation, required Widget child})
|
||||||
|
: _animation = animation,
|
||||||
|
_child = child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> {
|
|||||||
final grid = CustomScrollView(
|
final grid = CustomScrollView(
|
||||||
primary: true,
|
primary: true,
|
||||||
physics: _scrollPhysics,
|
physics: _scrollPhysics,
|
||||||
scrollCacheExtent: .pixels(maxHeight * 2),
|
cacheExtent: maxHeight * 2,
|
||||||
slivers: [
|
slivers: [
|
||||||
if (isSelectionMode) const SelectionSliverAppBar() else if (widget.appBar != null) widget.appBar!,
|
if (isSelectionMode) const SelectionSliverAppBar() else if (widget.appBar != null) widget.appBar!,
|
||||||
if (widget.topSliverWidget != null) widget.topSliverWidget!,
|
if (widget.topSliverWidget != null) widget.topSliverWidget!,
|
||||||
@@ -503,7 +503,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> {
|
|||||||
class _SliverSegmentedList extends SliverMultiBoxAdaptorWidget {
|
class _SliverSegmentedList extends SliverMultiBoxAdaptorWidget {
|
||||||
final List<Segment> _segments;
|
final List<Segment> _segments;
|
||||||
|
|
||||||
const _SliverSegmentedList({required this._segments, required super.delegate});
|
const _SliverSegmentedList({required List<Segment> segments, required super.delegate}) : _segments = segments;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_RenderSliverTimelineBoxAdaptor createRenderObject(BuildContext context) =>
|
_RenderSliverTimelineBoxAdaptor createRenderObject(BuildContext context) =>
|
||||||
@@ -527,7 +527,8 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor {
|
|||||||
markNeedsLayout();
|
markNeedsLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
_RenderSliverTimelineBoxAdaptor({required super.childManager, required this._segments});
|
_RenderSliverTimelineBoxAdaptor({required super.childManager, required List<Segment> segments})
|
||||||
|
: _segments = segments;
|
||||||
|
|
||||||
int getMinChildIndexForScrollOffset(double offset) =>
|
int getMinChildIndexForScrollOffset(double offset) =>
|
||||||
_segments.findByOffset(offset)?.getMinChildIndexForScrollOffset(offset) ?? 0;
|
_segments.findByOffset(offset)?.getMinChildIndexForScrollOffset(offset) ?? 0;
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import 'package:immich_mobile/domain/models/store.model.dart';
|
|||||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
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/providers/app_settings.provider.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';
|
||||||
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/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';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
enum AppLifeCycleEnum { active, inactive, paused, resumed, detached, hidden }
|
enum AppLifeCycleEnum { active, inactive, paused, resumed, detached, hidden }
|
||||||
@@ -107,7 +108,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(metadataProvider).appConfig.backup.syncAlbums;
|
final isAlbumLinkedSyncEnable = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bool syncSuccess = false;
|
bool syncSuccess = false;
|
||||||
@@ -137,7 +138,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resumeBackup() async {
|
Future<void> _resumeBackup() async {
|
||||||
final isEnableBackup = _ref.read(metadataProvider).appConfig.backup.enabled;
|
final isEnableBackup = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
||||||
|
|
||||||
if (isEnableBackup) {
|
if (isEnableBackup) {
|
||||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ import 'package:immich_mobile/domain/services/background_worker.service.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/platform/connectivity_api.g.dart';
|
import 'package:immich_mobile/platform/connectivity_api.g.dart';
|
||||||
import 'package:immich_mobile/platform/local_image_api.g.dart';
|
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||||
|
import 'package:immich_mobile/platform/local_image_api.g.dart';
|
||||||
import 'package:immich_mobile/platform/network_api.g.dart';
|
import 'package:immich_mobile/platform/network_api.g.dart';
|
||||||
import 'package:immich_mobile/platform/permission_api.g.dart';
|
|
||||||
import 'package:immich_mobile/platform/remote_image_api.g.dart';
|
import 'package:immich_mobile/platform/remote_image_api.g.dart';
|
||||||
|
|
||||||
final backgroundWorkerFgServiceProvider = Provider((_) => BackgroundWorkerFgService(BackgroundWorkerFgHostApi()));
|
final backgroundWorkerFgServiceProvider = Provider((_) => BackgroundWorkerFgService(BackgroundWorkerFgHostApi()));
|
||||||
@@ -17,8 +16,6 @@ final backgroundWorkerLockServiceProvider = Provider<BackgroundWorkerLockService
|
|||||||
|
|
||||||
final nativeSyncApiProvider = Provider<NativeSyncApi>((_) => NativeSyncApi());
|
final nativeSyncApiProvider = Provider<NativeSyncApi>((_) => NativeSyncApi());
|
||||||
|
|
||||||
final permissionApiProvider = Provider<PermissionApi>((_) => PermissionApi());
|
|
||||||
|
|
||||||
final connectivityApiProvider = Provider<ConnectivityApi>((_) => ConnectivityApi());
|
final connectivityApiProvider = Provider<ConnectivityApi>((_) => ConnectivityApi());
|
||||||
|
|
||||||
final localImageApi = LocalImageApi();
|
final localImageApi = LocalImageApi();
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
|||||||
import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/cancel.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/platform.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/permission.repository.dart';
|
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
||||||
|
|
||||||
final syncMigrationRepositoryProvider = Provider((ref) => SyncMigrationRepository(ref.watch(driftProvider)));
|
final syncMigrationRepositoryProvider = Provider((ref) => SyncMigrationRepository(ref.watch(driftProvider)));
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ final syncStreamServiceProvider = Provider(
|
|||||||
syncStreamRepository: ref.watch(syncStreamRepositoryProvider),
|
syncStreamRepository: ref.watch(syncStreamRepositoryProvider),
|
||||||
localAssetRepository: ref.watch(localAssetRepository),
|
localAssetRepository: ref.watch(localAssetRepository),
|
||||||
trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository),
|
trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository),
|
||||||
assetMediaRepository: ref.watch(assetMediaRepositoryProvider),
|
localFilesManager: ref.watch(localFilesManagerRepositoryProvider),
|
||||||
permissionRepository: ref.watch(permissionRepositoryProvider),
|
storageRepository: ref.watch(storageRepositoryProvider),
|
||||||
syncMigrationRepository: ref.watch(syncMigrationRepositoryProvider),
|
syncMigrationRepository: ref.watch(syncMigrationRepositoryProvider),
|
||||||
api: ref.watch(apiServiceProvider),
|
api: ref.watch(apiServiceProvider),
|
||||||
cancelChecker: ref.watch(cancellationProvider),
|
cancelChecker: ref.watch(cancellationProvider),
|
||||||
@@ -39,8 +39,8 @@ final localSyncServiceProvider = Provider(
|
|||||||
localAlbumRepository: ref.watch(localAlbumRepository),
|
localAlbumRepository: ref.watch(localAlbumRepository),
|
||||||
localAssetRepository: ref.watch(localAssetRepository),
|
localAssetRepository: ref.watch(localAssetRepository),
|
||||||
trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository),
|
trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository),
|
||||||
assetMediaRepository: ref.watch(assetMediaRepositoryProvider),
|
localFilesManager: ref.watch(localFilesManagerRepositoryProvider),
|
||||||
permissionRepository: ref.watch(permissionRepositoryProvider),
|
storageRepository: ref.watch(storageRepositoryProvider),
|
||||||
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
nativeSyncApi: ref.watch(nativeSyncApiProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ 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/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 +192,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isSyncAlbumEnabled = _ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
final isSyncAlbumEnabled = Store.get(StoreKey.syncAlbums, false);
|
||||||
try {
|
try {
|
||||||
unawaited(
|
unawaited(
|
||||||
_ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) {
|
_ref.read(backgroundSyncProvider).syncWebsocketBatchV1(_batchedAssetUploadReady.toList()).then((_) {
|
||||||
@@ -214,7 +213,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isSyncAlbumEnabled = _ref.read(metadataProvider).appConfig.backup.syncAlbums;
|
final isSyncAlbumEnabled = Store.get(StoreKey.syncAlbums, false);
|
||||||
try {
|
try {
|
||||||
unawaited(
|
unawaited(
|
||||||
_ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) {
|
_ref.read(backgroundSyncProvider).syncWebsocketBatchV2(_batchedAssetUploadReady.toList()).then((_) {
|
||||||
|
|||||||
@@ -8,24 +8,19 @@ 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/platform_extensions.dart';
|
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/response_extensions.dart';
|
import 'package:immich_mobile/extensions/response_extensions.dart';
|
||||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
|
||||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart';
|
import 'package:photo_manager/photo_manager.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
final assetMediaRepositoryProvider = Provider(
|
final assetMediaRepositoryProvider = Provider((ref) => AssetMediaRepository(ref.watch(assetApiRepositoryProvider)));
|
||||||
(ref) => AssetMediaRepository(ref.watch(assetApiRepositoryProvider), ref.watch(nativeSyncApiProvider)),
|
|
||||||
);
|
|
||||||
|
|
||||||
class AssetMediaRepository {
|
class AssetMediaRepository {
|
||||||
final AssetApiRepository _assetApiRepository;
|
final AssetApiRepository _assetApiRepository;
|
||||||
final NativeSyncApi _nativeSyncApi;
|
|
||||||
static final Logger _log = Logger("AssetMediaRepository");
|
static final Logger _log = Logger("AssetMediaRepository");
|
||||||
|
|
||||||
const AssetMediaRepository(this._assetApiRepository, this._nativeSyncApi);
|
const AssetMediaRepository(this._assetApiRepository);
|
||||||
|
|
||||||
Future<bool> _androidSupportsTrash() async {
|
Future<bool> _androidSupportsTrash() async {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
@@ -50,27 +45,6 @@ class AssetMediaRepository {
|
|||||||
return PhotoManager.editor.deleteWithIds(ids);
|
return PhotoManager.editor.deleteWithIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _restoreFromTrashById(String mediaId, int type) async {
|
|
||||||
try {
|
|
||||||
return await _nativeSyncApi.restoreFromTrashById(mediaId, type);
|
|
||||||
} catch (e, s) {
|
|
||||||
_log.warning('Error restore file from trash by Id', e, s);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<String>> restoreAssetsFromTrash(Iterable<LocalAsset> assets) async {
|
|
||||||
final restoredIds = <String>[];
|
|
||||||
for (final asset in assets) {
|
|
||||||
_log.info("Restoring from trash, localId: ${asset.id}, checksum: ${asset.checksum}");
|
|
||||||
final result = await _restoreFromTrashById(asset.id, asset.type.index);
|
|
||||||
if (result) {
|
|
||||||
restoredIds.add(asset.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return restoredIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<AssetEntity?> get(String id) async {
|
Future<AssetEntity?> get(String id) async {
|
||||||
final entity = await AssetEntity.fromId(id);
|
final entity = await AssetEntity.fromId(id);
|
||||||
return entity;
|
return entity;
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/services/local_files_manager.service.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
final localFilesManagerRepositoryProvider = Provider(
|
||||||
|
(ref) => LocalFilesManagerRepository(ref.watch(localFileManagerServiceProvider)),
|
||||||
|
);
|
||||||
|
|
||||||
|
class LocalFilesManagerRepository {
|
||||||
|
LocalFilesManagerRepository(this._service);
|
||||||
|
|
||||||
|
final Logger _logger = Logger('LocalFilesManagerRepo');
|
||||||
|
final LocalFilesManagerService _service;
|
||||||
|
|
||||||
|
Future<bool> moveToTrash(List<String> mediaUrls) async {
|
||||||
|
return await _service.moveToTrash(mediaUrls);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> restoreFromTrash(String fileName, int type) async {
|
||||||
|
return await _service.restoreFromTrash(fileName, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> requestManageMediaPermission() async {
|
||||||
|
return await _service.requestManageMediaPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> hasManageMediaPermission() async {
|
||||||
|
return await _service.hasManageMediaPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> manageMediaPermission() async {
|
||||||
|
return await _service.manageMediaPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<String>> restoreAssetsFromTrash(Iterable<LocalAsset> assets) async {
|
||||||
|
final restoredIds = <String>[];
|
||||||
|
for (final asset in assets) {
|
||||||
|
_logger.info("Restoring from trash, localId: ${asset.id}, remoteId: ${asset.checksum}");
|
||||||
|
try {
|
||||||
|
final result = await _service.restoreFromTrashById(asset.id, asset.type.index);
|
||||||
|
if (result) {
|
||||||
|
restoredIds.add(asset.id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
_logger.warning("Restoring failure: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return restoredIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,12 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/platform/permission_api.g.dart';
|
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
final permissionRepositoryProvider = Provider((ref) {
|
final permissionRepositoryProvider = Provider((_) {
|
||||||
return PermissionRepository(ref.watch(permissionApiProvider));
|
return const PermissionRepository();
|
||||||
});
|
});
|
||||||
|
|
||||||
class PermissionRepository implements IPermissionRepository {
|
class PermissionRepository implements IPermissionRepository {
|
||||||
final PermissionApi _permissionApi;
|
const PermissionRepository();
|
||||||
|
|
||||||
const PermissionRepository(this._permissionApi);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> hasLocationWhenInUsePermission() {
|
Future<bool> hasLocationWhenInUsePermission() {
|
||||||
@@ -38,21 +34,6 @@ class PermissionRepository implements IPermissionRepository {
|
|||||||
Future<bool> openSettings() {
|
Future<bool> openSettings() {
|
||||||
return openAppSettings();
|
return openAppSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> hasManageMediaPermission() {
|
|
||||||
return _permissionApi.hasManageMediaPermission();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> requestManageMediaPermission() {
|
|
||||||
return _permissionApi.requestManageMediaPermission();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> manageMediaPermission() {
|
|
||||||
return _permissionApi.manageMediaPermission();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract interface class IPermissionRepository {
|
abstract interface class IPermissionRepository {
|
||||||
@@ -61,7 +42,4 @@ abstract interface class IPermissionRepository {
|
|||||||
Future<bool> hasLocationAlwaysPermission();
|
Future<bool> hasLocationAlwaysPermission();
|
||||||
Future<bool> requestLocationAlwaysPermission();
|
Future<bool> requestLocationAlwaysPermission();
|
||||||
Future<bool> openSettings();
|
Future<bool> openSettings();
|
||||||
Future<bool> hasManageMediaPermission();
|
|
||||||
Future<bool> requestManageMediaPermission();
|
|
||||||
Future<bool> manageMediaPermission();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:home_widget/home_widget.dart';
|
import 'package:home_widget/home_widget.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
|
||||||
|
|
||||||
final widgetRepositoryProvider = Provider((_) => const WidgetRepository());
|
final widgetRepositoryProvider = Provider((_) => const WidgetRepository());
|
||||||
|
|
||||||
@@ -15,7 +14,7 @@ class WidgetRepository {
|
|||||||
await HomeWidget.updateWidget(iOSName: iosName, qualifiedAndroidName: androidName);
|
await HomeWidget.updateWidget(iOSName: iosName, qualifiedAndroidName: androidName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setAppGroupId() async {
|
Future<void> setAppGroupId(String appGroupId) async {
|
||||||
await HomeWidget.setAppGroupId(await networkApi.getAppGroupId());
|
await HomeWidget.setAppGroupId(appGroupId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,13 @@ enum AppSettingsEnum<T> {
|
|||||||
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, null, false),
|
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, null, false),
|
||||||
manageLocalMediaAndroid<bool>(StoreKey.manageLocalMediaAndroid, null, false),
|
manageLocalMediaAndroid<bool>(StoreKey.manageLocalMediaAndroid, null, false),
|
||||||
enableHapticFeedback<bool>(StoreKey.enableHapticFeedback, null, true),
|
enableHapticFeedback<bool>(StoreKey.enableHapticFeedback, null, true),
|
||||||
readonlyModeEnabled<bool>(StoreKey.readonlyModeEnabled, "readonlyModeEnabled", false);
|
syncAlbums<bool>(StoreKey.syncAlbums, null, false),
|
||||||
|
enableBackup<bool>(StoreKey.enableBackup, null, false),
|
||||||
|
useCellularForUploadVideos<bool>(StoreKey.useWifiForUploadVideos, null, false),
|
||||||
|
useCellularForUploadPhotos<bool>(StoreKey.useWifiForUploadPhotos, null, false),
|
||||||
|
readonlyModeEnabled<bool>(StoreKey.readonlyModeEnabled, "readonlyModeEnabled", false),
|
||||||
|
backupRequireCharging<bool>(StoreKey.backupRequireCharging, null, false),
|
||||||
|
backupTriggerDelay<int>(StoreKey.backupTriggerDelay, null, 30);
|
||||||
|
|
||||||
const AppSettingsEnum(this.storeKey, this.hiveKey, this.defaultValue);
|
const AppSettingsEnum(this.storeKey, this.hiveKey, this.defaultValue);
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
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/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/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';
|
||||||
import 'package:immich_mobile/providers/api.provider.dart';
|
import 'package:immich_mobile/providers/api.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/auth.repository.dart';
|
import 'package:immich_mobile/repositories/auth.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/auth_api.repository.dart';
|
import 'package:immich_mobile/repositories/auth_api.repository.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:immich_mobile/services/network.service.dart';
|
import 'package:immich_mobile/services/network.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
@@ -25,6 +25,7 @@ final authServiceProvider = Provider(
|
|||||||
ref.watch(apiServiceProvider),
|
ref.watch(apiServiceProvider),
|
||||||
ref.watch(networkServiceProvider),
|
ref.watch(networkServiceProvider),
|
||||||
ref.watch(backgroundSyncProvider),
|
ref.watch(backgroundSyncProvider),
|
||||||
|
ref.watch(appSettingsServiceProvider),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ class AuthService {
|
|||||||
final ApiService _apiService;
|
final ApiService _apiService;
|
||||||
final NetworkService _networkService;
|
final NetworkService _networkService;
|
||||||
final BackgroundSyncManager _backgroundSyncManager;
|
final BackgroundSyncManager _backgroundSyncManager;
|
||||||
|
final AppSettingsService _appSettingsService;
|
||||||
final _log = Logger("AuthService");
|
final _log = Logger("AuthService");
|
||||||
|
|
||||||
AuthService(
|
AuthService(
|
||||||
@@ -42,6 +44,7 @@ class AuthService {
|
|||||||
this._apiService,
|
this._apiService,
|
||||||
this._networkService,
|
this._networkService,
|
||||||
this._backgroundSyncManager,
|
this._backgroundSyncManager,
|
||||||
|
this._appSettingsService,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Validates the provided server URL by resolving and setting the endpoint.
|
/// Validates the provided server URL by resolving and setting the endpoint.
|
||||||
@@ -100,7 +103,7 @@ class AuthService {
|
|||||||
_log.severe("Error clearing local data", error, stackTrace);
|
_log.severe("Error clearing local data", error, stackTrace);
|
||||||
});
|
});
|
||||||
|
|
||||||
await MetadataRepository.instance.write(MetadataKey.backupEnabled, false);
|
await _appSettingsService.setSetting(AppSettingsEnum.enableBackup, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ 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/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/app_settings.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/storage.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/upload.repository.dart';
|
import 'package:immich_mobile/repositories/upload.repository.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.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';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
@@ -30,6 +31,7 @@ final backgroundUploadServiceProvider = Provider((ref) {
|
|||||||
ref.watch(storageRepositoryProvider),
|
ref.watch(storageRepositoryProvider),
|
||||||
ref.watch(localAssetRepository),
|
ref.watch(localAssetRepository),
|
||||||
ref.watch(backupRepositoryProvider),
|
ref.watch(backupRepositoryProvider),
|
||||||
|
ref.watch(appSettingsServiceProvider),
|
||||||
ref.watch(assetMediaRepositoryProvider),
|
ref.watch(assetMediaRepositoryProvider),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -103,6 +105,7 @@ class BackgroundUploadService {
|
|||||||
this._storageRepository,
|
this._storageRepository,
|
||||||
this._localAssetRepository,
|
this._localAssetRepository,
|
||||||
this._backupRepository,
|
this._backupRepository,
|
||||||
|
this._appSettingsService,
|
||||||
this._assetMediaRepository,
|
this._assetMediaRepository,
|
||||||
) {
|
) {
|
||||||
_uploadRepository.onUploadStatus = _onUploadCallback;
|
_uploadRepository.onUploadStatus = _onUploadCallback;
|
||||||
@@ -113,6 +116,7 @@ class BackgroundUploadService {
|
|||||||
final StorageRepository _storageRepository;
|
final StorageRepository _storageRepository;
|
||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
final DriftBackupRepository _backupRepository;
|
final DriftBackupRepository _backupRepository;
|
||||||
|
final AppSettingsService _appSettingsService;
|
||||||
final AssetMediaRepository _assetMediaRepository;
|
final AssetMediaRepository _assetMediaRepository;
|
||||||
final Logger _logger = Logger('BackgroundUploadService');
|
final Logger _logger = Logger('BackgroundUploadService');
|
||||||
|
|
||||||
@@ -359,14 +363,15 @@ class BackgroundUploadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _shouldRequireWiFi(LocalAsset asset) {
|
bool _shouldRequireWiFi(LocalAsset asset) {
|
||||||
final backup = MetadataRepository.instance.appConfig.backup;
|
bool requiresWiFi = true;
|
||||||
if (asset.isVideo && backup.useCellularForVideos) {
|
|
||||||
return false;
|
if (asset.isVideo && _appSettingsService.getSetting(AppSettingsEnum.useCellularForUploadVideos)) {
|
||||||
|
requiresWiFi = false;
|
||||||
|
} else if (!asset.isVideo && _appSettingsService.getSetting(AppSettingsEnum.useCellularForUploadPhotos)) {
|
||||||
|
requiresWiFi = false;
|
||||||
}
|
}
|
||||||
if (!asset.isVideo && backup.useCellularForPhotos) {
|
|
||||||
return false;
|
return requiresWiFi;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<UploadTask> buildUploadTask(
|
Future<UploadTask> buildUploadTask(
|
||||||
|
|||||||
@@ -7,17 +7,18 @@ import 'package:immich_mobile/domain/models/asset/asset_metadata.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/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/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/network_capability_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/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/app_settings.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/storage.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||||
import 'package:immich_mobile/repositories/upload.repository.dart';
|
import 'package:immich_mobile/repositories/upload.repository.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:photo_manager/photo_manager.dart' show PMProgressHandler;
|
import 'package:photo_manager/photo_manager.dart' show PMProgressHandler;
|
||||||
@@ -38,6 +39,7 @@ final foregroundUploadServiceProvider = Provider((ref) {
|
|||||||
ref.watch(storageRepositoryProvider),
|
ref.watch(storageRepositoryProvider),
|
||||||
ref.watch(backupRepositoryProvider),
|
ref.watch(backupRepositoryProvider),
|
||||||
ref.watch(connectivityApiProvider),
|
ref.watch(connectivityApiProvider),
|
||||||
|
ref.watch(appSettingsServiceProvider),
|
||||||
ref.watch(assetMediaRepositoryProvider),
|
ref.watch(assetMediaRepositoryProvider),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -53,6 +55,7 @@ class ForegroundUploadService {
|
|||||||
this._storageRepository,
|
this._storageRepository,
|
||||||
this._backupRepository,
|
this._backupRepository,
|
||||||
this._connectivityApi,
|
this._connectivityApi,
|
||||||
|
this._appSettingsService,
|
||||||
this._assetMediaRepository,
|
this._assetMediaRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -60,6 +63,7 @@ class ForegroundUploadService {
|
|||||||
final StorageRepository _storageRepository;
|
final StorageRepository _storageRepository;
|
||||||
final DriftBackupRepository _backupRepository;
|
final DriftBackupRepository _backupRepository;
|
||||||
final ConnectivityApi _connectivityApi;
|
final ConnectivityApi _connectivityApi;
|
||||||
|
final AppSettingsService _appSettingsService;
|
||||||
final AssetMediaRepository _assetMediaRepository;
|
final AssetMediaRepository _assetMediaRepository;
|
||||||
final Logger _logger = Logger('ForegroundUploadService');
|
final Logger _logger = Logger('ForegroundUploadService');
|
||||||
|
|
||||||
@@ -451,13 +455,14 @@ class ForegroundUploadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _shouldRequireWiFi(LocalAsset asset) {
|
bool _shouldRequireWiFi(LocalAsset asset) {
|
||||||
final backup = MetadataRepository.instance.appConfig.backup;
|
bool requiresWiFi = true;
|
||||||
if (asset.isVideo && backup.useCellularForVideos) {
|
|
||||||
return false;
|
if (asset.isVideo && _appSettingsService.getSetting(AppSettingsEnum.useCellularForUploadVideos)) {
|
||||||
|
requiresWiFi = false;
|
||||||
|
} else if (!asset.isVideo && _appSettingsService.getSetting(AppSettingsEnum.useCellularForUploadPhotos)) {
|
||||||
|
requiresWiFi = false;
|
||||||
}
|
}
|
||||||
if (!asset.isVideo && backup.useCellularForPhotos) {
|
|
||||||
return false;
|
return requiresWiFi;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
final localFileManagerServiceProvider = Provider<LocalFilesManagerService>((ref) => const LocalFilesManagerService());
|
||||||
|
|
||||||
|
class LocalFilesManagerService {
|
||||||
|
const LocalFilesManagerService();
|
||||||
|
|
||||||
|
static final Logger _logger = Logger('LocalFilesManager');
|
||||||
|
static const MethodChannel _channel = MethodChannel('file_trash');
|
||||||
|
|
||||||
|
Future<bool> moveToTrash(List<String> mediaUrls) async {
|
||||||
|
try {
|
||||||
|
return await _channel.invokeMethod('moveToTrash', {'mediaUrls': mediaUrls});
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error moving file to trash', e, s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> restoreFromTrash(String fileName, int type) async {
|
||||||
|
try {
|
||||||
|
return await _channel.invokeMethod('restoreFromTrash', {'fileName': fileName, 'type': type});
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error restore file from trash', e, s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> restoreFromTrashById(String mediaId, int type) async {
|
||||||
|
try {
|
||||||
|
return await _channel.invokeMethod('restoreFromTrash', {'mediaId': mediaId, 'type': type});
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error restore file from trash by Id', e, s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> requestManageMediaPermission() async {
|
||||||
|
try {
|
||||||
|
return await _channel.invokeMethod('requestManageMediaPermission');
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error requesting manage media permission', e, s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> hasManageMediaPermission() async {
|
||||||
|
try {
|
||||||
|
return await _channel.invokeMethod('hasManageMediaPermission');
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error requesting manage media permission state', e, s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> manageMediaPermission() async {
|
||||||
|
try {
|
||||||
|
return await _channel.invokeMethod('manageMediaPermission');
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Error requesting manage media permission settings', e, s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ class WidgetService {
|
|||||||
const WidgetService(this._repository);
|
const WidgetService(this._repository);
|
||||||
|
|
||||||
Future<void> writeCredentials(String serverURL, String sessionKey, String? customHeaders) async {
|
Future<void> writeCredentials(String serverURL, String sessionKey, String? customHeaders) async {
|
||||||
await _repository.setAppGroupId();
|
await _repository.setAppGroupId(appShareGroupId);
|
||||||
await _repository.saveData(kWidgetServerEndpoint, serverURL);
|
await _repository.saveData(kWidgetServerEndpoint, serverURL);
|
||||||
await _repository.saveData(kWidgetAuthToken, sessionKey);
|
await _repository.saveData(kWidgetAuthToken, sessionKey);
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ class WidgetService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> clearCredentials() async {
|
Future<void> clearCredentials() async {
|
||||||
await _repository.setAppGroupId();
|
await _repository.setAppGroupId(appShareGroupId);
|
||||||
await _repository.saveData(kWidgetServerEndpoint, "");
|
await _repository.saveData(kWidgetServerEndpoint, "");
|
||||||
await _repository.saveData(kWidgetAuthToken, "");
|
await _repository.saveData(kWidgetAuthToken, "");
|
||||||
await _repository.saveData(kWidgetCustomHeaders, "");
|
await _repository.saveData(kWidgetCustomHeaders, "");
|
||||||
|
|||||||
@@ -124,13 +124,6 @@ Future<void> _migrateTo26(Drift drift) async {
|
|||||||
await _migrateAlbumSortMode(migrator);
|
await _migrateAlbumSortMode(migrator);
|
||||||
await migrator.migrateBool(StoreKey.legacySelectedAlbumSortReverse, MetadataKey.albumIsReverse);
|
await migrator.migrateBool(StoreKey.legacySelectedAlbumSortReverse, MetadataKey.albumIsReverse);
|
||||||
await migrator.migrateBool(StoreKey.legacyAlbumGridView, MetadataKey.albumIsGrid);
|
await migrator.migrateBool(StoreKey.legacyAlbumGridView, MetadataKey.albumIsGrid);
|
||||||
// Backup
|
|
||||||
await migrator.migrateBool(StoreKey.legacyEnableBackup, MetadataKey.backupEnabled);
|
|
||||||
await migrator.migrateBool(StoreKey.legacyUseWifiForUploadVideos, MetadataKey.backupUseCellularForVideos);
|
|
||||||
await migrator.migrateBool(StoreKey.legacyUseWifiForUploadPhotos, MetadataKey.backupUseCellularForPhotos);
|
|
||||||
await migrator.migrateBool(StoreKey.legacyBackupRequireCharging, MetadataKey.backupRequireCharging);
|
|
||||||
await migrator.migrateInt(StoreKey.legacyBackupTriggerDelay, MetadataKey.backupTriggerDelay);
|
|
||||||
await migrator.migrateBool(StoreKey.legacySyncAlbums, MetadataKey.backupSyncAlbums);
|
|
||||||
await migrator.complete();
|
await migrator.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.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/models/server_info/server_info.model.dart';
|
import 'package:immich_mobile/models/server_info/server_info.model.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/cast.provider.dart';
|
import 'package:immich_mobile/providers/cast.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/setting.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/sync_status.provider.dart';
|
import 'package:immich_mobile/providers/sync_status.provider.dart';
|
||||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||||
@@ -192,51 +193,64 @@ class _BackupIndicator extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget? _getBackupBadgeIcon(BuildContext context, WidgetRef ref) {
|
Widget? _getBackupBadgeIcon(BuildContext context, WidgetRef ref) {
|
||||||
final backupEnabled = ref.watch(appConfigProvider.select((c) => c.backup.enabled));
|
final backupStateStream = ref.watch(settingsProvider).watch(Setting.enableBackup);
|
||||||
final hasError = ref.watch(driftBackupProvider.select((state) => state.error != BackupError.none));
|
final hasError = ref.watch(driftBackupProvider.select((state) => state.error != BackupError.none));
|
||||||
final isDarkTheme = context.isDarkTheme;
|
final isDarkTheme = context.isDarkTheme;
|
||||||
final iconColor = isDarkTheme ? Colors.white : Colors.black;
|
final iconColor = isDarkTheme ? Colors.white : Colors.black;
|
||||||
final isUploading = ref.watch(driftBackupProvider.select((state) => state.uploadItems.isNotEmpty));
|
final isUploading = ref.watch(driftBackupProvider.select((state) => state.uploadItems.isNotEmpty));
|
||||||
|
|
||||||
if (!backupEnabled) {
|
return StreamBuilder(
|
||||||
return _BadgeLabel(
|
stream: backupStateStream,
|
||||||
Icon(Icons.cloud_off_rounded, size: 9, color: iconColor, semanticLabel: 'backup_controller_page_backup'.tr()),
|
initialData: false,
|
||||||
);
|
builder: (ctx, snapshot) {
|
||||||
}
|
final backupEnabled = snapshot.data ?? false;
|
||||||
|
|
||||||
if (hasError) {
|
if (!backupEnabled) {
|
||||||
return _BadgeLabel(
|
return _BadgeLabel(
|
||||||
Icon(
|
Icon(
|
||||||
Icons.warning_rounded,
|
Icons.cloud_off_rounded,
|
||||||
size: 12,
|
size: 9,
|
||||||
color: context.colorScheme.error,
|
color: iconColor,
|
||||||
semanticLabel: 'backup_controller_page_backup'.tr(),
|
semanticLabel: 'backup_controller_page_backup'.tr(),
|
||||||
),
|
|
||||||
backgroundColor: context.colorScheme.errorContainer,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUploading) {
|
|
||||||
return _BadgeLabel(
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(3.5),
|
|
||||||
child: Theme(
|
|
||||||
data: context.themeData.copyWith(
|
|
||||||
progressIndicatorTheme: context.themeData.progressIndicatorTheme.copyWith(year2023: true),
|
|
||||||
),
|
),
|
||||||
child: CircularProgressIndicator(
|
);
|
||||||
strokeWidth: 2,
|
}
|
||||||
strokeCap: StrokeCap.round,
|
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(iconColor),
|
|
||||||
semanticsLabel: 'backup_controller_page_backup'.tr(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _BadgeLabel(
|
if (hasError) {
|
||||||
Icon(Icons.check_outlined, size: 9, color: iconColor, semanticLabel: 'backup_controller_page_backup'.tr()),
|
return _BadgeLabel(
|
||||||
|
Icon(
|
||||||
|
Icons.warning_rounded,
|
||||||
|
size: 12,
|
||||||
|
color: context.colorScheme.error,
|
||||||
|
semanticLabel: 'backup_controller_page_backup'.tr(),
|
||||||
|
),
|
||||||
|
backgroundColor: context.colorScheme.errorContainer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUploading) {
|
||||||
|
return _BadgeLabel(
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(3.5),
|
||||||
|
child: Theme(
|
||||||
|
data: context.themeData.copyWith(
|
||||||
|
progressIndicatorTheme: context.themeData.progressIndicatorTheme.copyWith(year2023: true),
|
||||||
|
),
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
strokeCap: StrokeCap.round,
|
||||||
|
valueColor: AlwaysStoppedAnimation<Color>(iconColor),
|
||||||
|
semanticsLabel: 'backup_controller_page_backup'.tr(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _BadgeLabel(
|
||||||
|
Icon(Icons.check_outlined, size: 9, color: iconColor, semanticLabel: 'backup_controller_page_backup'.tr()),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ 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/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/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/gallery_permission.provider.dart';
|
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
|
||||||
import 'package:immich_mobile/providers/oauth.provider.dart';
|
import 'package:immich_mobile/providers/oauth.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';
|
||||||
import 'package:immich_mobile/repositories/permission.repository.dart';
|
import 'package:immich_mobile/repositories/local_files_manager.repository.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/utils/provider_utils.dart';
|
import 'package:immich_mobile/utils/provider_utils.dart';
|
||||||
import 'package:immich_mobile/utils/url_helper.dart';
|
import 'package:immich_mobile/utils/url_helper.dart';
|
||||||
@@ -187,13 +186,13 @@ class LoginForm extends HookConsumerWidget {
|
|||||||
await backgroundManager.syncRemote();
|
await backgroundManager.syncRemote();
|
||||||
await backgroundManager.hashAssets();
|
await backgroundManager.hashAssets();
|
||||||
|
|
||||||
if (MetadataRepository.instance.appConfig.backup.syncAlbums) {
|
if (Store.get(StoreKey.syncAlbums, false)) {
|
||||||
await backgroundManager.syncLinkedAlbum();
|
await backgroundManager.syncLinkedAlbum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getManageMediaPermission() async {
|
getManageMediaPermission() async {
|
||||||
final hasPermission = await ref.read(permissionRepositoryProvider).hasManageMediaPermission();
|
final hasPermission = await ref.read(localFilesManagerRepositoryProvider).hasManageMediaPermission();
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
await showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -224,7 +223,7 @@ class LoginForm extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
unawaited(ref.read(permissionRepositoryProvider).requestManageMediaPermission());
|
ref.read(localFilesManagerRepositoryProvider).requestManageMediaPermission();
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user