Compare commits

..

1 Commits

Author SHA1 Message Date
timonrieger f2b2171d04 refactor: use zod codec for response DTO serialization 2026-04-17 17:42:05 +02:00
785 changed files with 8813 additions and 38834 deletions
-6
View File
@@ -6,12 +6,6 @@ mobile/openapi/**/*.dart linguist-generated=true
mobile/lib/**/*.g.dart -diff -merge
mobile/lib/**/*.g.dart linguist-generated=true
mobile/android/**/*.g.kt -diff -merge
mobile/android/**/*.g.kt linguist-generated=true
mobile/ios/**/*.g.swift -diff -merge
mobile/ios/**/*.g.swift linguist-generated=true
mobile/lib/**/*.drift.dart -diff -merge
mobile/lib/**/*.drift.dart linguist-generated=true
+1 -1
View File
@@ -1 +1 @@
24.15.0
24.14.1
+9 -9
View File
@@ -103,7 +103,7 @@ jobs:
- name: Restore Gradle Cache
id: cache-gradle-restore
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: |
~/.gradle/caches
@@ -143,9 +143,9 @@ jobs:
ALIAS: ${{ secrets.ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
IS_RELEASE: ${{ inputs.environment == 'production' || github.ref == 'refs/heads/main' }}
IS_MAIN: ${{ github.ref == 'refs/heads/main' }}
run: |
if [[ $IS_RELEASE == 'true' ]]; then
if [[ $IS_MAIN == 'true' ]]; then
flutter build apk --release
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
else
@@ -160,7 +160,7 @@ jobs:
- name: Save Gradle Cache
id: cache-gradle-save
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
if: github.ref == 'refs/heads/main'
with:
path: |
@@ -210,7 +210,7 @@ jobs:
working-directory: ./mobile
- name: Setup Ruby
uses: ruby/setup-ruby@7372622e62b60b3cb750dcd2b9e32c247ffec26a # v1.302.0
uses: ruby/setup-ruby@e65c17d16e57e481586a6a5a0282698790062f92 # v1.300.0
with:
ruby-version: '3.3'
bundler-cache: true
@@ -268,20 +268,20 @@ jobs:
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
ENVIRONMENT: ${{ inputs.environment || 'development' }}
BUNDLE_ID_SUFFIX: ${{ inputs.environment == 'production' && '' || 'development' }}
IS_RELEASE: ${{ inputs.environment == 'production' || github.ref == 'refs/heads/main' }}
GITHUB_REF: ${{ github.ref }}
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 120
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 6
working-directory: ./mobile/ios
run: |
# Upload to TestFlight on main or when explicitly invoked as a production release.
if [[ "$IS_RELEASE" == "true" ]]; then
# Only upload to TestFlight on main branch
if [[ "$GITHUB_REF" == "refs/heads/main" ]]; then
if [[ "$ENVIRONMENT" == "development" ]]; then
bundle exec fastlane gha_testflight_dev
else
bundle exec fastlane gha_release_prod
fi
else
# Build only, no TestFlight upload
# Build only, no TestFlight upload for non-main branches
bundle exec fastlane gha_build_only
fi
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
persist-credentials: false
- name: Check for breaking API changes
uses: oasdiff/oasdiff-action/breaking@f8cb9308b42121e793f835bd14c0b8090420430c # v0.0.39
uses: oasdiff/oasdiff-action/breaking@e6faebce24cf20ac38653d0d2c7f4aa80aaafc79 # v0.0.38
with:
base: https://raw.githubusercontent.com/${{ github.repository }}/main/open-api/immich-openapi-specs.json
revision: open-api/immich-openapi-specs.json
+3 -3
View File
@@ -57,7 +57,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -70,7 +70,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
# ️ 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 +83,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
with:
category: '/language:${{matrix.language}}'
+3 -5
View File
@@ -3,7 +3,7 @@ name: Docker
on:
workflow_dispatch:
push:
branches: [main, 'release/**']
branches: [main]
pull_request:
release:
types: [published]
@@ -53,8 +53,7 @@ jobs:
permissions:
contents: read
packages: write
# Retag sources from the :main image, so only retag for PRs and main-branch pushes.
if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == false && !github.event.pull_request.head.repo.fork && (github.event_name == 'pull_request' || github.ref == 'refs/heads/main') }}
if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == false && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
strategy:
matrix:
@@ -84,8 +83,7 @@ jobs:
permissions:
contents: read
packages: write
# Retag sources from the :main image, so only retag for PRs and main-branch pushes.
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == false && !github.event.pull_request.head.repo.fork && (github.event_name == 'pull_request' || github.ref == 'refs/heads/main') }}
if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == false && !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
strategy:
matrix:
+2 -2
View File
@@ -1,7 +1,7 @@
name: Docs build
on:
push:
branches: [main, 'release/**']
branches: [main]
pull_request:
release:
types: [published]
@@ -39,7 +39,7 @@ jobs:
force-filters: |
- '.github/workflows/docs-build.yml'
force-events: 'release'
force-branches: 'main,release/**'
force-branches: 'main'
build:
name: Docs Build
+1 -1
View File
@@ -211,7 +211,7 @@ jobs:
run: 'mise run //deployment:tf apply'
- name: Comment
uses: actions-cool/maintain-one-comment@909842216bc8e8658364c572ec52100f4c2cc50a # v3.3.0
uses: actions-cool/maintain-one-comment@4b2dbf086015f892dcb5e8c1106f5fccd6c1476b # v3.2.0
if: ${{ steps.parameters.outputs.event == 'pr' }}
with:
token: ${{ steps.token.outputs.token }}
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
run: 'mise run //deployment:tf destroy -- -refresh=false'
- name: Comment
uses: actions-cool/maintain-one-comment@909842216bc8e8658364c572ec52100f4c2cc50a # v3.3.0
uses: actions-cool/maintain-one-comment@4b2dbf086015f892dcb5e8c1106f5fccd6c1476b # v3.2.0
with:
token: ${{ steps.token.outputs.token }}
number: ${{ github.event.number }}
+12 -101
View File
@@ -3,13 +3,8 @@ name: Prepare new release
on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to release from (must be main or release/*)'
required: true
default: 'main'
type: string
serverBump:
description: 'Bump server version (only patch allowed on release/* branches)'
description: 'Bump server version'
required: true
default: 'false'
type: choice
@@ -34,31 +29,10 @@ concurrency:
permissions: {}
jobs:
validate_inputs:
runs-on: ubuntu-latest
permissions: {}
steps:
- name: Validate branch and bump combination
env:
BRANCH: ${{ inputs.branch }}
SERVER_BUMP: ${{ inputs.serverBump }}
run: |
set -euo pipefail
if [[ "$BRANCH" != "main" && "$BRANCH" != release/* ]]; then
echo "::error::branch must be 'main' or start with 'release/' (got '$BRANCH')"
exit 1
fi
if [[ "$BRANCH" != "main" && "$SERVER_BUMP" != "false" && "$SERVER_BUMP" != "patch" ]]; then
echo "::error::only 'patch' (or 'false') serverBump is allowed on '$BRANCH'"
exit 1
fi
merge_translations:
needs: [validate_inputs]
uses: ./.github/workflows/merge-translations.yml
with:
# Weblate tracks main only, so skip translations when releasing from a release/* branch.
skip: ${{ inputs.skipTranslations || inputs.branch != 'main' }}
skip: ${{ inputs.skipTranslations }}
permissions:
pull-requests: write
secrets:
@@ -86,7 +60,7 @@ jobs:
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: true
ref: ${{ inputs.branch }}
ref: main
- name: Install uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
@@ -120,10 +94,6 @@ jobs:
push: true
build_mobile:
# Mobile build numbers are monotonic per store; releasing from a release/* branch
# would collide with build numbers already shipped from main. Skip mobile on patch
# releases — handle mobile patches on main instead.
if: ${{ inputs.branch == 'main' }}
uses: ./.github/workflows/build-mobile.yml
needs: bump_version
permissions:
@@ -148,8 +118,6 @@ jobs:
prepare_release:
runs-on: ubuntu-latest
needs: [build_mobile, bump_version]
# Run even when build_mobile is skipped (patch release from release/* branch).
if: ${{ always() && needs.bump_version.result == 'success' && (needs.build_mobile.result == 'success' || needs.build_mobile.result == 'skipped') }}
permissions:
actions: read # To download the app artifact
# No content permissions are needed because it uses the app-token
@@ -166,83 +134,26 @@ jobs:
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: false
ref: ${{ needs.bump_version.outputs.ref }}
- name: Download APK
if: ${{ needs.build_mobile.result == 'success' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-apk-signed
github-token: ${{ steps.generate-token.outputs.token }}
- name: Assemble release assets
id: assets
env:
HAS_APK: ${{ needs.build_mobile.result == 'success' }}
run: |
{
echo 'files<<EOF'
echo 'docker/docker-compose.yml'
echo 'docker/docker-compose.rootless.yml'
echo 'docker/example.env'
echo 'docker/hwaccel.ml.yml'
echo 'docker/hwaccel.transcoding.yml'
echo 'docker/prometheus.yml'
if [[ "$HAS_APK" == "true" ]]; then
echo '*.apk'
fi
echo 'EOF'
} >> "$GITHUB_OUTPUT"
- name: Create draft release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
with:
draft: true
tag_name: ${{ needs.bump_version.outputs.version }}
target_commitish: ${{ inputs.branch }}
token: ${{ steps.generate-token.outputs.token }}
generate_release_notes: true
body_path: misc/release/notes.tmpl
files: ${{ steps.assets.outputs.files }}
backport_archived_versions:
# When releasing from a release/* branch, the archived-versions.json update
# lives on that branch only. Open a PR to mirror the new entry onto main so
# main's docs keep a complete archive list.
if: ${{ inputs.branch != 'main' && needs.bump_version.result == 'success' }}
runs-on: ubuntu-latest
needs: [bump_version, prepare_release]
permissions: {} # uses the app token
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }}
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
- name: Checkout main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
persist-credentials: false
ref: main
- name: Update archived versions on main
env:
VERSION: ${{ needs.bump_version.outputs.version }}
run: ./misc/release/archive-version.js "${VERSION#v}"
- name: Open backport PR
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
token: ${{ steps.generate-token.outputs.token }}
branch: backport/archived-versions-${{ needs.bump_version.outputs.version }}
base: main
commit-message: 'chore(docs): archive ${{ needs.bump_version.outputs.version }}'
title: 'chore(docs): archive ${{ needs.bump_version.outputs.version }}'
body: |
Backports the `archived-versions.json` entry for ${{ needs.bump_version.outputs.version }},
released from `${{ inputs.branch }}`, so main's docs archive list stays complete.
add-paths: docs/static/archived-versions.json
delete-branch: true
files: |
docker/docker-compose.yml
docker/docker-compose.rootless.yml
docker/example.env
docker/hwaccel.ml.yml
docker/hwaccel.transcoding.yml
docker/prometheus.yml
*.apk
+3
View File
@@ -1,3 +1,6 @@
[submodule "mobile/.isar"]
path = mobile/.isar
url = https://github.com/isar/isar
[submodule "e2e/test-assets"]
path = e2e/test-assets
url = https://github.com/immich-app/test-assets
+12
View File
@@ -13,6 +13,10 @@
"editor.wordBasedSuggestions": "off"
},
"[javascript]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.removeUnusedImports": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
@@ -25,10 +29,18 @@
"editor.formatOnSave": true
},
"[svelte]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.removeUnusedImports": "explicit"
},
"editor.defaultFormatter": "svelte.svelte-vscode",
"editor.formatOnSave": true
},
"[typescript]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit",
"source.removeUnusedImports": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
+1 -1
View File
@@ -1 +1 @@
24.15.0
24.14.1
+1 -1
View File
@@ -68,6 +68,6 @@
"micromatch": "^4.0.8"
},
"volta": {
"node": "24.15.0"
"node": "24.14.1"
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
[tools]
terragrunt = "1.0.1"
opentofu = "1.11.6"
terragrunt = "1.0.0"
opentofu = "1.11.5"
[tasks."tg:fmt"]
run = "terragrunt hclfmt"
+1 -1
View File
@@ -85,7 +85,7 @@ services:
container_name: immich_prometheus
ports:
- 9090:9090
image: prom/prometheus@sha256:5550dc63da361dc30f6fe02ac0e4dfc736ededfef3c8d12a634db04a67824d78
image: prom/prometheus@sha256:dda13e28bf95a5e5ca5b8ed56852006094c1c8e8871d9c9dbeed30aa6e55271f
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
+1 -1
View File
@@ -1 +1 @@
24.15.0
24.14.1
-7
View File
@@ -50,10 +50,6 @@ Before enabling OAuth in Immich, a new client application needs to be configured
- `https://immich.example.com/auth/login`
- `https://immich.example.com/user-settings`
3. Configure Backchannel logout URL
If the authentication server supports it, the **Backchannel logout URL** can be specified, and it is of the form: `http://DOMAIN:PORT/api/oauth/backchannel-logout`.
## Enable OAuth
Once you have a new OAuth client application configured, Immich can be configured using the Administration Settings page, available on the web (Administration -> Settings).
@@ -67,8 +63,6 @@ Once you have a new OAuth client application configured, Immich can be configure
| `scope` | string | openid email profile | Full list of scopes to send with the request (space delimited) |
| `id_token_signed_response_alg` | string | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
| `userinfo_signed_response_alg` | string | none | The algorithm used to sign the userinfo response (examples: RS256, HS256) |
| `prompt` | string | (empty) | Prompt parameter for authorization url (examples: select_account, login, consent) |
| `end_session_endpoint` | URL | (empty) | Http(s) alternative end session endpoint (logout URI) |
| Request timeout | string | 30,000 (30 seconds) | Number of milliseconds to wait for http requests to complete before giving up |
| Storage Label Claim | string | preferred_username | Claim mapping for the user's storage label**¹** |
| Role Claim | string | immich_role | Claim mapping for the user's role. (should return "user" or "admin")**¹** |
@@ -187,7 +181,6 @@ Configuration of OAuth in Immich System Settings
| Scope | openid email profile immich_scope |
| ID Token Signed Response Algorithm | RS256 |
| Userinfo Signed Response Algorithm | RS256 |
| End Session Endpoint | https://auth.example.com/logout?rd=https://immich.example.com/ |
| Storage Label Claim | uid |
| Storage Quota Claim | immich_quota |
| Default Storage Quota (GiB) | 0 (empty for unlimited quota) |
-1
View File
@@ -18,7 +18,6 @@ For the full list, refer to the [Immich source code](https://github.com/immich-a
| `JPEG 2000` | `.jp2` | :white_check_mark: | |
| `JPEG` | `.jpeg` `.jpg` `.jpe` `.insp` | :white_check_mark: | |
| `JPEG XL` | `.jxl` | :white_check_mark: | |
| `MPO` | `.mpo` | :white_check_mark: | Multi-Picture |
| `PNG` | `.png` | :white_check_mark: | |
| `PSD` | `.psd` | :white_check_mark: | Adobe Photoshop |
| `RAW` | `.raw` | :white_check_mark: | |
-1
View File
@@ -193,7 +193,6 @@ The default configuration looks like this:
"defaultStorageQuota": null,
"enabled": false,
"issuerUrl": "",
"endSessionEndpoint": "",
"mobileOverrideEnabled": false,
"mobileRedirectUri": "",
"profileSigningAlgorithm": "none",
+1 -1
View File
@@ -37,7 +37,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N
| `IMMICH_LOG_FORMAT` | Log output format (`console`, `json`) | `console` | server | api, microservices |
| `IMMICH_MEDIA_LOCATION` | Media location inside the container ⚠️**You probably shouldn't set this**<sup>\*2</sup>⚠️ | `/data` | server | api, microservices |
| `IMMICH_CONFIG_FILE` | Path to config file | | server | api, microservices |
| `IMMICH_HELMET_FILE` | Path to a json file with [helmet](https://www.npmjs.com/package/helmet) options. Set to `false` to disable. Set to `true` to use `server/helmet.json`. | `false` | server | api |
| `IMMICH_HELMET_FILE` | Path to a json file with [helmet](https://www.npmjs.com/package/helmet) options. Set to `false` to disable. Set to `true` to use `server/helmet.json`. | `false` | server | api, microservices |
| `NO_COLOR` | Set to `true` to disable color-coded log output | `false` | server, machine learning | |
| `CPU_CORES` | Number of cores available to the Immich server | auto-detected CPU core count | server | |
| `IMMICH_API_METRICS_PORT` | Port for the OTEL metrics | `8081` | server | api |
+7 -7
View File
@@ -17,10 +17,10 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "~3.10.0",
"@docusaurus/preset-classic": "~3.10.0",
"@docusaurus/theme-common": "~3.10.0",
"@docusaurus/theme-mermaid": "~3.10.0",
"@docusaurus/core": "~3.9.0",
"@docusaurus/preset-classic": "~3.9.0",
"@docusaurus/theme-common": "~3.9.0",
"@docusaurus/theme-mermaid": "~3.9.0",
"@mdi/js": "^7.3.67",
"@mdi/react": "^1.6.1",
"@mdx-js/react": "^3.0.0",
@@ -36,9 +36,9 @@
"url": "^0.11.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "~3.10.0",
"@docusaurus/module-type-aliases": "~3.9.0",
"@docusaurus/tsconfig": "^3.10.0",
"@docusaurus/types": "^3.10.0",
"@docusaurus/types": "^3.7.0",
"prettier": "^3.7.4",
"typescript": "^6.0.0"
},
@@ -58,6 +58,6 @@
"node": ">=20"
},
"volta": {
"node": "24.15.0"
"node": "24.14.1"
}
}
+5 -31
View File
@@ -1,12 +1,5 @@
import {
calculateJwkThumbprint,
exportJWK,
importPKCS8,
importSPKI,
SignJWT,
} from 'jose';
import { exportJWK, generateKeyPair } from 'jose';
import Provider from 'oidc-provider';
import { PRIVATE_KEY_PEM, PUBLIC_KEY_PEM } from './test-keys';
export enum OAuthClient {
DEFAULT = 'client-default',
@@ -51,29 +44,6 @@ const claims = [
},
];
const privateKey = await importPKCS8(PRIVATE_KEY_PEM, 'RS256', {
extractable: true,
});
const publicKey = await importSPKI(PUBLIC_KEY_PEM, 'RS256', {
extractable: true,
});
const kid = await calculateJwkThumbprint(await exportJWK(publicKey));
export async function generateLogoutToken(iss: string, sub: string) {
return await new SignJWT({
iss: iss,
aud: OAuthClient.DEFAULT,
iat: Math.floor(Date.now() / 1000),
jti: crypto.randomUUID(),
sub: sub,
events: {
'http://schemas.openid.net/event/backchannel-logout': {},
},
})
.setProtectedHeader({ alg: 'RS256', typ: 'logout+jwt', kid: kid })
.sign(privateKey);
}
const withDefaultClaims = (sub: string) => ({
sub,
email: `${sub}@immich.app`,
@@ -96,6 +66,10 @@ const getClaims = (sub: string, use?: string) => {
};
const setup = async () => {
const { privateKey, publicKey } = await generateKeyPair('RS256', {
extractable: true,
});
const redirectUris = [
'http://127.0.0.1:2285/auth/login',
'https://photos.immich.app/oauth/mobile-redirect',
-38
View File
@@ -1,38 +0,0 @@
export const PRIVATE_KEY_PEM = `-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVj5C7hzN3E2HO
TcJ+DN/e2NSTQFj4rPylz4J8xjm8Es7l0k2kK5EEGvUNVGZbw7s055c+6kwP9eqg
B5XFE7+26Fcq1sou6Tbm310kU4dnMW5l2CgwrhaGyb1pNysao0AMLT60dFYqtUwn
ha9ceCsa+ZU1JrknVf3rONtppBvhWoI7CO9XX1keVQ0unHPzCWUjpXTzC8OGEbmB
2w7ZIUf8OfJkd5RZ4OtIpML71W9n13aDxT50x2/EW/pFLFtQ/oaleOKHpvlRXDRX
W86G4moUJym3gHMXMUj2aOcFG2UJnpLruKz3i5qZwYiTRlBP6O9EIQNCVtYxchuN
V1CCcBU1AgMBAAECggEAJLfXMu8Nx89ynPVyyUMMaFfoEpHC9iR0L5obQVpiPMYK
VRqVVLecdftPS9s7eQ58BNBRzdC0ZVu841aRYs3HLNbsZZhPkYZQpAxU//Dg5okY
fzj7Hv5yidt4HN9+Pd8z/3lRMnj4WapifLaBt8xJ2ujJBMBRxzJBsXDnT0+Kx7+y
bYDeuVfyUTEikaK3QZTbuRF3D3eiuN16GG+hv8UqTF2eYbPxdiLjYpTSHa4mH88C
qfJz2Xt4SEzmyeo3G+MO17wDFOwtEe8ojlJfULHnHJSFdUwTfYIFM1bg5/fJ9MOS
/fO3TSG+wkQqjQa6eoGssAzP87fL2XNLzlDtGY/7uQKBgQDHuJHOtf1EjOvNYiP7
EN+8QGs41ghzt9CQRQxWbHpusR3IW3P83KMXwYmrlG70oOUXBRGSB/ESXUofXc5W
pu5+Y55S44aUnu/a9yOBttYW0dtHZSL0zFT+PlVASwUzFZ2zcH1KXlUkSpfL5OAD
PyDDTnBZ2AWh45fRO9wLo6PPuQKBgQC/tI03RqU3mOjqukKbquYeIpXHfRU5Z0DM
u9ru1THYEl6fmkMXycxo/mvW3awyFuyKy/VodqIgKnFgumEqCHZh6OAMm/LC7TfA
l9tjFSs/MyOqQVD4kbX+z6Oq4c4GccDoXfsQ3gzECoBapegi/F+6/25y+/C8ghXb
J/Jg1GQXXQKBgQDFgWbfzuVZZyrBfu4qGLPJDMN7/114YizknwPma3xf/tN/EcGQ
K/k1QvWMMkvPq1UiAKcxjJ0AFjV482FcG9T6NDWbrtmmG88C8Sex3Ue2ZW2+GuwI
vhDHJIlV/Vp0/Elp7DJa2xLDwuh+gCZvz3vs6KL+ljxrrhCyn8mp0PfsMQKBgFFZ
KnuETOO0zVGdzFoGQTQUdP58A5+iQwsdxB+I9Ge+E80iRso3ZbhADj7VPhbbR3D2
b6LuhImluQrUzBpsEOAnU7vGCVPSGdBuIDiBaSKebsn2gYeZPWNtdQQ0YZq2dqek
Cb/0mfIuipzsvf7qnSza62F7q4IyqVegMegI+Jg5AoGATM3NMy7JZeKzSkm+3ohU
3xZOwgqKV9SH+0OeYWpuBxT7D7FlrKKI4NJ3XN3hg2f/DJAF6dH11CPe7pk94yol
HMbh+PQUQ6GYvAzxIOvagWboQ3lzeyubNMpyFjfOrIE/WOQCUBZ9tIwCHIarIuyi
QRuNOj3+U8T/n1Ww352HBdw=
-----END PRIVATE KEY-----`;
export const PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlY+Qu4czdxNhzk3Cfgzf
3tjUk0BY+Kz8pc+CfMY5vBLO5dJNpCuRBBr1DVRmW8O7NOeXPupMD/XqoAeVxRO/
tuhXKtbKLuk25t9dJFOHZzFuZdgoMK4Whsm9aTcrGqNADC0+tHRWKrVMJ4WvXHgr
GvmVNSa5J1X96zjbaaQb4VqCOwjvV19ZHlUNLpxz8wllI6V08wvDhhG5gdsO2SFH
/DnyZHeUWeDrSKTC+9VvZ9d2g8U+dMdvxFv6RSxbUP6GpXjih6b5UVw0V1vOhuJq
FCcpt4BzFzFI9mjnBRtlCZ6S67is94uamcGIk0ZQT+jvRCEDQlbWMXIbjVdQgnAV
NQIDAQAB
-----END PUBLIC KEY-----`;
+1 -1
View File
@@ -1 +1 @@
24.15.0
24.14.1
+1 -1
View File
@@ -58,6 +58,6 @@
"vitest": "^4.0.0"
},
"volta": {
"node": "24.15.0"
"node": "24.14.1"
}
}
+34 -66
View File
@@ -154,31 +154,23 @@ describe('/albums', () => {
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedLink,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedEditorUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedViewerUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user2.userId,
albumName: user2SharedUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user2.userId }) },
]),
shared: true,
}),
]),
@@ -192,31 +184,23 @@ describe('/albums', () => {
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedEditorUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedViewerUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedLink,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1NotShared,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: false,
}),
]),
@@ -232,31 +216,23 @@ describe('/albums', () => {
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedEditorUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedViewerUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user1.userId,
albumName: user1SharedLink,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: true,
}),
expect.objectContaining({
ownerId: user2.userId,
albumName: user2SharedUser,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user2.userId }) },
]),
shared: true,
}),
]),
@@ -272,10 +248,8 @@ describe('/albums', () => {
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({
ownerId: user1.userId,
albumName: user1NotShared,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) },
]),
shared: false,
}),
]),
@@ -312,17 +286,13 @@ describe('/albums', () => {
expect(body).toEqual(
expect.arrayContaining([
expect.objectContaining({
ownerId: user4.userId,
albumName: user4DeletedAsset,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user4.userId }) },
]),
shared: false,
}),
expect.objectContaining({
ownerId: user4.userId,
albumName: user4Empty,
albumUsers: expect.arrayContaining([
{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user4.userId }) },
]),
shared: false,
}),
]),
@@ -392,17 +362,16 @@ describe('/albums', () => {
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
contributorCounts: [{ userId: user1.userId, assetCount: 1 }],
assetCount: 1,
lastModifiedAssetTimestamp: expect.any(String),
endDate: expect.any(String),
startDate: expect.any(String),
albumUsers: expect.any(Array),
shared: true,
}),
);
expect(body).toEqual({
...user2Albums[0],
contributorCounts: [{ userId: user1.userId, assetCount: 1 }],
assetCount: 1,
lastModifiedAssetTimestamp: expect.any(String),
endDate: expect.any(String),
startDate: expect.any(String),
albumUsers: expect.any(Array),
shared: true,
});
});
});
@@ -428,13 +397,15 @@ describe('/albums', () => {
id: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String),
ownerId: user1.userId,
albumName: 'New album',
description: '',
albumThumbnailAssetId: null,
shared: false,
albumUsers: [{ role: AlbumUserRole.Owner, user: expect.objectContaining({ id: user1.userId }) }],
albumUsers: [],
hasSharedLink: false,
assetCount: 0,
owner: expect.objectContaining({ email: user1.userEmail }),
isActivityEnabled: true,
order: AssetOrder.Desc,
});
@@ -650,11 +621,11 @@ describe('/albums', () => {
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
albumUsers: expect.arrayContaining([
albumUsers: [
expect.objectContaining({
user: expect.objectContaining({ id: user2.userId }),
}),
]),
],
}),
);
});
@@ -666,7 +637,7 @@ describe('/albums', () => {
.send({ albumUsers: [{ userId: user1.userId, role: AlbumUserRole.Editor }] });
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('User already added'));
expect(body).toEqual(errorDto.badRequest('Cannot be shared with owner'));
});
it('should not be able to add existing user to shared album', async () => {
@@ -692,7 +663,7 @@ describe('/albums', () => {
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }],
});
expect(album.albumUsers[1].role).toEqual(AlbumUserRole.Viewer);
expect(album.albumUsers[0].role).toEqual(AlbumUserRole.Viewer);
const { status } = await request(app)
.put(`/albums/${album.id}/user/${user2.userId}`)
@@ -707,10 +678,7 @@ describe('/albums', () => {
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(body).toEqual(
expect.objectContaining({
albumUsers: [
expect.objectContaining({ role: AlbumUserRole.Owner }),
expect.objectContaining({ role: AlbumUserRole.Editor }),
],
albumUsers: [expect.objectContaining({ role: AlbumUserRole.Editor })],
}),
);
});
@@ -721,7 +689,7 @@ describe('/albums', () => {
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }],
});
expect(album.albumUsers[1].role).toEqual(AlbumUserRole.Viewer);
expect(album.albumUsers[0].role).toEqual(AlbumUserRole.Viewer);
const { status, body } = await request(app)
.put(`/albums/${album.id}/user/${user2.userId}`)
+11 -94
View File
@@ -1,10 +1,9 @@
import { OAuthClient, OAuthUser, generateLogoutToken } from '@immich/e2e-auth-server';
import { OAuthClient, OAuthUser } from '@immich/e2e-auth-server';
import {
LoginResponseDto,
SystemConfigOAuthDto,
getConfigDefaults,
getMyUser,
getSessions,
startOAuth,
updateConfig,
} from '@immich/sdk';
@@ -89,19 +88,17 @@ describe(`/oauth`, () => {
beforeAll(async () => {
await utils.resetDatabase();
admin = await utils.adminSetup();
await setupOAuth(admin.accessToken, {
enabled: true,
clientId: OAuthClient.DEFAULT,
clientSecret: OAuthClient.DEFAULT,
buttonText: 'Login with Immich',
storageLabelClaim: 'immich_username',
});
});
describe('POST /oauth/authorize', () => {
beforeAll(async () => {
await setupOAuth(admin.accessToken, {
enabled: true,
clientId: OAuthClient.DEFAULT,
clientSecret: OAuthClient.DEFAULT,
buttonText: 'Login with Immich',
storageLabelClaim: 'immich_username',
});
});
it(`should throw an error if a redirect uri is not provided`, async () => {
const { status, body } = await request(app).post('/oauth/authorize').send({});
expect(status).toBe(400);
@@ -121,46 +118,9 @@ describe(`/oauth`, () => {
expect(params.get('redirect_uri')).toBe('http://127.0.0.1:2285/auth/login');
expect(params.get('state')).toBeDefined();
});
it('should not include the prompt parameter when not configured', async () => {
const { status, body } = await request(app)
.post('/oauth/authorize')
.send({ redirectUri: 'http://127.0.0.1:2285/auth/login' });
expect(status).toBe(201);
const params = new URL(body.url).searchParams;
expect(params.get('prompt')).toBeNull();
});
it('should include the prompt parameter when configured', async () => {
await setupOAuth(admin.accessToken, {
enabled: true,
clientId: OAuthClient.DEFAULT,
clientSecret: OAuthClient.DEFAULT,
prompt: 'select_account',
});
const { status, body } = await request(app)
.post('/oauth/authorize')
.send({ redirectUri: 'http://127.0.0.1:2285/auth/login' });
expect(status).toBe(201);
const params = new URL(body.url).searchParams;
expect(params.get('prompt')).toBe('select_account');
});
});
describe('POST /oauth/callback', () => {
beforeAll(async () => {
await setupOAuth(admin.accessToken, {
enabled: true,
clientId: OAuthClient.DEFAULT,
clientSecret: OAuthClient.DEFAULT,
buttonText: 'Login with Immich',
storageLabelClaim: 'immich_username',
});
});
it(`should throw an error if a url is not provided`, async () => {
const { status, body } = await request(app).post('/oauth/callback').send({});
expect(status).toBe(400);
@@ -199,9 +159,10 @@ describe(`/oauth`, () => {
it(`should throw an error if the codeVerifier doesn't match the challenge`, async () => {
const callbackParams = await loginWithOAuth('oauth-auto-register');
const { codeVerifier } = await loginWithOAuth('oauth-auto-register');
const { status } = await request(app)
const { status, body } = await request(app)
.post('/oauth/callback')
.send({ ...callbackParams, codeVerifier });
console.log(body);
expect(status).toBeGreaterThanOrEqual(400);
});
@@ -373,50 +334,6 @@ describe(`/oauth`, () => {
});
});
describe(`POST /oauth/backchannel-logout`, () => {
it(`should throw an error if the logout_token is not provided`, async () => {
const { status, body } = await request(app).post('/oauth/backchannel-logout').send({});
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest(['[logout_token] Invalid input: expected string, received undefined']));
});
it(`should throw an error if an invalid logout token is provided`, async () => {
const { status, body } = await request(app)
.post('/oauth/backchannel-logout')
.send({ logout_token: 'invalid token' });
expect(status).toBe(400);
expect(body).toEqual(errorDto.badRequest('Error backchannel logout: token validation failed'));
});
it(`should logout user if a valid logout token is provided`, async () => {
await setupOAuth(admin.accessToken, {
enabled: true,
clientId: OAuthClient.DEFAULT,
clientSecret: OAuthClient.DEFAULT,
autoRegister: true,
signingAlgorithm: 'RS256',
buttonText: 'Login with Immich',
});
const callbackParams = await loginWithOAuth('backchannel-logout-user');
const { status: callbackStatus, body: callbackBody } = await request(app)
.post('/oauth/callback')
.send(callbackParams);
expect(callbackStatus).toBe(201);
await expect(getSessions({ headers: asBearerAuth(callbackBody.accessToken) })).resolves.toHaveLength(1);
const logoutToken = await generateLogoutToken('http://0.0.0.0:2286', 'backchannel-logout-user');
const { status, body } = await request(app).post('/oauth/backchannel-logout').send({ logout_token: logoutToken });
expect(status).toBe(200);
expect(body).toMatchObject({});
await expect(getSessions({ headers: asBearerAuth(callbackBody.accessToken) })).rejects.toMatchObject({
status: 401,
});
});
});
describe('mobile redirect override', () => {
beforeAll(async () => {
await setupOAuth(admin.accessToken, {
@@ -3,7 +3,6 @@
*/
import {
AlbumUserRole,
AssetTypeEnum,
AssetVisibility,
UserAvatarColor,
@@ -421,7 +420,9 @@ export function getAlbum(
albumThumbnailAssetId: album.thumbnailAssetId,
createdAt: album.createdAt,
updatedAt: album.updatedAt,
albumUsers: [{ user: albumOwner, role: AlbumUserRole.Owner }],
ownerId: albumOwner.id,
owner: albumOwner,
albumUsers: [], // Empty array for non-shared album
shared: false,
hasSharedLink: false,
isActivityEnabled: true,
-1
View File
@@ -223,7 +223,6 @@ export const setupBaseMockApiRoutes = async (context: BrowserContext, adminUserI
'.jp2',
'.jpe',
'.jxl',
'.mpo',
'.svg',
'.tif',
'.tiff',
@@ -349,7 +349,7 @@ test.describe('Timeline', () => {
expect(visibleMockAssetsYearMonths).toContain(month);
}
});
test.skip('Deep link to last photo, scroll up', async ({ page }) => {
test('Deep link to last photo, scroll up', async ({ page }) => {
const lastAsset = assets.at(-1)!;
await pageUtils.deepLinkPhotosPage(page, lastAsset.id);
@@ -361,7 +361,7 @@ test.describe('Timeline', () => {
await thumbnailUtils.expectInViewport(page, '14e5901f-fd7f-40c0-b186-4d7e7fc67968');
});
test.skip('Deep link to first bucket, scroll down', async ({ page }) => {
test('Deep link to first bucket, scroll down', async ({ page }) => {
const lastAsset = assets.at(0)!;
await pageUtils.deepLinkPhotosPage(page, lastAsset.id);
await timelineUtils.locator(page).hover();
@@ -440,7 +440,7 @@ test.describe('Timeline', () => {
await thumbnailUtils.expectInViewport(page, asset.id);
await thumbnailUtils.expectSelectedDisabled(page, asset.id);
});
test.skip('Add photos to album', async ({ page }) => {
test('Add photos to album', async ({ page }) => {
const album = timelineRestData.album;
await pageUtils.openAlbumPage(page, album.id);
await page.locator('nav button[aria-label="Add photos"]').click();
@@ -752,7 +752,7 @@ test.describe('Timeline', () => {
await page.getByText('Photos', { exact: true }).click();
await thumbnailUtils.expectInViewport(page, assetToFavorite.id);
});
test.skip('open /favorites, archive photo, unarchive photo', async ({ page }) => {
test('open /favorites, archive photo, unarchive photo', async ({ page }) => {
await pageUtils.openFavorites(page);
const assetToArchive = getAsset(timelineRestData, 'ad31e29f-2069-4574-b9a9-ad86523c92cb')!;
await thumbnailUtils.withAssetId(page, assetToArchive.id).hover();
-2
View File
@@ -276,11 +276,9 @@
"oauth_button_text": "Button text",
"oauth_client_secret_description": "Required for confidential client, or if PKCE (Proof Key for Code Exchange) is not supported for public client.",
"oauth_enable_description": "Login with OAuth",
"oauth_end_session_url_description": "Redirect the user to this URI when they log out.",
"oauth_mobile_redirect_uri": "Mobile redirect URI",
"oauth_mobile_redirect_uri_override": "Mobile redirect URI override",
"oauth_mobile_redirect_uri_override_description": "Enable when OAuth provider does not allow a mobile URI, like ''{callback}''",
"oauth_prompt_description": "Prompt parameter (e.g. select_account, login, consent)",
"oauth_role_claim": "Role Claim",
"oauth_role_claim_description": "Automatically grant admin access based on the presence of this claim. The claim may have either 'user' or 'admin'.",
"oauth_settings": "OAuth",
+4 -4
View File
@@ -14,11 +14,11 @@ config_roots = [
]
[tools]
node = "24.15.0"
flutter = "3.41.6"
node = "24.14.1"
flutter = "3.35.7"
pnpm = "10.33.0"
terragrunt = "1.0.1"
opentofu = "1.11.6"
terragrunt = "1.0.0"
opentofu = "1.11.5"
java = "21.0.2"
[tools."github:CQLabs/homebrew-dcm"]
+1 -1
View File
@@ -1,5 +1,5 @@
{
"dart.flutterSdkPath": ".fvm/versions/3.41.7",
"dart.flutterSdkPath": ".fvm/versions/3.41.6",
"dart.lineLength": 120,
"[dart]": {
"editor.rulers": [
@@ -43,8 +43,8 @@ class BackgroundEngineLock(context: Context) : BackgroundWorkerLockApi, ImmichPl
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
super.onAttachedToEngine(binding)
engineCount.incrementAndGet()
checkAndEnforceBackgroundLock(binding.applicationContext)
engineCount.incrementAndGet()
Log.i(TAG, "Flutter engine attached. Attached Engines count: $engineCount")
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -37,150 +37,36 @@ private object BackgroundWorkerPigeonUtils {
)
}
}
fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}
fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}
fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}
fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}
fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}
/**
@@ -193,7 +79,7 @@ class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : RuntimeException()
) : Throwable()
/** Generated class from Pigeon that represents data sent in messages. */
data class BackgroundWorkerSettings (
@@ -215,22 +101,15 @@ data class BackgroundWorkerSettings (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is BackgroundWorkerSettings) {
return false
}
if (this === other) {
return true
}
val other = other as BackgroundWorkerSettings
return BackgroundWorkerPigeonUtils.deepEquals(this.requiresCharging, other.requiresCharging) && BackgroundWorkerPigeonUtils.deepEquals(this.minimumDelaySeconds, other.minimumDelaySeconds)
}
return BackgroundWorkerPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.requiresCharging)
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.minimumDelaySeconds)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@@ -5,10 +5,8 @@ import android.provider.MediaStore
import android.util.Log
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import io.flutter.embedding.engine.FlutterEngineCache
import java.util.concurrent.TimeUnit
@@ -20,7 +18,6 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
override fun enable() {
enqueueMediaObserver(ctx)
enqueuePeriodicWorker(ctx)
}
override fun saveNotificationMessage(title: String, body: String) {
@@ -30,14 +27,12 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
override fun configure(settings: BackgroundWorkerSettings) {
BackgroundWorkerPreferences(ctx).updateSettings(settings)
enqueueMediaObserver(ctx)
enqueuePeriodicWorker(ctx)
}
override fun disable() {
WorkManager.getInstance(ctx).apply {
cancelUniqueWork(OBSERVER_WORKER_NAME)
cancelUniqueWork(BACKGROUND_WORKER_NAME)
cancelUniqueWork(PERIODIC_WORKER_NAME)
}
Log.i(TAG, "Cancelled background upload tasks")
}
@@ -45,7 +40,6 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
companion object {
private const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1"
private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1"
private const val PERIODIC_WORKER_NAME = "immich/PeriodicBackgroundWorkerV1"
const val ENGINE_CACHE_KEY = "immich::background_worker::engine"
@@ -61,7 +55,7 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
setRequiresCharging(settings.requiresCharging)
}.build()
val work = OneTimeWorkRequestBuilder<MediaObserver>()
val work = OneTimeWorkRequest.Builder(MediaObserver::class.java)
.setConstraints(constraints)
.build()
WorkManager.getInstance(ctx)
@@ -73,30 +67,10 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
)
}
fun enqueuePeriodicWorker(ctx: Context) {
val settings = BackgroundWorkerPreferences(ctx).getSettings()
val constraints = Constraints.Builder().apply {
setRequiresCharging(settings.requiresCharging)
}.build()
val work =
PeriodicWorkRequestBuilder<PeriodicWorker>(
1,
TimeUnit.HOURS,
15,
TimeUnit.MINUTES
).setConstraints(constraints)
.build()
WorkManager.getInstance(ctx)
.enqueueUniquePeriodicWork(PERIODIC_WORKER_NAME, ExistingPeriodicWorkPolicy.UPDATE, work)
Log.i(TAG, "Enqueued periodic background worker with name: $PERIODIC_WORKER_NAME")
}
fun enqueueBackgroundWorker(ctx: Context) {
val constraints = Constraints.Builder().setRequiresBatteryNotLow(true).build()
val work = OneTimeWorkRequestBuilder<BackgroundWorker>()
val work = OneTimeWorkRequest.Builder(BackgroundWorker::class.java)
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
.build()
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -1,16 +0,0 @@
package app.alextran.immich.background
import android.content.Context
import android.util.Log
import androidx.work.Worker
import androidx.work.WorkerParameters
class PeriodicWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
private val ctx: Context = context.applicationContext
override fun doWork(): Result {
Log.i("PeriodicWorker", "Periodic worker triggered, starting background worker")
BackgroundWorkerApiImpl.enqueueBackgroundWorker(ctx)
return Result.success()
}
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -46,7 +46,7 @@ class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : RuntimeException()
) : Throwable()
enum class NetworkCapability(val raw: Int) {
CELLULAR(0),
@@ -75,7 +75,7 @@ private open class ConnectivityPigeonCodec : StandardMessageCodec() {
when (value) {
is NetworkCapability -> {
stream.write(129)
writeValue(stream, value.raw.toLong())
writeValue(stream, value.raw)
}
else -> super.writeValue(stream, value)
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -34,150 +34,36 @@ private object NetworkPigeonUtils {
)
}
}
fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}
fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}
fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}
fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}
fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}
/**
@@ -190,7 +76,7 @@ class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : RuntimeException()
) : Throwable()
/** Generated class from Pigeon that represents data sent in messages. */
data class ClientCertData (
@@ -212,22 +98,15 @@ data class ClientCertData (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is ClientCertData) {
return false
}
if (this === other) {
return true
}
val other = other as ClientCertData
return NetworkPigeonUtils.deepEquals(this.data, other.data) && NetworkPigeonUtils.deepEquals(this.password, other.password)
}
return NetworkPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + NetworkPigeonUtils.deepHash(this.data)
result = 31 * result + NetworkPigeonUtils.deepHash(this.password)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
@@ -256,24 +135,15 @@ data class ClientCertPrompt (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is ClientCertPrompt) {
return false
}
if (this === other) {
return true
}
val other = other as ClientCertPrompt
return NetworkPigeonUtils.deepEquals(this.title, other.title) && NetworkPigeonUtils.deepEquals(this.message, other.message) && NetworkPigeonUtils.deepEquals(this.cancel, other.cancel) && NetworkPigeonUtils.deepEquals(this.confirm, other.confirm)
}
return NetworkPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + NetworkPigeonUtils.deepHash(this.title)
result = 31 * result + NetworkPigeonUtils.deepHash(this.message)
result = 31 * result + NetworkPigeonUtils.deepHash(this.cancel)
result = 31 * result + NetworkPigeonUtils.deepHash(this.confirm)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
private open class NetworkPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -46,7 +46,7 @@ class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : RuntimeException()
) : Throwable()
private open class LocalImagesPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return super.readValueOfType(type, buffer)
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -34,150 +34,36 @@ private object MessagesPigeonUtils {
)
}
}
fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}
fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}
fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}
fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}
fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}
/**
@@ -190,7 +76,7 @@ class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : RuntimeException()
) : Throwable()
enum class PlatformAssetPlaybackStyle(val raw: Int) {
UNKNOWN(0),
@@ -216,7 +102,7 @@ data class PlatformAsset (
val updatedAt: Long? = null,
val width: Long? = null,
val height: Long? = null,
val durationMs: Long,
val durationInSeconds: Long,
val orientation: Long,
val isFavorite: Boolean,
val adjustmentTime: Long? = null,
@@ -234,14 +120,14 @@ data class PlatformAsset (
val updatedAt = pigeonVar_list[4] as Long?
val width = pigeonVar_list[5] as Long?
val height = pigeonVar_list[6] as Long?
val durationMs = pigeonVar_list[7] as Long
val durationInSeconds = pigeonVar_list[7] as Long
val orientation = pigeonVar_list[8] as Long
val isFavorite = pigeonVar_list[9] as Boolean
val adjustmentTime = pigeonVar_list[10] as Long?
val latitude = pigeonVar_list[11] as Double?
val longitude = pigeonVar_list[12] as Double?
val playbackStyle = pigeonVar_list[13] as PlatformAssetPlaybackStyle
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationMs, orientation, isFavorite, adjustmentTime, latitude, longitude, playbackStyle)
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite, adjustmentTime, latitude, longitude, playbackStyle)
}
}
fun toList(): List<Any?> {
@@ -253,7 +139,7 @@ data class PlatformAsset (
updatedAt,
width,
height,
durationMs,
durationInSeconds,
orientation,
isFavorite,
adjustmentTime,
@@ -263,34 +149,15 @@ data class PlatformAsset (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is PlatformAsset) {
return false
}
if (this === other) {
return true
}
val other = other as PlatformAsset
return MessagesPigeonUtils.deepEquals(this.id, other.id) && MessagesPigeonUtils.deepEquals(this.name, other.name) && MessagesPigeonUtils.deepEquals(this.type, other.type) && MessagesPigeonUtils.deepEquals(this.createdAt, other.createdAt) && MessagesPigeonUtils.deepEquals(this.updatedAt, other.updatedAt) && MessagesPigeonUtils.deepEquals(this.width, other.width) && MessagesPigeonUtils.deepEquals(this.height, other.height) && MessagesPigeonUtils.deepEquals(this.durationMs, other.durationMs) && MessagesPigeonUtils.deepEquals(this.orientation, other.orientation) && MessagesPigeonUtils.deepEquals(this.isFavorite, other.isFavorite) && MessagesPigeonUtils.deepEquals(this.adjustmentTime, other.adjustmentTime) && MessagesPigeonUtils.deepEquals(this.latitude, other.latitude) && MessagesPigeonUtils.deepEquals(this.longitude, other.longitude) && MessagesPigeonUtils.deepEquals(this.playbackStyle, other.playbackStyle)
}
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + MessagesPigeonUtils.deepHash(this.id)
result = 31 * result + MessagesPigeonUtils.deepHash(this.name)
result = 31 * result + MessagesPigeonUtils.deepHash(this.type)
result = 31 * result + MessagesPigeonUtils.deepHash(this.createdAt)
result = 31 * result + MessagesPigeonUtils.deepHash(this.updatedAt)
result = 31 * result + MessagesPigeonUtils.deepHash(this.width)
result = 31 * result + MessagesPigeonUtils.deepHash(this.height)
result = 31 * result + MessagesPigeonUtils.deepHash(this.durationMs)
result = 31 * result + MessagesPigeonUtils.deepHash(this.orientation)
result = 31 * result + MessagesPigeonUtils.deepHash(this.isFavorite)
result = 31 * result + MessagesPigeonUtils.deepHash(this.adjustmentTime)
result = 31 * result + MessagesPigeonUtils.deepHash(this.latitude)
result = 31 * result + MessagesPigeonUtils.deepHash(this.longitude)
result = 31 * result + MessagesPigeonUtils.deepHash(this.playbackStyle)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
@@ -322,25 +189,15 @@ data class PlatformAlbum (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is PlatformAlbum) {
return false
}
if (this === other) {
return true
}
val other = other as PlatformAlbum
return MessagesPigeonUtils.deepEquals(this.id, other.id) && MessagesPigeonUtils.deepEquals(this.name, other.name) && MessagesPigeonUtils.deepEquals(this.updatedAt, other.updatedAt) && MessagesPigeonUtils.deepEquals(this.isCloud, other.isCloud) && MessagesPigeonUtils.deepEquals(this.assetCount, other.assetCount)
}
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + MessagesPigeonUtils.deepHash(this.id)
result = 31 * result + MessagesPigeonUtils.deepHash(this.name)
result = 31 * result + MessagesPigeonUtils.deepHash(this.updatedAt)
result = 31 * result + MessagesPigeonUtils.deepHash(this.isCloud)
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetCount)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
@@ -369,24 +226,15 @@ data class SyncDelta (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is SyncDelta) {
return false
}
if (this === other) {
return true
}
val other = other as SyncDelta
return MessagesPigeonUtils.deepEquals(this.hasChanges, other.hasChanges) && MessagesPigeonUtils.deepEquals(this.updates, other.updates) && MessagesPigeonUtils.deepEquals(this.deletes, other.deletes) && MessagesPigeonUtils.deepEquals(this.assetAlbums, other.assetAlbums)
}
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + MessagesPigeonUtils.deepHash(this.hasChanges)
result = 31 * result + MessagesPigeonUtils.deepHash(this.updates)
result = 31 * result + MessagesPigeonUtils.deepHash(this.deletes)
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetAlbums)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
@@ -412,23 +260,15 @@ data class HashResult (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is HashResult) {
return false
}
if (this === other) {
return true
}
val other = other as HashResult
return MessagesPigeonUtils.deepEquals(this.assetId, other.assetId) && MessagesPigeonUtils.deepEquals(this.error, other.error) && MessagesPigeonUtils.deepEquals(this.hash, other.hash)
}
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetId)
result = 31 * result + MessagesPigeonUtils.deepHash(this.error)
result = 31 * result + MessagesPigeonUtils.deepHash(this.hash)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
@@ -454,23 +294,15 @@ data class CloudIdResult (
)
}
override fun equals(other: Any?): Boolean {
if (other == null || other.javaClass != javaClass) {
if (other !is CloudIdResult) {
return false
}
if (this === other) {
return true
}
val other = other as CloudIdResult
return MessagesPigeonUtils.deepEquals(this.assetId, other.assetId) && MessagesPigeonUtils.deepEquals(this.error, other.error) && MessagesPigeonUtils.deepEquals(this.cloudId, other.cloudId)
}
return MessagesPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + MessagesPigeonUtils.deepHash(this.assetId)
result = 31 * result + MessagesPigeonUtils.deepHash(this.error)
result = 31 * result + MessagesPigeonUtils.deepHash(this.cloudId)
return result
}
override fun hashCode(): Int = toList().hashCode()
}
private open class MessagesPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@@ -512,7 +344,7 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
when (value) {
is PlatformAssetPlaybackStyle -> {
stream.write(129)
writeValue(stream, value.raw.toLong())
writeValue(stream, value.raw)
}
is PlatformAsset -> {
stream.write(130)
@@ -178,7 +178,7 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin() {
val height = c.getInt(heightColumn).toLong()
// Duration is milliseconds
val duration = if (rawMediaType == MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE) 0L
else c.getLong(durationColumn)
else c.getLong(durationColumn) / 1000
val orientation = c.getInt(orientationColumn)
val isFavorite = if (favoriteColumn == -1) false else c.getInt(favoriteColumn) != 0
+1 -1
View File
@@ -46,6 +46,6 @@ material = { module = "com.google.android.material:material", version.ref = "mat
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
# TODO: update to version.ref = "kotlin" when background_downloader is removed
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "2.1.0" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "1.9.22" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
+1 -1
View File
@@ -21,7 +21,7 @@ plugins {
id "com.android.application" version "8.11.2" apply false
id "org.jetbrains.kotlin.android" version "2.2.20" apply false
// TODO: update to match kotlin version when background_downloader is removed
id "org.jetbrains.kotlin.plugin.serialization" version "2.1.0" apply false
id "org.jetbrains.kotlin.plugin.serialization" version "1.9.22" apply false
id "com.google.devtools.ksp" version "2.2.20-2.0.3" apply false
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+64 -20
View File
@@ -20,21 +20,19 @@ PODS:
- Flutter
- flutter_udid (0.0.1):
- Flutter
- KeychainAccess
- flutter_web_auth_2 (5.0.0):
- SAMKeychain
- flutter_web_auth_2 (3.0.0):
- Flutter
- fluttertoast (0.0.2):
- Flutter
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- home_widget (0.0.1):
- Flutter
- image_picker_ios (0.0.1):
- Flutter
- integration_test (0.0.1):
- Flutter
- KeychainAccess (4.2.2)
- local_auth_darwin (0.0.1):
- Flutter
- FlutterMacOS
@@ -46,13 +44,19 @@ PODS:
- Flutter
- network_info_plus (0.0.1):
- Flutter
- objective_c (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- permission_handler_apple (9.3.0):
- Flutter
- photo_manager (3.9.0):
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- photo_manager (3.7.1):
- Flutter
- FlutterMacOS
- SAMKeychain (1.5.3)
- share_handler_ios (0.0.14):
- Flutter
- share_handler_ios/share_handler_ios_models (= 0.0.14)
@@ -66,6 +70,28 @@ PODS:
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- sqlite3 (3.49.2):
- sqlite3/common (= 3.49.2)
- sqlite3/common (3.49.2)
- sqlite3/dbstatvtab (3.49.2):
- sqlite3/common
- sqlite3/fts5 (3.49.2):
- sqlite3/common
- sqlite3/perf-threadsafe (3.49.2):
- sqlite3/common
- sqlite3/rtree (3.49.2):
- sqlite3/common
- sqlite3_flutter_libs (0.0.1):
- Flutter
- FlutterMacOS
- sqlite3 (~> 3.49.1)
- sqlite3/dbstatvtab
- sqlite3/fts5
- sqlite3/perf-threadsafe
- sqlite3/rtree
- url_launcher_ios (0.0.1):
- Flutter
- wakelock_plus (0.0.1):
@@ -84,7 +110,7 @@ DEPENDENCIES:
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
- flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`)
- home_widget (from `.symlinks/plugins/home_widget/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
@@ -92,20 +118,25 @@ DEPENDENCIES:
- maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`)
- native_video_player (from `.symlinks/plugins/native_video_player/ios`)
- network_info_plus (from `.symlinks/plugins/network_info_plus/ios`)
- objective_c (from `.symlinks/plugins/objective_c/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- photo_manager (from `.symlinks/plugins/photo_manager/darwin`)
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
- share_handler_ios (from `.symlinks/plugins/share_handler_ios/ios`)
- share_handler_ios_models (from `.symlinks/plugins/share_handler_ios/ios/Models`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
SPEC REPOS:
trunk:
- KeychainAccess
- MapLibre
- SAMKeychain
- sqlite3
EXTERNAL SOURCES:
background_downloader:
@@ -133,7 +164,7 @@ EXTERNAL SOURCES:
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/darwin"
:path: ".symlinks/plugins/geolocator_apple/ios"
home_widget:
:path: ".symlinks/plugins/home_widget/ios"
image_picker_ios:
@@ -148,12 +179,16 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/native_video_player/ios"
network_info_plus:
:path: ".symlinks/plugins/network_info_plus/ios"
objective_c:
:path: ".symlinks/plugins/objective_c/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
photo_manager:
:path: ".symlinks/plugins/photo_manager/darwin"
:path: ".symlinks/plugins/photo_manager/ios"
share_handler_ios:
:path: ".symlinks/plugins/share_handler_ios/ios"
share_handler_ios_models:
@@ -162,6 +197,10 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
sqlite3_flutter_libs:
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
wakelock_plus:
@@ -177,27 +216,32 @@ SPEC CHECKSUMS:
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
flutter_udid: 92a5d31fe0526b7b6002a2318df702e12e7eb300
flutter_web_auth_2: 646fc9df97a01c59e5eea99b237da2c6360f8439
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
flutter_web_auth_2: 5c8d9dcd7848b5a9efb086d24e7a9adcae979c80
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
geolocator_apple: 1560c3c875af2a412242c7a923e15d0d401966ff
home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
MapLibre: 69e572367f4ef6287e18246cfafc39c80cdcabcd
maplibre_gl: 3c924e44725147b03dda33430ad216005b40555f
native_video_player: b65c58951ede2f93d103a25366bdebca95081265
network_info_plus: cf61925ab5205dce05a4f0895989afdb6aade5fc
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
photo_manager: 25fd77df14f4f0ba5ef99e2c61814dde77e2bceb
photo_manager: 1d80ae07a89a67dfbcae95953a1e5a24af7c3e62
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
share_handler_ios: e2244e990f826b2c8eaa291ac3831569438ba0fb
share_handler_ios_models: fc638c9b4330dc7f082586c92aee9dfa0b87b871
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
sqlite3: 3c950dc86011117c307eb0b28c4a7bb449dce9f1
sqlite3_flutter_libs: f8fc13346870e73fe35ebf6dbb997fbcd156b241
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
PODFILE CHECKSUM: 938abbae4114b9c2140c550a2a0d8f7c674f5dfe
+16 -16
View File
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 77;
objects = {
/* Begin PBXBuildFile section */
@@ -751,7 +751,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@@ -760,7 +760,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.121.0;
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.profile;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile;
PRODUCT_NAME = "Immich-Profile";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -895,7 +895,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@@ -904,7 +904,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.121.0;
PRODUCT_BUNDLE_IDENTIFIER = app.futo.immich.debug;
PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug;
PRODUCT_NAME = "Immich-Debug";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -925,7 +925,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
@@ -958,7 +958,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
@@ -975,7 +975,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 = app.alextran.immich.vdebug.Widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
@@ -1001,7 +1001,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
@@ -1041,7 +1041,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
@@ -1057,7 +1057,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 = app.alextran.immich.profile.Widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -1081,7 +1081,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
@@ -1098,7 +1098,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 = app.alextran.immich.vdebug.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
@@ -1125,7 +1125,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
@@ -1166,7 +1166,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 240;
CUSTOM_GROUP_ID = group.app.immich.share;
DEVELOPMENT_TEAM = 2W7AC6T8T5;
DEVELOPMENT_TEAM = 2F67MQ8R79;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
@@ -1182,7 +1182,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 = app.alextran.immich.profile.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
+8
View File
@@ -1,4 +1,12 @@
import BackgroundTasks
import Flutter
import native_video_player
import network_info_plus
import path_provider_foundation
import permission_handler_apple
import photo_manager
import shared_preferences_foundation
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -32,7 +32,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}
return [
"\(error)",
"\(Swift.type(of: error))",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
@@ -50,19 +50,6 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
return value as! T?
}
private func doubleEqualsBackgroundWorker(_ lhs: Double, _ rhs: Double) -> Bool {
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
}
private func doubleHashBackgroundWorker(_ value: Double, _ hasher: inout Hasher) {
if value.isNaN {
hasher.combine(0x7FF8000000000000)
} else {
// Normalize -0.0 to 0.0
hasher.combine(value == 0 ? 0 : value)
}
}
func deepEqualsBackgroundWorker(_ lhs: Any?, _ rhs: Any?) -> Bool {
let cleanLhs = nilOrValue(lhs) as Any?
let cleanRhs = nilOrValue(rhs) as Any?
@@ -73,92 +60,59 @@ func deepEqualsBackgroundWorker(_ lhs: Any?, _ rhs: Any?) -> Bool {
case (nil, _), (_, nil):
return false
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
return true
case is (Void, Void):
return true
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
guard lhsArray.count == rhsArray.count else { return false }
for (index, element) in lhsArray.enumerated() {
if !deepEqualsBackgroundWorker(element, rhsArray[index]) {
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
return cleanLhsHashable == cleanRhsHashable
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
for (index, element) in cleanLhsArray.enumerated() {
if !deepEqualsBackgroundWorker(element, cleanRhsArray[index]) {
return false
}
}
return true
case (let lhsArray, let rhsArray) as ([Double], [Double]):
guard lhsArray.count == rhsArray.count else { return false }
for (index, element) in lhsArray.enumerated() {
if !doubleEqualsBackgroundWorker(element, rhsArray[index]) {
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
for (key, cleanLhsValue) in cleanLhsDictionary {
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
if !deepEqualsBackgroundWorker(cleanLhsValue, cleanRhsDictionary[key]!) {
return false
}
}
return true
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard lhsDictionary.count == rhsDictionary.count else { return false }
for (lhsKey, lhsValue) in lhsDictionary {
var found = false
for (rhsKey, rhsValue) in rhsDictionary {
if deepEqualsBackgroundWorker(lhsKey, rhsKey) {
if deepEqualsBackgroundWorker(lhsValue, rhsValue) {
found = true
break
} else {
return false
}
}
}
if !found { return false }
}
return true
case (let lhs as Double, let rhs as Double):
return doubleEqualsBackgroundWorker(lhs, rhs)
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
return lhsHashable == rhsHashable
default:
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
return false
}
}
func deepHashBackgroundWorker(value: Any?, hasher: inout Hasher) {
let cleanValue = nilOrValue(value) as Any?
if let cleanValue = cleanValue {
if let doubleValue = cleanValue as? Double {
doubleHashBackgroundWorker(doubleValue, &hasher)
} else if let valueList = cleanValue as? [Any?] {
for item in valueList {
deepHashBackgroundWorker(value: item, hasher: &hasher)
}
} else if let valueList = cleanValue as? [Double] {
for item in valueList {
doubleHashBackgroundWorker(item, &hasher)
}
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
var result = 0
for (key, value) in valueDict {
var entryKeyHasher = Hasher()
deepHashBackgroundWorker(value: key, hasher: &entryKeyHasher)
var entryValueHasher = Hasher()
deepHashBackgroundWorker(value: value, hasher: &entryValueHasher)
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
}
hasher.combine(result)
} else if let hashableValue = cleanValue as? AnyHashable {
hasher.combine(hashableValue)
} else {
hasher.combine(String(describing: cleanValue))
}
} else {
hasher.combine(0)
if let valueList = value as? [AnyHashable] {
for item in valueList { deepHashBackgroundWorker(value: item, hasher: &hasher) }
return
}
if let valueDict = value as? [AnyHashable: AnyHashable] {
for key in valueDict.keys {
hasher.combine(key)
deepHashBackgroundWorker(value: valueDict[key]!, hasher: &hasher)
}
return
}
if let hashableValue = value as? AnyHashable {
hasher.combine(hashableValue.hashValue)
}
return hasher.combine(String(describing: value))
}
/// Generated class from Pigeon that represents data sent in messages.
struct BackgroundWorkerSettings: Hashable {
@@ -183,16 +137,9 @@ struct BackgroundWorkerSettings: Hashable {
]
}
static func == (lhs: BackgroundWorkerSettings, rhs: BackgroundWorkerSettings) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsBackgroundWorker(lhs.requiresCharging, rhs.requiresCharging) && deepEqualsBackgroundWorker(lhs.minimumDelaySeconds, rhs.minimumDelaySeconds)
}
return deepEqualsBackgroundWorker(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("BackgroundWorkerSettings")
deepHashBackgroundWorker(value: requiresCharging, hasher: &hasher)
deepHashBackgroundWorker(value: minimumDelaySeconds, hasher: &hasher)
deepHashBackgroundWorker(value: toList(), hasher: &hasher)
}
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -32,7 +32,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}
return [
"\(error)",
"\(Swift.type(of: error))",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
+37 -99
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -32,7 +32,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}
return [
"\(error)",
"\(Swift.type(of: error))",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
@@ -46,19 +46,6 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
return value as! T?
}
private func doubleEqualsNetwork(_ lhs: Double, _ rhs: Double) -> Bool {
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
}
private func doubleHashNetwork(_ value: Double, _ hasher: inout Hasher) {
if value.isNaN {
hasher.combine(0x7FF8000000000000)
} else {
// Normalize -0.0 to 0.0
hasher.combine(value == 0 ? 0 : value)
}
}
func deepEqualsNetwork(_ lhs: Any?, _ rhs: Any?) -> Bool {
let cleanLhs = nilOrValue(lhs) as Any?
let cleanRhs = nilOrValue(rhs) as Any?
@@ -69,92 +56,59 @@ func deepEqualsNetwork(_ lhs: Any?, _ rhs: Any?) -> Bool {
case (nil, _), (_, nil):
return false
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
return true
case is (Void, Void):
return true
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
guard lhsArray.count == rhsArray.count else { return false }
for (index, element) in lhsArray.enumerated() {
if !deepEqualsNetwork(element, rhsArray[index]) {
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
return cleanLhsHashable == cleanRhsHashable
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
for (index, element) in cleanLhsArray.enumerated() {
if !deepEqualsNetwork(element, cleanRhsArray[index]) {
return false
}
}
return true
case (let lhsArray, let rhsArray) as ([Double], [Double]):
guard lhsArray.count == rhsArray.count else { return false }
for (index, element) in lhsArray.enumerated() {
if !doubleEqualsNetwork(element, rhsArray[index]) {
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
for (key, cleanLhsValue) in cleanLhsDictionary {
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
if !deepEqualsNetwork(cleanLhsValue, cleanRhsDictionary[key]!) {
return false
}
}
return true
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard lhsDictionary.count == rhsDictionary.count else { return false }
for (lhsKey, lhsValue) in lhsDictionary {
var found = false
for (rhsKey, rhsValue) in rhsDictionary {
if deepEqualsNetwork(lhsKey, rhsKey) {
if deepEqualsNetwork(lhsValue, rhsValue) {
found = true
break
} else {
return false
}
}
}
if !found { return false }
}
return true
case (let lhs as Double, let rhs as Double):
return doubleEqualsNetwork(lhs, rhs)
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
return lhsHashable == rhsHashable
default:
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
return false
}
}
func deepHashNetwork(value: Any?, hasher: inout Hasher) {
let cleanValue = nilOrValue(value) as Any?
if let cleanValue = cleanValue {
if let doubleValue = cleanValue as? Double {
doubleHashNetwork(doubleValue, &hasher)
} else if let valueList = cleanValue as? [Any?] {
for item in valueList {
deepHashNetwork(value: item, hasher: &hasher)
}
} else if let valueList = cleanValue as? [Double] {
for item in valueList {
doubleHashNetwork(item, &hasher)
}
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
var result = 0
for (key, value) in valueDict {
var entryKeyHasher = Hasher()
deepHashNetwork(value: key, hasher: &entryKeyHasher)
var entryValueHasher = Hasher()
deepHashNetwork(value: value, hasher: &entryValueHasher)
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
}
hasher.combine(result)
} else if let hashableValue = cleanValue as? AnyHashable {
hasher.combine(hashableValue)
} else {
hasher.combine(String(describing: cleanValue))
}
} else {
hasher.combine(0)
if let valueList = value as? [AnyHashable] {
for item in valueList { deepHashNetwork(value: item, hasher: &hasher) }
return
}
if let valueDict = value as? [AnyHashable: AnyHashable] {
for key in valueDict.keys {
hasher.combine(key)
deepHashNetwork(value: valueDict[key]!, hasher: &hasher)
}
return
}
if let hashableValue = value as? AnyHashable {
hasher.combine(hashableValue.hashValue)
}
return hasher.combine(String(describing: value))
}
/// Generated class from Pigeon that represents data sent in messages.
struct ClientCertData: Hashable {
@@ -179,16 +133,9 @@ struct ClientCertData: Hashable {
]
}
static func == (lhs: ClientCertData, rhs: ClientCertData) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsNetwork(lhs.data, rhs.data) && deepEqualsNetwork(lhs.password, rhs.password)
}
return deepEqualsNetwork(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("ClientCertData")
deepHashNetwork(value: data, hasher: &hasher)
deepHashNetwork(value: password, hasher: &hasher)
deepHashNetwork(value: toList(), hasher: &hasher)
}
}
@@ -223,18 +170,9 @@ struct ClientCertPrompt: Hashable {
]
}
static func == (lhs: ClientCertPrompt, rhs: ClientCertPrompt) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsNetwork(lhs.title, rhs.title) && deepEqualsNetwork(lhs.message, rhs.message) && deepEqualsNetwork(lhs.cancel, rhs.cancel) && deepEqualsNetwork(lhs.confirm, rhs.confirm)
}
return deepEqualsNetwork(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("ClientCertPrompt")
deepHashNetwork(value: title, hasher: &hasher)
deepHashNetwork(value: message, hasher: &hasher)
deepHashNetwork(value: cancel, hasher: &hasher)
deepHashNetwork(value: confirm, hasher: &hasher)
deepHashNetwork(value: toList(), hasher: &hasher)
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -32,7 +32,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}
return [
"\(error)",
"\(Swift.type(of: error))",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -32,7 +32,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}
return [
"\(error)",
"\(Swift.type(of: error))",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
+21 -21
View File
@@ -150,27 +150,6 @@
<array>
<string>INSendMessageIntent</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
@@ -197,6 +176,27 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>io.flutter.embedded_views_preview</key>
+47 -147
View File
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
@@ -50,7 +50,7 @@ private func wrapError(_ error: Any) -> [Any?] {
}
return [
"\(error)",
"\(Swift.type(of: error))",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
@@ -64,19 +64,6 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
return value as! T?
}
private func doubleEqualsMessages(_ lhs: Double, _ rhs: Double) -> Bool {
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
}
private func doubleHashMessages(_ value: Double, _ hasher: inout Hasher) {
if value.isNaN {
hasher.combine(0x7FF8000000000000)
} else {
// Normalize -0.0 to 0.0
hasher.combine(value == 0 ? 0 : value)
}
}
func deepEqualsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool {
let cleanLhs = nilOrValue(lhs) as Any?
let cleanRhs = nilOrValue(rhs) as Any?
@@ -87,92 +74,59 @@ func deepEqualsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool {
case (nil, _), (_, nil):
return false
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
return true
case is (Void, Void):
return true
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
guard lhsArray.count == rhsArray.count else { return false }
for (index, element) in lhsArray.enumerated() {
if !deepEqualsMessages(element, rhsArray[index]) {
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
return cleanLhsHashable == cleanRhsHashable
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
for (index, element) in cleanLhsArray.enumerated() {
if !deepEqualsMessages(element, cleanRhsArray[index]) {
return false
}
}
return true
case (let lhsArray, let rhsArray) as ([Double], [Double]):
guard lhsArray.count == rhsArray.count else { return false }
for (index, element) in lhsArray.enumerated() {
if !doubleEqualsMessages(element, rhsArray[index]) {
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
for (key, cleanLhsValue) in cleanLhsDictionary {
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
if !deepEqualsMessages(cleanLhsValue, cleanRhsDictionary[key]!) {
return false
}
}
return true
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard lhsDictionary.count == rhsDictionary.count else { return false }
for (lhsKey, lhsValue) in lhsDictionary {
var found = false
for (rhsKey, rhsValue) in rhsDictionary {
if deepEqualsMessages(lhsKey, rhsKey) {
if deepEqualsMessages(lhsValue, rhsValue) {
found = true
break
} else {
return false
}
}
}
if !found { return false }
}
return true
case (let lhs as Double, let rhs as Double):
return doubleEqualsMessages(lhs, rhs)
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
return lhsHashable == rhsHashable
default:
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
return false
}
}
func deepHashMessages(value: Any?, hasher: inout Hasher) {
let cleanValue = nilOrValue(value) as Any?
if let cleanValue = cleanValue {
if let doubleValue = cleanValue as? Double {
doubleHashMessages(doubleValue, &hasher)
} else if let valueList = cleanValue as? [Any?] {
for item in valueList {
deepHashMessages(value: item, hasher: &hasher)
}
} else if let valueList = cleanValue as? [Double] {
for item in valueList {
doubleHashMessages(item, &hasher)
}
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
var result = 0
for (key, value) in valueDict {
var entryKeyHasher = Hasher()
deepHashMessages(value: key, hasher: &entryKeyHasher)
var entryValueHasher = Hasher()
deepHashMessages(value: value, hasher: &entryValueHasher)
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
}
hasher.combine(result)
} else if let hashableValue = cleanValue as? AnyHashable {
hasher.combine(hashableValue)
} else {
hasher.combine(String(describing: cleanValue))
}
} else {
hasher.combine(0)
if let valueList = value as? [AnyHashable] {
for item in valueList { deepHashMessages(value: item, hasher: &hasher) }
return
}
if let valueDict = value as? [AnyHashable: AnyHashable] {
for key in valueDict.keys {
hasher.combine(key)
deepHashMessages(value: valueDict[key]!, hasher: &hasher)
}
return
}
if let hashableValue = value as? AnyHashable {
hasher.combine(hashableValue.hashValue)
}
return hasher.combine(String(describing: value))
}
enum PlatformAssetPlaybackStyle: Int {
case unknown = 0
@@ -192,7 +146,7 @@ struct PlatformAsset: Hashable {
var updatedAt: Int64? = nil
var width: Int64? = nil
var height: Int64? = nil
var durationMs: Int64
var durationInSeconds: Int64
var orientation: Int64
var isFavorite: Bool
var adjustmentTime: Int64? = nil
@@ -210,7 +164,7 @@ struct PlatformAsset: Hashable {
let updatedAt: Int64? = nilOrValue(pigeonVar_list[4])
let width: Int64? = nilOrValue(pigeonVar_list[5])
let height: Int64? = nilOrValue(pigeonVar_list[6])
let durationMs = pigeonVar_list[7] as! Int64
let durationInSeconds = pigeonVar_list[7] as! Int64
let orientation = pigeonVar_list[8] as! Int64
let isFavorite = pigeonVar_list[9] as! Bool
let adjustmentTime: Int64? = nilOrValue(pigeonVar_list[10])
@@ -226,7 +180,7 @@ struct PlatformAsset: Hashable {
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
orientation: orientation,
isFavorite: isFavorite,
adjustmentTime: adjustmentTime,
@@ -244,7 +198,7 @@ struct PlatformAsset: Hashable {
updatedAt,
width,
height,
durationMs,
durationInSeconds,
orientation,
isFavorite,
adjustmentTime,
@@ -254,28 +208,9 @@ struct PlatformAsset: Hashable {
]
}
static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsMessages(lhs.id, rhs.id) && deepEqualsMessages(lhs.name, rhs.name) && deepEqualsMessages(lhs.type, rhs.type) && deepEqualsMessages(lhs.createdAt, rhs.createdAt) && deepEqualsMessages(lhs.updatedAt, rhs.updatedAt) && deepEqualsMessages(lhs.width, rhs.width) && deepEqualsMessages(lhs.height, rhs.height) && deepEqualsMessages(lhs.durationMs, rhs.durationMs) && deepEqualsMessages(lhs.orientation, rhs.orientation) && deepEqualsMessages(lhs.isFavorite, rhs.isFavorite) && deepEqualsMessages(lhs.adjustmentTime, rhs.adjustmentTime) && deepEqualsMessages(lhs.latitude, rhs.latitude) && deepEqualsMessages(lhs.longitude, rhs.longitude) && deepEqualsMessages(lhs.playbackStyle, rhs.playbackStyle)
}
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("PlatformAsset")
deepHashMessages(value: id, hasher: &hasher)
deepHashMessages(value: name, hasher: &hasher)
deepHashMessages(value: type, hasher: &hasher)
deepHashMessages(value: createdAt, hasher: &hasher)
deepHashMessages(value: updatedAt, hasher: &hasher)
deepHashMessages(value: width, hasher: &hasher)
deepHashMessages(value: height, hasher: &hasher)
deepHashMessages(value: durationMs, hasher: &hasher)
deepHashMessages(value: orientation, hasher: &hasher)
deepHashMessages(value: isFavorite, hasher: &hasher)
deepHashMessages(value: adjustmentTime, hasher: &hasher)
deepHashMessages(value: latitude, hasher: &hasher)
deepHashMessages(value: longitude, hasher: &hasher)
deepHashMessages(value: playbackStyle, hasher: &hasher)
deepHashMessages(value: toList(), hasher: &hasher)
}
}
@@ -314,19 +249,9 @@ struct PlatformAlbum: Hashable {
]
}
static func == (lhs: PlatformAlbum, rhs: PlatformAlbum) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsMessages(lhs.id, rhs.id) && deepEqualsMessages(lhs.name, rhs.name) && deepEqualsMessages(lhs.updatedAt, rhs.updatedAt) && deepEqualsMessages(lhs.isCloud, rhs.isCloud) && deepEqualsMessages(lhs.assetCount, rhs.assetCount)
}
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("PlatformAlbum")
deepHashMessages(value: id, hasher: &hasher)
deepHashMessages(value: name, hasher: &hasher)
deepHashMessages(value: updatedAt, hasher: &hasher)
deepHashMessages(value: isCloud, hasher: &hasher)
deepHashMessages(value: assetCount, hasher: &hasher)
deepHashMessages(value: toList(), hasher: &hasher)
}
}
@@ -361,18 +286,9 @@ struct SyncDelta: Hashable {
]
}
static func == (lhs: SyncDelta, rhs: SyncDelta) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsMessages(lhs.hasChanges, rhs.hasChanges) && deepEqualsMessages(lhs.updates, rhs.updates) && deepEqualsMessages(lhs.deletes, rhs.deletes) && deepEqualsMessages(lhs.assetAlbums, rhs.assetAlbums)
}
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("SyncDelta")
deepHashMessages(value: hasChanges, hasher: &hasher)
deepHashMessages(value: updates, hasher: &hasher)
deepHashMessages(value: deletes, hasher: &hasher)
deepHashMessages(value: assetAlbums, hasher: &hasher)
deepHashMessages(value: toList(), hasher: &hasher)
}
}
@@ -403,17 +319,9 @@ struct HashResult: Hashable {
]
}
static func == (lhs: HashResult, rhs: HashResult) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsMessages(lhs.assetId, rhs.assetId) && deepEqualsMessages(lhs.error, rhs.error) && deepEqualsMessages(lhs.hash, rhs.hash)
}
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("HashResult")
deepHashMessages(value: assetId, hasher: &hasher)
deepHashMessages(value: error, hasher: &hasher)
deepHashMessages(value: hash, hasher: &hasher)
deepHashMessages(value: toList(), hasher: &hasher)
}
}
@@ -444,17 +352,9 @@ struct CloudIdResult: Hashable {
]
}
static func == (lhs: CloudIdResult, rhs: CloudIdResult) -> Bool {
if Swift.type(of: lhs) != Swift.type(of: rhs) {
return false
}
return deepEqualsMessages(lhs.assetId, rhs.assetId) && deepEqualsMessages(lhs.error, rhs.error) && deepEqualsMessages(lhs.cloudId, rhs.cloudId)
}
return deepEqualsMessages(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
hasher.combine("CloudIdResult")
deepHashMessages(value: assetId, hasher: &hasher)
deepHashMessages(value: error, hasher: &hasher)
deepHashMessages(value: cloudId, hasher: &hasher)
deepHashMessages(value: toList(), hasher: &hasher)
}
}
+1 -1
View File
@@ -171,7 +171,7 @@ class NativeSyncApiImpl: ImmichPlugin, NativeSyncApi, FlutterPlugin {
id: asset.localIdentifier,
name: "",
type: 0,
durationMs: 0,
durationInSeconds: 0,
orientation: 0,
isFavorite: false,
playbackStyle: .unknown
@@ -21,7 +21,7 @@ extension PHAsset {
updatedAt: modificationDate.map { Int64($0.timeIntervalSince1970) },
width: Int64(pixelWidth),
height: Int64(pixelHeight),
durationMs: Int64(duration * 1000),
durationInSeconds: Int64(duration),
orientation: 0,
isFavorite: isFavorite,
adjustmentTime: adjustmentTimestamp,
+26 -26
View File
@@ -1,35 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AppGroupId</key>
<string>$(CUSTOM_GROUP_ID)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
<key>NSExtensionActivationRule</key>
<string>SUBQUERY ( extensionItems, $extensionItem, SUBQUERY ( $extensionItem.attachments,
<dict>
<key>AppGroupId</key>
<string>$(CUSTOM_GROUP_ID)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
<key>NSExtensionActivationRule</key>
<string>SUBQUERY ( extensionItems, $extensionItem, SUBQUERY ( $extensionItem.attachments,
$attachment, ( ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.file-url"
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.image" || ANY
$attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.text" || ANY
$attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.movie" || ANY
$attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.url" ) ).@count &gt; 0
).@count &gt; 0 </string>
<key>PHSupportedMediaTypes</key>
<array>
<string>Video</string>
<string>Image</string>
</array>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>
<key>PHSupportedMediaTypes</key>
<array>
<string>Video</string>
<string>Image</string>
</array>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
</dict>
</plist>
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.app.immich.share</string>
</array>
</dict>
</plist>
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.app.immich.share</string>
</array>
</dict>
</plist>
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.app.immich.share</string>
</array>
</dict>
</plist>
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.app.immich.share</string>
</array>
</dict>
</plist>
@@ -8,7 +8,6 @@ enum AlbumUserRole {
// do not change this order!
editor,
viewer,
owner,
}
// Model for an album stored in the server
@@ -25,7 +25,7 @@ sealed class BaseAsset {
final DateTime updatedAt;
final int? width;
final int? height;
final int? durationMs;
final int? durationInSeconds;
final bool isFavorite;
final String? livePhotoVideoId;
final bool isEdited;
@@ -38,7 +38,7 @@ sealed class BaseAsset {
required this.updatedAt,
this.width,
this.height,
this.durationMs,
this.durationInSeconds,
this.isFavorite = false,
this.livePhotoVideoId,
required this.isEdited,
@@ -53,17 +53,15 @@ sealed class BaseAsset {
AssetPlaybackStyle get playbackStyle {
if (isVideo) return AssetPlaybackStyle.video;
if (isMotionPhoto) return AssetPlaybackStyle.livePhoto;
if (isImage && durationMs != null && durationMs! > 0) {
return AssetPlaybackStyle.imageAnimated;
}
if (isImage && durationInSeconds != null && durationInSeconds! > 0) return AssetPlaybackStyle.imageAnimated;
if (isImage) return AssetPlaybackStyle.image;
return AssetPlaybackStyle.unknown;
}
Duration get duration {
final durationMs = this.durationMs;
if (durationMs != null) {
return Duration(milliseconds: durationMs);
final durationInSeconds = this.durationInSeconds;
if (durationInSeconds != null) {
return Duration(seconds: durationInSeconds);
}
return const Duration();
}
@@ -90,7 +88,7 @@ sealed class BaseAsset {
updatedAt: $updatedAt,
width: ${width ?? "<NA>"},
height: ${height ?? "<NA>"},
durationMs: ${durationMs ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"},
isFavorite: $isFavorite,
isEdited: $isEdited,
}''';
@@ -106,7 +104,7 @@ sealed class BaseAsset {
updatedAt == other.updatedAt &&
width == other.width &&
height == other.height &&
durationMs == other.durationMs &&
durationInSeconds == other.durationInSeconds &&
isFavorite == other.isFavorite &&
isEdited == other.isEdited;
}
@@ -121,7 +119,7 @@ sealed class BaseAsset {
updatedAt.hashCode ^
width.hashCode ^
height.hashCode ^
durationMs.hashCode ^
durationInSeconds.hashCode ^
isFavorite.hashCode ^
isEdited.hashCode;
}
@@ -23,7 +23,7 @@ class LocalAsset extends BaseAsset {
required super.updatedAt,
super.width,
super.height,
super.durationMs,
super.durationInSeconds,
super.isFavorite = false,
super.livePhotoVideoId,
this.orientation = 0,
@@ -58,7 +58,7 @@ class LocalAsset extends BaseAsset {
updatedAt: $updatedAt,
width: ${width ?? "<NA>"},
height: ${height ?? "<NA>"},
durationMs: ${durationMs ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"},
playbackStyle: $playbackStyle,
remoteId: ${remoteId ?? "<NA>"},
cloudId: ${cloudId ?? "<NA>"},
@@ -108,7 +108,7 @@ class LocalAsset extends BaseAsset {
DateTime? updatedAt,
int? width,
int? height,
int? durationMs,
int? durationInSeconds,
bool? isFavorite,
int? orientation,
AssetPlaybackStyle? playbackStyle,
@@ -128,7 +128,7 @@ class LocalAsset extends BaseAsset {
updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationMs: durationMs ?? this.durationMs,
durationInSeconds: durationInSeconds ?? this.durationInSeconds,
isFavorite: isFavorite ?? this.isFavorite,
orientation: orientation ?? this.orientation,
playbackStyle: playbackStyle ?? this.playbackStyle,
@@ -22,7 +22,7 @@ class RemoteAsset extends BaseAsset {
required super.updatedAt,
super.width,
super.height,
super.durationMs,
super.durationInSeconds,
super.isFavorite = false,
this.thumbHash,
this.visibility = AssetVisibility.timeline,
@@ -57,7 +57,7 @@ class RemoteAsset extends BaseAsset {
updatedAt: $updatedAt,
width: ${width ?? "<NA>"},
height: ${height ?? "<NA>"},
durationMs: ${durationMs ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"},
localId: ${localId ?? "<NA>"},
isFavorite: $isFavorite,
thumbHash: ${thumbHash ?? "<NA>"},
@@ -102,7 +102,7 @@ class RemoteAsset extends BaseAsset {
DateTime? updatedAt,
int? width,
int? height,
int? durationMs,
int? durationInSeconds,
bool? isFavorite,
String? thumbHash,
AssetVisibility? visibility,
@@ -121,7 +121,7 @@ class RemoteAsset extends BaseAsset {
updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationMs: durationMs ?? this.durationMs,
durationInSeconds: durationInSeconds ?? this.durationInSeconds,
isFavorite: isFavorite ?? this.isFavorite,
thumbHash: thumbHash ?? this.thumbHash,
visibility: visibility ?? this.visibility,
@@ -146,7 +146,7 @@ class RemoteAssetExif extends RemoteAsset {
required super.updatedAt,
super.width,
super.height,
super.durationMs,
super.durationInSeconds,
super.isFavorite = false,
super.thumbHash,
super.visibility = AssetVisibility.timeline,
@@ -178,7 +178,7 @@ class RemoteAssetExif extends RemoteAsset {
DateTime? updatedAt,
int? width,
int? height,
int? durationMs,
int? durationInSeconds,
bool? isFavorite,
String? thumbHash,
AssetVisibility? visibility,
@@ -198,7 +198,7 @@ class RemoteAssetExif extends RemoteAsset {
updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationMs: durationMs ?? this.durationMs,
durationInSeconds: durationInSeconds ?? this.durationInSeconds,
isFavorite: isFavorite ?? this.isFavorite,
thumbHash: thumbHash ?? this.thumbHash,
visibility: visibility ?? this.visibility,
+1 -1
View File
@@ -29,7 +29,7 @@ class ExifInfo {
bool get hasCoordinates => latitude != null && longitude != null && latitude != 0 && longitude != 0;
String get exposureTime {
if (exposureSeconds == null || exposureSeconds! <= 0 || exposureSeconds!.isNaN) {
if (exposureSeconds == null) {
return "";
}
if (exposureSeconds! < 1) {
@@ -337,7 +337,7 @@ class LocalSyncService {
a.createdAt.isAtSameMomentAs(b.createdAt) &&
a.width == b.width &&
a.height == b.height &&
a.durationMs == b.durationMs;
a.durationInSeconds == b.durationInSeconds;
}
final firstAdjustment = a.adjustmentTime?.millisecondsSinceEpoch ?? 0;
@@ -346,7 +346,7 @@ class LocalSyncService {
a.createdAt.isAtSameMomentAs(b.createdAt) &&
a.width == b.width &&
a.height == b.height &&
a.durationMs == b.durationMs &&
a.durationInSeconds == b.durationInSeconds &&
a.latitude == b.latitude &&
a.longitude == b.longitude;
}
@@ -432,7 +432,7 @@ extension PlatformToLocalAsset on PlatformAsset {
updatedAt: tryFromSecondsSinceEpoch(updatedAt, isUtc: true) ?? DateTime.timestamp(),
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
isFavorite: isFavorite,
orientation: orientation,
playbackStyle: _toPlaybackStyle(playbackStyle),
@@ -7,8 +7,8 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
import 'package:immich_mobile/models/albums/album_search.model.dart';
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
class RemoteAlbumService {
final DriftRemoteAlbumRepository _repository;
@@ -28,6 +28,10 @@ class RemoteAlbumService {
return _repository.get(albumId);
}
Future<RemoteAlbum?> getByName(String albumName, String ownerId) {
return _repository.getByName(albumName, ownerId);
}
Future<List<RemoteAlbum>> sortAlbums(
List<RemoteAlbum> albums,
AlbumSortMode sortMode, {
@@ -82,18 +86,8 @@ class RemoteAlbumService {
return filtered;
}
Future<RemoteAlbum> createAlbum({
required String title,
required UserDto owner,
required List<String> assetIds,
String? description,
}) async {
final album = await _albumApiRepository.createDriftAlbum(
title,
owner,
description: description,
assetIds: assetIds,
);
Future<RemoteAlbum> createAlbum({required String title, required List<String> assetIds, String? description}) async {
final album = await _albumApiRepository.createDriftAlbum(title, description: description, assetIds: assetIds);
await _repository.create(album, assetIds);
return album;
@@ -107,10 +101,8 @@ class RemoteAlbumService {
bool? isActivityEnabled,
AlbumAssetOrder? order,
}) async {
final owner = await _repository.getOwner(albumId);
final updatedAlbum = await _albumApiRepository.updateAlbum(
albumId,
owner,
name: name,
description: description,
thumbnailAssetId: thumbnailAssetId,
@@ -1,11 +1,8 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/services/store.service.dart';
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:logging/logging.dart';
@@ -15,7 +12,6 @@ final syncLinkedAlbumServiceProvider = Provider(
ref.watch(localAlbumRepository),
ref.watch(remoteAlbumRepository),
ref.watch(driftAlbumApiRepositoryProvider),
ref.watch(storeServiceProvider),
),
);
@@ -23,14 +19,8 @@ class SyncLinkedAlbumService {
final DriftLocalAlbumRepository _localAlbumRepository;
final DriftRemoteAlbumRepository _remoteAlbumRepository;
final DriftAlbumApiRepository _albumApiRepository;
final StoreService _storeService;
SyncLinkedAlbumService(
this._localAlbumRepository,
this._remoteAlbumRepository,
this._albumApiRepository,
this._storeService,
);
SyncLinkedAlbumService(this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository);
final _log = Logger("SyncLinkedAlbumService");
@@ -113,11 +103,7 @@ class SyncLinkedAlbumService {
/// Creates a new remote album and links it to the local album
Future<void> _createAndLinkNewRemoteAlbum(LocalAlbum localAlbum) async {
dPrint(() => "Creating new remote album for local album: ${localAlbum.name}");
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(
localAlbum.name,
_storeService.get(StoreKey.currentUser),
assetIds: [],
);
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(localAlbum.name, assetIds: []);
await _remoteAlbumRepository.create(newRemoteAlbum, []);
return _localAlbumRepository.linkRemoteAlbum(localAlbum.id, newRemoteAlbum.id);
}
@@ -225,8 +225,6 @@ class SyncStreamService {
return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'partner backfill');
case SyncEntityType.albumV1:
return _syncStreamRepository.updateAlbumsV1(data.cast());
case SyncEntityType.albumV2:
return _syncStreamRepository.updateAlbumsV2(data.cast());
case SyncEntityType.albumDeleteV1:
return _syncStreamRepository.deleteAlbumsV1(data.cast());
case SyncEntityType.albumUserV1:
+2 -2
View File
@@ -14,7 +14,7 @@ extension DTOToAsset on api.AssetResponseDto {
updatedAt: updatedAt,
ownerId: ownerId,
visibility: visibility.toAssetVisibility(),
durationMs: duration?.toDuration()?.inMilliseconds ?? 0,
durationInSeconds: duration?.toDuration()?.inSeconds ?? 0,
height: height?.toInt(),
width: width?.toInt(),
isFavorite: isFavorite,
@@ -36,7 +36,7 @@ extension DTOToAsset on api.AssetResponseDto {
updatedAt: updatedAt,
ownerId: ownerId,
visibility: visibility.toAssetVisibility(),
durationMs: duration?.toDuration()?.inMilliseconds ?? 0,
durationInSeconds: duration?.toDuration()?.inSeconds ?? 0,
height: height?.toInt(),
width: width?.toInt(),
isFavorite: isFavorite,
+3 -8
View File
@@ -7,16 +7,11 @@ extension StringExtension on String {
}
extension DurationExtension on String {
/// Parses and returns the string of format HH:MM:SS.ffffff as a duration object else null
/// Parses and returns the string of format HH:MM:SS as a duration object else null
Duration? toDuration() {
try {
final parts = split(':');
final hours = double.parse(parts[0]).toInt();
final minutes = double.parse(parts[1]).toInt();
final secondsParts = parts[2].split('.');
final seconds = int.parse(secondsParts[0]);
final milliseconds = secondsParts.length > 1 ? (double.parse('0.${secondsParts[1]}') * 1000).round() : 0;
return Duration(hours: hours, minutes: minutes, seconds: seconds, milliseconds: milliseconds);
final parts = split(':').map((e) => double.parse(e).toInt()).toList(growable: false);
return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]);
} catch (e) {
return null;
}
@@ -39,7 +39,7 @@ extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData {
type: type,
createdAt: createdAt,
updatedAt: updatedAt,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
isFavorite: isFavorite,
height: height,
width: width,
@@ -16,7 +16,7 @@ typedef $$LocalAssetEntityTableCreateCompanionBuilder =
i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationMs,
i0.Value<int?> durationInSeconds,
required String id,
i0.Value<String?> checksum,
i0.Value<bool> isFavorite,
@@ -35,7 +35,7 @@ typedef $$LocalAssetEntityTableUpdateCompanionBuilder =
i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationMs,
i0.Value<int?> durationInSeconds,
i0.Value<String> id,
i0.Value<String?> checksum,
i0.Value<bool> isFavorite,
@@ -87,8 +87,8 @@ class $$LocalAssetEntityTableFilterComposer
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.ColumnFilters<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => i0.ColumnFilters(column),
);
@@ -182,8 +182,8 @@ class $$LocalAssetEntityTableOrderingComposer
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.ColumnOrderings<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => i0.ColumnOrderings(column),
);
@@ -260,8 +260,8 @@ class $$LocalAssetEntityTableAnnotationComposer
i0.GeneratedColumn<int> get height =>
$composableBuilder(column: $table.height, builder: (column) => column);
i0.GeneratedColumn<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.GeneratedColumn<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => column,
);
@@ -348,7 +348,7 @@ class $$LocalAssetEntityTableTableManager
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
i0.Value<String> id = const i0.Value.absent(),
i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<bool> isFavorite = const i0.Value.absent(),
@@ -366,7 +366,7 @@ class $$LocalAssetEntityTableTableManager
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
id: id,
checksum: checksum,
isFavorite: isFavorite,
@@ -385,7 +385,7 @@ class $$LocalAssetEntityTableTableManager
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
required String id,
i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<bool> isFavorite = const i0.Value.absent(),
@@ -403,7 +403,7 @@ class $$LocalAssetEntityTableTableManager
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
id: id,
checksum: checksum,
isFavorite: isFavorite,
@@ -522,17 +522,17 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
static const i0.VerificationMeta _durationMsMeta = const i0.VerificationMeta(
'durationMs',
);
static const i0.VerificationMeta _durationInSecondsMeta =
const i0.VerificationMeta('durationInSeconds');
@override
late final i0.GeneratedColumn<int> durationMs = i0.GeneratedColumn<int>(
'duration_ms',
aliasedName,
true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
late final i0.GeneratedColumn<int> durationInSeconds =
i0.GeneratedColumn<int>(
'duration_in_seconds',
aliasedName,
true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
@@ -645,7 +645,7 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
updatedAt,
width,
height,
durationMs,
durationInSeconds,
id,
checksum,
isFavorite,
@@ -700,10 +700,13 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
height.isAcceptableOrUnknown(data['height']!, _heightMeta),
);
}
if (data.containsKey('duration_ms')) {
if (data.containsKey('duration_in_seconds')) {
context.handle(
_durationMsMeta,
durationMs.isAcceptableOrUnknown(data['duration_ms']!, _durationMsMeta),
_durationInSecondsMeta,
durationInSeconds.isAcceptableOrUnknown(
data['duration_in_seconds']!,
_durationInSecondsMeta,
),
);
}
if (data.containsKey('id')) {
@@ -797,9 +800,9 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
i0.DriftSqlType.int,
data['${effectivePrefix}height'],
),
durationMs: attachedDatabase.typeMapping.read(
durationInSeconds: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}duration_ms'],
data['${effectivePrefix}duration_in_seconds'],
),
id: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
@@ -867,7 +870,7 @@ class LocalAssetEntityData extends i0.DataClass
final DateTime updatedAt;
final int? width;
final int? height;
final int? durationMs;
final int? durationInSeconds;
final String id;
final String? checksum;
final bool isFavorite;
@@ -884,7 +887,7 @@ class LocalAssetEntityData extends i0.DataClass
required this.updatedAt,
this.width,
this.height,
this.durationMs,
this.durationInSeconds,
required this.id,
this.checksum,
required this.isFavorite,
@@ -912,8 +915,8 @@ class LocalAssetEntityData extends i0.DataClass
if (!nullToAbsent || height != null) {
map['height'] = i0.Variable<int>(height);
}
if (!nullToAbsent || durationMs != null) {
map['duration_ms'] = i0.Variable<int>(durationMs);
if (!nullToAbsent || durationInSeconds != null) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds);
}
map['id'] = i0.Variable<String>(id);
if (!nullToAbsent || checksum != null) {
@@ -955,7 +958,7 @@ class LocalAssetEntityData extends i0.DataClass
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
width: serializer.fromJson<int?>(json['width']),
height: serializer.fromJson<int?>(json['height']),
durationMs: serializer.fromJson<int?>(json['durationMs']),
durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']),
id: serializer.fromJson<String>(json['id']),
checksum: serializer.fromJson<String?>(json['checksum']),
isFavorite: serializer.fromJson<bool>(json['isFavorite']),
@@ -981,7 +984,7 @@ class LocalAssetEntityData extends i0.DataClass
'updatedAt': serializer.toJson<DateTime>(updatedAt),
'width': serializer.toJson<int?>(width),
'height': serializer.toJson<int?>(height),
'durationMs': serializer.toJson<int?>(durationMs),
'durationInSeconds': serializer.toJson<int?>(durationInSeconds),
'id': serializer.toJson<String>(id),
'checksum': serializer.toJson<String?>(checksum),
'isFavorite': serializer.toJson<bool>(isFavorite),
@@ -1003,7 +1006,7 @@ class LocalAssetEntityData extends i0.DataClass
DateTime? updatedAt,
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
String? id,
i0.Value<String?> checksum = const i0.Value.absent(),
bool? isFavorite,
@@ -1020,7 +1023,9 @@ class LocalAssetEntityData extends i0.DataClass
updatedAt: updatedAt ?? this.updatedAt,
width: width.present ? width.value : this.width,
height: height.present ? height.value : this.height,
durationMs: durationMs.present ? durationMs.value : this.durationMs,
durationInSeconds: durationInSeconds.present
? durationInSeconds.value
: this.durationInSeconds,
id: id ?? this.id,
checksum: checksum.present ? checksum.value : this.checksum,
isFavorite: isFavorite ?? this.isFavorite,
@@ -1041,9 +1046,9 @@ class LocalAssetEntityData extends i0.DataClass
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
width: data.width.present ? data.width.value : this.width,
height: data.height.present ? data.height.value : this.height,
durationMs: data.durationMs.present
? data.durationMs.value
: this.durationMs,
durationInSeconds: data.durationInSeconds.present
? data.durationInSeconds.value
: this.durationInSeconds,
id: data.id.present ? data.id.value : this.id,
checksum: data.checksum.present ? data.checksum.value : this.checksum,
isFavorite: data.isFavorite.present
@@ -1073,7 +1078,7 @@ class LocalAssetEntityData extends i0.DataClass
..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationMs: $durationMs, ')
..write('durationInSeconds: $durationInSeconds, ')
..write('id: $id, ')
..write('checksum: $checksum, ')
..write('isFavorite: $isFavorite, ')
@@ -1095,7 +1100,7 @@ class LocalAssetEntityData extends i0.DataClass
updatedAt,
width,
height,
durationMs,
durationInSeconds,
id,
checksum,
isFavorite,
@@ -1116,7 +1121,7 @@ class LocalAssetEntityData extends i0.DataClass
other.updatedAt == this.updatedAt &&
other.width == this.width &&
other.height == this.height &&
other.durationMs == this.durationMs &&
other.durationInSeconds == this.durationInSeconds &&
other.id == this.id &&
other.checksum == this.checksum &&
other.isFavorite == this.isFavorite &&
@@ -1136,7 +1141,7 @@ class LocalAssetEntityCompanion
final i0.Value<DateTime> updatedAt;
final i0.Value<int?> width;
final i0.Value<int?> height;
final i0.Value<int?> durationMs;
final i0.Value<int?> durationInSeconds;
final i0.Value<String> id;
final i0.Value<String?> checksum;
final i0.Value<bool> isFavorite;
@@ -1153,7 +1158,7 @@ class LocalAssetEntityCompanion
this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationMs = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(),
this.id = const i0.Value.absent(),
this.checksum = const i0.Value.absent(),
this.isFavorite = const i0.Value.absent(),
@@ -1171,7 +1176,7 @@ class LocalAssetEntityCompanion
this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationMs = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(),
required String id,
this.checksum = const i0.Value.absent(),
this.isFavorite = const i0.Value.absent(),
@@ -1191,7 +1196,7 @@ class LocalAssetEntityCompanion
i0.Expression<DateTime>? updatedAt,
i0.Expression<int>? width,
i0.Expression<int>? height,
i0.Expression<int>? durationMs,
i0.Expression<int>? durationInSeconds,
i0.Expression<String>? id,
i0.Expression<String>? checksum,
i0.Expression<bool>? isFavorite,
@@ -1209,7 +1214,7 @@ class LocalAssetEntityCompanion
if (updatedAt != null) 'updated_at': updatedAt,
if (width != null) 'width': width,
if (height != null) 'height': height,
if (durationMs != null) 'duration_ms': durationMs,
if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds,
if (id != null) 'id': id,
if (checksum != null) 'checksum': checksum,
if (isFavorite != null) 'is_favorite': isFavorite,
@@ -1229,7 +1234,7 @@ class LocalAssetEntityCompanion
i0.Value<DateTime>? updatedAt,
i0.Value<int?>? width,
i0.Value<int?>? height,
i0.Value<int?>? durationMs,
i0.Value<int?>? durationInSeconds,
i0.Value<String>? id,
i0.Value<String?>? checksum,
i0.Value<bool>? isFavorite,
@@ -1247,7 +1252,7 @@ class LocalAssetEntityCompanion
updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationMs: durationMs ?? this.durationMs,
durationInSeconds: durationInSeconds ?? this.durationInSeconds,
id: id ?? this.id,
checksum: checksum ?? this.checksum,
isFavorite: isFavorite ?? this.isFavorite,
@@ -1283,8 +1288,8 @@ class LocalAssetEntityCompanion
if (height.present) {
map['height'] = i0.Variable<int>(height.value);
}
if (durationMs.present) {
map['duration_ms'] = i0.Variable<int>(durationMs.value);
if (durationInSeconds.present) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds.value);
}
if (id.present) {
map['id'] = i0.Variable<String>(id.value);
@@ -1329,7 +1334,7 @@ class LocalAssetEntityCompanion
..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationMs: $durationMs, ')
..write('durationInSeconds: $durationInSeconds, ')
..write('id: $id, ')
..write('checksum: $checksum, ')
..write('isFavorite: $isFavorite, ')
@@ -14,7 +14,7 @@ SELECT
rae.updated_at,
rae.width,
rae.height,
rae.duration_ms,
rae.duration_in_seconds,
rae.is_favorite,
rae.thumb_hash,
rae.checksum,
@@ -52,7 +52,7 @@ SELECT
lae.updated_at,
lae.width,
lae.height,
lae.duration_ms,
lae.duration_in_seconds,
lae.is_favorite,
NULL as thumb_hash,
lae.checksum,
+4 -4
View File
@@ -29,7 +29,7 @@ class MergedAssetDrift extends i1.ModularAccessor {
);
$arrayStartIndex += generatedlimit.amountOfVariables;
return customSelect(
'SELECT rae.id AS remote_id, (SELECT lae.id FROM local_asset_entity AS lae WHERE lae.checksum = rae.checksum LIMIT 1) AS local_id, rae.name, rae.type, rae.created_at AS created_at, rae.updated_at, rae.width, rae.height, rae.duration_ms, rae.is_favorite, rae.thumb_hash, rae.checksum, rae.owner_id, rae.live_photo_video_id, 0 AS orientation, rae.stack_id, NULL AS i_cloud_id, NULL AS latitude, NULL AS longitude, NULL AS adjustmentTime, rae.is_edited, 0 AS playback_style FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT NULL AS remote_id, lae.id AS local_id, lae.name, lae.type, lae.created_at AS created_at, lae.updated_at, lae.width, lae.height, lae.duration_ms, lae.is_favorite, NULL AS thumb_hash, lae.checksum, NULL AS owner_id, NULL AS live_photo_video_id, lae.orientation, NULL AS stack_id, lae.i_cloud_id, lae.latitude, lae.longitude, lae.adjustment_time, 0 AS is_edited, lae.playback_style FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2) ORDER BY created_at DESC ${generatedlimit.sql}',
'SELECT rae.id AS remote_id, (SELECT lae.id FROM local_asset_entity AS lae WHERE lae.checksum = rae.checksum LIMIT 1) AS local_id, rae.name, rae.type, rae.created_at AS created_at, rae.updated_at, rae.width, rae.height, rae.duration_in_seconds, rae.is_favorite, rae.thumb_hash, rae.checksum, rae.owner_id, rae.live_photo_video_id, 0 AS orientation, rae.stack_id, NULL AS i_cloud_id, NULL AS latitude, NULL AS longitude, NULL AS adjustmentTime, rae.is_edited, 0 AS playback_style FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT NULL AS remote_id, lae.id AS local_id, lae.name, lae.type, lae.created_at AS created_at, lae.updated_at, lae.width, lae.height, lae.duration_in_seconds, lae.is_favorite, NULL AS thumb_hash, lae.checksum, NULL AS owner_id, NULL AS live_photo_video_id, lae.orientation, NULL AS stack_id, lae.i_cloud_id, lae.latitude, lae.longitude, lae.adjustment_time, 0 AS is_edited, lae.playback_style FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2) ORDER BY created_at DESC ${generatedlimit.sql}',
variables: [
for (var $ in userIds) i0.Variable<String>($),
...generatedlimit.introducedVariables,
@@ -54,7 +54,7 @@ class MergedAssetDrift extends i1.ModularAccessor {
updatedAt: row.read<DateTime>('updated_at'),
width: row.readNullable<int>('width'),
height: row.readNullable<int>('height'),
durationMs: row.readNullable<int>('duration_ms'),
durationInSeconds: row.readNullable<int>('duration_in_seconds'),
isFavorite: row.read<bool>('is_favorite'),
thumbHash: row.readNullable<String>('thumb_hash'),
checksum: row.readNullable<String>('checksum'),
@@ -127,7 +127,7 @@ class MergedAssetResult {
final DateTime updatedAt;
final int? width;
final int? height;
final int? durationMs;
final int? durationInSeconds;
final bool isFavorite;
final String? thumbHash;
final String? checksum;
@@ -150,7 +150,7 @@ class MergedAssetResult {
required this.updatedAt,
this.width,
this.height,
this.durationMs,
this.durationInSeconds,
required this.isFavorite,
this.thumbHash,
this.checksum,
@@ -1,8 +1,10 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_remote_album_owner_id ON remote_album_entity (owner_id)')
class RemoteAlbumEntity extends Table with DriftDefaultsMixin {
const RemoteAlbumEntity();
@@ -16,6 +18,8 @@ class RemoteAlbumEntity extends Table with DriftDefaultsMixin {
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
TextColumn get ownerId => text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
TextColumn get thumbnailAssetId =>
text().references(RemoteAssetEntity, #id, onDelete: KeyAction.setNull).nullable()();
@@ -7,9 +7,11 @@ import 'package:immich_mobile/domain/models/album/album.model.dart' as i2;
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart'
as i3;
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i5;
import 'package:drift/internal/modular.dart' as i6;
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'
as i7;
typedef $$RemoteAlbumEntityTableCreateCompanionBuilder =
i1.RemoteAlbumEntityCompanion Function({
@@ -18,6 +20,7 @@ typedef $$RemoteAlbumEntityTableCreateCompanionBuilder =
i0.Value<String> description,
i0.Value<DateTime> createdAt,
i0.Value<DateTime> updatedAt,
required String ownerId,
i0.Value<String?> thumbnailAssetId,
i0.Value<bool> isActivityEnabled,
required i2.AlbumAssetOrder order,
@@ -29,6 +32,7 @@ typedef $$RemoteAlbumEntityTableUpdateCompanionBuilder =
i0.Value<String> description,
i0.Value<DateTime> createdAt,
i0.Value<DateTime> updatedAt,
i0.Value<String> ownerId,
i0.Value<String?> thumbnailAssetId,
i0.Value<bool> isActivityEnabled,
i0.Value<i2.AlbumAssetOrder> order,
@@ -47,10 +51,42 @@ final class $$RemoteAlbumEntityTableReferences
super.$_typedResult,
);
static i5.$RemoteAssetEntityTable _thumbnailAssetIdTable(
static i5.$UserEntityTable _ownerIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.createAlias(
i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db)
.resultSet<i1.$RemoteAlbumEntityTable>('remote_album_entity')
.ownerId,
i6.ReadDatabaseContainer(
db,
).resultSet<i5.$UserEntityTable>('user_entity').id,
),
);
i5.$$UserEntityTableProcessedTableManager get ownerId {
final $_column = $_itemColumn<String>('owner_id')!;
final manager = i5
.$$UserEntityTableTableManager(
$_db,
i6.ReadDatabaseContainer(
$_db,
).resultSet<i5.$UserEntityTable>('user_entity'),
)
.filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_ownerIdTable($_db));
if (item == null) return manager;
return i0.ProcessedTableManager(
manager.$state.copyWith(prefetchedData: [item]),
);
}
static i7.$RemoteAssetEntityTable _thumbnailAssetIdTable(
i0.GeneratedDatabase db,
) => i6.ReadDatabaseContainer(db)
.resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity')
.resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity')
.createAlias(
i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db)
@@ -58,19 +94,19 @@ final class $$RemoteAlbumEntityTableReferences
.thumbnailAssetId,
i6.ReadDatabaseContainer(
db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity').id,
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity').id,
),
);
i5.$$RemoteAssetEntityTableProcessedTableManager? get thumbnailAssetId {
i7.$$RemoteAssetEntityTableProcessedTableManager? get thumbnailAssetId {
final $_column = $_itemColumn<String>('thumbnail_asset_id');
if ($_column == null) return null;
final manager = i5
final manager = i7
.$$RemoteAssetEntityTableTableManager(
$_db,
i6.ReadDatabaseContainer(
$_db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
)
.filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_thumbnailAssetIdTable($_db));
@@ -126,24 +162,51 @@ class $$RemoteAlbumEntityTableFilterComposer
builder: (column) => i0.ColumnWithTypeConverterFilters(column),
);
i5.$$RemoteAssetEntityTableFilterComposer get thumbnailAssetId {
final i5.$$RemoteAssetEntityTableFilterComposer composer = $composerBuilder(
i5.$$UserEntityTableFilterComposer get ownerId {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.thumbnailAssetId,
getCurrentColumn: (t) => t.ownerId,
referencedTable: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder:
(
joinBuilder, {
$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer,
}) => i5.$$RemoteAssetEntityTableFilterComposer(
}) => i5.$$UserEntityTableFilterComposer(
$db: $db,
$table: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
),
);
return composer;
}
i7.$$RemoteAssetEntityTableFilterComposer get thumbnailAssetId {
final i7.$$RemoteAssetEntityTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.thumbnailAssetId,
referencedTable: i6.ReadDatabaseContainer(
$db,
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
getReferencedColumn: (t) => t.id,
builder:
(
joinBuilder, {
$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer,
}) => i7.$$RemoteAssetEntityTableFilterComposer(
$db: $db,
$table: i6.ReadDatabaseContainer(
$db,
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
@@ -198,25 +261,52 @@ class $$RemoteAlbumEntityTableOrderingComposer
builder: (column) => i0.ColumnOrderings(column),
);
i5.$$RemoteAssetEntityTableOrderingComposer get thumbnailAssetId {
final i5.$$RemoteAssetEntityTableOrderingComposer composer =
i5.$$UserEntityTableOrderingComposer get ownerId {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.ownerId,
referencedTable: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder:
(
joinBuilder, {
$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer,
}) => i5.$$UserEntityTableOrderingComposer(
$db: $db,
$table: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
),
);
return composer;
}
i7.$$RemoteAssetEntityTableOrderingComposer get thumbnailAssetId {
final i7.$$RemoteAssetEntityTableOrderingComposer composer =
$composerBuilder(
composer: this,
getCurrentColumn: (t) => t.thumbnailAssetId,
referencedTable: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
getReferencedColumn: (t) => t.id,
builder:
(
joinBuilder, {
$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer,
}) => i5.$$RemoteAssetEntityTableOrderingComposer(
}) => i7.$$RemoteAssetEntityTableOrderingComposer(
$db: $db,
$table: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
@@ -261,25 +351,52 @@ class $$RemoteAlbumEntityTableAnnotationComposer
i0.GeneratedColumnWithTypeConverter<i2.AlbumAssetOrder, int> get order =>
$composableBuilder(column: $table.order, builder: (column) => column);
i5.$$RemoteAssetEntityTableAnnotationComposer get thumbnailAssetId {
final i5.$$RemoteAssetEntityTableAnnotationComposer composer =
i5.$$UserEntityTableAnnotationComposer get ownerId {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.ownerId,
referencedTable: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder:
(
joinBuilder, {
$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer,
}) => i5.$$UserEntityTableAnnotationComposer(
$db: $db,
$table: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
$removeJoinBuilderFromRootComposer,
),
);
return composer;
}
i7.$$RemoteAssetEntityTableAnnotationComposer get thumbnailAssetId {
final i7.$$RemoteAssetEntityTableAnnotationComposer composer =
$composerBuilder(
composer: this,
getCurrentColumn: (t) => t.thumbnailAssetId,
referencedTable: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
getReferencedColumn: (t) => t.id,
builder:
(
joinBuilder, {
$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer,
}) => i5.$$RemoteAssetEntityTableAnnotationComposer(
}) => i7.$$RemoteAssetEntityTableAnnotationComposer(
$db: $db,
$table: i6.ReadDatabaseContainer(
$db,
).resultSet<i5.$RemoteAssetEntityTable>('remote_asset_entity'),
).resultSet<i7.$RemoteAssetEntityTable>('remote_asset_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
@@ -303,7 +420,7 @@ class $$RemoteAlbumEntityTableTableManager
$$RemoteAlbumEntityTableUpdateCompanionBuilder,
(i1.RemoteAlbumEntityData, i1.$$RemoteAlbumEntityTableReferences),
i1.RemoteAlbumEntityData,
i0.PrefetchHooks Function({bool thumbnailAssetId})
i0.PrefetchHooks Function({bool ownerId, bool thumbnailAssetId})
> {
$$RemoteAlbumEntityTableTableManager(
i0.GeneratedDatabase db,
@@ -328,6 +445,7 @@ class $$RemoteAlbumEntityTableTableManager
i0.Value<String> description = const i0.Value.absent(),
i0.Value<DateTime> createdAt = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<String> ownerId = const i0.Value.absent(),
i0.Value<String?> thumbnailAssetId = const i0.Value.absent(),
i0.Value<bool> isActivityEnabled = const i0.Value.absent(),
i0.Value<i2.AlbumAssetOrder> order = const i0.Value.absent(),
@@ -337,6 +455,7 @@ class $$RemoteAlbumEntityTableTableManager
description: description,
createdAt: createdAt,
updatedAt: updatedAt,
ownerId: ownerId,
thumbnailAssetId: thumbnailAssetId,
isActivityEnabled: isActivityEnabled,
order: order,
@@ -348,6 +467,7 @@ class $$RemoteAlbumEntityTableTableManager
i0.Value<String> description = const i0.Value.absent(),
i0.Value<DateTime> createdAt = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
required String ownerId,
i0.Value<String?> thumbnailAssetId = const i0.Value.absent(),
i0.Value<bool> isActivityEnabled = const i0.Value.absent(),
required i2.AlbumAssetOrder order,
@@ -357,6 +477,7 @@ class $$RemoteAlbumEntityTableTableManager
description: description,
createdAt: createdAt,
updatedAt: updatedAt,
ownerId: ownerId,
thumbnailAssetId: thumbnailAssetId,
isActivityEnabled: isActivityEnabled,
order: order,
@@ -369,7 +490,7 @@ class $$RemoteAlbumEntityTableTableManager
),
)
.toList(),
prefetchHooksCallback: ({thumbnailAssetId = false}) {
prefetchHooksCallback: ({ownerId = false, thumbnailAssetId = false}) {
return i0.PrefetchHooks(
db: db,
explicitlyWatchedTables: [],
@@ -389,6 +510,21 @@ class $$RemoteAlbumEntityTableTableManager
dynamic
>
>(state) {
if (ownerId) {
state =
state.withJoin(
currentTable: table,
currentColumn: table.ownerId,
referencedTable: i1
.$$RemoteAlbumEntityTableReferences
._ownerIdTable(db),
referencedColumn: i1
.$$RemoteAlbumEntityTableReferences
._ownerIdTable(db)
.id,
)
as T;
}
if (thumbnailAssetId) {
state =
state.withJoin(
@@ -428,8 +564,12 @@ typedef $$RemoteAlbumEntityTableProcessedTableManager =
$$RemoteAlbumEntityTableUpdateCompanionBuilder,
(i1.RemoteAlbumEntityData, i1.$$RemoteAlbumEntityTableReferences),
i1.RemoteAlbumEntityData,
i0.PrefetchHooks Function({bool thumbnailAssetId})
i0.PrefetchHooks Function({bool ownerId, bool thumbnailAssetId})
>;
i0.Index get idxRemoteAlbumOwnerId => i0.Index(
'idx_remote_album_owner_id',
'CREATE INDEX IF NOT EXISTS idx_remote_album_owner_id ON remote_album_entity (owner_id)',
);
class $RemoteAlbumEntityTable extends i3.RemoteAlbumEntity
with i0.TableInfo<$RemoteAlbumEntityTable, i1.RemoteAlbumEntityData> {
@@ -496,6 +636,20 @@ class $RemoteAlbumEntityTable extends i3.RemoteAlbumEntity
requiredDuringInsert: false,
defaultValue: i4.currentDateAndTime,
);
static const i0.VerificationMeta _ownerIdMeta = const i0.VerificationMeta(
'ownerId',
);
@override
late final i0.GeneratedColumn<String> ownerId = i0.GeneratedColumn<String>(
'owner_id',
aliasedName,
false,
type: i0.DriftSqlType.string,
requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE',
),
);
static const i0.VerificationMeta _thumbnailAssetIdMeta =
const i0.VerificationMeta('thumbnailAssetId');
@override
@@ -544,6 +698,7 @@ class $RemoteAlbumEntityTable extends i3.RemoteAlbumEntity
description,
createdAt,
updatedAt,
ownerId,
thumbnailAssetId,
isActivityEnabled,
order,
@@ -594,6 +749,14 @@ class $RemoteAlbumEntityTable extends i3.RemoteAlbumEntity
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta),
);
}
if (data.containsKey('owner_id')) {
context.handle(
_ownerIdMeta,
ownerId.isAcceptableOrUnknown(data['owner_id']!, _ownerIdMeta),
);
} else if (isInserting) {
context.missing(_ownerIdMeta);
}
if (data.containsKey('thumbnail_asset_id')) {
context.handle(
_thumbnailAssetIdMeta,
@@ -644,6 +807,10 @@ class $RemoteAlbumEntityTable extends i3.RemoteAlbumEntity
i0.DriftSqlType.dateTime,
data['${effectivePrefix}updated_at'],
)!,
ownerId: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
data['${effectivePrefix}owner_id'],
)!,
thumbnailAssetId: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
data['${effectivePrefix}thumbnail_asset_id'],
@@ -683,6 +850,7 @@ class RemoteAlbumEntityData extends i0.DataClass
final String description;
final DateTime createdAt;
final DateTime updatedAt;
final String ownerId;
final String? thumbnailAssetId;
final bool isActivityEnabled;
final i2.AlbumAssetOrder order;
@@ -692,6 +860,7 @@ class RemoteAlbumEntityData extends i0.DataClass
required this.description,
required this.createdAt,
required this.updatedAt,
required this.ownerId,
this.thumbnailAssetId,
required this.isActivityEnabled,
required this.order,
@@ -704,6 +873,7 @@ class RemoteAlbumEntityData extends i0.DataClass
map['description'] = i0.Variable<String>(description);
map['created_at'] = i0.Variable<DateTime>(createdAt);
map['updated_at'] = i0.Variable<DateTime>(updatedAt);
map['owner_id'] = i0.Variable<String>(ownerId);
if (!nullToAbsent || thumbnailAssetId != null) {
map['thumbnail_asset_id'] = i0.Variable<String>(thumbnailAssetId);
}
@@ -727,6 +897,7 @@ class RemoteAlbumEntityData extends i0.DataClass
description: serializer.fromJson<String>(json['description']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
ownerId: serializer.fromJson<String>(json['ownerId']),
thumbnailAssetId: serializer.fromJson<String?>(json['thumbnailAssetId']),
isActivityEnabled: serializer.fromJson<bool>(json['isActivityEnabled']),
order: i1.$RemoteAlbumEntityTable.$converterorder.fromJson(
@@ -743,6 +914,7 @@ class RemoteAlbumEntityData extends i0.DataClass
'description': serializer.toJson<String>(description),
'createdAt': serializer.toJson<DateTime>(createdAt),
'updatedAt': serializer.toJson<DateTime>(updatedAt),
'ownerId': serializer.toJson<String>(ownerId),
'thumbnailAssetId': serializer.toJson<String?>(thumbnailAssetId),
'isActivityEnabled': serializer.toJson<bool>(isActivityEnabled),
'order': serializer.toJson<int>(
@@ -757,6 +929,7 @@ class RemoteAlbumEntityData extends i0.DataClass
String? description,
DateTime? createdAt,
DateTime? updatedAt,
String? ownerId,
i0.Value<String?> thumbnailAssetId = const i0.Value.absent(),
bool? isActivityEnabled,
i2.AlbumAssetOrder? order,
@@ -766,6 +939,7 @@ class RemoteAlbumEntityData extends i0.DataClass
description: description ?? this.description,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
ownerId: ownerId ?? this.ownerId,
thumbnailAssetId: thumbnailAssetId.present
? thumbnailAssetId.value
: this.thumbnailAssetId,
@@ -781,6 +955,7 @@ class RemoteAlbumEntityData extends i0.DataClass
: this.description,
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId,
thumbnailAssetId: data.thumbnailAssetId.present
? data.thumbnailAssetId.value
: this.thumbnailAssetId,
@@ -799,6 +974,7 @@ class RemoteAlbumEntityData extends i0.DataClass
..write('description: $description, ')
..write('createdAt: $createdAt, ')
..write('updatedAt: $updatedAt, ')
..write('ownerId: $ownerId, ')
..write('thumbnailAssetId: $thumbnailAssetId, ')
..write('isActivityEnabled: $isActivityEnabled, ')
..write('order: $order')
@@ -813,6 +989,7 @@ class RemoteAlbumEntityData extends i0.DataClass
description,
createdAt,
updatedAt,
ownerId,
thumbnailAssetId,
isActivityEnabled,
order,
@@ -826,6 +1003,7 @@ class RemoteAlbumEntityData extends i0.DataClass
other.description == this.description &&
other.createdAt == this.createdAt &&
other.updatedAt == this.updatedAt &&
other.ownerId == this.ownerId &&
other.thumbnailAssetId == this.thumbnailAssetId &&
other.isActivityEnabled == this.isActivityEnabled &&
other.order == this.order);
@@ -838,6 +1016,7 @@ class RemoteAlbumEntityCompanion
final i0.Value<String> description;
final i0.Value<DateTime> createdAt;
final i0.Value<DateTime> updatedAt;
final i0.Value<String> ownerId;
final i0.Value<String?> thumbnailAssetId;
final i0.Value<bool> isActivityEnabled;
final i0.Value<i2.AlbumAssetOrder> order;
@@ -847,6 +1026,7 @@ class RemoteAlbumEntityCompanion
this.description = const i0.Value.absent(),
this.createdAt = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(),
this.ownerId = const i0.Value.absent(),
this.thumbnailAssetId = const i0.Value.absent(),
this.isActivityEnabled = const i0.Value.absent(),
this.order = const i0.Value.absent(),
@@ -857,11 +1037,13 @@ class RemoteAlbumEntityCompanion
this.description = const i0.Value.absent(),
this.createdAt = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(),
required String ownerId,
this.thumbnailAssetId = const i0.Value.absent(),
this.isActivityEnabled = const i0.Value.absent(),
required i2.AlbumAssetOrder order,
}) : id = i0.Value(id),
name = i0.Value(name),
ownerId = i0.Value(ownerId),
order = i0.Value(order);
static i0.Insertable<i1.RemoteAlbumEntityData> custom({
i0.Expression<String>? id,
@@ -869,6 +1051,7 @@ class RemoteAlbumEntityCompanion
i0.Expression<String>? description,
i0.Expression<DateTime>? createdAt,
i0.Expression<DateTime>? updatedAt,
i0.Expression<String>? ownerId,
i0.Expression<String>? thumbnailAssetId,
i0.Expression<bool>? isActivityEnabled,
i0.Expression<int>? order,
@@ -879,6 +1062,7 @@ class RemoteAlbumEntityCompanion
if (description != null) 'description': description,
if (createdAt != null) 'created_at': createdAt,
if (updatedAt != null) 'updated_at': updatedAt,
if (ownerId != null) 'owner_id': ownerId,
if (thumbnailAssetId != null) 'thumbnail_asset_id': thumbnailAssetId,
if (isActivityEnabled != null) 'is_activity_enabled': isActivityEnabled,
if (order != null) 'order': order,
@@ -891,6 +1075,7 @@ class RemoteAlbumEntityCompanion
i0.Value<String>? description,
i0.Value<DateTime>? createdAt,
i0.Value<DateTime>? updatedAt,
i0.Value<String>? ownerId,
i0.Value<String?>? thumbnailAssetId,
i0.Value<bool>? isActivityEnabled,
i0.Value<i2.AlbumAssetOrder>? order,
@@ -901,6 +1086,7 @@ class RemoteAlbumEntityCompanion
description: description ?? this.description,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
ownerId: ownerId ?? this.ownerId,
thumbnailAssetId: thumbnailAssetId ?? this.thumbnailAssetId,
isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled,
order: order ?? this.order,
@@ -925,6 +1111,9 @@ class RemoteAlbumEntityCompanion
if (updatedAt.present) {
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
}
if (ownerId.present) {
map['owner_id'] = i0.Variable<String>(ownerId.value);
}
if (thumbnailAssetId.present) {
map['thumbnail_asset_id'] = i0.Variable<String>(thumbnailAssetId.value);
}
@@ -947,6 +1136,7 @@ class RemoteAlbumEntityCompanion
..write('description: $description, ')
..write('createdAt: $createdAt, ')
..write('updatedAt: $updatedAt, ')
..write('ownerId: $ownerId, ')
..write('thumbnailAssetId: $thumbnailAssetId, ')
..write('isActivityEnabled: $isActivityEnabled, ')
..write('order: $order')
@@ -66,7 +66,7 @@ extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData {
type: type,
createdAt: createdAt,
updatedAt: updatedAt,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
isFavorite: isFavorite,
height: height,
width: width,
@@ -19,7 +19,7 @@ typedef $$RemoteAssetEntityTableCreateCompanionBuilder =
i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationMs,
i0.Value<int?> durationInSeconds,
required String id,
required String checksum,
i0.Value<bool> isFavorite,
@@ -41,7 +41,7 @@ typedef $$RemoteAssetEntityTableUpdateCompanionBuilder =
i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationMs,
i0.Value<int?> durationInSeconds,
i0.Value<String> id,
i0.Value<String> checksum,
i0.Value<bool> isFavorite,
@@ -142,8 +142,8 @@ class $$RemoteAssetEntityTableFilterComposer
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.ColumnFilters<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => i0.ColumnFilters(column),
);
@@ -270,8 +270,8 @@ class $$RemoteAssetEntityTableOrderingComposer
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.ColumnOrderings<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => i0.ColumnOrderings(column),
);
@@ -385,8 +385,8 @@ class $$RemoteAssetEntityTableAnnotationComposer
i0.GeneratedColumn<int> get height =>
$composableBuilder(column: $table.height, builder: (column) => column);
i0.GeneratedColumn<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.GeneratedColumn<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => column,
);
@@ -499,7 +499,7 @@ class $$RemoteAssetEntityTableTableManager
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
i0.Value<String> id = const i0.Value.absent(),
i0.Value<String> checksum = const i0.Value.absent(),
i0.Value<bool> isFavorite = const i0.Value.absent(),
@@ -520,7 +520,7 @@ class $$RemoteAssetEntityTableTableManager
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
id: id,
checksum: checksum,
isFavorite: isFavorite,
@@ -542,7 +542,7 @@ class $$RemoteAssetEntityTableTableManager
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
required String id,
required String checksum,
i0.Value<bool> isFavorite = const i0.Value.absent(),
@@ -562,7 +562,7 @@ class $$RemoteAssetEntityTableTableManager
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
id: id,
checksum: checksum,
isFavorite: isFavorite,
@@ -724,17 +724,17 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
static const i0.VerificationMeta _durationMsMeta = const i0.VerificationMeta(
'durationMs',
);
static const i0.VerificationMeta _durationInSecondsMeta =
const i0.VerificationMeta('durationInSeconds');
@override
late final i0.GeneratedColumn<int> durationMs = i0.GeneratedColumn<int>(
'duration_ms',
aliasedName,
true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
late final i0.GeneratedColumn<int> durationInSeconds =
i0.GeneratedColumn<int>(
'duration_in_seconds',
aliasedName,
true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
@@ -886,7 +886,7 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
updatedAt,
width,
height,
durationMs,
durationInSeconds,
id,
checksum,
isFavorite,
@@ -944,10 +944,13 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
height.isAcceptableOrUnknown(data['height']!, _heightMeta),
);
}
if (data.containsKey('duration_ms')) {
if (data.containsKey('duration_in_seconds')) {
context.handle(
_durationMsMeta,
durationMs.isAcceptableOrUnknown(data['duration_ms']!, _durationMsMeta),
_durationInSecondsMeta,
durationInSeconds.isAcceptableOrUnknown(
data['duration_in_seconds']!,
_durationInSecondsMeta,
),
);
}
if (data.containsKey('id')) {
@@ -1063,9 +1066,9 @@ class $RemoteAssetEntityTable extends i3.RemoteAssetEntity
i0.DriftSqlType.int,
data['${effectivePrefix}height'],
),
durationMs: attachedDatabase.typeMapping.read(
durationInSeconds: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}duration_ms'],
data['${effectivePrefix}duration_in_seconds'],
),
id: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
@@ -1145,7 +1148,7 @@ class RemoteAssetEntityData extends i0.DataClass
final DateTime updatedAt;
final int? width;
final int? height;
final int? durationMs;
final int? durationInSeconds;
final String id;
final String checksum;
final bool isFavorite;
@@ -1165,7 +1168,7 @@ class RemoteAssetEntityData extends i0.DataClass
required this.updatedAt,
this.width,
this.height,
this.durationMs,
this.durationInSeconds,
required this.id,
required this.checksum,
required this.isFavorite,
@@ -1196,8 +1199,8 @@ class RemoteAssetEntityData extends i0.DataClass
if (!nullToAbsent || height != null) {
map['height'] = i0.Variable<int>(height);
}
if (!nullToAbsent || durationMs != null) {
map['duration_ms'] = i0.Variable<int>(durationMs);
if (!nullToAbsent || durationInSeconds != null) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds);
}
map['id'] = i0.Variable<String>(id);
map['checksum'] = i0.Variable<String>(checksum);
@@ -1244,7 +1247,7 @@ class RemoteAssetEntityData extends i0.DataClass
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
width: serializer.fromJson<int?>(json['width']),
height: serializer.fromJson<int?>(json['height']),
durationMs: serializer.fromJson<int?>(json['durationMs']),
durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']),
id: serializer.fromJson<String>(json['id']),
checksum: serializer.fromJson<String>(json['checksum']),
isFavorite: serializer.fromJson<bool>(json['isFavorite']),
@@ -1273,7 +1276,7 @@ class RemoteAssetEntityData extends i0.DataClass
'updatedAt': serializer.toJson<DateTime>(updatedAt),
'width': serializer.toJson<int?>(width),
'height': serializer.toJson<int?>(height),
'durationMs': serializer.toJson<int?>(durationMs),
'durationInSeconds': serializer.toJson<int?>(durationInSeconds),
'id': serializer.toJson<String>(id),
'checksum': serializer.toJson<String>(checksum),
'isFavorite': serializer.toJson<bool>(isFavorite),
@@ -1298,7 +1301,7 @@ class RemoteAssetEntityData extends i0.DataClass
DateTime? updatedAt,
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
String? id,
String? checksum,
bool? isFavorite,
@@ -1318,7 +1321,9 @@ class RemoteAssetEntityData extends i0.DataClass
updatedAt: updatedAt ?? this.updatedAt,
width: width.present ? width.value : this.width,
height: height.present ? height.value : this.height,
durationMs: durationMs.present ? durationMs.value : this.durationMs,
durationInSeconds: durationInSeconds.present
? durationInSeconds.value
: this.durationInSeconds,
id: id ?? this.id,
checksum: checksum ?? this.checksum,
isFavorite: isFavorite ?? this.isFavorite,
@@ -1344,9 +1349,9 @@ class RemoteAssetEntityData extends i0.DataClass
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
width: data.width.present ? data.width.value : this.width,
height: data.height.present ? data.height.value : this.height,
durationMs: data.durationMs.present
? data.durationMs.value
: this.durationMs,
durationInSeconds: data.durationInSeconds.present
? data.durationInSeconds.value
: this.durationInSeconds,
id: data.id.present ? data.id.value : this.id,
checksum: data.checksum.present ? data.checksum.value : this.checksum,
isFavorite: data.isFavorite.present
@@ -1379,7 +1384,7 @@ class RemoteAssetEntityData extends i0.DataClass
..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationMs: $durationMs, ')
..write('durationInSeconds: $durationInSeconds, ')
..write('id: $id, ')
..write('checksum: $checksum, ')
..write('isFavorite: $isFavorite, ')
@@ -1404,7 +1409,7 @@ class RemoteAssetEntityData extends i0.DataClass
updatedAt,
width,
height,
durationMs,
durationInSeconds,
id,
checksum,
isFavorite,
@@ -1428,7 +1433,7 @@ class RemoteAssetEntityData extends i0.DataClass
other.updatedAt == this.updatedAt &&
other.width == this.width &&
other.height == this.height &&
other.durationMs == this.durationMs &&
other.durationInSeconds == this.durationInSeconds &&
other.id == this.id &&
other.checksum == this.checksum &&
other.isFavorite == this.isFavorite &&
@@ -1451,7 +1456,7 @@ class RemoteAssetEntityCompanion
final i0.Value<DateTime> updatedAt;
final i0.Value<int?> width;
final i0.Value<int?> height;
final i0.Value<int?> durationMs;
final i0.Value<int?> durationInSeconds;
final i0.Value<String> id;
final i0.Value<String> checksum;
final i0.Value<bool> isFavorite;
@@ -1471,7 +1476,7 @@ class RemoteAssetEntityCompanion
this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationMs = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(),
this.id = const i0.Value.absent(),
this.checksum = const i0.Value.absent(),
this.isFavorite = const i0.Value.absent(),
@@ -1492,7 +1497,7 @@ class RemoteAssetEntityCompanion
this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationMs = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(),
required String id,
required String checksum,
this.isFavorite = const i0.Value.absent(),
@@ -1518,7 +1523,7 @@ class RemoteAssetEntityCompanion
i0.Expression<DateTime>? updatedAt,
i0.Expression<int>? width,
i0.Expression<int>? height,
i0.Expression<int>? durationMs,
i0.Expression<int>? durationInSeconds,
i0.Expression<String>? id,
i0.Expression<String>? checksum,
i0.Expression<bool>? isFavorite,
@@ -1539,7 +1544,7 @@ class RemoteAssetEntityCompanion
if (updatedAt != null) 'updated_at': updatedAt,
if (width != null) 'width': width,
if (height != null) 'height': height,
if (durationMs != null) 'duration_ms': durationMs,
if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds,
if (id != null) 'id': id,
if (checksum != null) 'checksum': checksum,
if (isFavorite != null) 'is_favorite': isFavorite,
@@ -1562,7 +1567,7 @@ class RemoteAssetEntityCompanion
i0.Value<DateTime>? updatedAt,
i0.Value<int?>? width,
i0.Value<int?>? height,
i0.Value<int?>? durationMs,
i0.Value<int?>? durationInSeconds,
i0.Value<String>? id,
i0.Value<String>? checksum,
i0.Value<bool>? isFavorite,
@@ -1583,7 +1588,7 @@ class RemoteAssetEntityCompanion
updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationMs: durationMs ?? this.durationMs,
durationInSeconds: durationInSeconds ?? this.durationInSeconds,
id: id ?? this.id,
checksum: checksum ?? this.checksum,
isFavorite: isFavorite ?? this.isFavorite,
@@ -1622,8 +1627,8 @@ class RemoteAssetEntityCompanion
if (height.present) {
map['height'] = i0.Variable<int>(height.value);
}
if (durationMs.present) {
map['duration_ms'] = i0.Variable<int>(durationMs.value);
if (durationInSeconds.present) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds.value);
}
if (id.present) {
map['id'] = i0.Variable<String>(id.value);
@@ -1675,7 +1680,7 @@ class RemoteAssetEntityCompanion
..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationMs: $durationMs, ')
..write('durationInSeconds: $durationInSeconds, ')
..write('id: $id, ')
..write('checksum: $checksum, ')
..write('isFavorite: $isFavorite, ')
@@ -42,7 +42,7 @@ extension TrashedLocalAssetEntityDataDomainExtension on TrashedLocalAssetEntityD
type: type,
createdAt: createdAt,
updatedAt: updatedAt,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
isFavorite: isFavorite,
height: height,
width: width,
@@ -16,7 +16,7 @@ typedef $$TrashedLocalAssetEntityTableCreateCompanionBuilder =
i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationMs,
i0.Value<int?> durationInSeconds,
required String id,
required String albumId,
i0.Value<String?> checksum,
@@ -33,7 +33,7 @@ typedef $$TrashedLocalAssetEntityTableUpdateCompanionBuilder =
i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationMs,
i0.Value<int?> durationInSeconds,
i0.Value<String> id,
i0.Value<String> albumId,
i0.Value<String?> checksum,
@@ -84,8 +84,8 @@ class $$TrashedLocalAssetEntityTableFilterComposer
builder: (column) => i0.ColumnFilters(column),
);
i0.ColumnFilters<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.ColumnFilters<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => i0.ColumnFilters(column),
);
@@ -171,8 +171,8 @@ class $$TrashedLocalAssetEntityTableOrderingComposer
builder: (column) => i0.ColumnOrderings(column),
);
i0.ColumnOrderings<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.ColumnOrderings<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => i0.ColumnOrderings(column),
);
@@ -240,8 +240,8 @@ class $$TrashedLocalAssetEntityTableAnnotationComposer
i0.GeneratedColumn<int> get height =>
$composableBuilder(column: $table.height, builder: (column) => column);
i0.GeneratedColumn<int> get durationMs => $composableBuilder(
column: $table.durationMs,
i0.GeneratedColumn<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds,
builder: (column) => column,
);
@@ -326,7 +326,7 @@ class $$TrashedLocalAssetEntityTableTableManager
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
i0.Value<String> id = const i0.Value.absent(),
i0.Value<String> albumId = const i0.Value.absent(),
i0.Value<String?> checksum = const i0.Value.absent(),
@@ -342,7 +342,7 @@ class $$TrashedLocalAssetEntityTableTableManager
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
id: id,
albumId: albumId,
checksum: checksum,
@@ -359,7 +359,7 @@ class $$TrashedLocalAssetEntityTableTableManager
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
required String id,
required String albumId,
i0.Value<String?> checksum = const i0.Value.absent(),
@@ -375,7 +375,7 @@ class $$TrashedLocalAssetEntityTableTableManager
updatedAt: updatedAt,
width: width,
height: height,
durationMs: durationMs,
durationInSeconds: durationInSeconds,
id: id,
albumId: albumId,
checksum: checksum,
@@ -498,17 +498,17 @@ class $TrashedLocalAssetEntityTable extends i3.TrashedLocalAssetEntity
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
static const i0.VerificationMeta _durationMsMeta = const i0.VerificationMeta(
'durationMs',
);
static const i0.VerificationMeta _durationInSecondsMeta =
const i0.VerificationMeta('durationInSeconds');
@override
late final i0.GeneratedColumn<int> durationMs = i0.GeneratedColumn<int>(
'duration_ms',
aliasedName,
true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
late final i0.GeneratedColumn<int> durationInSeconds =
i0.GeneratedColumn<int>(
'duration_in_seconds',
aliasedName,
true,
type: i0.DriftSqlType.int,
requiredDuringInsert: false,
);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override
late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
@@ -599,7 +599,7 @@ class $TrashedLocalAssetEntityTable extends i3.TrashedLocalAssetEntity
updatedAt,
width,
height,
durationMs,
durationInSeconds,
id,
albumId,
checksum,
@@ -652,10 +652,13 @@ class $TrashedLocalAssetEntityTable extends i3.TrashedLocalAssetEntity
height.isAcceptableOrUnknown(data['height']!, _heightMeta),
);
}
if (data.containsKey('duration_ms')) {
if (data.containsKey('duration_in_seconds')) {
context.handle(
_durationMsMeta,
durationMs.isAcceptableOrUnknown(data['duration_ms']!, _durationMsMeta),
_durationInSecondsMeta,
durationInSeconds.isAcceptableOrUnknown(
data['duration_in_seconds']!,
_durationInSecondsMeta,
),
);
}
if (data.containsKey('id')) {
@@ -730,9 +733,9 @@ class $TrashedLocalAssetEntityTable extends i3.TrashedLocalAssetEntity
i0.DriftSqlType.int,
data['${effectivePrefix}height'],
),
durationMs: attachedDatabase.typeMapping.read(
durationInSeconds: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int,
data['${effectivePrefix}duration_ms'],
data['${effectivePrefix}duration_in_seconds'],
),
id: attachedDatabase.typeMapping.read(
i0.DriftSqlType.string,
@@ -797,7 +800,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
final DateTime updatedAt;
final int? width;
final int? height;
final int? durationMs;
final int? durationInSeconds;
final String id;
final String albumId;
final String? checksum;
@@ -812,7 +815,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
required this.updatedAt,
this.width,
this.height,
this.durationMs,
this.durationInSeconds,
required this.id,
required this.albumId,
this.checksum,
@@ -838,8 +841,8 @@ class TrashedLocalAssetEntityData extends i0.DataClass
if (!nullToAbsent || height != null) {
map['height'] = i0.Variable<int>(height);
}
if (!nullToAbsent || durationMs != null) {
map['duration_ms'] = i0.Variable<int>(durationMs);
if (!nullToAbsent || durationInSeconds != null) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds);
}
map['id'] = i0.Variable<String>(id);
map['album_id'] = i0.Variable<String>(albumId);
@@ -877,7 +880,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
width: serializer.fromJson<int?>(json['width']),
height: serializer.fromJson<int?>(json['height']),
durationMs: serializer.fromJson<int?>(json['durationMs']),
durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']),
id: serializer.fromJson<String>(json['id']),
albumId: serializer.fromJson<String>(json['albumId']),
checksum: serializer.fromJson<String?>(json['checksum']),
@@ -902,7 +905,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
'updatedAt': serializer.toJson<DateTime>(updatedAt),
'width': serializer.toJson<int?>(width),
'height': serializer.toJson<int?>(height),
'durationMs': serializer.toJson<int?>(durationMs),
'durationInSeconds': serializer.toJson<int?>(durationInSeconds),
'id': serializer.toJson<String>(id),
'albumId': serializer.toJson<String>(albumId),
'checksum': serializer.toJson<String?>(checksum),
@@ -926,7 +929,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
DateTime? updatedAt,
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationMs = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(),
String? id,
String? albumId,
i0.Value<String?> checksum = const i0.Value.absent(),
@@ -941,7 +944,9 @@ class TrashedLocalAssetEntityData extends i0.DataClass
updatedAt: updatedAt ?? this.updatedAt,
width: width.present ? width.value : this.width,
height: height.present ? height.value : this.height,
durationMs: durationMs.present ? durationMs.value : this.durationMs,
durationInSeconds: durationInSeconds.present
? durationInSeconds.value
: this.durationInSeconds,
id: id ?? this.id,
albumId: albumId ?? this.albumId,
checksum: checksum.present ? checksum.value : this.checksum,
@@ -960,9 +965,9 @@ class TrashedLocalAssetEntityData extends i0.DataClass
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
width: data.width.present ? data.width.value : this.width,
height: data.height.present ? data.height.value : this.height,
durationMs: data.durationMs.present
? data.durationMs.value
: this.durationMs,
durationInSeconds: data.durationInSeconds.present
? data.durationInSeconds.value
: this.durationInSeconds,
id: data.id.present ? data.id.value : this.id,
albumId: data.albumId.present ? data.albumId.value : this.albumId,
checksum: data.checksum.present ? data.checksum.value : this.checksum,
@@ -988,7 +993,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationMs: $durationMs, ')
..write('durationInSeconds: $durationInSeconds, ')
..write('id: $id, ')
..write('albumId: $albumId, ')
..write('checksum: $checksum, ')
@@ -1008,7 +1013,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
updatedAt,
width,
height,
durationMs,
durationInSeconds,
id,
albumId,
checksum,
@@ -1027,7 +1032,7 @@ class TrashedLocalAssetEntityData extends i0.DataClass
other.updatedAt == this.updatedAt &&
other.width == this.width &&
other.height == this.height &&
other.durationMs == this.durationMs &&
other.durationInSeconds == this.durationInSeconds &&
other.id == this.id &&
other.albumId == this.albumId &&
other.checksum == this.checksum &&
@@ -1045,7 +1050,7 @@ class TrashedLocalAssetEntityCompanion
final i0.Value<DateTime> updatedAt;
final i0.Value<int?> width;
final i0.Value<int?> height;
final i0.Value<int?> durationMs;
final i0.Value<int?> durationInSeconds;
final i0.Value<String> id;
final i0.Value<String> albumId;
final i0.Value<String?> checksum;
@@ -1060,7 +1065,7 @@ class TrashedLocalAssetEntityCompanion
this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationMs = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(),
this.id = const i0.Value.absent(),
this.albumId = const i0.Value.absent(),
this.checksum = const i0.Value.absent(),
@@ -1076,7 +1081,7 @@ class TrashedLocalAssetEntityCompanion
this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationMs = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(),
required String id,
required String albumId,
this.checksum = const i0.Value.absent(),
@@ -1096,7 +1101,7 @@ class TrashedLocalAssetEntityCompanion
i0.Expression<DateTime>? updatedAt,
i0.Expression<int>? width,
i0.Expression<int>? height,
i0.Expression<int>? durationMs,
i0.Expression<int>? durationInSeconds,
i0.Expression<String>? id,
i0.Expression<String>? albumId,
i0.Expression<String>? checksum,
@@ -1112,7 +1117,7 @@ class TrashedLocalAssetEntityCompanion
if (updatedAt != null) 'updated_at': updatedAt,
if (width != null) 'width': width,
if (height != null) 'height': height,
if (durationMs != null) 'duration_ms': durationMs,
if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds,
if (id != null) 'id': id,
if (albumId != null) 'album_id': albumId,
if (checksum != null) 'checksum': checksum,
@@ -1130,7 +1135,7 @@ class TrashedLocalAssetEntityCompanion
i0.Value<DateTime>? updatedAt,
i0.Value<int?>? width,
i0.Value<int?>? height,
i0.Value<int?>? durationMs,
i0.Value<int?>? durationInSeconds,
i0.Value<String>? id,
i0.Value<String>? albumId,
i0.Value<String?>? checksum,
@@ -1146,7 +1151,7 @@ class TrashedLocalAssetEntityCompanion
updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationMs: durationMs ?? this.durationMs,
durationInSeconds: durationInSeconds ?? this.durationInSeconds,
id: id ?? this.id,
albumId: albumId ?? this.albumId,
checksum: checksum ?? this.checksum,
@@ -1180,8 +1185,8 @@ class TrashedLocalAssetEntityCompanion
if (height.present) {
map['height'] = i0.Variable<int>(height.value);
}
if (durationMs.present) {
map['duration_ms'] = i0.Variable<int>(durationMs.value);
if (durationInSeconds.present) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds.value);
}
if (id.present) {
map['id'] = i0.Variable<String>(id.value);
@@ -1222,7 +1227,7 @@ class TrashedLocalAssetEntityCompanion
..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationMs: $durationMs, ')
..write('durationInSeconds: $durationInSeconds, ')
..write('id: $id, ')
..write('albumId: $albumId, ')
..write('checksum: $checksum, ')
@@ -1,3 +1,5 @@
// ignore_for_file: experimental_member_use
import 'dart:async';
import 'package:drift/drift.dart';
@@ -10,7 +12,6 @@ import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/memory.entity.dart';
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
@@ -19,12 +20,10 @@ import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset_cloud_id.entity.dart';
import 'package:immich_mobile/infrastructure/entities/stack.entity.dart';
import 'package:immich_mobile/infrastructure/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.drift.dart';
@@ -84,7 +83,7 @@ class Drift extends $Drift {
}
@override
int get schemaVersion => 24;
int get schemaVersion => 22;
@override
MigrationStrategy get migration => MigrationStrategy(
@@ -225,31 +224,6 @@ class Drift extends $Drift {
await m.createTable(v22.assetEditEntity);
await m.createIndex(v22.idxAssetEditAssetId);
},
from22To23: (m, v23) async {
await m.renameColumn(v23.localAssetEntity, 'duration_in_seconds', v23.localAssetEntity.durationMs);
await m.renameColumn(v23.remoteAssetEntity, 'duration_in_seconds', v23.remoteAssetEntity.durationMs);
await m.renameColumn(
v23.trashedLocalAssetEntity,
'duration_in_seconds',
v23.trashedLocalAssetEntity.durationMs,
);
await localAssetEntity.update().write(
LocalAssetEntityCompanion.custom(durationMs: v23.localAssetEntity.durationMs * const Constant(1000)),
);
await remoteAssetEntity.update().write(
RemoteAssetEntityCompanion.custom(durationMs: v23.remoteAssetEntity.durationMs * const Constant(1000)),
);
await trashedLocalAssetEntity.update().write(
TrashedLocalAssetEntityCompanion.custom(
durationMs: v23.trashedLocalAssetEntity.durationMs * const Constant(1000),
),
);
},
from23To24: (m, v24) async {
await customStatement('DROP INDEX IF EXISTS idx_remote_album_owner_id');
await m.alterTable(TableMigration(v24.remoteAlbumEntity));
},
),
);
@@ -105,6 +105,7 @@ abstract class $Drift extends i0.GeneratedDatabase {
localAlbumEntity,
localAlbumAssetEntity,
i7.idxLocalAlbumAssetAlbumAsset,
i5.idxRemoteAlbumOwnerId,
i4.idxLocalAssetChecksum,
i4.idxLocalAssetCloudId,
i3.idxStackPrimaryAssetId,
@@ -159,6 +160,15 @@ abstract class $Drift extends i0.GeneratedDatabase {
),
result: [i0.TableUpdate('stack_entity', kind: i0.UpdateKind.delete)],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName(
'user_entity',
limitUpdateKind: i0.UpdateKind.delete,
),
result: [
i0.TableUpdate('remote_album_entity', kind: i0.UpdateKind.delete),
],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName(
'remote_asset_entity',
File diff suppressed because it is too large Load Diff
@@ -297,7 +297,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
updatedAt: Value(asset.updatedAt),
width: Value(asset.width),
height: Value(asset.height),
durationMs: Value(asset.durationMs),
durationInSeconds: Value(asset.durationInSeconds),
id: asset.id,
orientation: Value(asset.orientation),
isFavorite: Value(asset.isFavorite),
@@ -329,7 +329,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
updatedAt: Value(asset.updatedAt),
width: Value(asset.width),
height: Value(asset.height),
durationMs: Value(asset.durationMs),
durationInSeconds: Value(asset.durationInSeconds),
id: asset.id,
checksum: const Value(null),
orientation: Value(asset.orientation),
@@ -32,23 +32,17 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
_db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId),
useColumns: false,
),
leftOuterJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), useColumns: false),
leftOuterJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
useColumns: false,
),
innerJoin(
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumUserEntity.userId) &
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id) &
_db.remoteAlbumUserEntity.role.equalsValue(AlbumUserRole.owner),
useColumns: false,
),
]);
query
..where(_db.remoteAssetEntity.deletedAt.isNull())
..addColumns([assetCount])
..addColumns([_db.userEntity.name, _db.userEntity.id])
..addColumns([_db.userEntity.name])
..addColumns([_db.remoteAlbumUserEntity.userId.count(distinct: true)])
..groupBy([_db.remoteAlbumEntity.id]);
@@ -69,7 +63,6 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
.readTable(_db.remoteAlbumEntity)
.toDto(
assetCount: row.read(assetCount) ?? 0,
ownerId: row.read(_db.userEntity.id)!,
ownerName: row.read(_db.userEntity.name)!,
isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0,
),
@@ -93,21 +86,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
useColumns: false,
),
leftOuterJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId),
useColumns: false,
),
innerJoin(
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumUserEntity.userId) &
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id) &
_db.remoteAlbumUserEntity.role.equalsValue(AlbumUserRole.owner),
leftOuterJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
useColumns: false,
),
])
..where(_db.remoteAlbumEntity.id.equals(albumId) & _db.remoteAssetEntity.deletedAt.isNull())
..addColumns([assetCount])
..addColumns([_db.userEntity.name, _db.userEntity.id])
..addColumns([_db.userEntity.name])
..addColumns([_db.remoteAlbumUserEntity.userId.count(distinct: true)])
..groupBy([_db.remoteAlbumEntity.id]);
@@ -117,7 +108,6 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
.readTable(_db.remoteAlbumEntity)
.toDto(
assetCount: row.read(assetCount) ?? 0,
ownerId: row.read(_db.userEntity.id)!,
ownerName: row.read(_db.userEntity.name)!,
isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0,
),
@@ -126,29 +116,12 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
}
Future<RemoteAlbum?> getByName(String albumName, String ownerId) {
final query = _db.remoteAlbumEntity.select().join([
innerJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id) &
_db.remoteAlbumUserEntity.userId.equals(ownerId) &
_db.remoteAlbumUserEntity.role.equalsValue(AlbumUserRole.owner),
useColumns: false,
),
]);
query
..addColumns([_db.remoteAlbumUserEntity.userId])
..where(_db.remoteAlbumEntity.name.equals(albumName))
..orderBy([OrderingTerm.desc(_db.remoteAlbumEntity.createdAt)])
final query = _db.remoteAlbumEntity.select()
..where((row) => row.name.equals(albumName) & row.ownerId.equals(ownerId))
..orderBy([(row) => OrderingTerm.desc(row.createdAt)])
..limit(1);
return query
.map(
(row) => row
.readTable(_db.remoteAlbumEntity)
.toDto(ownerId: row.read(_db.remoteAlbumUserEntity.userId)!, ownerName: '', isShared: false),
)
.getSingleOrNull();
return query.map((row) => row.toDto(ownerName: '', isShared: false)).getSingleOrNull();
}
Future<void> create(RemoteAlbum album, List<String> assetIds) async {
@@ -156,6 +129,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
final entity = RemoteAlbumEntityCompanion(
id: Value(album.id),
name: Value(album.name),
ownerId: Value(album.ownerId),
createdAt: Value(album.createdAt),
updatedAt: Value(album.updatedAt),
description: Value(album.description),
@@ -166,14 +140,6 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
await _db.remoteAlbumEntity.insertOne(entity);
await _db.remoteAlbumUserEntity.insertOne(
RemoteAlbumUserEntityCompanion(
albumId: Value(album.id),
userId: Value(album.ownerId),
role: const Value(AlbumUserRole.owner),
),
);
if (assetIds.isNotEmpty) {
final albumAssets = assetIds.map(
(assetId) => RemoteAlbumAssetEntityCompanion(albumId: Value(album.id), assetId: Value(assetId)),
@@ -191,6 +157,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
RemoteAlbumEntityCompanion(
id: Value(album.id),
name: Value(album.name),
ownerId: Value(album.ownerId),
createdAt: Value(album.createdAt),
updatedAt: Value(album.updatedAt),
description: Value(album.description),
@@ -230,7 +197,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
Future<List<UserDto>> getSharedUsers(String albumId) async {
final albumUserRows = await (_db.select(
_db.remoteAlbumUserEntity,
)..where((row) => row.albumId.equals(albumId) & row.role.isNotValue(AlbumUserRole.owner.index))).get();
)..where((row) => row.albumId.equals(albumId))).get();
if (albumUserRows.isEmpty) {
return [];
@@ -328,21 +295,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
_db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId),
useColumns: false,
),
leftOuterJoin(
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId),
useColumns: false,
),
leftOuterJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
useColumns: false,
),
innerJoin(
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumUserEntity.userId) &
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id) &
_db.remoteAlbumUserEntity.role.equalsValue(AlbumUserRole.owner),
useColumns: false,
),
])
..where(_db.remoteAlbumEntity.id.equals(albumId))
..addColumns([_db.userEntity.name, _db.userEntity.id])
..addColumns([_db.userEntity.name])
..addColumns([_db.remoteAlbumUserEntity.userId.count(distinct: true)])
..groupBy([_db.remoteAlbumEntity.id]);
@@ -350,7 +315,6 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
final album = row
.readTable(_db.remoteAlbumEntity)
.toDto(
ownerId: row.read(_db.userEntity.id)!,
ownerName: row.read(_db.userEntity.name)!,
isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0,
);
@@ -391,37 +355,6 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
return _db.managers.remoteAlbumEntity.count();
}
Future<UserDto> getOwner(String albumId) {
final query =
_db.userEntity.select().join([
innerJoin(
_db.remoteAlbumUserEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumUserEntity.userId),
useColumns: false,
),
])..where(
_db.remoteAlbumUserEntity.albumId.equals(albumId) &
_db.remoteAlbumUserEntity.role.equalsValue(AlbumUserRole.owner),
);
return query
.map(
(row) => UserDto(
id: row.read(_db.userEntity.id)!,
email: row.read(_db.userEntity.email)!,
name: row.read(_db.userEntity.name)!,
memoryEnabled: true,
inTimeline: false,
isPartnerSharedBy: false,
isPartnerSharedWith: false,
profileChangedAt: row.read(_db.userEntity.profileChangedAt)!,
hasProfileImage: row.read(_db.userEntity.hasProfileImage)!,
avatarColor: AvatarColor.values[row.read(_db.userEntity.avatarColor)!],
),
)
.getSingle();
}
Future<List<String>> getLinkedAssetIds(String userId, String localAlbumId, String remoteAlbumId) async {
// Find remote asset ids that:
// 1. Belong to the provided local album (via local_album_asset_entity)
@@ -484,22 +417,20 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
useColumns: false,
),
leftOuterJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId),
useColumns: false,
),
innerJoin(
_db.userEntity,
_db.userEntity.id.equalsExp(_db.remoteAlbumUserEntity.userId) &
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id) &
_db.remoteAlbumUserEntity.role.equalsValue(AlbumUserRole.owner),
leftOuterJoin(
_db.remoteAlbumUserEntity,
_db.remoteAlbumUserEntity.albumId.equalsExp(_db.remoteAlbumEntity.id),
useColumns: false,
),
])
..where(_db.remoteAlbumEntity.id.isIn(albumIds) & _db.remoteAssetEntity.deletedAt.isNull())
..addColumns([assetCount])
..addColumns([_db.remoteAlbumUserEntity.userId.count(distinct: true)])
..addColumns([_db.userEntity.name, _db.userEntity.id])
..addColumns([_db.userEntity.name])
..groupBy([_db.remoteAlbumEntity.id]);
return query
@@ -507,7 +438,6 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
(row) => row
.readTable(_db.remoteAlbumEntity)
.toDto(
ownerId: row.read(_db.userEntity.id)!,
ownerName: row.read(_db.userEntity.name) ?? '',
isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0,
assetCount: row.read(assetCount) ?? 0,
@@ -518,7 +448,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
}
extension on RemoteAlbumEntityData {
RemoteAlbum toDto({int assetCount = 0, required String ownerName, required String ownerId, required bool isShared}) {
RemoteAlbum toDto({int assetCount = 0, required String ownerName, required bool isShared}) {
return RemoteAlbum(
id: id,
name: name,
@@ -53,10 +53,7 @@ class SyncApiRepository {
SyncRequestType.partnersV1,
SyncRequestType.partnerAssetsV1,
SyncRequestType.partnerAssetExifsV1,
if (serverVersion < const SemVer(major: 3, minor: 0, patch: 0))
SyncRequestType.albumsV1
else
SyncRequestType.albumsV2,
SyncRequestType.albumsV1,
SyncRequestType.albumUsersV1,
SyncRequestType.albumAssetsV1,
SyncRequestType.albumAssetExifsV1,
@@ -165,7 +162,6 @@ const _kResponseMap = <SyncEntityType, Function(Object)>{
SyncEntityType.partnerAssetExifV1: SyncAssetExifV1.fromJson,
SyncEntityType.partnerAssetExifBackfillV1: SyncAssetExifV1.fromJson,
SyncEntityType.albumV1: SyncAlbumV1.fromJson,
SyncEntityType.albumV2: SyncAlbumV2.fromJson,
SyncEntityType.albumDeleteV1: SyncAlbumDeleteV1.fromJson,
SyncEntityType.albumUserV1: SyncAlbumUserV1.fromJson,
SyncEntityType.albumUserBackfillV1: SyncAlbumUserV1.fromJson,
@@ -9,7 +9,6 @@ import 'package:immich_mobile/domain/models/asset_edit.model.dart';
import 'package:immich_mobile/domain/models/memory.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/extensions/string_extensions.dart';
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
@@ -30,7 +29,7 @@ import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/utils/exif.converter.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart' as api show AssetVisibility, AlbumUserRole, UserMetadataKey, AssetEditAction;
import 'package:openapi/api.dart' hide UserMetadataKey, AssetEditAction, AssetVisibility, AlbumUserRole;
import 'package:openapi/api.dart' hide AlbumUserRole, UserMetadataKey, AssetEditAction, AssetVisibility;
class SyncStreamRepository extends DriftDatabaseRepository {
final Logger _logger = Logger('DriftSyncStreamRepository');
@@ -191,7 +190,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
type: Value(asset.type.toAssetType()),
createdAt: Value.absentIfNull(asset.fileCreatedAt),
updatedAt: Value.absentIfNull(asset.fileModifiedAt),
durationMs: Value(asset.duration?.toDuration()?.inMilliseconds ?? 0),
durationInSeconds: Value(asset.duration?.toDuration()?.inSeconds ?? 0),
checksum: Value(asset.checksum),
isFavorite: Value(asset.isFavorite),
ownerId: Value(asset.ownerId),
@@ -397,47 +396,6 @@ class SyncStreamRepository extends DriftDatabaseRepository {
}
Future<void> updateAlbumsV1(Iterable<SyncAlbumV1> data) async {
try {
await _db.transaction(() async {
await _db.batch((batch) {
for (final album in data) {
final companion = RemoteAlbumEntityCompanion(
name: Value(album.name),
description: Value(album.description),
isActivityEnabled: Value(album.isActivityEnabled),
order: Value(album.order.toAlbumAssetOrder()),
thumbnailAssetId: Value(album.thumbnailAssetId),
createdAt: Value(album.createdAt),
updatedAt: Value(album.updatedAt),
);
batch.insert(
_db.remoteAlbumEntity,
companion.copyWith(id: Value(album.id)),
onConflict: DoUpdate((_) => companion),
);
}
});
await _db.batch((batch) {
for (final album in data) {
final companion = RemoteAlbumUserEntityCompanion(
albumId: Value(album.id),
userId: Value(album.ownerId),
role: const Value(AlbumUserRole.owner),
);
batch.insert(_db.remoteAlbumUserEntity, companion, onConflict: DoUpdate((_) => companion));
}
});
});
} catch (error, stack) {
_logger.severe('Error: updateAlbumsV1', error, stack);
rethrow;
}
}
Future<void> updateAlbumsV2(Iterable<SyncAlbumV2> data) async {
try {
await _db.batch((batch) {
for (final album in data) {
@@ -447,6 +405,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
isActivityEnabled: Value(album.isActivityEnabled),
order: Value(album.order.toAlbumAssetOrder()),
thumbnailAssetId: Value(album.thumbnailAssetId),
ownerId: Value(album.ownerId),
createdAt: Value(album.createdAt),
updatedAt: Value(album.updatedAt),
);
@@ -459,7 +418,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
}
});
} catch (error, stack) {
_logger.severe('Error: updateAlbumsV2', error, stack);
_logger.severe('Error: updateAlbumsV1', error, stack);
rethrow;
}
}
@@ -861,7 +820,6 @@ extension on api.AlbumUserRole {
AlbumUserRole toAlbumUserRole() => switch (this) {
api.AlbumUserRole.editor => AlbumUserRole.editor,
api.AlbumUserRole.viewer => AlbumUserRole.viewer,
api.AlbumUserRole.owner => AlbumUserRole.owner,
_ => throw Exception('Unknown AlbumUserRole value: $this'),
};
}
@@ -885,6 +843,18 @@ extension on api.UserMetadataKey {
};
}
extension on String {
Duration? toDuration() {
try {
final parts = split(':').map((e) => double.parse(e).toInt()).toList(growable: false);
return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]);
} catch (_) {
return null;
}
}
}
extension on UserAvatarColor {
AvatarColor? toAvatarColor() => AvatarColor.values.firstWhereOrNull((c) => c.name == value);
}
@@ -83,7 +83,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
width: row.width,
height: row.height,
isFavorite: row.isFavorite,
durationMs: row.durationMs,
durationInSeconds: row.durationInSeconds,
livePhotoVideoId: row.livePhotoVideoId,
stackId: row.stackId,
isEdited: row.isEdited,
@@ -99,7 +99,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
width: row.width,
height: row.height,
isFavorite: row.isFavorite,
durationMs: row.durationMs,
durationInSeconds: row.durationInSeconds,
orientation: row.orientation,
playbackStyle: AssetPlaybackStyle.values[row.playbackStyle],
cloudId: row.iCloudId,
@@ -82,7 +82,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
updatedAt: Value(item.asset.updatedAt),
width: Value(item.asset.width),
height: Value(item.asset.height),
durationMs: Value(item.asset.durationMs),
durationInSeconds: Value(item.asset.durationInSeconds),
isFavorite: Value(item.asset.isFavorite),
orientation: Value(item.asset.orientation),
playbackStyle: Value(item.asset.playbackStyle),
@@ -145,7 +145,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
type: Value(asset.type),
width: Value(asset.width),
height: Value(asset.height),
durationMs: Value(asset.durationMs),
durationInSeconds: Value(asset.durationInSeconds),
isFavorite: Value(asset.isFavorite),
orientation: Value(asset.orientation),
playbackStyle: Value(asset.playbackStyle),
@@ -193,7 +193,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
updatedAt: Value(e.updatedAt),
width: Value(e.width),
height: Value(e.height),
durationMs: Value(e.durationMs),
durationInSeconds: Value(e.durationInSeconds),
checksum: Value(e.checksum),
isFavorite: Value(e.isFavorite),
orientation: Value(e.orientation),
@@ -244,7 +244,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
updatedAt: Value(e.asset.updatedAt),
width: Value(e.asset.width),
height: Value(e.asset.height),
durationMs: Value(e.asset.durationMs),
durationInSeconds: Value(e.asset.durationInSeconds),
checksum: Value(e.asset.checksum),
isFavorite: Value(e.asset.isFavorite),
orientation: Value(e.asset.orientation),
@@ -8,5 +8,5 @@ mixin AssetEntityMixin on Table {
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
IntColumn get width => integer().nullable()();
IntColumn get height => integer().nullable()();
IntColumn get durationMs => integer().nullable()();
IntColumn get durationInSeconds => integer().nullable()();
}
@@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/people/partner_user_avatar.widget.dart';
import 'package:immich_mobile/providers/infrastructure/partner.provider.dart';
+115 -111
View File
@@ -1,29 +1,18 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
Object? _extractReplyValueOrThrow(List<Object?>? replyList, String channelName, {required bool isNullValid}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(code: replyList[0]! as String, message: replyList[1] as String?, details: replyList[2]);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
}
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
@@ -37,65 +26,19 @@ List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty
}
bool _deepEquals(Object? a, Object? b) {
if (identical(a, b)) {
return true;
}
if (a is double && b is double) {
if (a.isNaN && b.isNaN) {
return true;
}
return a == b;
}
if (a is List && b is List) {
return a.length == b.length && a.indexed.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
}
if (a is Map && b is Map) {
if (a.length != b.length) {
return false;
}
for (final MapEntry<Object?, Object?> entryA in a.entries) {
bool found = false;
for (final MapEntry<Object?, Object?> entryB in b.entries) {
if (_deepEquals(entryA.key, entryB.key)) {
if (_deepEquals(entryA.value, entryB.value)) {
found = true;
break;
} else {
return false;
}
}
}
if (!found) {
return false;
}
}
return true;
return a.length == b.length &&
a.entries.every(
(MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) && _deepEquals(entry.value, b[entry.key]),
);
}
return a == b;
}
int _deepHash(Object? value) {
if (value is List) {
return Object.hashAll(value.map(_deepHash));
}
if (value is Map) {
int result = 0;
for (final MapEntry<Object?, Object?> entry in value.entries) {
result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value);
}
return result;
}
if (value is double && value.isNaN) {
// Normalize NaN to a consistent hash.
return 0x7FF8000000000000.hashCode;
}
if (value is double && value == 0.0) {
// Normalize -0.0 to 0.0 so they have the same hash code.
return 0.0.hashCode;
}
return value.hashCode;
}
class BackgroundWorkerSettings {
BackgroundWorkerSettings({required this.requiresCharging, required this.minimumDelaySeconds});
@@ -125,13 +68,12 @@ class BackgroundWorkerSettings {
if (identical(this, other)) {
return true;
}
return _deepEquals(requiresCharging, other.requiresCharging) &&
_deepEquals(minimumDelaySeconds, other.minimumDelaySeconds);
return _deepEquals(encode(), other.encode());
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
int get hashCode => Object.hashAll(_toList());
}
class _PigeonCodec extends StandardMessageCodec {
@@ -174,59 +116,95 @@ class BackgroundWorkerFgHostApi {
final String pigeonVar_messageChannelSuffix;
Future<void> enable() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> saveNotificationMessage(String title, String body) async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[title, body]);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> configure(BackgroundWorkerSettings settings) async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[settings]);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> disable() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
@@ -244,31 +222,49 @@ class BackgroundWorkerBgHostApi {
final String pigeonVar_messageChannelSuffix;
Future<void> onInitialized() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.onInitialized$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> close() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerBgHostApi.close$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
@@ -288,7 +284,7 @@ abstract class BackgroundWorkerFlutterApi {
}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
@@ -297,11 +293,19 @@ abstract class BackgroundWorkerFlutterApi {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
final List<Object?> args = message! as List<Object?>;
final bool arg_isRefresh = args[0]! as bool;
final int? arg_maxSeconds = args[1] as int?;
assert(
message != null,
'Argument for dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload was null.',
);
final List<Object?> args = (message as List<Object?>?)!;
final bool? arg_isRefresh = (args[0] as bool?);
assert(
arg_isRefresh != null,
'Argument for dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onIosUpload was null, expected non-null bool.',
);
final int? arg_maxSeconds = (args[1] as int?);
try {
await api.onIosUpload(arg_isRefresh, arg_maxSeconds);
await api.onIosUpload(arg_isRefresh!, arg_maxSeconds);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
@@ -314,7 +318,7 @@ abstract class BackgroundWorkerFlutterApi {
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.onAndroidUpload$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
@@ -337,7 +341,7 @@ abstract class BackgroundWorkerFlutterApi {
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFlutterApi.cancel$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
+37 -30
View File
@@ -1,29 +1,18 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
Object? _extractReplyValueOrThrow(List<Object?>? replyList, String channelName, {required bool isNullValid}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(code: replyList[0]! as String, message: replyList[1] as String?, details: replyList[2]);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
}
class _PigeonCodec extends StandardMessageCodec {
@@ -61,30 +50,48 @@ class BackgroundWorkerLockApi {
final String pigeonVar_messageChannelSuffix;
Future<void> lock() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.lock$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> unlock() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.unlock$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
+29 -31
View File
@@ -1,29 +1,18 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
Object? _extractReplyValueOrThrow(List<Object?>? replyList, String channelName, {required bool isNullValid}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(code: replyList[0]! as String, message: replyList[1] as String?, details: replyList[2]);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
}
enum NetworkCapability { cellular, wifi, vpn, unmetered }
@@ -47,7 +36,7 @@ class _PigeonCodec extends StandardMessageCodec {
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
final value = readValue(buffer) as int?;
final int? value = readValue(buffer) as int?;
return value == null ? null : NetworkCapability.values[value];
default:
return super.readValueOfType(type, buffer);
@@ -69,21 +58,30 @@ class ConnectivityApi {
final String pigeonVar_messageChannelSuffix;
Future<List<NetworkCapability>> getCapabilities() async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
);
return (pigeonVar_replyValue! as List<Object?>).cast<NetworkCapability>();
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as List<Object?>?)!.cast<NetworkCapability>();
}
}
}
+56 -45
View File
@@ -1,29 +1,18 @@
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
// Autogenerated from Pigeon (v26.0.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
Object? _extractReplyValueOrThrow(List<Object?>? replyList, String channelName, {required bool isNullValid}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(code: replyList[0]! as String, message: replyList[1] as String?, details: replyList[2]);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
}
class _PigeonCodec extends StandardMessageCodec {
@@ -68,9 +57,9 @@ class LocalImageApi {
required bool isVideo,
required bool preferEncoded,
}) async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.LocalImageApi.requestImage$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
@@ -83,46 +72,68 @@ class LocalImageApi {
isVideo,
preferEncoded,
]);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: true,
);
return (pigeonVar_replyValue as Map<Object?, Object?>?)?.cast<String, int>();
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)?.cast<String, int>();
}
}
Future<void> cancelRequest(int requestId) async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.LocalImageApi.cancelRequest$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[requestId]);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<Map<String, int>> getThumbhash(String thumbhash) async {
final pigeonVar_channelName =
final String pigeonVar_channelName =
'dev.flutter.pigeon.immich_mobile.LocalImageApi.getThumbhash$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[thumbhash]);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
);
return (pigeonVar_replyValue! as Map<Object?, Object?>).cast<String, int>();
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)!.cast<String, int>();
}
}
}

Some files were not shown because too many files have changed in this diff Show More