mirror of
https://github.com/immich-app/immich.git
synced 2026-07-17 05:34:25 +03:00
Compare commits
54 Commits
feat/workf
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f19f30ec66 | ||
|
|
297316c7b8 | ||
|
|
f18065b3c2 | ||
|
|
a3dd19cd2f | ||
|
|
9cea3f2375 | ||
|
|
507448d797 | ||
|
|
fe3eb7d865 | ||
|
|
90dc328c22 | ||
|
|
a5623c41ec | ||
|
|
3a016f4451 | ||
|
|
0af8284456 | ||
|
|
ad7a9bd189 | ||
|
|
80cdfebbc7 | ||
|
|
c50a807bc1 | ||
|
|
26e07548a7 | ||
|
|
f73c53c563 | ||
|
|
d2744f52b1 | ||
|
|
d8ed7d7bb9 | ||
|
|
834cc54abc | ||
|
|
eda605c534 | ||
|
|
b75e6520bb | ||
|
|
4c2d2284aa | ||
|
|
5d29f3edc1 | ||
|
|
e00dcf7850 | ||
|
|
e7f773197f | ||
|
|
2237078bd5 | ||
|
|
55dc579059 | ||
|
|
b4530b0671 | ||
|
|
a04e2ddeca | ||
|
|
5f2e8a4fcf | ||
|
|
dc55b234d9 | ||
|
|
f6bf22d9ca | ||
|
|
2cdbd0d00f | ||
|
|
cd308ad930 | ||
|
|
12061f3bf8 | ||
|
|
2460d431af | ||
|
|
24556cd3fc | ||
|
|
c84ab54889 | ||
|
|
19e59ebd98 | ||
|
|
89b0d906e8 | ||
|
|
3c43e8d6c1 | ||
|
|
2ed8b2bddd | ||
|
|
9c8d718ddc | ||
|
|
20e123c839 | ||
|
|
35fcca6254 | ||
|
|
ffafc144c6 | ||
|
|
89d31aaba1 | ||
|
|
f2ddace584 | ||
|
|
99883096d6 | ||
|
|
84dff19ca9 | ||
|
|
da8774801b | ||
|
|
9057ae9759 | ||
|
|
557189d7a8 | ||
|
|
19313e75fd |
14
.github/workflows/build-mobile.yml
vendored
14
.github/workflows/build-mobile.yml
vendored
@@ -51,10 +51,11 @@ jobs:
|
||||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Check what should run
|
||||
id: check
|
||||
@@ -79,10 +80,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
@@ -103,7 +106,7 @@ jobs:
|
||||
working-directory: ./mobile
|
||||
run: printf "%s" $KEY_JKS | base64 -d > android/key.jks
|
||||
|
||||
- uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
|
||||
- uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '17'
|
||||
@@ -202,10 +205,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Select Xcode 26
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
|
||||
@@ -237,7 +241,7 @@ jobs:
|
||||
run: flutter build ios --config-only --no-codesign
|
||||
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@0dafeac902942906541bc140009cdbf32665b601 # v1.315.0
|
||||
uses: ruby/setup-ruby@d45b1a4e94b71acab930e56e79c6aa188764e7f9 # v1.316.0
|
||||
with:
|
||||
ruby-version: '3.3'
|
||||
bundler-cache: true
|
||||
|
||||
4
.github/workflows/cache-cleanup.yml
vendored
4
.github/workflows/cache-cleanup.yml
vendored
@@ -19,10 +19,12 @@ jobs:
|
||||
actions: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
permission-actions: write
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
2
.github/workflows/check-openapi.yml
vendored
2
.github/workflows/check-openapi.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check for breaking API changes
|
||||
uses: oasdiff/oasdiff-action/breaking@ae5ef6402ebe218ac6e872c59d0fa4557694e75c # v0.1.4
|
||||
uses: oasdiff/oasdiff-action/breaking@291b6594ce617f22f49af5898ee038ed0b46e8fe # v0.1.5
|
||||
with:
|
||||
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
|
||||
revision: open-api/immich-openapi-specs.json
|
||||
|
||||
8
.github/workflows/cli.yml
vendored
8
.github/workflows/cli.yml
vendored
@@ -31,10 +31,11 @@ jobs:
|
||||
working-directory: ./packages/cli
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -63,10 +64,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -81,7 +83,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
|
||||
2
.github/workflows/close-duplicates.yml
vendored
2
.github/workflows/close-duplicates.yml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
needs: [get_body, should_run]
|
||||
if: ${{ needs.should_run.outputs.should_run == 'true' }}
|
||||
container:
|
||||
image: ghcr.io/immich-app/mdq:main@sha256:2a64c7f045cb7b580fbdf3614d7d1805f5775fec453e3d1023764180efa8c70b
|
||||
image: ghcr.io/immich-app/mdq:main@sha256:e3fe456f346b02c2f479462100763aee3ba8245768dfeac3c4262acb068e5c62
|
||||
outputs:
|
||||
checked: ${{ steps.get_checkbox.outputs.checked }}
|
||||
steps:
|
||||
|
||||
9
.github/workflows/codeql-analysis.yml
vendored
9
.github/workflows/codeql-analysis.yml
vendored
@@ -44,10 +44,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -57,7 +58,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -70,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@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
|
||||
# ℹ️ 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
|
||||
@@ -83,6 +84,6 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
|
||||
uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
|
||||
with:
|
||||
category: '/language:${{matrix.language}}'
|
||||
|
||||
7
.github/workflows/docker.yml
vendored
7
.github/workflows/docker.yml
vendored
@@ -23,10 +23,11 @@ jobs:
|
||||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Check what should run
|
||||
id: check
|
||||
@@ -60,7 +61,7 @@ jobs:
|
||||
suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn']
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -90,7 +91,7 @@ jobs:
|
||||
suffix: ['']
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4.3.0
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
|
||||
6
.github/workflows/docs-build.yml
vendored
6
.github/workflows/docs-build.yml
vendored
@@ -21,10 +21,11 @@ jobs:
|
||||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Check what should run
|
||||
id: check
|
||||
@@ -54,10 +55,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
9
.github/workflows/docs-deploy.yml
vendored
9
.github/workflows/docs-deploy.yml
vendored
@@ -20,10 +20,12 @@ jobs:
|
||||
artifact: ${{ steps.get-artifact.outputs.result }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-actions: read
|
||||
permission-pull-requests: read
|
||||
|
||||
- if: ${{ github.event.workflow_run.conclusion != 'success' }}
|
||||
run: echo 'The triggering workflow did not succeed' && exit 1
|
||||
@@ -126,10 +128,13 @@ jobs:
|
||||
if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
permission-actions: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
4
.github/workflows/docs-destroy.yml
vendored
4
.github/workflows/docs-destroy.yml
vendored
@@ -17,10 +17,12 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
56
.github/workflows/fdroid.yml
vendored
Normal file
56
.github/workflows/fdroid.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Update F-Droid Repo
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
update-index:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !github.event.release.prerelease }}
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout pubspec for versionCode
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
ref: ${{ github.event.release.tag_name }}
|
||||
persist-credentials: false
|
||||
sparse-checkout: mobile/pubspec.yaml
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: Update F-Droid repo
|
||||
env:
|
||||
GITLAB_TOKEN: ${{ secrets.FDROID_REPO_TOKEN }}
|
||||
RELEASE: ${{ toJSON(github.event.release) }}
|
||||
TAG: ${{ github.event.release.tag_name }}
|
||||
run: |
|
||||
VERSION_CODE=$(yq '.version' mobile/pubspec.yaml | cut -d+ -f2)
|
||||
export VERSION_CODE
|
||||
|
||||
NEW_ENTRY=$(yq -P '
|
||||
[.assets[] | select(.name == "app-release.apk")] as $matches |
|
||||
with(select($matches | length == 0); error("app-release.apk not found in release assets")) |
|
||||
{
|
||||
"url": $matches[0].browser_download_url,
|
||||
"sha256sum": ($matches[0].digest | sub("^sha256:", "")),
|
||||
"date": (.published_at | split("T") | .[0]),
|
||||
"version-code": env(VERSION_CODE)
|
||||
} | .date tag= "!!timestamp"
|
||||
' <<< "$RELEASE")
|
||||
export NEW_ENTRY
|
||||
|
||||
git clone --depth 1 "https://oauth2:${GITLAB_TOKEN}@gitlab.futo.org/fdroid/repo-v2.git" fdroid-repo
|
||||
cd fdroid-repo
|
||||
|
||||
yq -i '
|
||||
with(select([.apks[] | select(."version-code" == env(VERSION_CODE))] | length > 0); error("version-code already in index")) |
|
||||
.apks = [env(NEW_ENTRY)] + .apks
|
||||
' apps/Immich/index.yml
|
||||
|
||||
git config user.name "Immich Release Bot"
|
||||
git config user.email "bot@immich.app"
|
||||
git commit -am "Immich: add version-code ${VERSION_CODE} (${TAG})"
|
||||
git push
|
||||
4
.github/workflows/fix-format.yml
vendored
4
.github/workflows/fix-format.yml
vendored
@@ -15,10 +15,12 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: write
|
||||
permission-pull-requests: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
2
.github/workflows/merge-translations.yml
vendored
2
.github/workflows/merge-translations.yml
vendored
@@ -35,6 +35,8 @@ jobs:
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: write
|
||||
permission-pull-requests: write
|
||||
|
||||
- name: Find translation PR
|
||||
id: find_pr
|
||||
|
||||
5
.github/workflows/pr-label-validation.yml
vendored
5
.github/workflows/pr-label-validation.yml
vendored
@@ -14,13 +14,14 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-pull-requests: write
|
||||
|
||||
- name: Require PR to have a changelog label
|
||||
uses: mheap/github-action-required-labels@0ac283b4e65c1fb28ce6079dea5546ceca98ccbe # v5.5.2
|
||||
uses: mheap/github-action-required-labels@23e10fde7e062233401931a0eece796cd9bf3177 # v5.6.0
|
||||
with:
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
mode: exactly
|
||||
|
||||
6
.github/workflows/pr-labeler.yml
vendored
6
.github/workflows/pr-labeler.yml
vendored
@@ -12,11 +12,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
|
||||
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
|
||||
with:
|
||||
repo-token: ${{ steps.token.outputs.token }}
|
||||
|
||||
7
.github/workflows/prepare-release.yml
vendored
7
.github/workflows/prepare-release.yml
vendored
@@ -54,10 +54,11 @@ jobs:
|
||||
permissions: {} # No job-level permissions are needed because it uses the app-token
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: write
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -73,7 +74,7 @@ jobs:
|
||||
|
||||
# TODO move to mise
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
||||
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
||||
|
||||
- name: Bump version
|
||||
env:
|
||||
@@ -135,6 +136,8 @@ jobs:
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: write
|
||||
permission-actions: read
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
6
.github/workflows/preview-label.yaml
vendored
6
.github/workflows/preview-label.yaml
vendored
@@ -14,10 +14,11 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-pull-requests: write
|
||||
|
||||
- uses: immich-app/devtools/actions/sticky-comment@0135acd12ad9f3369b94a2aa3c0ae8c835a4e926 # sticky-comment-action-v1.0.0
|
||||
with:
|
||||
@@ -32,10 +33,11 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-pull-requests: write
|
||||
|
||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
|
||||
3
.github/workflows/sdk.yml
vendored
3
.github/workflows/sdk.yml
vendored
@@ -16,10 +16,11 @@ jobs:
|
||||
packages: write
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
7
.github/workflows/static_analysis.yml
vendored
7
.github/workflows/static_analysis.yml
vendored
@@ -20,10 +20,11 @@ jobs:
|
||||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Check what should run
|
||||
id: check
|
||||
@@ -33,6 +34,7 @@ jobs:
|
||||
filters: |
|
||||
mobile:
|
||||
- 'mobile/**'
|
||||
- 'i18n/en.json'
|
||||
force-filters: |
|
||||
- '.github/workflows/static_analysis.yml'
|
||||
force-events: 'workflow_dispatch,release'
|
||||
@@ -49,10 +51,11 @@ jobs:
|
||||
working-directory: ./mobile
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
54
.github/workflows/test.yml
vendored
54
.github/workflows/test.yml
vendored
@@ -17,10 +17,11 @@ jobs:
|
||||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Check what should run
|
||||
id: check
|
||||
@@ -77,10 +78,11 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -105,10 +107,11 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -136,10 +139,11 @@ jobs:
|
||||
working-directory: ./packages/cli
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -167,10 +171,11 @@ jobs:
|
||||
working-directory: ./packages/cli
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -211,10 +216,11 @@ jobs:
|
||||
working-directory: ./web
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -249,10 +255,11 @@ jobs:
|
||||
working-directory: ./web
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -277,10 +284,11 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -327,10 +335,11 @@ jobs:
|
||||
working-directory: ./e2e
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -359,10 +368,11 @@ jobs:
|
||||
working-directory: ./server
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -395,10 +405,11 @@ jobs:
|
||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -472,10 +483,11 @@ jobs:
|
||||
runner: [ubuntu-latest, ubuntu-24.04-arm]
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -580,10 +592,11 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
@@ -618,10 +631,11 @@ jobs:
|
||||
working-directory: ./machine-learning
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
@@ -648,10 +662,11 @@ jobs:
|
||||
working-directory: ./.github
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -678,10 +693,11 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
@@ -699,10 +715,11 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -757,10 +774,11 @@ jobs:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
|
||||
6
.github/workflows/weblate-lock.yml
vendored
6
.github/workflows/weblate-lock.yml
vendored
@@ -24,10 +24,11 @@ jobs:
|
||||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Check what should run
|
||||
id: check
|
||||
@@ -47,10 +48,11 @@ jobs:
|
||||
if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }}
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@9db058b2e6eec20e07760b0e17a0505c78ec3191 # create-workflow-token-action-v2.0.1
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-pull-requests: read
|
||||
|
||||
- name: Bot review status
|
||||
env:
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
/web/ @danieldietzler
|
||||
/machine-learning/ @mertalev
|
||||
/e2e/ @danieldietzler
|
||||
/mobile/ @shenlong-tanwen @santoshakil
|
||||
/mobile/ @shenlong-tanwen @santoshakil @agg23
|
||||
|
||||
@@ -85,7 +85,7 @@ services:
|
||||
container_name: immich_prometheus
|
||||
ports:
|
||||
- 9090:9090
|
||||
image: prom/prometheus@sha256:a75c5a35bc21d7afe69551eefa3cb1e1fb1775fe759408007a66b54ec3de1f29
|
||||
image: prom/prometheus@sha256:3c42b892cf723fa54d2f262c37a0e1f80aa8c8ddb1da7b9b0df9455a35a7f893
|
||||
volumes:
|
||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus-data:/prometheus
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
# System Integrity
|
||||
|
||||
## Integrity report
|
||||
|
||||
At a [customizable interval](https://my.immich.app/admin/system-settings?isOpen=integrity-checks), Immich runs integrity checks to ensure that your library is still intact and there are no corrupt files.
|
||||
There are three kind of issues Immich checks for:
|
||||
|
||||
- Untracked files: the path was found in Immich's directories but it is not referenced in Immich's database
|
||||
- Missing files: the path is found in the Immich internal database, but does not actually exist on disk
|
||||
- Checksum mismatches: the checksum of the file stored in Immich's database does not match the actual file's checksum anymore
|
||||
|
||||
All three run nightly at 3am by default. For the "Checksum files" check, there are additional time and progress limits, as those are the most taxing checks. With these additional limits, Immich can slowly check checksums of your files over the course of a couple of days.
|
||||
|
||||
You can see the results of these checks on the [maintenance](https://my.immich.app/admin/maintenance) page. Here, you can also trigger a full scan (a _check_) for specific jobs, or all of them. In addition, you can also _refresh_ checks. This will only look at items that have currently been reported on, and check if those have been fixed.
|
||||
|
||||
### Common causes
|
||||
|
||||
Most common are untracked files. In many cases those are corrupted thumbnails or encoded videos that have been partially generated at some point and never got cleaned up properly. These are usually fine to delete, as both can always be regenerated at a later point. Other files will need to be investigated on a case-by-case basis by checking they already exist in Immich and thinking about how they might have gotten untracked.
|
||||
|
||||
:::info
|
||||
You might want to run the _missing_ jobs for thumbnails and encoded videos (https://my.immich.app/admin/queues) to make sure all your assets have proper thumbnails and encoded videos. Watch the server logs while running the jobs, in case there are any issues with some assets.
|
||||
:::
|
||||
|
||||
Missing files are files where Immich references them internally, but they don't actually exist on disk in that location. It could be that you deleted a file on disk from the internal library (don't do that, Immich doesn't support it). It could also be that there are issues with your file storage. Please carefully investigate missing files, and never hesitate to reach out on [our Discord](https://discord.immich.app) if you have any questions!
|
||||
|
||||
Checksum mismatches are often indicative of file system corruption. It could also be that you previously edited a file from the internal library on the disk, which is also not supported and will cause a checksum mismatch. Again, the recommended action is to look at any reported item individually, check it out, try to remember if you changed it or some metadata on it at some point. If you edited the file, the supported resolution is to delete the mismatched asset from Immich and reupload it as a new asset.
|
||||
|
||||
## Folder checks
|
||||
|
||||
:::info
|
||||
@@ -40,7 +65,7 @@ The above error messages show that the server has previously (successfully) writ
|
||||
|
||||
### Ignoring the checks
|
||||
|
||||
:::warning
|
||||
:::danger
|
||||
The checks are designed to catch common problems that we have seen users have in the past, and often indicate there's something wrong that you should solve. If you know what you're doing and you want to disable them you can set the following environment variable:
|
||||
:::
|
||||
|
||||
|
||||
@@ -99,6 +99,21 @@ To see local changes to `@immich/ui` in Immich, do the following:
|
||||
2. Run `mise //mobile:translation` to generate the translation file.
|
||||
3. Change to the `mobile/` directory and run `flutter run` to start the app.
|
||||
|
||||
##### iOS Code Signing
|
||||
|
||||
The Immich Apple Team ID and bundle IDs are specified in `mobile/ios/Signing.xcconfig`. For local development, we provide an override mechanism.
|
||||
|
||||
Create `mobile/ios/Signing.local.xcconfig` and populate it with the necessary values needed to build and sign Immich yourself. This local override file is gitignored.
|
||||
|
||||
```
|
||||
IMMICH_TEAM_ID = ABCDE12345
|
||||
IMMICH_BUNDLE_ID_PROD = com.customuniqueid.immich
|
||||
IMMICH_BUNDLE_ID_DEV = com.customuniqueid.immichdev
|
||||
IMMICH_GROUP_ID = group.com.customuniqueid.immich
|
||||
```
|
||||
|
||||
The environment values are used across Immich's targets and schemes to prevent redundant edits by contributors.
|
||||
|
||||
#### Translation
|
||||
|
||||
To add a new translation text, enter the key-value pair in the `i18n/en.json` in the root of the immich project. Then run:
|
||||
|
||||
@@ -99,6 +99,7 @@ Options:
|
||||
-H, --include-hidden Include hidden folders (default: false, env: IMMICH_INCLUDE_HIDDEN)
|
||||
-a, --album Automatically create albums based on folder name (default: false, env: IMMICH_AUTO_CREATE_ALBUM)
|
||||
-A, --album-name <name> Add all assets to specified album (env: IMMICH_ALBUM_NAME)
|
||||
--visibility <visibility> Set the visibility of uploaded assets (choices: "archive", "timeline", "hidden", "locked", env: IMMICH_VISIBILITY)
|
||||
-n, --dry-run Don't perform any actions, just show what will be done (default: false, env: IMMICH_DRY_RUN)
|
||||
-c, --concurrency <number> Number of assets to upload at the same time (default: 4, env: IMMICH_UPLOAD_CONCURRENCY)
|
||||
-j, --json-output Output detailed information in json format (default: false, env: IMMICH_JSON_OUTPUT)
|
||||
@@ -176,6 +177,12 @@ By default, hidden files are skipped. If you want to include hidden files, use t
|
||||
immich upload --include-hidden --recursive directory/
|
||||
```
|
||||
|
||||
You can set the visibility of uploaded assets to `archive`, `timeline`, `hidden`, or `locked` with the `--visibility` option:
|
||||
|
||||
```bash
|
||||
immich upload --visibility archive --recursive directory/
|
||||
```
|
||||
|
||||
You can use the `--json-output` option to get a json printed which includes
|
||||
three keys: `newFiles`, `duplicates` and `newAssets`. Due to some logging
|
||||
output you will need to strip the first three lines of output to get the json.
|
||||
|
||||
@@ -121,7 +121,7 @@ alt="Go to Docker Tab and visit the address listed next to immich-web"
|
||||
width="90%"
|
||||
alt="Go to Docker Tab and visit the address listed next to immich-web"
|
||||
/>
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
:::tip
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
The mobile app can be downloaded from the following places:
|
||||
|
||||
- Obtainium: You can get your Obtainium config link from the [Utilities page of your Immich server](https://my.immich.app/utilities).
|
||||
- [Google Play Store](https://play.google.com/store/apps/details?id=app.alextran.immich)
|
||||
- [Apple App Store](https://apps.apple.com/us/app/immich/id1613945652)
|
||||
- [F-Droid](https://f-droid.org/packages/app.alextran.immich)
|
||||
- [GitHub Releases (apk)](https://github.com/immich-app/immich/releases)
|
||||
- [Google Play Store](https://play.google.com/store/apps/details?id=app.alextran.immich)
|
||||
- [GitHub Releases (APK)](https://github.com/immich-app/immich/releases)
|
||||
- Obtainium: You can get your Obtainium config link from the [Utilities page of your Immich server](https://my.immich.app/utilities).
|
||||
- [F-Droid](https://app.futo.org/fdroid/repo/)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
||||
|
||||
[[tools.wrangler]]
|
||||
version = "4.100.0"
|
||||
version = "4.110.0"
|
||||
backend = "npm:wrangler"
|
||||
|
||||
[tools.wrangler.options]
|
||||
|
||||
@@ -28,4 +28,4 @@ run = "prettier --write ."
|
||||
run = "wrangler pages deploy build --project-name=${PROJECT_NAME} --branch=${BRANCH_NAME}"
|
||||
|
||||
[tools]
|
||||
wrangler = "4.100.0"
|
||||
wrangler = "4.110.0"
|
||||
|
||||
4
docs/static/archived-versions.json
vendored
4
docs/static/archived-versions.json
vendored
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"label": "v3.0.2",
|
||||
"url": "https://docs.v3.0.2.archive.immich.app"
|
||||
"label": "v3.0.3",
|
||||
"url": "https://docs.v3.0.3.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.7.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.3",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
@@ -32,7 +32,7 @@
|
||||
"@playwright/test": "^1.44.1",
|
||||
"@socket.io/component-emitter": "^3.1.2",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/node": "^24.13.2",
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/pg": "^8.15.1",
|
||||
"@types/pngjs": "^6.0.4",
|
||||
"@types/supertest": "^7.0.0",
|
||||
|
||||
@@ -796,5 +796,22 @@ describe('/albums', () => {
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest('Not found or no album.share access'));
|
||||
});
|
||||
|
||||
it('should not allow an editor to change the role of an owner', async () => {
|
||||
const album = await utils.createAlbum(user1.accessToken, {
|
||||
albumName: 'testAlbum',
|
||||
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Editor }],
|
||||
});
|
||||
|
||||
expect(album.albumUsers[1].role).toEqual(AlbumUserRole.Editor);
|
||||
|
||||
const { status, body } = await request(app)
|
||||
.put(`/albums/${album.id}/user/${user1.userId}`)
|
||||
.set('Authorization', `Bearer ${user2.accessToken}`)
|
||||
.send({ role: AlbumUserRole.Editor });
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest('User is owner'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
15
i18n/en.json
15
i18n/en.json
@@ -814,7 +814,6 @@
|
||||
"custom_date": "Custom date",
|
||||
"custom_locale": "Custom locale",
|
||||
"custom_locale_description": "Format dates, times, and numbers based on the selected language and region",
|
||||
"custom_url": "Custom URL",
|
||||
"cutoff_date_description": "Keep photos from the last…",
|
||||
"cutoff_day": "{count, plural, one {day} other {days}}",
|
||||
"cutoff_year": "{count, plural, one {year} other {years}}",
|
||||
@@ -1621,7 +1620,7 @@
|
||||
"person": "Person",
|
||||
"person_age_months": "{months, plural, one {# month} other {# months}} old",
|
||||
"person_age_year_months": "1 year, {months, plural, one {# month} other {# months}} old",
|
||||
"person_age_years": "{years, plural, other {# years}} old",
|
||||
"person_age_years": "{years, plural, one {# year} other {# years}} old",
|
||||
"person_birthdate": "Born on {date}",
|
||||
"person_hidden": "{name}{hidden, select, true { (hidden)} other {}}",
|
||||
"person_recognized": "Person recognized",
|
||||
@@ -1787,7 +1786,6 @@
|
||||
"restore_all": "Restore all",
|
||||
"restore_user": "Restore user",
|
||||
"restored_asset": "Restored asset",
|
||||
"result": "Result",
|
||||
"resume": "Resume",
|
||||
"resume_paused_jobs": "Resume {count, plural, one {# paused job} other {# paused jobs}}",
|
||||
"review_duplicates": "Review duplicates",
|
||||
@@ -1949,7 +1947,9 @@
|
||||
"shared_link_app_bar_title": "Shared Links",
|
||||
"shared_link_clipboard_copied_massage": "Copied to clipboard",
|
||||
"shared_link_create_error": "Error while creating shared link",
|
||||
"shared_link_custom_url_description": "Access this shared link with a custom URL",
|
||||
"shared_link_custom_url_description": "Access this shared link with a custom URL name",
|
||||
"shared_link_custom_url_title": "Custom URL",
|
||||
"shared_link_custom_url_warning": "Warning: a custom URL name with a forward slash may not behave as you expect.",
|
||||
"shared_link_edit_description_hint": "Enter the share description",
|
||||
"shared_link_edit_expire_after_option_day": "1 day",
|
||||
"shared_link_edit_expire_after_option_days": "{count} days",
|
||||
@@ -2274,13 +2274,6 @@
|
||||
"workflow_info": "Workflow info",
|
||||
"workflow_json": "Workflow JSON",
|
||||
"workflow_json_help": "Edit the workflow configuration in JSON format. Changes will sync to the visual builder.",
|
||||
"workflow_logging_completed": "Completed",
|
||||
"workflow_logging_disable": "Disable logging",
|
||||
"workflow_logging_disabled_description": "Logging is currently disabled for this workflow.",
|
||||
"workflow_logging_enable": "Enable logging",
|
||||
"workflow_logging_error_step": "Error on step #{step}",
|
||||
"workflow_logging_halted": "Halted",
|
||||
"workflow_logging_halted_step": "Halted on step #{step}",
|
||||
"workflow_name": "Workflow name",
|
||||
"workflow_navigation_prompt": "Are you sure you want to leave without saving your changes?",
|
||||
"workflow_summary": "Workflow summary",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "immich-ml"
|
||||
version = "3.0.2"
|
||||
version = "3.0.3"
|
||||
description = ""
|
||||
authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }]
|
||||
requires-python = ">=3.11,<4.0"
|
||||
|
||||
2
machine-learning/uv.lock
generated
2
machine-learning/uv.lock
generated
@@ -974,7 +974,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "immich-ml"
|
||||
version = "3.0.2"
|
||||
version = "3.0.3"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "aiocache" },
|
||||
|
||||
38
mise.lock
38
mise.lock
@@ -287,43 +287,43 @@ url = "https://github.com/opentofu/opentofu/releases/download/v1.11.6/tofu_1.11.
|
||||
url_api = "https://api.github.com/repos/opentofu/opentofu/releases/assets/391536406"
|
||||
|
||||
[[tools.pnpm]]
|
||||
version = "11.6.0"
|
||||
version = "11.11.0"
|
||||
backend = "aqua:pnpm/pnpm"
|
||||
|
||||
[tools.pnpm."platforms.linux-arm64"]
|
||||
checksum = "sha256:2fec653ff6dadab340d1c3d2214688a7451cc471f39710839440b293ca7c53b0"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.6.0/pnpm-linux-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/445120174"
|
||||
checksum = "sha256:4871093439f036b3082df6102255ac119f3b6f4f50c51c5711fc7c358b8b22d7"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.11.0/pnpm-linux-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/471734816"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.linux-arm64-musl"]
|
||||
checksum = "sha256:56a78c08cf22adf29e7dacb6f7f100139731693863d20fb94a7883463a62169e"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.6.0/pnpm-linux-arm64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/445120177"
|
||||
checksum = "sha256:f97316cee0deb3ae3fd64e8a09e1c8c88a76da33373a2b465bd6a4c3e85e0690"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.11.0/pnpm-linux-arm64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/471734819"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.linux-x64"]
|
||||
checksum = "sha256:74d64c1646385fb21691f32f0ab6aca1a9f5c829ba54d3cda3a24838a228e68c"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.6.0/pnpm-linux-x64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/445120176"
|
||||
checksum = "sha256:df4699e897012ab14df2cc6eaa942910e830eb7fcaa420a2a1421a9461fd9108"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.11.0/pnpm-linux-x64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/471734818"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.linux-x64-musl"]
|
||||
checksum = "sha256:7a0c463a09d912fba6b7d9eca0a946bc228ea50f3015a05c09a29e7e85a932d7"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.6.0/pnpm-linux-x64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/445120175"
|
||||
checksum = "sha256:aad186f8a8ae72d827d5efe63e99e801456715fb7f2798949405fa33f20260db"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.11.0/pnpm-linux-x64-musl.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/471734821"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.macos-arm64"]
|
||||
checksum = "sha256:87c901635a14481fb30566a3749041134ffd4317bc6fe866c345b69fdf9b6b85"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.6.0/pnpm-darwin-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/445120180"
|
||||
checksum = "sha256:ad46ad16c2376c2b78354ac488c1b166e076aa59bfcbcfd567d55957d755a690"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.11.0/pnpm-darwin-arm64.tar.gz"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/471734814"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[tools.pnpm."platforms.windows-x64"]
|
||||
checksum = "sha256:91c753435542b04859c689304fae0dd64eba6b40937cfa426a48485b712e4e9c"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.6.0/pnpm-win32-x64.zip"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/445120173"
|
||||
checksum = "sha256:13ad8a9b139c4c829fea33462cf04d061d72f0926b2b76a92ac03c9a36e405f9"
|
||||
url = "https://github.com/pnpm/pnpm/releases/download/v11.11.0/pnpm-win32-x64.zip"
|
||||
url_api = "https://api.github.com/repos/pnpm/pnpm/releases/assets/471734820"
|
||||
provenance = "github-attestations"
|
||||
|
||||
[[tools.terragrunt]]
|
||||
|
||||
@@ -16,7 +16,7 @@ config_roots = [
|
||||
|
||||
[tools]
|
||||
node = "24.15.0"
|
||||
pnpm = "11.6.0"
|
||||
pnpm = "11.11.0"
|
||||
terragrunt = "1.0.3"
|
||||
opentofu = "1.11.6"
|
||||
"npm:oazapfts" = "7.5.0"
|
||||
|
||||
@@ -89,13 +89,6 @@ flutter {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
constraints {
|
||||
implementation("androidx.glance:glance-appwidget") {
|
||||
version { strictly libs.versions.glance.get() }
|
||||
because 'home_widget requests 1.+ which can resolve to pre-releases incompatible with our compileSdk/AGP'
|
||||
}
|
||||
}
|
||||
|
||||
implementation libs.okhttp
|
||||
implementation libs.cronet.embedded
|
||||
implementation libs.media3.datasource.okhttp
|
||||
|
||||
@@ -64,13 +64,7 @@ fun Bitmap.toNativeBuffer(): Map<String, Long> {
|
||||
// native convert declined (OOM/lock) -> fall through to the Skia copy path below.
|
||||
}
|
||||
// Other non-8888 configs (e.g. HDR F16) still need Skia's convert; 8-bit is copied as-is.
|
||||
val bitmap = if (config != Bitmap.Config.ARGB_8888) {
|
||||
val converted = copy(Bitmap.Config.ARGB_8888, false)
|
||||
recycle()
|
||||
converted ?: throw IOException("could not convert bitmap to ARGB_8888")
|
||||
} else {
|
||||
this
|
||||
}
|
||||
val bitmap = toArgb8888()
|
||||
val size = bitmap.width * bitmap.height * 4
|
||||
val pointer = NativeBuffer.allocate(size)
|
||||
try {
|
||||
@@ -217,7 +211,7 @@ class LocalImagesImpl(context: Context) : LocalImageApi {
|
||||
if (orientation == ExifInterface.ORIENTATION_NORMAL || orientation == ExifInterface.ORIENTATION_UNDEFINED) {
|
||||
bitmap.toNativeBuffer()
|
||||
} else {
|
||||
rotateToNativeBuffer(bitmap, orientation, signal)
|
||||
rotateToNativeBuffer(bitmap, orientation)
|
||||
}
|
||||
}
|
||||
// Don't re-check cancellation here: res owns a malloc'd buffer, and bailing to CANCELLED would
|
||||
@@ -257,39 +251,7 @@ class LocalImagesImpl(context: Context) : LocalImageApi {
|
||||
}
|
||||
|
||||
private fun rawOrientation(uri: Uri): Int {
|
||||
return resolver.openInputStream(uri)?.use {
|
||||
ExifInterface(it).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
||||
} ?: ExifInterface.ORIENTATION_NORMAL
|
||||
}
|
||||
|
||||
// ImageDecoder / loadThumbnail skip EXIF orientation for raw (e.g. DNG) on Q+, so the decoded
|
||||
// bitmap comes back unrotated. Rotate it into the output buffer in native code (one pass, no
|
||||
// intermediate rotated bitmap).
|
||||
private fun rotateToNativeBuffer(bitmap: Bitmap, orientation: Int, signal: CancellationSignal): Map<String, Long> {
|
||||
signal.throwIfCanceled()
|
||||
// Force ARGB_8888: the native rotate needs a lockable 8888 buffer, and toNativeBuffer() below
|
||||
// allocates width*height*4 (an F16/HDR decode would otherwise under-allocate). No-op for the
|
||||
// common already-8888 case.
|
||||
val src = if (bitmap.config != Bitmap.Config.ARGB_8888) {
|
||||
val converted = bitmap.copy(Bitmap.Config.ARGB_8888, false)
|
||||
bitmap.recycle()
|
||||
converted ?: throw IOException("could not convert bitmap to ARGB_8888")
|
||||
} else {
|
||||
bitmap
|
||||
}
|
||||
try {
|
||||
val info = IntArray(3)
|
||||
val pointer = NativeImage.rotate(src, orientation, info)
|
||||
if (pointer == 0L) throw IOException("native rotate failed for orientation $orientation")
|
||||
return mapOf(
|
||||
"pointer" to pointer,
|
||||
"width" to info[0].toLong(),
|
||||
"height" to info[1].toLong(),
|
||||
"rowBytes" to info[2].toLong()
|
||||
)
|
||||
} finally {
|
||||
if (!src.isRecycled) src.recycle()
|
||||
}
|
||||
return resolver.openInputStream(uri)?.use { readOrientation(it) } ?: ExifInterface.ORIENTATION_NORMAL
|
||||
}
|
||||
|
||||
private fun decodeVideoThumbnail(id: Long, target: Size, signal: CancellationSignal): Bitmap {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package app.alextran.immich.images
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import app.alextran.immich.NativeImage
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
fun readOrientation(input: InputStream): Int =
|
||||
ExifInterface(input).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
||||
|
||||
// Reads the EXIF orientation (TIFF tag 0x0112) from a raw file's IFD0.
|
||||
fun readRawOrientation(buffer: ByteBuffer, len: Int): Int {
|
||||
try {
|
||||
if (len < 8) return ExifInterface.ORIENTATION_NORMAL
|
||||
buffer.order(
|
||||
when (buffer.get(0).toInt() and 0xFF) {
|
||||
0x49 -> ByteOrder.LITTLE_ENDIAN
|
||||
0x4D -> ByteOrder.BIG_ENDIAN
|
||||
else -> return ExifInterface.ORIENTATION_NORMAL
|
||||
}
|
||||
)
|
||||
val ifd0 = buffer.getInt(4).toLong() and 0xFFFFFFFFL
|
||||
if (ifd0 < 8 || ifd0 + 2 > len) return ExifInterface.ORIENTATION_NORMAL
|
||||
val start = ifd0.toInt()
|
||||
val entries = buffer.getShort(start).toInt() and 0xFFFF
|
||||
if (entries <= 0 || entries > 512) return ExifInterface.ORIENTATION_NORMAL
|
||||
// Each IFD entry is 12 bytes: tag(2) type(2) count(4) value(4); orientation is a SHORT in value.
|
||||
for (i in 0 until entries) {
|
||||
val p = start + 2 + i * 12
|
||||
if (p + 12 > len) return ExifInterface.ORIENTATION_NORMAL
|
||||
if ((buffer.getShort(p).toInt() and 0xFFFF) == 0x0112) {
|
||||
val value = buffer.getShort(p + 8).toInt() and 0xFFFF
|
||||
return if (value in 1..8) value else ExifInterface.ORIENTATION_NORMAL
|
||||
}
|
||||
}
|
||||
return ExifInterface.ORIENTATION_NORMAL
|
||||
} catch (_: Exception) {
|
||||
return ExifInterface.ORIENTATION_NORMAL
|
||||
}
|
||||
}
|
||||
|
||||
fun Bitmap.toArgb8888(): Bitmap {
|
||||
if (config == Bitmap.Config.ARGB_8888) return this
|
||||
val converted = copy(Bitmap.Config.ARGB_8888, false)
|
||||
recycle()
|
||||
return converted ?: throw IOException("could not convert bitmap to ARGB_8888")
|
||||
}
|
||||
|
||||
// Force ARGB_8888 first: the native rotate needs a lockable 8888 buffer and allocates w*h*4.
|
||||
fun rotateToNativeBuffer(bitmap: Bitmap, orientation: Int): Map<String, Long> {
|
||||
val src = bitmap.toArgb8888()
|
||||
try {
|
||||
val info = IntArray(3)
|
||||
val pointer = NativeImage.rotate(src, orientation, info)
|
||||
if (pointer == 0L) throw IOException("native rotate failed for orientation $orientation")
|
||||
return mapOf(
|
||||
"pointer" to pointer,
|
||||
"width" to info[0].toLong(),
|
||||
"height" to info[1].toLong(),
|
||||
"rowBytes" to info[2].toLong()
|
||||
)
|
||||
} finally {
|
||||
if (!src.isRecycled) src.recycle()
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import android.graphics.ImageDecoder
|
||||
import android.os.Build
|
||||
import android.os.CancellationSignal
|
||||
import android.os.OperationCanceledException
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import app.alextran.immich.INITIAL_BUFFER_SIZE
|
||||
import app.alextran.immich.NativeBuffer
|
||||
import app.alextran.immich.NativeByteBuffer
|
||||
@@ -30,6 +31,35 @@ private const val MAX_PREALLOC_BYTES = 128 * 1024 * 1024
|
||||
|
||||
private class RemoteRequest(val cancellationSignal: CancellationSignal)
|
||||
|
||||
// The full mimeTypes.raw set the server can serve (short + vendor forms).
|
||||
private val RAW_MIME_TYPES = setOf(
|
||||
"image/3fr", "image/ari", "image/arw",
|
||||
"image/cap", "image/cin", "image/cr2",
|
||||
"image/cr3", "image/crw", "image/dcr",
|
||||
"image/dng", "image/erf", "image/fff",
|
||||
"image/iiq", "image/k25", "image/kdc",
|
||||
"image/mrw", "image/nef", "image/nrw",
|
||||
"image/orf", "image/ori", "image/pef",
|
||||
"image/psd", "image/raf", "image/raw",
|
||||
"image/rw2", "image/rwl", "image/sr2",
|
||||
"image/srf", "image/srw", "image/vnd.adobe.photoshop",
|
||||
"image/x-adobe-dng", "image/x-arriflex-ari", "image/x-canon-cr2",
|
||||
"image/x-canon-cr3", "image/x-canon-crw", "image/x-epson-erf",
|
||||
"image/x-fuji-raf", "image/x-hasselblad-3fr", "image/x-hasselblad-fff",
|
||||
"image/x-kodak-dcr", "image/x-kodak-k25", "image/x-kodak-kdc",
|
||||
"image/x-leica-rwl", "image/x-minolta-mrw", "image/x-nikon-nef",
|
||||
"image/x-nikon-nrw", "image/x-olympus-orf", "image/x-olympus-ori",
|
||||
"image/x-panasonic-raw", "image/x-panasonic-rw2", "image/x-pentax-pef",
|
||||
"image/x-phantom-cin", "image/x-phaseone-cap", "image/x-phaseone-iiq",
|
||||
"image/x-samsung-srw", "image/x-sigma-x3f", "image/x-sony-arw",
|
||||
"image/x-sony-sr2", "image/x-sony-srf", "image/x3f",
|
||||
)
|
||||
|
||||
private fun isRawMime(contentType: String?): Boolean {
|
||||
val mime = contentType?.substringBefore(';')?.trim()?.lowercase() ?: return false
|
||||
return mime in RAW_MIME_TYPES
|
||||
}
|
||||
|
||||
class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
||||
private val requestMap = ConcurrentHashMap<Long, RemoteRequest>()
|
||||
|
||||
@@ -57,7 +87,7 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
||||
ImageFetcherManager.fetch(
|
||||
url,
|
||||
signal,
|
||||
onSuccess = { buffer ->
|
||||
onSuccess = { buffer, contentType ->
|
||||
if (signal.isCanceled) {
|
||||
requestMap.remove(requestId)
|
||||
buffer.free()
|
||||
@@ -72,8 +102,18 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
||||
if (!preferEncoded && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
decodeExecutor.execute {
|
||||
val res = if (signal.isCanceled) null else try {
|
||||
val source = ImageDecoder.createSource(NativeBuffer.wrap(buffer.pointer, buffer.offset))
|
||||
source.decodeBitmap().toNativeBuffer()
|
||||
val bitmap = ImageDecoder.createSource(NativeBuffer.wrap(buffer.pointer, buffer.offset)).decodeBitmap()
|
||||
// The embedded preview a raw decodes to has no orientation, so read the container's.
|
||||
val orientation = if (isRawMime(contentType)) {
|
||||
readRawOrientation(NativeBuffer.wrap(buffer.pointer, buffer.offset), buffer.offset)
|
||||
} else {
|
||||
ExifInterface.ORIENTATION_NORMAL
|
||||
}
|
||||
if (orientation == ExifInterface.ORIENTATION_NORMAL || orientation == ExifInterface.ORIENTATION_UNDEFINED) {
|
||||
bitmap.toNativeBuffer()
|
||||
} else {
|
||||
rotateToNativeBuffer(bitmap, orientation)
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
null
|
||||
}
|
||||
@@ -154,7 +194,7 @@ private object ImageFetcherManager {
|
||||
fun fetch(
|
||||
url: String,
|
||||
signal: CancellationSignal,
|
||||
onSuccess: (NativeByteBuffer) -> Unit,
|
||||
onSuccess: (NativeByteBuffer, String?) -> Unit,
|
||||
onFailure: (Exception) -> Unit,
|
||||
) {
|
||||
fetcher.fetch(url, signal, onSuccess, onFailure)
|
||||
@@ -185,7 +225,7 @@ private sealed interface ImageFetcher {
|
||||
fun fetch(
|
||||
url: String,
|
||||
signal: CancellationSignal,
|
||||
onSuccess: (NativeByteBuffer) -> Unit,
|
||||
onSuccess: (NativeByteBuffer, String?) -> Unit,
|
||||
onFailure: (Exception) -> Unit,
|
||||
)
|
||||
|
||||
@@ -203,7 +243,7 @@ private class CronetImageFetcher : ImageFetcher {
|
||||
override fun fetch(
|
||||
url: String,
|
||||
signal: CancellationSignal,
|
||||
onSuccess: (NativeByteBuffer) -> Unit,
|
||||
onSuccess: (NativeByteBuffer, String?) -> Unit,
|
||||
onFailure: (Exception) -> Unit,
|
||||
) {
|
||||
synchronized(stateLock) {
|
||||
@@ -271,7 +311,7 @@ private class CronetImageFetcher : ImageFetcher {
|
||||
}
|
||||
|
||||
private class FetchCallback(
|
||||
private val onSuccess: (NativeByteBuffer) -> Unit,
|
||||
private val onSuccess: (NativeByteBuffer, String?) -> Unit,
|
||||
private val onFailure: (Exception) -> Unit,
|
||||
private val onComplete: () -> Unit,
|
||||
) : UrlRequest.Callback() {
|
||||
@@ -328,7 +368,9 @@ private class CronetImageFetcher : ImageFetcher {
|
||||
}
|
||||
|
||||
override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) {
|
||||
onSuccess(buffer!!)
|
||||
val contentType = info.allHeaders.entries
|
||||
.firstOrNull { it.key.equals("content-type", ignoreCase = true) }?.value?.firstOrNull()
|
||||
onSuccess(buffer!!, contentType)
|
||||
onComplete()
|
||||
}
|
||||
|
||||
@@ -379,7 +421,7 @@ private class OkHttpImageFetcher private constructor(
|
||||
override fun fetch(
|
||||
url: String,
|
||||
signal: CancellationSignal,
|
||||
onSuccess: (NativeByteBuffer) -> Unit,
|
||||
onSuccess: (NativeByteBuffer, String?) -> Unit,
|
||||
onFailure: (Exception) -> Unit,
|
||||
) {
|
||||
synchronized(stateLock) {
|
||||
@@ -433,7 +475,7 @@ private class OkHttpImageFetcher private constructor(
|
||||
buffer.ensureHeadroom()
|
||||
}
|
||||
}
|
||||
onSuccess(buffer)
|
||||
onSuccess(buffer, response.header("Content-Type"))
|
||||
} catch (e: Exception) {
|
||||
buffer.free()
|
||||
onFailure(e)
|
||||
|
||||
@@ -22,8 +22,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 3055,
|
||||
"android.injected.version.name" => "3.0.2",
|
||||
"android.injected.version.code" => 3056,
|
||||
"android.injected.version.name" => "3.0.3",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab', track: 'beta')
|
||||
@@ -35,8 +35,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 3055,
|
||||
"android.injected.version.name" => "3.0.2",
|
||||
"android.injected.version.code" => 3056,
|
||||
"android.injected.version.name" => "3.0.3",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||
|
||||
3
mobile/ios/.gitignore
vendored
3
mobile/ios/.gitignore
vendored
@@ -26,6 +26,9 @@ Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Local signing overrides.
|
||||
Signing.local.xcconfig
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '14.0'
|
||||
platform :ios, '15.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
@@ -45,7 +45,7 @@ post_install do |installer|
|
||||
installer.generated_projects.each do |project|
|
||||
project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,12 +12,8 @@ PODS:
|
||||
- Flutter
|
||||
- fluttertoast (0.0.2):
|
||||
- Flutter
|
||||
- home_widget (0.0.1):
|
||||
- Flutter
|
||||
- native_video_player (1.0.0):
|
||||
- Flutter
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- share_handler_ios (0.0.14):
|
||||
- Flutter
|
||||
- share_handler_ios/share_handler_ios_models (= 0.0.14)
|
||||
@@ -34,9 +30,7 @@ DEPENDENCIES:
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- home_widget (from `.symlinks/plugins/home_widget/ios`)
|
||||
- native_video_player (from `.symlinks/plugins/native_video_player/ios`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- share_handler_ios (from `.symlinks/plugins/share_handler_ios/ios`)
|
||||
- share_handler_ios_models (from `.symlinks/plugins/share_handler_ios/ios/Models`)
|
||||
|
||||
@@ -53,12 +47,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||
fluttertoast:
|
||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||
home_widget:
|
||||
:path: ".symlinks/plugins/home_widget/ios"
|
||||
native_video_player:
|
||||
:path: ".symlinks/plugins/native_video_player/ios"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
share_handler_ios:
|
||||
:path: ".symlinks/plugins/share_handler_ios/ios"
|
||||
share_handler_ios_models:
|
||||
@@ -71,12 +61,10 @@ SPEC CHECKSUMS:
|
||||
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
|
||||
native_video_player: b65c58951ede2f93d103a25366bdebca95081265
|
||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||
share_handler_ios: e2244e990f826b2c8eaa291ac3831569438ba0fb
|
||||
share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871
|
||||
|
||||
PODFILE CHECKSUM: 938abbae4114b9c2140c550a2a0d8f7c674f5dfe
|
||||
PODFILE CHECKSUM: 3c43a700a4bffb4120bf696cad263aefd4bb3c8c
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
51516E0F2A0000000000C0F1 /* Signing.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Signing.xcconfig; sourceTree = "<group>"; };
|
||||
8AB817AA297EDEC88B23F3F6 /* Pods_ShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
937632897A02DE9C249F20A6 /* Pods-ShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
@@ -153,11 +154,15 @@
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
B231F52D2E93A44A00BC45D1 /* Core */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
path = Core;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
path = Sync;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -179,6 +184,8 @@
|
||||
};
|
||||
FEE084F22EC172080045228E /* Schemas */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
path = Schemas;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -256,6 +263,7 @@
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51516E0F2A0000000000C0F1 /* Signing.xcconfig */,
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
FAC6F8B62D287F120078CB2F /* ShareExtension */,
|
||||
@@ -370,7 +378,6 @@
|
||||
FAC6F89A2D287C890078CB2F /* Embed Foundation Extensions */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
513DA7292DED6106813332F4 /* [CP] Embed Pods Frameworks */,
|
||||
2FA39DEC809D6D7C4A01EFCB /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -464,7 +471,7 @@
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
packageReferences = (
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
|
||||
FEE084F62EC172460045228E /* XCRemoteSwiftPackageReference "sqlite-data" */,
|
||||
FEE084F92EC1725A0045228E /* XCRemoteSwiftPackageReference "swift-http-structured-headers" */,
|
||||
);
|
||||
@@ -511,27 +518,6 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
2FA39DEC809D6D7C4A01EFCB /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
@@ -556,14 +542,10 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
@@ -714,6 +696,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 51516E0F2A0000000000C0F1 /* Signing.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
@@ -744,7 +727,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share.profile;
|
||||
CUSTOM_GROUP_ID = "$(IMMICH_GROUP_ID).profile";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -757,7 +740,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
NEW_SETTING = "";
|
||||
SDKROOT = iphoneos;
|
||||
@@ -777,16 +760,16 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.profile;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_DEV).profile";
|
||||
PRODUCT_NAME = "Immich-Profile";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -797,6 +780,7 @@
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 51516E0F2A0000000000C0F1 /* Signing.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
@@ -827,7 +811,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share.debug;
|
||||
CUSTOM_GROUP_ID = "$(IMMICH_GROUP_ID).debug";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -846,7 +830,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
NEW_SETTING = "";
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
@@ -857,6 +841,7 @@
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 51516E0F2A0000000000C0F1 /* Signing.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
@@ -887,7 +872,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CUSTOM_GROUP_ID = group.app.immich.share;
|
||||
CUSTOM_GROUP_ID = "$(IMMICH_GROUP_ID)";
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -900,7 +885,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
NEW_SETTING = "";
|
||||
SDKROOT = iphoneos;
|
||||
@@ -922,16 +907,16 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.debug;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_DEV).debug";
|
||||
PRODUCT_NAME = "Immich-Debug";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -951,16 +936,16 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_PROD)";
|
||||
PRODUCT_NAME = Immich;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -984,7 +969,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 240;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1001,7 +986,7 @@
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.debug.Widget;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_DEV).debug.Widget";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
@@ -1027,7 +1012,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 240;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1043,7 +1028,7 @@
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.Widget;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_PROD).Widget";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -1067,7 +1052,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 240;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1083,7 +1068,7 @@
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.profile.Widget;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_DEV).profile.Widget";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -1106,7 +1091,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 240;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1123,7 +1108,7 @@
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.debug.ShareExtension;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_DEV).debug.ShareExtension";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -1149,7 +1134,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 240;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1165,7 +1150,7 @@
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.ShareExtension;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_PROD).ShareExtension";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -1189,7 +1174,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 240;
|
||||
DEVELOPMENT_TEAM = 2W7AC6T8T5;
|
||||
DEVELOPMENT_TEAM = "$(IMMICH_TEAM_ID)";
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -1205,7 +1190,7 @@
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.profile.ShareExtension;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(IMMICH_BUNDLE_ID_DEV).profile.ShareExtension";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -1261,7 +1246,7 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCLocalSwiftPackageReference section */
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
|
||||
isa = XCLocalSwiftPackageReference;
|
||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
|
||||
@@ -122,8 +122,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/pointfreeco/swift-sharing",
|
||||
"state" : {
|
||||
"revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818",
|
||||
"version" : "2.7.4"
|
||||
"revision" : "8244fe63bf43e58188ab13851ad693eecf6a9e90",
|
||||
"version" : "2.9.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.0.2</string>
|
||||
<string>3.0.3</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
29
mobile/ios/Signing.xcconfig
Normal file
29
mobile/ios/Signing.xcconfig
Normal file
@@ -0,0 +1,29 @@
|
||||
// Xcode Signing Constants
|
||||
//
|
||||
// These are integrated into the Xcode project at build time to allow for dynamic signing configs
|
||||
// across our many targets.
|
||||
//
|
||||
// Create `Signing.local.xcconfig` overriding each variable to provide your own personal signing
|
||||
// overrides during local development:
|
||||
// IMMICH_TEAM_ID = ABCDE12345
|
||||
// IMMICH_BUNDLE_ID_PROD = com.customuniqueid.immich
|
||||
// IMMICH_BUNDLE_ID_DEV = com.customuniqueid.immichdev
|
||||
// IMMICH_GROUP_ID = group.com.customuniqueid.immich
|
||||
|
||||
// Apple Developer Team ID used for automatically provisioning signing credentials
|
||||
IMMICH_TEAM_ID = 2W7AC6T8T5
|
||||
|
||||
// Root bundle identifier for the Release configuration.
|
||||
// Extension suffixes (`.ShareExtension`/`.Widget`) will be appended
|
||||
IMMICH_BUNDLE_ID_PROD = app.alextran.immich
|
||||
|
||||
// Root bundle identifier for the Debug and Profile configurations.
|
||||
// Build scheme suffixes (`.debug`/`.profile`) will be appended
|
||||
IMMICH_BUNDLE_ID_DEV = app.futo.immich
|
||||
|
||||
// Root App Group identifier.
|
||||
// Build scheme suffixes (`.debug`/`.profile`) will be appended
|
||||
IMMICH_GROUP_ID = group.app.immich.share
|
||||
|
||||
// Optional per-developer configuration override
|
||||
#include? "Signing.local.xcconfig"
|
||||
@@ -26,7 +26,6 @@ const String kDownloadGroupLivePhoto = 'group_livephoto';
|
||||
const String kShareDownloadGroup = 'group_share';
|
||||
|
||||
// Timeline constants
|
||||
const int kTimelineNoneSegmentSize = 120;
|
||||
const int kTimelineAssetLoadBatchSize = 1024;
|
||||
const int kTimelineAssetLoadOppositeSize = 64;
|
||||
|
||||
|
||||
@@ -70,6 +70,10 @@ class RemoteAsset extends BaseAsset {
|
||||
|
||||
bool get isTrashed => deletedAt != null;
|
||||
|
||||
bool get isStacked => stackId != null;
|
||||
|
||||
bool get isArchived => visibility == .archive;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''Asset {
|
||||
|
||||
@@ -44,16 +44,7 @@ final class $$AssetEditEntityTableReferences
|
||||
static i5.$RemoteAssetEntityTable _assetIdTable(i0.GeneratedDatabase db) =>
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$AssetEditEntityTable>('asset_edit_entity')
|
||||
.assetId,
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('asset_edit_entity__asset_id__remote_asset_entity__id');
|
||||
|
||||
i5.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
final $_column = $_itemColumn<String>('asset_id')!;
|
||||
|
||||
@@ -59,16 +59,7 @@ final class $$AssetFaceEntityTableReferences
|
||||
static i4.$RemoteAssetEntityTable _assetIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$AssetFaceEntityTable>('asset_face_entity')
|
||||
.assetId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('asset_face_entity__asset_id__remote_asset_entity__id');
|
||||
|
||||
i4.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
final $_column = $_itemColumn<String>('asset_id')!;
|
||||
@@ -91,16 +82,7 @@ final class $$AssetFaceEntityTableReferences
|
||||
static i6.$PersonEntityTable _personIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i6.$PersonEntityTable>('person_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$AssetFaceEntityTable>('asset_face_entity')
|
||||
.personId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i6.$PersonEntityTable>('person_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('asset_face_entity__person_id__person_entity__id');
|
||||
|
||||
i6.$$PersonEntityTableProcessedTableManager? get personId {
|
||||
final $_column = $_itemColumn<String>('person_id');
|
||||
|
||||
@@ -61,16 +61,7 @@ final class $$AssetOcrEntityTableReferences
|
||||
static i4.$RemoteAssetEntityTable _assetIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i1.$AssetOcrEntityTable>('asset_ocr_entity').assetId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('asset_ocr_entity__asset_id__remote_asset_entity__id');
|
||||
|
||||
i4.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
final $_column = $_itemColumn<String>('asset_id')!;
|
||||
|
||||
@@ -75,16 +75,7 @@ final class $$RemoteExifEntityTableReferences
|
||||
static i3.$RemoteAssetEntityTable _assetIdTable(i0.GeneratedDatabase db) =>
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteExifEntityTable>('remote_exif_entity')
|
||||
.assetId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('remote_exif_entity__asset_id__remote_asset_entity__id');
|
||||
|
||||
i3.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
final $_column = $_itemColumn<String>('asset_id')!;
|
||||
|
||||
@@ -50,14 +50,7 @@ final class $$LocalAlbumEntityTableReferences
|
||||
) => i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$LocalAlbumEntityTable>('local_album_entity')
|
||||
.linkedRemoteAlbumId,
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity').id,
|
||||
),
|
||||
'local_album_entity__linked_remote_album_id__remote_album_entity__id',
|
||||
);
|
||||
|
||||
i5.$$RemoteAlbumEntityTableProcessedTableManager? get linkedRemoteAlbumId {
|
||||
|
||||
@@ -41,16 +41,7 @@ final class $$LocalAlbumAssetEntityTableReferences
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i3.$LocalAssetEntityTable>('local_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$LocalAlbumAssetEntityTable>(
|
||||
'local_album_asset_entity',
|
||||
)
|
||||
.assetId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i3.$LocalAssetEntityTable>('local_asset_entity').id,
|
||||
),
|
||||
'local_album_asset_entity__asset_id__local_asset_entity__id',
|
||||
);
|
||||
|
||||
i3.$$LocalAssetEntityTableProcessedTableManager get assetId {
|
||||
@@ -75,16 +66,7 @@ final class $$LocalAlbumAssetEntityTableReferences
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$LocalAlbumEntityTable>('local_album_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$LocalAlbumAssetEntityTable>(
|
||||
'local_album_asset_entity',
|
||||
)
|
||||
.albumId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$LocalAlbumEntityTable>('local_album_entity').id,
|
||||
),
|
||||
'local_album_asset_entity__album_id__local_album_entity__id',
|
||||
);
|
||||
|
||||
i5.$$LocalAlbumEntityTableProcessedTableManager get albumId {
|
||||
|
||||
@@ -53,16 +53,7 @@ final class $$MemoryEntityTableReferences
|
||||
static i5.$UserEntityTable _ownerIdTable(i0.GeneratedDatabase db) =>
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i1.$MemoryEntityTable>('memory_entity').ownerId,
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('memory_entity__owner_id__user_entity__id');
|
||||
|
||||
i5.$$UserEntityTableProcessedTableManager get ownerId {
|
||||
final $_column = $_itemColumn<String>('owner_id')!;
|
||||
|
||||
@@ -39,14 +39,7 @@ final class $$MemoryAssetEntityTableReferences
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$MemoryAssetEntityTable>('memory_asset_entity')
|
||||
.assetId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
'memory_asset_entity__asset_id__remote_asset_entity__id',
|
||||
);
|
||||
|
||||
i3.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
@@ -70,16 +63,7 @@ final class $$MemoryAssetEntityTableReferences
|
||||
static i5.$MemoryEntityTable _memoryIdTable(i0.GeneratedDatabase db) =>
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$MemoryEntityTable>('memory_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$MemoryAssetEntityTable>('memory_asset_entity')
|
||||
.memoryId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$MemoryEntityTable>('memory_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('memory_asset_entity__memory_id__memory_entity__id');
|
||||
|
||||
i5.$$MemoryEntityTableProcessedTableManager get memoryId {
|
||||
final $_column = $_itemColumn<String>('memory_id')!;
|
||||
|
||||
@@ -39,16 +39,7 @@ final class $$PartnerEntityTableReferences
|
||||
static i4.$UserEntityTable _sharedByIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i1.$PartnerEntityTable>('partner_entity').sharedById,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('partner_entity__shared_by_id__user_entity__id');
|
||||
|
||||
i4.$$UserEntityTableProcessedTableManager get sharedById {
|
||||
final $_column = $_itemColumn<String>('shared_by_id')!;
|
||||
@@ -71,16 +62,7 @@ final class $$PartnerEntityTableReferences
|
||||
static i4.$UserEntityTable _sharedWithIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$PartnerEntityTable>('partner_entity')
|
||||
.sharedWithId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('partner_entity__shared_with_id__user_entity__id');
|
||||
|
||||
i4.$$UserEntityTableProcessedTableManager get sharedWithId {
|
||||
final $_column = $_itemColumn<String>('shared_with_id')!;
|
||||
|
||||
@@ -48,16 +48,7 @@ final class $$PersonEntityTableReferences
|
||||
static i4.$UserEntityTable _ownerIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i1.$PersonEntityTable>('person_entity').ownerId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('person_entity__owner_id__user_entity__id');
|
||||
|
||||
i4.$$UserEntityTableProcessedTableManager get ownerId {
|
||||
final $_column = $_itemColumn<String>('owner_id')!;
|
||||
|
||||
@@ -52,14 +52,7 @@ final class $$RemoteAlbumEntityTableReferences
|
||||
) => i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAlbumEntityTable>('remote_album_entity')
|
||||
.thumbnailAssetId,
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
'remote_album_entity__thumbnail_asset_id__remote_asset_entity__id',
|
||||
);
|
||||
|
||||
i5.$$RemoteAssetEntityTableProcessedTableManager? get thumbnailAssetId {
|
||||
|
||||
@@ -39,16 +39,7 @@ final class $$RemoteAlbumAssetEntityTableReferences
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAlbumAssetEntityTable>(
|
||||
'remote_album_asset_entity',
|
||||
)
|
||||
.assetId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
'remote_album_asset_entity__asset_id__remote_asset_entity__id',
|
||||
);
|
||||
|
||||
i3.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
@@ -73,16 +64,7 @@ final class $$RemoteAlbumAssetEntityTableReferences
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAlbumAssetEntityTable>(
|
||||
'remote_album_asset_entity',
|
||||
)
|
||||
.albumId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$RemoteAlbumEntityTable>('remote_album_entity').id,
|
||||
),
|
||||
'remote_album_asset_entity__album_id__remote_album_entity__id',
|
||||
);
|
||||
|
||||
i5.$$RemoteAlbumEntityTableProcessedTableManager get albumId {
|
||||
|
||||
@@ -42,16 +42,7 @@ final class $$RemoteAlbumUserEntityTableReferences
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$RemoteAlbumEntityTable>('remote_album_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAlbumUserEntityTable>(
|
||||
'remote_album_user_entity',
|
||||
)
|
||||
.albumId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$RemoteAlbumEntityTable>('remote_album_entity').id,
|
||||
),
|
||||
'remote_album_user_entity__album_id__remote_album_entity__id',
|
||||
);
|
||||
|
||||
i4.$$RemoteAlbumEntityTableProcessedTableManager get albumId {
|
||||
@@ -75,18 +66,7 @@ final class $$RemoteAlbumUserEntityTableReferences
|
||||
static i6.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i6.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAlbumUserEntityTable>(
|
||||
'remote_album_user_entity',
|
||||
)
|
||||
.userId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i6.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('remote_album_user_entity__user_id__user_entity__id');
|
||||
|
||||
i6.$$UserEntityTableProcessedTableManager get userId {
|
||||
final $_column = $_itemColumn<String>('user_id')!;
|
||||
|
||||
@@ -74,16 +74,7 @@ final class $$RemoteAssetEntityTableReferences
|
||||
static i5.$UserEntityTable _ownerIdTable(i0.GeneratedDatabase db) =>
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.ownerId,
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('remote_asset_entity__owner_id__user_entity__id');
|
||||
|
||||
i5.$$UserEntityTableProcessedTableManager get ownerId {
|
||||
final $_column = $_itemColumn<String>('owner_id')!;
|
||||
|
||||
@@ -45,16 +45,7 @@ final class $$RemoteAssetCloudIdEntityTableReferences
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i4.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$RemoteAssetCloudIdEntityTable>(
|
||||
'remote_asset_cloud_id_entity',
|
||||
)
|
||||
.assetId,
|
||||
i4.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i3.$RemoteAssetEntityTable>('remote_asset_entity').id,
|
||||
),
|
||||
'remote_asset_cloud_id_entity__asset_id__remote_asset_entity__id',
|
||||
);
|
||||
|
||||
i3.$$RemoteAssetEntityTableProcessedTableManager get assetId {
|
||||
|
||||
@@ -38,16 +38,7 @@ final class $$StackEntityTableReferences
|
||||
static i4.$UserEntityTable _ownerIdTable(i0.GeneratedDatabase db) =>
|
||||
i5.ReadDatabaseContainer(db)
|
||||
.resultSet<i4.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i1.$StackEntityTable>('stack_entity').ownerId,
|
||||
i5.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i4.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('stack_entity__owner_id__user_entity__id');
|
||||
|
||||
i4.$$UserEntityTableProcessedTableManager get ownerId {
|
||||
final $_column = $_itemColumn<String>('owner_id')!;
|
||||
|
||||
@@ -40,18 +40,7 @@ final class $$UserMetadataEntityTableReferences
|
||||
static i5.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) =>
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i5.$UserEntityTable>('user_entity')
|
||||
.createAlias(
|
||||
i0.$_aliasNameGenerator(
|
||||
i6.ReadDatabaseContainer(db)
|
||||
.resultSet<i1.$UserMetadataEntityTable>(
|
||||
'user_metadata_entity',
|
||||
)
|
||||
.userId,
|
||||
i6.ReadDatabaseContainer(
|
||||
db,
|
||||
).resultSet<i5.$UserEntityTable>('user_entity').id,
|
||||
),
|
||||
);
|
||||
.createAlias('user_metadata_entity__user_id__user_entity__id');
|
||||
|
||||
i5.$$UserEntityTableProcessedTableManager get userId {
|
||||
final $_column = $_itemColumn<String>('user_id')!;
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
@@ -685,16 +684,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
}
|
||||
}
|
||||
|
||||
List<Bucket> _generateBuckets(int count) {
|
||||
final buckets = List.filled(
|
||||
(count / kTimelineNoneSegmentSize).ceil(),
|
||||
const Bucket(assetCount: kTimelineNoneSegmentSize),
|
||||
);
|
||||
if (count % kTimelineNoneSegmentSize != 0) {
|
||||
buckets[buckets.length - 1] = Bucket(assetCount: count % kTimelineNoneSegmentSize);
|
||||
}
|
||||
return buckets;
|
||||
}
|
||||
List<Bucket> _generateBuckets(int count) => count == 0 ? const [] : [Bucket(assetCount: count)];
|
||||
|
||||
extension on Expression<DateTime> {
|
||||
Expression<String> dateFmt(GroupAssetsBy groupBy, {bool toLocal = false}) {
|
||||
|
||||
@@ -132,10 +132,10 @@ class SharedLinkEditPage extends HookConsumerWidget {
|
||||
textInputAction: TextInputAction.done,
|
||||
autofocus: false,
|
||||
decoration: InputDecoration(
|
||||
labelText: slugController.text.isNotEmpty ? context.t.custom_url : null,
|
||||
labelText: slugController.text.isNotEmpty ? context.t.shared_link_custom_url_title : null,
|
||||
labelStyle: const TextStyle(fontWeight: FontWeight.bold),
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: context.t.custom_url,
|
||||
hintText: context.t.shared_link_custom_url_title,
|
||||
prefixText: slugController.text.isNotEmpty ? '/s/' : null,
|
||||
prefixStyle: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
),
|
||||
|
||||
@@ -3,25 +3,23 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:immich_mobile/utils/asset_filter.dart';
|
||||
import 'package:immich_ui/immich_ui.dart';
|
||||
|
||||
class FavoriteAction extends AssetAction<RemoteAsset> {
|
||||
final bool shouldFavorite;
|
||||
final bool favorite;
|
||||
|
||||
FavoriteAction({required super.assets}) : shouldFavorite = assets.any((asset) => !asset.isFavorite);
|
||||
FavoriteAction({required super.assets}) : favorite = assets.any((asset) => !asset.isFavorite);
|
||||
|
||||
@override
|
||||
IconData get icon => shouldFavorite ? Icons.favorite_border_rounded : Icons.favorite_rounded;
|
||||
IconData get icon => favorite ? Icons.favorite_border_rounded : Icons.favorite_rounded;
|
||||
|
||||
@override
|
||||
String label(ActionScope scope) => shouldFavorite ? scope.context.t.favorite : scope.context.t.unfavorite;
|
||||
String label(ActionScope scope) => favorite ? scope.context.t.favorite : scope.context.t.unfavorite;
|
||||
|
||||
@override
|
||||
Iterable<RemoteAsset> filter(ActionScope scope) => assets
|
||||
.where(
|
||||
(asset) => asset is RemoteAsset && asset.ownerId == scope.authUser.id && asset.isFavorite == !shouldFavorite,
|
||||
)
|
||||
.cast<RemoteAsset>();
|
||||
Iterable<RemoteAsset> filter(ActionScope scope) =>
|
||||
AssetFilter(assets).owned(scope.authUser.id).favorite(isFavorite: !favorite);
|
||||
|
||||
@override
|
||||
bool isVisible(ActionScope scope) => filter(scope).isNotEmpty;
|
||||
@@ -31,8 +29,8 @@ class FavoriteAction extends AssetAction<RemoteAsset> {
|
||||
final ActionScope(:ref) = scope;
|
||||
final assets = filter(scope).map((asset) => asset.id).toList(growable: false);
|
||||
|
||||
await ref.read(assetServiceProvider).updateFavorite(assets, shouldFavorite);
|
||||
final message = shouldFavorite
|
||||
await ref.read(assetServiceProvider).updateFavorite(assets, favorite);
|
||||
final message = favorite
|
||||
? StaticTranslations.instance.favorite_action_prompt(count: assets.length)
|
||||
: StaticTranslations.instance.unfavorite_action_prompt(count: assets.length);
|
||||
snackbar.success(message);
|
||||
|
||||
@@ -99,6 +99,8 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||
case TimelineReloadEvent():
|
||||
final asset = ref.read(timelineServiceProvider).getAssetSafe(widget.index);
|
||||
if (asset != _asset) {
|
||||
_isZoomed = false;
|
||||
_viewer.setZoomed(false);
|
||||
setState(() => _asset = asset);
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -81,6 +81,12 @@ class AssetViewer extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||
static const _viewerOverlayStyle = SystemUiOverlayStyle(
|
||||
statusBarIconBrightness: Brightness.light,
|
||||
statusBarBrightness: Brightness.dark,
|
||||
systemNavigationBarIconBrightness: Brightness.light,
|
||||
);
|
||||
|
||||
late final _heroOffset = widget.heroOffset ?? TabsRouterScope.of(context)?.controller.activeIndex ?? 0;
|
||||
late final _pageController = PageController(initialPage: widget.initialIndex);
|
||||
late final _preloader = AssetPreloader(timelineService: ref.read(timelineServiceProvider), mounted: () => mounted);
|
||||
@@ -280,49 +286,52 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||
_setSystemUIMode(controls, details);
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: const ViewerTopAppBar(),
|
||||
extendBody: true,
|
||||
extendBodyBehindAppBar: true,
|
||||
floatingActionButton: IgnorePointer(
|
||||
ignoring: !showingControls,
|
||||
child: AnimatedOpacity(
|
||||
opacity: showingControls ? 1.0 : 0.0,
|
||||
duration: Durations.short2,
|
||||
child: const DownloadStatusFloatingButton(),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: const ViewerBottomAppBar(),
|
||||
body: Stack(
|
||||
children: [
|
||||
NotificationListener<ScrollEndNotification>(
|
||||
onNotification: _onScrollEnd,
|
||||
child: PhotoViewGestureDetectorScope(
|
||||
axis: Axis.horizontal,
|
||||
child: PageView.builder(
|
||||
controller: _pageController,
|
||||
physics: isZoomed
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: CurrentPlatform.isIOS
|
||||
? const FastScrollPhysics()
|
||||
: const FastClampingScrollPhysics(),
|
||||
itemCount: _totalAssets,
|
||||
itemBuilder: (context, index) =>
|
||||
AssetPage(index: index, heroOffset: _heroOffset, onTapNavigate: _onTapNavigate),
|
||||
),
|
||||
),
|
||||
return AnnotatedRegion(
|
||||
value: _viewerOverlayStyle,
|
||||
child: Scaffold(
|
||||
backgroundColor: backgroundColor,
|
||||
resizeToAvoidBottomInset: false,
|
||||
appBar: const ViewerTopAppBar(),
|
||||
extendBody: true,
|
||||
extendBodyBehindAppBar: true,
|
||||
floatingActionButton: IgnorePointer(
|
||||
ignoring: !showingControls,
|
||||
child: AnimatedOpacity(
|
||||
opacity: showingControls ? 1.0 : 0.0,
|
||||
duration: Durations.short2,
|
||||
child: const DownloadStatusFloatingButton(),
|
||||
),
|
||||
if (!CurrentPlatform.isIOS)
|
||||
IgnorePointer(
|
||||
child: AnimatedContainer(
|
||||
duration: Durations.short2,
|
||||
color: Colors.black.withValues(alpha: showingDetails ? 0.6 : 0.0),
|
||||
height: context.padding.top,
|
||||
),
|
||||
bottomNavigationBar: const ViewerBottomAppBar(),
|
||||
body: Stack(
|
||||
children: [
|
||||
NotificationListener<ScrollEndNotification>(
|
||||
onNotification: _onScrollEnd,
|
||||
child: PhotoViewGestureDetectorScope(
|
||||
axis: Axis.horizontal,
|
||||
child: PageView.builder(
|
||||
controller: _pageController,
|
||||
physics: isZoomed
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: CurrentPlatform.isIOS
|
||||
? const FastScrollPhysics()
|
||||
: const FastClampingScrollPhysics(),
|
||||
itemCount: _totalAssets,
|
||||
itemBuilder: (context, index) =>
|
||||
AssetPage(index: index, heroOffset: _heroOffset, onTapNavigate: _onTapNavigate),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
if (!CurrentPlatform.isIOS)
|
||||
IgnorePointer(
|
||||
child: AnimatedContainer(
|
||||
duration: Durations.short2,
|
||||
color: Colors.black.withValues(alpha: showingDetails ? 0.6 : 0.0),
|
||||
height: context.padding.top,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
|
||||
ActionIconButtonWidget(action: FavoriteAction(assets: assetForAction)),
|
||||
|
||||
ViewerKebabMenu(originalTheme: originalTheme),
|
||||
ImmichColorOverride(color: null, child: ViewerKebabMenu(originalTheme: originalTheme)),
|
||||
];
|
||||
|
||||
final lockedViewActions = <Widget>[ViewerKebabMenu(originalTheme: originalTheme)];
|
||||
|
||||
@@ -317,6 +317,8 @@ class BackgroundUploadService {
|
||||
priority: priority,
|
||||
isFavorite: asset.isFavorite,
|
||||
requiresWiFi: requiresWiFi,
|
||||
// Visibility hidden on upload to prevent the server from running regular jobs on the live photo asset
|
||||
fields: entity.isLivePhoto ? {'visibility': api.AssetVisibility.hidden.value} : null,
|
||||
cloudId: entity.isLivePhoto ? null : asset.cloudId,
|
||||
adjustmentTime: entity.isLivePhoto ? null : asset.adjustmentTime?.toIso8601String(),
|
||||
latitude: entity.isLivePhoto ? null : asset.latitude?.toString(),
|
||||
@@ -336,8 +338,7 @@ class BackgroundUploadService {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Visibility hidden on upload to prevent the server from running regular jobs on the live photo asset
|
||||
final fields = {'livePhotoVideoId': livePhotoVideoId, 'visibility': api.AssetVisibility.hidden.value};
|
||||
final fields = {'livePhotoVideoId': livePhotoVideoId};
|
||||
|
||||
final requiresWiFi = _shouldRequireWiFi(asset);
|
||||
final originalFileName = await _assetMediaRepository.getOriginalFilename(asset.id) ?? asset.name;
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/asset_metadata.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' hide AssetVisibility;
|
||||
@@ -100,7 +101,7 @@ class ForegroundUploadService {
|
||||
final requireWifi = _shouldRequireWiFi(asset);
|
||||
return requireWifi && !hasWifi;
|
||||
},
|
||||
processItem: (asset) => _uploadSingleAsset(asset, cancelToken, callbacks: callbacks),
|
||||
processItem: (asset) => uploadSingleAsset(asset, cancelToken, callbacks: callbacks),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -126,7 +127,7 @@ class ForegroundUploadService {
|
||||
continue;
|
||||
}
|
||||
|
||||
await _uploadSingleAsset(asset, cancelToken, callbacks: callbacks);
|
||||
await uploadSingleAsset(asset, cancelToken, callbacks: callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ class ForegroundUploadService {
|
||||
await _executeWithWorkerPool<LocalAsset>(
|
||||
items: localAssets,
|
||||
cancelToken: cancelToken,
|
||||
processItem: (asset) => _uploadSingleAsset(asset, cancelToken, callbacks: callbacks),
|
||||
processItem: (asset) => uploadSingleAsset(asset, cancelToken, callbacks: callbacks),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -233,7 +234,8 @@ class ForegroundUploadService {
|
||||
await Future.wait(workerFutures);
|
||||
}
|
||||
|
||||
Future<void> _uploadSingleAsset(
|
||||
@visibleForTesting
|
||||
Future<void> uploadSingleAsset(
|
||||
LocalAsset asset,
|
||||
Completer<void>? cancelToken, {
|
||||
required UploadCallbacks callbacks,
|
||||
|
||||
22
mobile/lib/utils/asset_filter.dart
Normal file
22
mobile/lib/utils/asset_filter.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
|
||||
extension type const AssetFilter<T extends BaseAsset>(Iterable<T> assets) implements Iterable<T> {
|
||||
AssetFilter<T> where(bool Function(T asset) test) => AssetFilter(assets.where(test));
|
||||
AssetFilter<T> whereNot(bool Function(T asset) test) => AssetFilter(assets.where((asset) => !test(asset)));
|
||||
|
||||
AssetFilter<T> type(AssetType type) => where((asset) => asset.type == type);
|
||||
AssetFilter<T> favorite({bool isFavorite = true}) => where((asset) => asset.isFavorite == isFavorite);
|
||||
|
||||
AssetFilter<RemoteAsset> remote() => AssetFilter(assets.whereType<RemoteAsset>());
|
||||
AssetFilter<RemoteAsset> owned(String ownerId) => remote().where((asset) => asset.ownerId == ownerId);
|
||||
AssetFilter<RemoteAsset> visibility(AssetVisibility visibility) =>
|
||||
remote().where((asset) => asset.visibility == visibility);
|
||||
AssetFilter<RemoteAsset> notVisibility(AssetVisibility visibility) =>
|
||||
remote().where((asset) => asset.visibility != visibility);
|
||||
AssetFilter<RemoteAsset> archived({bool isArchived = true}) =>
|
||||
remote().where((asset) => asset.isArchived == isArchived);
|
||||
AssetFilter<RemoteAsset> stacked({bool isStacked = true}) => remote().where((asset) => asset.isStacked == isStacked);
|
||||
|
||||
AssetFilter<LocalAsset> local() => AssetFilter(assets.whereType<LocalAsset>());
|
||||
AssetFilter<LocalAsset> backedUp() => local().where((asset) => asset.remoteAssetId != null);
|
||||
}
|
||||
@@ -41,7 +41,6 @@ final Map<String, Map<String, Object?>> openApiPatches = {
|
||||
'SyncAssetV1': {'isEdited': false},
|
||||
'ServerFeaturesDto': {'ocr': false, 'realtimeTranscoding': false},
|
||||
'MemoriesResponse': {'duration': 5},
|
||||
'WorkflowResponseDto': {'logging': false},
|
||||
};
|
||||
|
||||
void upgradeDto(dynamic value, String targetType) {
|
||||
|
||||
@@ -393,10 +393,8 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic
|
||||
builder: (context, child) {
|
||||
return Transform.scale(
|
||||
scale: _zoomAnimation.value,
|
||||
filterQuality: Platform.isAndroid ? FilterQuality.low : null,
|
||||
child: Transform.translate(
|
||||
offset: _panAnimation.value,
|
||||
filterQuality: Platform.isAndroid ? FilterQuality.low : null,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
||||
@@ -496,10 +496,8 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic
|
||||
builder: (context, child) {
|
||||
return Transform.scale(
|
||||
scale: _zoomAnimation.value,
|
||||
filterQuality: Platform.isAndroid ? FilterQuality.low : null,
|
||||
child: Transform.translate(
|
||||
offset: _panAnimation.value,
|
||||
filterQuality: Platform.isAndroid ? FilterQuality.low : null,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
||||
@@ -472,10 +472,8 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground> with Tic
|
||||
builder: (context, child) {
|
||||
return Transform.scale(
|
||||
scale: _zoomAnimation.value,
|
||||
filterQuality: Platform.isAndroid ? FilterQuality.low : null,
|
||||
child: Transform.translate(
|
||||
offset: _panAnimation.value,
|
||||
filterQuality: Platform.isAndroid ? FilterQuality.low : null,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html
|
||||
|
||||
[[tools."aqua:flutter/flutter"]]
|
||||
version = "3.44.1"
|
||||
version = "3.44.6"
|
||||
backend = "aqua:flutter/flutter"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.linux-arm64"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.1-stable.tar.xz"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.6-stable.tar.xz"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.linux-arm64-musl"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.1-stable.tar.xz"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.6-stable.tar.xz"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.linux-x64"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.1-stable.tar.xz"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.6-stable.tar.xz"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.linux-x64-musl"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.1-stable.tar.xz"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.6-stable.tar.xz"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.macos-arm64"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_arm64_3.44.1-stable.zip"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_arm64_3.44.6-stable.zip"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.macos-x64"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_3.44.1-stable.zip"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_3.44.6-stable.zip"
|
||||
|
||||
[tools."aqua:flutter/flutter"."platforms.windows-x64"]
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.44.1-stable.zip"
|
||||
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.44.6-stable.zip"
|
||||
|
||||
[[tools."github:CQLabs/homebrew-dcm"]]
|
||||
version = "1.37.0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[tools]
|
||||
"aqua:flutter/flutter" = "3.44.1"
|
||||
"aqua:flutter/flutter" = "3.44.6"
|
||||
java = "21.0.2"
|
||||
|
||||
[tools."github:CQLabs/homebrew-dcm"]
|
||||
|
||||
6
mobile/openapi/README.md
generated
6
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 3.0.2
|
||||
- API version: 3.0.3
|
||||
- Generator version: 7.22.0
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
@@ -341,7 +341,6 @@ Class | Method | HTTP request | Description
|
||||
*WorkflowsApi* | [**deleteWorkflow**](doc//WorkflowsApi.md#deleteworkflow) | **DELETE** /workflows/{id} | Delete a workflow
|
||||
*WorkflowsApi* | [**getWorkflow**](doc//WorkflowsApi.md#getworkflow) | **GET** /workflows/{id} | Retrieve a workflow
|
||||
*WorkflowsApi* | [**getWorkflowForShare**](doc//WorkflowsApi.md#getworkflowforshare) | **GET** /workflows/{id}/share | Retrieve a workflow
|
||||
*WorkflowsApi* | [**getWorkflowLogs**](doc//WorkflowsApi.md#getworkflowlogs) | **GET** /workflows/{id}/logs | Retrieve a workflow
|
||||
*WorkflowsApi* | [**getWorkflowTriggers**](doc//WorkflowsApi.md#getworkflowtriggers) | **GET** /workflows/triggers | List all workflow triggers
|
||||
*WorkflowsApi* | [**searchWorkflows**](doc//WorkflowsApi.md#searchworkflows) | **GET** /workflows | List all workflows
|
||||
*WorkflowsApi* | [**updateWorkflow**](doc//WorkflowsApi.md#updateworkflow) | **PUT** /workflows/{id} | Update a workflow
|
||||
@@ -712,10 +711,7 @@ Class | Method | HTTP request | Description
|
||||
- [VideoCodec](doc//VideoCodec.md)
|
||||
- [VideoContainer](doc//VideoContainer.md)
|
||||
- [WorkflowCreateDto](doc//WorkflowCreateDto.md)
|
||||
- [WorkflowLogEntryDto](doc//WorkflowLogEntryDto.md)
|
||||
- [WorkflowLogEntryDtoLastStep](doc//WorkflowLogEntryDtoLastStep.md)
|
||||
- [WorkflowResponseDto](doc//WorkflowResponseDto.md)
|
||||
- [WorkflowResult](doc//WorkflowResult.md)
|
||||
- [WorkflowShareResponseDto](doc//WorkflowShareResponseDto.md)
|
||||
- [WorkflowShareStepDto](doc//WorkflowShareStepDto.md)
|
||||
- [WorkflowStepDto](doc//WorkflowStepDto.md)
|
||||
|
||||
3
mobile/openapi/lib/api.dart
generated
3
mobile/openapi/lib/api.dart
generated
@@ -432,10 +432,7 @@ part 'model/version_check_state_response_dto.dart';
|
||||
part 'model/video_codec.dart';
|
||||
part 'model/video_container.dart';
|
||||
part 'model/workflow_create_dto.dart';
|
||||
part 'model/workflow_log_entry_dto.dart';
|
||||
part 'model/workflow_log_entry_dto_last_step.dart';
|
||||
part 'model/workflow_response_dto.dart';
|
||||
part 'model/workflow_result.dart';
|
||||
part 'model/workflow_share_response_dto.dart';
|
||||
part 'model/workflow_share_step_dto.dart';
|
||||
part 'model/workflow_step_dto.dart';
|
||||
|
||||
8
mobile/openapi/lib/api/albums_api.dart
generated
8
mobile/openapi/lib/api/albums_api.dart
generated
@@ -681,8 +681,10 @@ class AlbumsApi {
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
/// Album ID
|
||||
///
|
||||
/// * [String] userId (required):
|
||||
/// Album user ID, or \"me\" to reference the current user.
|
||||
Future<Response> removeUserFromAlbumWithHttpInfo(String id, String userId, { Future<void>? abortTrigger, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/albums/{id}/user/{userId}'
|
||||
@@ -718,8 +720,10 @@ class AlbumsApi {
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
/// Album ID
|
||||
///
|
||||
/// * [String] userId (required):
|
||||
/// Album user ID, or \"me\" to reference the current user.
|
||||
Future<void> removeUserFromAlbum(String id, String userId, { Future<void>? abortTrigger, }) async {
|
||||
final response = await removeUserFromAlbumWithHttpInfo(id, userId, abortTrigger: abortTrigger,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
@@ -798,8 +802,10 @@ class AlbumsApi {
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
/// Album ID
|
||||
///
|
||||
/// * [String] userId (required):
|
||||
/// Album user ID, or \"me\" to reference the current user.
|
||||
///
|
||||
/// * [UpdateAlbumUserDto] updateAlbumUserDto (required):
|
||||
Future<Response> updateAlbumUserWithHttpInfo(String id, String userId, UpdateAlbumUserDto updateAlbumUserDto, { Future<void>? abortTrigger, }) async {
|
||||
@@ -837,8 +843,10 @@ class AlbumsApi {
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
/// Album ID
|
||||
///
|
||||
/// * [String] userId (required):
|
||||
/// Album user ID, or \"me\" to reference the current user.
|
||||
///
|
||||
/// * [UpdateAlbumUserDto] updateAlbumUserDto (required):
|
||||
Future<void> updateAlbumUser(String id, String userId, UpdateAlbumUserDto updateAlbumUserDto, { Future<void>? abortTrigger, }) async {
|
||||
|
||||
104
mobile/openapi/lib/api/workflows_api.dart
generated
104
mobile/openapi/lib/api/workflows_api.dart
generated
@@ -239,95 +239,6 @@ class WorkflowsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Retrieve a workflow
|
||||
///
|
||||
/// Retrieve a workflow details without ids, default values, etc.
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [DateTime] before:
|
||||
/// Filter by runs before a date/time
|
||||
///
|
||||
/// * [int] limit:
|
||||
/// Maximum number of logs
|
||||
///
|
||||
/// * [WorkflowResult] result:
|
||||
/// Filter by run result
|
||||
Future<Response> getWorkflowLogsWithHttpInfo(String id, { DateTime? before, int? limit, WorkflowResult? result, Future<void>? abortTrigger, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/workflows/{id}/logs'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
if (before != null) {
|
||||
queryParams.addAll(_queryParams('', 'before', before));
|
||||
}
|
||||
if (limit != null) {
|
||||
queryParams.addAll(_queryParams('', 'limit', limit));
|
||||
}
|
||||
if (result != null) {
|
||||
queryParams.addAll(_queryParams('', 'result', result));
|
||||
}
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
abortTrigger: abortTrigger,
|
||||
);
|
||||
}
|
||||
|
||||
/// Retrieve a workflow
|
||||
///
|
||||
/// Retrieve a workflow details without ids, default values, etc.
|
||||
///
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [DateTime] before:
|
||||
/// Filter by runs before a date/time
|
||||
///
|
||||
/// * [int] limit:
|
||||
/// Maximum number of logs
|
||||
///
|
||||
/// * [WorkflowResult] result:
|
||||
/// Filter by run result
|
||||
Future<List<WorkflowLogEntryDto>?> getWorkflowLogs(String id, { DateTime? before, int? limit, WorkflowResult? result, Future<void>? abortTrigger, }) async {
|
||||
final response = await getWorkflowLogsWithHttpInfo(id, before: before, limit: limit, result: result, abortTrigger: abortTrigger,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<WorkflowLogEntryDto>') as List)
|
||||
.cast<WorkflowLogEntryDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// List all workflow triggers
|
||||
///
|
||||
/// Retrieve a list of all available workflow triggers.
|
||||
@@ -397,15 +308,12 @@ class WorkflowsApi {
|
||||
/// * [String] id:
|
||||
/// Workflow ID
|
||||
///
|
||||
/// * [bool] logging:
|
||||
/// Workflow logs run results
|
||||
///
|
||||
/// * [String] name:
|
||||
/// Workflow name
|
||||
///
|
||||
/// * [WorkflowTrigger] trigger:
|
||||
/// Workflow trigger type
|
||||
Future<Response> searchWorkflowsWithHttpInfo({ String? description, bool? enabled, String? id, bool? logging, String? name, WorkflowTrigger? trigger, Future<void>? abortTrigger, }) async {
|
||||
Future<Response> searchWorkflowsWithHttpInfo({ String? description, bool? enabled, String? id, String? name, WorkflowTrigger? trigger, Future<void>? abortTrigger, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/workflows';
|
||||
|
||||
@@ -425,9 +333,6 @@ class WorkflowsApi {
|
||||
if (id != null) {
|
||||
queryParams.addAll(_queryParams('', 'id', id));
|
||||
}
|
||||
if (logging != null) {
|
||||
queryParams.addAll(_queryParams('', 'logging', logging));
|
||||
}
|
||||
if (name != null) {
|
||||
queryParams.addAll(_queryParams('', 'name', name));
|
||||
}
|
||||
@@ -465,16 +370,13 @@ class WorkflowsApi {
|
||||
/// * [String] id:
|
||||
/// Workflow ID
|
||||
///
|
||||
/// * [bool] logging:
|
||||
/// Workflow logs run results
|
||||
///
|
||||
/// * [String] name:
|
||||
/// Workflow name
|
||||
///
|
||||
/// * [WorkflowTrigger] trigger:
|
||||
/// Workflow trigger type
|
||||
Future<List<WorkflowResponseDto>?> searchWorkflows({ String? description, bool? enabled, String? id, bool? logging, String? name, WorkflowTrigger? trigger, Future<void>? abortTrigger, }) async {
|
||||
final response = await searchWorkflowsWithHttpInfo(description: description, enabled: enabled, id: id, logging: logging, name: name, trigger: trigger, abortTrigger: abortTrigger,);
|
||||
Future<List<WorkflowResponseDto>?> searchWorkflows({ String? description, bool? enabled, String? id, String? name, WorkflowTrigger? trigger, Future<void>? abortTrigger, }) async {
|
||||
final response = await searchWorkflowsWithHttpInfo(description: description, enabled: enabled, id: id, name: name, trigger: trigger, abortTrigger: abortTrigger,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
|
||||
6
mobile/openapi/lib/api_client.dart
generated
6
mobile/openapi/lib/api_client.dart
generated
@@ -909,14 +909,8 @@ class ApiClient {
|
||||
return VideoContainerTypeTransformer().decode(value);
|
||||
case 'WorkflowCreateDto':
|
||||
return WorkflowCreateDto.fromJson(value);
|
||||
case 'WorkflowLogEntryDto':
|
||||
return WorkflowLogEntryDto.fromJson(value);
|
||||
case 'WorkflowLogEntryDtoLastStep':
|
||||
return WorkflowLogEntryDtoLastStep.fromJson(value);
|
||||
case 'WorkflowResponseDto':
|
||||
return WorkflowResponseDto.fromJson(value);
|
||||
case 'WorkflowResult':
|
||||
return WorkflowResultTypeTransformer().decode(value);
|
||||
case 'WorkflowShareResponseDto':
|
||||
return WorkflowShareResponseDto.fromJson(value);
|
||||
case 'WorkflowShareStepDto':
|
||||
|
||||
3
mobile/openapi/lib/api_helper.dart
generated
3
mobile/openapi/lib/api_helper.dart
generated
@@ -214,9 +214,6 @@ String parameterToString(dynamic value) {
|
||||
if (value is VideoContainer) {
|
||||
return VideoContainerTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is WorkflowResult) {
|
||||
return WorkflowResultTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is WorkflowTrigger) {
|
||||
return WorkflowTriggerTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
||||
3
mobile/openapi/lib/model/permission.dart
generated
3
mobile/openapi/lib/model/permission.dart
generated
@@ -172,7 +172,6 @@ class Permission {
|
||||
static const workflowPeriodRead = Permission._(r'workflow.read');
|
||||
static const workflowPeriodUpdate = Permission._(r'workflow.update');
|
||||
static const workflowPeriodDelete = Permission._(r'workflow.delete');
|
||||
static const workflowPeriodLogs = Permission._(r'workflow.logs');
|
||||
static const adminUserPeriodCreate = Permission._(r'adminUser.create');
|
||||
static const adminUserPeriodRead = Permission._(r'adminUser.read');
|
||||
static const adminUserPeriodUpdate = Permission._(r'adminUser.update');
|
||||
@@ -331,7 +330,6 @@ class Permission {
|
||||
workflowPeriodRead,
|
||||
workflowPeriodUpdate,
|
||||
workflowPeriodDelete,
|
||||
workflowPeriodLogs,
|
||||
adminUserPeriodCreate,
|
||||
adminUserPeriodRead,
|
||||
adminUserPeriodUpdate,
|
||||
@@ -525,7 +523,6 @@ class PermissionTypeTransformer {
|
||||
case r'workflow.read': return Permission.workflowPeriodRead;
|
||||
case r'workflow.update': return Permission.workflowPeriodUpdate;
|
||||
case r'workflow.delete': return Permission.workflowPeriodDelete;
|
||||
case r'workflow.logs': return Permission.workflowPeriodLogs;
|
||||
case r'adminUser.create': return Permission.adminUserPeriodCreate;
|
||||
case r'adminUser.read': return Permission.adminUserPeriodRead;
|
||||
case r'adminUser.update': return Permission.adminUserPeriodUpdate;
|
||||
|
||||
19
mobile/openapi/lib/model/workflow_create_dto.dart
generated
19
mobile/openapi/lib/model/workflow_create_dto.dart
generated
@@ -15,7 +15,6 @@ class WorkflowCreateDto {
|
||||
WorkflowCreateDto({
|
||||
this.description = const Optional.absent(),
|
||||
this.enabled = const Optional.absent(),
|
||||
this.logging = const Optional.absent(),
|
||||
this.name = const Optional.absent(),
|
||||
this.steps = const Optional.present(const []),
|
||||
required this.trigger,
|
||||
@@ -33,15 +32,6 @@ class WorkflowCreateDto {
|
||||
///
|
||||
Optional<bool?> enabled;
|
||||
|
||||
/// Workflow logs run results
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<bool?> logging;
|
||||
|
||||
/// Workflow name
|
||||
Optional<String?> name;
|
||||
|
||||
@@ -53,7 +43,6 @@ class WorkflowCreateDto {
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowCreateDto &&
|
||||
other.description == description &&
|
||||
other.enabled == enabled &&
|
||||
other.logging == logging &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger;
|
||||
@@ -63,13 +52,12 @@ class WorkflowCreateDto {
|
||||
// ignore: unnecessary_parenthesis
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enabled == null ? 0 : enabled!.hashCode) +
|
||||
(logging == null ? 0 : logging!.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowCreateDto[description=$description, enabled=$enabled, logging=$logging, name=$name, steps=$steps, trigger=$trigger]';
|
||||
String toString() => 'WorkflowCreateDto[description=$description, enabled=$enabled, name=$name, steps=$steps, trigger=$trigger]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
@@ -81,10 +69,6 @@ class WorkflowCreateDto {
|
||||
final value = this.enabled.value;
|
||||
json[r'enabled'] = value;
|
||||
}
|
||||
if (this.logging.isPresent) {
|
||||
final value = this.logging.value;
|
||||
json[r'logging'] = value;
|
||||
}
|
||||
if (this.name.isPresent) {
|
||||
final value = this.name.value;
|
||||
json[r'name'] = value;
|
||||
@@ -108,7 +92,6 @@ class WorkflowCreateDto {
|
||||
return WorkflowCreateDto(
|
||||
description: json.containsKey(r'description') ? Optional.present(mapValueOfType<String>(json, r'description')) : const Optional.absent(),
|
||||
enabled: json.containsKey(r'enabled') ? Optional.present(mapValueOfType<bool>(json, r'enabled')) : const Optional.absent(),
|
||||
logging: json.containsKey(r'logging') ? Optional.present(mapValueOfType<bool>(json, r'logging')) : const Optional.absent(),
|
||||
name: json.containsKey(r'name') ? Optional.present(mapValueOfType<String>(json, r'name')) : const Optional.absent(),
|
||||
steps: json.containsKey(r'steps') ? Optional.present(WorkflowStepDto.listFromJson(json[r'steps'])) : const Optional.absent(),
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
|
||||
|
||||
150
mobile/openapi/lib/model/workflow_log_entry_dto.dart
generated
150
mobile/openapi/lib/model/workflow_log_entry_dto.dart
generated
@@ -1,150 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowLogEntryDto {
|
||||
/// Returns a new [WorkflowLogEntryDto] instance.
|
||||
WorkflowLogEntryDto({
|
||||
required this.at,
|
||||
required this.id,
|
||||
this.lastStep = const Optional.absent(),
|
||||
required this.result,
|
||||
this.triggerDataId = const Optional.absent(),
|
||||
});
|
||||
|
||||
/// Workflow run date/time
|
||||
String at;
|
||||
|
||||
/// Workflow log entry ID
|
||||
String id;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<WorkflowLogEntryDtoLastStep?> lastStep;
|
||||
|
||||
WorkflowResult result;
|
||||
|
||||
/// Workflow trigger data ID
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<String?> triggerDataId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowLogEntryDto &&
|
||||
other.at == at &&
|
||||
other.id == id &&
|
||||
other.lastStep == lastStep &&
|
||||
other.result == result &&
|
||||
other.triggerDataId == triggerDataId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(at.hashCode) +
|
||||
(id.hashCode) +
|
||||
(lastStep == null ? 0 : lastStep!.hashCode) +
|
||||
(result.hashCode) +
|
||||
(triggerDataId == null ? 0 : triggerDataId!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowLogEntryDto[at=$at, id=$id, lastStep=$lastStep, result=$result, triggerDataId=$triggerDataId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'at'] = this.at;
|
||||
json[r'id'] = this.id;
|
||||
if (this.lastStep.isPresent) {
|
||||
final value = this.lastStep.value;
|
||||
json[r'lastStep'] = value;
|
||||
}
|
||||
json[r'result'] = this.result;
|
||||
if (this.triggerDataId.isPresent) {
|
||||
final value = this.triggerDataId.value;
|
||||
json[r'triggerDataId'] = value;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowLogEntryDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowLogEntryDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowLogEntryDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowLogEntryDto(
|
||||
at: mapValueOfType<String>(json, r'at')!,
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
lastStep: json.containsKey(r'lastStep') ? Optional.present(WorkflowLogEntryDtoLastStep.fromJson(json[r'lastStep'])) : const Optional.absent(),
|
||||
result: WorkflowResult.fromJson(json[r'result'])!,
|
||||
triggerDataId: json.containsKey(r'triggerDataId') ? Optional.present(mapValueOfType<String>(json, r'triggerDataId')) : const Optional.absent(),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowLogEntryDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowLogEntryDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowLogEntryDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowLogEntryDto> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowLogEntryDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowLogEntryDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowLogEntryDto-objects as value to a dart map
|
||||
static Map<String, List<WorkflowLogEntryDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowLogEntryDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowLogEntryDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'at',
|
||||
'id',
|
||||
'result',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class WorkflowLogEntryDtoLastStep {
|
||||
/// Returns a new [WorkflowLogEntryDtoLastStep] instance.
|
||||
WorkflowLogEntryDtoLastStep({
|
||||
required this.index,
|
||||
required this.method,
|
||||
});
|
||||
|
||||
/// Index of the step in the workflow
|
||||
///
|
||||
/// Minimum value: 0
|
||||
/// Maximum value: 9007199254740991
|
||||
int index;
|
||||
|
||||
/// Method of the step
|
||||
String method;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowLogEntryDtoLastStep &&
|
||||
other.index == index &&
|
||||
other.method == method;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(index.hashCode) +
|
||||
(method.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowLogEntryDtoLastStep[index=$index, method=$method]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'index'] = this.index;
|
||||
json[r'method'] = this.method;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [WorkflowLogEntryDtoLastStep] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static WorkflowLogEntryDtoLastStep? fromJson(dynamic value) {
|
||||
upgradeDto(value, "WorkflowLogEntryDtoLastStep");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return WorkflowLogEntryDtoLastStep(
|
||||
index: mapValueOfType<int>(json, r'index')!,
|
||||
method: mapValueOfType<String>(json, r'method')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<WorkflowLogEntryDtoLastStep> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowLogEntryDtoLastStep>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowLogEntryDtoLastStep.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, WorkflowLogEntryDtoLastStep> mapFromJson(dynamic json) {
|
||||
final map = <String, WorkflowLogEntryDtoLastStep>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = WorkflowLogEntryDtoLastStep.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of WorkflowLogEntryDtoLastStep-objects as value to a dart map
|
||||
static Map<String, List<WorkflowLogEntryDtoLastStep>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<WorkflowLogEntryDtoLastStep>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = WorkflowLogEntryDtoLastStep.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'index',
|
||||
'method',
|
||||
};
|
||||
}
|
||||
|
||||
11
mobile/openapi/lib/model/workflow_response_dto.dart
generated
11
mobile/openapi/lib/model/workflow_response_dto.dart
generated
@@ -17,7 +17,6 @@ class WorkflowResponseDto {
|
||||
required this.description,
|
||||
required this.enabled,
|
||||
required this.id,
|
||||
required this.logging,
|
||||
required this.name,
|
||||
this.steps = const [],
|
||||
required this.trigger,
|
||||
@@ -36,9 +35,6 @@ class WorkflowResponseDto {
|
||||
/// Workflow ID
|
||||
String id;
|
||||
|
||||
/// Workflow logs run results
|
||||
bool logging;
|
||||
|
||||
/// Workflow name
|
||||
String? name;
|
||||
|
||||
@@ -56,7 +52,6 @@ class WorkflowResponseDto {
|
||||
other.description == description &&
|
||||
other.enabled == enabled &&
|
||||
other.id == id &&
|
||||
other.logging == logging &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger &&
|
||||
@@ -69,14 +64,13 @@ class WorkflowResponseDto {
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enabled.hashCode) +
|
||||
(id.hashCode) +
|
||||
(logging.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger.hashCode) +
|
||||
(updatedAt.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowResponseDto[createdAt=$createdAt, description=$description, enabled=$enabled, id=$id, logging=$logging, name=$name, steps=$steps, trigger=$trigger, updatedAt=$updatedAt]';
|
||||
String toString() => 'WorkflowResponseDto[createdAt=$createdAt, description=$description, enabled=$enabled, id=$id, name=$name, steps=$steps, trigger=$trigger, updatedAt=$updatedAt]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
@@ -88,7 +82,6 @@ class WorkflowResponseDto {
|
||||
}
|
||||
json[r'enabled'] = this.enabled;
|
||||
json[r'id'] = this.id;
|
||||
json[r'logging'] = this.logging;
|
||||
if (this.name != null) {
|
||||
json[r'name'] = this.name;
|
||||
} else {
|
||||
@@ -113,7 +106,6 @@ class WorkflowResponseDto {
|
||||
description: mapValueOfType<String>(json, r'description'),
|
||||
enabled: mapValueOfType<bool>(json, r'enabled')!,
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
logging: mapValueOfType<bool>(json, r'logging')!,
|
||||
name: mapValueOfType<String>(json, r'name'),
|
||||
steps: WorkflowStepDto.listFromJson(json[r'steps']),
|
||||
trigger: WorkflowTrigger.fromJson(json[r'trigger'])!,
|
||||
@@ -169,7 +161,6 @@ class WorkflowResponseDto {
|
||||
'description',
|
||||
'enabled',
|
||||
'id',
|
||||
'logging',
|
||||
'name',
|
||||
'steps',
|
||||
'trigger',
|
||||
|
||||
88
mobile/openapi/lib/model/workflow_result.dart
generated
88
mobile/openapi/lib/model/workflow_result.dart
generated
@@ -1,88 +0,0 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.18
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
/// Workflow run result
|
||||
class WorkflowResult {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const WorkflowResult._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const completed = WorkflowResult._(r'completed');
|
||||
static const halted = WorkflowResult._(r'halted');
|
||||
static const error = WorkflowResult._(r'error');
|
||||
|
||||
/// List of all possible values in this [enum][WorkflowResult].
|
||||
static const values = <WorkflowResult>[
|
||||
completed,
|
||||
halted,
|
||||
error,
|
||||
];
|
||||
|
||||
static WorkflowResult? fromJson(dynamic value) => WorkflowResultTypeTransformer().decode(value);
|
||||
|
||||
static List<WorkflowResult> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <WorkflowResult>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = WorkflowResult.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [WorkflowResult] to String,
|
||||
/// and [decode] dynamic data back to [WorkflowResult].
|
||||
class WorkflowResultTypeTransformer {
|
||||
factory WorkflowResultTypeTransformer() => _instance ??= const WorkflowResultTypeTransformer._();
|
||||
|
||||
const WorkflowResultTypeTransformer._();
|
||||
|
||||
String encode(WorkflowResult data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a WorkflowResult.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
WorkflowResult? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'completed': return WorkflowResult.completed;
|
||||
case r'halted': return WorkflowResult.halted;
|
||||
case r'error': return WorkflowResult.error;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [WorkflowResultTypeTransformer] instance.
|
||||
static WorkflowResultTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
19
mobile/openapi/lib/model/workflow_update_dto.dart
generated
19
mobile/openapi/lib/model/workflow_update_dto.dart
generated
@@ -15,7 +15,6 @@ class WorkflowUpdateDto {
|
||||
WorkflowUpdateDto({
|
||||
this.description = const Optional.absent(),
|
||||
this.enabled = const Optional.absent(),
|
||||
this.logging = const Optional.absent(),
|
||||
this.name = const Optional.absent(),
|
||||
this.steps = const Optional.present(const []),
|
||||
this.trigger = const Optional.absent(),
|
||||
@@ -33,15 +32,6 @@ class WorkflowUpdateDto {
|
||||
///
|
||||
Optional<bool?> enabled;
|
||||
|
||||
/// Workflow logs run results
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
Optional<bool?> logging;
|
||||
|
||||
/// Workflow name
|
||||
Optional<String?> name;
|
||||
|
||||
@@ -59,7 +49,6 @@ class WorkflowUpdateDto {
|
||||
bool operator ==(Object other) => identical(this, other) || other is WorkflowUpdateDto &&
|
||||
other.description == description &&
|
||||
other.enabled == enabled &&
|
||||
other.logging == logging &&
|
||||
other.name == name &&
|
||||
_deepEquality.equals(other.steps, steps) &&
|
||||
other.trigger == trigger;
|
||||
@@ -69,13 +58,12 @@ class WorkflowUpdateDto {
|
||||
// ignore: unnecessary_parenthesis
|
||||
(description == null ? 0 : description!.hashCode) +
|
||||
(enabled == null ? 0 : enabled!.hashCode) +
|
||||
(logging == null ? 0 : logging!.hashCode) +
|
||||
(name == null ? 0 : name!.hashCode) +
|
||||
(steps.hashCode) +
|
||||
(trigger == null ? 0 : trigger!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'WorkflowUpdateDto[description=$description, enabled=$enabled, logging=$logging, name=$name, steps=$steps, trigger=$trigger]';
|
||||
String toString() => 'WorkflowUpdateDto[description=$description, enabled=$enabled, name=$name, steps=$steps, trigger=$trigger]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
@@ -87,10 +75,6 @@ class WorkflowUpdateDto {
|
||||
final value = this.enabled.value;
|
||||
json[r'enabled'] = value;
|
||||
}
|
||||
if (this.logging.isPresent) {
|
||||
final value = this.logging.value;
|
||||
json[r'logging'] = value;
|
||||
}
|
||||
if (this.name.isPresent) {
|
||||
final value = this.name.value;
|
||||
json[r'name'] = value;
|
||||
@@ -117,7 +101,6 @@ class WorkflowUpdateDto {
|
||||
return WorkflowUpdateDto(
|
||||
description: json.containsKey(r'description') ? Optional.present(mapValueOfType<String>(json, r'description')) : const Optional.absent(),
|
||||
enabled: json.containsKey(r'enabled') ? Optional.present(mapValueOfType<bool>(json, r'enabled')) : const Optional.absent(),
|
||||
logging: json.containsKey(r'logging') ? Optional.present(mapValueOfType<bool>(json, r'logging')) : const Optional.absent(),
|
||||
name: json.containsKey(r'name') ? Optional.present(mapValueOfType<String>(json, r'name')) : const Optional.absent(),
|
||||
steps: json.containsKey(r'steps') ? Optional.present(WorkflowStepDto.listFromJson(json[r'steps'])) : const Optional.absent(),
|
||||
trigger: json.containsKey(r'trigger') ? Optional.present(WorkflowTrigger.fromJson(json[r'trigger'])) : const Optional.absent(),
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter/widgets.dart';
|
||||
class ImmichColorOverride extends InheritedWidget {
|
||||
const ImmichColorOverride({super.key, required this.color, required super.child});
|
||||
|
||||
final Color color;
|
||||
final Color? color;
|
||||
|
||||
static Color? maybeOf(BuildContext context) =>
|
||||
context.dependOnInheritedWidgetOfExactType<ImmichColorOverride>()?.color;
|
||||
|
||||
@@ -366,18 +366,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: drift
|
||||
sha256: "8033500116b24398fba0cca0369cc31678cd627c01e41753a61186911cea743e"
|
||||
sha256: "6cc0b623c0e83f7080524d8396e9301b1d78b9c66a4fdceeb0f798211303254c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.33.0"
|
||||
version: "2.34.0"
|
||||
drift_dev:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: drift_dev
|
||||
sha256: b3dd5b75e30522a91da8abda9f5bb17230cb038097f6d15fa75d42bb563428aa
|
||||
sha256: "9cfff1576b49725da0d32c040651a41ae195e8c4af8d8da301593e41d7abc2f7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.33.0"
|
||||
version: "2.34.0"
|
||||
drift_sqlite_async:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -772,10 +772,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: home_widget
|
||||
sha256: "908d033514a981f829fd98213909e11a428104327be3b422718aa643ac9d084a"
|
||||
sha256: fece84c7464099873c3ace38394ad7053509a4b0e36e57a1105a6aa31f47f23c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.1"
|
||||
version: "0.9.3"
|
||||
hooks:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1056,26 +1056,26 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: maplibre_gl
|
||||
sha256: "5c7b1008396b2a321bada7d986ed60f9423406fbc7bd16f7ce91b385dfa054cd"
|
||||
sha256: b676f124a2fcf88c4dafedc7b462155e6396d61ce7af46354b4de11b45c9812f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.22.0"
|
||||
version: "0.26.2"
|
||||
maplibre_gl_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: maplibre_gl_platform_interface
|
||||
sha256: "08ee0a2d0853ea945a0ab619d52c0c714f43144145cd67478fc6880b52f37509"
|
||||
sha256: "1f0ca8a99f03fa9434618ee21f4e42dd615830a7dd973e632b11c73ffec993a8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.22.0"
|
||||
version: "0.26.2"
|
||||
maplibre_gl_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: maplibre_gl_web
|
||||
sha256: "2b13d4b1955a9a54e38a718f2324e56e4983c080fc6de316f6f4b5458baacb58"
|
||||
sha256: bbf022f29ceef26d73f63e584819fbd02fbaf4eb1facf5234206c78936cf8f1c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.22.0"
|
||||
version: "0.26.2"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -2014,4 +2014,4 @@ packages:
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.12.0 <4.0.0"
|
||||
flutter: "3.44.1"
|
||||
flutter: "3.44.6"
|
||||
|
||||
@@ -2,11 +2,11 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: 'none'
|
||||
version: 3.0.2+3055
|
||||
version: 3.0.3+3056
|
||||
|
||||
environment:
|
||||
sdk: '>=3.12.0 <4.0.0'
|
||||
flutter: 3.44.1
|
||||
flutter: 3.44.6
|
||||
|
||||
dependencies:
|
||||
async: ^2.13.1
|
||||
@@ -19,7 +19,7 @@ dependencies:
|
||||
crypto: ^3.0.7
|
||||
device_info_plus: ^12.4.0
|
||||
diacritic: ^0.1.6
|
||||
drift: ^2.32.1
|
||||
drift: ^2.34.0
|
||||
drift_sqlite_async: 0.3.1
|
||||
dynamic_color: ^1.8.1
|
||||
easy_localization: ^3.0.8
|
||||
@@ -35,7 +35,7 @@ dependencies:
|
||||
flutter_web_auth_2: ^5.0.2
|
||||
fluttertoast: ^8.2.14
|
||||
geolocator: ^14.0.2
|
||||
home_widget: ^0.8.1
|
||||
home_widget: ^0.9.3
|
||||
hooks_riverpod: ^2.6.1
|
||||
http: ^1.6.0
|
||||
image_picker: ^1.2.1
|
||||
@@ -44,7 +44,7 @@ dependencies:
|
||||
intl: ^0.20.2
|
||||
local_auth: ^2.3.0
|
||||
logging: ^1.3.0
|
||||
maplibre_gl: ^0.22.0
|
||||
maplibre_gl: ^0.26.0
|
||||
native_video_player:
|
||||
git:
|
||||
url: https://github.com/immich-app/native_video_player
|
||||
@@ -96,7 +96,7 @@ dev_dependencies:
|
||||
auto_route_generator: ^10.5.0
|
||||
build_runner: ^2.13.1
|
||||
# Drift generator
|
||||
drift_dev: ^2.32.1
|
||||
drift_dev: ^2.34.0
|
||||
fake_async: ^1.3.3
|
||||
file: ^7.0.1 # for MemoryFileSystem
|
||||
flutter_launcher_icons: ^0.14.4
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user