mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
Merge branch 'main' into feat/new-search-ui
This commit is contained in:
commit
c54722d666
1039 changed files with 10274 additions and 359814 deletions
14
.gitattributes
vendored
14
.gitattributes
vendored
|
|
@ -1,29 +1,15 @@
|
|||
mobile/openapi/**/*.md -diff -merge
|
||||
mobile/openapi/**/*.md linguist-generated=true
|
||||
mobile/openapi/**/*.dart -diff -merge
|
||||
mobile/openapi/**/*.dart linguist-generated=true
|
||||
|
||||
mobile/lib/**/*.g.dart -diff -merge
|
||||
mobile/lib/**/*.g.dart linguist-generated=true
|
||||
|
||||
mobile/android/**/*.g.kt -diff -merge
|
||||
mobile/android/**/*.g.kt linguist-generated=true
|
||||
|
||||
mobile/ios/**/*.g.swift -diff -merge
|
||||
mobile/ios/**/*.g.swift linguist-generated=true
|
||||
|
||||
mobile/lib/**/*.drift.dart -diff -merge
|
||||
mobile/lib/**/*.drift.dart linguist-generated=true
|
||||
|
||||
mobile/drift_schemas/main/drift_schema_*.json -diff -merge
|
||||
mobile/drift_schemas/main/drift_schema_*.json linguist-generated=true
|
||||
|
||||
mobile/lib/infrastructure/repositories/db.repository.steps.dart -diff -merge
|
||||
mobile/lib/infrastructure/repositories/db.repository.steps.dart linguist-generated=true
|
||||
|
||||
mobile/test/drift/main/generated/** -diff -merge
|
||||
mobile/test/drift/main/generated/** linguist-generated=true
|
||||
|
||||
packages/sdk/fetch-client.ts -diff -merge
|
||||
packages/sdk/fetch-client.ts linguist-generated=true
|
||||
|
||||
|
|
|
|||
2
.github/workflows/auto-close.yml
vendored
2
.github/workflows/auto-close.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
outputs:
|
||||
uses_template: ${{ steps.check.outputs.uses_template }}
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
sparse-checkout: .github/pull_request_template.md
|
||||
sparse-checkout-cone-mode: false
|
||||
|
|
|
|||
25
.github/workflows/build-mobile.yml
vendored
25
.github/workflows/build-mobile.yml
vendored
|
|
@ -87,14 +87,14 @@ jobs:
|
|||
permission-contents: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
working_directory: ./mobile
|
||||
|
|
@ -130,12 +130,8 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: mise //mobile:install:ci
|
||||
|
||||
- name: Generate translation file
|
||||
run: mise //mobile:codegen:translation
|
||||
|
||||
- name: Generate platform APIs
|
||||
run: mise //mobile:codegen:pigeon
|
||||
working-directory: ./mobile
|
||||
- name: Perform codegen
|
||||
run: mise //mobile:codegen
|
||||
|
||||
- name: Build Android App Bundle
|
||||
working-directory: ./mobile
|
||||
|
|
@ -214,13 +210,13 @@ jobs:
|
|||
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ inputs.ref || github.sha }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
working_directory: ./mobile
|
||||
|
|
@ -228,18 +224,15 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: mise //mobile:install:ci
|
||||
|
||||
- name: Generate translation files
|
||||
run: mise //mobile:codegen:translation
|
||||
|
||||
- name: Generate platform APIs
|
||||
run: mise //mobile:codegen:pigeon
|
||||
- name: Perform codegen
|
||||
run: mise //mobile:codegen
|
||||
|
||||
- name: Resolve iOS Swift Packages
|
||||
working-directory: ./mobile
|
||||
run: flutter build ios --config-only --no-codesign
|
||||
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@003a5c4d8d6321bd302e38f6f0ec593f77f06600 # v1.319.0
|
||||
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
||||
with:
|
||||
ruby-version: '3.3'
|
||||
bundler-cache: true
|
||||
|
|
|
|||
2
.github/workflows/cache-cleanup.yml
vendored
2
.github/workflows/cache-cleanup.yml
vendored
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
permission-actions: write
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
|
|
|||
8
.github/workflows/check-openapi.yml
vendored
8
.github/workflows/check-openapi.yml
vendored
|
|
@ -20,12 +20,12 @@ jobs:
|
|||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check for breaking API changes
|
||||
uses: oasdiff/oasdiff-action/breaking@024f6c399f9a21ada1addb0f9a36ce1bfac995f1 # v0.1.6
|
||||
uses: oasdiff/oasdiff-action/breaking@0ab8ad204b00d25acc5ae87106281433e288d0c1 # v0.1.10
|
||||
with:
|
||||
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
|
||||
revision: open-api/immich-openapi-specs.json
|
||||
|
|
@ -38,12 +38,12 @@ jobs:
|
|||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ github.token }}
|
||||
working_directory: ./mobile
|
||||
|
|
|
|||
8
.github/workflows/cli.yml
vendored
8
.github/workflows/cli.yml
vendored
|
|
@ -38,13 +38,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
|
@ -83,7 +83,7 @@ jobs:
|
|||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
|
|
|
|||
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
|
|
@ -51,14 +51,14 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
|
||||
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
|
|
@ -71,7 +71,7 @@ jobs:
|
|||
# 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)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
|
||||
uses: github/codeql-action/autobuild@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
|
||||
|
||||
# ℹ️ 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
|
||||
|
|
@ -84,6 +84,6 @@ jobs:
|
|||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
|
||||
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
|
||||
with:
|
||||
category: '/language:${{matrix.language}}'
|
||||
|
|
|
|||
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
|
|
@ -61,7 +61,7 @@ jobs:
|
|||
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
suffix: ['']
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
|
|
|
|||
4
.github/workflows/docs-build.yml
vendored
4
.github/workflows/docs-build.yml
vendored
|
|
@ -62,13 +62,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
|
|||
4
.github/workflows/docs-deploy.yml
vendored
4
.github/workflows/docs-deploy.yml
vendored
|
|
@ -137,13 +137,13 @@ jobs:
|
|||
permission-pull-requests: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
|
|||
4
.github/workflows/docs-destroy.yml
vendored
4
.github/workflows/docs-destroy.yml
vendored
|
|
@ -25,13 +25,13 @@ jobs:
|
|||
permission-pull-requests: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
|
|||
2
.github/workflows/fdroid.yml
vendored
2
.github/workflows/fdroid.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
contents: read
|
||||
steps:
|
||||
- name: Checkout pubspec for versionCode
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ github.event.release.tag_name }}
|
||||
persist-credentials: false
|
||||
|
|
|
|||
4
.github/workflows/fix-format.yml
vendored
4
.github/workflows/fix-format.yml
vendored
|
|
@ -23,14 +23,14 @@ jobs:
|
|||
permission-pull-requests: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
persist-credentials: true
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
|
|||
1
.github/workflows/pr-label-validation.yml
vendored
1
.github/workflows/pr-label-validation.yml
vendored
|
|
@ -8,6 +8,7 @@ permissions: {}
|
|||
|
||||
jobs:
|
||||
validate-release-label:
|
||||
if: ${{ !startsWith(github.event.pull_request.head.ref, 'mergify/merge-queue/') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
|
|
|
|||
2
.github/workflows/pr-labeler.yml
vendored
2
.github/workflows/pr-labeler.yml
vendored
|
|
@ -19,6 +19,6 @@ jobs:
|
|||
permission-contents: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
|
||||
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
|
||||
with:
|
||||
repo-token: ${{ steps.token.outputs.token }}
|
||||
|
|
|
|||
8
.github/workflows/prepare-release.yml
vendored
8
.github/workflows/prepare-release.yml
vendored
|
|
@ -61,20 +61,20 @@ jobs:
|
|||
permission-contents: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
persist-credentials: true
|
||||
ref: main
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
# TODO move to mise
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
||||
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
|
||||
- name: Bump version
|
||||
env:
|
||||
|
|
@ -140,7 +140,7 @@ jobs:
|
|||
permission-actions: read
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
persist-credentials: false
|
||||
|
|
|
|||
4
.github/workflows/sdk.yml
vendored
4
.github/workflows/sdk.yml
vendored
|
|
@ -23,13 +23,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
|
|||
34
.github/workflows/static_analysis.yml
vendored
34
.github/workflows/static_analysis.yml
vendored
|
|
@ -58,13 +58,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
working_directory: ./mobile
|
||||
|
|
@ -76,34 +76,8 @@ jobs:
|
|||
run: flutter pub get --enforce-lockfile
|
||||
working-directory: ./mobile/packages/ui
|
||||
|
||||
- name: Generate translation files
|
||||
run: mise //mobile:codegen:translation
|
||||
|
||||
- name: Run Build Runner
|
||||
run: mise //mobile:codegen:dart
|
||||
|
||||
- name: Generate platform API
|
||||
run: mise //mobile:codegen:pigeon
|
||||
|
||||
- name: Find file changes
|
||||
uses: tj-actions/verify-changed-files@a1c6acee9df209257a246f2cc6ae8cb6581c1edf # v20.0.4
|
||||
id: verify-changed-files
|
||||
with:
|
||||
files: |
|
||||
mobile/**/*.g.dart
|
||||
mobile/**/*.gr.dart
|
||||
mobile/**/*.drift.dart
|
||||
mobile/**/*.g.swift
|
||||
mobile/**/*.g.kt
|
||||
|
||||
- name: Verify files have not changed
|
||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.verify-changed-files.outputs.changed_files }}
|
||||
run: |
|
||||
echo "ERROR: Generated files not up to date! Run 'mise //mobile:codegen:dart' and 'mise //mobile:codegen:pigeon'"
|
||||
echo "Changed files: ${CHANGED_FILES}"
|
||||
exit 1
|
||||
- name: Perform codegen
|
||||
run: mise //mobile:codegen
|
||||
|
||||
- name: Run analyze
|
||||
run: mise //mobile:analyze
|
||||
|
|
|
|||
79
.github/workflows/test.yml
vendored
79
.github/workflows/test.yml
vendored
|
|
@ -85,13 +85,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -114,13 +114,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -146,13 +146,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -178,13 +178,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -223,13 +223,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -262,13 +262,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -291,13 +291,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -342,13 +342,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -375,14 +375,14 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: 'recursive'
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: 'recursive'
|
||||
|
|
@ -441,6 +441,7 @@ jobs:
|
|||
if: ${{ !cancelled() }}
|
||||
|
||||
- name: Start Docker Compose
|
||||
id: docker
|
||||
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
|
|
@ -448,13 +449,13 @@ jobs:
|
|||
env:
|
||||
VITEST_DISABLE_DOCKER_SETUP: true
|
||||
run: pnpm test
|
||||
if: ${{ !cancelled() }}
|
||||
if: ${{ !cancelled() && steps.docker.outcome == 'success' }}
|
||||
|
||||
- name: Run e2e tests (maintenance)
|
||||
env:
|
||||
VITEST_DISABLE_DOCKER_SETUP: true
|
||||
run: pnpm test:maintenance
|
||||
if: ${{ !cancelled() }}
|
||||
if: ${{ !cancelled() && steps.docker.outcome == 'success' }}
|
||||
|
||||
- name: Capture Docker logs
|
||||
if: always()
|
||||
|
|
@ -490,7 +491,7 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: 'recursive'
|
||||
|
|
@ -519,6 +520,7 @@ jobs:
|
|||
if: ${{ !cancelled() }}
|
||||
|
||||
- name: Docker build
|
||||
id: docker
|
||||
run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
|
|
@ -526,7 +528,7 @@ jobs:
|
|||
env:
|
||||
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
||||
run: pnpm test:web
|
||||
if: ${{ !cancelled() }}
|
||||
if: ${{ !cancelled() && steps.docker.outcome == 'success' }}
|
||||
|
||||
- name: Archive e2e test (web) results
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
|
|
@ -539,7 +541,7 @@ jobs:
|
|||
env:
|
||||
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
||||
run: pnpm test:web:ui
|
||||
if: ${{ !cancelled() }}
|
||||
if: ${{ !cancelled() && steps.docker.outcome == 'success' }}
|
||||
|
||||
- name: Archive ui test (web) results
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
|
|
@ -552,7 +554,7 @@ jobs:
|
|||
env:
|
||||
PLAYWRIGHT_DISABLE_WEBSERVER: true
|
||||
run: pnpm test:web:maintenance
|
||||
if: ${{ !cancelled() }}
|
||||
if: ${{ !cancelled() && steps.docker.outcome == 'success' }}
|
||||
|
||||
- name: Archive maintenance tests (web) results
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
|
|
@ -598,13 +600,13 @@ jobs:
|
|||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
working_directory: ./mobile
|
||||
|
|
@ -612,8 +614,8 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: mise //mobile:install:ci
|
||||
|
||||
- name: Generate translation files
|
||||
run: mise //mobile:codegen:translation
|
||||
- name: Perform codegen
|
||||
run: mise //mobile:codegen
|
||||
|
||||
- name: Run tests
|
||||
run: mise //mobile:test
|
||||
|
|
@ -636,13 +638,13 @@ jobs:
|
|||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -668,13 +670,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -698,7 +700,7 @@ jobs:
|
|||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
|
@ -721,13 +723,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
@ -742,7 +744,6 @@ jobs:
|
|||
id: verify-changed-files
|
||||
with:
|
||||
files: |
|
||||
mobile/openapi
|
||||
packages/sdk
|
||||
open-api/immich-openapi-specs.json
|
||||
|
||||
|
|
@ -780,13 +781,13 @@ jobs:
|
|||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
uses: immich-app/devtools/actions/use-mise@06a9ef925332c91be647d6256642b86b398592c8 # use-mise-action-v3.2.1
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
|
||||
|
|
|
|||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -11,13 +11,10 @@ docker/library
|
|||
uploads
|
||||
coverage
|
||||
|
||||
mobile/generated
|
||||
mobile/gradle.properties
|
||||
mobile/openapi/pubspec.lock
|
||||
mobile/*.jks
|
||||
mobile/libisar.dylib
|
||||
mobile/openapi/test
|
||||
mobile/openapi/doc
|
||||
mobile/openapi/.openapi-generator/FILES
|
||||
mobile/ios/build
|
||||
|
||||
packages/**/build
|
||||
|
|
|
|||
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
|
|
@ -12,6 +12,8 @@
|
|||
"editorconfig.editorconfig",
|
||||
"foxundermoon.shell-format",
|
||||
"timonwong.shellcheck",
|
||||
"bluebrown.yamlfmt"
|
||||
"bluebrown.yamlfmt",
|
||||
// TODO TS 7 while it's still in preview
|
||||
"typescriptteam.native-preview"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -60,6 +60,8 @@
|
|||
"**/dist/**": true,
|
||||
"**/node_modules/**": true
|
||||
},
|
||||
// TODO remove once the ts7 extension is stable
|
||||
"js/ts.experimental.useTsgo": true,
|
||||
"js/ts.preferences.importModuleSpecifier": "non-relative",
|
||||
"search.exclude": {
|
||||
"**/.svelte-kit": true,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ We usually do not assign issues to new contributors, since it happens often that
|
|||
|
||||
## Use of generative AI
|
||||
|
||||
We ask you not to open PRs generated with an LLM. We find that code generated like this tends to need a large amount of back-and-forth, which is a very inefficient use of our time. If we want LLM-generated code, it's much faster for us to use an LLM ourselves than to go through an intermediary via a pull request.
|
||||
We ask you not to open PRs generated with an LLM. We find that code generated like this tends to need a large amount of back-and-forth, which is a very inefficient use of our time. Even a one line change can have significant impact. We cannot have any confidence in an LLM, so if it's non-trivial for us to verify it works and you don't show that you fully understand all implications of the change, reviewing the PR is not worth our time. If we want LLM-generated code, it's much faster for us to use an LLM ourselves than to go through an intermediary via a pull request.
|
||||
|
||||
If you use an LLM to translate a PR description or title, that is fine. Please make sure however that you stick to the PR template and that the text is written concisely.
|
||||
|
||||
Misrepresenting LLM use, contribution farming (automated low-effort PRs), or repeatedly hitting auto-close rules may be grounds for a block at maintainer discretion.
|
||||
|
||||
## Feature freezes
|
||||
|
||||
|
|
@ -38,7 +42,7 @@ All our translations are done through [Weblate](https://hosted.weblate.org/proje
|
|||
|
||||
### Datasets
|
||||
|
||||
Help us improve our [Immich Datasets](https://datasets.immich.app) by submitting photos and videos taken from a variety of devices, including smartphones, DSLRs, and action cameras, as well as photos with unique features, such as panoramas, burst photos, and photo spheres. These datasets will be publically available for anyone to use, do not submit private/sensitive photos.
|
||||
Help us improve our [Immich Datasets](https://datasets.immich.app) by submitting photos and videos taken from a variety of devices, including smartphones, DSLRs, and action cameras, as well as photos with unique features, such as panoramas, burst photos, and photo spheres. These datasets will be publicly available for anyone to use, do not submit private/sensitive photos.
|
||||
|
||||
### Community support
|
||||
|
||||
|
|
|
|||
58
Makefile
58
Makefile
|
|
@ -1,58 +0,0 @@
|
|||
dev:
|
||||
@printf "This command has been removed. Please use:\n\n mise dev # or mise //:dev from another directory\n\n" >&2 && exit 1
|
||||
|
||||
dev-down:
|
||||
@printf "This command has been removed. Please use:\n\n mise dev-down # or mise //:dev-down from another directory\n\n" >&2 && exit 1
|
||||
|
||||
dev-update:
|
||||
@printf "This command has been removed. Please use:\n\n mise dev-update # or mise //:dev-update from another directory\n\n" >&2 && exit 1
|
||||
|
||||
dev-scale:
|
||||
@printf "This command has been removed. Please use:\n\n mise dev-scale # or mise //:dev-scale from another directory\n\n" >&2 && exit 1
|
||||
|
||||
dev-docs:
|
||||
npm --prefix docs run start
|
||||
|
||||
.PHONY: e2e
|
||||
e2e:
|
||||
@printf "This command has been removed. Please use:\n\n mise e2e # or mise //:e2e from another directory\n\n" >&2 && exit 1
|
||||
|
||||
e2e-dev:
|
||||
@printf "This command has been removed. Please use:\n\n mise e2e-dev # or mise //:e2e-dev from another directory\n\n" >&2 && exit 1
|
||||
|
||||
e2e-update:
|
||||
@printf "This command has been removed. Please use:\n\n mise e2e-update # or mise //:e2e-update from another directory\n\n" >&2 && exit 1
|
||||
|
||||
e2e-down:
|
||||
@printf "This command has been removed. Please use:\n\n mise e2e-down # or mise //:e2e-down from another directory\n\n" >&2 && exit 1
|
||||
|
||||
prod:
|
||||
@printf "This command has been removed. Please use:\n\n mise prod # or mise //:prod from another directory\n\n" >&2 && exit 1
|
||||
|
||||
prod-down:
|
||||
@printf "This command has been removed. Please use:\n\n mise prod-down # or mise //:prod-down from another directory\n\n" >&2 && exit 1
|
||||
|
||||
prod-scale:
|
||||
@printf "This command has been removed. Please use:\n\n mise prod-scale # or mise //:prod-scale from another directory\n\n" >&2 && exit 1
|
||||
|
||||
.PHONY: open-api
|
||||
open-api:
|
||||
@printf "This command has been removed. Please use:\n\n mise open-api # or mise //:open-api from another directory\n\n" >&2 && exit 1
|
||||
|
||||
sql:
|
||||
@printf "This command has been removed. Please use:\n\n mise sql # or mise //:sql from another directory\n\n" >&2 && exit 1
|
||||
|
||||
|
||||
renovate:
|
||||
LOG_LEVEL=debug pnpm exec renovate --platform=local --repository-cache=reset
|
||||
|
||||
# Include .env file if it exists
|
||||
-include docker/.env
|
||||
|
||||
MODULES = e2e server web cli sdk docs .github
|
||||
|
||||
test-e2e:
|
||||
@printf "This command has been removed. Please use:\n\n mise //e2e:test # or mise //e2e:test-web for web tests, respectively\n\n" >&2 && exit 1
|
||||
|
||||
clean:
|
||||
@printf "This command has been removed. Please use:\n\n mise clean # or mise //:clean from another directory\n\n" >&2 && exit 1
|
||||
|
|
@ -1,43 +1,43 @@
|
|||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
||||
|
||||
[[tools.opentofu]]
|
||||
version = "1.11.6"
|
||||
version = "1.12.5"
|
||||
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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536382"
|
||||
checksum = "sha256:e67e9da2b1ddf5050ebee62a584cb826eafe1dfd3827d7ec20899ac62791ed1a"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602545"
|
||||
|
||||
[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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536382"
|
||||
checksum = "sha256:e67e9da2b1ddf5050ebee62a584cb826eafe1dfd3827d7ec20899ac62791ed1a"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602545"
|
||||
|
||||
[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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536401"
|
||||
checksum = "sha256:a6894d45ae7a17ce83189cce8fe04b5a65f68cefceb62455b5a6a89fa53ab38f"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602624"
|
||||
|
||||
[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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536401"
|
||||
checksum = "sha256:a6894d45ae7a17ce83189cce8fe04b5a65f68cefceb62455b5a6a89fa53ab38f"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602624"
|
||||
|
||||
[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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536399"
|
||||
checksum = "sha256:2ae38150a667f5c0bd57b318d18ad8091d08f93fcca40345f3d88998661de5a9"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_darwin_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602544"
|
||||
|
||||
[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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536384"
|
||||
checksum = "sha256:1012d8f3d4567bcbcd1f2c7d766feca39a30bced32fb8be47e1887fbbee2456d"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_darwin_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602621"
|
||||
|
||||
[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"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536406"
|
||||
checksum = "sha256:af11850b496f3720e0184084c56d8b43aa74ea92d2338978bf368d70c96473f1"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_windows_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602547"
|
||||
|
||||
[[tools.terragrunt]]
|
||||
version = "1.0.3"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tools]
|
||||
terragrunt = "1.1.1"
|
||||
opentofu = "1.12.4"
|
||||
opentofu = "1.12.5"
|
||||
|
||||
[tasks."tg:fmt"]
|
||||
run = "terragrunt hclfmt"
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ services:
|
|||
|
||||
redis:
|
||||
container_name: immich_redis
|
||||
image: docker.io/valkey/valkey:9@sha256:8e8d64b405ce18f41b8e5ee20aa4687a8ed0022d1298f2ce31cdcf3a76e09411
|
||||
image: docker.io/valkey/valkey:9@sha256:3acc0687f2a2e1091fae6450d7842dd658c941338cf0a873ddd9e14b9e4ea4dd
|
||||
healthcheck:
|
||||
test: redis-cli ping || exit 1
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ services:
|
|||
|
||||
redis:
|
||||
container_name: immich_redis
|
||||
image: docker.io/valkey/valkey:9@sha256:8e8d64b405ce18f41b8e5ee20aa4687a8ed0022d1298f2ce31cdcf3a76e09411
|
||||
image: docker.io/valkey/valkey:9@sha256:3acc0687f2a2e1091fae6450d7842dd658c941338cf0a873ddd9e14b9e4ea4dd
|
||||
healthcheck:
|
||||
test: redis-cli ping || exit 1
|
||||
restart: always
|
||||
|
|
@ -97,7 +97,7 @@ services:
|
|||
command: ['./run.sh', '-disable-reporting']
|
||||
ports:
|
||||
- 3000:3000
|
||||
image: grafana/grafana:12.4.5-ubuntu@sha256:00396460e499415c828b7c298f19287c8a0f95e72412ee37ac11723655c2d6b9
|
||||
image: grafana/grafana:12.4.6-ubuntu@sha256:35c75489ff2e2e69c53977a180de491643d51fdb32108f9335317527978daed7
|
||||
volumes:
|
||||
- grafana-data:/var/lib/grafana
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,6 @@ services:
|
|||
- NET_RAW
|
||||
volumes:
|
||||
- ./ml-model-cache:/cache
|
||||
- ./ml-dotcache:/.cache
|
||||
- ./ml-config:/.config
|
||||
env_file:
|
||||
- .env
|
||||
restart: always
|
||||
|
|
@ -61,7 +59,7 @@ services:
|
|||
|
||||
redis:
|
||||
container_name: immich_redis
|
||||
image: docker.io/valkey/valkey:9@sha256:8e8d64b405ce18f41b8e5ee20aa4687a8ed0022d1298f2ce31cdcf3a76e09411
|
||||
image: docker.io/valkey/valkey:9@sha256:3acc0687f2a2e1091fae6450d7842dd658c941338cf0a873ddd9e14b9e4ea4dd
|
||||
user: '1000:1000'
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ services:
|
|||
|
||||
redis:
|
||||
container_name: immich_redis
|
||||
image: docker.io/valkey/valkey:9@sha256:8e8d64b405ce18f41b8e5ee20aa4687a8ed0022d1298f2ce31cdcf3a76e09411
|
||||
image: docker.io/valkey/valkey:9@sha256:3acc0687f2a2e1091fae6450d7842dd658c941338cf0a873ddd9e14b9e4ea4dd
|
||||
healthcheck:
|
||||
test: redis-cli ping || exit 1
|
||||
restart: always
|
||||
|
|
|
|||
|
|
@ -413,8 +413,6 @@ You can change the user in the container by setting the `user` argument in `dock
|
|||
|
||||
You may need to add mount points or docker volumes for the following internal container paths:
|
||||
|
||||
- `immich-machine-learning:/.config`
|
||||
- `immich-machine-learning:/.cache`
|
||||
- `redis:/data`
|
||||
|
||||
The non-root user/group needs read/write access to the volume mounts, including `UPLOAD_LOCATION` and `/cache` for machine-learning.
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ Configuration of OAuth in Immich System Settings
|
|||
| ---------------------------- | ----------------------------------------------------- |
|
||||
| Issuer URL | `https://<KEYCLOAK_DOMAIN>/realms/<YOUR_REALM>` |
|
||||
| Client ID | immich |
|
||||
| Client Secret | can be optained from Clients -> immich -> Credentials |
|
||||
| Client Secret | can be obtained from Clients -> immich -> Credentials |
|
||||
| Scope | openid email profile |
|
||||
| Signing Algorithm | RS256 |
|
||||
| Storage Label Claim | preferred_username |
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@ OpenAPI is used to generate the client (Typescript, Dart) SDK. `openapi-generato
|
|||
mise open-api
|
||||
```
|
||||
|
||||
You can find the generated client SDK in the `packages/sdk/client` for Typescript SDK and `mobile/openapi` for Dart SDK.
|
||||
You can find the generated client SDK in the `packages/sdk/client` for Typescript SDK and `mobile/generated/openapi` for Dart SDK.
|
||||
|
|
|
|||
|
|
@ -6,14 +6,18 @@ sidebar_position: 100
|
|||
|
||||
A config file can be provided as an alternative to the UI configuration.
|
||||
|
||||
:::note Interaction with the web UI
|
||||
While the config file does not need to include all keys from the below example, specifying `IMMICH_CONFIG_FILE` will disable the ability to edit other properties from the Immich web UI.
|
||||
:::
|
||||
|
||||
### Step 1 - Create a new config file
|
||||
|
||||
In JSON format, create a new config file (e.g. `immich.json`) and put it in a location mounted in the container that can be accessed by Immich.
|
||||
In JSON format, create a new config file (e.g. `immich-config.json`) and put it in a location mounted in the container that can be accessed by Immich.
|
||||
YAML-formatted config files are also supported.
|
||||
The default configuration looks like this:
|
||||
|
||||
<details>
|
||||
<summary>immich.json</summary>
|
||||
<summary>immich-config.json</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -250,6 +254,10 @@ So you can just grab it from there, paste it into a file and you're pretty much
|
|||
|
||||
### Step 2 - Specify the file location
|
||||
|
||||
:::note
|
||||
If you have any `microservices` workers, they will also need to have the config file mounted to their container.
|
||||
:::
|
||||
|
||||
In your `.env` file, set the variable `IMMICH_CONFIG_FILE` to the path of your config.
|
||||
For more information, refer to the [Environment Variables](/install/environment-variables.md) section.
|
||||
|
||||
|
|
@ -261,7 +269,7 @@ It is recommended to reuse this variable in your `docker-compose.yml`:
|
|||
|
||||
```yaml
|
||||
volumes:
|
||||
- ./configuration.yml:${IMMICH_CONFIG_FILE}
|
||||
- ./immich-config.json:${IMMICH_CONFIG_FILE}
|
||||
```
|
||||
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N
|
|||
| `IMMICH_PROCESS_INVALID_IMAGES` | When `true`, generate thumbnails for invalid images | | server | microservices |
|
||||
| `IMMICH_TRUSTED_PROXIES` | List of comma-separated IPs set as trusted proxies | | server | api |
|
||||
| `IMMICH_IGNORE_MOUNT_CHECK_ERRORS` | See [System Integrity](/administration/system-integrity) | | server | api, microservices |
|
||||
| `IMMICH_ALLOW_SETUP` | When `false` disables the `/auth/admin-sign-up` endpoint | `true` | server | api |
|
||||
| `IMMICH_ALLOW_SETUP` | When `false` disables the `/auth/admin-sign-up` and `/admin/database-backups/start-restore` endpoints | `true` | server | api |
|
||||
|
||||
\*1: `TZ` should be set to a `TZ identifier` from [this list][tz-list]. For example, `TZ="Etc/UTC"`.
|
||||
`TZ` is used by `exiftool` as a fallback in case the timezone cannot be determined from the image metadata. It is also used for logfile timestamps and cron job execution.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
---
|
||||
sidebar_position: 60
|
||||
sidebar_position: 70
|
||||
---
|
||||
|
||||
# Unraid
|
||||
# Unraid [ Community ]
|
||||
|
||||
:::note
|
||||
This is a community contribution and not officially supported by the Immich team, but included here for convenience.
|
||||
|
||||
Community support can be found in the dedicated channel on the [Discord Server](https://discord.immich.app/).
|
||||
:::
|
||||
|
||||
Immich can easily be installed and updated on Unraid via:
|
||||
|
||||
1. [Docker Compose Manager](https://forums.unraid.net/topic/114415-plugin-docker-compose-manager/) plugin from the Unraid Community Apps
|
||||
2. Community made template on the Unraid Community Apps
|
||||
1. Community made template on the Unraid Community Apps
|
||||
2. [Docker Compose Manager](https://forums.unraid.net/topic/114415-plugin-docker-compose-manager/) plugin from the Unraid Community Apps
|
||||
|
||||
## Community Applications Template
|
||||
|
||||
|
|
@ -23,7 +29,7 @@ Once you have Redis and PostgreSQL running, search for Immich on the Unraid CA,
|
|||
|
||||
For more information about setting up the community image see [here](https://github.com/imagegenius/docker-immich#application-setup)
|
||||
|
||||
## Docker-Compose Method (Official)
|
||||
## Docker-Compose Method
|
||||
|
||||
:::info
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ const config = {
|
|||
},
|
||||
{
|
||||
label: 'Privacy Policy',
|
||||
to: '/privacy-policy',
|
||||
href: 'https://immich.app/privacy-policy',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,4 +28,4 @@ run = "prettier --write ."
|
|||
run = "wrangler pages deploy build --project-name=${PROJECT_NAME} --branch=${BRANCH_NAME}"
|
||||
|
||||
[tools]
|
||||
wrangler = "4.111.0"
|
||||
wrangler = "4.114.0"
|
||||
|
|
|
|||
|
|
@ -1,78 +0,0 @@
|
|||
import useIsBrowser from '@docusaurus/useIsBrowser';
|
||||
import { mdiCheckboxBlankCircle, mdiCheckboxMarkedCircle } from '@mdi/js';
|
||||
import Icon from '@mdi/react';
|
||||
import React from 'react';
|
||||
|
||||
export type Item = {
|
||||
icon: string;
|
||||
iconColor: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
link?: { url: string; text: string };
|
||||
done?: false;
|
||||
getDateLabel: (language: string) => string;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
items: Item[];
|
||||
}
|
||||
|
||||
export function Timeline({ items }: Props): JSX.Element {
|
||||
const isBrowser = useIsBrowser();
|
||||
|
||||
return (
|
||||
<ul className="flex flex-col pl-4">
|
||||
{items.map((item, index) => {
|
||||
const isFirst = index === 0;
|
||||
const isLast = index === items.length - 1;
|
||||
const done = item.done ?? true;
|
||||
const dateLabel = item.getDateLabel(isBrowser ? navigator.language : 'en-US');
|
||||
const timelineIcon = done ? mdiCheckboxMarkedCircle : mdiCheckboxBlankCircle;
|
||||
const cardIcon = item.icon;
|
||||
|
||||
return (
|
||||
<li key={index} className={`flex min-h-24 w-[700px] max-w-[90vw] ${done ? '' : 'italic'}`}>
|
||||
<div className="md:flex justify-start w-36 mr-8 items-center dark:text-immich-dark-primary text-immich-primary hidden">
|
||||
{dateLabel}
|
||||
</div>
|
||||
<div className={`${isFirst && 'relative top-[50%]'} ${isLast && 'relative bottom-[50%]'}`}>
|
||||
<div
|
||||
className={`h-full border-solid border-4 border-immich-primary dark:border-immich-dark-primary ${
|
||||
isFirst && 'rounded rounded-t-full'
|
||||
} ${isLast && 'rounded rounded-b-full'}`}
|
||||
></div>
|
||||
</div>
|
||||
<div className="z-10 flex items-center bg-immich-primary dark:bg-immich-dark-primary border-2 border-solid rounded-full dark:text-black text-white relative top-[50%] left-[-3px] translate-y-[-50%] translate-x-[-50%] w-8 h-8 shadow-lg ">
|
||||
{<Icon path={timelineIcon} size={1.25} />}
|
||||
</div>
|
||||
<section className=" dark:bg-immich-dark-gray bg-immich-gray dark:border-0 border-gray-200 border border-solid rounded-2xl flex flex-row w-full gap-2 p-4 md:ml-4 my-2 hover:bg-immich-primary/10 dark:hover:bg-immich-dark-primary/10 transition-all">
|
||||
<div className="flex flex-col flex-grow justify-between gap-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
{cardIcon === 'immich' ? (
|
||||
<img src="/img/immich-logo.svg" height="30" className="rounded-none" />
|
||||
) : (
|
||||
<Icon path={cardIcon} size={1} color={item.iconColor} />
|
||||
)}
|
||||
<p className="m-0 mt-1 text-lg items-start flex gap-2 place-items-center content-center">
|
||||
<span>{item.title}</span>
|
||||
</p>
|
||||
</div>
|
||||
<p className="m-0 text-sm text-gray-600 dark:text-gray-300">{item.description}</p>
|
||||
</div>
|
||||
<div className="flex flex-col justify-between place-items-end">
|
||||
<span className="dark:text-immich-dark-primary text-immich-primary">
|
||||
{item.link && (
|
||||
<a href={item.link.url} target="_blank" rel="noopener">
|
||||
[{item.link.text}]
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
<div className="md:hidden text-sm text-right">{dateLabel}</div>
|
||||
</div>
|
||||
</section>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
function HomepageHeader() {
|
||||
return (
|
||||
<header>
|
||||
<section className="max-w-[900px] m-4 p-4 md:p-6 md:m-auto md:my-12 border border-red-400 rounded-2xl bg-slate-200 dark:bg-immich-dark-gray">
|
||||
<section>
|
||||
<h1>Privacy Policy</h1>
|
||||
<p>Last updated: July 31st 2024</p>
|
||||
<p>
|
||||
Welcome to Immich. We are committed to respecting your privacy. This Privacy Policy sets out how we collect,
|
||||
use, and share information when you use our Immich app.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* 1. Scope of This Policy */}
|
||||
<section>
|
||||
<h2>1. Scope of This Policy</h2>
|
||||
<p>
|
||||
This Privacy Policy applies to the Immich app ("we", "our", or "us") and covers our collection, use, and
|
||||
disclosure of your information. This Policy does not cover any third-party websites, services, or
|
||||
applications that can be accessed through our app, or third-party services you may access through Immich.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* 2. Information We Collect */}
|
||||
<section>
|
||||
<h2>2. Information We Collect</h2>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Locally Stored Data</strong>: Immich stores all your photos, albums, settings, and locally on your
|
||||
device. We do not have access to this data, nor do we transmit or store it on any of our servers.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<strong>Purchase Information:</strong> When you make a purchase within the{' '}
|
||||
<a href="https://buy.immich.app">https://buy.immich.app</a>, we collect the following information for tax
|
||||
calculation purposes:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Country of origin</li>
|
||||
<li>Postal code (if the user is from Canada or the United States)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 3. Use of Your Information */}
|
||||
<section>
|
||||
<h2>3. Use of Your Information</h2>
|
||||
<p>
|
||||
<strong>Tax Calculation:</strong> The country of origin and postal code (for users from Canada or the United
|
||||
States) are collected solely for determining the applicable tax rates on your purchase.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* 4. Sharing of Your Information */}
|
||||
<section>
|
||||
<h2>4. Sharing of Your Information</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Tax Authorities:</strong> The purchase information may be shared with tax authorities as required
|
||||
by law.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Payment Providers:</strong> The purchase information may be shared with payment providers where
|
||||
required.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{/* 5. Changes to This Policy */}
|
||||
<section>
|
||||
<h2>5. Changes to This Policy</h2>
|
||||
<p>
|
||||
We may update our Privacy Policy from time to time. If we make any changes, we will notify you by revising
|
||||
the "Last updated" date at the top of this policy. It's encouraged that users frequently check this page for
|
||||
any changes to stay informed about how we are helping to protect the personal information we collect.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* 6. Contact Us */}
|
||||
<section>
|
||||
<h2>6. Contact Us</h2>
|
||||
<p>
|
||||
If you have any questions about this Privacy Policy, please contact us at{' '}
|
||||
<a href="mailto:immich@futo.org">immich@futo.org</a>
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
return (
|
||||
<Layout
|
||||
title="Home"
|
||||
description="immich Self-hosted photo and video backup solution directly from your mobile phone "
|
||||
noFooter={true}
|
||||
>
|
||||
<HomepageHeader />
|
||||
<div className="flex flex-col place-items-center place-content-center">
|
||||
<p>This project is available under GNU AGPL v3 license.</p>
|
||||
<p className="text-xs">Privacy should not be a luxury</p>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
1
docs/static/_redirects
vendored
1
docs/static/_redirects
vendored
|
|
@ -36,3 +36,4 @@
|
|||
/overview/welcome /overview/quick-start 307
|
||||
/docs/* /:splat 307
|
||||
/features/automatic-backup /features/mobile-backup 307
|
||||
/privacy-policy https://immich.app/privacy-policy 307
|
||||
|
|
|
|||
|
|
@ -11,15 +11,9 @@ module.exports = {
|
|||
colors: {
|
||||
// Light Theme
|
||||
'immich-primary': '#4250af',
|
||||
'immich-bg': '#f9f8fb',
|
||||
'immich-fg': 'black',
|
||||
'immich-gray': '#F6F6F4',
|
||||
|
||||
// Dark Theme
|
||||
'immich-dark-primary': '#adcbfa',
|
||||
'immich-dark-bg': '#000000',
|
||||
'immich-dark-fg': '#e5e7eb',
|
||||
'immich-dark-gray': '#111111',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ services:
|
|||
|
||||
redis:
|
||||
container_name: immich-e2e-redis
|
||||
image: docker.io/valkey/valkey:9@sha256:8e8d64b405ce18f41b8e5ee20aa4687a8ed0022d1298f2ce31cdcf3a76e09411
|
||||
image: docker.io/valkey/valkey:9@sha256:3acc0687f2a2e1091fae6450d7842dd658c941338cf0a873ddd9e14b9e4ea4dd
|
||||
healthcheck:
|
||||
test: redis-cli ping || exit 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[tasks.install]
|
||||
run = "pnpm install --filter immich-e2e --frozen-lockfile"
|
||||
run = "pnpm install --filter immich-e2e... --frozen-lockfile"
|
||||
|
||||
[tasks.build]
|
||||
dir = "{{ config_root }}"
|
||||
|
|
@ -40,18 +40,19 @@ run = "tsc --noEmit"
|
|||
|
||||
|
||||
[tasks.ci-setup]
|
||||
depends = [
|
||||
"//:sdk:install",
|
||||
"//:sdk:build",
|
||||
"//packages/cli:install",
|
||||
"//packages/cli:build",
|
||||
run = [
|
||||
{ task = "//:sdk:install" },
|
||||
{ task = "//:sdk:build" },
|
||||
{ task = "//packages/cli:install" },
|
||||
{ task = "//packages/cli:build" },
|
||||
{ task = ":install" },
|
||||
]
|
||||
run = { task = ":install" }
|
||||
|
||||
|
||||
[tasks.ci-unit]
|
||||
depends = ["//:sdk:install", "//:sdk:build"]
|
||||
run = [
|
||||
{ task = "//:sdk:install" },
|
||||
{ task = "//:sdk:build" },
|
||||
{ task = ":install" },
|
||||
{ task = ":format" },
|
||||
{ task = ":lint" },
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@ export const errorDto = {
|
|||
incorrectLogin: {
|
||||
message: 'Incorrect email or password',
|
||||
},
|
||||
alreadyHasAdmin: {
|
||||
message: 'The server already has an admin',
|
||||
},
|
||||
};
|
||||
|
||||
export const signupResponseDto = {
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ describe('/admin/database-backups', () => {
|
|||
const { status, body } = await request(app).post('/admin/database-backups/start-restore').send();
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest('The server already has an admin'));
|
||||
expect(body).toEqual(errorDto.badRequest('Admin setup is not available'));
|
||||
});
|
||||
|
||||
it.sequential('should enter maintenance mode in "database restore mode"', async () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
LoginResponseDto,
|
||||
Permission,
|
||||
QueueName,
|
||||
createStack,
|
||||
deleteUserAdmin,
|
||||
|
|
@ -358,6 +359,31 @@ describe('/admin/users', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('GET /admin/users/:id/calendar-heatmap', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).get(`/admin/users/${nonAdmin.userId}/calendar-heatmap`);
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should require admin permissions', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get(`/admin/users/${nonAdmin.userId}/calendar-heatmap`)
|
||||
.set('Authorization', `Bearer ${nonAdmin.accessToken}`);
|
||||
expect(status).toBe(403);
|
||||
expect(body).toEqual(errorDto.forbidden);
|
||||
});
|
||||
|
||||
it('should require the AdminUserRead permission', async () => {
|
||||
const { secret } = await utils.createApiKey(admin.accessToken, [Permission.UserRead]);
|
||||
const { status, body } = await request(app)
|
||||
.get(`/admin/users/${nonAdmin.userId}/calendar-heatmap`)
|
||||
.set('x-api-key', secret);
|
||||
expect(status).toBe(403);
|
||||
expect(body).toEqual(errorDto.forbidden);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /admin/users/:id/restore', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).post(`/admin/users/${userToDelete.userId}/restore`);
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ export const pageUtils = {
|
|||
await section.locator('.w-8').click();
|
||||
},
|
||||
async pauseTestDebug() {
|
||||
console.log('NOTE: pausing test indefinately for debug');
|
||||
console.log('NOTE: pausing test indefinitely for debug');
|
||||
await new Promise(() => void 0);
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
"add_to_album_bottom_sheet_added": "Added to {album}",
|
||||
"add_to_album_bottom_sheet_already_exists": "Already in {album}",
|
||||
"add_to_album_bottom_sheet_some_local_assets": "Some local assets could not be added to album",
|
||||
"add_to_album_item_count": "Add {count, plural, one {# item} other {# items}} to album",
|
||||
"add_to_albums": "Add to albums",
|
||||
"add_to_albums_count": "Add to albums ({count})",
|
||||
"add_to_bottom_bar": "Add to",
|
||||
|
|
|
|||
|
|
@ -160,6 +160,9 @@ ENV IMMICH_SOURCE_REF=${BUILD_SOURCE_REF}
|
|||
ENV IMMICH_SOURCE_COMMIT=${BUILD_SOURCE_COMMIT}
|
||||
ENV IMMICH_SOURCE_URL=https://github.com/immich-app/immich/commit/${BUILD_SOURCE_COMMIT}
|
||||
|
||||
# store matplotlib config in /cache subfolder to enable rootless deployment with a single volume
|
||||
ENV MPLCONFIGDIR=/cache/matplotlib
|
||||
|
||||
ENTRYPOINT ["tini", "--"]
|
||||
CMD ["python", "-m", "immich_ml"]
|
||||
|
||||
|
|
|
|||
124
mise.lock
124
mise.lock
|
|
@ -82,6 +82,15 @@ url_api = "https://api.github.com/repos/extism/js-pdk/releases/assets/353224133"
|
|||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[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:jellyfin/jellyfin-ffmpeg"]]
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_macarm64-gpl.tar.xz"
|
||||
|
||||
|
|
@ -111,23 +120,6 @@ url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets
|
|||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_linux64-gpl.tar.xz"
|
||||
|
||||
[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"]]
|
||||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[tools."github:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_mac64-gpl.tar.xz"
|
||||
|
||||
|
|
@ -140,10 +132,18 @@ url_api = "https://api.github.com/repos/jellyfin/jellyfin-ffmpeg/releases/assets
|
|||
version = "7.1.3-6"
|
||||
backend = "github:jellyfin/jellyfin-ffmpeg"
|
||||
|
||||
[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:jellyfin/jellyfin-ffmpeg".options]
|
||||
asset_pattern = "jellyfin-ffmpeg_*_portable_linux64-gpl.tar.xz"
|
||||
|
||||
[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:webassembly/binaryen"]]
|
||||
version = "version_124"
|
||||
|
|
@ -252,82 +252,82 @@ version = "7.5.0"
|
|||
backend = "npm:oazapfts"
|
||||
|
||||
[[tools.opentofu]]
|
||||
version = "1.12.4"
|
||||
version = "1.12.5"
|
||||
backend = "aqua:opentofu/opentofu"
|
||||
|
||||
[tools.opentofu."platforms.linux-arm64"]
|
||||
checksum = "sha256:dc7bfcd93ce9795a86c58fbf71efd013c39dcd1febb13c9cd3555c43b9c2403a"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_linux_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646678"
|
||||
checksum = "sha256:e67e9da2b1ddf5050ebee62a584cb826eafe1dfd3827d7ec20899ac62791ed1a"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602545"
|
||||
|
||||
[tools.opentofu."platforms.linux-arm64-musl"]
|
||||
checksum = "sha256:dc7bfcd93ce9795a86c58fbf71efd013c39dcd1febb13c9cd3555c43b9c2403a"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_linux_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646678"
|
||||
checksum = "sha256:e67e9da2b1ddf5050ebee62a584cb826eafe1dfd3827d7ec20899ac62791ed1a"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602545"
|
||||
|
||||
[tools.opentofu."platforms.linux-x64"]
|
||||
checksum = "sha256:81836d0f12b4fe9013b85586349f993def9429b6383bb77cdd6c2f3a9d9aac24"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_linux_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646677"
|
||||
checksum = "sha256:a6894d45ae7a17ce83189cce8fe04b5a65f68cefceb62455b5a6a89fa53ab38f"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602624"
|
||||
|
||||
[tools.opentofu."platforms.linux-x64-musl"]
|
||||
checksum = "sha256:81836d0f12b4fe9013b85586349f993def9429b6383bb77cdd6c2f3a9d9aac24"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_linux_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646677"
|
||||
checksum = "sha256:a6894d45ae7a17ce83189cce8fe04b5a65f68cefceb62455b5a6a89fa53ab38f"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_linux_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602624"
|
||||
|
||||
[tools.opentofu."platforms.macos-arm64"]
|
||||
checksum = "sha256:7c06e4390d9ccd467773e37ff1c3d833c7ca0c24742cd9e9ad47284bea472247"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_darwin_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646544"
|
||||
checksum = "sha256:2ae38150a667f5c0bd57b318d18ad8091d08f93fcca40345f3d88998661de5a9"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_darwin_arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602544"
|
||||
|
||||
[tools.opentofu."platforms.macos-x64"]
|
||||
checksum = "sha256:ead1d2ce643addb4ffeb93240b9377ae1c2fd793a6bd22d65922ac37adfdf546"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_darwin_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646688"
|
||||
checksum = "sha256:1012d8f3d4567bcbcd1f2c7d766feca39a30bced32fb8be47e1887fbbee2456d"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_darwin_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602621"
|
||||
|
||||
[tools.opentofu."platforms.windows-x64"]
|
||||
checksum = "sha256:a4d86a07755c8d151f20f945e6cfb5b40deeed942af36a9bd385c5c2e965d5dd"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.4/tofu_1.12.4_windows_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/475646543"
|
||||
checksum = "sha256:af11850b496f3720e0184084c56d8b43aa74ea92d2338978bf368d70c96473f1"
|
||||
url = "https://github.com/opentofu/opentofu/releases/download/v1.12.5/tofu_1.12.5_windows_amd64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/484602547"
|
||||
|
||||
[[tools.pnpm]]
|
||||
version = "11.13.1"
|
||||
version = "11.17.0"
|
||||
backend = "aqua:pnpm/pnpm"
|
||||
|
||||
[tools.pnpm."platforms.linux-arm64"]
|
||||
checksum = "sha256:b52db99d215ed7dc9563aed815953c62a6c1ffd7cd75803d3a07ad7e4f246aed"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.13.1/pnpm-linux-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/478563983"
|
||||
checksum = "sha256:730d17de742a3efbb020ba91d7acfc0456c6ba6ad1cd8eb49f4c229fe9f504d3"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.17.0/pnpm-linux-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/487422123"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.linux-arm64-musl"]
|
||||
checksum = "sha256:2cadd4fc815c591f498a0a84c9e74a836e3e8c1236275f6e1cfd355bae6ae957"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.13.1/pnpm-linux-arm64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/478563985"
|
||||
checksum = "sha256:cc072c0e7bdd290f52fb9afdcea778ede69f96f0f4dae63623163fc11d4beec3"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.17.0/pnpm-linux-arm64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/487422121"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.linux-x64"]
|
||||
checksum = "sha256:bd6d4b0e14536207ad76bc838f5980cecd968da15f69aae0b207380cca3f2e98"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.13.1/pnpm-linux-x64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/478563986"
|
||||
checksum = "sha256:bdb1db01bf0f757495405a59a09c5c287f315889dc98d3b14bc374b9fe43a0bf"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.17.0/pnpm-linux-x64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/487422122"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.linux-x64-musl"]
|
||||
checksum = "sha256:ba19690f4ed1b64f1203ade14e9216352b46232d5582468b26a0160e0c9618c5"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.13.1/pnpm-linux-x64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/478563980"
|
||||
checksum = "sha256:db2e4eeecab336bd41bbbc7a39626b166f1a15bb189efcf6a1dafdf159f23fe7"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.17.0/pnpm-linux-x64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/487422116"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.macos-arm64"]
|
||||
checksum = "sha256:765c2bf04e8129cb58c0f946e324262e418370b35a203b50b1f06a0567ef8bc1"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.13.1/pnpm-darwin-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/478563984"
|
||||
checksum = "sha256:1e9a35d76f9d382af365d95c64f3abf7815e24350653f5bb1a37e4546265bc2b"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.17.0/pnpm-darwin-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/487422117"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.windows-x64"]
|
||||
checksum = "sha256:d8bebbc71df2702961c1d34a5e61196bc0aa3bbde33c33253f6afa3dd4546a6d"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.13.1/pnpm-win32-x64.zip"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/478563981"
|
||||
checksum = "sha256:3025c174a6dcffec14a071a5c854cb0c350a09a8c7c2857a75f75cc7b29b939c"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.17.0/pnpm-win32-x64.zip"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/487422118"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[[tools.terragrunt]]
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ config_roots = [
|
|||
|
||||
[tools]
|
||||
node = "24.15.0"
|
||||
pnpm = "11.13.1"
|
||||
pnpm = "11.17.0"
|
||||
terragrunt = "1.1.1"
|
||||
opentofu = "1.12.4"
|
||||
opentofu = "1.12.5"
|
||||
"npm:@openapitools/openapi-generator-cli" = "2.40.1"
|
||||
"npm:oazapfts" = "7.5.0"
|
||||
"github:extism/cli" = "1.6.3"
|
||||
|
|
@ -69,7 +69,7 @@ sources = [
|
|||
"patch/*",
|
||||
"bin/generate-dart-sdk.sh",
|
||||
]
|
||||
outputs = ["../mobile/openapi/lib/"]
|
||||
outputs = ["../mobile/generated/openapi/"]
|
||||
run = "bash ./bin/generate-dart-sdk.sh"
|
||||
|
||||
[tasks.open-api]
|
||||
|
|
|
|||
8
mobile/.gitignore
vendored
8
mobile/.gitignore
vendored
|
|
@ -31,6 +31,14 @@
|
|||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
lib/**/*.drift.dart
|
||||
lib/routing/router.gr.dart
|
||||
test/drift/main/generated/
|
||||
|
||||
# Pigeon related
|
||||
/lib/platform/*.g.dart
|
||||
/ios/**/*.g.swift
|
||||
/android/**/*.g.kt
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
|
|
|||
|
|
@ -26,40 +26,68 @@ linter:
|
|||
# producing the lint.
|
||||
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
unawaited_futures: true
|
||||
use_build_context_synchronously: false
|
||||
# Formatting
|
||||
avoid_print: true
|
||||
require_trailing_commas: true
|
||||
unrelated_type_equality_checks: true
|
||||
prefer_const_constructors: true
|
||||
always_use_package_imports: true
|
||||
always_put_control_body_on_new_line: true
|
||||
unnecessary_null_checks: true
|
||||
unnecessary_parenthesis: true
|
||||
prefer_final_locals: true
|
||||
prefer_const_declarations: true
|
||||
prefer_const_literals_to_create_immutables: true
|
||||
use_super_parameters: true
|
||||
directives_ordering: true
|
||||
no_leading_underscores_for_local_identifiers: true
|
||||
always_declare_return_types: true
|
||||
avoid_void_async: true
|
||||
noop_primitive_operations: true
|
||||
use_named_constants: true
|
||||
combinators_ordering: true
|
||||
avoid_multiple_declarations_per_line: true
|
||||
unnecessary_breaks: true
|
||||
|
||||
# Correctness
|
||||
no_adjacent_strings_in_list: true
|
||||
cancel_subscriptions: true
|
||||
close_sinks: true
|
||||
unawaited_futures: true
|
||||
discarded_futures: true
|
||||
no_self_assignments: true
|
||||
throw_in_finally: true
|
||||
collection_methods_unrelated_type: true
|
||||
cast_nullable_to_non_nullable: true
|
||||
|
||||
# Known issues
|
||||
avoid_slow_async_io: true
|
||||
avoid_type_to_string: true
|
||||
|
||||
# Flutter specific
|
||||
use_build_context_synchronously: true
|
||||
sized_box_for_whitespace: true
|
||||
use_colored_box: true
|
||||
use_decorated_box: true
|
||||
avoid_unnecessary_containers: true
|
||||
use_full_hex_values_for_flutter_colors: true
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
analyzer:
|
||||
exclude:
|
||||
- openapi/**
|
||||
- generated/openapi/**
|
||||
- build/**
|
||||
- lib/generated_plugin_registrant.dart
|
||||
- lib/**/*.g.dart
|
||||
- lib/**/*.drift.dart
|
||||
|
||||
# TODO: Re-enable after upgrading custom_lint
|
||||
# plugins:
|
||||
# - custom_lint
|
||||
# NOTE: We explicitly do not use riverpod_lint as there are analyzer version conflicts between
|
||||
# our Flutter version and the required old riverpod_lint 2.x
|
||||
errors:
|
||||
unawaited_futures: warning
|
||||
always_put_control_body_on_new_line: warning
|
||||
|
||||
custom_lint:
|
||||
rules:
|
||||
- avoid_build_context_in_providers: false
|
||||
- avoid_public_notifier_properties: false
|
||||
- avoid_manual_providers_as_generated_provider_dependency: false
|
||||
- unsupported_provider_value: false
|
||||
|
||||
dart_code_metrics:
|
||||
rules:
|
||||
- banned-usage:
|
||||
|
|
@ -82,3 +110,17 @@ dart_code_metrics:
|
|||
- prefer-const-border-radius
|
||||
- prefer-declaring-const-constructor
|
||||
- prefer-switch-expression
|
||||
|
||||
# Riverpod
|
||||
- avoid-calling-notifier-members-inside-build
|
||||
- avoid-notifier-constructors
|
||||
- avoid-nullable-async-value-pattern
|
||||
- avoid-public-notifier-properties
|
||||
- avoid-ref-inside-state-dispose
|
||||
- avoid-ref-read-inside-build
|
||||
- avoid-ref-watch-outside-build
|
||||
- avoid-unnecessary-consumer-widgets
|
||||
- dispose-provided-instances
|
||||
- prefer-immutable-provider-arguments
|
||||
- use-ref-and-state-synchronously
|
||||
- use-ref-read-synchronously
|
||||
|
|
|
|||
|
|
@ -1,453 +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.background
|
||||
|
||||
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 BackgroundWorkerPigeonUtils {
|
||||
|
||||
fun createConnectionError(channelName: String): FlutterError {
|
||||
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") }
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
fun doubleEquals(a: Double, b: Double): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun floatEquals(a: Float, b: Float): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun doubleHash(d: Double): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (d == 0.0) 0.0 else d
|
||||
val bits = java.lang.Double.doubleToLongBits(normalized)
|
||||
return (bits xor (bits ushr 32)).toInt()
|
||||
}
|
||||
|
||||
fun floatHash(f: Float): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (f == 0.0f) 0.0f else f
|
||||
return java.lang.Float.floatToIntBits(normalized)
|
||||
}
|
||||
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false
|
||||
}
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!doubleEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is FloatArray && b is FloatArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!floatEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!deepEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
if (a.size != b.size) return false
|
||||
val iterA = a.iterator()
|
||||
val iterB = b.iterator()
|
||||
while (iterA.hasNext() && iterB.hasNext()) {
|
||||
if (!deepEquals(iterA.next(), iterB.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
if (a.size != b.size) return false
|
||||
for (entry in a) {
|
||||
val key = entry.key
|
||||
var found = false
|
||||
for (bEntry in b) {
|
||||
if (deepEquals(key, bEntry.key)) {
|
||||
if (deepEquals(entry.value, bEntry.value)) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Double && b is Double) {
|
||||
return doubleEquals(a, b)
|
||||
}
|
||||
if (a is Float && b is Float) {
|
||||
return floatEquals(a, b)
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
fun deepHash(value: Any?): Int {
|
||||
return when (value) {
|
||||
null -> 0
|
||||
is ByteArray -> value.contentHashCode()
|
||||
is IntArray -> value.contentHashCode()
|
||||
is LongArray -> value.contentHashCode()
|
||||
is DoubleArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + doubleHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is FloatArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + floatHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Array<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is List<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var result = 0
|
||||
for (entry in value) {
|
||||
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
|
||||
}
|
||||
result
|
||||
}
|
||||
is Double -> doubleHash(value)
|
||||
is Float -> floatHash(value)
|
||||
else -> value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class BackgroundWorkerSettings (
|
||||
val requiresCharging: Boolean,
|
||||
val minimumDelaySeconds: Long
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): BackgroundWorkerSettings {
|
||||
val requiresCharging = pigeonVar_list[0] as Boolean
|
||||
val minimumDelaySeconds = pigeonVar_list[1] as Long
|
||||
return BackgroundWorkerSettings(requiresCharging, minimumDelaySeconds)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
requiresCharging,
|
||||
minimumDelaySeconds,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as BackgroundWorkerSettings
|
||||
return BackgroundWorkerPigeonUtils.deepEquals(this.requiresCharging, other.requiresCharging) && BackgroundWorkerPigeonUtils.deepEquals(this.minimumDelaySeconds, other.minimumDelaySeconds)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.requiresCharging)
|
||||
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.minimumDelaySeconds)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
BackgroundWorkerSettings.fromList(it)
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is BackgroundWorkerSettings -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface BackgroundWorkerFgHostApi {
|
||||
fun enable()
|
||||
fun saveNotificationMessage(title: String, body: String)
|
||||
fun configure(settings: BackgroundWorkerSettings)
|
||||
fun disable()
|
||||
|
||||
companion object {
|
||||
/** The codec used by BackgroundWorkerFgHostApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
BackgroundWorkerPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `BackgroundWorkerFgHostApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: BackgroundWorkerFgHostApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.enable()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val titleArg = args[0] as String
|
||||
val bodyArg = args[1] as String
|
||||
val wrapped: List<Any?> = try {
|
||||
api.saveNotificationMessage(titleArg, bodyArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val settingsArg = args[0] as BackgroundWorkerSettings
|
||||
val wrapped: List<Any?> = try {
|
||||
api.configure(settingsArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.disable()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface BackgroundWorkerBgHostApi {
|
||||
fun onInitialized()
|
||||
fun close()
|
||||
|
||||
companion object {
|
||||
/** The codec used by BackgroundWorkerBgHostApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
BackgroundWorkerPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `BackgroundWorkerBgHostApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: BackgroundWorkerBgHostApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.onInitialized$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.onInitialized()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.close()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */
|
||||
class BackgroundWorkerFlutterApi(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") {
|
||||
companion object {
|
||||
/** The codec used by BackgroundWorkerFlutterApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
BackgroundWorkerPigeonCodec()
|
||||
}
|
||||
}
|
||||
fun onIosUpload(isRefreshArg: Boolean, maxSecondsArg: Long?, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(isRefreshArg, maxSecondsArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(BackgroundWorkerPigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onAndroidUpload(maxMinutesArg: Long?, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onAndroidUpload$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(maxMinutesArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(BackgroundWorkerPigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun cancel(callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.cancel$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(null) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(BackgroundWorkerPigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +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.background
|
||||
|
||||
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 BackgroundWorkerLockPigeonUtils {
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
private open class BackgroundWorkerLockPigeonCodec : 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 BackgroundWorkerLockApi {
|
||||
fun lock()
|
||||
fun unlock()
|
||||
|
||||
companion object {
|
||||
/** The codec used by BackgroundWorkerLockApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
BackgroundWorkerLockPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `BackgroundWorkerLockApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: BackgroundWorkerLockApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.lock$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.lock()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerLockPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.unlock$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.unlock()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerLockPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,116 +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.connectivity
|
||||
|
||||
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 ConnectivityPigeonUtils {
|
||||
|
||||
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()
|
||||
|
||||
enum class NetworkCapability(val raw: Int) {
|
||||
CELLULAR(0),
|
||||
WIFI(1),
|
||||
VPN(2),
|
||||
UNMETERED(3);
|
||||
|
||||
companion object {
|
||||
fun ofRaw(raw: Int): NetworkCapability? {
|
||||
return values().firstOrNull { it.raw == raw }
|
||||
}
|
||||
}
|
||||
}
|
||||
private open class ConnectivityPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
NetworkCapability.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is NetworkCapability -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.raw.toLong())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface ConnectivityApi {
|
||||
fun getCapabilities(): List<NetworkCapability>
|
||||
|
||||
companion object {
|
||||
/** The codec used by ConnectivityApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
ConnectivityPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `ConnectivityApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: ConnectivityApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val taskQueue = binaryMessenger.makeBackgroundTaskQueue()
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities$separatedMessageChannelSuffix", codec, taskQueue)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.getCapabilities())
|
||||
} catch (exception: Throwable) {
|
||||
ConnectivityPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,451 +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.core
|
||||
|
||||
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 NetworkPigeonUtils {
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
fun doubleEquals(a: Double, b: Double): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun floatEquals(a: Float, b: Float): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun doubleHash(d: Double): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (d == 0.0) 0.0 else d
|
||||
val bits = java.lang.Double.doubleToLongBits(normalized)
|
||||
return (bits xor (bits ushr 32)).toInt()
|
||||
}
|
||||
|
||||
fun floatHash(f: Float): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (f == 0.0f) 0.0f else f
|
||||
return java.lang.Float.floatToIntBits(normalized)
|
||||
}
|
||||
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false
|
||||
}
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!doubleEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is FloatArray && b is FloatArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!floatEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!deepEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
if (a.size != b.size) return false
|
||||
val iterA = a.iterator()
|
||||
val iterB = b.iterator()
|
||||
while (iterA.hasNext() && iterB.hasNext()) {
|
||||
if (!deepEquals(iterA.next(), iterB.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
if (a.size != b.size) return false
|
||||
for (entry in a) {
|
||||
val key = entry.key
|
||||
var found = false
|
||||
for (bEntry in b) {
|
||||
if (deepEquals(key, bEntry.key)) {
|
||||
if (deepEquals(entry.value, bEntry.value)) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Double && b is Double) {
|
||||
return doubleEquals(a, b)
|
||||
}
|
||||
if (a is Float && b is Float) {
|
||||
return floatEquals(a, b)
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
fun deepHash(value: Any?): Int {
|
||||
return when (value) {
|
||||
null -> 0
|
||||
is ByteArray -> value.contentHashCode()
|
||||
is IntArray -> value.contentHashCode()
|
||||
is LongArray -> value.contentHashCode()
|
||||
is DoubleArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + doubleHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is FloatArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + floatHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Array<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is List<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var result = 0
|
||||
for (entry in value) {
|
||||
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
|
||||
}
|
||||
result
|
||||
}
|
||||
is Double -> doubleHash(value)
|
||||
is Float -> floatHash(value)
|
||||
else -> value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class ClientCertData (
|
||||
val data: ByteArray,
|
||||
val password: String
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): ClientCertData {
|
||||
val data = pigeonVar_list[0] as ByteArray
|
||||
val password = pigeonVar_list[1] as String
|
||||
return ClientCertData(data, password)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
data,
|
||||
password,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as ClientCertData
|
||||
return NetworkPigeonUtils.deepEquals(this.data, other.data) && NetworkPigeonUtils.deepEquals(this.password, other.password)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + NetworkPigeonUtils.deepHash(this.data)
|
||||
result = 31 * result + NetworkPigeonUtils.deepHash(this.password)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class ClientCertPrompt (
|
||||
val title: String,
|
||||
val message: String,
|
||||
val cancel: String,
|
||||
val confirm: String
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): ClientCertPrompt {
|
||||
val title = pigeonVar_list[0] as String
|
||||
val message = pigeonVar_list[1] as String
|
||||
val cancel = pigeonVar_list[2] as String
|
||||
val confirm = pigeonVar_list[3] as String
|
||||
return ClientCertPrompt(title, message, cancel, confirm)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
title,
|
||||
message,
|
||||
cancel,
|
||||
confirm,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as ClientCertPrompt
|
||||
return NetworkPigeonUtils.deepEquals(this.title, other.title) && NetworkPigeonUtils.deepEquals(this.message, other.message) && NetworkPigeonUtils.deepEquals(this.cancel, other.cancel) && NetworkPigeonUtils.deepEquals(this.confirm, other.confirm)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + NetworkPigeonUtils.deepHash(this.title)
|
||||
result = 31 * result + NetworkPigeonUtils.deepHash(this.message)
|
||||
result = 31 * result + NetworkPigeonUtils.deepHash(this.cancel)
|
||||
result = 31 * result + NetworkPigeonUtils.deepHash(this.confirm)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class NetworkPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ClientCertData.fromList(it)
|
||||
}
|
||||
}
|
||||
130.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ClientCertPrompt.fromList(it)
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is ClientCertData -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is ClientCertPrompt -> {
|
||||
stream.write(130)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface NetworkApi {
|
||||
fun addCertificate(clientData: ClientCertData, callback: (Result<Unit>) -> Unit)
|
||||
fun selectCertificate(promptText: ClientCertPrompt, callback: (Result<Unit>) -> Unit)
|
||||
fun removeCertificate(callback: (Result<Unit>) -> Unit)
|
||||
fun hasCertificate(): Boolean
|
||||
fun getClientPointer(): Long
|
||||
fun setRequestHeaders(headers: Map<String, String>, serverUrls: List<String>, token: String?)
|
||||
fun getAppGroupId(): String
|
||||
|
||||
companion object {
|
||||
/** The codec used by NetworkApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
NetworkPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `NetworkApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: NetworkApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.addCertificate$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val clientDataArg = args[0] as ClientCertData
|
||||
api.addCertificate(clientDataArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(NetworkPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(NetworkPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.selectCertificate$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val promptTextArg = args[0] as ClientCertPrompt
|
||||
api.selectCertificate(promptTextArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(NetworkPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(NetworkPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.removeCertificate$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.removeCertificate{ result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(NetworkPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(NetworkPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.hasCertificate$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.hasCertificate())
|
||||
} catch (exception: Throwable) {
|
||||
NetworkPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.getClientPointer$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.getClientPointer())
|
||||
} catch (exception: Throwable) {
|
||||
NetworkPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.setRequestHeaders$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val headersArg = args[0] as Map<String, String>
|
||||
val serverUrlsArg = args[1] as List<String>
|
||||
val tokenArg = args[2] as String?
|
||||
val wrapped: List<Any?> = try {
|
||||
api.setRequestHeaders(headersArg, serverUrlsArg, tokenArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
NetworkPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +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.images
|
||||
|
||||
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 LocalImagesPigeonUtils {
|
||||
|
||||
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 LocalImagesPigeonCodec : 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 LocalImageApi {
|
||||
fun requestImage(assetId: String, requestId: Long, width: Long, height: Long, isVideo: Boolean, preferEncoded: Boolean, callback: (Result<Map<String, Long>?>) -> Unit)
|
||||
fun cancelRequest(requestId: Long)
|
||||
fun getThumbhash(thumbhash: String, callback: (Result<Map<String, Long>>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by LocalImageApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
LocalImagesPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `LocalImageApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: LocalImageApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.LocalImageApi.requestImage$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val assetIdArg = args[0] as String
|
||||
val requestIdArg = args[1] as Long
|
||||
val widthArg = args[2] as Long
|
||||
val heightArg = args[3] as Long
|
||||
val isVideoArg = args[4] as Boolean
|
||||
val preferEncodedArg = args[5] as Boolean
|
||||
api.requestImage(assetIdArg, requestIdArg, widthArg, heightArg, isVideoArg, preferEncodedArg) { result: Result<Map<String, Long>?> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(LocalImagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(LocalImagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.LocalImageApi.cancelRequest$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val requestIdArg = args[0] as Long
|
||||
val wrapped: List<Any?> = try {
|
||||
api.cancelRequest(requestIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
LocalImagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.LocalImageApi.getThumbhash$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val thumbhashArg = args[0] as String
|
||||
api.getThumbhash(thumbhashArg) { result: Result<Map<String, Long>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(LocalImagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(LocalImagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +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.images
|
||||
|
||||
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 RemoteImagesPigeonUtils {
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
private open class RemoteImagesPigeonCodec : 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 RemoteImageApi {
|
||||
fun requestImage(url: String, requestId: Long, preferEncoded: Boolean, callback: (Result<Map<String, Long>?>) -> Unit)
|
||||
fun cancelRequest(requestId: Long)
|
||||
fun clearCache(callback: (Result<Long>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by RemoteImageApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
RemoteImagesPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `RemoteImageApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: RemoteImageApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.RemoteImageApi.requestImage$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val urlArg = args[0] as String
|
||||
val requestIdArg = args[1] as Long
|
||||
val preferEncodedArg = args[2] as Boolean
|
||||
api.requestImage(urlArg, requestIdArg, preferEncodedArg) { result: Result<Map<String, Long>?> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(RemoteImagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(RemoteImagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.RemoteImageApi.cancelRequest$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val requestIdArg = args[0] as Long
|
||||
val wrapped: List<Any?> = try {
|
||||
api.cancelRequest(requestIdArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
RemoteImagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.RemoteImageApi.clearCache$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.clearCache{ result: Result<Long> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(RemoteImagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(RemoteImagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,169 +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()
|
||||
|
||||
enum class PermissionStatus(val raw: Int) {
|
||||
GRANTED(0),
|
||||
DENIED(1),
|
||||
PERMANENTLY_DENIED(2);
|
||||
|
||||
companion object {
|
||||
fun ofRaw(raw: Int): PermissionStatus? {
|
||||
return values().firstOrNull { it.raw == raw }
|
||||
}
|
||||
}
|
||||
}
|
||||
private open class PermissionApiPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
PermissionStatus.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is PermissionStatus -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.raw.toLong())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface PermissionApi {
|
||||
fun isIgnoringBatteryOptimizations(): PermissionStatus
|
||||
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.isIgnoringBatteryOptimizations$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.isIgnoringBatteryOptimizations())
|
||||
} 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.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,823 +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.sync
|
||||
|
||||
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 MessagesPigeonUtils {
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
fun doubleEquals(a: Double, b: Double): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun floatEquals(a: Float, b: Float): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun doubleHash(d: Double): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (d == 0.0) 0.0 else d
|
||||
val bits = java.lang.Double.doubleToLongBits(normalized)
|
||||
return (bits xor (bits ushr 32)).toInt()
|
||||
}
|
||||
|
||||
fun floatHash(f: Float): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (f == 0.0f) 0.0f else f
|
||||
return java.lang.Float.floatToIntBits(normalized)
|
||||
}
|
||||
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false
|
||||
}
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!doubleEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is FloatArray && b is FloatArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!floatEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!deepEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
if (a.size != b.size) return false
|
||||
val iterA = a.iterator()
|
||||
val iterB = b.iterator()
|
||||
while (iterA.hasNext() && iterB.hasNext()) {
|
||||
if (!deepEquals(iterA.next(), iterB.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
if (a.size != b.size) return false
|
||||
for (entry in a) {
|
||||
val key = entry.key
|
||||
var found = false
|
||||
for (bEntry in b) {
|
||||
if (deepEquals(key, bEntry.key)) {
|
||||
if (deepEquals(entry.value, bEntry.value)) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Double && b is Double) {
|
||||
return doubleEquals(a, b)
|
||||
}
|
||||
if (a is Float && b is Float) {
|
||||
return floatEquals(a, b)
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
fun deepHash(value: Any?): Int {
|
||||
return when (value) {
|
||||
null -> 0
|
||||
is ByteArray -> value.contentHashCode()
|
||||
is IntArray -> value.contentHashCode()
|
||||
is LongArray -> value.contentHashCode()
|
||||
is DoubleArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + doubleHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is FloatArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + floatHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Array<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is List<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var result = 0
|
||||
for (entry in value) {
|
||||
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
|
||||
}
|
||||
result
|
||||
}
|
||||
is Double -> doubleHash(value)
|
||||
is Float -> floatHash(value)
|
||||
else -> value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
enum class PlatformAssetPlaybackStyle(val raw: Int) {
|
||||
UNKNOWN(0),
|
||||
IMAGE(1),
|
||||
VIDEO(2),
|
||||
IMAGE_ANIMATED(3),
|
||||
LIVE_PHOTO(4),
|
||||
VIDEO_LOOPING(5);
|
||||
|
||||
companion object {
|
||||
fun ofRaw(raw: Int): PlatformAssetPlaybackStyle? {
|
||||
return values().firstOrNull { it.raw == raw }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class PlatformAsset (
|
||||
val id: String,
|
||||
val name: String,
|
||||
val type: Long,
|
||||
val createdAt: Long? = null,
|
||||
val updatedAt: Long? = null,
|
||||
val width: Long? = null,
|
||||
val height: Long? = null,
|
||||
val durationMs: Long,
|
||||
val orientation: Long,
|
||||
val isFavorite: Boolean,
|
||||
val adjustmentTime: Long? = null,
|
||||
val latitude: Double? = null,
|
||||
val longitude: Double? = null,
|
||||
val playbackStyle: PlatformAssetPlaybackStyle
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): PlatformAsset {
|
||||
val id = pigeonVar_list[0] as String
|
||||
val name = pigeonVar_list[1] as String
|
||||
val type = pigeonVar_list[2] as Long
|
||||
val createdAt = pigeonVar_list[3] as Long?
|
||||
val updatedAt = pigeonVar_list[4] as Long?
|
||||
val width = pigeonVar_list[5] as Long?
|
||||
val height = pigeonVar_list[6] as Long?
|
||||
val durationMs = pigeonVar_list[7] as Long
|
||||
val orientation = pigeonVar_list[8] as Long
|
||||
val isFavorite = pigeonVar_list[9] as Boolean
|
||||
val adjustmentTime = pigeonVar_list[10] as Long?
|
||||
val latitude = pigeonVar_list[11] as Double?
|
||||
val longitude = pigeonVar_list[12] as Double?
|
||||
val playbackStyle = pigeonVar_list[13] as PlatformAssetPlaybackStyle
|
||||
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationMs, orientation, isFavorite, adjustmentTime, latitude, longitude, playbackStyle)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
width,
|
||||
height,
|
||||
durationMs,
|
||||
orientation,
|
||||
isFavorite,
|
||||
adjustmentTime,
|
||||
latitude,
|
||||
longitude,
|
||||
playbackStyle,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as PlatformAsset
|
||||
return MessagesPigeonUtils.deepEquals(this.id, other.id) && MessagesPigeonUtils.deepEquals(this.name, other.name) && MessagesPigeonUtils.deepEquals(this.type, other.type) && MessagesPigeonUtils.deepEquals(this.createdAt, other.createdAt) && MessagesPigeonUtils.deepEquals(this.updatedAt, other.updatedAt) && MessagesPigeonUtils.deepEquals(this.width, other.width) && MessagesPigeonUtils.deepEquals(this.height, other.height) && MessagesPigeonUtils.deepEquals(this.durationMs, other.durationMs) && MessagesPigeonUtils.deepEquals(this.orientation, other.orientation) && MessagesPigeonUtils.deepEquals(this.isFavorite, other.isFavorite) && MessagesPigeonUtils.deepEquals(this.adjustmentTime, other.adjustmentTime) && MessagesPigeonUtils.deepEquals(this.latitude, other.latitude) && MessagesPigeonUtils.deepEquals(this.longitude, other.longitude) && MessagesPigeonUtils.deepEquals(this.playbackStyle, other.playbackStyle)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.id)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.name)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.type)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.createdAt)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.updatedAt)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.width)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.height)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.durationMs)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.orientation)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.isFavorite)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.adjustmentTime)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.latitude)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.longitude)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.playbackStyle)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class PlatformAlbum (
|
||||
val id: String,
|
||||
val name: String,
|
||||
val updatedAt: Long? = null,
|
||||
val isCloud: Boolean,
|
||||
val assetCount: Long
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): PlatformAlbum {
|
||||
val id = pigeonVar_list[0] as String
|
||||
val name = pigeonVar_list[1] as String
|
||||
val updatedAt = pigeonVar_list[2] as Long?
|
||||
val isCloud = pigeonVar_list[3] as Boolean
|
||||
val assetCount = pigeonVar_list[4] as Long
|
||||
return PlatformAlbum(id, name, updatedAt, isCloud, assetCount)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
id,
|
||||
name,
|
||||
updatedAt,
|
||||
isCloud,
|
||||
assetCount,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as PlatformAlbum
|
||||
return MessagesPigeonUtils.deepEquals(this.id, other.id) && MessagesPigeonUtils.deepEquals(this.name, other.name) && MessagesPigeonUtils.deepEquals(this.updatedAt, other.updatedAt) && MessagesPigeonUtils.deepEquals(this.isCloud, other.isCloud) && MessagesPigeonUtils.deepEquals(this.assetCount, other.assetCount)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.id)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.name)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.updatedAt)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.isCloud)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetCount)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class SyncDelta (
|
||||
val hasChanges: Boolean,
|
||||
val updates: List<PlatformAsset>,
|
||||
val deletes: List<String>,
|
||||
val assetAlbums: Map<String, List<String>>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): SyncDelta {
|
||||
val hasChanges = pigeonVar_list[0] as Boolean
|
||||
val updates = pigeonVar_list[1] as List<PlatformAsset>
|
||||
val deletes = pigeonVar_list[2] as List<String>
|
||||
val assetAlbums = pigeonVar_list[3] as Map<String, List<String>>
|
||||
return SyncDelta(hasChanges, updates, deletes, assetAlbums)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
hasChanges,
|
||||
updates,
|
||||
deletes,
|
||||
assetAlbums,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as SyncDelta
|
||||
return MessagesPigeonUtils.deepEquals(this.hasChanges, other.hasChanges) && MessagesPigeonUtils.deepEquals(this.updates, other.updates) && MessagesPigeonUtils.deepEquals(this.deletes, other.deletes) && MessagesPigeonUtils.deepEquals(this.assetAlbums, other.assetAlbums)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.hasChanges)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.updates)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.deletes)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetAlbums)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class HashResult (
|
||||
val assetId: String,
|
||||
val error: String? = null,
|
||||
val hash: String? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): HashResult {
|
||||
val assetId = pigeonVar_list[0] as String
|
||||
val error = pigeonVar_list[1] as String?
|
||||
val hash = pigeonVar_list[2] as String?
|
||||
return HashResult(assetId, error, hash)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
assetId,
|
||||
error,
|
||||
hash,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as HashResult
|
||||
return MessagesPigeonUtils.deepEquals(this.assetId, other.assetId) && MessagesPigeonUtils.deepEquals(this.error, other.error) && MessagesPigeonUtils.deepEquals(this.hash, other.hash)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetId)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.error)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.hash)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class CloudIdResult (
|
||||
val assetId: String,
|
||||
val error: String? = null,
|
||||
val cloudId: String? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): CloudIdResult {
|
||||
val assetId = pigeonVar_list[0] as String
|
||||
val error = pigeonVar_list[1] as String?
|
||||
val cloudId = pigeonVar_list[2] as String?
|
||||
return CloudIdResult(assetId, error, cloudId)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
assetId,
|
||||
error,
|
||||
cloudId,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as CloudIdResult
|
||||
return MessagesPigeonUtils.deepEquals(this.assetId, other.assetId) && MessagesPigeonUtils.deepEquals(this.error, other.error) && MessagesPigeonUtils.deepEquals(this.cloudId, other.cloudId)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetId)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.error)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.cloudId)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as Long?)?.let {
|
||||
PlatformAssetPlaybackStyle.ofRaw(it.toInt())
|
||||
}
|
||||
}
|
||||
130.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
PlatformAsset.fromList(it)
|
||||
}
|
||||
}
|
||||
131.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
PlatformAlbum.fromList(it)
|
||||
}
|
||||
}
|
||||
132.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
SyncDelta.fromList(it)
|
||||
}
|
||||
}
|
||||
133.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
HashResult.fromList(it)
|
||||
}
|
||||
}
|
||||
134.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
CloudIdResult.fromList(it)
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is PlatformAssetPlaybackStyle -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.raw.toLong())
|
||||
}
|
||||
is PlatformAsset -> {
|
||||
stream.write(130)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is PlatformAlbum -> {
|
||||
stream.write(131)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is SyncDelta -> {
|
||||
stream.write(132)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is HashResult -> {
|
||||
stream.write(133)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is CloudIdResult -> {
|
||||
stream.write(134)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface NativeSyncApi {
|
||||
fun shouldFullSync(callback: (Result<Boolean>) -> Unit)
|
||||
fun getMediaChanges(callback: (Result<SyncDelta>) -> Unit)
|
||||
fun checkpointSync()
|
||||
fun clearSyncCheckpoint()
|
||||
fun getAssetIdsForAlbum(albumId: String, callback: (Result<List<String>>) -> Unit)
|
||||
fun getAlbums(callback: (Result<List<PlatformAlbum>>) -> Unit)
|
||||
fun getAssetsCountSince(albumId: String, timestamp: Long): Long
|
||||
fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?, callback: (Result<List<PlatformAsset>>) -> Unit)
|
||||
fun hashAssets(assetIds: List<String>, allowNetworkAccess: Boolean, callback: (Result<List<HashResult>>) -> Unit)
|
||||
fun cancelHashing()
|
||||
fun cancelSync()
|
||||
fun getTrashedAssets(): Map<String, List<PlatformAsset>>
|
||||
fun restoreFromTrashById(mediaId: String, type: Long, callback: (Result<Boolean>) -> Unit)
|
||||
fun getCloudIdForAssetIds(assetIds: List<String>): List<CloudIdResult>
|
||||
|
||||
companion object {
|
||||
/** The codec used by NativeSyncApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
MessagesPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `NativeSyncApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: NativeSyncApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val taskQueue = binaryMessenger.makeBackgroundTaskQueue()
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.shouldFullSync$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.shouldFullSync{ 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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getMediaChanges$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.getMediaChanges{ result: Result<SyncDelta> ->
|
||||
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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.checkpointSync$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.checkpointSync()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.clearSyncCheckpoint$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.clearSyncCheckpoint()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetIdsForAlbum$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val albumIdArg = args[0] as String
|
||||
api.getAssetIdsForAlbum(albumIdArg) { result: Result<List<String>> ->
|
||||
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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAlbums$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.getAlbums{ result: Result<List<PlatformAlbum>> ->
|
||||
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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetsCountSince$separatedMessageChannelSuffix", codec, taskQueue)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val albumIdArg = args[0] as String
|
||||
val timestampArg = args[1] as Long
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.getAssetsCountSince(albumIdArg, timestampArg))
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetsForAlbum$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val albumIdArg = args[0] as String
|
||||
val updatedTimeCondArg = args[1] as Long?
|
||||
api.getAssetsForAlbum(albumIdArg, updatedTimeCondArg) { result: Result<List<PlatformAsset>> ->
|
||||
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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets$separatedMessageChannelSuffix", codec, taskQueue)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val assetIdsArg = args[0] as List<String>
|
||||
val allowNetworkAccessArg = args[1] as Boolean
|
||||
api.hashAssets(assetIdsArg, allowNetworkAccessArg) { result: Result<List<HashResult>> ->
|
||||
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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.cancelHashing()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelSync$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
api.cancelSync()
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssets$separatedMessageChannelSuffix", codec, taskQueue)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.getTrashedAssets())
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
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 {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getCloudIdForAssetIds$separatedMessageChannelSuffix", codec, taskQueue)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val assetIdsArg = args[0] as List<String>
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.getCloudIdForAssetIds(assetIdsArg))
|
||||
} catch (exception: Throwable) {
|
||||
MessagesPigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
|||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.ext.SdkExtensions
|
||||
|
|
@ -30,6 +29,8 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.security.MessageDigest
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
|
|
@ -377,7 +378,11 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
|
|||
)?.use { cursor -> cursor.count.toLong() } ?: 0L
|
||||
|
||||
|
||||
fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?, callback: (Result<List<PlatformAsset>>) -> Unit) {
|
||||
fun getAssetsForAlbum(
|
||||
albumId: String,
|
||||
updatedTimeCond: Long?,
|
||||
callback: (Result<List<PlatformAsset>>) -> Unit
|
||||
) {
|
||||
runSync(callback) { getAssetsForAlbum(albumId, updatedTimeCond) }
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +424,7 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
|
|||
}.awaitAll()
|
||||
|
||||
completeWhenActive(callback, Result.success(results))
|
||||
} catch (e: CancellationException) {
|
||||
} catch (_: CancellationException) {
|
||||
completeWhenActive(
|
||||
callback, Result.failure(
|
||||
FlutterError(
|
||||
|
|
@ -437,23 +442,20 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
|
|||
|
||||
private suspend fun hashAsset(assetId: String): HashResult {
|
||||
return try {
|
||||
val assetUri = ContentUris.withAppendedId(
|
||||
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
|
||||
assetId.toLong()
|
||||
)
|
||||
|
||||
val digest = MessageDigest.getInstance("SHA-1")
|
||||
ctx.contentResolver.openInputStream(assetUri)?.use { inputStream ->
|
||||
var bytesRead: Int
|
||||
openOriginalStream(assetId).use { inputStream ->
|
||||
val buffer = ByteArray(HASH_BUFFER_SIZE)
|
||||
while (inputStream.read(buffer).also { bytesRead = it } > 0) {
|
||||
while (true) {
|
||||
val bytesRead = inputStream.read(buffer)
|
||||
if (bytesRead == -1) break
|
||||
currentCoroutineContext().ensureActive()
|
||||
digest.update(buffer, 0, bytesRead)
|
||||
}
|
||||
} ?: return HashResult(assetId, "Cannot open input stream for asset", null)
|
||||
}
|
||||
|
||||
val hashString = Base64.encodeToString(digest.digest(), Base64.NO_WRAP)
|
||||
HashResult(assetId, null, hashString)
|
||||
HashResult(assetId, null, Base64.encodeToString(digest.digest(), Base64.NO_WRAP))
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: SecurityException) {
|
||||
HashResult(assetId, "Permission denied accessing asset: ${e.message}", null)
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -461,6 +463,37 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
|
|||
}
|
||||
}
|
||||
|
||||
private fun openOriginalStream(assetId: String): InputStream {
|
||||
val id = assetId.toLong()
|
||||
val collection = when (getMediaType(id)) {
|
||||
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
else -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||
}
|
||||
val uri = ContentUris.withAppendedId(collection, id)
|
||||
val original = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
MediaStore.setRequireOriginal(uri)
|
||||
} else {
|
||||
uri
|
||||
}
|
||||
|
||||
return ctx.contentResolver.openInputStream(original)
|
||||
?: throw IOException("Cannot open original stream for asset $assetId")
|
||||
}
|
||||
|
||||
private fun getMediaType(id: Long): Int =
|
||||
getCursor(
|
||||
MediaStore.VOLUME_EXTERNAL,
|
||||
"${MediaStore.MediaColumns._ID} = ?",
|
||||
arrayOf(id.toString()),
|
||||
arrayOf(MediaStore.Files.FileColumns.MEDIA_TYPE)
|
||||
)?.use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MEDIA_TYPE))
|
||||
} else {
|
||||
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
|
||||
}
|
||||
} ?: MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
|
||||
|
||||
fun cancelHashing() {
|
||||
hashTask?.cancel()
|
||||
hashTask = null
|
||||
|
|
@ -476,8 +509,11 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
|
|||
syncJob = CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
completeWhenActive(callback, Result.success(work()))
|
||||
} catch (e: CancellationException) {
|
||||
completeWhenActive(callback, Result.failure(FlutterError(SYNC_CANCELLED_CODE, "Sync cancelled", null)))
|
||||
} catch (_: CancellationException) {
|
||||
completeWhenActive(
|
||||
callback,
|
||||
Result.failure(FlutterError(SYNC_CANCELLED_CODE, "Sync cancelled", null))
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
completeWhenActive(callback, Result.failure(e))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,292 +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.viewintent
|
||||
|
||||
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 ViewIntentPigeonUtils {
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
fun doubleEquals(a: Double, b: Double): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun floatEquals(a: Float, b: Float): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun doubleHash(d: Double): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (d == 0.0) 0.0 else d
|
||||
val bits = java.lang.Double.doubleToLongBits(normalized)
|
||||
return (bits xor (bits ushr 32)).toInt()
|
||||
}
|
||||
|
||||
fun floatHash(f: Float): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (f == 0.0f) 0.0f else f
|
||||
return java.lang.Float.floatToIntBits(normalized)
|
||||
}
|
||||
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false
|
||||
}
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!doubleEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is FloatArray && b is FloatArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!floatEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!deepEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
if (a.size != b.size) return false
|
||||
val iterA = a.iterator()
|
||||
val iterB = b.iterator()
|
||||
while (iterA.hasNext() && iterB.hasNext()) {
|
||||
if (!deepEquals(iterA.next(), iterB.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
if (a.size != b.size) return false
|
||||
for (entry in a) {
|
||||
val key = entry.key
|
||||
var found = false
|
||||
for (bEntry in b) {
|
||||
if (deepEquals(key, bEntry.key)) {
|
||||
if (deepEquals(entry.value, bEntry.value)) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Double && b is Double) {
|
||||
return doubleEquals(a, b)
|
||||
}
|
||||
if (a is Float && b is Float) {
|
||||
return floatEquals(a, b)
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
fun deepHash(value: Any?): Int {
|
||||
return when (value) {
|
||||
null -> 0
|
||||
is ByteArray -> value.contentHashCode()
|
||||
is IntArray -> value.contentHashCode()
|
||||
is LongArray -> value.contentHashCode()
|
||||
is DoubleArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + doubleHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is FloatArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + floatHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Array<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is List<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var result = 0
|
||||
for (entry in value) {
|
||||
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
|
||||
}
|
||||
result
|
||||
}
|
||||
is Double -> doubleHash(value)
|
||||
is Float -> floatHash(value)
|
||||
else -> value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class ViewIntentPayload (
|
||||
val path: String? = null,
|
||||
val mimeType: String,
|
||||
val localAssetId: String? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): ViewIntentPayload {
|
||||
val path = pigeonVar_list[0] as String?
|
||||
val mimeType = pigeonVar_list[1] as String
|
||||
val localAssetId = pigeonVar_list[2] as String?
|
||||
return ViewIntentPayload(path, mimeType, localAssetId)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
path,
|
||||
mimeType,
|
||||
localAssetId,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as ViewIntentPayload
|
||||
return ViewIntentPigeonUtils.deepEquals(this.path, other.path) && ViewIntentPigeonUtils.deepEquals(this.mimeType, other.mimeType) && ViewIntentPigeonUtils.deepEquals(this.localAssetId, other.localAssetId)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + ViewIntentPigeonUtils.deepHash(this.path)
|
||||
result = 31 * result + ViewIntentPigeonUtils.deepHash(this.mimeType)
|
||||
result = 31 * result + ViewIntentPigeonUtils.deepHash(this.localAssetId)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class ViewIntentPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
ViewIntentPayload.fromList(it)
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
when (value) {
|
||||
is ViewIntentPayload -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface ViewIntentHostApi {
|
||||
fun consumeViewIntent(callback: (Result<ViewIntentPayload?>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by ViewIntentHostApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
ViewIntentPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `ViewIntentHostApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: ViewIntentHostApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ViewIntentHostApi.consumeViewIntent$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.consumeViewIntent{ result: Result<ViewIntentPayload?> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(ViewIntentPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(ViewIntentPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// ignore_for_file: avoid_print
|
||||
// ignore_for_file: avoid_slow_async_io, avoid_print
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
|
|
|||
418
mobile/ios/Runner/Background/BackgroundWorker.g.swift
generated
418
mobile/ios/Runner/Background/BackgroundWorker.g.swift
generated
|
|
@ -1,418 +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 createConnectionError(withChannelName channelName: String) -> PigeonError {
|
||||
return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "")
|
||||
}
|
||||
|
||||
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?
|
||||
}
|
||||
|
||||
private func doubleEqualsBackgroundWorker(_ lhs: Double, _ rhs: Double) -> Bool {
|
||||
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
|
||||
}
|
||||
|
||||
private func doubleHashBackgroundWorker(_ value: Double, _ hasher: inout Hasher) {
|
||||
if value.isNaN {
|
||||
hasher.combine(0x7FF8000000000000)
|
||||
} else {
|
||||
// Normalize -0.0 to 0.0
|
||||
hasher.combine(value == 0 ? 0 : value)
|
||||
}
|
||||
}
|
||||
|
||||
func deepEqualsBackgroundWorker(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
let cleanLhs = nilOrValue(lhs) as Any?
|
||||
let cleanRhs = nilOrValue(rhs) as Any?
|
||||
switch (cleanLhs, cleanRhs) {
|
||||
case (nil, nil):
|
||||
return true
|
||||
|
||||
case (nil, _), (_, nil):
|
||||
return false
|
||||
|
||||
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
|
||||
return true
|
||||
|
||||
case is (Void, Void):
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !deepEqualsBackgroundWorker(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Double], [Double]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !doubleEqualsBackgroundWorker(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard lhsDictionary.count == rhsDictionary.count else { return false }
|
||||
for (lhsKey, lhsValue) in lhsDictionary {
|
||||
var found = false
|
||||
for (rhsKey, rhsValue) in rhsDictionary {
|
||||
if deepEqualsBackgroundWorker(lhsKey, rhsKey) {
|
||||
if deepEqualsBackgroundWorker(lhsValue, rhsValue) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found { return false }
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhs as Double, let rhs as Double):
|
||||
return doubleEqualsBackgroundWorker(lhs, rhs)
|
||||
|
||||
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
|
||||
return lhsHashable == rhsHashable
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func deepHashBackgroundWorker(value: Any?, hasher: inout Hasher) {
|
||||
let cleanValue = nilOrValue(value) as Any?
|
||||
if let cleanValue = cleanValue {
|
||||
if let doubleValue = cleanValue as? Double {
|
||||
doubleHashBackgroundWorker(doubleValue, &hasher)
|
||||
} else if let valueList = cleanValue as? [Any?] {
|
||||
for item in valueList {
|
||||
deepHashBackgroundWorker(value: item, hasher: &hasher)
|
||||
}
|
||||
} else if let valueList = cleanValue as? [Double] {
|
||||
for item in valueList {
|
||||
doubleHashBackgroundWorker(item, &hasher)
|
||||
}
|
||||
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
|
||||
var result = 0
|
||||
for (key, value) in valueDict {
|
||||
var entryKeyHasher = Hasher()
|
||||
deepHashBackgroundWorker(value: key, hasher: &entryKeyHasher)
|
||||
var entryValueHasher = Hasher()
|
||||
deepHashBackgroundWorker(value: value, hasher: &entryValueHasher)
|
||||
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
|
||||
}
|
||||
hasher.combine(result)
|
||||
} else if let hashableValue = cleanValue as? AnyHashable {
|
||||
hasher.combine(hashableValue)
|
||||
} else {
|
||||
hasher.combine(String(describing: cleanValue))
|
||||
}
|
||||
} else {
|
||||
hasher.combine(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct BackgroundWorkerSettings: Hashable {
|
||||
var requiresCharging: Bool
|
||||
var minimumDelaySeconds: Int64
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> BackgroundWorkerSettings? {
|
||||
let requiresCharging = pigeonVar_list[0] as! Bool
|
||||
let minimumDelaySeconds = pigeonVar_list[1] as! Int64
|
||||
|
||||
return BackgroundWorkerSettings(
|
||||
requiresCharging: requiresCharging,
|
||||
minimumDelaySeconds: minimumDelaySeconds
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
requiresCharging,
|
||||
minimumDelaySeconds,
|
||||
]
|
||||
}
|
||||
static func == (lhs: BackgroundWorkerSettings, rhs: BackgroundWorkerSettings) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsBackgroundWorker(lhs.requiresCharging, rhs.requiresCharging) && deepEqualsBackgroundWorker(lhs.minimumDelaySeconds, rhs.minimumDelaySeconds)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("BackgroundWorkerSettings")
|
||||
deepHashBackgroundWorker(value: requiresCharging, hasher: &hasher)
|
||||
deepHashBackgroundWorker(value: minimumDelaySeconds, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
private class BackgroundWorkerPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
return BackgroundWorkerSettings.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BackgroundWorkerPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? BackgroundWorkerSettings {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BackgroundWorkerPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return BackgroundWorkerPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return BackgroundWorkerPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class BackgroundWorkerPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = BackgroundWorkerPigeonCodec(readerWriter: BackgroundWorkerPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol BackgroundWorkerFgHostApi {
|
||||
func enable() throws
|
||||
func saveNotificationMessage(title: String, body: String) throws
|
||||
func configure(settings: BackgroundWorkerSettings) throws
|
||||
func disable() throws
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class BackgroundWorkerFgHostApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { BackgroundWorkerPigeonCodec.shared }
|
||||
/// Sets up an instance of `BackgroundWorkerFgHostApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: BackgroundWorkerFgHostApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let enableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
enableChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.enable()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enableChannel.setMessageHandler(nil)
|
||||
}
|
||||
let saveNotificationMessageChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
saveNotificationMessageChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let titleArg = args[0] as! String
|
||||
let bodyArg = args[1] as! String
|
||||
do {
|
||||
try api.saveNotificationMessage(title: titleArg, body: bodyArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
saveNotificationMessageChannel.setMessageHandler(nil)
|
||||
}
|
||||
let configureChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
configureChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let settingsArg = args[0] as! BackgroundWorkerSettings
|
||||
do {
|
||||
try api.configure(settings: settingsArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
configureChannel.setMessageHandler(nil)
|
||||
}
|
||||
let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
disableChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.disable()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disableChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol BackgroundWorkerBgHostApi {
|
||||
func onInitialized() throws
|
||||
func close() throws
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class BackgroundWorkerBgHostApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { BackgroundWorkerPigeonCodec.shared }
|
||||
/// Sets up an instance of `BackgroundWorkerBgHostApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: BackgroundWorkerBgHostApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let onInitializedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.onInitialized\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
onInitializedChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.onInitialized()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
onInitializedChannel.setMessageHandler(nil)
|
||||
}
|
||||
let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
closeChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.close()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
closeChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||
protocol BackgroundWorkerFlutterApiProtocol {
|
||||
func onIosUpload(isRefresh isRefreshArg: Bool, maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func onAndroidUpload(maxMinutes maxMinutesArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
func cancel(completion: @escaping (Result<Void, PigeonError>) -> Void)
|
||||
}
|
||||
class BackgroundWorkerFlutterApi: BackgroundWorkerFlutterApiProtocol {
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
private let messageChannelSuffix: String
|
||||
init(binaryMessenger: FlutterBinaryMessenger, messageChannelSuffix: String = "") {
|
||||
self.binaryMessenger = binaryMessenger
|
||||
self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
}
|
||||
var codec: BackgroundWorkerPigeonCodec {
|
||||
return BackgroundWorkerPigeonCodec.shared
|
||||
}
|
||||
func onIosUpload(isRefresh isRefreshArg: Bool, maxSeconds maxSecondsArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([isRefreshArg, maxSecondsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
}
|
||||
if listResponse.count > 1 {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onAndroidUpload(maxMinutes maxMinutesArg: Int64?, completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onAndroidUpload\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([maxMinutesArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
}
|
||||
if listResponse.count > 1 {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func cancel(completion: @escaping (Result<Void, PigeonError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.cancel\(messageChannelSuffix)"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage(nil) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName: channelName)))
|
||||
return
|
||||
}
|
||||
if listResponse.count > 1 {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(PigeonError(code: code, message: message, details: details)))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
mobile/ios/Runner/Connectivity/Connectivity.g.swift
generated
129
mobile/ios/Runner/Connectivity/Connectivity.g.swift
generated
|
|
@ -1,129 +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?
|
||||
}
|
||||
|
||||
|
||||
enum NetworkCapability: Int {
|
||||
case cellular = 0
|
||||
case wifi = 1
|
||||
case vpn = 2
|
||||
case unmetered = 3
|
||||
}
|
||||
|
||||
private class ConnectivityPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
|
||||
if let enumResultAsInt = enumResultAsInt {
|
||||
return NetworkCapability(rawValue: enumResultAsInt)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ConnectivityPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? NetworkCapability {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.rawValue)
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ConnectivityPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return ConnectivityPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return ConnectivityPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectivityPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = ConnectivityPigeonCodec(readerWriter: ConnectivityPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol ConnectivityApi {
|
||||
func getCapabilities() throws -> [NetworkCapability]
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class ConnectivityApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { ConnectivityPigeonCodec.shared }
|
||||
/// Sets up an instance of `ConnectivityApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: ConnectivityApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
#if os(iOS)
|
||||
let taskQueue = binaryMessenger.makeBackgroundTaskQueue?()
|
||||
#else
|
||||
let taskQueue: FlutterTaskQueue? = nil
|
||||
#endif
|
||||
let getCapabilitiesChannel = taskQueue == nil
|
||||
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||
if let api = api {
|
||||
getCapabilitiesChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
let result = try api.getCapabilities()
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getCapabilitiesChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
406
mobile/ios/Runner/Core/Network.g.swift
generated
406
mobile/ios/Runner/Core/Network.g.swift
generated
|
|
@ -1,406 +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?
|
||||
}
|
||||
|
||||
private func doubleEqualsNetwork(_ lhs: Double, _ rhs: Double) -> Bool {
|
||||
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
|
||||
}
|
||||
|
||||
private func doubleHashNetwork(_ value: Double, _ hasher: inout Hasher) {
|
||||
if value.isNaN {
|
||||
hasher.combine(0x7FF8000000000000)
|
||||
} else {
|
||||
// Normalize -0.0 to 0.0
|
||||
hasher.combine(value == 0 ? 0 : value)
|
||||
}
|
||||
}
|
||||
|
||||
func deepEqualsNetwork(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
let cleanLhs = nilOrValue(lhs) as Any?
|
||||
let cleanRhs = nilOrValue(rhs) as Any?
|
||||
switch (cleanLhs, cleanRhs) {
|
||||
case (nil, nil):
|
||||
return true
|
||||
|
||||
case (nil, _), (_, nil):
|
||||
return false
|
||||
|
||||
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
|
||||
return true
|
||||
|
||||
case is (Void, Void):
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !deepEqualsNetwork(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Double], [Double]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !doubleEqualsNetwork(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard lhsDictionary.count == rhsDictionary.count else { return false }
|
||||
for (lhsKey, lhsValue) in lhsDictionary {
|
||||
var found = false
|
||||
for (rhsKey, rhsValue) in rhsDictionary {
|
||||
if deepEqualsNetwork(lhsKey, rhsKey) {
|
||||
if deepEqualsNetwork(lhsValue, rhsValue) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found { return false }
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhs as Double, let rhs as Double):
|
||||
return doubleEqualsNetwork(lhs, rhs)
|
||||
|
||||
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
|
||||
return lhsHashable == rhsHashable
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func deepHashNetwork(value: Any?, hasher: inout Hasher) {
|
||||
let cleanValue = nilOrValue(value) as Any?
|
||||
if let cleanValue = cleanValue {
|
||||
if let doubleValue = cleanValue as? Double {
|
||||
doubleHashNetwork(doubleValue, &hasher)
|
||||
} else if let valueList = cleanValue as? [Any?] {
|
||||
for item in valueList {
|
||||
deepHashNetwork(value: item, hasher: &hasher)
|
||||
}
|
||||
} else if let valueList = cleanValue as? [Double] {
|
||||
for item in valueList {
|
||||
doubleHashNetwork(item, &hasher)
|
||||
}
|
||||
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
|
||||
var result = 0
|
||||
for (key, value) in valueDict {
|
||||
var entryKeyHasher = Hasher()
|
||||
deepHashNetwork(value: key, hasher: &entryKeyHasher)
|
||||
var entryValueHasher = Hasher()
|
||||
deepHashNetwork(value: value, hasher: &entryValueHasher)
|
||||
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
|
||||
}
|
||||
hasher.combine(result)
|
||||
} else if let hashableValue = cleanValue as? AnyHashable {
|
||||
hasher.combine(hashableValue)
|
||||
} else {
|
||||
hasher.combine(String(describing: cleanValue))
|
||||
}
|
||||
} else {
|
||||
hasher.combine(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct ClientCertData: Hashable {
|
||||
var data: FlutterStandardTypedData
|
||||
var password: String
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> ClientCertData? {
|
||||
let data = pigeonVar_list[0] as! FlutterStandardTypedData
|
||||
let password = pigeonVar_list[1] as! String
|
||||
|
||||
return ClientCertData(
|
||||
data: data,
|
||||
password: password
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
data,
|
||||
password,
|
||||
]
|
||||
}
|
||||
static func == (lhs: ClientCertData, rhs: ClientCertData) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsNetwork(lhs.data, rhs.data) && deepEqualsNetwork(lhs.password, rhs.password)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("ClientCertData")
|
||||
deepHashNetwork(value: data, hasher: &hasher)
|
||||
deepHashNetwork(value: password, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct ClientCertPrompt: Hashable {
|
||||
var title: String
|
||||
var message: String
|
||||
var cancel: String
|
||||
var confirm: String
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> ClientCertPrompt? {
|
||||
let title = pigeonVar_list[0] as! String
|
||||
let message = pigeonVar_list[1] as! String
|
||||
let cancel = pigeonVar_list[2] as! String
|
||||
let confirm = pigeonVar_list[3] as! String
|
||||
|
||||
return ClientCertPrompt(
|
||||
title: title,
|
||||
message: message,
|
||||
cancel: cancel,
|
||||
confirm: confirm
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
title,
|
||||
message,
|
||||
cancel,
|
||||
confirm,
|
||||
]
|
||||
}
|
||||
static func == (lhs: ClientCertPrompt, rhs: ClientCertPrompt) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsNetwork(lhs.title, rhs.title) && deepEqualsNetwork(lhs.message, rhs.message) && deepEqualsNetwork(lhs.cancel, rhs.cancel) && deepEqualsNetwork(lhs.confirm, rhs.confirm)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("ClientCertPrompt")
|
||||
deepHashNetwork(value: title, hasher: &hasher)
|
||||
deepHashNetwork(value: message, hasher: &hasher)
|
||||
deepHashNetwork(value: cancel, hasher: &hasher)
|
||||
deepHashNetwork(value: confirm, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
return ClientCertData.fromList(self.readValue() as! [Any?])
|
||||
case 130:
|
||||
return ClientCertPrompt.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? ClientCertData {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? ClientCertPrompt {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return NetworkPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return NetworkPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = NetworkPigeonCodec(readerWriter: NetworkPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol NetworkApi {
|
||||
func addCertificate(clientData: ClientCertData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func selectCertificate(promptText: ClientCertPrompt, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func removeCertificate(completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func hasCertificate() throws -> Bool
|
||||
func getClientPointer() throws -> Int64
|
||||
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`.
|
||||
class NetworkApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { NetworkPigeonCodec.shared }
|
||||
/// Sets up an instance of `NetworkApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: NetworkApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let addCertificateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.addCertificate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
addCertificateChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let clientDataArg = args[0] as! ClientCertData
|
||||
api.addCertificate(clientData: clientDataArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addCertificateChannel.setMessageHandler(nil)
|
||||
}
|
||||
let selectCertificateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.selectCertificate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
selectCertificateChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let promptTextArg = args[0] as! ClientCertPrompt
|
||||
api.selectCertificate(promptText: promptTextArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selectCertificateChannel.setMessageHandler(nil)
|
||||
}
|
||||
let removeCertificateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.removeCertificate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
removeCertificateChannel.setMessageHandler { _, reply in
|
||||
api.removeCertificate { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeCertificateChannel.setMessageHandler(nil)
|
||||
}
|
||||
let hasCertificateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.hasCertificate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
hasCertificateChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
let result = try api.hasCertificate()
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hasCertificateChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getClientPointerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.getClientPointer\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getClientPointerChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
let result = try api.getClientPointer()
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getClientPointerChannel.setMessageHandler(nil)
|
||||
}
|
||||
let setRequestHeadersChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.setRequestHeaders\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
setRequestHeadersChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let headersArg = args[0] as! [String: String]
|
||||
let serverUrlsArg = args[1] as! [String]
|
||||
let tokenArg: String? = nilOrValue(args[2])
|
||||
do {
|
||||
try api.setRequestHeaders(headers: headersArg, serverUrls: serverUrlsArg, token: tokenArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
139
mobile/ios/Runner/Images/LocalImages.g.swift
generated
139
mobile/ios/Runner/Images/LocalImages.g.swift
generated
|
|
@ -1,139 +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?
|
||||
}
|
||||
|
||||
|
||||
private class LocalImagesPigeonCodecReader: FlutterStandardReader {
|
||||
}
|
||||
|
||||
private class LocalImagesPigeonCodecWriter: FlutterStandardWriter {
|
||||
}
|
||||
|
||||
private class LocalImagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return LocalImagesPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return LocalImagesPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class LocalImagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = LocalImagesPigeonCodec(readerWriter: LocalImagesPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol LocalImageApi {
|
||||
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, preferEncoded: Bool, completion: @escaping (Result<[String: Int64]?, Error>) -> Void)
|
||||
func cancelRequest(requestId: Int64) throws
|
||||
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class LocalImageApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { LocalImagesPigeonCodec.shared }
|
||||
/// Sets up an instance of `LocalImageApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: LocalImageApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let requestImageChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.LocalImageApi.requestImage\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
requestImageChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let assetIdArg = args[0] as! String
|
||||
let requestIdArg = args[1] as! Int64
|
||||
let widthArg = args[2] as! Int64
|
||||
let heightArg = args[3] as! Int64
|
||||
let isVideoArg = args[4] as! Bool
|
||||
let preferEncodedArg = args[5] as! Bool
|
||||
api.requestImage(assetId: assetIdArg, requestId: requestIdArg, width: widthArg, height: heightArg, isVideo: isVideoArg, preferEncoded: preferEncodedArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
requestImageChannel.setMessageHandler(nil)
|
||||
}
|
||||
let cancelRequestChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.LocalImageApi.cancelRequest\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
cancelRequestChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let requestIdArg = args[0] as! Int64
|
||||
do {
|
||||
try api.cancelRequest(requestId: requestIdArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancelRequestChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getThumbhashChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.LocalImageApi.getThumbhash\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getThumbhashChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let thumbhashArg = args[0] as! String
|
||||
api.getThumbhash(thumbhash: thumbhashArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getThumbhashChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ class LocalImageApiImpl: LocalImageApi {
|
|||
requestOptions.version = .current
|
||||
return requestOptions
|
||||
}()
|
||||
private static let maxPixelSize: CGFloat = 16384
|
||||
|
||||
private static let registry = RequestRegistry<ImageRequest>()
|
||||
|
||||
|
|
@ -108,11 +109,16 @@ class LocalImageApiImpl: LocalImageApi {
|
|||
]))
|
||||
}
|
||||
|
||||
let isOriginal = !(width > 0 && height > 0)
|
||||
let targetSize = isOriginal
|
||||
? CGSize(width: Self.maxPixelSize, height: Self.maxPixelSize)
|
||||
: CGSize(width: Double(width), height: Double(height))
|
||||
let contentMode: PHImageContentMode = isOriginal ? .aspectFit : .aspectFill
|
||||
var image: UIImage?
|
||||
Self.imageManager.requestImage(
|
||||
for: asset,
|
||||
targetSize: width > 0 && height > 0 ? CGSize(width: Double(width), height: Double(height)) : PHImageManagerMaximumSize,
|
||||
contentMode: .aspectFill,
|
||||
targetSize: targetSize,
|
||||
contentMode: contentMode,
|
||||
options: Self.requestOptions,
|
||||
resultHandler: { (_image, info) -> Void in
|
||||
image = _image
|
||||
|
|
@ -123,12 +129,38 @@ class LocalImageApiImpl: LocalImageApi {
|
|||
return request.completion(ImageProcessing.cancelledResult)
|
||||
}
|
||||
|
||||
guard let image = image,
|
||||
let cgImage = image.cgImage else {
|
||||
guard let fastImage = image,
|
||||
var cgImage = fastImage.cgImage else {
|
||||
Self.registry.remove(requestId: requestId)
|
||||
return request.completion(.failure(PigeonError(code: "", message: "Could not get pixel data for \(assetId)", details: nil)))
|
||||
}
|
||||
|
||||
// .fast can return larger than the target, so retry with .exact to guarantee the bound.
|
||||
if max(cgImage.width, cgImage.height) > Int(Self.maxPixelSize) {
|
||||
let exactOptions = Self.requestOptions.copy() as! PHImageRequestOptions
|
||||
exactOptions.resizeMode = .exact
|
||||
image = nil
|
||||
Self.imageManager.requestImage(
|
||||
for: asset,
|
||||
targetSize: targetSize,
|
||||
contentMode: contentMode,
|
||||
options: exactOptions,
|
||||
resultHandler: { (_image, info) -> Void in
|
||||
image = _image
|
||||
}
|
||||
)
|
||||
|
||||
if request.isCancelled {
|
||||
return request.completion(ImageProcessing.cancelledResult)
|
||||
}
|
||||
|
||||
guard let exactImage = image?.cgImage else {
|
||||
Self.registry.remove(requestId: requestId)
|
||||
return request.completion(.failure(PigeonError(code: "", message: "Could not resize image for \(assetId)", details: nil)))
|
||||
}
|
||||
cgImage = exactImage
|
||||
}
|
||||
|
||||
if request.isCancelled {
|
||||
return request.completion(ImageProcessing.cancelledResult)
|
||||
}
|
||||
|
|
|
|||
134
mobile/ios/Runner/Images/RemoteImages.g.swift
generated
134
mobile/ios/Runner/Images/RemoteImages.g.swift
generated
|
|
@ -1,134 +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?
|
||||
}
|
||||
|
||||
|
||||
private class RemoteImagesPigeonCodecReader: FlutterStandardReader {
|
||||
}
|
||||
|
||||
private class RemoteImagesPigeonCodecWriter: FlutterStandardWriter {
|
||||
}
|
||||
|
||||
private class RemoteImagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return RemoteImagesPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return RemoteImagesPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteImagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = RemoteImagesPigeonCodec(readerWriter: RemoteImagesPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol RemoteImageApi {
|
||||
func requestImage(url: String, requestId: Int64, preferEncoded: Bool, completion: @escaping (Result<[String: Int64]?, Error>) -> Void)
|
||||
func cancelRequest(requestId: Int64) throws
|
||||
func clearCache(completion: @escaping (Result<Int64, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class RemoteImageApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { RemoteImagesPigeonCodec.shared }
|
||||
/// Sets up an instance of `RemoteImageApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: RemoteImageApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let requestImageChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.RemoteImageApi.requestImage\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
requestImageChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let urlArg = args[0] as! String
|
||||
let requestIdArg = args[1] as! Int64
|
||||
let preferEncodedArg = args[2] as! Bool
|
||||
api.requestImage(url: urlArg, requestId: requestIdArg, preferEncoded: preferEncodedArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
requestImageChannel.setMessageHandler(nil)
|
||||
}
|
||||
let cancelRequestChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.RemoteImageApi.cancelRequest\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
cancelRequestChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let requestIdArg = args[0] as! Int64
|
||||
do {
|
||||
try api.cancelRequest(requestId: requestIdArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancelRequestChannel.setMessageHandler(nil)
|
||||
}
|
||||
let clearCacheChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.RemoteImageApi.clearCache\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
clearCacheChannel.setMessageHandler { _, reply in
|
||||
api.clearCache { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clearCacheChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
168
mobile/ios/Runner/Permission/PermissionApi.g.swift
generated
168
mobile/ios/Runner/Permission/PermissionApi.g.swift
generated
|
|
@ -1,168 +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?
|
||||
}
|
||||
|
||||
|
||||
enum PermissionStatus: Int {
|
||||
case granted = 0
|
||||
case denied = 1
|
||||
case permanentlyDenied = 2
|
||||
}
|
||||
|
||||
private class PermissionApiPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
|
||||
if let enumResultAsInt = enumResultAsInt {
|
||||
return PermissionStatus(rawValue: enumResultAsInt)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PermissionApiPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? PermissionStatus {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.rawValue)
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PermissionApiPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return PermissionApiPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return PermissionApiPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class PermissionApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = PermissionApiPigeonCodec(readerWriter: PermissionApiPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol PermissionApi {
|
||||
func isIgnoringBatteryOptimizations() throws -> PermissionStatus
|
||||
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 { PermissionApiPigeonCodec.shared }
|
||||
/// 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 isIgnoringBatteryOptimizationsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.PermissionApi.isIgnoringBatteryOptimizations\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
isIgnoringBatteryOptimizationsChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
let result = try api.isIgnoringBatteryOptimizations()
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isIgnoringBatteryOptimizationsChannel.setMessageHandler(nil)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
777
mobile/ios/Runner/Sync/Messages.g.swift
generated
777
mobile/ios/Runner/Sync/Messages.g.swift
generated
|
|
@ -1,777 +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
|
||||
|
||||
/// Error class for passing custom error details to Dart side.
|
||||
final class PigeonError: Error {
|
||||
let code: String
|
||||
let message: String?
|
||||
let details: Sendable?
|
||||
|
||||
init(code: String, message: String?, details: Sendable?) {
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.details = details
|
||||
}
|
||||
|
||||
var localizedDescription: String {
|
||||
return
|
||||
"PigeonError(code: \(code), message: \(message ?? "<nil>"), details: \(details ?? "<nil>")"
|
||||
}
|
||||
}
|
||||
|
||||
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?
|
||||
}
|
||||
|
||||
private func doubleEqualsMessages(_ lhs: Double, _ rhs: Double) -> Bool {
|
||||
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
|
||||
}
|
||||
|
||||
private func doubleHashMessages(_ value: Double, _ hasher: inout Hasher) {
|
||||
if value.isNaN {
|
||||
hasher.combine(0x7FF8000000000000)
|
||||
} else {
|
||||
// Normalize -0.0 to 0.0
|
||||
hasher.combine(value == 0 ? 0 : value)
|
||||
}
|
||||
}
|
||||
|
||||
func deepEqualsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
let cleanLhs = nilOrValue(lhs) as Any?
|
||||
let cleanRhs = nilOrValue(rhs) as Any?
|
||||
switch (cleanLhs, cleanRhs) {
|
||||
case (nil, nil):
|
||||
return true
|
||||
|
||||
case (nil, _), (_, nil):
|
||||
return false
|
||||
|
||||
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
|
||||
return true
|
||||
|
||||
case is (Void, Void):
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !deepEqualsMessages(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Double], [Double]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !doubleEqualsMessages(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard lhsDictionary.count == rhsDictionary.count else { return false }
|
||||
for (lhsKey, lhsValue) in lhsDictionary {
|
||||
var found = false
|
||||
for (rhsKey, rhsValue) in rhsDictionary {
|
||||
if deepEqualsMessages(lhsKey, rhsKey) {
|
||||
if deepEqualsMessages(lhsValue, rhsValue) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found { return false }
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhs as Double, let rhs as Double):
|
||||
return doubleEqualsMessages(lhs, rhs)
|
||||
|
||||
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
|
||||
return lhsHashable == rhsHashable
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func deepHashMessages(value: Any?, hasher: inout Hasher) {
|
||||
let cleanValue = nilOrValue(value) as Any?
|
||||
if let cleanValue = cleanValue {
|
||||
if let doubleValue = cleanValue as? Double {
|
||||
doubleHashMessages(doubleValue, &hasher)
|
||||
} else if let valueList = cleanValue as? [Any?] {
|
||||
for item in valueList {
|
||||
deepHashMessages(value: item, hasher: &hasher)
|
||||
}
|
||||
} else if let valueList = cleanValue as? [Double] {
|
||||
for item in valueList {
|
||||
doubleHashMessages(item, &hasher)
|
||||
}
|
||||
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
|
||||
var result = 0
|
||||
for (key, value) in valueDict {
|
||||
var entryKeyHasher = Hasher()
|
||||
deepHashMessages(value: key, hasher: &entryKeyHasher)
|
||||
var entryValueHasher = Hasher()
|
||||
deepHashMessages(value: value, hasher: &entryValueHasher)
|
||||
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
|
||||
}
|
||||
hasher.combine(result)
|
||||
} else if let hashableValue = cleanValue as? AnyHashable {
|
||||
hasher.combine(hashableValue)
|
||||
} else {
|
||||
hasher.combine(String(describing: cleanValue))
|
||||
}
|
||||
} else {
|
||||
hasher.combine(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum PlatformAssetPlaybackStyle: Int {
|
||||
case unknown = 0
|
||||
case image = 1
|
||||
case video = 2
|
||||
case imageAnimated = 3
|
||||
case livePhoto = 4
|
||||
case videoLooping = 5
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct PlatformAsset: Hashable {
|
||||
var id: String
|
||||
var name: String
|
||||
var type: Int64
|
||||
var createdAt: Int64? = nil
|
||||
var updatedAt: Int64? = nil
|
||||
var width: Int64? = nil
|
||||
var height: Int64? = nil
|
||||
var durationMs: Int64
|
||||
var orientation: Int64
|
||||
var isFavorite: Bool
|
||||
var adjustmentTime: Int64? = nil
|
||||
var latitude: Double? = nil
|
||||
var longitude: Double? = nil
|
||||
var playbackStyle: PlatformAssetPlaybackStyle
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> PlatformAsset? {
|
||||
let id = pigeonVar_list[0] as! String
|
||||
let name = pigeonVar_list[1] as! String
|
||||
let type = pigeonVar_list[2] as! Int64
|
||||
let createdAt: Int64? = nilOrValue(pigeonVar_list[3])
|
||||
let updatedAt: Int64? = nilOrValue(pigeonVar_list[4])
|
||||
let width: Int64? = nilOrValue(pigeonVar_list[5])
|
||||
let height: Int64? = nilOrValue(pigeonVar_list[6])
|
||||
let durationMs = pigeonVar_list[7] as! Int64
|
||||
let orientation = pigeonVar_list[8] as! Int64
|
||||
let isFavorite = pigeonVar_list[9] as! Bool
|
||||
let adjustmentTime: Int64? = nilOrValue(pigeonVar_list[10])
|
||||
let latitude: Double? = nilOrValue(pigeonVar_list[11])
|
||||
let longitude: Double? = nilOrValue(pigeonVar_list[12])
|
||||
let playbackStyle = pigeonVar_list[13] as! PlatformAssetPlaybackStyle
|
||||
|
||||
return PlatformAsset(
|
||||
id: id,
|
||||
name: name,
|
||||
type: type,
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt,
|
||||
width: width,
|
||||
height: height,
|
||||
durationMs: durationMs,
|
||||
orientation: orientation,
|
||||
isFavorite: isFavorite,
|
||||
adjustmentTime: adjustmentTime,
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
playbackStyle: playbackStyle
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
width,
|
||||
height,
|
||||
durationMs,
|
||||
orientation,
|
||||
isFavorite,
|
||||
adjustmentTime,
|
||||
latitude,
|
||||
longitude,
|
||||
playbackStyle,
|
||||
]
|
||||
}
|
||||
static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.id, rhs.id) && deepEqualsMessages(lhs.name, rhs.name) && deepEqualsMessages(lhs.type, rhs.type) && deepEqualsMessages(lhs.createdAt, rhs.createdAt) && deepEqualsMessages(lhs.updatedAt, rhs.updatedAt) && deepEqualsMessages(lhs.width, rhs.width) && deepEqualsMessages(lhs.height, rhs.height) && deepEqualsMessages(lhs.durationMs, rhs.durationMs) && deepEqualsMessages(lhs.orientation, rhs.orientation) && deepEqualsMessages(lhs.isFavorite, rhs.isFavorite) && deepEqualsMessages(lhs.adjustmentTime, rhs.adjustmentTime) && deepEqualsMessages(lhs.latitude, rhs.latitude) && deepEqualsMessages(lhs.longitude, rhs.longitude) && deepEqualsMessages(lhs.playbackStyle, rhs.playbackStyle)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("PlatformAsset")
|
||||
deepHashMessages(value: id, hasher: &hasher)
|
||||
deepHashMessages(value: name, hasher: &hasher)
|
||||
deepHashMessages(value: type, hasher: &hasher)
|
||||
deepHashMessages(value: createdAt, hasher: &hasher)
|
||||
deepHashMessages(value: updatedAt, hasher: &hasher)
|
||||
deepHashMessages(value: width, hasher: &hasher)
|
||||
deepHashMessages(value: height, hasher: &hasher)
|
||||
deepHashMessages(value: durationMs, hasher: &hasher)
|
||||
deepHashMessages(value: orientation, hasher: &hasher)
|
||||
deepHashMessages(value: isFavorite, hasher: &hasher)
|
||||
deepHashMessages(value: adjustmentTime, hasher: &hasher)
|
||||
deepHashMessages(value: latitude, hasher: &hasher)
|
||||
deepHashMessages(value: longitude, hasher: &hasher)
|
||||
deepHashMessages(value: playbackStyle, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct PlatformAlbum: Hashable {
|
||||
var id: String
|
||||
var name: String
|
||||
var updatedAt: Int64? = nil
|
||||
var isCloud: Bool
|
||||
var assetCount: Int64
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> PlatformAlbum? {
|
||||
let id = pigeonVar_list[0] as! String
|
||||
let name = pigeonVar_list[1] as! String
|
||||
let updatedAt: Int64? = nilOrValue(pigeonVar_list[2])
|
||||
let isCloud = pigeonVar_list[3] as! Bool
|
||||
let assetCount = pigeonVar_list[4] as! Int64
|
||||
|
||||
return PlatformAlbum(
|
||||
id: id,
|
||||
name: name,
|
||||
updatedAt: updatedAt,
|
||||
isCloud: isCloud,
|
||||
assetCount: assetCount
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
id,
|
||||
name,
|
||||
updatedAt,
|
||||
isCloud,
|
||||
assetCount,
|
||||
]
|
||||
}
|
||||
static func == (lhs: PlatformAlbum, rhs: PlatformAlbum) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.id, rhs.id) && deepEqualsMessages(lhs.name, rhs.name) && deepEqualsMessages(lhs.updatedAt, rhs.updatedAt) && deepEqualsMessages(lhs.isCloud, rhs.isCloud) && deepEqualsMessages(lhs.assetCount, rhs.assetCount)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("PlatformAlbum")
|
||||
deepHashMessages(value: id, hasher: &hasher)
|
||||
deepHashMessages(value: name, hasher: &hasher)
|
||||
deepHashMessages(value: updatedAt, hasher: &hasher)
|
||||
deepHashMessages(value: isCloud, hasher: &hasher)
|
||||
deepHashMessages(value: assetCount, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct SyncDelta: Hashable {
|
||||
var hasChanges: Bool
|
||||
var updates: [PlatformAsset]
|
||||
var deletes: [String]
|
||||
var assetAlbums: [String: [String]]
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> SyncDelta? {
|
||||
let hasChanges = pigeonVar_list[0] as! Bool
|
||||
let updates = pigeonVar_list[1] as! [PlatformAsset]
|
||||
let deletes = pigeonVar_list[2] as! [String]
|
||||
let assetAlbums = pigeonVar_list[3] as! [String: [String]]
|
||||
|
||||
return SyncDelta(
|
||||
hasChanges: hasChanges,
|
||||
updates: updates,
|
||||
deletes: deletes,
|
||||
assetAlbums: assetAlbums
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
hasChanges,
|
||||
updates,
|
||||
deletes,
|
||||
assetAlbums,
|
||||
]
|
||||
}
|
||||
static func == (lhs: SyncDelta, rhs: SyncDelta) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.hasChanges, rhs.hasChanges) && deepEqualsMessages(lhs.updates, rhs.updates) && deepEqualsMessages(lhs.deletes, rhs.deletes) && deepEqualsMessages(lhs.assetAlbums, rhs.assetAlbums)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("SyncDelta")
|
||||
deepHashMessages(value: hasChanges, hasher: &hasher)
|
||||
deepHashMessages(value: updates, hasher: &hasher)
|
||||
deepHashMessages(value: deletes, hasher: &hasher)
|
||||
deepHashMessages(value: assetAlbums, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct HashResult: Hashable {
|
||||
var assetId: String
|
||||
var error: String? = nil
|
||||
var hash: String? = nil
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> HashResult? {
|
||||
let assetId = pigeonVar_list[0] as! String
|
||||
let error: String? = nilOrValue(pigeonVar_list[1])
|
||||
let hash: String? = nilOrValue(pigeonVar_list[2])
|
||||
|
||||
return HashResult(
|
||||
assetId: assetId,
|
||||
error: error,
|
||||
hash: hash
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
assetId,
|
||||
error,
|
||||
hash,
|
||||
]
|
||||
}
|
||||
static func == (lhs: HashResult, rhs: HashResult) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.assetId, rhs.assetId) && deepEqualsMessages(lhs.error, rhs.error) && deepEqualsMessages(lhs.hash, rhs.hash)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("HashResult")
|
||||
deepHashMessages(value: assetId, hasher: &hasher)
|
||||
deepHashMessages(value: error, hasher: &hasher)
|
||||
deepHashMessages(value: hash, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct CloudIdResult: Hashable {
|
||||
var assetId: String
|
||||
var error: String? = nil
|
||||
var cloudId: String? = nil
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> CloudIdResult? {
|
||||
let assetId = pigeonVar_list[0] as! String
|
||||
let error: String? = nilOrValue(pigeonVar_list[1])
|
||||
let cloudId: String? = nilOrValue(pigeonVar_list[2])
|
||||
|
||||
return CloudIdResult(
|
||||
assetId: assetId,
|
||||
error: error,
|
||||
cloudId: cloudId
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
assetId,
|
||||
error,
|
||||
cloudId,
|
||||
]
|
||||
}
|
||||
static func == (lhs: CloudIdResult, rhs: CloudIdResult) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.assetId, rhs.assetId) && deepEqualsMessages(lhs.error, rhs.error) && deepEqualsMessages(lhs.cloudId, rhs.cloudId)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("CloudIdResult")
|
||||
deepHashMessages(value: assetId, hasher: &hasher)
|
||||
deepHashMessages(value: error, hasher: &hasher)
|
||||
deepHashMessages(value: cloudId, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
|
||||
if let enumResultAsInt = enumResultAsInt {
|
||||
return PlatformAssetPlaybackStyle(rawValue: enumResultAsInt)
|
||||
}
|
||||
return nil
|
||||
case 130:
|
||||
return PlatformAsset.fromList(self.readValue() as! [Any?])
|
||||
case 131:
|
||||
return PlatformAlbum.fromList(self.readValue() as! [Any?])
|
||||
case 132:
|
||||
return SyncDelta.fromList(self.readValue() as! [Any?])
|
||||
case 133:
|
||||
return HashResult.fromList(self.readValue() as! [Any?])
|
||||
case 134:
|
||||
return CloudIdResult.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? PlatformAssetPlaybackStyle {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.rawValue)
|
||||
} else if let value = value as? PlatformAsset {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? PlatformAlbum {
|
||||
super.writeByte(131)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? SyncDelta {
|
||||
super.writeByte(132)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? HashResult {
|
||||
super.writeByte(133)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? CloudIdResult {
|
||||
super.writeByte(134)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return MessagesPigeonCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return MessagesPigeonCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter())
|
||||
}
|
||||
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol NativeSyncApi {
|
||||
func shouldFullSync(completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func getMediaChanges(completion: @escaping (Result<SyncDelta, Error>) -> Void)
|
||||
func checkpointSync() throws
|
||||
func clearSyncCheckpoint() throws
|
||||
func getAssetIdsForAlbum(albumId: String, completion: @escaping (Result<[String], Error>) -> Void)
|
||||
func getAlbums(completion: @escaping (Result<[PlatformAlbum], Error>) -> Void)
|
||||
func getAssetsCountSince(albumId: String, timestamp: Int64) throws -> Int64
|
||||
func getAssetsForAlbum(albumId: String, updatedTimeCond: Int64?, completion: @escaping (Result<[PlatformAsset], Error>) -> Void)
|
||||
func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void)
|
||||
func cancelHashing() throws
|
||||
func cancelSync() throws
|
||||
func getTrashedAssets() throws -> [String: [PlatformAsset]]
|
||||
func restoreFromTrashById(mediaId: String, type: Int64, completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func getCloudIdForAssetIds(assetIds: [String]) throws -> [CloudIdResult]
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class NativeSyncApiSetup {
|
||||
static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared }
|
||||
/// Sets up an instance of `NativeSyncApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: NativeSyncApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
#if os(iOS)
|
||||
let taskQueue = binaryMessenger.makeBackgroundTaskQueue?()
|
||||
#else
|
||||
let taskQueue: FlutterTaskQueue? = nil
|
||||
#endif
|
||||
let shouldFullSyncChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.shouldFullSync\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
shouldFullSyncChannel.setMessageHandler { _, reply in
|
||||
api.shouldFullSync { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shouldFullSyncChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getMediaChangesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getMediaChanges\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getMediaChangesChannel.setMessageHandler { _, reply in
|
||||
api.getMediaChanges { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getMediaChangesChannel.setMessageHandler(nil)
|
||||
}
|
||||
let checkpointSyncChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.checkpointSync\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
checkpointSyncChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.checkpointSync()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
checkpointSyncChannel.setMessageHandler(nil)
|
||||
}
|
||||
let clearSyncCheckpointChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.clearSyncCheckpoint\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
clearSyncCheckpointChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.clearSyncCheckpoint()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clearSyncCheckpointChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getAssetIdsForAlbumChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetIdsForAlbum\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getAssetIdsForAlbumChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let albumIdArg = args[0] as! String
|
||||
api.getAssetIdsForAlbum(albumId: albumIdArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getAssetIdsForAlbumChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getAlbumsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAlbums\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getAlbumsChannel.setMessageHandler { _, reply in
|
||||
api.getAlbums { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getAlbumsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getAssetsCountSinceChannel = taskQueue == nil
|
||||
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetsCountSince\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetsCountSince\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||
if let api = api {
|
||||
getAssetsCountSinceChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let albumIdArg = args[0] as! String
|
||||
let timestampArg = args[1] as! Int64
|
||||
do {
|
||||
let result = try api.getAssetsCountSince(albumId: albumIdArg, timestamp: timestampArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getAssetsCountSinceChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getAssetsForAlbumChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getAssetsForAlbum\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getAssetsForAlbumChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let albumIdArg = args[0] as! String
|
||||
let updatedTimeCondArg: Int64? = nilOrValue(args[1])
|
||||
api.getAssetsForAlbum(albumId: albumIdArg, updatedTimeCond: updatedTimeCondArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getAssetsForAlbumChannel.setMessageHandler(nil)
|
||||
}
|
||||
let hashAssetsChannel = taskQueue == nil
|
||||
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||
if let api = api {
|
||||
hashAssetsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let assetIdsArg = args[0] as! [String]
|
||||
let allowNetworkAccessArg = args[1] as! Bool
|
||||
api.hashAssets(assetIds: assetIdsArg, allowNetworkAccess: allowNetworkAccessArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hashAssetsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let cancelHashingChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
cancelHashingChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.cancelHashing()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancelHashingChannel.setMessageHandler(nil)
|
||||
}
|
||||
let cancelSyncChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelSync\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
cancelSyncChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.cancelSync()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancelSyncChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getTrashedAssetsChannel = taskQueue == nil
|
||||
? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
: FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.getTrashedAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue)
|
||||
if let api = api {
|
||||
getTrashedAssetsChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
let result = try api.getTrashedAssets()
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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
|
||||
? 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)
|
||||
if let api = api {
|
||||
getCloudIdForAssetIdsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let assetIdsArg = args[0] as! [String]
|
||||
do {
|
||||
let result = try api.getCloudIdForAssetIds(assetIds: assetIdsArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getCloudIdForAssetIdsChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,13 +12,15 @@ struct ImageEntry: TimelineEntry {
|
|||
var subtitle: String? = nil
|
||||
var error: WidgetError? = nil
|
||||
var deepLink: URL? = nil
|
||||
var forceFullColor: Bool = true
|
||||
}
|
||||
|
||||
static func build(
|
||||
api: ImmichAPI,
|
||||
asset: Asset,
|
||||
dateOffset: Int,
|
||||
subtitle: String? = nil
|
||||
subtitle: String? = nil,
|
||||
forceFullColor: Bool = true
|
||||
)
|
||||
async throws -> Self
|
||||
{
|
||||
|
|
@ -34,7 +36,8 @@ struct ImageEntry: TimelineEntry {
|
|||
image: image,
|
||||
metadata: EntryMetadata(
|
||||
subtitle: subtitle,
|
||||
deepLink: asset.deepLink
|
||||
deepLink: asset.deepLink,
|
||||
forceFullColor: forceFullColor
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -111,12 +114,26 @@ struct ImageEntry: TimelineEntry {
|
|||
|
||||
}
|
||||
|
||||
// Required so that we can decode older versions of the metadata
|
||||
extension ImageEntry.Metadata {
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
subtitle = try container.decodeIfPresent(String.self, forKey: .subtitle)
|
||||
error = try container.decodeIfPresent(WidgetError.self, forKey: .error)
|
||||
deepLink = try container.decodeIfPresent(URL.self, forKey: .deepLink)
|
||||
|
||||
forceFullColor =
|
||||
try container.decodeIfPresent(Bool.self, forKey: .forceFullColor) ?? true
|
||||
}
|
||||
}
|
||||
|
||||
func generateRandomEntries(
|
||||
api: ImmichAPI,
|
||||
now: Date,
|
||||
count: Int,
|
||||
filter: SearchFilter = Album.NONE.filter,
|
||||
subtitle: String? = nil
|
||||
subtitle: String? = nil,
|
||||
forceFullColor: Bool = true
|
||||
)
|
||||
async throws -> [ImageEntry]
|
||||
{
|
||||
|
|
@ -132,7 +149,8 @@ func generateRandomEntries(
|
|||
api: api,
|
||||
asset: asset,
|
||||
dateOffset: dateOffset,
|
||||
subtitle: subtitle
|
||||
subtitle: subtitle,
|
||||
forceFullColor: forceFullColor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ import WidgetKit
|
|||
|
||||
extension Image {
|
||||
@ViewBuilder
|
||||
func tintedWidgetImageModifier() -> some View {
|
||||
func tintedWidgetImageModifier(forceFullColor: Bool) -> some View {
|
||||
if #available(iOS 18.0, *) {
|
||||
self
|
||||
.widgetAccentedRenderingMode(.accentedDesaturated)
|
||||
.widgetAccentedRenderingMode(forceFullColor ? .accentedDesaturated : .fullColor)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
|
|
@ -18,15 +18,24 @@ struct ImmichWidgetView: View {
|
|||
|
||||
var body: some View {
|
||||
if let image = entry.image {
|
||||
ImmichWidgetContentView(image: image, subtitle: entry.metadata.subtitle, deepLink: entry.metadata.deepLink)
|
||||
ImmichWidgetContentView(
|
||||
image: image,
|
||||
subtitle: entry.metadata.subtitle,
|
||||
deepLink: entry.metadata.deepLink,
|
||||
forceFullColor: entry.metadata.forceFullColor
|
||||
)
|
||||
} else {
|
||||
ImmichWidgetLoadingView(message: entry.metadata.error?.errorDescription)
|
||||
ImmichWidgetLoadingView(
|
||||
message: entry.metadata.error?.errorDescription,
|
||||
forceFullColor: entry.metadata.forceFullColor
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct ImmichWidgetLoadingView: View {
|
||||
let message: String?
|
||||
let forceFullColor: Bool
|
||||
|
||||
var body: some View {
|
||||
let messageText = Text(message ?? "")
|
||||
|
|
@ -39,7 +48,7 @@ private struct ImmichWidgetLoadingView: View {
|
|||
messageText.hidden()
|
||||
|
||||
Image("LaunchImage")
|
||||
.tintedWidgetImageModifier()
|
||||
.tintedWidgetImageModifier(forceFullColor: forceFullColor)
|
||||
|
||||
messageText
|
||||
}
|
||||
|
|
@ -50,13 +59,14 @@ private struct ImmichWidgetContentView: View {
|
|||
let image: UIImage
|
||||
let subtitle: String?
|
||||
let deepLink: URL?
|
||||
let forceFullColor: Bool
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .leading) {
|
||||
Color.clear.overlay(
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.tintedWidgetImageModifier()
|
||||
.tintedWidgetImageModifier(forceFullColor: forceFullColor)
|
||||
.scaledToFill()
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,21 @@ import AppIntents
|
|||
import SwiftUI
|
||||
import WidgetKit
|
||||
|
||||
struct ImmichMemoryProvider: TimelineProvider {
|
||||
// MARK: Widget Configuration
|
||||
|
||||
struct MemoryConfigurationAppIntent: WidgetConfigurationIntent {
|
||||
static var title: LocalizedStringResource { "Memories" }
|
||||
static var description: IntentDescription {
|
||||
"See memories from Immich."
|
||||
}
|
||||
|
||||
@Parameter(title: "Always Display in Full Color", default: false)
|
||||
var forceFullColor: Bool
|
||||
}
|
||||
|
||||
// MARK: Provider
|
||||
|
||||
struct ImmichMemoryProvider: AppIntentTimelineProvider {
|
||||
func getYearDifferenceSubtitle(assetYear: Int) -> String {
|
||||
let currentYear = Calendar.current.component(.year, from: Date.now)
|
||||
// construct a "X years ago" subtitle
|
||||
|
|
@ -15,144 +29,132 @@ struct ImmichMemoryProvider: TimelineProvider {
|
|||
ImageEntry(date: Date(), image: nil)
|
||||
}
|
||||
|
||||
func getSnapshot(
|
||||
in context: Context,
|
||||
completion: @escaping @Sendable (ImageEntry) -> Void
|
||||
) {
|
||||
func snapshot(
|
||||
for configuration: MemoryConfigurationAppIntent,
|
||||
in context: Context
|
||||
) async -> ImageEntry {
|
||||
let cacheKey = "memory_\(context.family.rawValue)"
|
||||
|
||||
Task {
|
||||
guard let api = try? await ImmichAPI() else {
|
||||
completion(
|
||||
ImageEntry.handleError(for: cacheKey, error: .noLogin).entries.first!
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
guard let memories = try? await api.fetchMemory(for: Date.now)
|
||||
else {
|
||||
completion(ImageEntry.handleError(for: cacheKey).entries.first!)
|
||||
return
|
||||
}
|
||||
|
||||
for memory in memories {
|
||||
if let asset = memory.assets.first(where: { $0.type == .image }),
|
||||
let entry = try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: asset,
|
||||
dateOffset: 0,
|
||||
subtitle: getYearDifferenceSubtitle(assetYear: memory.data.year)
|
||||
)
|
||||
{
|
||||
completion(entry)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to random image
|
||||
guard
|
||||
let randomImage = try? await api.fetchSearchResults().first,
|
||||
let imageEntry = try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: randomImage,
|
||||
dateOffset: 0
|
||||
)
|
||||
else {
|
||||
completion(ImageEntry.handleError(for: cacheKey).entries.first!)
|
||||
return
|
||||
}
|
||||
|
||||
completion(imageEntry)
|
||||
guard let api = try? await ImmichAPI() else {
|
||||
return ImageEntry.handleError(for: cacheKey, error: .noLogin).entries
|
||||
.first!
|
||||
}
|
||||
|
||||
guard let memories = try? await api.fetchMemory(for: Date.now) else {
|
||||
return ImageEntry.handleError(for: cacheKey).entries.first!
|
||||
}
|
||||
|
||||
for memory in memories {
|
||||
if let asset = memory.assets.first(where: { $0.type == .image }),
|
||||
let entry = try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: asset,
|
||||
dateOffset: 0,
|
||||
subtitle: getYearDifferenceSubtitle(assetYear: memory.data.year),
|
||||
forceFullColor: configuration.forceFullColor
|
||||
)
|
||||
{
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to random image
|
||||
guard
|
||||
let randomImage = try? await api.fetchSearchResults().first,
|
||||
let imageEntry = try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: randomImage,
|
||||
dateOffset: 0,
|
||||
forceFullColor: configuration.forceFullColor
|
||||
)
|
||||
else {
|
||||
return ImageEntry.handleError(for: cacheKey).entries.first!
|
||||
}
|
||||
|
||||
return imageEntry
|
||||
}
|
||||
|
||||
func getTimeline(
|
||||
in context: Context,
|
||||
completion: @escaping @Sendable (Timeline<ImageEntry>) -> Void
|
||||
) {
|
||||
Task {
|
||||
var entries: [ImageEntry] = []
|
||||
let now = Date()
|
||||
func timeline(
|
||||
for configuration: MemoryConfigurationAppIntent,
|
||||
in context: Context
|
||||
) async
|
||||
-> Timeline<ImageEntry>
|
||||
{
|
||||
var entries: [ImageEntry] = []
|
||||
let now = Date()
|
||||
|
||||
let cacheKey = "memory_\(context.family.rawValue)"
|
||||
let cacheKey = "memory_\(context.family.rawValue)"
|
||||
|
||||
guard let api = try? await ImmichAPI() else {
|
||||
completion(
|
||||
ImageEntry.handleError(for: cacheKey, error: .noLogin)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
let memories: [MemoryResult]
|
||||
do {
|
||||
memories = try await api.fetchMemory(for: Date.now)
|
||||
|
||||
await withTaskGroup(of: ImageEntry?.self) { group in
|
||||
var totalAssets = 0
|
||||
|
||||
for memory in memories {
|
||||
for asset in memory.assets {
|
||||
if asset.type == .image && totalAssets < 12 {
|
||||
group.addTask {
|
||||
try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: asset,
|
||||
dateOffset: totalAssets,
|
||||
subtitle: getYearDifferenceSubtitle(
|
||||
assetYear: memory.data.year
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
totalAssets += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for await result in group {
|
||||
if let entry = result {
|
||||
entries.append(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
completion(ImageEntry.handleError(for: cacheKey))
|
||||
return
|
||||
}
|
||||
|
||||
// If we didn't add any memory images (some failure occurred or no images in memory),
|
||||
// default to 12 hours of random photos
|
||||
if entries.count == 0 {
|
||||
// this must be a do/catch since we need to
|
||||
// distinguish between a network fail and an empty search
|
||||
do {
|
||||
let search = try await generateRandomEntries(
|
||||
api: api,
|
||||
now: now,
|
||||
count: 12
|
||||
)
|
||||
|
||||
// Load or save a cached asset for when network conditions are bad
|
||||
if search.count == 0 {
|
||||
completion(
|
||||
ImageEntry.handleError(for: cacheKey, error: .noAssetsAvailable)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
entries.append(contentsOf: search)
|
||||
} catch {
|
||||
completion(ImageEntry.handleError(for: cacheKey))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// cache the last image
|
||||
try? entries.last!.cache(for: cacheKey)
|
||||
|
||||
completion(Timeline(entries: entries, policy: .atEnd))
|
||||
guard let api = try? await ImmichAPI() else {
|
||||
return ImageEntry.handleError(for: cacheKey, error: .noLogin)
|
||||
}
|
||||
|
||||
let memories: [MemoryResult]
|
||||
do {
|
||||
memories = try await api.fetchMemory(for: Date.now)
|
||||
|
||||
await withTaskGroup(of: ImageEntry?.self) { group in
|
||||
var totalAssets = 0
|
||||
|
||||
for memory in memories {
|
||||
for asset in memory.assets {
|
||||
if asset.type == .image && totalAssets < 12 {
|
||||
group.addTask {
|
||||
try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: asset,
|
||||
dateOffset: totalAssets,
|
||||
subtitle: getYearDifferenceSubtitle(
|
||||
assetYear: memory.data.year
|
||||
),
|
||||
forceFullColor: configuration.forceFullColor
|
||||
)
|
||||
}
|
||||
|
||||
totalAssets += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for await result in group {
|
||||
if let entry = result {
|
||||
entries.append(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
return ImageEntry.handleError(for: cacheKey)
|
||||
}
|
||||
|
||||
// If we didn't add any memory images (some failure occurred or no images in memory),
|
||||
// default to 12 hours of random photos
|
||||
if entries.count == 0 {
|
||||
// this must be a do/catch since we need to
|
||||
// distinguish between a network fail and an empty search
|
||||
do {
|
||||
let search = try await generateRandomEntries(
|
||||
api: api,
|
||||
now: now,
|
||||
count: 12,
|
||||
forceFullColor: configuration.forceFullColor
|
||||
)
|
||||
|
||||
// Load or save a cached asset for when network conditions are bad
|
||||
if search.count == 0 {
|
||||
return ImageEntry.handleError(for: cacheKey, error: .noAssetsAvailable)
|
||||
}
|
||||
|
||||
entries.append(contentsOf: search)
|
||||
} catch {
|
||||
return ImageEntry.handleError(for: cacheKey)
|
||||
}
|
||||
}
|
||||
|
||||
// cache the last image
|
||||
try? entries.last!.cache(for: cacheKey)
|
||||
|
||||
return Timeline(entries: entries, policy: .atEnd)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,8 +162,9 @@ struct ImmichMemoryWidget: Widget {
|
|||
let kind: String = "com.immich.widget.memory"
|
||||
|
||||
var body: some WidgetConfiguration {
|
||||
StaticConfiguration(
|
||||
AppIntentConfiguration(
|
||||
kind: kind,
|
||||
intent: MemoryConfigurationAppIntent.self,
|
||||
provider: ImmichMemoryProvider()
|
||||
) { entry in
|
||||
ImmichWidgetView(entry: entry)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ struct RandomConfigurationAppIntent: WidgetConfigurationIntent {
|
|||
|
||||
@Parameter(title: "Show Album Name", default: false)
|
||||
var showAlbumName: Bool
|
||||
|
||||
@Parameter(title: "Always Display in Full Color", default: false)
|
||||
var forceFullColor: Bool
|
||||
}
|
||||
|
||||
// MARK: Provider
|
||||
|
|
@ -76,7 +79,8 @@ struct ImmichRandomProvider: AppIntentTimelineProvider {
|
|||
let entry = try? await ImageEntry.build(
|
||||
api: api,
|
||||
asset: randomImage,
|
||||
dateOffset: 0
|
||||
dateOffset: 0,
|
||||
forceFullColor: configuration.forceFullColor
|
||||
)
|
||||
else {
|
||||
return ImageEntry.handleError(for: cacheKey).entries.first!
|
||||
|
|
@ -114,7 +118,8 @@ struct ImmichRandomProvider: AppIntentTimelineProvider {
|
|||
now: now,
|
||||
count: 12,
|
||||
filter: album.filter,
|
||||
subtitle: configuration.showAlbumName ? albumName : nil
|
||||
subtitle: configuration.showAlbumName ? albumName : nil,
|
||||
forceFullColor: configuration.forceFullColor
|
||||
)
|
||||
|
||||
// Load or save a cached asset for when network conditions are bad
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ class CropAspectRatio {
|
|||
}
|
||||
}
|
||||
|
||||
const aspectRatioFree = CropAspectRatio(customLabel: "Free", icon: Icons.crop_free);
|
||||
const aspectRatioOriginal = CropAspectRatio(customLabel: "Original", icon: Icons.crop_original);
|
||||
const aspectRatioFree = CropAspectRatio.free;
|
||||
const aspectRatioOriginal = CropAspectRatio.original;
|
||||
|
||||
final aspectRatioPresets = [
|
||||
CropAspectRatio.free,
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ const Map<String, Locale> locales = {
|
|||
'Arabic (ar)': Locale('ar'),
|
||||
'Basque (eu)': Locale('eu'),
|
||||
'Belarusian (be)': Locale('be'),
|
||||
'Bosnian (bl)': Locale('bn'),
|
||||
'Bengali (bn)': Locale('bn'),
|
||||
'Brazilian Portuguese (pt_BR)': Locale('pt', 'BR'),
|
||||
'Bulgarian (bg)': Locale('bg'),
|
||||
'Catalan (ca)': Locale('ca'),
|
||||
'Cantonese (Traditional)': Locale.fromSubtags(languageCode: 'yue', scriptCode: 'Hant'),
|
||||
'Chinese Simplified (zh_CN)': Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
|
||||
'Chinese Traditional (zh_TW)': Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
|
||||
'Croatian (hr)': Locale('hr'),
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ sealed class BaseAsset {
|
|||
if (durationMs != null) {
|
||||
return Duration(milliseconds: durationMs);
|
||||
}
|
||||
return const Duration();
|
||||
return Duration.zero;
|
||||
}
|
||||
|
||||
bool get hasRemote => storage == AssetState.remote || storage == AssetState.merged;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import "package:openapi/api.dart" show CropParameters, RotateParameters, MirrorParameters;
|
||||
import "package:openapi/api.dart" show CropParameters, MirrorParameters, RotateParameters;
|
||||
|
||||
enum AssetEditAction { rotate, crop, mirror, other }
|
||||
|
||||
|
|
|
|||
|
|
@ -190,9 +190,9 @@ class AppConfig {
|
|||
.viewerTapToNavigate => copyWith(viewer: viewer.copyWith(tapToNavigate: value as bool)),
|
||||
.networkAutoEndpointSwitching => copyWith(network: network.copyWith(autoEndpointSwitching: value as bool)),
|
||||
.networkPreferredWifiName => copyWith(
|
||||
network: network.copyWith(preferredWifiName: .fromNullable((value as String?))),
|
||||
network: network.copyWith(preferredWifiName: .fromNullable(value as String?)),
|
||||
),
|
||||
.networkLocalEndpoint => copyWith(network: network.copyWith(localEndpoint: .fromNullable((value as String?)))),
|
||||
.networkLocalEndpoint => copyWith(network: network.copyWith(localEndpoint: .fromNullable(value as String?))),
|
||||
.networkExternalEndpointList => copyWith(network: network.copyWith(externalEndpointList: value as List<String>)),
|
||||
.networkCustomHeaders => copyWith(network: network.copyWith(customHeaders: value as Map<String, String>)),
|
||||
.albumSortMode => copyWith(album: album.copyWith(sortMode: value as AlbumSortMode)),
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class Onboarding {
|
|||
}
|
||||
|
||||
factory Onboarding.fromMap(Map<String, Object?> map) {
|
||||
return Onboarding(isOnboarded: map["isOnboarded"] as bool);
|
||||
return Onboarding(isOnboarded: map["isOnboarded"]! as bool);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -195,9 +195,9 @@ class License {
|
|||
|
||||
factory License.fromMap(Map<String, Object?> map) {
|
||||
return License(
|
||||
activatedAt: DateTime.parse(map["activatedAt"] as String),
|
||||
activationKey: map["activationKey"] as String,
|
||||
licenseKey: map["licenseKey"] as String,
|
||||
activatedAt: DateTime.parse(map["activatedAt"]! as String),
|
||||
activationKey: map["activationKey"]! as String,
|
||||
licenseKey: map["licenseKey"]! as String,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,15 @@ import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
|||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset_edit.model.dart';
|
||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.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/remote_asset.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/remote_exif.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||
import 'package:immich_mobile/utils/option.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
|
|
@ -14,12 +19,16 @@ class AssetService {
|
|||
final RemoteExifRepository _exifRepository;
|
||||
final DriftLocalAssetRepository _localRepository;
|
||||
final AssetApiRepository _apiRepository;
|
||||
final AssetMediaRepository _mediaRepository;
|
||||
final DriftTrashedLocalAssetRepository _trashedLocalRepository;
|
||||
|
||||
const AssetService({
|
||||
required this._remoteRepository,
|
||||
required this._exifRepository,
|
||||
required this._localRepository,
|
||||
required this._apiRepository,
|
||||
required this._mediaRepository,
|
||||
required this._trashedLocalRepository,
|
||||
});
|
||||
|
||||
Future<BaseAsset?> getAsset(BaseAsset asset) {
|
||||
|
|
@ -36,8 +45,8 @@ class AssetService {
|
|||
return _localRepository.getByChecksum(checksum);
|
||||
}
|
||||
|
||||
Future<RemoteAsset?> getRemoteAssetByChecksum(String checksum) {
|
||||
return _remoteRepository.getByChecksum(checksum);
|
||||
Future<List<RemoteAsset>> getAllRemoteAssetDebugByChecksum(String checksum) {
|
||||
return _remoteRepository.getAllDebugForChecksum(checksum);
|
||||
}
|
||||
|
||||
Future<RemoteAsset?> getRemoteAsset(String id) {
|
||||
|
|
@ -167,17 +176,25 @@ class AssetService {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(shenlong): remove after action migration
|
||||
Future<int> deleteLocal(List<String> localIds) async {
|
||||
if (localIds.isEmpty) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final deletedIds = await _mediaRepository.deleteAll(localIds);
|
||||
if (deletedIds.isEmpty) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CurrentPlatform.isAndroid && Store.get(StoreKey.manageLocalMediaAndroid, false)) {
|
||||
await _trashedLocalRepository.applyTrashedAssets(deletedIds);
|
||||
} else {
|
||||
await _localRepository.delete(deletedIds);
|
||||
}
|
||||
return deletedIds.length;
|
||||
}
|
||||
|
||||
Future<LocalAsset?> getLocalAsset(String id) {
|
||||
return _localRepository.get(id);
|
||||
}
|
||||
|
||||
Future<void> updateFavorite(List<String> remoteIds, bool isFavorite) async {
|
||||
if (remoteIds.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
await _apiRepository.updateFavorite(remoteIds, isFavorite);
|
||||
await _remoteRepository.updateFavorite(remoteIds, isFavorite);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class HashService {
|
|||
}) : _batchSize = batchSize ?? kBatchHashFileLimit {
|
||||
// Stop the in-flight native hash call promptly on cancellation; the loops
|
||||
// below also observe [isCancelled] to bail between batches.
|
||||
_cancellation?.future.then((_) => _nativeSyncApi.cancelHashing().onError(_log.warning));
|
||||
unawaited(_cancellation?.future.then((_) => _nativeSyncApi.cancelHashing().onError(_log.warning)));
|
||||
}
|
||||
|
||||
bool get isCancelled => _cancellation?.isCompleted ?? false;
|
||||
|
|
@ -66,11 +66,12 @@ class HashService {
|
|||
await _hashAssets(pseudoAlbum, trashedToHash, isTrashed: true);
|
||||
}
|
||||
}
|
||||
} on PlatformException catch (e) {
|
||||
} on PlatformException catch (e, s) {
|
||||
if (e.code == _kHashCancelledCode) {
|
||||
_log.warning("Hashing cancelled by platform");
|
||||
return;
|
||||
}
|
||||
_log.severe("Native hashing failed: ${e.code}", e, s);
|
||||
} catch (e, s) {
|
||||
_log.severe("Error during hashing", e, s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class LocalSyncService {
|
|||
required this._permissionRepository,
|
||||
this._cancellation,
|
||||
}) {
|
||||
_cancellation?.future.then((_) => _nativeSyncApi.cancelSync().onError(_log.warning));
|
||||
unawaited(_cancellation?.future.then((_) => _nativeSyncApi.cancelSync().onError(_log.warning)));
|
||||
}
|
||||
|
||||
bool get _isCancelled => _cancellation?.isCompleted ?? false;
|
||||
|
|
|
|||
|
|
@ -105,10 +105,8 @@ class RemoteAlbumService {
|
|||
switch (filterMode) {
|
||||
case QuickFilterMode.myAlbums:
|
||||
filtered = filtered.where((album) => album.ownerId == userId).toList();
|
||||
break;
|
||||
case QuickFilterMode.sharedWithMe:
|
||||
filtered = filtered.where((album) => album.ownerId != userId).toList();
|
||||
break;
|
||||
case QuickFilterMode.all:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class SyncStreamService {
|
|||
}
|
||||
|
||||
Future<void> _handleEvents(List<SyncEvent> events, Function() abort, Function() reset) async {
|
||||
List<SyncEvent> items = [];
|
||||
final List<SyncEvent> items = [];
|
||||
for (final event in events) {
|
||||
if (isCancelled) {
|
||||
_logger.warning("Sync stream cancelled");
|
||||
|
|
|
|||
|
|
@ -106,32 +106,34 @@ class TimelineService {
|
|||
|
||||
TimelineService._({required this._assetSource, required this._bucketSource, required this.origin}) {
|
||||
_bucketSubscription = _bucketSource().listen((buckets) {
|
||||
_mutex.run(() async {
|
||||
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
|
||||
unawaited(
|
||||
_mutex.run(() async {
|
||||
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
|
||||
|
||||
if (totalAssets == 0) {
|
||||
_bufferOffset = 0;
|
||||
_buffer = [];
|
||||
} else {
|
||||
final int offset;
|
||||
final int count;
|
||||
// When the buffer is empty or the old bufferOffset is greater than the new total assets,
|
||||
// we need to reset the buffer and load the first batch of assets.
|
||||
if (_bufferOffset >= totalAssets || _buffer.isEmpty) {
|
||||
offset = 0;
|
||||
count = kTimelineAssetLoadBatchSize;
|
||||
if (totalAssets == 0) {
|
||||
_bufferOffset = 0;
|
||||
_buffer = [];
|
||||
} else {
|
||||
offset = _bufferOffset;
|
||||
count = math.min(_buffer.length, totalAssets - _bufferOffset);
|
||||
final int offset;
|
||||
final int count;
|
||||
// When the buffer is empty or the old bufferOffset is greater than the new total assets,
|
||||
// we need to reset the buffer and load the first batch of assets.
|
||||
if (_bufferOffset >= totalAssets || _buffer.isEmpty) {
|
||||
offset = 0;
|
||||
count = kTimelineAssetLoadBatchSize;
|
||||
} else {
|
||||
offset = _bufferOffset;
|
||||
count = math.min(_buffer.length, totalAssets - _bufferOffset);
|
||||
}
|
||||
_buffer = await _assetSource(offset, count);
|
||||
_bufferOffset = offset;
|
||||
}
|
||||
_buffer = await _assetSource(offset, count);
|
||||
_bufferOffset = offset;
|
||||
}
|
||||
|
||||
// change the state's total assets count only after the buffer is reloaded
|
||||
_totalAssets = totalAssets;
|
||||
EventStream.shared.emit(const TimelineReloadEvent());
|
||||
});
|
||||
// change the state's total assets count only after the buffer is reloaded
|
||||
_totalAssets = totalAssets;
|
||||
EventStream.shared.emit(const TimelineReloadEvent());
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +180,7 @@ class TimelineService {
|
|||
if (!hasRange(index, count)) {
|
||||
throw RangeError('TimelineService::getAssets Index out of range');
|
||||
}
|
||||
int start = index - _bufferOffset;
|
||||
final int start = index - _bufferOffset;
|
||||
return _buffer.slice(start, start + count);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class BackgroundSyncManager {
|
|||
final SyncErrorCallback? onCloudIdSyncError;
|
||||
|
||||
Cancelable<bool?>? _syncTask;
|
||||
bool _syncQueued = false;
|
||||
Cancelable<void>? _syncWebsocketTask;
|
||||
Cancelable<void>? _cloudIdSyncTask;
|
||||
Cancelable<void>? _deviceAlbumSyncTask;
|
||||
|
|
@ -50,6 +51,7 @@ class BackgroundSyncManager {
|
|||
});
|
||||
|
||||
Future<void> cancel() async {
|
||||
_syncQueued = false;
|
||||
final tasks = [
|
||||
_syncTask,
|
||||
_syncWebsocketTask,
|
||||
|
|
@ -133,8 +135,9 @@ class BackgroundSyncManager {
|
|||
});
|
||||
}
|
||||
|
||||
Future<bool> syncRemote() {
|
||||
Future<bool> syncRemote({bool enqueue = false}) {
|
||||
if (_syncTask != null) {
|
||||
_syncQueued |= enqueue;
|
||||
return _syncTask!.future.then((result) => result ?? false).catchError((_) => false);
|
||||
}
|
||||
|
||||
|
|
@ -148,15 +151,20 @@ class BackgroundSyncManager {
|
|||
.then((result) {
|
||||
final success = result ?? false;
|
||||
onRemoteSyncComplete?.call(success);
|
||||
_syncQueued &= success;
|
||||
return success;
|
||||
})
|
||||
.catchError((error) {
|
||||
onRemoteSyncError?.call(error.toString());
|
||||
_syncTask = null;
|
||||
_syncQueued = false;
|
||||
return false;
|
||||
})
|
||||
.whenComplete(() {
|
||||
_syncTask = null;
|
||||
if (_syncQueued) {
|
||||
_syncQueued = false;
|
||||
unawaited(syncRemote());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class EventStream {
|
|||
}
|
||||
|
||||
/// Closes the stream controller
|
||||
void dispose() {
|
||||
_controller.close();
|
||||
Future<void> dispose() {
|
||||
return _controller.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ extension DTOToAsset on api.AssetResponseDto {
|
|||
ownerId: ownerId,
|
||||
visibility: visibility.toAssetVisibility(),
|
||||
durationMs: duration,
|
||||
height: height?.toInt(),
|
||||
width: width?.toInt(),
|
||||
height: height,
|
||||
width: width,
|
||||
isFavorite: isFavorite,
|
||||
livePhotoVideoId: livePhotoVideoId.orElse(null),
|
||||
thumbHash: thumbhash,
|
||||
|
|
@ -38,8 +38,8 @@ extension DTOToAsset on api.AssetResponseDto {
|
|||
ownerId: ownerId,
|
||||
visibility: visibility.toAssetVisibility(),
|
||||
durationMs: duration,
|
||||
height: height?.toInt(),
|
||||
width: width?.toInt(),
|
||||
height: height,
|
||||
width: width,
|
||||
isFavorite: isFavorite,
|
||||
livePhotoVideoId: livePhotoVideoId.orElse(null),
|
||||
thumbHash: thumbhash,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import 'package:collection/collection.dart';
|
|||
extension ListExtension<E> on List<E> {
|
||||
List<E> uniqueConsecutive({int Function(E a, E b)? compare, void Function(E a, E b)? onDuplicate}) {
|
||||
compare ??= (E a, E b) => a == b ? 0 : 1;
|
||||
int i = 1, j = 1;
|
||||
int i = 1;
|
||||
int j = 1;
|
||||
for (; i < length; i++) {
|
||||
if (compare(this[i - 1], this[i]) != 0) {
|
||||
if (i != j) {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
extension TimeAgoExtension on DateTime {
|
||||
/// Displays the time difference of this [DateTime] object to the current time as a [String]
|
||||
String timeAgo({bool numericDates = true}) {
|
||||
DateTime date = toLocal();
|
||||
final DateTime date = toLocal();
|
||||
final now = DateTime.now().toLocal();
|
||||
final difference = now.difference(date);
|
||||
|
||||
|
|
@ -13,27 +13,27 @@ extension TimeAgoExtension on DateTime {
|
|||
} else if (difference.inSeconds < 60) {
|
||||
return '${difference.inSeconds} seconds ago';
|
||||
} else if (difference.inMinutes <= 1) {
|
||||
return (numericDates) ? '1 minute ago' : 'A minute ago';
|
||||
return numericDates ? '1 minute ago' : 'A minute ago';
|
||||
} else if (difference.inMinutes < 60) {
|
||||
return '${difference.inMinutes} minutes ago';
|
||||
} else if (difference.inHours <= 1) {
|
||||
return (numericDates) ? '1 hour ago' : 'An hour ago';
|
||||
return numericDates ? '1 hour ago' : 'An hour ago';
|
||||
} else if (difference.inHours < 60) {
|
||||
return '${difference.inHours} hours ago';
|
||||
} else if (difference.inDays <= 1) {
|
||||
return (numericDates) ? '1 day ago' : 'Yesterday';
|
||||
return numericDates ? '1 day ago' : 'Yesterday';
|
||||
} else if (difference.inDays < 6) {
|
||||
return '${difference.inDays} days ago';
|
||||
} else if ((difference.inDays / 7).ceil() <= 1) {
|
||||
return (numericDates) ? '1 week ago' : 'Last week';
|
||||
return numericDates ? '1 week ago' : 'Last week';
|
||||
} else if ((difference.inDays / 7).ceil() < 4) {
|
||||
return '${(difference.inDays / 7).ceil()} weeks ago';
|
||||
} else if ((difference.inDays / 30).ceil() <= 1) {
|
||||
return (numericDates) ? '1 month ago' : 'Last month';
|
||||
return numericDates ? '1 month ago' : 'Last month';
|
||||
} else if ((difference.inDays / 30).ceil() < 30) {
|
||||
return '${(difference.inDays / 30).ceil()} months ago';
|
||||
} else if ((difference.inDays / 365).ceil() <= 1) {
|
||||
return (numericDates) ? '1 year ago' : 'Last year';
|
||||
return numericDates ? '1 year ago' : 'Last year';
|
||||
}
|
||||
return '${(difference.inDays / 365).floor()} years ago';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class AssetEditEntity extends Table with DriftDefaultsMixin {
|
|||
}
|
||||
|
||||
final JsonTypeConverter2<Map<String, Object?>, Uint8List, Object?> editParameterConverter = TypeConverter.jsonb(
|
||||
fromJson: (json) => json as Map<String, Object?>,
|
||||
fromJson: (json) => json! as Map<String, Object?>,
|
||||
);
|
||||
|
||||
extension AssetEditEntityDataDomainEx on AssetEditEntityData {
|
||||
|
|
|
|||
|
|
@ -1,743 +0,0 @@
|
|||
// dart format width=80
|
||||
// ignore_for_file: type=lint
|
||||
import 'package:drift/drift.dart' as i0;
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.drift.dart'
|
||||
as i1;
|
||||
import 'package:immich_mobile/domain/models/asset_edit.model.dart' as i2;
|
||||
import 'dart:typed_data' as i3;
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.dart'
|
||||
as i4;
|
||||
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'
|
||||
as i5;
|
||||
import 'package:drift/internal/modular.dart' as i6;
|
||||
|
||||
typedef $$AssetEditEntityTableCreateCompanionBuilder =
|
||||
i1.AssetEditEntityCompanion Function({
|
||||
required String id,
|
||||
required String assetId,
|
||||
required i2.AssetEditAction action,
|
||||
required Map<String, Object?> parameters,
|
||||
required int sequence,
|
||||
});
|
||||
typedef $$AssetEditEntityTableUpdateCompanionBuilder =
|
||||
i1.AssetEditEntityCompanion Function({
|
||||
i0.Value<String> id,
|
||||
i0.Value<String> assetId,
|
||||
i0.Value<i2.AssetEditAction> action,
|
||||
i0.Value<Map<String, Object?>> parameters,
|
||||
i0.Value<int> sequence,
|
||||
});
|
||||
|
||||
final class $$AssetEditEntityTableReferences
|
||||
extends
|
||||
i0.BaseReferences<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AssetEditEntityTable,
|
||||
i1.AssetEditEntityData
|
||||
> {
|
||||
$$AssetEditEntityTableReferences(
|
||||
super.$_db,
|
||||
super.$_table,
|
||||
super.$_typedResult,
|
||||
);
|
||||
|
||||
static i5.$RemoteAssetEntityTable _assetIdTable(i0.GeneratedDatabase db) =>
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias('asset_edit_entity__asset_id__remote_asset_entity__id');
|
||||
|
||||
i5.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
final $_column = $_itemColumn<String>('asset_id')!;
|
||||
|
||||
final manager = i5
|
||||
.$$RemoteAssetEntityTableTableManager(
|
||||
$_db,
|
||||
i6.ReadDatabaseContainer(
|
||||
$_db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
)
|
||||
.filter((f) => f.id.sqlEquals($_column));
|
||||
final item = $_typedResult.readTableOrNull(_assetIdTable($_db));
|
||||
if (item == null) return manager;
|
||||
return i0.ProcessedTableManager(
|
||||
manager.$state.copyWith(prefetchedData: [item]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class $$AssetEditEntityTableFilterComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$AssetEditEntityTable> {
|
||||
$$AssetEditEntityTableFilterComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.ColumnFilters<String> get id => $composableBuilder(
|
||||
column: $table.id,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnWithTypeConverterFilters<i2.AssetEditAction, i2.AssetEditAction, int>
|
||||
get action => $composableBuilder(
|
||||
column: $table.action,
|
||||
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnWithTypeConverterFilters<
|
||||
Map<String, Object?>,
|
||||
Map<String, Object>,
|
||||
i3.Uint8List
|
||||
>
|
||||
get parameters => $composableBuilder(
|
||||
column: $table.parameters,
|
||||
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<int> get sequence => $composableBuilder(
|
||||
column: $table.sequence,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i5.$$RemoteAssetEntityTableFilterComposer get assetId {
|
||||
final i5.$$RemoteAssetEntityTableFilterComposer composer = $composerBuilder(
|
||||
composer: this,
|
||||
getCurrentColumn: (t) => t.assetId,
|
||||
referencedTable: i6.ReadDatabaseContainer(
|
||||
$db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
getReferencedColumn: (t) => t.id,
|
||||
builder:
|
||||
(
|
||||
joinBuilder, {
|
||||
$addJoinBuilderToRootComposer,
|
||||
$removeJoinBuilderFromRootComposer,
|
||||
}) => i5.$$RemoteAssetEntityTableFilterComposer(
|
||||
$db: $db,
|
||||
$table: i6.ReadDatabaseContainer(
|
||||
$db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||
joinBuilder: joinBuilder,
|
||||
$removeJoinBuilderFromRootComposer:
|
||||
$removeJoinBuilderFromRootComposer,
|
||||
),
|
||||
);
|
||||
return composer;
|
||||
}
|
||||
}
|
||||
|
||||
class $$AssetEditEntityTableOrderingComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$AssetEditEntityTable> {
|
||||
$$AssetEditEntityTableOrderingComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.ColumnOrderings<String> get id => $composableBuilder(
|
||||
column: $table.id,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<int> get action => $composableBuilder(
|
||||
column: $table.action,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<i3.Uint8List> get parameters => $composableBuilder(
|
||||
column: $table.parameters,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<int> get sequence => $composableBuilder(
|
||||
column: $table.sequence,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i5.$$RemoteAssetEntityTableOrderingComposer get assetId {
|
||||
final i5.$$RemoteAssetEntityTableOrderingComposer composer =
|
||||
$composerBuilder(
|
||||
composer: this,
|
||||
getCurrentColumn: (t) => t.assetId,
|
||||
referencedTable: i6.ReadDatabaseContainer(
|
||||
$db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
getReferencedColumn: (t) => t.id,
|
||||
builder:
|
||||
(
|
||||
joinBuilder, {
|
||||
$addJoinBuilderToRootComposer,
|
||||
$removeJoinBuilderFromRootComposer,
|
||||
}) => i5.$$RemoteAssetEntityTableOrderingComposer(
|
||||
$db: $db,
|
||||
$table: i6.ReadDatabaseContainer(
|
||||
$db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||
joinBuilder: joinBuilder,
|
||||
$removeJoinBuilderFromRootComposer:
|
||||
$removeJoinBuilderFromRootComposer,
|
||||
),
|
||||
);
|
||||
return composer;
|
||||
}
|
||||
}
|
||||
|
||||
class $$AssetEditEntityTableAnnotationComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$AssetEditEntityTable> {
|
||||
$$AssetEditEntityTableAnnotationComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.GeneratedColumn<String> get id =>
|
||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumnWithTypeConverter<i2.AssetEditAction, int> get action =>
|
||||
$composableBuilder(column: $table.action, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumnWithTypeConverter<Map<String, Object?>, i3.Uint8List>
|
||||
get parameters => $composableBuilder(
|
||||
column: $table.parameters,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumn<int> get sequence =>
|
||||
$composableBuilder(column: $table.sequence, builder: (column) => column);
|
||||
|
||||
i5.$$RemoteAssetEntityTableAnnotationComposer get assetId {
|
||||
final i5.$$RemoteAssetEntityTableAnnotationComposer composer =
|
||||
$composerBuilder(
|
||||
composer: this,
|
||||
getCurrentColumn: (t) => t.assetId,
|
||||
referencedTable: i6.ReadDatabaseContainer(
|
||||
$db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
getReferencedColumn: (t) => t.id,
|
||||
builder:
|
||||
(
|
||||
joinBuilder, {
|
||||
$addJoinBuilderToRootComposer,
|
||||
$removeJoinBuilderFromRootComposer,
|
||||
}) => i5.$$RemoteAssetEntityTableAnnotationComposer(
|
||||
$db: $db,
|
||||
$table: i6.ReadDatabaseContainer(
|
||||
$db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
|
||||
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
|
||||
joinBuilder: joinBuilder,
|
||||
$removeJoinBuilderFromRootComposer:
|
||||
$removeJoinBuilderFromRootComposer,
|
||||
),
|
||||
);
|
||||
return composer;
|
||||
}
|
||||
}
|
||||
|
||||
class $$AssetEditEntityTableTableManager
|
||||
extends
|
||||
i0.RootTableManager<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AssetEditEntityTable,
|
||||
i1.AssetEditEntityData,
|
||||
i1.$$AssetEditEntityTableFilterComposer,
|
||||
i1.$$AssetEditEntityTableOrderingComposer,
|
||||
i1.$$AssetEditEntityTableAnnotationComposer,
|
||||
$$AssetEditEntityTableCreateCompanionBuilder,
|
||||
$$AssetEditEntityTableUpdateCompanionBuilder,
|
||||
(i1.AssetEditEntityData, i1.$$AssetEditEntityTableReferences),
|
||||
i1.AssetEditEntityData,
|
||||
i0.PrefetchHooks Function({bool assetId})
|
||||
> {
|
||||
$$AssetEditEntityTableTableManager(
|
||||
i0.GeneratedDatabase db,
|
||||
i1.$AssetEditEntityTable table,
|
||||
) : super(
|
||||
i0.TableManagerState(
|
||||
db: db,
|
||||
table: table,
|
||||
createFilteringComposer: () =>
|
||||
i1.$$AssetEditEntityTableFilterComposer($db: db, $table: table),
|
||||
createOrderingComposer: () =>
|
||||
i1.$$AssetEditEntityTableOrderingComposer($db: db, $table: table),
|
||||
createComputedFieldComposer: () => i1
|
||||
.$$AssetEditEntityTableAnnotationComposer($db: db, $table: table),
|
||||
updateCompanionCallback:
|
||||
({
|
||||
i0.Value<String> id = const i0.Value.absent(),
|
||||
i0.Value<String> assetId = const i0.Value.absent(),
|
||||
i0.Value<i2.AssetEditAction> action = const i0.Value.absent(),
|
||||
i0.Value<Map<String, Object?>> parameters =
|
||||
const i0.Value.absent(),
|
||||
i0.Value<int> sequence = const i0.Value.absent(),
|
||||
}) => i1.AssetEditEntityCompanion(
|
||||
id: id,
|
||||
assetId: assetId,
|
||||
action: action,
|
||||
parameters: parameters,
|
||||
sequence: sequence,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
required String id,
|
||||
required String assetId,
|
||||
required i2.AssetEditAction action,
|
||||
required Map<String, Object?> parameters,
|
||||
required int sequence,
|
||||
}) => i1.AssetEditEntityCompanion.insert(
|
||||
id: id,
|
||||
assetId: assetId,
|
||||
action: action,
|
||||
parameters: parameters,
|
||||
sequence: sequence,
|
||||
),
|
||||
withReferenceMapper: (p0) => p0
|
||||
.map(
|
||||
(e) => (
|
||||
e.readTable(table),
|
||||
i1.$$AssetEditEntityTableReferences(db, table, e),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
prefetchHooksCallback: ({assetId = false}) {
|
||||
return i0.PrefetchHooks(
|
||||
db: db,
|
||||
explicitlyWatchedTables: [],
|
||||
addJoins:
|
||||
<
|
||||
T extends i0.TableManagerState<
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic,
|
||||
dynamic
|
||||
>
|
||||
>(state) {
|
||||
if (assetId) {
|
||||
state =
|
||||
state.withJoin(
|
||||
currentTable: table,
|
||||
currentColumn: table.assetId,
|
||||
referencedTable: i1
|
||||
.$$AssetEditEntityTableReferences
|
||||
._assetIdTable(db),
|
||||
referencedColumn: i1
|
||||
.$$AssetEditEntityTableReferences
|
||||
._assetIdTable(db)
|
||||
.id,
|
||||
)
|
||||
as T;
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
getPrefetchedDataCallback: (items) async {
|
||||
return [];
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
typedef $$AssetEditEntityTableProcessedTableManager =
|
||||
i0.ProcessedTableManager<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AssetEditEntityTable,
|
||||
i1.AssetEditEntityData,
|
||||
i1.$$AssetEditEntityTableFilterComposer,
|
||||
i1.$$AssetEditEntityTableOrderingComposer,
|
||||
i1.$$AssetEditEntityTableAnnotationComposer,
|
||||
$$AssetEditEntityTableCreateCompanionBuilder,
|
||||
$$AssetEditEntityTableUpdateCompanionBuilder,
|
||||
(i1.AssetEditEntityData, i1.$$AssetEditEntityTableReferences),
|
||||
i1.AssetEditEntityData,
|
||||
i0.PrefetchHooks Function({bool assetId})
|
||||
>;
|
||||
i0.Index get idxAssetEditAssetId => i0.Index(
|
||||
'idx_asset_edit_asset_id',
|
||||
'CREATE INDEX IF NOT EXISTS idx_asset_edit_asset_id ON asset_edit_entity (asset_id)',
|
||||
);
|
||||
|
||||
class $AssetEditEntityTable extends i4.AssetEditEntity
|
||||
with i0.TableInfo<$AssetEditEntityTable, i1.AssetEditEntityData> {
|
||||
@override
|
||||
final i0.GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$AssetEditEntityTable(this.attachedDatabase, [this._alias]);
|
||||
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
|
||||
'id',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const i0.VerificationMeta _assetIdMeta = const i0.VerificationMeta(
|
||||
'assetId',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> assetId = i0.GeneratedColumn<String>(
|
||||
'asset_id',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||
'REFERENCES remote_asset_entity (id) ON DELETE CASCADE',
|
||||
),
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumnWithTypeConverter<i2.AssetEditAction, int>
|
||||
action =
|
||||
i0.GeneratedColumn<int>(
|
||||
'action',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.int,
|
||||
requiredDuringInsert: true,
|
||||
).withConverter<i2.AssetEditAction>(
|
||||
i1.$AssetEditEntityTable.$converteraction,
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumnWithTypeConverter<
|
||||
Map<String, Object?>,
|
||||
i3.Uint8List
|
||||
>
|
||||
parameters =
|
||||
i0.GeneratedColumn<i3.Uint8List>(
|
||||
'parameters',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.blob,
|
||||
requiredDuringInsert: true,
|
||||
).withConverter<Map<String, Object?>>(
|
||||
i1.$AssetEditEntityTable.$converterparameters,
|
||||
);
|
||||
static const i0.VerificationMeta _sequenceMeta = const i0.VerificationMeta(
|
||||
'sequence',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<int> sequence = i0.GeneratedColumn<int>(
|
||||
'sequence',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.int,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
@override
|
||||
List<i0.GeneratedColumn> get $columns => [
|
||||
id,
|
||||
assetId,
|
||||
action,
|
||||
parameters,
|
||||
sequence,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'asset_edit_entity';
|
||||
@override
|
||||
i0.VerificationContext validateIntegrity(
|
||||
i0.Insertable<i1.AssetEditEntityData> instance, {
|
||||
bool isInserting = false,
|
||||
}) {
|
||||
final context = i0.VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (data.containsKey('asset_id')) {
|
||||
context.handle(
|
||||
_assetIdMeta,
|
||||
assetId.isAcceptableOrUnknown(data['asset_id']!, _assetIdMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_assetIdMeta);
|
||||
}
|
||||
if (data.containsKey('sequence')) {
|
||||
context.handle(
|
||||
_sequenceMeta,
|
||||
sequence.isAcceptableOrUnknown(data['sequence']!, _sequenceMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_sequenceMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
i1.AssetEditEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return i1.AssetEditEntityData(
|
||||
id: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}id'],
|
||||
)!,
|
||||
assetId: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}asset_id'],
|
||||
)!,
|
||||
action: i1.$AssetEditEntityTable.$converteraction.fromSql(
|
||||
attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.int,
|
||||
data['${effectivePrefix}action'],
|
||||
)!,
|
||||
),
|
||||
parameters: i1.$AssetEditEntityTable.$converterparameters.fromSql(
|
||||
attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.blob,
|
||||
data['${effectivePrefix}parameters'],
|
||||
)!,
|
||||
),
|
||||
sequence: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.int,
|
||||
data['${effectivePrefix}sequence'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$AssetEditEntityTable createAlias(String alias) {
|
||||
return $AssetEditEntityTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static i0.JsonTypeConverter2<i2.AssetEditAction, int, int> $converteraction =
|
||||
const i0.EnumIndexConverter<i2.AssetEditAction>(
|
||||
i2.AssetEditAction.values,
|
||||
);
|
||||
static i0.JsonTypeConverter2<Map<String, Object?>, i3.Uint8List, Object?>
|
||||
$converterparameters = i4.editParameterConverter;
|
||||
@override
|
||||
bool get withoutRowId => true;
|
||||
@override
|
||||
bool get isStrict => true;
|
||||
}
|
||||
|
||||
class AssetEditEntityData extends i0.DataClass
|
||||
implements i0.Insertable<i1.AssetEditEntityData> {
|
||||
final String id;
|
||||
final String assetId;
|
||||
final i2.AssetEditAction action;
|
||||
final Map<String, Object?> parameters;
|
||||
final int sequence;
|
||||
const AssetEditEntityData({
|
||||
required this.id,
|
||||
required this.assetId,
|
||||
required this.action,
|
||||
required this.parameters,
|
||||
required this.sequence,
|
||||
});
|
||||
@override
|
||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, i0.Expression>{};
|
||||
map['id'] = i0.Variable<String>(id);
|
||||
map['asset_id'] = i0.Variable<String>(assetId);
|
||||
{
|
||||
map['action'] = i0.Variable<int>(
|
||||
i1.$AssetEditEntityTable.$converteraction.toSql(action),
|
||||
);
|
||||
}
|
||||
{
|
||||
map['parameters'] = i0.Variable<i3.Uint8List>(
|
||||
i1.$AssetEditEntityTable.$converterparameters.toSql(parameters),
|
||||
);
|
||||
}
|
||||
map['sequence'] = i0.Variable<int>(sequence);
|
||||
return map;
|
||||
}
|
||||
|
||||
factory AssetEditEntityData.fromJson(
|
||||
Map<String, dynamic> json, {
|
||||
i0.ValueSerializer? serializer,
|
||||
}) {
|
||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||
return AssetEditEntityData(
|
||||
id: serializer.fromJson<String>(json['id']),
|
||||
assetId: serializer.fromJson<String>(json['assetId']),
|
||||
action: i1.$AssetEditEntityTable.$converteraction.fromJson(
|
||||
serializer.fromJson<int>(json['action']),
|
||||
),
|
||||
parameters: i1.$AssetEditEntityTable.$converterparameters.fromJson(
|
||||
serializer.fromJson<Object?>(json['parameters']),
|
||||
),
|
||||
sequence: serializer.fromJson<int>(json['sequence']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<String>(id),
|
||||
'assetId': serializer.toJson<String>(assetId),
|
||||
'action': serializer.toJson<int>(
|
||||
i1.$AssetEditEntityTable.$converteraction.toJson(action),
|
||||
),
|
||||
'parameters': serializer.toJson<Object?>(
|
||||
i1.$AssetEditEntityTable.$converterparameters.toJson(parameters),
|
||||
),
|
||||
'sequence': serializer.toJson<int>(sequence),
|
||||
};
|
||||
}
|
||||
|
||||
i1.AssetEditEntityData copyWith({
|
||||
String? id,
|
||||
String? assetId,
|
||||
i2.AssetEditAction? action,
|
||||
Map<String, Object?>? parameters,
|
||||
int? sequence,
|
||||
}) => i1.AssetEditEntityData(
|
||||
id: id ?? this.id,
|
||||
assetId: assetId ?? this.assetId,
|
||||
action: action ?? this.action,
|
||||
parameters: parameters ?? this.parameters,
|
||||
sequence: sequence ?? this.sequence,
|
||||
);
|
||||
AssetEditEntityData copyWithCompanion(i1.AssetEditEntityCompanion data) {
|
||||
return AssetEditEntityData(
|
||||
id: data.id.present ? data.id.value : this.id,
|
||||
assetId: data.assetId.present ? data.assetId.value : this.assetId,
|
||||
action: data.action.present ? data.action.value : this.action,
|
||||
parameters: data.parameters.present
|
||||
? data.parameters.value
|
||||
: this.parameters,
|
||||
sequence: data.sequence.present ? data.sequence.value : this.sequence,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('AssetEditEntityData(')
|
||||
..write('id: $id, ')
|
||||
..write('assetId: $assetId, ')
|
||||
..write('action: $action, ')
|
||||
..write('parameters: $parameters, ')
|
||||
..write('sequence: $sequence')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, assetId, action, parameters, sequence);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is i1.AssetEditEntityData &&
|
||||
other.id == this.id &&
|
||||
other.assetId == this.assetId &&
|
||||
other.action == this.action &&
|
||||
other.parameters == this.parameters &&
|
||||
other.sequence == this.sequence);
|
||||
}
|
||||
|
||||
class AssetEditEntityCompanion
|
||||
extends i0.UpdateCompanion<i1.AssetEditEntityData> {
|
||||
final i0.Value<String> id;
|
||||
final i0.Value<String> assetId;
|
||||
final i0.Value<i2.AssetEditAction> action;
|
||||
final i0.Value<Map<String, Object?>> parameters;
|
||||
final i0.Value<int> sequence;
|
||||
const AssetEditEntityCompanion({
|
||||
this.id = const i0.Value.absent(),
|
||||
this.assetId = const i0.Value.absent(),
|
||||
this.action = const i0.Value.absent(),
|
||||
this.parameters = const i0.Value.absent(),
|
||||
this.sequence = const i0.Value.absent(),
|
||||
});
|
||||
AssetEditEntityCompanion.insert({
|
||||
required String id,
|
||||
required String assetId,
|
||||
required i2.AssetEditAction action,
|
||||
required Map<String, Object?> parameters,
|
||||
required int sequence,
|
||||
}) : id = i0.Value(id),
|
||||
assetId = i0.Value(assetId),
|
||||
action = i0.Value(action),
|
||||
parameters = i0.Value(parameters),
|
||||
sequence = i0.Value(sequence);
|
||||
static i0.Insertable<i1.AssetEditEntityData> custom({
|
||||
i0.Expression<String>? id,
|
||||
i0.Expression<String>? assetId,
|
||||
i0.Expression<int>? action,
|
||||
i0.Expression<i3.Uint8List>? parameters,
|
||||
i0.Expression<int>? sequence,
|
||||
}) {
|
||||
return i0.RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (assetId != null) 'asset_id': assetId,
|
||||
if (action != null) 'action': action,
|
||||
if (parameters != null) 'parameters': parameters,
|
||||
if (sequence != null) 'sequence': sequence,
|
||||
});
|
||||
}
|
||||
|
||||
i1.AssetEditEntityCompanion copyWith({
|
||||
i0.Value<String>? id,
|
||||
i0.Value<String>? assetId,
|
||||
i0.Value<i2.AssetEditAction>? action,
|
||||
i0.Value<Map<String, Object?>>? parameters,
|
||||
i0.Value<int>? sequence,
|
||||
}) {
|
||||
return i1.AssetEditEntityCompanion(
|
||||
id: id ?? this.id,
|
||||
assetId: assetId ?? this.assetId,
|
||||
action: action ?? this.action,
|
||||
parameters: parameters ?? this.parameters,
|
||||
sequence: sequence ?? this.sequence,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, i0.Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = i0.Variable<String>(id.value);
|
||||
}
|
||||
if (assetId.present) {
|
||||
map['asset_id'] = i0.Variable<String>(assetId.value);
|
||||
}
|
||||
if (action.present) {
|
||||
map['action'] = i0.Variable<int>(
|
||||
i1.$AssetEditEntityTable.$converteraction.toSql(action.value),
|
||||
);
|
||||
}
|
||||
if (parameters.present) {
|
||||
map['parameters'] = i0.Variable<i3.Uint8List>(
|
||||
i1.$AssetEditEntityTable.$converterparameters.toSql(parameters.value),
|
||||
);
|
||||
}
|
||||
if (sequence.present) {
|
||||
map['sequence'] = i0.Variable<int>(sequence.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('AssetEditEntityCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('assetId: $assetId, ')
|
||||
..write('action: $action, ')
|
||||
..write('parameters: $parameters, ')
|
||||
..write('sequence: $sequence')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,933 +0,0 @@
|
|||
// dart format width=80
|
||||
// ignore_for_file: type=lint
|
||||
import 'package:drift/drift.dart' as i0;
|
||||
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart'
|
||||
as i1;
|
||||
import 'package:immich_mobile/domain/models/user.model.dart' as i2;
|
||||
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.dart'
|
||||
as i3;
|
||||
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
|
||||
|
||||
typedef $$AuthUserEntityTableCreateCompanionBuilder =
|
||||
i1.AuthUserEntityCompanion Function({
|
||||
required String id,
|
||||
required String name,
|
||||
required String email,
|
||||
i0.Value<bool> isAdmin,
|
||||
i0.Value<bool> hasProfileImage,
|
||||
i0.Value<DateTime> profileChangedAt,
|
||||
required i2.AvatarColor avatarColor,
|
||||
i0.Value<int> quotaSizeInBytes,
|
||||
i0.Value<int> quotaUsageInBytes,
|
||||
i0.Value<String?> pinCode,
|
||||
});
|
||||
typedef $$AuthUserEntityTableUpdateCompanionBuilder =
|
||||
i1.AuthUserEntityCompanion Function({
|
||||
i0.Value<String> id,
|
||||
i0.Value<String> name,
|
||||
i0.Value<String> email,
|
||||
i0.Value<bool> isAdmin,
|
||||
i0.Value<bool> hasProfileImage,
|
||||
i0.Value<DateTime> profileChangedAt,
|
||||
i0.Value<i2.AvatarColor> avatarColor,
|
||||
i0.Value<int> quotaSizeInBytes,
|
||||
i0.Value<int> quotaUsageInBytes,
|
||||
i0.Value<String?> pinCode,
|
||||
});
|
||||
|
||||
class $$AuthUserEntityTableFilterComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$AuthUserEntityTable> {
|
||||
$$AuthUserEntityTableFilterComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.ColumnFilters<String> get id => $composableBuilder(
|
||||
column: $table.id,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<String> get name => $composableBuilder(
|
||||
column: $table.name,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<String> get email => $composableBuilder(
|
||||
column: $table.email,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<bool> get isAdmin => $composableBuilder(
|
||||
column: $table.isAdmin,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<bool> get hasProfileImage => $composableBuilder(
|
||||
column: $table.hasProfileImage,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<DateTime> get profileChangedAt => $composableBuilder(
|
||||
column: $table.profileChangedAt,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnWithTypeConverterFilters<i2.AvatarColor, i2.AvatarColor, int>
|
||||
get avatarColor => $composableBuilder(
|
||||
column: $table.avatarColor,
|
||||
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<int> get quotaSizeInBytes => $composableBuilder(
|
||||
column: $table.quotaSizeInBytes,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<int> get quotaUsageInBytes => $composableBuilder(
|
||||
column: $table.quotaUsageInBytes,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<String> get pinCode => $composableBuilder(
|
||||
column: $table.pinCode,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$AuthUserEntityTableOrderingComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$AuthUserEntityTable> {
|
||||
$$AuthUserEntityTableOrderingComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.ColumnOrderings<String> get id => $composableBuilder(
|
||||
column: $table.id,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<String> get name => $composableBuilder(
|
||||
column: $table.name,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<String> get email => $composableBuilder(
|
||||
column: $table.email,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<bool> get isAdmin => $composableBuilder(
|
||||
column: $table.isAdmin,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<bool> get hasProfileImage => $composableBuilder(
|
||||
column: $table.hasProfileImage,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<DateTime> get profileChangedAt => $composableBuilder(
|
||||
column: $table.profileChangedAt,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<int> get avatarColor => $composableBuilder(
|
||||
column: $table.avatarColor,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<int> get quotaSizeInBytes => $composableBuilder(
|
||||
column: $table.quotaSizeInBytes,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<int> get quotaUsageInBytes => $composableBuilder(
|
||||
column: $table.quotaUsageInBytes,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<String> get pinCode => $composableBuilder(
|
||||
column: $table.pinCode,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$AuthUserEntityTableAnnotationComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$AuthUserEntityTable> {
|
||||
$$AuthUserEntityTableAnnotationComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.GeneratedColumn<String> get id =>
|
||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<String> get name =>
|
||||
$composableBuilder(column: $table.name, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<String> get email =>
|
||||
$composableBuilder(column: $table.email, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<bool> get isAdmin =>
|
||||
$composableBuilder(column: $table.isAdmin, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<bool> get hasProfileImage => $composableBuilder(
|
||||
column: $table.hasProfileImage,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumn<DateTime> get profileChangedAt => $composableBuilder(
|
||||
column: $table.profileChangedAt,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumnWithTypeConverter<i2.AvatarColor, int> get avatarColor =>
|
||||
$composableBuilder(
|
||||
column: $table.avatarColor,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumn<int> get quotaSizeInBytes => $composableBuilder(
|
||||
column: $table.quotaSizeInBytes,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumn<int> get quotaUsageInBytes => $composableBuilder(
|
||||
column: $table.quotaUsageInBytes,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
i0.GeneratedColumn<String> get pinCode =>
|
||||
$composableBuilder(column: $table.pinCode, builder: (column) => column);
|
||||
}
|
||||
|
||||
class $$AuthUserEntityTableTableManager
|
||||
extends
|
||||
i0.RootTableManager<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AuthUserEntityTable,
|
||||
i1.AuthUserEntityData,
|
||||
i1.$$AuthUserEntityTableFilterComposer,
|
||||
i1.$$AuthUserEntityTableOrderingComposer,
|
||||
i1.$$AuthUserEntityTableAnnotationComposer,
|
||||
$$AuthUserEntityTableCreateCompanionBuilder,
|
||||
$$AuthUserEntityTableUpdateCompanionBuilder,
|
||||
(
|
||||
i1.AuthUserEntityData,
|
||||
i0.BaseReferences<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AuthUserEntityTable,
|
||||
i1.AuthUserEntityData
|
||||
>,
|
||||
),
|
||||
i1.AuthUserEntityData,
|
||||
i0.PrefetchHooks Function()
|
||||
> {
|
||||
$$AuthUserEntityTableTableManager(
|
||||
i0.GeneratedDatabase db,
|
||||
i1.$AuthUserEntityTable table,
|
||||
) : super(
|
||||
i0.TableManagerState(
|
||||
db: db,
|
||||
table: table,
|
||||
createFilteringComposer: () =>
|
||||
i1.$$AuthUserEntityTableFilterComposer($db: db, $table: table),
|
||||
createOrderingComposer: () =>
|
||||
i1.$$AuthUserEntityTableOrderingComposer($db: db, $table: table),
|
||||
createComputedFieldComposer: () => i1
|
||||
.$$AuthUserEntityTableAnnotationComposer($db: db, $table: table),
|
||||
updateCompanionCallback:
|
||||
({
|
||||
i0.Value<String> id = const i0.Value.absent(),
|
||||
i0.Value<String> name = const i0.Value.absent(),
|
||||
i0.Value<String> email = const i0.Value.absent(),
|
||||
i0.Value<bool> isAdmin = const i0.Value.absent(),
|
||||
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
||||
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
||||
i0.Value<i2.AvatarColor> avatarColor = const i0.Value.absent(),
|
||||
i0.Value<int> quotaSizeInBytes = const i0.Value.absent(),
|
||||
i0.Value<int> quotaUsageInBytes = const i0.Value.absent(),
|
||||
i0.Value<String?> pinCode = const i0.Value.absent(),
|
||||
}) => i1.AuthUserEntityCompanion(
|
||||
id: id,
|
||||
name: name,
|
||||
email: email,
|
||||
isAdmin: isAdmin,
|
||||
hasProfileImage: hasProfileImage,
|
||||
profileChangedAt: profileChangedAt,
|
||||
avatarColor: avatarColor,
|
||||
quotaSizeInBytes: quotaSizeInBytes,
|
||||
quotaUsageInBytes: quotaUsageInBytes,
|
||||
pinCode: pinCode,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
required String id,
|
||||
required String name,
|
||||
required String email,
|
||||
i0.Value<bool> isAdmin = const i0.Value.absent(),
|
||||
i0.Value<bool> hasProfileImage = const i0.Value.absent(),
|
||||
i0.Value<DateTime> profileChangedAt = const i0.Value.absent(),
|
||||
required i2.AvatarColor avatarColor,
|
||||
i0.Value<int> quotaSizeInBytes = const i0.Value.absent(),
|
||||
i0.Value<int> quotaUsageInBytes = const i0.Value.absent(),
|
||||
i0.Value<String?> pinCode = const i0.Value.absent(),
|
||||
}) => i1.AuthUserEntityCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
email: email,
|
||||
isAdmin: isAdmin,
|
||||
hasProfileImage: hasProfileImage,
|
||||
profileChangedAt: profileChangedAt,
|
||||
avatarColor: avatarColor,
|
||||
quotaSizeInBytes: quotaSizeInBytes,
|
||||
quotaUsageInBytes: quotaUsageInBytes,
|
||||
pinCode: pinCode,
|
||||
),
|
||||
withReferenceMapper: (p0) => p0
|
||||
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
||||
.toList(),
|
||||
prefetchHooksCallback: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
typedef $$AuthUserEntityTableProcessedTableManager =
|
||||
i0.ProcessedTableManager<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AuthUserEntityTable,
|
||||
i1.AuthUserEntityData,
|
||||
i1.$$AuthUserEntityTableFilterComposer,
|
||||
i1.$$AuthUserEntityTableOrderingComposer,
|
||||
i1.$$AuthUserEntityTableAnnotationComposer,
|
||||
$$AuthUserEntityTableCreateCompanionBuilder,
|
||||
$$AuthUserEntityTableUpdateCompanionBuilder,
|
||||
(
|
||||
i1.AuthUserEntityData,
|
||||
i0.BaseReferences<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$AuthUserEntityTable,
|
||||
i1.AuthUserEntityData
|
||||
>,
|
||||
),
|
||||
i1.AuthUserEntityData,
|
||||
i0.PrefetchHooks Function()
|
||||
>;
|
||||
|
||||
class $AuthUserEntityTable extends i3.AuthUserEntity
|
||||
with i0.TableInfo<$AuthUserEntityTable, i1.AuthUserEntityData> {
|
||||
@override
|
||||
final i0.GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$AuthUserEntityTable(this.attachedDatabase, [this._alias]);
|
||||
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
|
||||
'id',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const i0.VerificationMeta _nameMeta = const i0.VerificationMeta(
|
||||
'name',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> name = i0.GeneratedColumn<String>(
|
||||
'name',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const i0.VerificationMeta _emailMeta = const i0.VerificationMeta(
|
||||
'email',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> email = i0.GeneratedColumn<String>(
|
||||
'email',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const i0.VerificationMeta _isAdminMeta = const i0.VerificationMeta(
|
||||
'isAdmin',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<bool> isAdmin = i0.GeneratedColumn<bool>(
|
||||
'is_admin',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||
'CHECK ("is_admin" IN (0, 1))',
|
||||
),
|
||||
defaultValue: const i4.Constant(false),
|
||||
);
|
||||
static const i0.VerificationMeta _hasProfileImageMeta =
|
||||
const i0.VerificationMeta('hasProfileImage');
|
||||
@override
|
||||
late final i0.GeneratedColumn<bool> hasProfileImage =
|
||||
i0.GeneratedColumn<bool>(
|
||||
'has_profile_image',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
|
||||
'CHECK ("has_profile_image" IN (0, 1))',
|
||||
),
|
||||
defaultValue: const i4.Constant(false),
|
||||
);
|
||||
static const i0.VerificationMeta _profileChangedAtMeta =
|
||||
const i0.VerificationMeta('profileChangedAt');
|
||||
@override
|
||||
late final i0.GeneratedColumn<DateTime> profileChangedAt =
|
||||
i0.GeneratedColumn<DateTime>(
|
||||
'profile_changed_at',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.dateTime,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: i4.currentDateAndTime,
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumnWithTypeConverter<i2.AvatarColor, int>
|
||||
avatarColor =
|
||||
i0.GeneratedColumn<int>(
|
||||
'avatar_color',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.int,
|
||||
requiredDuringInsert: true,
|
||||
).withConverter<i2.AvatarColor>(
|
||||
i1.$AuthUserEntityTable.$converteravatarColor,
|
||||
);
|
||||
static const i0.VerificationMeta _quotaSizeInBytesMeta =
|
||||
const i0.VerificationMeta('quotaSizeInBytes');
|
||||
@override
|
||||
late final i0.GeneratedColumn<int> quotaSizeInBytes = i0.GeneratedColumn<int>(
|
||||
'quota_size_in_bytes',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const i4.Constant(0),
|
||||
);
|
||||
static const i0.VerificationMeta _quotaUsageInBytesMeta =
|
||||
const i0.VerificationMeta('quotaUsageInBytes');
|
||||
@override
|
||||
late final i0.GeneratedColumn<int> quotaUsageInBytes =
|
||||
i0.GeneratedColumn<int>(
|
||||
'quota_usage_in_bytes',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const i4.Constant(0),
|
||||
);
|
||||
static const i0.VerificationMeta _pinCodeMeta = const i0.VerificationMeta(
|
||||
'pinCode',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> pinCode = i0.GeneratedColumn<String>(
|
||||
'pin_code',
|
||||
aliasedName,
|
||||
true,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
@override
|
||||
List<i0.GeneratedColumn> get $columns => [
|
||||
id,
|
||||
name,
|
||||
email,
|
||||
isAdmin,
|
||||
hasProfileImage,
|
||||
profileChangedAt,
|
||||
avatarColor,
|
||||
quotaSizeInBytes,
|
||||
quotaUsageInBytes,
|
||||
pinCode,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'auth_user_entity';
|
||||
@override
|
||||
i0.VerificationContext validateIntegrity(
|
||||
i0.Insertable<i1.AuthUserEntityData> instance, {
|
||||
bool isInserting = false,
|
||||
}) {
|
||||
final context = i0.VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (data.containsKey('name')) {
|
||||
context.handle(
|
||||
_nameMeta,
|
||||
name.isAcceptableOrUnknown(data['name']!, _nameMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_nameMeta);
|
||||
}
|
||||
if (data.containsKey('email')) {
|
||||
context.handle(
|
||||
_emailMeta,
|
||||
email.isAcceptableOrUnknown(data['email']!, _emailMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_emailMeta);
|
||||
}
|
||||
if (data.containsKey('is_admin')) {
|
||||
context.handle(
|
||||
_isAdminMeta,
|
||||
isAdmin.isAcceptableOrUnknown(data['is_admin']!, _isAdminMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('has_profile_image')) {
|
||||
context.handle(
|
||||
_hasProfileImageMeta,
|
||||
hasProfileImage.isAcceptableOrUnknown(
|
||||
data['has_profile_image']!,
|
||||
_hasProfileImageMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('profile_changed_at')) {
|
||||
context.handle(
|
||||
_profileChangedAtMeta,
|
||||
profileChangedAt.isAcceptableOrUnknown(
|
||||
data['profile_changed_at']!,
|
||||
_profileChangedAtMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('quota_size_in_bytes')) {
|
||||
context.handle(
|
||||
_quotaSizeInBytesMeta,
|
||||
quotaSizeInBytes.isAcceptableOrUnknown(
|
||||
data['quota_size_in_bytes']!,
|
||||
_quotaSizeInBytesMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('quota_usage_in_bytes')) {
|
||||
context.handle(
|
||||
_quotaUsageInBytesMeta,
|
||||
quotaUsageInBytes.isAcceptableOrUnknown(
|
||||
data['quota_usage_in_bytes']!,
|
||||
_quotaUsageInBytesMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('pin_code')) {
|
||||
context.handle(
|
||||
_pinCodeMeta,
|
||||
pinCode.isAcceptableOrUnknown(data['pin_code']!, _pinCodeMeta),
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<i0.GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
i1.AuthUserEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return i1.AuthUserEntityData(
|
||||
id: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}id'],
|
||||
)!,
|
||||
name: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}name'],
|
||||
)!,
|
||||
email: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}email'],
|
||||
)!,
|
||||
isAdmin: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.bool,
|
||||
data['${effectivePrefix}is_admin'],
|
||||
)!,
|
||||
hasProfileImage: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.bool,
|
||||
data['${effectivePrefix}has_profile_image'],
|
||||
)!,
|
||||
profileChangedAt: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.dateTime,
|
||||
data['${effectivePrefix}profile_changed_at'],
|
||||
)!,
|
||||
avatarColor: i1.$AuthUserEntityTable.$converteravatarColor.fromSql(
|
||||
attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.int,
|
||||
data['${effectivePrefix}avatar_color'],
|
||||
)!,
|
||||
),
|
||||
quotaSizeInBytes: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.int,
|
||||
data['${effectivePrefix}quota_size_in_bytes'],
|
||||
)!,
|
||||
quotaUsageInBytes: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.int,
|
||||
data['${effectivePrefix}quota_usage_in_bytes'],
|
||||
)!,
|
||||
pinCode: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}pin_code'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$AuthUserEntityTable createAlias(String alias) {
|
||||
return $AuthUserEntityTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static i0.JsonTypeConverter2<i2.AvatarColor, int, int> $converteravatarColor =
|
||||
const i0.EnumIndexConverter<i2.AvatarColor>(i2.AvatarColor.values);
|
||||
@override
|
||||
bool get withoutRowId => true;
|
||||
@override
|
||||
bool get isStrict => true;
|
||||
}
|
||||
|
||||
class AuthUserEntityData extends i0.DataClass
|
||||
implements i0.Insertable<i1.AuthUserEntityData> {
|
||||
final String id;
|
||||
final String name;
|
||||
final String email;
|
||||
final bool isAdmin;
|
||||
final bool hasProfileImage;
|
||||
final DateTime profileChangedAt;
|
||||
final i2.AvatarColor avatarColor;
|
||||
final int quotaSizeInBytes;
|
||||
final int quotaUsageInBytes;
|
||||
final String? pinCode;
|
||||
const AuthUserEntityData({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.email,
|
||||
required this.isAdmin,
|
||||
required this.hasProfileImage,
|
||||
required this.profileChangedAt,
|
||||
required this.avatarColor,
|
||||
required this.quotaSizeInBytes,
|
||||
required this.quotaUsageInBytes,
|
||||
this.pinCode,
|
||||
});
|
||||
@override
|
||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, i0.Expression>{};
|
||||
map['id'] = i0.Variable<String>(id);
|
||||
map['name'] = i0.Variable<String>(name);
|
||||
map['email'] = i0.Variable<String>(email);
|
||||
map['is_admin'] = i0.Variable<bool>(isAdmin);
|
||||
map['has_profile_image'] = i0.Variable<bool>(hasProfileImage);
|
||||
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt);
|
||||
{
|
||||
map['avatar_color'] = i0.Variable<int>(
|
||||
i1.$AuthUserEntityTable.$converteravatarColor.toSql(avatarColor),
|
||||
);
|
||||
}
|
||||
map['quota_size_in_bytes'] = i0.Variable<int>(quotaSizeInBytes);
|
||||
map['quota_usage_in_bytes'] = i0.Variable<int>(quotaUsageInBytes);
|
||||
if (!nullToAbsent || pinCode != null) {
|
||||
map['pin_code'] = i0.Variable<String>(pinCode);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
factory AuthUserEntityData.fromJson(
|
||||
Map<String, dynamic> json, {
|
||||
i0.ValueSerializer? serializer,
|
||||
}) {
|
||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||
return AuthUserEntityData(
|
||||
id: serializer.fromJson<String>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
email: serializer.fromJson<String>(json['email']),
|
||||
isAdmin: serializer.fromJson<bool>(json['isAdmin']),
|
||||
hasProfileImage: serializer.fromJson<bool>(json['hasProfileImage']),
|
||||
profileChangedAt: serializer.fromJson<DateTime>(json['profileChangedAt']),
|
||||
avatarColor: i1.$AuthUserEntityTable.$converteravatarColor.fromJson(
|
||||
serializer.fromJson<int>(json['avatarColor']),
|
||||
),
|
||||
quotaSizeInBytes: serializer.fromJson<int>(json['quotaSizeInBytes']),
|
||||
quotaUsageInBytes: serializer.fromJson<int>(json['quotaUsageInBytes']),
|
||||
pinCode: serializer.fromJson<String?>(json['pinCode']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<String>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
'email': serializer.toJson<String>(email),
|
||||
'isAdmin': serializer.toJson<bool>(isAdmin),
|
||||
'hasProfileImage': serializer.toJson<bool>(hasProfileImage),
|
||||
'profileChangedAt': serializer.toJson<DateTime>(profileChangedAt),
|
||||
'avatarColor': serializer.toJson<int>(
|
||||
i1.$AuthUserEntityTable.$converteravatarColor.toJson(avatarColor),
|
||||
),
|
||||
'quotaSizeInBytes': serializer.toJson<int>(quotaSizeInBytes),
|
||||
'quotaUsageInBytes': serializer.toJson<int>(quotaUsageInBytes),
|
||||
'pinCode': serializer.toJson<String?>(pinCode),
|
||||
};
|
||||
}
|
||||
|
||||
i1.AuthUserEntityData copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
String? email,
|
||||
bool? isAdmin,
|
||||
bool? hasProfileImage,
|
||||
DateTime? profileChangedAt,
|
||||
i2.AvatarColor? avatarColor,
|
||||
int? quotaSizeInBytes,
|
||||
int? quotaUsageInBytes,
|
||||
i0.Value<String?> pinCode = const i0.Value.absent(),
|
||||
}) => i1.AuthUserEntityData(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
email: email ?? this.email,
|
||||
isAdmin: isAdmin ?? this.isAdmin,
|
||||
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||
avatarColor: avatarColor ?? this.avatarColor,
|
||||
quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes,
|
||||
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
|
||||
pinCode: pinCode.present ? pinCode.value : this.pinCode,
|
||||
);
|
||||
AuthUserEntityData copyWithCompanion(i1.AuthUserEntityCompanion data) {
|
||||
return AuthUserEntityData(
|
||||
id: data.id.present ? data.id.value : this.id,
|
||||
name: data.name.present ? data.name.value : this.name,
|
||||
email: data.email.present ? data.email.value : this.email,
|
||||
isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin,
|
||||
hasProfileImage: data.hasProfileImage.present
|
||||
? data.hasProfileImage.value
|
||||
: this.hasProfileImage,
|
||||
profileChangedAt: data.profileChangedAt.present
|
||||
? data.profileChangedAt.value
|
||||
: this.profileChangedAt,
|
||||
avatarColor: data.avatarColor.present
|
||||
? data.avatarColor.value
|
||||
: this.avatarColor,
|
||||
quotaSizeInBytes: data.quotaSizeInBytes.present
|
||||
? data.quotaSizeInBytes.value
|
||||
: this.quotaSizeInBytes,
|
||||
quotaUsageInBytes: data.quotaUsageInBytes.present
|
||||
? data.quotaUsageInBytes.value
|
||||
: this.quotaUsageInBytes,
|
||||
pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('AuthUserEntityData(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name, ')
|
||||
..write('email: $email, ')
|
||||
..write('isAdmin: $isAdmin, ')
|
||||
..write('hasProfileImage: $hasProfileImage, ')
|
||||
..write('profileChangedAt: $profileChangedAt, ')
|
||||
..write('avatarColor: $avatarColor, ')
|
||||
..write('quotaSizeInBytes: $quotaSizeInBytes, ')
|
||||
..write('quotaUsageInBytes: $quotaUsageInBytes, ')
|
||||
..write('pinCode: $pinCode')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
id,
|
||||
name,
|
||||
email,
|
||||
isAdmin,
|
||||
hasProfileImage,
|
||||
profileChangedAt,
|
||||
avatarColor,
|
||||
quotaSizeInBytes,
|
||||
quotaUsageInBytes,
|
||||
pinCode,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is i1.AuthUserEntityData &&
|
||||
other.id == this.id &&
|
||||
other.name == this.name &&
|
||||
other.email == this.email &&
|
||||
other.isAdmin == this.isAdmin &&
|
||||
other.hasProfileImage == this.hasProfileImage &&
|
||||
other.profileChangedAt == this.profileChangedAt &&
|
||||
other.avatarColor == this.avatarColor &&
|
||||
other.quotaSizeInBytes == this.quotaSizeInBytes &&
|
||||
other.quotaUsageInBytes == this.quotaUsageInBytes &&
|
||||
other.pinCode == this.pinCode);
|
||||
}
|
||||
|
||||
class AuthUserEntityCompanion
|
||||
extends i0.UpdateCompanion<i1.AuthUserEntityData> {
|
||||
final i0.Value<String> id;
|
||||
final i0.Value<String> name;
|
||||
final i0.Value<String> email;
|
||||
final i0.Value<bool> isAdmin;
|
||||
final i0.Value<bool> hasProfileImage;
|
||||
final i0.Value<DateTime> profileChangedAt;
|
||||
final i0.Value<i2.AvatarColor> avatarColor;
|
||||
final i0.Value<int> quotaSizeInBytes;
|
||||
final i0.Value<int> quotaUsageInBytes;
|
||||
final i0.Value<String?> pinCode;
|
||||
const AuthUserEntityCompanion({
|
||||
this.id = const i0.Value.absent(),
|
||||
this.name = const i0.Value.absent(),
|
||||
this.email = const i0.Value.absent(),
|
||||
this.isAdmin = const i0.Value.absent(),
|
||||
this.hasProfileImage = const i0.Value.absent(),
|
||||
this.profileChangedAt = const i0.Value.absent(),
|
||||
this.avatarColor = const i0.Value.absent(),
|
||||
this.quotaSizeInBytes = const i0.Value.absent(),
|
||||
this.quotaUsageInBytes = const i0.Value.absent(),
|
||||
this.pinCode = const i0.Value.absent(),
|
||||
});
|
||||
AuthUserEntityCompanion.insert({
|
||||
required String id,
|
||||
required String name,
|
||||
required String email,
|
||||
this.isAdmin = const i0.Value.absent(),
|
||||
this.hasProfileImage = const i0.Value.absent(),
|
||||
this.profileChangedAt = const i0.Value.absent(),
|
||||
required i2.AvatarColor avatarColor,
|
||||
this.quotaSizeInBytes = const i0.Value.absent(),
|
||||
this.quotaUsageInBytes = const i0.Value.absent(),
|
||||
this.pinCode = const i0.Value.absent(),
|
||||
}) : id = i0.Value(id),
|
||||
name = i0.Value(name),
|
||||
email = i0.Value(email),
|
||||
avatarColor = i0.Value(avatarColor);
|
||||
static i0.Insertable<i1.AuthUserEntityData> custom({
|
||||
i0.Expression<String>? id,
|
||||
i0.Expression<String>? name,
|
||||
i0.Expression<String>? email,
|
||||
i0.Expression<bool>? isAdmin,
|
||||
i0.Expression<bool>? hasProfileImage,
|
||||
i0.Expression<DateTime>? profileChangedAt,
|
||||
i0.Expression<int>? avatarColor,
|
||||
i0.Expression<int>? quotaSizeInBytes,
|
||||
i0.Expression<int>? quotaUsageInBytes,
|
||||
i0.Expression<String>? pinCode,
|
||||
}) {
|
||||
return i0.RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (name != null) 'name': name,
|
||||
if (email != null) 'email': email,
|
||||
if (isAdmin != null) 'is_admin': isAdmin,
|
||||
if (hasProfileImage != null) 'has_profile_image': hasProfileImage,
|
||||
if (profileChangedAt != null) 'profile_changed_at': profileChangedAt,
|
||||
if (avatarColor != null) 'avatar_color': avatarColor,
|
||||
if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes,
|
||||
if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes,
|
||||
if (pinCode != null) 'pin_code': pinCode,
|
||||
});
|
||||
}
|
||||
|
||||
i1.AuthUserEntityCompanion copyWith({
|
||||
i0.Value<String>? id,
|
||||
i0.Value<String>? name,
|
||||
i0.Value<String>? email,
|
||||
i0.Value<bool>? isAdmin,
|
||||
i0.Value<bool>? hasProfileImage,
|
||||
i0.Value<DateTime>? profileChangedAt,
|
||||
i0.Value<i2.AvatarColor>? avatarColor,
|
||||
i0.Value<int>? quotaSizeInBytes,
|
||||
i0.Value<int>? quotaUsageInBytes,
|
||||
i0.Value<String?>? pinCode,
|
||||
}) {
|
||||
return i1.AuthUserEntityCompanion(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
email: email ?? this.email,
|
||||
isAdmin: isAdmin ?? this.isAdmin,
|
||||
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||
avatarColor: avatarColor ?? this.avatarColor,
|
||||
quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes,
|
||||
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
|
||||
pinCode: pinCode ?? this.pinCode,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, i0.Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = i0.Variable<String>(id.value);
|
||||
}
|
||||
if (name.present) {
|
||||
map['name'] = i0.Variable<String>(name.value);
|
||||
}
|
||||
if (email.present) {
|
||||
map['email'] = i0.Variable<String>(email.value);
|
||||
}
|
||||
if (isAdmin.present) {
|
||||
map['is_admin'] = i0.Variable<bool>(isAdmin.value);
|
||||
}
|
||||
if (hasProfileImage.present) {
|
||||
map['has_profile_image'] = i0.Variable<bool>(hasProfileImage.value);
|
||||
}
|
||||
if (profileChangedAt.present) {
|
||||
map['profile_changed_at'] = i0.Variable<DateTime>(profileChangedAt.value);
|
||||
}
|
||||
if (avatarColor.present) {
|
||||
map['avatar_color'] = i0.Variable<int>(
|
||||
i1.$AuthUserEntityTable.$converteravatarColor.toSql(avatarColor.value),
|
||||
);
|
||||
}
|
||||
if (quotaSizeInBytes.present) {
|
||||
map['quota_size_in_bytes'] = i0.Variable<int>(quotaSizeInBytes.value);
|
||||
}
|
||||
if (quotaUsageInBytes.present) {
|
||||
map['quota_usage_in_bytes'] = i0.Variable<int>(quotaUsageInBytes.value);
|
||||
}
|
||||
if (pinCode.present) {
|
||||
map['pin_code'] = i0.Variable<String>(pinCode.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('AuthUserEntityCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name, ')
|
||||
..write('email: $email, ')
|
||||
..write('isAdmin: $isAdmin, ')
|
||||
..write('hasProfileImage: $hasProfileImage, ')
|
||||
..write('profileChangedAt: $profileChangedAt, ')
|
||||
..write('avatarColor: $avatarColor, ')
|
||||
..write('quotaSizeInBytes: $quotaSizeInBytes, ')
|
||||
..write('quotaUsageInBytes: $quotaUsageInBytes, ')
|
||||
..write('pinCode: $pinCode')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -79,8 +79,8 @@ extension RemoteExifEntityDataDomainEx on RemoteExifEntityData {
|
|||
orientation: orientation,
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
f: fNumber?.toDouble(),
|
||||
mm: focalLength?.toDouble(),
|
||||
f: fNumber,
|
||||
mm: focalLength,
|
||||
lens: lens,
|
||||
isFlipped: ExifDtoConverter.isOrientationFlipped(orientation),
|
||||
exposureSeconds: ExifDtoConverter.exposureTimeToSeconds(exposureTime),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue