mirror of
https://github.com/immich-app/immich.git
synced 2026-07-21 21:34:17 +03:00
Compare commits
14 Commits
feat/nativ
...
fix/backgr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
456ae684e6 | ||
|
|
2e587fc7e8 | ||
|
|
df970da59e | ||
|
|
8061a2e5ff | ||
|
|
77091b0107 | ||
|
|
4c754f2999 | ||
|
|
6fa3f2feac | ||
|
|
3f6897ef80 | ||
|
|
89d0a9d59f | ||
|
|
45a6ea84af | ||
|
|
bf64f3867b | ||
|
|
4a4d468aa2 | ||
|
|
522def1ed6 | ||
|
|
3adc3920fb |
54
.github/workflows/build-mobile.yml
vendored
54
.github/workflows/build-mobile.yml
vendored
@@ -65,7 +65,6 @@ jobs:
|
||||
filters: |
|
||||
mobile:
|
||||
- 'mobile/**'
|
||||
- 'native/**'
|
||||
force-filters: |
|
||||
- '.github/workflows/build-mobile.yml'
|
||||
force-events: 'workflow_call,workflow_dispatch'
|
||||
@@ -155,59 +154,6 @@ jobs:
|
||||
flutter build apk --release
|
||||
fi
|
||||
|
||||
- name: Verify native Android compatibility
|
||||
run: |
|
||||
apk=mobile/build/app/outputs/flutter-apk/app-release.apk
|
||||
sdk=${ANDROID_SDK_ROOT:-${ANDROID_HOME:?Android SDK path is not set}}
|
||||
min_sdk=$(sed -nE 's/^[[:space:]]*minSdk[[:space:]]*=[[:space:]]*([0-9]+)[[:space:]]*$/\1/p' mobile/android/app/build.gradle)
|
||||
[[ $min_sdk =~ ^[0-9]+$ ]] || { printf 'Could not parse minSdk from mobile/android/app/build.gradle\n' >&2; exit 1; }
|
||||
readelf=$(find "$sdk/ndk" -path '*/toolchains/llvm/prebuilt/*/bin/llvm-readelf' -print | sort -V | tail -n 1)
|
||||
[[ -n $readelf ]] || { printf 'No llvm-readelf found under %s\n' "$sdk/ndk" >&2; exit 1; }
|
||||
dir=$(mktemp -d)
|
||||
trap 'rm -rf "$dir"' EXIT
|
||||
|
||||
test -f "$apk"
|
||||
[[ -x $readelf ]] || { printf 'llvm-readelf is not executable: %s\n' "$readelf" >&2; exit 1; }
|
||||
|
||||
for abi in armeabi-v7a arm64-v8a x86_64; do
|
||||
so="$dir/$abi.so"
|
||||
unzip -p "$apk" "lib/$abi/libimmich_core_ffi.so" > "$so"
|
||||
test -s "$so"
|
||||
|
||||
notes=$("$readelf" -n "$so")
|
||||
headers=$("$readelf" -lW "$so")
|
||||
printf '%s notes:\n%s\n' "$abi" "$notes"
|
||||
printf '%s LOAD headers:\n%s\n' "$abi" "$(printf '%s\n' "$headers" | awk '/^[[:space:]]*LOAD[[:space:]]/')"
|
||||
|
||||
bytes=$(printf '%s\n' "$notes" | awk '
|
||||
/^[[:space:]]*Android[[:space:]]/ { android = 1; next }
|
||||
android && /description data:/ {
|
||||
sub(/^.*description data:[[:space:]]*/, "")
|
||||
print $1, $2, $3, $4
|
||||
exit
|
||||
}
|
||||
')
|
||||
read -r b0 b1 b2 b3 <<< "$bytes"
|
||||
for byte in "$b0" "$b1" "$b2" "$b3"; do
|
||||
[[ $byte =~ ^[0-9a-fA-F]{2}$ ]]
|
||||
done
|
||||
api=$((16#$b0 + (16#$b1 << 8) + (16#$b2 << 16) + (16#$b3 << 24)))
|
||||
printf '%s Android API: %d\n' "$abi" "$api"
|
||||
if ((api > min_sdk)); then
|
||||
printf '%s Android API %d exceeds minSdk %d\n' "$abi" "$api" "$min_sdk" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
alignments=$(printf '%s\n' "$headers" | awk '/^[[:space:]]*LOAD[[:space:]]/ { print $NF }')
|
||||
test -n "$alignments"
|
||||
while read -r alignment; do
|
||||
if [[ $alignment != 0x4000 ]]; then
|
||||
printf '%s LOAD alignment %s is not 0x4000\n' "$abi" "$alignment" >&2
|
||||
exit 1
|
||||
fi
|
||||
done <<< "$alignments"
|
||||
done
|
||||
|
||||
- name: Publish Android Artifact
|
||||
id: upload-apk
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
|
||||
1
.github/workflows/static_analysis.yml
vendored
1
.github/workflows/static_analysis.yml
vendored
@@ -35,7 +35,6 @@ jobs:
|
||||
mobile:
|
||||
- 'mobile/**'
|
||||
- 'i18n/en.json'
|
||||
- 'native/**'
|
||||
force-filters: |
|
||||
- '.github/workflows/static_analysis.yml'
|
||||
force-events: 'workflow_dispatch,release'
|
||||
|
||||
43
.github/workflows/test.yml
vendored
43
.github/workflows/test.yml
vendored
@@ -59,10 +59,6 @@ jobs:
|
||||
- 'mise.toml'
|
||||
mobile:
|
||||
- 'mobile/**'
|
||||
- 'native/**'
|
||||
- 'mise.toml'
|
||||
native:
|
||||
- 'native/**'
|
||||
- 'mise.toml'
|
||||
machine-learning:
|
||||
- 'machine-learning/**'
|
||||
@@ -73,45 +69,6 @@ jobs:
|
||||
- '.github/workflows/test.yml'
|
||||
force-events: 'workflow_dispatch'
|
||||
|
||||
native-tests:
|
||||
name: Test & Lint Native Core
|
||||
needs: pre-job
|
||||
if: ${{ fromJSON(needs.pre-job.outputs.should_run).native == true }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./native
|
||||
steps:
|
||||
- id: token
|
||||
uses: immich-app/devtools/actions/create-workflow-token@1af396ae134e4bc3b63d947e672bc68bf4ff9dc5 # create-workflow-token-action-v3.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }}
|
||||
permission-contents: read
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
|
||||
- name: Setup Mise
|
||||
uses: immich-app/devtools/actions/use-mise@3bca63ca3c15020293b36b51737a3ee2c773340b # use-mise-action-v3.1.0
|
||||
with:
|
||||
github_token: ${{ steps.token.outputs.token }}
|
||||
working_directory: ./native
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all --check
|
||||
|
||||
- name: Run Clippy
|
||||
run: cargo clippy --workspace --all-targets --locked -- -D warnings
|
||||
|
||||
- name: Run tests
|
||||
run: cargo test --workspace --locked
|
||||
|
||||
script-unit-tests:
|
||||
name: Scripts unit tests
|
||||
needs: pre-job
|
||||
|
||||
38
.vscode/settings.json
vendored
38
.vscode/settings.json
vendored
@@ -29,9 +29,6 @@
|
||||
"editor.formatOnSave": true,
|
||||
"tailwindCSS.lint.suggestCanonicalClasses": "ignore"
|
||||
},
|
||||
"svelte.plugin.svelte.compilerWarnings": {
|
||||
"state_referenced_locally": "ignore"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
@@ -43,37 +40,40 @@
|
||||
"eslint.useFlatConfig": true,
|
||||
"eslint.validate": ["javascript", "typescript", "svelte"],
|
||||
"eslint.workingDirectories": [
|
||||
{ "directory": "cli", "changeProcessCWD": true },
|
||||
{ "directory": "e2e", "changeProcessCWD": true },
|
||||
{ "directory": "server", "changeProcessCWD": true },
|
||||
{ "directory": "web", "changeProcessCWD": true }
|
||||
{ "changeProcessCWD": true, "directory": "cli" },
|
||||
{ "changeProcessCWD": true, "directory": "e2e" },
|
||||
{ "changeProcessCWD": true, "directory": "server" },
|
||||
{ "changeProcessCWD": true, "directory": "web" }
|
||||
],
|
||||
"files.watcherExclude": {
|
||||
"**/.jj/**": true,
|
||||
"**/.git/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/build/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/.svelte-kit/**": true
|
||||
},
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart",
|
||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
|
||||
"*.js": "${capture}.spec.js,${capture}.mock.js",
|
||||
"*.ts": "${capture}.spec.ts,${capture}.mock.ts",
|
||||
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb, bun.lock, pnpm-workspace.yaml, .pnpmfile.cjs"
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/.git/**": true,
|
||||
"**/.jj/**": true,
|
||||
"**/.svelte-kit/**": true,
|
||||
"**/build/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/node_modules/**": true
|
||||
},
|
||||
"js/ts.preferences.importModuleSpecifier": "non-relative",
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/.svelte-kit": true,
|
||||
"**/build": true,
|
||||
"**/dist": true,
|
||||
"**/.svelte-kit": true,
|
||||
"**/node_modules": true,
|
||||
"**/open-api/typescript-sdk/src": true
|
||||
},
|
||||
"svelte.enable-ts-plugin": true,
|
||||
"svelte.plugin.svelte.compilerWarnings": {
|
||||
"state_referenced_locally": "ignore"
|
||||
},
|
||||
"tailwindCSS.experimental.configFile": {
|
||||
"web/src/app.css": "web/src/**"
|
||||
},
|
||||
"js/ts.preferences.importModuleSpecifier": "non-relative",
|
||||
"vitest.maximumConfigs": 10
|
||||
}
|
||||
|
||||
@@ -5,4 +5,3 @@
|
||||
/machine-learning/ @mertalev
|
||||
/e2e/ @danieldietzler
|
||||
/mobile/ @shenlong-tanwen @santoshakil @agg23
|
||||
/native/ @santoshakil @mertalev
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<a href="readme_i18n/README_zh_TW.md">正體中文</a>
|
||||
<a href="readme_i18n/README_uk_UA.md">Українська</a>
|
||||
<a href="readme_i18n/README_ru_RU.md">Русский</a>
|
||||
<a href="readme_i18n/README_bg_BG.md">Български</a>
|
||||
<a href="readme_i18n/README_pt_BR.md">Português Brasileiro</a>
|
||||
<a href="readme_i18n/README_sv_SE.md">Svenska</a>
|
||||
<a href="readme_i18n/README_ar_JO.md">العربية</a>
|
||||
|
||||
@@ -41,9 +41,17 @@ export default typescriptEslint.config([
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
'unicorn/prefer-module': 'off',
|
||||
'unicorn/import-style': 'off',
|
||||
'unicorn/consistent-boolean-name': 'off',
|
||||
'unicorn/no-non-function-verb-prefix': 'off',
|
||||
'unicorn/no-unreadable-for-of-expression': 'off',
|
||||
'unicorn/max-nested-calls': 'off',
|
||||
'unicorn/prefer-uint8array-base64': 'off',
|
||||
'unicorn/isolated-functions': 'off',
|
||||
'unicorn/prefer-promise-with-resolvers': 'off',
|
||||
'unicorn/no-declarations-before-early-exit': 'off',
|
||||
curly: 2,
|
||||
'prettier/prettier': 0,
|
||||
'unicorn/prevent-abbreviations': 'off',
|
||||
'unicorn/name-replacements': 'off',
|
||||
'unicorn/filename-case': 'off',
|
||||
'unicorn/no-null': 'off',
|
||||
'unicorn/prefer-top-level-await': 'off',
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"eslint": "^10.0.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-unicorn": "^64.0.0",
|
||||
"eslint-plugin-unicorn": "^70.0.0",
|
||||
"exiftool-vendored": "^35.0.0",
|
||||
"globals": "^17.0.0",
|
||||
"luxon": "^3.4.4",
|
||||
|
||||
@@ -118,7 +118,7 @@ describe('/admin/database-backups', () => {
|
||||
|
||||
expect(status).toBe(201);
|
||||
|
||||
cookie = headers['set-cookie'][0].split(';')[0];
|
||||
cookie = headers['set-cookie'][0].split(';', 1)[0];
|
||||
|
||||
await expect
|
||||
.poll(
|
||||
@@ -224,7 +224,7 @@ describe('/admin/database-backups', () => {
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
cookie = headers['set-cookie'][0].split(';')[0];
|
||||
cookie = headers['set-cookie'][0].split(';', 1)[0];
|
||||
|
||||
await expect
|
||||
.poll(
|
||||
@@ -295,7 +295,7 @@ describe('/admin/database-backups', () => {
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
cookie = headers['set-cookie'][0].split(';')[0];
|
||||
cookie = headers['set-cookie'][0].split(';', 1)[0];
|
||||
|
||||
await expect
|
||||
.poll(
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('/admin/maintenance', () => {
|
||||
|
||||
expect(status).toBe(201);
|
||||
|
||||
cookie = headers['set-cookie'][0].split(';')[0];
|
||||
cookie = headers['set-cookie'][0].split(';', 1)[0];
|
||||
expect(cookie).toEqual(
|
||||
expect.stringMatching(/^immich_maintenance_token=[A-Za-z0-9-_]*\.[A-Za-z0-9-_]*\.[A-Za-z0-9-_]*$/),
|
||||
);
|
||||
@@ -149,7 +149,7 @@ describe('/admin/maintenance', () => {
|
||||
const { status, body } = await request(app)
|
||||
.post('/admin/maintenance/login')
|
||||
.send({
|
||||
token: cookie!.split('=')[1].trim(),
|
||||
token: cookie!.split('=', 2)[1].trim(),
|
||||
});
|
||||
expect(status).toBe(201);
|
||||
expect(body).toEqual(
|
||||
|
||||
@@ -27,7 +27,7 @@ test.describe('Maintenance', () => {
|
||||
test('maintenance shows no options to users until they authenticate', async ({ page }) => {
|
||||
const setCookie = await utils.enterMaintenance(admin.accessToken);
|
||||
const cookie = setCookie
|
||||
?.map((cookie) => cookie.split(';')[0].split('='))
|
||||
?.map((cookie) => cookie.split(';', 1)[0].split('='))
|
||||
?.find(([name]) => name === 'immich_maintenance_token');
|
||||
|
||||
expect(cookie).toBeTruthy();
|
||||
|
||||
@@ -120,6 +120,7 @@ describe('/albums', () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
// eslint-disable-next-line unicorn/no-unreadable-array-destructuring
|
||||
[user2Albums[0]] = await Promise.all([
|
||||
getAlbumInfo({ id: user2Albums[0].id }, { headers: asBearerAuth(user2.accessToken) }),
|
||||
deleteUserAdmin({ id: user3.userId, userAdminDeleteDto: {} }, { headers: asBearerAuth(admin.accessToken) }),
|
||||
|
||||
@@ -781,7 +781,7 @@ describe('/asset', () => {
|
||||
exifImageWidth: 4032,
|
||||
exifImageHeight: 3024,
|
||||
latitude: 41.2203,
|
||||
longitude: -96.071_625,
|
||||
longitude: -96.071625,
|
||||
make: 'Apple',
|
||||
model: 'iPhone 7',
|
||||
lensModel: 'iPhone 7 back camera 3.99mm f/1.8',
|
||||
@@ -973,9 +973,9 @@ describe('/asset', () => {
|
||||
fileSizeInByte: 31_175_472,
|
||||
focalLength: 18.3,
|
||||
iso: 100,
|
||||
latitude: 36.613_24,
|
||||
latitude: 36.61324,
|
||||
lensModel: '18.3mm F2.8',
|
||||
longitude: -121.897_85,
|
||||
longitude: -121.89785,
|
||||
make: 'RICOH IMAGING COMPANY, LTD.',
|
||||
model: 'RICOH GR III',
|
||||
orientation: '1',
|
||||
|
||||
@@ -75,7 +75,7 @@ describe('/map', () => {
|
||||
country: 'United States of America',
|
||||
id: expect.any(String),
|
||||
lat: expect.closeTo(39.115),
|
||||
lon: expect.closeTo(-108.400_968),
|
||||
lon: expect.closeTo(-108.400968),
|
||||
state: 'Colorado',
|
||||
},
|
||||
{
|
||||
@@ -83,7 +83,7 @@ describe('/map', () => {
|
||||
country: 'United States of America',
|
||||
id: expect.any(String),
|
||||
lat: expect.closeTo(41.2203),
|
||||
lon: expect.closeTo(-96.071_625),
|
||||
lon: expect.closeTo(-96.071625),
|
||||
state: 'Nebraska',
|
||||
},
|
||||
]);
|
||||
@@ -123,7 +123,7 @@ describe('/map', () => {
|
||||
country: 'United States of America',
|
||||
id: expect.any(String),
|
||||
lat: expect.closeTo(39.115),
|
||||
lon: expect.closeTo(-108.400_968),
|
||||
lon: expect.closeTo(-108.400968),
|
||||
state: 'Colorado',
|
||||
},
|
||||
{
|
||||
@@ -131,7 +131,7 @@ describe('/map', () => {
|
||||
country: 'United States of America',
|
||||
id: expect.any(String),
|
||||
lat: expect.closeTo(41.2203),
|
||||
lon: expect.closeTo(-96.071_625),
|
||||
lon: expect.closeTo(-96.071625),
|
||||
state: 'Nebraska',
|
||||
},
|
||||
]);
|
||||
@@ -188,20 +188,20 @@ describe('/map', () => {
|
||||
const reverseGeocodeTestCases = [
|
||||
{
|
||||
name: 'Vaucluse',
|
||||
lat: -33.858_977_058_663_13,
|
||||
lon: 151.278_490_730_270_48,
|
||||
lat: -33.85897705866313,
|
||||
lon: 151.27849073027048,
|
||||
results: [{ city: 'Vaucluse', state: 'New South Wales', country: 'Australia' }],
|
||||
},
|
||||
{
|
||||
name: 'Ravenhall',
|
||||
lat: -37.765_732_399_174_75,
|
||||
lon: 144.752_453_164_883_3,
|
||||
lat: -37.76573239917475,
|
||||
lon: 144.7524531648833,
|
||||
results: [{ city: 'Ravenhall', state: 'Victoria', country: 'Australia' }],
|
||||
},
|
||||
{
|
||||
name: 'Scarborough',
|
||||
lat: -31.894_346_156_789_997,
|
||||
lon: 115.757_617_103_904_64,
|
||||
lat: -31.894346156789997,
|
||||
lon: 115.75761710390464,
|
||||
results: [{ city: 'Scarborough', state: 'Western Australia', country: 'Australia' }],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -44,7 +44,7 @@ const loginWithOAuth = async (sub: OAuthUser | string, redirectUri?: string) =>
|
||||
});
|
||||
|
||||
// login
|
||||
const response1 = await redirect(url.replace(authServer.internal, authServer.external));
|
||||
const response1 = await redirect(url.replace(authServer.internal, () => authServer.external));
|
||||
const response2 = await request(authServer.external + response1.location)
|
||||
.post('')
|
||||
.set('Cookie', response1.cookies)
|
||||
|
||||
@@ -87,23 +87,23 @@ describe('/search', () => {
|
||||
|
||||
// note: the coordinates here are not the actual coordinates of the images and are random for most of them
|
||||
const coordinates = [
|
||||
{ latitude: 48.853_41, longitude: 2.3488 }, // paris
|
||||
{ latitude: 35.6895, longitude: 139.691_71 }, // tokyo
|
||||
{ latitude: 52.524_37, longitude: 13.410_53 }, // berlin
|
||||
{ latitude: 1.314_663_1, longitude: 103.845_409_3 }, // singapore
|
||||
{ latitude: 41.013_84, longitude: 28.949_66 }, // istanbul
|
||||
{ latitude: 5.556_02, longitude: -0.1969 }, // accra
|
||||
{ latitude: 37.544_270_6, longitude: -4.727_752_8 }, // andalusia
|
||||
{ latitude: 23.133_02, longitude: -82.383_04 }, // havana
|
||||
{ latitude: 41.694_11, longitude: 44.833_68 }, // tbilisi
|
||||
{ latitude: 31.222_22, longitude: 121.458_06 }, // shanghai
|
||||
{ latitude: 48.85341, longitude: 2.3488 }, // paris
|
||||
{ latitude: 35.6895, longitude: 139.69171 }, // tokyo
|
||||
{ latitude: 52.52437, longitude: 13.41053 }, // berlin
|
||||
{ latitude: 1.3146631, longitude: 103.8454093 }, // singapore
|
||||
{ latitude: 41.01384, longitude: 28.94966 }, // istanbul
|
||||
{ latitude: 5.55602, longitude: -0.1969 }, // accra
|
||||
{ latitude: 37.5442706, longitude: -4.7277528 }, // andalusia
|
||||
{ latitude: 23.13302, longitude: -82.38304 }, // havana
|
||||
{ latitude: 41.69411, longitude: 44.83368 }, // tbilisi
|
||||
{ latitude: 31.22222, longitude: 121.45806 }, // shanghai
|
||||
{ latitude: 38.9711, longitude: -109.7137 }, // thompson springs
|
||||
{ latitude: 40.714_27, longitude: -74.005_97 }, // new york
|
||||
{ latitude: 47.040_57, longitude: 9.068_04 }, // glarus
|
||||
{ latitude: 32.771_52, longitude: -89.116_73 }, // philadelphia
|
||||
{ latitude: 31.634_16, longitude: -7.999_94 }, // marrakesh
|
||||
{ latitude: 38.523_735_4, longitude: -78.488_619_4 }, // tanners ridge
|
||||
{ latitude: 59.938_63, longitude: 30.314_13 }, // st. petersburg
|
||||
{ latitude: 40.71427, longitude: -74.00597 }, // new york
|
||||
{ latitude: 47.04057, longitude: 9.06804 }, // glarus
|
||||
{ latitude: 32.77152, longitude: -89.11673 }, // philadelphia
|
||||
{ latitude: 31.63416, longitude: -7.99994 }, // marrakesh
|
||||
{ latitude: 38.5237354, longitude: -78.4886194 }, // tanners ridge
|
||||
{ latitude: 59.93863, longitude: 30.31413 }, // st. petersburg
|
||||
{ latitude: 0, longitude: 0 }, // null island
|
||||
];
|
||||
|
||||
@@ -112,7 +112,7 @@ describe('/search', () => {
|
||||
);
|
||||
|
||||
await Promise.all(updates);
|
||||
for (const [i] of coordinates.entries()) {
|
||||
for (const i of coordinates.keys()) {
|
||||
await utils.waitForWebsocketEvent({ event: 'assetUpdate', id: assets[i].id });
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ describe(`immich login`, () => {
|
||||
it('should login and save auth.yml with 600', async () => {
|
||||
const admin = await utils.adminSetup();
|
||||
const key = await utils.createApiKey(admin.accessToken, [Permission.All]);
|
||||
const { stdout, stderr, exitCode } = await immichCli(['login', app, `${key.secret}`]);
|
||||
const { stdout, stderr, exitCode } = await immichCli(['login', app, key.secret]);
|
||||
expect(stdout.split('\n')).toEqual([
|
||||
'Logging in to http://127.0.0.1:2285/api',
|
||||
'Logged in as admin@immich.cloud',
|
||||
@@ -48,7 +48,7 @@ describe(`immich login`, () => {
|
||||
it('should login without /api in the url', async () => {
|
||||
const admin = await utils.adminSetup();
|
||||
const key = await utils.createApiKey(admin.accessToken, [Permission.All]);
|
||||
const { stdout, stderr, exitCode } = await immichCli(['login', app.replaceAll('/api', ''), `${key.secret}`]);
|
||||
const { stdout, stderr, exitCode } = await immichCli(['login', app.replaceAll('/api', ''), key.secret]);
|
||||
expect(stdout.split('\n')).toEqual([
|
||||
'Logging in to http://127.0.0.1:2285',
|
||||
'Discovered API at http://127.0.0.1:2285/api',
|
||||
|
||||
@@ -119,7 +119,9 @@ describe(`immich upload`, () => {
|
||||
const baseDir = `/tmp/upload/`;
|
||||
|
||||
const testPaths = Object.keys(files).map((filePath) => `${baseDir}/${filePath}`);
|
||||
testPaths.map((filePath) => utils.createImageFile(filePath));
|
||||
for (const filePath of testPaths) {
|
||||
utils.createImageFile(filePath);
|
||||
}
|
||||
|
||||
const commandLine = paths.map((argument) => `${baseDir}/${argument}`);
|
||||
|
||||
@@ -135,7 +137,9 @@ describe(`immich upload`, () => {
|
||||
const assets = await getAssetStatistics({}, { headers: asKeyAuth(key) });
|
||||
expect(assets.total).toBe(expectedCount);
|
||||
|
||||
testPaths.map((filePath) => utils.removeImageFile(filePath));
|
||||
for (const filePath of testPaths) {
|
||||
utils.removeImageFile(filePath);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ export const randomImageFromString = async (
|
||||
let seedNumber = 0;
|
||||
for (let i = 0; i < seed.length; i++) {
|
||||
seedNumber = (seedNumber << 5) - seedNumber + (seed.codePointAt(i) ?? 0);
|
||||
seedNumber = seedNumber & seedNumber; // Convert to 32bit integer
|
||||
seedNumber &= seedNumber; // Convert to 32bit integer
|
||||
}
|
||||
return randomImage(new SeededRandom(Math.abs(seedNumber)), { width, height });
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ export function generateAsset(
|
||||
const asset: MockTimelineAsset = {
|
||||
id: assetId,
|
||||
ownerId,
|
||||
ratio: Number.parseFloat(ratio.split(':')[0]) / Number.parseFloat(ratio.split(':')[1]),
|
||||
ratio: Number(ratio.split(':', 1)[0]) / Number(ratio.split(':', 2)[1]),
|
||||
thumbhash: generateThumbhash(rng),
|
||||
localDateTime: date.toISOString(),
|
||||
fileCreatedAt: date.toISOString(),
|
||||
@@ -214,7 +214,7 @@ export function generateTimelineData(config: TimelineConfig): MockTimelineData {
|
||||
}
|
||||
|
||||
// Create a mock album from random assets
|
||||
const allAssets = [...buckets.values()].flat();
|
||||
const allAssets = buckets.values().toArray().flat();
|
||||
|
||||
// Select 10-30 random assets for the album (or all assets if less than 10)
|
||||
const albumSize = Math.min(allAssets.length, globalRng.nextInt(10, 31));
|
||||
|
||||
@@ -172,11 +172,7 @@ function shouldIncludeAsset(
|
||||
if (isArchived !== undefined && actuallyArchived !== isArchived) {
|
||||
return false;
|
||||
}
|
||||
if (isFavorite !== undefined && actuallyFavorited !== isFavorite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return isFavorite === undefined || actuallyFavorited === isFavorite;
|
||||
}
|
||||
/**
|
||||
* Get summary for all buckets (mimics getTimeBuckets API)
|
||||
@@ -361,7 +357,7 @@ export function getAsset(
|
||||
owner?: UserResponseDto,
|
||||
): AssetResponseDto | undefined {
|
||||
// Search through all buckets for the asset
|
||||
const buckets = [...timelineData.buckets.values()];
|
||||
const buckets = timelineData.buckets.values().toArray();
|
||||
for (const assets of buckets) {
|
||||
const asset = assets.find((a) => a.id === assetId);
|
||||
if (asset) {
|
||||
@@ -395,7 +391,7 @@ export function getAlbum(
|
||||
|
||||
// Get the actual asset objects from the timeline data
|
||||
const albumAssets: AssetResponseDto[] = [];
|
||||
const allAssets = [...timelineData.buckets.values()].flat();
|
||||
const allAssets = timelineData.buckets.values().toArray().flat();
|
||||
|
||||
for (const assetId of album.assetIds) {
|
||||
const assetConfig = allAssets.find((a) => a.id === assetId);
|
||||
|
||||
@@ -143,7 +143,7 @@ export function validateTimelineConfig(config: TimelineConfig): void {
|
||||
}
|
||||
|
||||
// Validate seed if provided
|
||||
if (config.seed !== undefined && (config.seed < 0 || !Number.isInteger(config.seed))) {
|
||||
if (config.seed !== undefined && (config.seed < 0 || !Number.isSafeInteger(config.seed))) {
|
||||
throw new Error('Seed must be a non-negative integer');
|
||||
}
|
||||
|
||||
|
||||
@@ -153,11 +153,8 @@ export function getMockAsset(
|
||||
const isInDifferentPeriod = (date1: DateTime, date2: DateTime): boolean => {
|
||||
if (unit === 'day') {
|
||||
return !date1.startOf('day').equals(date2.startOf('day'));
|
||||
} else if (unit === 'month') {
|
||||
return date1.year !== date2.year || date1.month !== date2.month;
|
||||
} else {
|
||||
return date1.year !== date2.year;
|
||||
}
|
||||
return unit === 'month' ? date1.year !== date2.year || date1.month !== date2.month : date1.year !== date2.year;
|
||||
};
|
||||
|
||||
if (direction === 'next') {
|
||||
|
||||
@@ -40,7 +40,8 @@ export const setupTimelineMockApiRoutes = async (
|
||||
contentType: 'application/json',
|
||||
json: getTimeBuckets(timelineRestData, isTrashed, isArchived, isFavorite, albumId, changes),
|
||||
});
|
||||
} else if (pathname === '/api/timeline/bucket') {
|
||||
}
|
||||
if (pathname === '/api/timeline/bucket') {
|
||||
const timeBucket = url.searchParams.get('timeBucket');
|
||||
if (!timeBucket) {
|
||||
return route.continue();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable unicorn/no-this-outside-of-class */
|
||||
import type { AssetResponseDto } from '@immich/sdk';
|
||||
import { expect, Page } from '@playwright/test';
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ export const thumbnailUtils = {
|
||||
},
|
||||
async queryThumbnailInViewport(page: Page, collector: (assetId: string) => boolean) {
|
||||
const assetIds: string[] = [];
|
||||
// eslint-disable-next-line unicorn/no-this-outside-of-class
|
||||
for (const thumb of await this.locator(page).all()) {
|
||||
const box = await thumb.boundingBox();
|
||||
if (box) {
|
||||
@@ -151,6 +152,7 @@ export const timelineUtils = {
|
||||
page.evaluate(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
|
||||
return document.querySelector('#asset-grid').scrollTop;
|
||||
});
|
||||
await expect.poll(queryTop).toBeGreaterThan(0);
|
||||
@@ -177,6 +179,7 @@ export const assetViewerUtils = {
|
||||
page.evaluate(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line unicorn/no-optional-chaining-on-undeclared-variable
|
||||
return document.activeElement?.dataset?.asset;
|
||||
});
|
||||
await expect(poll(page, activeElement, (result) => result === assetId)).resolves.toBe(assetId);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable unicorn/no-top-level-assignment-in-function */
|
||||
import {
|
||||
AssetMediaCreateDto,
|
||||
AssetMediaResponseDto,
|
||||
@@ -177,7 +178,7 @@ export const utils = {
|
||||
resetDatabase: async (tables?: string[]) => {
|
||||
client = await utils.connectDatabase();
|
||||
|
||||
tables = tables || [
|
||||
tables ||= [
|
||||
// TODO e2e test for deleting a stack, since it is quite complex
|
||||
'stack',
|
||||
'library',
|
||||
@@ -304,7 +305,7 @@ export const utils = {
|
||||
},
|
||||
|
||||
adminSetup: async (options?: AdminSetupOptions) => {
|
||||
options = options || { onboarding: true };
|
||||
options ||= { onboarding: true };
|
||||
|
||||
await signUpAdmin({ signUpDto: signupDto.admin });
|
||||
const response = await login({ loginCredentialDto: loginDto.admin });
|
||||
@@ -545,6 +546,7 @@ export const utils = {
|
||||
{
|
||||
headers: asBearerAuth(accessToken),
|
||||
fetch: (...args: Parameters<typeof fetch>) =>
|
||||
// eslint-disable-next-line unicorn/no-invalid-argument-count, unicorn/prefer-await
|
||||
fetch(...args).then((response) => {
|
||||
setCookie = response.headers.getSetCookie();
|
||||
return response;
|
||||
@@ -674,7 +676,7 @@ export const utils = {
|
||||
|
||||
cliLogin: async (accessToken: string) => {
|
||||
const key = await utils.createApiKey(accessToken, [Permission.All]);
|
||||
await immichCli(['login', app, `${key.secret}`]);
|
||||
await immichCli(['login', app, key.secret]);
|
||||
return key.secret;
|
||||
},
|
||||
|
||||
@@ -706,6 +708,7 @@ export const utils = {
|
||||
},
|
||||
};
|
||||
|
||||
// eslint-disable-next-line unicorn/no-top-level-side-effects
|
||||
utils.initSdk();
|
||||
|
||||
if (!existsSync(`${testAssetDir}/albums`)) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"target": "es2023",
|
||||
"lib": ["dom", "ESNext"],
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"incremental": true,
|
||||
|
||||
@@ -12,7 +12,6 @@ config_roots = [
|
||||
"docs",
|
||||
".github",
|
||||
"machine-learning",
|
||||
"native",
|
||||
]
|
||||
|
||||
[tools]
|
||||
|
||||
13
mobile/android/app/CMakeLists.txt
Normal file
13
mobile/android/app/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
project(native_buffer LANGUAGES C)
|
||||
|
||||
add_library(native_buffer SHARED
|
||||
src/main/cpp/native_buffer.c
|
||||
src/main/cpp/native_image.c
|
||||
)
|
||||
|
||||
target_link_libraries(native_buffer jnigraphics)
|
||||
@@ -77,6 +77,11 @@ android {
|
||||
}
|
||||
namespace 'app.alextran.immich'
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
|
||||
52
mobile/android/app/src/main/cpp/native_buffer.c
Normal file
52
mobile/android/app/src/main/cpp/native_buffer.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_app_alextran_immich_NativeBuffer_allocate(
|
||||
JNIEnv *env, jclass clazz, jint size) {
|
||||
void *ptr = malloc(size);
|
||||
return (jlong) ptr;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_alextran_immich_NativeBuffer_free(
|
||||
JNIEnv *env, jclass clazz, jlong address) {
|
||||
free((void *) address);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_app_alextran_immich_NativeBuffer_realloc(
|
||||
JNIEnv *env, jclass clazz, jlong address, jint size) {
|
||||
void *ptr = realloc((void *) address, size);
|
||||
return (jlong) ptr;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_app_alextran_immich_NativeBuffer_wrap(
|
||||
JNIEnv *env, jclass clazz, jlong address, jint capacity) {
|
||||
return (*env)->NewDirectByteBuffer(env, (void *) address, capacity);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_alextran_immich_NativeBuffer_copy(
|
||||
JNIEnv *env, jclass clazz, jobject buffer, jlong destAddress, jint offset, jint length) {
|
||||
void *src = (*env)->GetDirectBufferAddress(env, buffer);
|
||||
if (src != NULL) {
|
||||
memcpy((void *) destAddress, (char *) src + offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JNI global reference to the given object and returns its address.
|
||||
* The caller is responsible for deleting the global reference when it's no longer needed.
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_app_alextran_immich_NativeBuffer_createGlobalRef(JNIEnv *env, jobject clazz, jobject obj) {
|
||||
if (obj == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
jobject globalRef = (*env)->NewGlobalRef(env, obj);
|
||||
return (jlong) globalRef;
|
||||
}
|
||||
173
mobile/android/app/src/main/cpp/native_image.c
Normal file
173
mobile/android/app/src/main/cpp/native_image.c
Normal file
@@ -0,0 +1,173 @@
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <android/bitmap.h>
|
||||
|
||||
// Cache-friendly block size for the tiled rotation (in pixels). 32x32 uint32 = 4KB, fits L1.
|
||||
#define TILE 32
|
||||
|
||||
// EXIF orientation values (androidx.exifinterface.media.ExifInterface.ORIENTATION_*).
|
||||
enum {
|
||||
ORIENTATION_FLIP_HORIZONTAL = 2,
|
||||
ORIENTATION_ROTATE_180 = 3,
|
||||
ORIENTATION_FLIP_VERTICAL = 4,
|
||||
ORIENTATION_TRANSPOSE = 5,
|
||||
ORIENTATION_ROTATE_90 = 6,
|
||||
ORIENTATION_TRANSVERSE = 7,
|
||||
ORIENTATION_ROTATE_270 = 8,
|
||||
};
|
||||
|
||||
// The orientations that swap width and height. Must stay in sync with affine_for's dim usage.
|
||||
static int swaps_dims(int o) {
|
||||
return o == ORIENTATION_ROTATE_90 || o == ORIENTATION_ROTATE_270 ||
|
||||
o == ORIENTATION_TRANSPOSE || o == ORIENTATION_TRANSVERSE;
|
||||
}
|
||||
|
||||
// A source pixel (sx, sy) maps to destination index base + sx*stepX + sy*stepY, where dw is the
|
||||
// destination width. This affine form covers all 8 EXIF orientations and matches the pixel layout
|
||||
// of Bitmap.createBitmap(src, matrixForExifOrientation(o)). int64_t so it stays correct on
|
||||
// armeabi-v7a (32-bit long) regardless of how large MAX_RAW_DECODE_PIXELS grows.
|
||||
static void affine_for(int o, int sw, int sh, int dw, int64_t *base, int64_t *stepX, int64_t *stepY) {
|
||||
switch (o) {
|
||||
case ORIENTATION_ROTATE_90: *base = sh - 1; *stepX = dw; *stepY = -1; break;
|
||||
case ORIENTATION_ROTATE_270: *base = (int64_t) (sw - 1) * dw; *stepX = -dw; *stepY = 1; break;
|
||||
case ORIENTATION_ROTATE_180: *base = (int64_t) (sh - 1) * dw + (sw - 1); *stepX = -1; *stepY = -dw; break;
|
||||
case ORIENTATION_FLIP_HORIZONTAL: *base = sw - 1; *stepX = -1; *stepY = dw; break;
|
||||
case ORIENTATION_FLIP_VERTICAL: *base = (int64_t) (sh - 1) * dw; *stepX = 1; *stepY = -dw; break;
|
||||
case ORIENTATION_TRANSPOSE: *base = 0; *stepX = dw; *stepY = 1; break;
|
||||
case ORIENTATION_TRANSVERSE: *base = (int64_t) (sw - 1) * dw + (sh - 1); *stepX = -dw; *stepY = -1; break;
|
||||
default: *base = 0; *stepX = 1; *stepY = dw; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy each source pixel (whole uint32, so channel order/premult is irrelevant) to its rotated
|
||||
// destination, walking TILE x TILE blocks so the scattered writes of a 90/270 transpose stay
|
||||
// cache-resident. dst is densely packed (rowBytes == dw*4, no padding), which the affine math relies on.
|
||||
static void rotate_tiled(const uint8_t *src, int srcStride, uint32_t *dst,
|
||||
int sw, int sh, int64_t base, int64_t stepX, int64_t stepY) {
|
||||
for (int ty = 0; ty < sh; ty += TILE) {
|
||||
int yEnd = ty + TILE < sh ? ty + TILE : sh;
|
||||
for (int tx = 0; tx < sw; tx += TILE) {
|
||||
int xEnd = tx + TILE < sw ? tx + TILE : sw;
|
||||
for (int sy = ty; sy < yEnd; sy++) {
|
||||
const uint32_t *srcRow = (const uint32_t *) (src + (size_t) sy * srcStride);
|
||||
int64_t idx = base + (int64_t) sy * stepY + (int64_t) tx * stepX;
|
||||
for (int sx = tx; sx < xEnd; sx++) {
|
||||
dst[idx] = srcRow[sx];
|
||||
idx += stepX;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rotates an RGBA_8888 bitmap to the given EXIF orientation into a freshly malloc'd buffer (free it
|
||||
// via NativeBuffer.free). Fills outInfo with {width, height, rowBytes} and returns the buffer
|
||||
// address, or 0 if the bitmap can't be handled (e.g. a non-8888 format) so the caller can fall back.
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_app_alextran_immich_NativeImage_rotate(
|
||||
JNIEnv *env, jclass clazz, jobject bitmap, jint orientation, jintArray outInfo) {
|
||||
AndroidBitmapInfo info;
|
||||
if (AndroidBitmap_getInfo(env, bitmap, &info) != ANDROID_BITMAP_RESULT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sw = (int) info.width;
|
||||
int sh = (int) info.height;
|
||||
int dw = swaps_dims(orientation) ? sh : sw;
|
||||
int dh = swaps_dims(orientation) ? sw : sh;
|
||||
|
||||
uint32_t *dst = (uint32_t *) malloc((size_t) dw * dh * 4);
|
||||
if (dst == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *srcPixels = NULL;
|
||||
if (AndroidBitmap_lockPixels(env, bitmap, &srcPixels) != ANDROID_BITMAP_RESULT_SUCCESS) {
|
||||
free(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t base, stepX, stepY;
|
||||
affine_for(orientation, sw, sh, dw, &base, &stepX, &stepY);
|
||||
rotate_tiled((const uint8_t *) srcPixels, (int) info.stride, dst, sw, sh, base, stepX, stepY);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
|
||||
jint dims[3] = {dw, dh, dw * 4};
|
||||
(*env)->SetIntArrayRegion(env, outInfo, 0, 3, dims);
|
||||
// Keep ownership in C until the buffer is safely handed back: if outInfo was somehow too small,
|
||||
// SetIntArrayRegion left a pending exception and Kotlin will never receive (or free) dst.
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
free(dst);
|
||||
return 0;
|
||||
}
|
||||
return (jlong) dst;
|
||||
}
|
||||
|
||||
// Convert an RGBA_1010102 buffer to densely-packed RGBA_8888, matching Skia's
|
||||
// Bitmap.copy(ARGB_8888) byte-for-byte so it's a drop-in for the intermediate 8888 bitmap.
|
||||
// Each source pixel is a native (little-endian on every Android ABI) u32 with R in bits 0-9,
|
||||
// G in 10-19, B in 20-29, A in 30-31 (standard RGB10_A2). Each 10-bit channel maps to 8-bit via
|
||||
// round(v*255/1023). The 2-bit alpha maps to a*85. Both are kept as plain arithmetic as the whole
|
||||
// loop auto-vectorizes to NEON and measures faster than a LUT on-device. Output is R,G,B,A bytes
|
||||
// per pixel, i.e. Android ARGB_8888 memory == Dart PixelFormat.rgba8888.
|
||||
static void convert_1010102(const uint8_t *src, int srcStride, uint32_t *dst, int w, int h) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
const uint32_t *srcRow = (const uint32_t *) (src + (size_t) y * srcStride);
|
||||
uint32_t *dstRow = dst + (size_t) y * w;
|
||||
for (int x = 0; x < w; x++) {
|
||||
uint32_t px = srcRow[x];
|
||||
uint32_t r = ((px & 0x3FF) * 16336u + 32768u) >> 16;
|
||||
uint32_t g = (((px >> 10) & 0x3FF) * 16336u + 32768u) >> 16;
|
||||
uint32_t b = (((px >> 20) & 0x3FF) * 16336u + 32768u) >> 16;
|
||||
uint32_t a = ((px >> 30) & 0x3) * 85u;
|
||||
dstRow[x] = r | (g << 8) | (b << 16) | (a << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Converts an RGBA_1010102 bitmap (what a 10-bit HEIC/AVIF decodes to on API 33+) into a freshly
|
||||
// malloc'd RGBA_8888 buffer. Fills outInfo with {width, height, rowBytes} and returns the buffer
|
||||
// address, or 0 (so the caller falls back to a Skia copy) if the bitmap isn't 1010102 or can't be
|
||||
// locked. Same ownership contract as rotate: free the returned buffer via NativeBuffer.free.
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_app_alextran_immich_NativeImage_convert1010102(
|
||||
JNIEnv *env, jclass clazz, jobject bitmap, jintArray outInfo) {
|
||||
AndroidBitmapInfo info;
|
||||
if (AndroidBitmap_getInfo(env, bitmap, &info) != ANDROID_BITMAP_RESULT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_1010102) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w = (int) info.width;
|
||||
int h = (int) info.height;
|
||||
|
||||
uint32_t *dst = (uint32_t *) malloc((size_t) w * h * 4);
|
||||
if (dst == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *srcPixels = NULL;
|
||||
if (AndroidBitmap_lockPixels(env, bitmap, &srcPixels) != ANDROID_BITMAP_RESULT_SUCCESS) {
|
||||
free(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
convert_1010102((const uint8_t *) srcPixels, (int) info.stride, dst, w, h);
|
||||
|
||||
AndroidBitmap_unlockPixels(env, bitmap);
|
||||
|
||||
jint dims[3] = {w, h, w * 4};
|
||||
(*env)->SetIntArrayRegion(env, outInfo, 0, 3, dims);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
free(dst);
|
||||
return 0;
|
||||
}
|
||||
return (jlong) dst;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ const val INITIAL_BUFFER_SIZE = 32 * 1024
|
||||
|
||||
object NativeBuffer {
|
||||
init {
|
||||
System.loadLibrary("immich_core_ffi")
|
||||
System.loadLibrary("native_buffer")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -21,6 +21,9 @@ object NativeBuffer {
|
||||
@JvmStatic
|
||||
external fun wrap(address: Long, capacity: Int): ByteBuffer
|
||||
|
||||
@JvmStatic
|
||||
external fun copy(buffer: ByteBuffer, destAddress: Long, offset: Int, length: Int)
|
||||
|
||||
@JvmStatic
|
||||
external fun createGlobalRef(obj: Any): Long
|
||||
}
|
||||
@@ -32,12 +35,8 @@ class NativeByteBuffer(initialCapacity: Int) {
|
||||
|
||||
inline fun ensureHeadroom() {
|
||||
if (offset == capacity) {
|
||||
check(capacity <= Int.MAX_VALUE / 2) { "Native buffer capacity overflow" }
|
||||
val newCapacity = capacity * 2
|
||||
val newPointer = NativeBuffer.realloc(pointer, newCapacity)
|
||||
check(newPointer != 0L) { "Native buffer realloc failed" }
|
||||
pointer = newPointer
|
||||
capacity = newCapacity
|
||||
capacity *= 2
|
||||
pointer = NativeBuffer.realloc(pointer, capacity)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,27 +4,26 @@ import android.graphics.Bitmap
|
||||
|
||||
object NativeImage {
|
||||
init {
|
||||
System.loadLibrary("immich_core_ffi")
|
||||
// rotate() is compiled into the native_buffer shared lib (which already links jnigraphics).
|
||||
System.loadLibrary("native_buffer")
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates an RGBA_8888 [bitmap] and returns a malloc'd buffer, or 0 on failure.
|
||||
* [outInfo] receives width, height, and row bytes.
|
||||
* Rotates an RGBA_8888 [bitmap] to the given EXIF [orientation], writing the result into a freshly
|
||||
* malloc'd native buffer. Returns the buffer address (free it with [NativeBuffer.free]) and fills
|
||||
* [outInfo] with {width, height, rowBytes}. Returns 0 when the bitmap can't be handled (e.g. a
|
||||
* non-8888 config) so the caller can fall back.
|
||||
*/
|
||||
@JvmStatic
|
||||
external fun rotate(bitmap: Bitmap, orientation: Int, outInfo: IntArray): Long
|
||||
|
||||
/**
|
||||
* Converts an RGBA_1010102 [bitmap] to RGBA_8888 and returns a malloc'd buffer, or 0 on failure.
|
||||
* [outInfo] receives width, height, and row bytes.
|
||||
* Converts an RGBA_1010102 [bitmap] (what a 10-bit HEIC/AVIF decodes to on API 33+) to RGBA_8888,
|
||||
* writing the result into a freshly malloc'd native buffer in one pass, with no intermediate
|
||||
* ARGB_8888 bitmap. Returns the buffer address (free it with [NativeBuffer.free]) and fills
|
||||
* [outInfo] with {width, height, rowBytes}. Returns 0 when the bitmap isn't RGBA_1010102 so the
|
||||
* caller can fall back to a Skia copy.
|
||||
*/
|
||||
@JvmStatic
|
||||
external fun convert1010102(bitmap: Bitmap, outInfo: IntArray): Long
|
||||
|
||||
/**
|
||||
* Decodes a ThumbHash into a malloc'd RGBA_8888 buffer, or 0 on failure.
|
||||
* [outInfo] receives width, height, and row bytes.
|
||||
*/
|
||||
@JvmStatic
|
||||
external fun thumbhash(hash: ByteArray, outInfo: IntArray): Long
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.provider.MediaStore.Video
|
||||
import android.util.Size
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import app.alextran.immich.BuildConfig
|
||||
import app.alextran.immich.NativeBuffer
|
||||
import app.alextran.immich.NativeImage
|
||||
import kotlin.math.*
|
||||
@@ -50,23 +49,17 @@ fun Bitmap.toNativeBuffer(): Map<String, Long> {
|
||||
// Dart reads the buffer as rgba8888, but 10-bit sources decode to RGBA_1010102, which garbles
|
||||
// colors when copied verbatim. Convert those straight into the output buffer in native code -
|
||||
// one pass, no intermediate ARGB_8888 bitmap.
|
||||
val source1010102 =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && config == Bitmap.Config.RGBA_1010102
|
||||
if (source1010102) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && config == Bitmap.Config.RGBA_1010102) {
|
||||
val info = IntArray(3)
|
||||
val pointer = NativeImage.convert1010102(this, info)
|
||||
if (pointer != 0L) {
|
||||
recycle()
|
||||
return buildMap {
|
||||
put("pointer", pointer)
|
||||
put("width", info[0].toLong())
|
||||
put("height", info[1].toLong())
|
||||
put("rowBytes", info[2].toLong())
|
||||
if (BuildConfig.DEBUG) {
|
||||
put("source1010102", 1L)
|
||||
put("converted1010102", 1L)
|
||||
}
|
||||
}
|
||||
return mapOf(
|
||||
"pointer" to pointer,
|
||||
"width" to info[0].toLong(),
|
||||
"height" to info[1].toLong(),
|
||||
"rowBytes" to info[2].toLong()
|
||||
)
|
||||
}
|
||||
// native convert declined (OOM/lock) -> fall through to the Skia copy path below.
|
||||
}
|
||||
@@ -77,16 +70,12 @@ fun Bitmap.toNativeBuffer(): Map<String, Long> {
|
||||
try {
|
||||
val buffer = NativeBuffer.wrap(pointer, size)
|
||||
bitmap.copyPixelsToBuffer(buffer)
|
||||
return buildMap {
|
||||
put("pointer", pointer)
|
||||
put("width", bitmap.width.toLong())
|
||||
put("height", bitmap.height.toLong())
|
||||
put("rowBytes", (bitmap.width * 4).toLong())
|
||||
if (BuildConfig.DEBUG) {
|
||||
put("source1010102", if (source1010102) 1L else 0L)
|
||||
put("converted1010102", 0L)
|
||||
}
|
||||
}
|
||||
return mapOf(
|
||||
"pointer" to pointer,
|
||||
"width" to bitmap.width.toLong(),
|
||||
"height" to bitmap.height.toLong(),
|
||||
"rowBytes" to (bitmap.width * 4).toLong()
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
NativeBuffer.free(pointer)
|
||||
throw e
|
||||
@@ -112,14 +101,12 @@ class LocalImagesImpl(context: Context) : LocalImageApi {
|
||||
threadPool.execute {
|
||||
try {
|
||||
val bytes = Base64.getDecoder().decode(thumbhash)
|
||||
val info = IntArray(3)
|
||||
val pointer = NativeImage.thumbhash(bytes, info)
|
||||
require(pointer != 0L) { "Invalid thumbhash" }
|
||||
val image = ThumbHash.thumbHashToRGBA(bytes)
|
||||
val res = mapOf(
|
||||
"pointer" to pointer,
|
||||
"width" to info[0].toLong(),
|
||||
"height" to info[1].toLong(),
|
||||
"rowBytes" to info[2].toLong()
|
||||
"pointer" to image.pointer,
|
||||
"width" to image.width.toLong(),
|
||||
"height" to image.height.toLong(),
|
||||
"rowBytes" to (image.width * 4).toLong()
|
||||
)
|
||||
callback(Result.success(res))
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
package app.alextran.immich.images;
|
||||
|
||||
// Copyright (c) 2023 Evan Wallace
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import app.alextran.immich.NativeBuffer;
|
||||
|
||||
// modified to use native allocations
|
||||
public final class ThumbHash {
|
||||
/**
|
||||
* Decodes a ThumbHash to an RGBA image. RGB is not be premultiplied by A.
|
||||
*
|
||||
* @param hash The bytes of the ThumbHash.
|
||||
* @return The width, height, and pixels of the rendered placeholder image.
|
||||
*/
|
||||
public static Image thumbHashToRGBA(byte[] hash) {
|
||||
// Read the constants
|
||||
int header24 = (hash[0] & 255) | ((hash[1] & 255) << 8) | ((hash[2] & 255) << 16);
|
||||
int header16 = (hash[3] & 255) | ((hash[4] & 255) << 8);
|
||||
float l_dc = (float) (header24 & 63) / 63.0f;
|
||||
float p_dc = (float) ((header24 >> 6) & 63) / 31.5f - 1.0f;
|
||||
float q_dc = (float) ((header24 >> 12) & 63) / 31.5f - 1.0f;
|
||||
float l_scale = (float) ((header24 >> 18) & 31) / 31.0f;
|
||||
boolean hasAlpha = (header24 >> 23) != 0;
|
||||
float p_scale = (float) ((header16 >> 3) & 63) / 63.0f;
|
||||
float q_scale = (float) ((header16 >> 9) & 63) / 63.0f;
|
||||
boolean isLandscape = (header16 >> 15) != 0;
|
||||
int lx = Math.max(3, isLandscape ? hasAlpha ? 5 : 7 : header16 & 7);
|
||||
int ly = Math.max(3, isLandscape ? header16 & 7 : hasAlpha ? 5 : 7);
|
||||
float a_dc = hasAlpha ? (float) (hash[5] & 15) / 15.0f : 1.0f;
|
||||
float a_scale = (float) ((hash[5] >> 4) & 15) / 15.0f;
|
||||
|
||||
// Read the varying factors (boost saturation by 1.25x to compensate for quantization)
|
||||
int ac_start = hasAlpha ? 6 : 5;
|
||||
int ac_index = 0;
|
||||
Channel l_channel = new Channel(lx, ly);
|
||||
Channel p_channel = new Channel(3, 3);
|
||||
Channel q_channel = new Channel(3, 3);
|
||||
Channel a_channel = null;
|
||||
ac_index = l_channel.decode(hash, ac_start, ac_index, l_scale);
|
||||
ac_index = p_channel.decode(hash, ac_start, ac_index, p_scale * 1.25f);
|
||||
ac_index = q_channel.decode(hash, ac_start, ac_index, q_scale * 1.25f);
|
||||
if (hasAlpha) {
|
||||
a_channel = new Channel(5, 5);
|
||||
a_channel.decode(hash, ac_start, ac_index, a_scale);
|
||||
}
|
||||
float[] l_ac = l_channel.ac;
|
||||
float[] p_ac = p_channel.ac;
|
||||
float[] q_ac = q_channel.ac;
|
||||
float[] a_ac = hasAlpha ? a_channel.ac : null;
|
||||
|
||||
// Decode using the DCT into RGB
|
||||
float ratio = thumbHashToApproximateAspectRatio(hash);
|
||||
int w = Math.round(ratio > 1.0f ? 32.0f : 32.0f * ratio);
|
||||
int h = Math.round(ratio > 1.0f ? 32.0f / ratio : 32.0f);
|
||||
int size = w * h * 4;
|
||||
long pointer = NativeBuffer.allocate(size);
|
||||
ByteBuffer rgba = NativeBuffer.wrap(pointer, size);
|
||||
int cx_stop = Math.max(lx, hasAlpha ? 5 : 3);
|
||||
int cy_stop = Math.max(ly, hasAlpha ? 5 : 3);
|
||||
float[] fx = new float[cx_stop];
|
||||
float[] fy = new float[cy_stop];
|
||||
for (int y = 0, i = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++, i += 4) {
|
||||
float l = l_dc, p = p_dc, q = q_dc, a = a_dc;
|
||||
|
||||
// Precompute the coefficients
|
||||
for (int cx = 0; cx < cx_stop; cx++)
|
||||
fx[cx] = (float) Math.cos(Math.PI / w * (x + 0.5f) * cx);
|
||||
for (int cy = 0; cy < cy_stop; cy++)
|
||||
fy[cy] = (float) Math.cos(Math.PI / h * (y + 0.5f) * cy);
|
||||
|
||||
// Decode L
|
||||
for (int cy = 0, j = 0; cy < ly; cy++) {
|
||||
float fy2 = fy[cy] * 2.0f;
|
||||
for (int cx = cy > 0 ? 0 : 1; cx * ly < lx * (ly - cy); cx++, j++)
|
||||
l += l_ac[j] * fx[cx] * fy2;
|
||||
}
|
||||
|
||||
// Decode P and Q
|
||||
for (int cy = 0, j = 0; cy < 3; cy++) {
|
||||
float fy2 = fy[cy] * 2.0f;
|
||||
for (int cx = cy > 0 ? 0 : 1; cx < 3 - cy; cx++, j++) {
|
||||
float f = fx[cx] * fy2;
|
||||
p += p_ac[j] * f;
|
||||
q += q_ac[j] * f;
|
||||
}
|
||||
}
|
||||
|
||||
// Decode A
|
||||
if (hasAlpha)
|
||||
for (int cy = 0, j = 0; cy < 5; cy++) {
|
||||
float fy2 = fy[cy] * 2.0f;
|
||||
for (int cx = cy > 0 ? 0 : 1; cx < 5 - cy; cx++, j++)
|
||||
a += a_ac[j] * fx[cx] * fy2;
|
||||
}
|
||||
|
||||
// Convert to RGB
|
||||
float b = l - 2.0f / 3.0f * p;
|
||||
float r = (3.0f * l - b + q) / 2.0f;
|
||||
float g = r - q;
|
||||
rgba.put(i, (byte) Math.max(0, Math.round(255.0f * Math.min(1, r))));
|
||||
rgba.put(i + 1, (byte) Math.max(0, Math.round(255.0f * Math.min(1, g))));
|
||||
rgba.put(i + 2, (byte) Math.max(0, Math.round(255.0f * Math.min(1, b))));
|
||||
rgba.put(i + 3, (byte) Math.max(0, Math.round(255.0f * Math.min(1, a))));
|
||||
}
|
||||
}
|
||||
return new Image(w, h, pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the approximate aspect ratio of the original image.
|
||||
*
|
||||
* @param hash The bytes of the ThumbHash.
|
||||
* @return The approximate aspect ratio (i.e. width / height).
|
||||
*/
|
||||
public static float thumbHashToApproximateAspectRatio(byte[] hash) {
|
||||
byte header = hash[3];
|
||||
boolean hasAlpha = (hash[2] & 0x80) != 0;
|
||||
boolean isLandscape = (hash[4] & 0x80) != 0;
|
||||
int lx = isLandscape ? hasAlpha ? 5 : 7 : header & 7;
|
||||
int ly = isLandscape ? header & 7 : hasAlpha ? 5 : 7;
|
||||
return (float) lx / (float) ly;
|
||||
}
|
||||
|
||||
public static final class Image {
|
||||
public int width;
|
||||
public int height;
|
||||
public long pointer;
|
||||
|
||||
public Image(int width, int height, long pointer) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.pointer = pointer;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Channel {
|
||||
int nx;
|
||||
int ny;
|
||||
float[] ac;
|
||||
|
||||
Channel(int nx, int ny) {
|
||||
this.nx = nx;
|
||||
this.ny = ny;
|
||||
int n = 0;
|
||||
for (int cy = 0; cy < ny; cy++)
|
||||
for (int cx = cy > 0 ? 0 : 1; cx * ny < nx * (ny - cy); cx++)
|
||||
n++;
|
||||
ac = new float[n];
|
||||
}
|
||||
|
||||
int decode(byte[] hash, int start, int index, float scale) {
|
||||
for (int i = 0; i < ac.length; i++) {
|
||||
int data = hash[start + (index >> 1)] >> ((index & 1) << 2);
|
||||
ac[i] = ((float) (data & 15) / 7.5f - 1.0f) * scale;
|
||||
index++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void main() {
|
||||
|
||||
void sendUser(SyncStream stream, String id, String name) {
|
||||
stream.send(
|
||||
type: SyncEntityType.userV1.value,
|
||||
type: SyncEntityType.userV1.toString(),
|
||||
data: SyncUserV1(
|
||||
id: id,
|
||||
name: name,
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_native_core/immich_native_core.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
Uint8List _px1010102(int r, int g, int b, int a) {
|
||||
final px = (r & 0x3FF) | ((g & 0x3FF) << 10) | ((b & 0x3FF) << 20) | ((a & 0x3) << 30);
|
||||
return Uint8List(4)..buffer.asByteData().setUint32(0, px, Endian.little);
|
||||
}
|
||||
|
||||
Uint8List? _withBuffers(
|
||||
Uint8List src,
|
||||
int dstLen,
|
||||
bool Function(Pointer<Uint8> src, int dstLen, Pointer<Uint8> dst) call,
|
||||
) {
|
||||
final srcPtr = calloc<Uint8>(src.length);
|
||||
final dstPtr = calloc<Uint8>(dstLen);
|
||||
try {
|
||||
srcPtr.asTypedList(src.length).setAll(0, src);
|
||||
if (!call(srcPtr, dstLen, dstPtr)) {
|
||||
return null;
|
||||
}
|
||||
return Uint8List.fromList(dstPtr.asTypedList(dstLen));
|
||||
} finally {
|
||||
calloc.free(srcPtr);
|
||||
calloc.free(dstPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
test('loads the native core', () {
|
||||
final ptr = immich_core_version();
|
||||
expect(ptr, isNot(equals(nullptr)));
|
||||
final version = ptr.cast<Utf8>().toDartString();
|
||||
immich_core_free_string(ptr);
|
||||
expect(version, isNotEmpty);
|
||||
});
|
||||
|
||||
test('reports swapped orientations', () {
|
||||
for (final o in [5, 6, 7, 8]) {
|
||||
expect(immich_core_orientation_swaps_dims(o), isTrue, reason: 'o=$o');
|
||||
}
|
||||
for (final o in [0, 1, 2, 3, 4, 9]) {
|
||||
expect(immich_core_orientation_swaps_dims(o), isFalse, reason: 'o=$o');
|
||||
}
|
||||
});
|
||||
|
||||
test('rotates RGBA pixels', () {
|
||||
final src = Uint8List.fromList([255, 0, 0, 255, 0, 255, 0, 255]);
|
||||
final out = _withBuffers(src, 8, (s, len, d) => immich_core_rotate_rgba8888(s, src.length, 8, 2, 1, 3, d, len));
|
||||
expect(out, [0, 255, 0, 255, 255, 0, 0, 255]);
|
||||
});
|
||||
|
||||
test('converts RGBA_1010102 pixels', () {
|
||||
// 179 and 111 distinguish rounded scaling from `>> 2`.
|
||||
final src = Uint8List.fromList([..._px1010102(1023, 0, 0, 3), ..._px1010102(179, 111, 0, 3)]);
|
||||
final out = _withBuffers(
|
||||
src,
|
||||
8,
|
||||
(s, len, d) => immich_core_rgba1010102_to_rgba8888(s, src.length, 8, 2, 1, d, len),
|
||||
);
|
||||
expect(out, isNotNull);
|
||||
expect(out!.sublist(0, 4), [255, 0, 0, 255]);
|
||||
expect(out.sublist(4, 8), [45, 28, 0, 255]);
|
||||
});
|
||||
|
||||
test('decodes a thumbhash', () {
|
||||
final hash = base64Decode('1QcSHQRnh493V4dIh4eXh1h4kJUI');
|
||||
final hashPtr = malloc<Uint8>(hash.length);
|
||||
final info = malloc<Uint32>(3);
|
||||
try {
|
||||
hashPtr.asTypedList(hash.length).setAll(0, hash);
|
||||
final ptr = immich_core_thumbhash_decode(hashPtr, hash.length, info);
|
||||
expect(ptr, isNot(equals(nullptr)));
|
||||
expect((info[0], info[1], info[2]), (23, 32, 23 * 4));
|
||||
|
||||
final len = info[0] * info[1] * 4;
|
||||
final pixels = ptr.asTypedList(len);
|
||||
for (var i = 3; i < len; i += 4) {
|
||||
expect(pixels[i], 255, reason: 'alpha at $i');
|
||||
}
|
||||
expect(pixels.toSet().length, greaterThan(2));
|
||||
malloc.free(ptr);
|
||||
|
||||
expect(immich_core_thumbhash_decode(hashPtr, 4, info), equals(nullptr));
|
||||
} finally {
|
||||
malloc.free(hashPtr);
|
||||
malloc.free(info);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/platform/local_image_api.g.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
|
||||
const _fixture10BitAvifB64 =
|
||||
'AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAAD5bWV0YQAAAAAAAAAvaGRscgAAAAAA'
|
||||
'AAAAcGljdAAAAAAAAAAAAAAAAFBpY3R1cmVIYW5kbGVyAAAAAA5waXRtAAAAAAABAAAAHmlsb2MA'
|
||||
'AAAARAAAAQABAAAAAQAAASEAAAAmAAAAKGlpbmYAAAAAAAEAAAAaaW5mZQIAAAAAAQAAYXYwMUNv'
|
||||
'bG9yAAAAAGppcHJwAAAAS2lwY28AAAAUaXNwZQAAAAAAAABAAAAAQAAAABBwaXhpAAAAAAMKCgoA'
|
||||
'AAAMYXYxQ4EATAAAAAATY29scm5jbHgAAQACAAEAAAAAF2lwbWEAAAAAAAAAAQABBAECgwQAAAAu'
|
||||
'bWRhdAoNAAAAAq//jV86AgQCCDIVEACLggAAAAAAgAAifC/LKY1kV6Bd';
|
||||
|
||||
// 16x12 linear DNG with EXIF orientation 6; the pixel strip is appended below.
|
||||
const _fixtureOrientedDngHeaderB64 =
|
||||
'SUkqAAgAAAAVAAABAwABAAAAEAAAAAEBAwABAAAADAAAAAIBAwADAAAACgEAAAMBAwABAAAAAQAAAAYBAwABAAAATIgAAAoB'
|
||||
'AwABAAAAAQAAABEBBAABAAAAvAEAABIBAwABAAAABgAAABUBAwABAAAAAwAAABYBAwABAAAADAAAABcBBAABAAAAgAQAABwB'
|
||||
'AwABAAAAAQAAACkBAwACAAAAAAABAD4BBQACAAAAEAEAAD8BBQAGAAAAIAEAABLGAQAEAAAAAQQAABPGAQAEAAAAAQEAABTG'
|
||||
'AgAMAAAAUAEAACHGCgAJAAAAXAEAACjGBQADAAAApAEAAFrGAwABAAAAFQAAAAAAAAAQABAAEAA3GqAAAAAAAiuHCgAAACAA'
|
||||
'hetRAAAAgADD9agAAAAAAs3MTAAAAAABzcxMAAAAgADNzEwAAAAAAo/C9QAAAAAQSW1taWNoIFRlc3QAAQAAAAEAAAAAAAAA'
|
||||
'AQAAAAAAAAABAAAAAAAAAAEAAAABAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAA'
|
||||
'AQAAAAEAAAABAAAA';
|
||||
|
||||
Uint8List _orientedDng() {
|
||||
final header = base64Decode(_fixtureOrientedDngHeaderB64);
|
||||
final pixels = ByteData(16 * 12 * 6);
|
||||
for (var y = 0; y < 12; y++) {
|
||||
final r = (11 - y) * 65535 ~/ 11;
|
||||
final b = y * 65535 ~/ 11;
|
||||
for (var x = 0; x < 16; x++) {
|
||||
final offset = (y * 16 + x) * 6;
|
||||
pixels.setUint16(offset, r, Endian.little);
|
||||
pixels.setUint16(offset + 2, 0, Endian.little);
|
||||
pixels.setUint16(offset + 4, b, Endian.little);
|
||||
}
|
||||
}
|
||||
return Uint8List(header.length + pixels.lengthInBytes)
|
||||
..setAll(0, header)
|
||||
..setAll(header.length, pixels.buffer.asUint8List());
|
||||
}
|
||||
|
||||
Uint8List _read(int address, int length) => Uint8List.fromList(Pointer<Uint8>.fromAddress(address).asTypedList(length));
|
||||
|
||||
void _free(int address) => malloc.free(Pointer<Uint8>.fromAddress(address));
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
if (!Platform.isAndroid) {
|
||||
return;
|
||||
}
|
||||
|
||||
final api = LocalImageApi();
|
||||
final fixture = base64Decode(_fixture10BitAvifB64);
|
||||
String? assetId;
|
||||
String? orientedAssetId;
|
||||
|
||||
setUpAll(() async {
|
||||
await PhotoManager.setIgnorePermissionCheck(true);
|
||||
final entity = await PhotoManager.editor.saveImage(fixture, filename: 'immich_jni_fixture.avif');
|
||||
assetId = entity.id;
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
final ids = [assetId, orientedAssetId].whereType<String>().toList();
|
||||
if (ids.isNotEmpty) {
|
||||
try {
|
||||
await PhotoManager.editor.deleteWithIds(ids);
|
||||
} catch (_) {}
|
||||
}
|
||||
});
|
||||
|
||||
test('thumbhash JNI roundtrip', () async {
|
||||
final a = await api.getThumbhash('1QcSHQRnh493V4dIh4eXh1h4kJUI');
|
||||
final b = await api.getThumbhash('1QcSHQRnh493V4dIh4eXh1h4kJUI');
|
||||
final (w, h, rowBytes) = (a['width']!, a['height']!, a['rowBytes']!);
|
||||
expect(a['pointer'], isNot(0));
|
||||
expect(w, inInclusiveRange(1, 128));
|
||||
expect(h, inInclusiveRange(1, 128));
|
||||
expect(rowBytes, w * 4);
|
||||
|
||||
final pixelsA = _read(a['pointer']!, rowBytes * h);
|
||||
final pixelsB = _read(b['pointer']!, rowBytes * h);
|
||||
_free(a['pointer']!);
|
||||
_free(b['pointer']!);
|
||||
expect(pixelsA, pixelsB);
|
||||
expect(pixelsA.toSet().length, greaterThan(1));
|
||||
});
|
||||
|
||||
test('encoded image buffer roundtrip', () async {
|
||||
final res = await api.requestImage(
|
||||
assetId!,
|
||||
requestId: 900001,
|
||||
width: 0,
|
||||
height: 0,
|
||||
isVideo: false,
|
||||
preferEncoded: true,
|
||||
);
|
||||
expect(res, isNotNull);
|
||||
expect(res!['length'], fixture.length);
|
||||
final bytes = _read(res['pointer']!, res['length']!);
|
||||
_free(res['pointer']!);
|
||||
expect(bytes, fixture);
|
||||
});
|
||||
|
||||
test('10-bit decode runs NativeImage.convert1010102', () async {
|
||||
final Map<String, int>? res;
|
||||
try {
|
||||
res = await api.requestImage(
|
||||
assetId!,
|
||||
requestId: 900002,
|
||||
width: 0,
|
||||
height: 0,
|
||||
isVideo: false,
|
||||
preferEncoded: false,
|
||||
);
|
||||
} on PlatformException catch (e) {
|
||||
markTestSkipped('device cannot decode the 10-bit AVIF fixture: ${e.message}');
|
||||
return;
|
||||
}
|
||||
expect(res, isNotNull);
|
||||
final (w, h, rowBytes) = (res!['width']!, res['height']!, res['rowBytes']!);
|
||||
expect(w, 64);
|
||||
expect(h, 64);
|
||||
expect(rowBytes, w * 4);
|
||||
|
||||
final pixels = _read(res['pointer']!, rowBytes * h);
|
||||
_free(res['pointer']!);
|
||||
final source1010102 = res['source1010102'];
|
||||
expect(source1010102, isNotNull, reason: 'decode result did not report its source format');
|
||||
if (source1010102 == 0) {
|
||||
markTestSkipped('device decoded the 10-bit AVIF fixture without RGBA_1010102');
|
||||
return;
|
||||
}
|
||||
expect(source1010102, 1);
|
||||
expect(
|
||||
res['converted1010102'],
|
||||
1,
|
||||
reason: 'RGBA_1010102 source fell back instead of running the native conversion',
|
||||
);
|
||||
for (final (x, y) in [(2, 2), (32, 32), (61, 61)]) {
|
||||
final o = (y * w + x) * 4;
|
||||
expect(pixels[o], closeTo(45, 12), reason: 'R at ($x,$y)');
|
||||
expect(pixels[o + 1], closeTo(139, 12), reason: 'G at ($x,$y)');
|
||||
expect(pixels[o + 2], closeTo(107, 12), reason: 'B at ($x,$y)');
|
||||
expect(pixels[o + 3], 255, reason: 'A at ($x,$y)');
|
||||
}
|
||||
});
|
||||
|
||||
test('raw EXIF orientation rotates through NativeImage.rotate', () async {
|
||||
final sdkInt = (await DeviceInfoPlugin().androidInfo).version.sdkInt;
|
||||
if (sdkInt < 29) {
|
||||
markTestSkipped('raw image rotation needs Android 10 or newer');
|
||||
return;
|
||||
}
|
||||
final entity = await PhotoManager.editor.saveImage(_orientedDng(), filename: 'immich_jni_orientation.dng');
|
||||
orientedAssetId = entity.id;
|
||||
expect(await entity.mimeTypeAsync, anyOf('image/dng', 'image/x-adobe-dng'));
|
||||
expect(entity.orientation, 90);
|
||||
expect((entity.width, entity.height), (16, 12));
|
||||
|
||||
final Map<String, int>? res;
|
||||
try {
|
||||
res = await api.requestImage(
|
||||
entity.id,
|
||||
requestId: 900003,
|
||||
width: 0,
|
||||
height: 0,
|
||||
isVideo: false,
|
||||
preferEncoded: false,
|
||||
);
|
||||
} on PlatformException catch (e) {
|
||||
markTestSkipped('device cannot decode the DNG fixture: ${e.message}');
|
||||
return;
|
||||
}
|
||||
expect(res, isNotNull);
|
||||
final (w, h, rowBytes) = (res!['width']!, res['height']!, res['rowBytes']!);
|
||||
expect((w, h, rowBytes), (12, 16, 48));
|
||||
final pixels = _read(res['pointer']!, rowBytes * h);
|
||||
_free(res['pointer']!);
|
||||
for (final (x, r, b) in [(0, 0, 255), (11, 255, 0)]) {
|
||||
final o = 8 * rowBytes + x * 4;
|
||||
expect(pixels[o], closeTo(r, 12), reason: 'R at ($x,8)');
|
||||
expect(pixels[o + 2], closeTo(b, 12), reason: 'B at ($x,8)');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -36,6 +36,7 @@
|
||||
FE5499F62F11980E006016CB /* LocalImagesImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE5499F52F11980E006016CB /* LocalImagesImpl.swift */; };
|
||||
FE5499F82F1198E2006016CB /* RemoteImagesImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE5499F72F1198DE006016CB /* RemoteImagesImpl.swift */; };
|
||||
FE5FE4AE2F30FBC000A71243 /* ImageProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE5FE4AD2F30FBC000A71243 /* ImageProcessing.swift */; };
|
||||
FEAFA8732E4D42F4001E47FE /* Thumbhash.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEAFA8722E4D42F4001E47FE /* Thumbhash.swift */; };
|
||||
FEE084F82EC172460045228E /* SQLiteData in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084F72EC172460045228E /* SQLiteData */; };
|
||||
FEE084FB2EC1725A0045228E /* RawStructuredFieldValues in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084FA2EC1725A0045228E /* RawStructuredFieldValues */; };
|
||||
FEE084FD2EC1725A0045228E /* StructuredFieldValues in Frameworks */ = {isa = PBXBuildFile; productRef = FEE084FC2EC1725A0045228E /* StructuredFieldValues */; };
|
||||
@@ -130,6 +131,7 @@
|
||||
FE5499F52F11980E006016CB /* LocalImagesImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalImagesImpl.swift; sourceTree = "<group>"; };
|
||||
FE5499F72F1198DE006016CB /* RemoteImagesImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteImagesImpl.swift; sourceTree = "<group>"; };
|
||||
FE5FE4AD2F30FBC000A71243 /* ImageProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProcessing.swift; sourceTree = "<group>"; };
|
||||
FEAFA8722E4D42F4001E47FE /* Thumbhash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbhash.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
@@ -355,6 +357,7 @@
|
||||
FE5499F52F11980E006016CB /* LocalImagesImpl.swift */,
|
||||
FE5499F12F1197D8006016CB /* LocalImages.g.swift */,
|
||||
FE5499F22F1197D8006016CB /* RemoteImages.g.swift */,
|
||||
FEAFA8722E4D42F4001E47FE /* Thumbhash.swift */,
|
||||
);
|
||||
path = Images;
|
||||
sourceTree = "<group>";
|
||||
@@ -583,7 +586,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
|
||||
shellScript = "/bin/bash \"$SRCROOT/scripts/xcode_flutter_build.sh\"\n";
|
||||
};
|
||||
BAEA01ACA3F5C9CD3D732370 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -625,6 +628,7 @@
|
||||
B2EE00022E72CA15008B6CA7 /* PermissionApi.g.swift in Sources */,
|
||||
B2EE00042E72CA15008B6CA7 /* PermissionApiImpl.swift in Sources */,
|
||||
FE5499F82F1198E2006016CB /* RemoteImagesImpl.swift in Sources */,
|
||||
FEAFA8732E4D42F4001E47FE /* Thumbhash.swift in Sources */,
|
||||
B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */,
|
||||
B21E34AA2E5AFD2B0031FDB9 /* BackgroundWorkerApiImpl.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
// Native assets embed the framework without linking Runner, so resolve its symbol at runtime.
|
||||
enum NativeCore {
|
||||
typealias ThumbhashDecode = @convention(c) (
|
||||
UnsafePointer<UInt8>?, UInt, UnsafeMutablePointer<UInt32>?
|
||||
) -> UnsafeMutablePointer<UInt8>?
|
||||
|
||||
static let thumbhashDecode: ThumbhashDecode? = symbol("immich_core_thumbhash_decode")
|
||||
private static let logger = Logger(
|
||||
subsystem: Bundle.main.bundleIdentifier ?? "app.alextran.immich",
|
||||
category: "NativeCore"
|
||||
)
|
||||
|
||||
private static let handle: UnsafeMutableRawPointer? = load()
|
||||
|
||||
private static func load() -> UnsafeMutableRawPointer? {
|
||||
if let frameworks = Bundle.main.privateFrameworksPath {
|
||||
let path = "\(frameworks)/immich_core_ffi.framework/immich_core_ffi"
|
||||
dlerror()
|
||||
if let handle = dlopen(path, RTLD_NOW) {
|
||||
return handle
|
||||
}
|
||||
let error = lastError()
|
||||
logger.warning("dlopen failed for \(path, privacy: .public): \(error, privacy: .public)")
|
||||
}
|
||||
|
||||
dlerror()
|
||||
guard let handle = dlopen(nil, RTLD_NOW) else {
|
||||
let error = lastError()
|
||||
logger.error("dlopen failed for process scope: \(error, privacy: .public)")
|
||||
return nil
|
||||
}
|
||||
return handle
|
||||
}
|
||||
|
||||
private static func symbol<T>(_ name: String) -> T? {
|
||||
guard let handle else {
|
||||
logger.error("native core is unavailable while loading \(name, privacy: .public)")
|
||||
return nil
|
||||
}
|
||||
|
||||
dlerror()
|
||||
guard let sym = dlsym(handle, name) else {
|
||||
let error = lastError()
|
||||
logger.error("dlsym failed for \(name, privacy: .public): \(error, privacy: .public)")
|
||||
return nil
|
||||
}
|
||||
return unsafeBitCast(sym, to: T.self)
|
||||
}
|
||||
|
||||
private static func lastError() -> String {
|
||||
guard let error = dlerror() else { return "unknown error" }
|
||||
return String(cString: error)
|
||||
}
|
||||
}
|
||||
@@ -38,26 +38,15 @@ class LocalImageApiImpl: LocalImageApi {
|
||||
|
||||
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String : Int64], any Error>) -> Void) {
|
||||
ImageProcessing.queue.addOperation {
|
||||
guard let data = Data(base64Encoded: thumbhash) else {
|
||||
return completion(.failure(PigeonError(code: "invalid-base64", message: "Invalid base64 thumbhash", details: nil)))
|
||||
}
|
||||
guard let decode = NativeCore.thumbhashDecode else {
|
||||
return completion(.failure(PigeonError(code: "native-core-unavailable", message: "Native thumbhash decoder is unavailable", details: nil)))
|
||||
}
|
||||
|
||||
var info = [UInt32](repeating: 0, count: 3)
|
||||
let pointer = data.withUnsafeBytes { bytes in
|
||||
decode(bytes.bindMemory(to: UInt8.self).baseAddress, UInt(bytes.count), &info)
|
||||
}
|
||||
guard let pointer else {
|
||||
return completion(.failure(PigeonError(code: "invalid-thumbhash", message: "Invalid thumbhash", details: nil)))
|
||||
}
|
||||
guard let data = Data(base64Encoded: thumbhash)
|
||||
else { return completion(.failure(PigeonError(code: "", message: "Invalid base64 string: \(thumbhash)", details: nil)))}
|
||||
|
||||
let (width, height, pointer) = thumbHashToRGBA(hash: data)
|
||||
completion(.success([
|
||||
"pointer": Int64(Int(bitPattern: pointer)),
|
||||
"width": Int64(info[0]),
|
||||
"height": Int64(info[1]),
|
||||
"rowBytes": Int64(info[2])
|
||||
"pointer": Int64(Int(bitPattern: pointer.baseAddress)),
|
||||
"width": Int64(width),
|
||||
"height": Int64(height),
|
||||
"rowBytes": Int64(width * 4)
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
225
mobile/ios/Runner/Images/Thumbhash.swift
Normal file
225
mobile/ios/Runner/Images/Thumbhash.swift
Normal file
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) 2023 Evan Wallace
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
// NOTE: Swift has an exponential-time type checker and compiling very simple
|
||||
// expressions can easily take many seconds, especially when expressions involve
|
||||
// numeric type constructors.
|
||||
//
|
||||
// This file deliberately breaks compound expressions up into separate variables
|
||||
// to improve compile time even though this comes at the expense of readability.
|
||||
// This is a known workaround for this deficiency in the Swift compiler.
|
||||
//
|
||||
// The following command is helpful when debugging Swift compile time issues:
|
||||
//
|
||||
// swiftc ThumbHash.swift -Xfrontend -debug-time-function-bodies
|
||||
//
|
||||
// These optimizations brought the compile time for this file from around 2.5
|
||||
// seconds to around 250ms (10x faster).
|
||||
|
||||
// NOTE: Swift's debug-build performance of for-in loops over numeric ranges is
|
||||
// really awful. Debug builds compile a very generic indexing iterator thing
|
||||
// that makes many nested calls for every iteration, which makes debug-build
|
||||
// performance crawl.
|
||||
//
|
||||
// This file deliberately avoids for-in loops that loop for more than a few
|
||||
// times to improve debug-build run time even though this comes at the expense
|
||||
// of readability. Similarly unsafe pointers are used instead of array getters
|
||||
// to avoid unnecessary bounds checks, which have extra overhead in debug builds.
|
||||
//
|
||||
// These optimizations brought the run time to encode and decode 10 ThumbHashes
|
||||
// in debug mode from 700ms to 70ms (10x faster).
|
||||
|
||||
// changed signature and allocation method to avoid automatic GC
|
||||
func thumbHashToRGBA(hash: Data) -> (Int, Int, UnsafeMutableRawBufferPointer) {
|
||||
// Read the constants
|
||||
let h0 = UInt32(hash[0])
|
||||
let h1 = UInt32(hash[1])
|
||||
let h2 = UInt32(hash[2])
|
||||
let h3 = UInt16(hash[3])
|
||||
let h4 = UInt16(hash[4])
|
||||
let header24 = h0 | (h1 << 8) | (h2 << 16)
|
||||
let header16 = h3 | (h4 << 8)
|
||||
let il_dc = header24 & 63
|
||||
let ip_dc = (header24 >> 6) & 63
|
||||
let iq_dc = (header24 >> 12) & 63
|
||||
var l_dc = Float32(il_dc)
|
||||
var p_dc = Float32(ip_dc)
|
||||
var q_dc = Float32(iq_dc)
|
||||
l_dc = l_dc / 63
|
||||
p_dc = p_dc / 31.5 - 1
|
||||
q_dc = q_dc / 31.5 - 1
|
||||
let il_scale = (header24 >> 18) & 31
|
||||
var l_scale = Float32(il_scale)
|
||||
l_scale = l_scale / 31
|
||||
let hasAlpha = (header24 >> 23) != 0
|
||||
let ip_scale = (header16 >> 3) & 63
|
||||
let iq_scale = (header16 >> 9) & 63
|
||||
var p_scale = Float32(ip_scale)
|
||||
var q_scale = Float32(iq_scale)
|
||||
p_scale = p_scale / 63
|
||||
q_scale = q_scale / 63
|
||||
let isLandscape = (header16 >> 15) != 0
|
||||
let lx16 = max(3, isLandscape ? hasAlpha ? 5 : 7 : header16 & 7)
|
||||
let ly16 = max(3, isLandscape ? header16 & 7 : hasAlpha ? 5 : 7)
|
||||
let lx = Int(lx16)
|
||||
let ly = Int(ly16)
|
||||
var a_dc = Float32(1)
|
||||
var a_scale = Float32(1)
|
||||
if hasAlpha {
|
||||
let ia_dc = hash[5] & 15
|
||||
let ia_scale = hash[5] >> 4
|
||||
a_dc = Float32(ia_dc)
|
||||
a_scale = Float32(ia_scale)
|
||||
a_dc /= 15
|
||||
a_scale /= 15
|
||||
}
|
||||
|
||||
// Read the varying factors (boost saturation by 1.25x to compensate for quantization)
|
||||
let ac_start = hasAlpha ? 6 : 5
|
||||
var ac_index = 0
|
||||
let decodeChannel = { (nx: Int, ny: Int, scale: Float32) -> [Float32] in
|
||||
var ac: [Float32] = []
|
||||
for cy in 0 ..< ny {
|
||||
var cx = cy > 0 ? 0 : 1
|
||||
while cx * ny < nx * (ny - cy) {
|
||||
let iac = (hash[ac_start + (ac_index >> 1)] >> ((ac_index & 1) << 2)) & 15;
|
||||
var fac = Float32(iac)
|
||||
fac = (fac / 7.5 - 1) * scale
|
||||
ac.append(fac)
|
||||
ac_index += 1
|
||||
cx += 1
|
||||
}
|
||||
}
|
||||
return ac
|
||||
}
|
||||
let l_ac = decodeChannel(lx, ly, l_scale)
|
||||
let p_ac = decodeChannel(3, 3, p_scale * 1.25)
|
||||
let q_ac = decodeChannel(3, 3, q_scale * 1.25)
|
||||
let a_ac = hasAlpha ? decodeChannel(5, 5, a_scale) : []
|
||||
|
||||
// Decode using the DCT into RGB
|
||||
let ratio = thumbHashToApproximateAspectRatio(hash: hash)
|
||||
let fw = round(ratio > 1 ? 32 : 32 * ratio)
|
||||
let fh = round(ratio > 1 ? 32 / ratio : 32)
|
||||
let w = Int(fw)
|
||||
let h = Int(fh)
|
||||
let pointer = UnsafeMutableRawBufferPointer.allocate(
|
||||
byteCount: w * h * 4,
|
||||
alignment: MemoryLayout<UInt8>.alignment
|
||||
)
|
||||
var rgba = pointer.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
let cx_stop = max(lx, hasAlpha ? 5 : 3)
|
||||
let cy_stop = max(ly, hasAlpha ? 5 : 3)
|
||||
var fx = [Float32](repeating: 0, count: cx_stop)
|
||||
var fy = [Float32](repeating: 0, count: cy_stop)
|
||||
fx.withUnsafeMutableBytes { fx in
|
||||
let fx = fx.baseAddress!.bindMemory(to: Float32.self, capacity: fx.count)
|
||||
fy.withUnsafeMutableBytes { fy in
|
||||
let fy = fy.baseAddress!.bindMemory(to: Float32.self, capacity: fy.count)
|
||||
var y = 0
|
||||
while y < h {
|
||||
var x = 0
|
||||
while x < w {
|
||||
var l = l_dc
|
||||
var p = p_dc
|
||||
var q = q_dc
|
||||
var a = a_dc
|
||||
|
||||
// Precompute the coefficients
|
||||
var cx = 0
|
||||
while cx < cx_stop {
|
||||
let fw = Float32(w)
|
||||
let fxx = Float32(x)
|
||||
let fcx = Float32(cx)
|
||||
fx[cx] = cos(Float32.pi / fw * (fxx + 0.5) * fcx)
|
||||
cx += 1
|
||||
}
|
||||
var cy = 0
|
||||
while cy < cy_stop {
|
||||
let fh = Float32(h)
|
||||
let fyy = Float32(y)
|
||||
let fcy = Float32(cy)
|
||||
fy[cy] = cos(Float32.pi / fh * (fyy + 0.5) * fcy)
|
||||
cy += 1
|
||||
}
|
||||
|
||||
// Decode L
|
||||
var j = 0
|
||||
cy = 0
|
||||
while cy < ly {
|
||||
var cx = cy > 0 ? 0 : 1
|
||||
let fy2 = fy[cy] * 2
|
||||
while cx * ly < lx * (ly - cy) {
|
||||
l += l_ac[j] * fx[cx] * fy2
|
||||
j += 1
|
||||
cx += 1
|
||||
}
|
||||
cy += 1
|
||||
}
|
||||
|
||||
// Decode P and Q
|
||||
j = 0
|
||||
cy = 0
|
||||
while cy < 3 {
|
||||
var cx = cy > 0 ? 0 : 1
|
||||
let fy2 = fy[cy] * 2
|
||||
while cx < 3 - cy {
|
||||
let f = fx[cx] * fy2
|
||||
p += p_ac[j] * f
|
||||
q += q_ac[j] * f
|
||||
j += 1
|
||||
cx += 1
|
||||
}
|
||||
cy += 1
|
||||
}
|
||||
|
||||
// Decode A
|
||||
if hasAlpha {
|
||||
j = 0
|
||||
cy = 0
|
||||
while cy < 5 {
|
||||
var cx = cy > 0 ? 0 : 1
|
||||
let fy2 = fy[cy] * 2
|
||||
while cx < 5 - cy {
|
||||
a += a_ac[j] * fx[cx] * fy2
|
||||
j += 1
|
||||
cx += 1
|
||||
}
|
||||
cy += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to RGB
|
||||
var b = l - 2 / 3 * p
|
||||
var r = (3 * l - b + q) / 2
|
||||
var g = r - q
|
||||
r = max(0, 255 * min(1, r))
|
||||
g = max(0, 255 * min(1, g))
|
||||
b = max(0, 255 * min(1, b))
|
||||
a = max(0, 255 * min(1, a))
|
||||
rgba[0] = UInt8(r)
|
||||
rgba[1] = UInt8(g)
|
||||
rgba[2] = UInt8(b)
|
||||
rgba[3] = UInt8(a)
|
||||
rgba = rgba.advanced(by: 4)
|
||||
x += 1
|
||||
}
|
||||
y += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return (w, h, pointer)
|
||||
}
|
||||
|
||||
func thumbHashToApproximateAspectRatio(hash: Data) -> Float32 {
|
||||
let header = hash[3]
|
||||
let hasAlpha = (hash[2] & 0x80) != 0
|
||||
let isLandscape = (hash[4] & 0x80) != 0
|
||||
let lx = isLandscape ? hasAlpha ? 5 : 7 : header & 7
|
||||
let ly = isLandscape ? header & 7 : hasAlpha ? 5 : 7
|
||||
return Float32(lx) / Float32(ly)
|
||||
}
|
||||
@@ -34,13 +34,6 @@ platform :ios do
|
||||
)
|
||||
end
|
||||
|
||||
# Xcode build phases need mise trust saved to disk.
|
||||
def trust_mise_configs
|
||||
return unless system("command -v mise > /dev/null 2>&1")
|
||||
sh("mise trust ../../../mise.toml")
|
||||
sh("mise trust ../../mise.toml")
|
||||
end
|
||||
|
||||
# Helper method to assemble xcargs with optional CUSTOM_GROUP_ID override
|
||||
def build_xcargs(group_id: nil)
|
||||
args = "-skipMacroValidation CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual"
|
||||
@@ -109,8 +102,6 @@ end
|
||||
)
|
||||
app_identifier = base_bundle_id
|
||||
|
||||
trust_mise_configs
|
||||
|
||||
# Set version number if provided
|
||||
if version_number
|
||||
increment_version_number(version_number: version_number)
|
||||
@@ -267,8 +258,6 @@ end
|
||||
|
||||
api_key = get_api_key
|
||||
|
||||
trust_mise_configs
|
||||
|
||||
# Download and install provisioning profiles from App Store Connect
|
||||
# Certificate is imported by GHA workflow into build.keychain
|
||||
sigh(api_key: api_key, app_identifier: DEV_BUNDLE_ID, force: true)
|
||||
@@ -295,7 +284,6 @@ end
|
||||
configuration: "Release",
|
||||
export_method: "app-store",
|
||||
skip_package_ipa: true,
|
||||
xcodebuild_formatter: "", # raw xcodebuild output so script-phase errors show in CI logs
|
||||
xcargs: build_xcargs(group_id: DEV_GROUP_ID),
|
||||
export_options: {
|
||||
provisioningProfiles: {
|
||||
|
||||
45
mobile/ios/scripts/xcode_flutter_build.sh
Executable file
45
mobile/ios/scripts/xcode_flutter_build.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# Makes Flutter's builds through the Xcode GUI properly display errors and warnings
|
||||
# in the Issue navigator
|
||||
#
|
||||
# Flutter's `xcode_backend.dart` runs `flutter assemble` with `allowFail: true`,
|
||||
# which intentionally does not prefix output with `error:`. Unsure why they do this,
|
||||
# but this script rebuilds the expected output so Xcode can parse and display the errors
|
||||
|
||||
set -o pipefail
|
||||
|
||||
# The Immich mobile root (containing the Dart `lib` directory). This is used to make
|
||||
# absolute paths for Xcode linking
|
||||
app_root="${FLUTTER_APPLICATION_PATH:-$SRCROOT/..}"
|
||||
|
||||
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build 2>&1 \
|
||||
| awk -v app_root="$app_root" '
|
||||
# Match Dart CFE diagnostics: <path>.dart:<line>:<col>: <Kind>: <message>
|
||||
# Written for macOS/POSIX/BSD awk
|
||||
{
|
||||
# Always pass the original line through to preserve the original build log
|
||||
print
|
||||
|
||||
if ($0 ~ /^.*\.dart:[0-9]+:[0-9]+: (Error|Warning|Context|Info):/) {
|
||||
# Locate the ": Kind:" separator to split location from message.
|
||||
rest = $0
|
||||
if (match(rest, /: Error:/)) { kind = "Error"; keyword = "error" }
|
||||
else if (match(rest, /: Warning:/)) { kind = "Warning"; keyword = "warning" }
|
||||
else if (match(rest, /: Context:/)) { kind = "Context"; keyword = "note" }
|
||||
else if (match(rest, /: Info:/)) { kind = "Info"; keyword = "note" }
|
||||
|
||||
# location = everything before ": Kind:" (e.g. "lib/foo.dart:12:5")
|
||||
location = substr(rest, 1, RSTART - 1)
|
||||
# message = everything after ": Kind:" (leading space preserved)
|
||||
message = substr(rest, RSTART + length(": " kind ":"))
|
||||
|
||||
# Make the path absolute so Xcode links to it
|
||||
if (location !~ /^\//)
|
||||
location = app_root "/" location
|
||||
|
||||
printf "%s: %s:%s\n", location, keyword, message
|
||||
}
|
||||
}
|
||||
'
|
||||
|
||||
exit "${PIPESTATUS[0]}"
|
||||
@@ -6,7 +6,10 @@ import 'package:background_downloader/background_downloader.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/services/hash.service.dart';
|
||||
import 'package:immich_mobile/domain/services/local_sync.service.dart';
|
||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||
import 'package:immich_mobile/domain/services/sync_stream.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
@@ -14,11 +17,16 @@ import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.d
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
||||
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart' show nativeSyncApiProvider;
|
||||
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||
import 'package:immich_mobile/repositories/permission.repository.dart';
|
||||
import 'package:immich_mobile/services/auth.service.dart';
|
||||
import 'package:immich_mobile/services/foreground_upload.service.dart';
|
||||
import 'package:immich_mobile/services/localization.service.dart';
|
||||
@@ -58,12 +66,43 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
final BackgroundWorkerBgHostApi _backgroundHostApi;
|
||||
final _cancellationToken = Completer<void>();
|
||||
final Logger _logger = Logger('BackgroundWorkerBgService');
|
||||
late LocalSyncService _localSyncService;
|
||||
late SyncStreamService _remoteSyncService;
|
||||
late HashService _hashService;
|
||||
|
||||
bool _isCleanedUp = false;
|
||||
|
||||
BackgroundWorkerBgService({required this._drift, required this._driftLogger})
|
||||
: _backgroundHostApi = BackgroundWorkerBgHostApi() {
|
||||
_ref = ProviderContainer(overrides: [driftProvider.overrideWith(driftOverride(_drift))]);
|
||||
final ref = ProviderContainer(overrides: [driftProvider.overrideWith(driftOverride(_drift))]);
|
||||
_ref = ref;
|
||||
_localSyncService = LocalSyncService(
|
||||
localAlbumRepository: ref.read(localAlbumRepository),
|
||||
localAssetRepository: ref.read(localAssetRepository),
|
||||
nativeSyncApi: ref.read(nativeSyncApiProvider),
|
||||
trashedLocalAssetRepository: ref.read(trashedLocalAssetRepository),
|
||||
assetMediaRepository: ref.read(assetMediaRepositoryProvider),
|
||||
permissionRepository: ref.read(permissionRepositoryProvider),
|
||||
cancellation: _cancellationToken,
|
||||
);
|
||||
_remoteSyncService = SyncStreamService(
|
||||
syncApiRepository: ref.read(syncApiRepositoryProvider),
|
||||
syncStreamRepository: ref.read(syncStreamRepositoryProvider),
|
||||
localAssetRepository: ref.read(localAssetRepository),
|
||||
trashedLocalAssetRepository: ref.read(trashedLocalAssetRepository),
|
||||
assetMediaRepository: ref.read(assetMediaRepositoryProvider),
|
||||
permissionRepository: ref.read(permissionRepositoryProvider),
|
||||
syncMigrationRepository: ref.read(syncMigrationRepositoryProvider),
|
||||
api: ref.read(apiServiceProvider),
|
||||
cancellation: _cancellationToken,
|
||||
);
|
||||
_hashService = HashService(
|
||||
localAlbumRepository: ref.read(localAlbumRepository),
|
||||
localAssetRepository: ref.read(localAssetRepository),
|
||||
nativeSyncApi: ref.read(nativeSyncApiProvider),
|
||||
trashedLocalAssetRepository: ref.read(trashedLocalAssetRepository),
|
||||
cancellation: _cancellationToken,
|
||||
);
|
||||
BackgroundWorkerFlutterApi.setUp(this);
|
||||
}
|
||||
|
||||
@@ -119,11 +158,6 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
try {
|
||||
final budget = maxSeconds != null ? Duration(seconds: maxSeconds - 1) : null;
|
||||
|
||||
final sync = _ref?.read(backgroundSyncProvider);
|
||||
if (sync == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only for Background Processing tasks
|
||||
if (maxSeconds == null) {
|
||||
await _optimizeDB();
|
||||
@@ -135,9 +169,23 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
// hash and handle_backup read drift state and tolerate stale reads
|
||||
// (server-side dedup catches the rare race). The single budget caps the
|
||||
// whole batch; no phase needs its own timeout.
|
||||
final all = Future.wait<dynamic>([sync.syncLocal(), sync.syncRemote(), sync.hashAssets(), _handleBackup()]);
|
||||
final all = Future.wait<dynamic>([
|
||||
_localSyncService.sync(),
|
||||
_remoteSyncService.sync(),
|
||||
_hashService.hashAssets(),
|
||||
_handleBackup(),
|
||||
]);
|
||||
if (budget != null) {
|
||||
await all.timeout(budget, onTimeout: () => <dynamic>[]);
|
||||
await all.timeout(
|
||||
budget,
|
||||
onTimeout: () {
|
||||
if (!_cancellationToken.isCompleted) {
|
||||
_logger.warning("iOS background upload timed out after ${budget.inSeconds}s, cancelling tasks");
|
||||
_cancellationToken.complete();
|
||||
}
|
||||
return <dynamic>[];
|
||||
},
|
||||
);
|
||||
} else {
|
||||
await all;
|
||||
}
|
||||
@@ -221,7 +269,6 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
|
||||
try {
|
||||
_isCleanedUp = true;
|
||||
final backgroundSyncManager = _ref?.read(backgroundSyncProvider);
|
||||
final nativeSyncApi = _ref?.read(nativeSyncApiProvider);
|
||||
|
||||
_logger.info("Cleaning up background worker");
|
||||
@@ -230,10 +277,7 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
}
|
||||
|
||||
// Workers share one sqlite connection, so DB teardown must wait until every worker has stopped using it.
|
||||
await Future.wait([
|
||||
if (backgroundSyncManager != null) backgroundSyncManager.cancel(),
|
||||
if (nativeSyncApi != null) nativeSyncApi.cancelHashing(),
|
||||
]);
|
||||
await Future.wait([if (nativeSyncApi != null) nativeSyncApi.cancelHashing()]);
|
||||
await workerManagerPatch.dispose().catchError((_) async {});
|
||||
await Future.wait([LogService.I.dispose(), Store.dispose()]);
|
||||
await _drift.close();
|
||||
@@ -279,18 +323,18 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
}
|
||||
|
||||
Future<bool> _syncAssets({Duration? hashTimeout}) async {
|
||||
await _ref?.read(backgroundSyncProvider).syncLocal();
|
||||
await _localSyncService.sync();
|
||||
if (_isCleanedUp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final isSuccess = await _ref?.read(backgroundSyncProvider).syncRemote() ?? false;
|
||||
final isSuccess = await _remoteSyncService.sync();
|
||||
if (_isCleanedUp) {
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
var hashFuture = _ref?.read(backgroundSyncProvider).hashAssets();
|
||||
if (hashTimeout != null && hashFuture != null) {
|
||||
var hashFuture = _hashService.hashAssets();
|
||||
if (hashTimeout != null) {
|
||||
hashFuture = hashFuture.timeout(
|
||||
hashTimeout,
|
||||
onTimeout: () {
|
||||
|
||||
@@ -328,8 +328,6 @@ class SyncStreamService {
|
||||
return _syncStreamRepository.updateAssetOcrV1(data.cast());
|
||||
case SyncEntityType.assetOcrDeleteV1:
|
||||
return _syncStreamRepository.deleteAssetOcrV1(data.cast());
|
||||
default:
|
||||
_logger.warning("Unknown sync data type: $type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ extension on api.AssetVisibility {
|
||||
api.AssetVisibility.hidden => AssetVisibility.hidden,
|
||||
api.AssetVisibility.archive => AssetVisibility.archive,
|
||||
api.AssetVisibility.locked => AssetVisibility.locked,
|
||||
_ => AssetVisibility.timeline,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,6 +67,5 @@ extension on api.AssetTypeEnum {
|
||||
api.AssetTypeEnum.VIDEO => AssetType.video,
|
||||
api.AssetTypeEnum.AUDIO => AssetType.audio,
|
||||
api.AssetTypeEnum.OTHER => AssetType.other,
|
||||
_ => throw Exception('Unknown AssetType value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -937,7 +937,6 @@ extension on AssetTypeEnum {
|
||||
AssetTypeEnum.VIDEO => AssetType.video,
|
||||
AssetTypeEnum.AUDIO => AssetType.audio,
|
||||
AssetTypeEnum.OTHER => AssetType.other,
|
||||
_ => throw Exception('Unknown AssetType value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -945,14 +944,12 @@ extension on AssetOrder {
|
||||
AlbumAssetOrder toAlbumAssetOrder() => switch (this) {
|
||||
AssetOrder.asc => AlbumAssetOrder.asc,
|
||||
AssetOrder.desc => AlbumAssetOrder.desc,
|
||||
_ => throw Exception('Unknown AssetOrder value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
extension on MemoryType {
|
||||
MemoryTypeEnum toMemoryType() => switch (this) {
|
||||
MemoryType.onThisDay => MemoryTypeEnum.onThisDay,
|
||||
_ => throw Exception('Unknown MemoryType value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -961,7 +958,6 @@ extension on api.AlbumUserRole {
|
||||
api.AlbumUserRole.editor => AlbumUserRole.editor,
|
||||
api.AlbumUserRole.viewer => AlbumUserRole.viewer,
|
||||
api.AlbumUserRole.owner => AlbumUserRole.owner,
|
||||
_ => throw Exception('Unknown AlbumUserRole value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -971,7 +967,6 @@ extension on api.AssetVisibility {
|
||||
api.AssetVisibility.hidden => AssetVisibility.hidden,
|
||||
api.AssetVisibility.archive => AssetVisibility.archive,
|
||||
api.AssetVisibility.locked => AssetVisibility.locked,
|
||||
_ => throw Exception('Unknown AssetVisibility value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -980,12 +975,11 @@ extension on api.UserMetadataKey {
|
||||
api.UserMetadataKey.onboarding => UserMetadataKey.onboarding,
|
||||
api.UserMetadataKey.preferences => UserMetadataKey.preferences,
|
||||
api.UserMetadataKey.license => UserMetadataKey.license,
|
||||
_ => throw Exception('Unknown UserMetadataKey value: $this'),
|
||||
};
|
||||
}
|
||||
|
||||
extension on UserAvatarColor {
|
||||
AvatarColor? toAvatarColor() => AvatarColor.values.firstWhereOrNull((c) => c.name == value);
|
||||
AvatarColor? toAvatarColor() => AvatarColor.values.firstWhereOrNull((c) => c.name == toString());
|
||||
}
|
||||
|
||||
extension on api.AssetEditAction {
|
||||
@@ -993,6 +987,5 @@ extension on api.AssetEditAction {
|
||||
api.AssetEditAction.crop => AssetEditAction.crop,
|
||||
api.AssetEditAction.rotate => AssetEditAction.rotate,
|
||||
api.AssetEditAction.mirror => AssetEditAction.mirror,
|
||||
_ => AssetEditAction.other,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
|
||||
}
|
||||
case AppLifecycleState.paused:
|
||||
_shouldPlayOnForeground = await _controller?.isPlaying() ?? true;
|
||||
if (_shouldPlayOnForeground) {
|
||||
if (_shouldPlayOnForeground && mounted) {
|
||||
await _notifier.pause();
|
||||
}
|
||||
default:
|
||||
@@ -268,10 +268,13 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
|
||||
return;
|
||||
}
|
||||
|
||||
await _notifier.load(source);
|
||||
// Grab refs to prevent reading after dispose
|
||||
final loopVideo = ref.read(appConfigProvider).viewer.loopVideo;
|
||||
await _notifier.setLoop(!widget.asset.isMotionPhoto && loopVideo);
|
||||
await _notifier.setVolume(1);
|
||||
final localNotifier = _notifier;
|
||||
|
||||
await localNotifier.load(source);
|
||||
await localNotifier.setLoop(!widget.asset.isMotionPhoto && loopVideo);
|
||||
await localNotifier.setVolume(1);
|
||||
}
|
||||
|
||||
void _initController(NativeVideoPlayerController nc) {
|
||||
|
||||
@@ -318,7 +318,7 @@ class BackgroundUploadService {
|
||||
isFavorite: asset.isFavorite,
|
||||
requiresWiFi: requiresWiFi,
|
||||
// Visibility hidden on upload to prevent the server from running regular jobs on the live photo asset
|
||||
fields: entity.isLivePhoto ? {'visibility': api.AssetVisibility.hidden.value} : null,
|
||||
fields: entity.isLivePhoto ? {'visibility': api.AssetVisibility.hidden.toString()} : null,
|
||||
cloudId: entity.isLivePhoto ? null : asset.cloudId,
|
||||
adjustmentTime: entity.isLivePhoto ? null : asset.adjustmentTime?.toIso8601String(),
|
||||
latitude: entity.isLivePhoto ? null : asset.latitude?.toString(),
|
||||
|
||||
@@ -342,7 +342,7 @@ class ForegroundUploadService {
|
||||
file: livePhotoFile,
|
||||
originalFileName: livePhotoTitle,
|
||||
// Visibility hidden on upload to prevent the server from running regular jobs on the live photo asset
|
||||
fields: {...fields, 'visibility': AssetVisibility.hidden.value},
|
||||
fields: {...fields, 'visibility': AssetVisibility.hidden.toString()},
|
||||
cancelToken: cancelToken,
|
||||
onProgress: onProgress != null
|
||||
? (bytes, totalBytes) => onProgress(asset.localId!, livePhotoTitle, bytes, totalBytes)
|
||||
|
||||
@@ -1,76 +1,16 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_native_core/immich_native_core.dart';
|
||||
import 'package:thumbhash/thumbhash.dart' as thumbhash;
|
||||
|
||||
ObjectRef<Uint8List?> useDriftBlurHashRef(RemoteAsset? asset) {
|
||||
return useRef(decodeDriftThumbHash(asset?.thumbHash));
|
||||
}
|
||||
|
||||
Uint8List? decodeDriftThumbHash(String? thumbHash) {
|
||||
if (thumbHash == null || thumbHash.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Uint8List hash;
|
||||
try {
|
||||
hash = base64Decode(thumbHash);
|
||||
} on FormatException {
|
||||
return null;
|
||||
}
|
||||
|
||||
final hashPtr = malloc<Uint8>(hash.length);
|
||||
final info = malloc<Uint32>(3);
|
||||
try {
|
||||
hashPtr.asTypedList(hash.length).setAll(0, hash);
|
||||
final rgba = immich_core_thumbhash_decode(hashPtr, hash.length, info);
|
||||
if (rgba == nullptr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return _rgbaToBmp(rgba, info[0], info[1], info[2]);
|
||||
} finally {
|
||||
malloc.free(rgba);
|
||||
}
|
||||
} finally {
|
||||
malloc.free(hashPtr);
|
||||
malloc.free(info);
|
||||
}
|
||||
}
|
||||
|
||||
Uint8List? _rgbaToBmp(Pointer<Uint8> rgba, int width, int height, int stride) {
|
||||
if (width <= 0 || width > 32 || height <= 0 || height > 32 || stride != width * 4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const headerSize = 54;
|
||||
final imageSize = stride * height;
|
||||
final data = ByteData(headerSize + imageSize);
|
||||
|
||||
data
|
||||
..setUint16(0, 0x4d42, Endian.little)
|
||||
..setUint32(2, data.lengthInBytes, Endian.little)
|
||||
..setUint32(10, headerSize, Endian.little)
|
||||
..setUint32(14, 40, Endian.little)
|
||||
..setInt32(18, width, Endian.little)
|
||||
..setInt32(22, -height, Endian.little)
|
||||
..setUint16(26, 1, Endian.little)
|
||||
..setUint16(28, 32, Endian.little)
|
||||
..setUint32(34, imageSize, Endian.little);
|
||||
|
||||
final pixels = rgba.asTypedList(imageSize);
|
||||
for (var src = 0, dst = headerSize; src < imageSize; src += 4, dst += 4) {
|
||||
data
|
||||
..setUint8(dst, pixels[src + 2])
|
||||
..setUint8(dst + 1, pixels[src + 1])
|
||||
..setUint8(dst + 2, pixels[src])
|
||||
..setUint8(dst + 3, pixels[src + 3]);
|
||||
}
|
||||
|
||||
return data.buffer.asUint8List();
|
||||
if (asset?.thumbHash == null) {
|
||||
return useRef(null);
|
||||
}
|
||||
|
||||
final rbga = thumbhash.thumbHashToRGBA(base64Decode(asset!.thumbHash!));
|
||||
|
||||
return useRef(thumbhash.rgbaToBmp(rbga));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ String getThumbnailUrlForRemoteId(
|
||||
bool edited = true,
|
||||
String? thumbhash,
|
||||
}) {
|
||||
final url = '${Store.get(StoreKey.serverEndpoint)}/assets/$id/thumbnail?size=${type.value}&edited=$edited';
|
||||
final url = '${Store.get(StoreKey.serverEndpoint)}/assets/$id/thumbnail?size=${type.toString()}&edited=$edited';
|
||||
return thumbhash != null ? '$url&c=${Uri.encodeComponent(thumbhash)}' : url;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,20 @@ import 'package:immich_mobile/domain/models/log.model.dart';
|
||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/feature_message.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/settings.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
||||
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
|
||||
|
||||
const int targetVersion = 26;
|
||||
|
||||
Future<void> migrateDatabaseIfNeeded(Drift drift) async {
|
||||
final int version = Store.get(StoreKey.version, targetVersion);
|
||||
final int? storedVersion = Store.tryGet(StoreKey.version);
|
||||
final version = storedVersion ?? targetVersion;
|
||||
|
||||
if (version < 25) {
|
||||
await _migrateTo25();
|
||||
@@ -31,6 +34,10 @@ Future<void> migrateDatabaseIfNeeded(Drift drift) async {
|
||||
await _migrateTo26(drift);
|
||||
}
|
||||
|
||||
if (storedVersion == null) {
|
||||
await FeatureMessageService(SettingsRepository.instance).markSeen();
|
||||
}
|
||||
|
||||
await Store.put(StoreKey.version, targetVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -184,10 +184,3 @@ url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c55847602
|
||||
[tools.java."platforms.windows-x64"]
|
||||
checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882664"
|
||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip"
|
||||
|
||||
[[tools.rust]]
|
||||
version = "1.92.0"
|
||||
backend = "core:rust"
|
||||
|
||||
[tools.rust.options]
|
||||
targets = "aarch64-apple-ios,aarch64-apple-ios-sim,aarch64-linux-android,armv7-linux-androideabi,x86_64-apple-ios,x86_64-linux-android"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
[tools]
|
||||
"aqua:flutter/flutter" = "3.44.6"
|
||||
java = "21.0.2"
|
||||
# RUSTUP_TOOLCHAIN makes build hooks ignore rust-toolchain.toml targets.
|
||||
rust = { version = "1.92.0", targets = "armv7-linux-androideabi,aarch64-linux-android,x86_64-linux-android,aarch64-apple-ios,aarch64-apple-ios-sim,x86_64-apple-ios" }
|
||||
|
||||
[tools."github:CQLabs/homebrew-dcm"]
|
||||
version = "1.37.0"
|
||||
|
||||
@@ -1 +1 @@
|
||||
7.22.0
|
||||
7.24.0
|
||||
|
||||
4
mobile/openapi/README.md
generated
4
mobile/openapi/README.md
generated
@@ -4,12 +4,12 @@ Immich API
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 3.0.3
|
||||
- Generator version: 7.22.0
|
||||
- Generator version: 7.24.0
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
## Requirements
|
||||
|
||||
Dart 2.12 or later
|
||||
Dart 2.17 or later
|
||||
|
||||
## Installation & Usage
|
||||
|
||||
|
||||
4
mobile/openapi/lib/api_client.dart
generated
4
mobile/openapi/lib/api_client.dart
generated
@@ -97,9 +97,9 @@ class ApiClient {
|
||||
if (nullableHeaderParams != null) {
|
||||
request.headers.addAll(nullableHeaderParams);
|
||||
}
|
||||
if (msgBody is String) {
|
||||
if (msgBody is String && msgBody.isNotEmpty) {
|
||||
request.body = msgBody;
|
||||
} else if (msgBody is List<int>) {
|
||||
} else if (msgBody is List<int> && msgBody.isNotEmpty) {
|
||||
request.bodyBytes = msgBody;
|
||||
} else if (msgBody is Map<String, String>) {
|
||||
request.bodyFields = msgBody;
|
||||
|
||||
44
mobile/openapi/lib/model/album_user_role.dart
generated
44
mobile/openapi/lib/model/album_user_role.dart
generated
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Album user role
|
||||
class AlbumUserRole {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AlbumUserRole._(this.value);
|
||||
enum AlbumUserRole {
|
||||
editor._(r'editor'),
|
||||
owner._(r'owner'),
|
||||
viewer._(r'viewer'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AlbumUserRole._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const editor = AlbumUserRole._(r'editor');
|
||||
static const owner = AlbumUserRole._(r'owner');
|
||||
static const viewer = AlbumUserRole._(r'viewer');
|
||||
|
||||
/// List of all possible values in this [enum][AlbumUserRole].
|
||||
static const values = <AlbumUserRole>[
|
||||
editor,
|
||||
owner,
|
||||
viewer,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AlbumUserRole] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AlbumUserRole? fromJson(dynamic value) => AlbumUserRoleTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AlbumUserRole]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AlbumUserRole> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AlbumUserRole>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class AlbumUserRoleTypeTransformer {
|
||||
|
||||
const AlbumUserRoleTypeTransformer._();
|
||||
|
||||
String encode(AlbumUserRole data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AlbumUserRole data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AlbumUserRole.
|
||||
/// Returns the instance of [AlbumUserRole] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class AlbumUserRoleTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AlbumUserRole? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AlbumUserRole) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'editor': return AlbumUserRole.editor;
|
||||
@@ -82,7 +86,7 @@ class AlbumUserRoleTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AlbumUserRoleTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AlbumUserRoleTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
44
mobile/openapi/lib/model/asset_edit_action.dart
generated
44
mobile/openapi/lib/model/asset_edit_action.dart
generated
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Type of edit action to perform
|
||||
class AssetEditAction {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetEditAction._(this.value);
|
||||
enum AssetEditAction {
|
||||
crop._(r'crop'),
|
||||
rotate._(r'rotate'),
|
||||
mirror._(r'mirror'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetEditAction._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const crop = AssetEditAction._(r'crop');
|
||||
static const rotate = AssetEditAction._(r'rotate');
|
||||
static const mirror = AssetEditAction._(r'mirror');
|
||||
|
||||
/// List of all possible values in this [enum][AssetEditAction].
|
||||
static const values = <AssetEditAction>[
|
||||
crop,
|
||||
rotate,
|
||||
mirror,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetEditAction] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetEditAction? fromJson(dynamic value) => AssetEditActionTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetEditAction]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetEditAction> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetEditAction>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class AssetEditActionTypeTransformer {
|
||||
|
||||
const AssetEditActionTypeTransformer._();
|
||||
|
||||
String encode(AssetEditAction data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetEditAction data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetEditAction.
|
||||
/// Returns the instance of [AssetEditAction] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class AssetEditActionTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetEditAction? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetEditAction) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'crop': return AssetEditAction.crop;
|
||||
@@ -82,7 +86,7 @@ class AssetEditActionTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetEditActionTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetEditActionTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
44
mobile/openapi/lib/model/asset_id_error_reason.dart
generated
44
mobile/openapi/lib/model/asset_id_error_reason.dart
generated
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Error reason if failed
|
||||
class AssetIdErrorReason {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetIdErrorReason._(this.value);
|
||||
enum AssetIdErrorReason {
|
||||
duplicate._(r'duplicate'),
|
||||
noPermission._(r'no_permission'),
|
||||
notFound._(r'not_found'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetIdErrorReason._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const duplicate = AssetIdErrorReason._(r'duplicate');
|
||||
static const noPermission = AssetIdErrorReason._(r'no_permission');
|
||||
static const notFound = AssetIdErrorReason._(r'not_found');
|
||||
|
||||
/// List of all possible values in this [enum][AssetIdErrorReason].
|
||||
static const values = <AssetIdErrorReason>[
|
||||
duplicate,
|
||||
noPermission,
|
||||
notFound,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetIdErrorReason] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetIdErrorReason? fromJson(dynamic value) => AssetIdErrorReasonTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetIdErrorReason]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetIdErrorReason> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetIdErrorReason>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class AssetIdErrorReasonTypeTransformer {
|
||||
|
||||
const AssetIdErrorReasonTypeTransformer._();
|
||||
|
||||
String encode(AssetIdErrorReason data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetIdErrorReason data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetIdErrorReason.
|
||||
/// Returns the instance of [AssetIdErrorReason] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class AssetIdErrorReasonTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetIdErrorReason? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetIdErrorReason) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'duplicate': return AssetIdErrorReason.duplicate;
|
||||
@@ -82,7 +86,7 @@ class AssetIdErrorReasonTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetIdErrorReasonTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetIdErrorReasonTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/asset_job_name.dart
generated
47
mobile/openapi/lib/model/asset_job_name.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Job name
|
||||
class AssetJobName {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetJobName._(this.value);
|
||||
enum AssetJobName {
|
||||
refreshFaces._(r'refresh-faces'),
|
||||
refreshMetadata._(r'refresh-metadata'),
|
||||
regenerateThumbnail._(r'regenerate-thumbnail'),
|
||||
transcodeVideo._(r'transcode-video'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetJobName._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const refreshFaces = AssetJobName._(r'refresh-faces');
|
||||
static const refreshMetadata = AssetJobName._(r'refresh-metadata');
|
||||
static const regenerateThumbnail = AssetJobName._(r'regenerate-thumbnail');
|
||||
static const transcodeVideo = AssetJobName._(r'transcode-video');
|
||||
|
||||
/// List of all possible values in this [enum][AssetJobName].
|
||||
static const values = <AssetJobName>[
|
||||
refreshFaces,
|
||||
refreshMetadata,
|
||||
regenerateThumbnail,
|
||||
transcodeVideo,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetJobName] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetJobName? fromJson(dynamic value) => AssetJobNameTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetJobName]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetJobName> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetJobName>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class AssetJobNameTypeTransformer {
|
||||
|
||||
const AssetJobNameTypeTransformer._();
|
||||
|
||||
String encode(AssetJobName data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetJobName data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetJobName.
|
||||
/// Returns the instance of [AssetJobName] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class AssetJobNameTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetJobName? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetJobName) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'refresh-faces': return AssetJobName.refreshFaces;
|
||||
@@ -85,7 +88,7 @@ class AssetJobNameTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetJobNameTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetJobNameTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/asset_media_size.dart
generated
47
mobile/openapi/lib/model/asset_media_size.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Asset media size
|
||||
class AssetMediaSize {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetMediaSize._(this.value);
|
||||
enum AssetMediaSize {
|
||||
original._(r'original'),
|
||||
fullsize._(r'fullsize'),
|
||||
preview._(r'preview'),
|
||||
thumbnail._(r'thumbnail'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetMediaSize._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const original = AssetMediaSize._(r'original');
|
||||
static const fullsize = AssetMediaSize._(r'fullsize');
|
||||
static const preview = AssetMediaSize._(r'preview');
|
||||
static const thumbnail = AssetMediaSize._(r'thumbnail');
|
||||
|
||||
/// List of all possible values in this [enum][AssetMediaSize].
|
||||
static const values = <AssetMediaSize>[
|
||||
original,
|
||||
fullsize,
|
||||
preview,
|
||||
thumbnail,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetMediaSize] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetMediaSize? fromJson(dynamic value) => AssetMediaSizeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetMediaSize]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetMediaSize> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetMediaSize>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class AssetMediaSizeTypeTransformer {
|
||||
|
||||
const AssetMediaSizeTypeTransformer._();
|
||||
|
||||
String encode(AssetMediaSize data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetMediaSize data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetMediaSize.
|
||||
/// Returns the instance of [AssetMediaSize] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class AssetMediaSizeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetMediaSize? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetMediaSize) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'original': return AssetMediaSize.original;
|
||||
@@ -85,7 +88,7 @@ class AssetMediaSizeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetMediaSizeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetMediaSizeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/asset_media_status.dart
generated
41
mobile/openapi/lib/model/asset_media_status.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Upload status
|
||||
class AssetMediaStatus {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetMediaStatus._(this.value);
|
||||
enum AssetMediaStatus {
|
||||
created._(r'created'),
|
||||
duplicate._(r'duplicate'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetMediaStatus._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const created = AssetMediaStatus._(r'created');
|
||||
static const duplicate = AssetMediaStatus._(r'duplicate');
|
||||
|
||||
/// List of all possible values in this [enum][AssetMediaStatus].
|
||||
static const values = <AssetMediaStatus>[
|
||||
created,
|
||||
duplicate,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetMediaStatus] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetMediaStatus? fromJson(dynamic value) => AssetMediaStatusTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetMediaStatus]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetMediaStatus> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetMediaStatus>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class AssetMediaStatusTypeTransformer {
|
||||
|
||||
const AssetMediaStatusTypeTransformer._();
|
||||
|
||||
String encode(AssetMediaStatus data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetMediaStatus data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetMediaStatus.
|
||||
/// Returns the instance of [AssetMediaStatus] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class AssetMediaStatusTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetMediaStatus? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetMediaStatus) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'created': return AssetMediaStatus.created;
|
||||
@@ -79,7 +84,7 @@ class AssetMediaStatusTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetMediaStatusTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetMediaStatusTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/asset_order.dart
generated
41
mobile/openapi/lib/model/asset_order.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Asset sort order
|
||||
class AssetOrder {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetOrder._(this.value);
|
||||
enum AssetOrder {
|
||||
asc._(r'asc'),
|
||||
desc._(r'desc'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetOrder._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const asc = AssetOrder._(r'asc');
|
||||
static const desc = AssetOrder._(r'desc');
|
||||
|
||||
/// List of all possible values in this [enum][AssetOrder].
|
||||
static const values = <AssetOrder>[
|
||||
asc,
|
||||
desc,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetOrder] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetOrder? fromJson(dynamic value) => AssetOrderTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetOrder]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetOrder> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetOrder>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class AssetOrderTypeTransformer {
|
||||
|
||||
const AssetOrderTypeTransformer._();
|
||||
|
||||
String encode(AssetOrder data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetOrder data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetOrder.
|
||||
/// Returns the instance of [AssetOrder] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class AssetOrderTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetOrder? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetOrder) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'asc': return AssetOrder.asc;
|
||||
@@ -79,7 +84,7 @@ class AssetOrderTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetOrderTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetOrderTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/asset_order_by.dart
generated
41
mobile/openapi/lib/model/asset_order_by.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Asset sorting property
|
||||
class AssetOrderBy {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetOrderBy._(this.value);
|
||||
enum AssetOrderBy {
|
||||
takenAt._(r'takenAt'),
|
||||
createdAt._(r'createdAt'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetOrderBy._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const takenAt = AssetOrderBy._(r'takenAt');
|
||||
static const createdAt = AssetOrderBy._(r'createdAt');
|
||||
|
||||
/// List of all possible values in this [enum][AssetOrderBy].
|
||||
static const values = <AssetOrderBy>[
|
||||
takenAt,
|
||||
createdAt,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetOrderBy] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetOrderBy? fromJson(dynamic value) => AssetOrderByTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetOrderBy]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetOrderBy> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetOrderBy>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class AssetOrderByTypeTransformer {
|
||||
|
||||
const AssetOrderByTypeTransformer._();
|
||||
|
||||
String encode(AssetOrderBy data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetOrderBy data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetOrderBy.
|
||||
/// Returns the instance of [AssetOrderBy] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class AssetOrderByTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetOrderBy? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetOrderBy) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'takenAt': return AssetOrderBy.takenAt;
|
||||
@@ -79,7 +84,7 @@ class AssetOrderByTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetOrderByTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetOrderByTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/asset_reject_reason.dart
generated
41
mobile/openapi/lib/model/asset_reject_reason.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Rejection reason if rejected
|
||||
class AssetRejectReason {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetRejectReason._(this.value);
|
||||
enum AssetRejectReason {
|
||||
duplicate._(r'duplicate'),
|
||||
unsupportedFormat._(r'unsupported-format'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetRejectReason._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const duplicate = AssetRejectReason._(r'duplicate');
|
||||
static const unsupportedFormat = AssetRejectReason._(r'unsupported-format');
|
||||
|
||||
/// List of all possible values in this [enum][AssetRejectReason].
|
||||
static const values = <AssetRejectReason>[
|
||||
duplicate,
|
||||
unsupportedFormat,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetRejectReason] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetRejectReason? fromJson(dynamic value) => AssetRejectReasonTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetRejectReason]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetRejectReason> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetRejectReason>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class AssetRejectReasonTypeTransformer {
|
||||
|
||||
const AssetRejectReasonTypeTransformer._();
|
||||
|
||||
String encode(AssetRejectReason data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetRejectReason data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetRejectReason.
|
||||
/// Returns the instance of [AssetRejectReason] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class AssetRejectReasonTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetRejectReason? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetRejectReason) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'duplicate': return AssetRejectReason.duplicate;
|
||||
@@ -79,7 +84,7 @@ class AssetRejectReasonTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetRejectReasonTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetRejectReasonTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/asset_type_enum.dart
generated
47
mobile/openapi/lib/model/asset_type_enum.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Asset type
|
||||
class AssetTypeEnum {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetTypeEnum._(this.value);
|
||||
enum AssetTypeEnum {
|
||||
IMAGE._(r'IMAGE'),
|
||||
VIDEO._(r'VIDEO'),
|
||||
AUDIO._(r'AUDIO'),
|
||||
OTHER._(r'OTHER'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetTypeEnum._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const IMAGE = AssetTypeEnum._(r'IMAGE');
|
||||
static const VIDEO = AssetTypeEnum._(r'VIDEO');
|
||||
static const AUDIO = AssetTypeEnum._(r'AUDIO');
|
||||
static const OTHER = AssetTypeEnum._(r'OTHER');
|
||||
|
||||
/// List of all possible values in this [enum][AssetTypeEnum].
|
||||
static const values = <AssetTypeEnum>[
|
||||
IMAGE,
|
||||
VIDEO,
|
||||
AUDIO,
|
||||
OTHER,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetTypeEnum] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetTypeEnum? fromJson(dynamic value) => AssetTypeEnumTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetTypeEnum]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetTypeEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetTypeEnum>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class AssetTypeEnumTypeTransformer {
|
||||
|
||||
const AssetTypeEnumTypeTransformer._();
|
||||
|
||||
String encode(AssetTypeEnum data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetTypeEnum data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetTypeEnum.
|
||||
/// Returns the instance of [AssetTypeEnum] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class AssetTypeEnumTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetTypeEnum? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetTypeEnum) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'IMAGE': return AssetTypeEnum.IMAGE;
|
||||
@@ -85,7 +88,7 @@ class AssetTypeEnumTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetTypeEnumTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetTypeEnumTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/asset_upload_action.dart
generated
41
mobile/openapi/lib/model/asset_upload_action.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Upload action
|
||||
class AssetUploadAction {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetUploadAction._(this.value);
|
||||
enum AssetUploadAction {
|
||||
accept._(r'accept'),
|
||||
reject._(r'reject'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetUploadAction._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const accept = AssetUploadAction._(r'accept');
|
||||
static const reject = AssetUploadAction._(r'reject');
|
||||
|
||||
/// List of all possible values in this [enum][AssetUploadAction].
|
||||
static const values = <AssetUploadAction>[
|
||||
accept,
|
||||
reject,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetUploadAction] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetUploadAction? fromJson(dynamic value) => AssetUploadActionTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetUploadAction]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetUploadAction> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetUploadAction>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class AssetUploadActionTypeTransformer {
|
||||
|
||||
const AssetUploadActionTypeTransformer._();
|
||||
|
||||
String encode(AssetUploadAction data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetUploadAction data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetUploadAction.
|
||||
/// Returns the instance of [AssetUploadAction] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class AssetUploadActionTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetUploadAction? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetUploadAction) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'accept': return AssetUploadAction.accept;
|
||||
@@ -79,7 +84,7 @@ class AssetUploadActionTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetUploadActionTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetUploadActionTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/asset_visibility.dart
generated
47
mobile/openapi/lib/model/asset_visibility.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Asset visibility
|
||||
class AssetVisibility {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AssetVisibility._(this.value);
|
||||
enum AssetVisibility {
|
||||
archive._(r'archive'),
|
||||
timeline._(r'timeline'),
|
||||
hidden._(r'hidden'),
|
||||
locked._(r'locked'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AssetVisibility._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const archive = AssetVisibility._(r'archive');
|
||||
static const timeline = AssetVisibility._(r'timeline');
|
||||
static const hidden = AssetVisibility._(r'hidden');
|
||||
static const locked = AssetVisibility._(r'locked');
|
||||
|
||||
/// List of all possible values in this [enum][AssetVisibility].
|
||||
static const values = <AssetVisibility>[
|
||||
archive,
|
||||
timeline,
|
||||
hidden,
|
||||
locked,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AssetVisibility] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AssetVisibility? fromJson(dynamic value) => AssetVisibilityTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AssetVisibility]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AssetVisibility> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AssetVisibility>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class AssetVisibilityTypeTransformer {
|
||||
|
||||
const AssetVisibilityTypeTransformer._();
|
||||
|
||||
String encode(AssetVisibility data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AssetVisibility data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AssetVisibility.
|
||||
/// Returns the instance of [AssetVisibility] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class AssetVisibilityTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AssetVisibility? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AssetVisibility) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'archive': return AssetVisibility.archive;
|
||||
@@ -85,7 +88,7 @@ class AssetVisibilityTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AssetVisibilityTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AssetVisibilityTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/audio_codec.dart
generated
47
mobile/openapi/lib/model/audio_codec.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Target audio codec
|
||||
class AudioCodec {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const AudioCodec._(this.value);
|
||||
enum AudioCodec {
|
||||
mp3._(r'mp3'),
|
||||
aac._(r'aac'),
|
||||
opus._(r'opus'),
|
||||
pcmS16le._(r'pcm_s16le'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const AudioCodec._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const mp3 = AudioCodec._(r'mp3');
|
||||
static const aac = AudioCodec._(r'aac');
|
||||
static const opus = AudioCodec._(r'opus');
|
||||
static const pcmS16le = AudioCodec._(r'pcm_s16le');
|
||||
|
||||
/// List of all possible values in this [enum][AudioCodec].
|
||||
static const values = <AudioCodec>[
|
||||
mp3,
|
||||
aac,
|
||||
opus,
|
||||
pcmS16le,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [AudioCodec] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static AudioCodec? fromJson(dynamic value) => AudioCodecTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [AudioCodec]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<AudioCodec> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <AudioCodec>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class AudioCodecTypeTransformer {
|
||||
|
||||
const AudioCodecTypeTransformer._();
|
||||
|
||||
String encode(AudioCodec data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(AudioCodec data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a AudioCodec.
|
||||
/// Returns the instance of [AudioCodec] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class AudioCodecTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
AudioCodec? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is AudioCodec) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'mp3': return AudioCodec.mp3;
|
||||
@@ -85,7 +88,7 @@ class AudioCodecTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [AudioCodecTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static AudioCodecTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
50
mobile/openapi/lib/model/bulk_id_error_reason.dart
generated
50
mobile/openapi/lib/model/bulk_id_error_reason.dart
generated
@@ -11,35 +11,32 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Error reason
|
||||
class BulkIdErrorReason {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const BulkIdErrorReason._(this.value);
|
||||
enum BulkIdErrorReason {
|
||||
duplicate._(r'duplicate'),
|
||||
noPermission._(r'no_permission'),
|
||||
notFound._(r'not_found'),
|
||||
unknown._(r'unknown'),
|
||||
validation._(r'validation'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const BulkIdErrorReason._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const duplicate = BulkIdErrorReason._(r'duplicate');
|
||||
static const noPermission = BulkIdErrorReason._(r'no_permission');
|
||||
static const notFound = BulkIdErrorReason._(r'not_found');
|
||||
static const unknown = BulkIdErrorReason._(r'unknown');
|
||||
static const validation = BulkIdErrorReason._(r'validation');
|
||||
|
||||
/// List of all possible values in this [enum][BulkIdErrorReason].
|
||||
static const values = <BulkIdErrorReason>[
|
||||
duplicate,
|
||||
noPermission,
|
||||
notFound,
|
||||
unknown,
|
||||
validation,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [BulkIdErrorReason] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static BulkIdErrorReason? fromJson(dynamic value) => BulkIdErrorReasonTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [BulkIdErrorReason]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<BulkIdErrorReason> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <BulkIdErrorReason>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -61,9 +58,11 @@ class BulkIdErrorReasonTypeTransformer {
|
||||
|
||||
const BulkIdErrorReasonTypeTransformer._();
|
||||
|
||||
String encode(BulkIdErrorReason data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(BulkIdErrorReason data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a BulkIdErrorReason.
|
||||
/// Returns the instance of [BulkIdErrorReason] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -72,6 +71,9 @@ class BulkIdErrorReasonTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
BulkIdErrorReason? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is BulkIdErrorReason) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'duplicate': return BulkIdErrorReason.duplicate;
|
||||
@@ -88,7 +90,7 @@ class BulkIdErrorReasonTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [BulkIdErrorReasonTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static BulkIdErrorReasonTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/calendar_heatmap_type.dart
generated
41
mobile/openapi/lib/model/calendar_heatmap_type.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Type of calendar heatmap
|
||||
class CalendarHeatmapType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const CalendarHeatmapType._(this.value);
|
||||
enum CalendarHeatmapType {
|
||||
upload._(r'Upload'),
|
||||
taken._(r'Taken'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const CalendarHeatmapType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const upload = CalendarHeatmapType._(r'Upload');
|
||||
static const taken = CalendarHeatmapType._(r'Taken');
|
||||
|
||||
/// List of all possible values in this [enum][CalendarHeatmapType].
|
||||
static const values = <CalendarHeatmapType>[
|
||||
upload,
|
||||
taken,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [CalendarHeatmapType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static CalendarHeatmapType? fromJson(dynamic value) => CalendarHeatmapTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [CalendarHeatmapType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<CalendarHeatmapType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <CalendarHeatmapType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class CalendarHeatmapTypeTypeTransformer {
|
||||
|
||||
const CalendarHeatmapTypeTypeTransformer._();
|
||||
|
||||
String encode(CalendarHeatmapType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(CalendarHeatmapType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a CalendarHeatmapType.
|
||||
/// Returns the instance of [CalendarHeatmapType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class CalendarHeatmapTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
CalendarHeatmapType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is CalendarHeatmapType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'Upload': return CalendarHeatmapType.upload;
|
||||
@@ -79,7 +84,7 @@ class CalendarHeatmapTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [CalendarHeatmapTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static CalendarHeatmapTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/colorspace.dart
generated
41
mobile/openapi/lib/model/colorspace.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Colorspace
|
||||
class Colorspace {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const Colorspace._(this.value);
|
||||
enum Colorspace {
|
||||
srgb._(r'srgb'),
|
||||
p3._(r'p3'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const Colorspace._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const srgb = Colorspace._(r'srgb');
|
||||
static const p3 = Colorspace._(r'p3');
|
||||
|
||||
/// List of all possible values in this [enum][Colorspace].
|
||||
static const values = <Colorspace>[
|
||||
srgb,
|
||||
p3,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [Colorspace] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static Colorspace? fromJson(dynamic value) => ColorspaceTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [Colorspace]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<Colorspace> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <Colorspace>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class ColorspaceTypeTransformer {
|
||||
|
||||
const ColorspaceTypeTransformer._();
|
||||
|
||||
String encode(Colorspace data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(Colorspace data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a Colorspace.
|
||||
/// Returns the instance of [Colorspace] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class ColorspaceTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
Colorspace? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is Colorspace) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'srgb': return Colorspace.srgb;
|
||||
@@ -79,7 +84,7 @@ class ColorspaceTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ColorspaceTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ColorspaceTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
44
mobile/openapi/lib/model/cq_mode.dart
generated
44
mobile/openapi/lib/model/cq_mode.dart
generated
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// CQ mode
|
||||
class CQMode {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const CQMode._(this.value);
|
||||
enum CQMode {
|
||||
auto._(r'auto'),
|
||||
cqp._(r'cqp'),
|
||||
icq._(r'icq'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const CQMode._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const auto = CQMode._(r'auto');
|
||||
static const cqp = CQMode._(r'cqp');
|
||||
static const icq = CQMode._(r'icq');
|
||||
|
||||
/// List of all possible values in this [enum][CQMode].
|
||||
static const values = <CQMode>[
|
||||
auto,
|
||||
cqp,
|
||||
icq,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [CQMode] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static CQMode? fromJson(dynamic value) => CQModeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [CQMode]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<CQMode> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <CQMode>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class CQModeTypeTransformer {
|
||||
|
||||
const CQModeTypeTransformer._();
|
||||
|
||||
String encode(CQMode data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(CQMode data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a CQMode.
|
||||
/// Returns the instance of [CQMode] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class CQModeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
CQMode? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is CQMode) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'auto': return CQMode.auto;
|
||||
@@ -82,7 +86,7 @@ class CQModeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [CQModeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static CQModeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
50
mobile/openapi/lib/model/hls_video_resolution.dart
generated
50
mobile/openapi/lib/model/hls_video_resolution.dart
generated
@@ -11,35 +11,32 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// HLS video resolution
|
||||
class HlsVideoResolution {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const HlsVideoResolution._(this.value);
|
||||
enum HlsVideoResolution {
|
||||
number480._(480),
|
||||
number720._(720),
|
||||
number1080._(1080),
|
||||
number1440._(1440),
|
||||
number2160._(2160),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const HlsVideoResolution._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final int value;
|
||||
final int _value;
|
||||
|
||||
@override
|
||||
String toString() => value.toString();
|
||||
String toString() => _value.toString();
|
||||
|
||||
int toJson() => value;
|
||||
|
||||
static const number480 = HlsVideoResolution._(480);
|
||||
static const number720 = HlsVideoResolution._(720);
|
||||
static const number1080 = HlsVideoResolution._(1080);
|
||||
static const number1440 = HlsVideoResolution._(1440);
|
||||
static const number2160 = HlsVideoResolution._(2160);
|
||||
|
||||
/// List of all possible values in this [enum][HlsVideoResolution].
|
||||
static const values = <HlsVideoResolution>[
|
||||
number480,
|
||||
number720,
|
||||
number1080,
|
||||
number1440,
|
||||
number2160,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
int toJson() => _value;
|
||||
|
||||
/// Returns the instance of [HlsVideoResolution] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static HlsVideoResolution? fromJson(dynamic value) => HlsVideoResolutionTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [HlsVideoResolution]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<HlsVideoResolution> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <HlsVideoResolution>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -61,9 +58,11 @@ class HlsVideoResolutionTypeTransformer {
|
||||
|
||||
const HlsVideoResolutionTypeTransformer._();
|
||||
|
||||
int encode(HlsVideoResolution data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
int encode(HlsVideoResolution data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a HlsVideoResolution.
|
||||
/// Returns the instance of [HlsVideoResolution] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -72,6 +71,9 @@ class HlsVideoResolutionTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
HlsVideoResolution? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is HlsVideoResolution) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case 480: return HlsVideoResolution.number480;
|
||||
@@ -88,7 +90,7 @@ class HlsVideoResolutionTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [HlsVideoResolutionTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static HlsVideoResolutionTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/image_format.dart
generated
41
mobile/openapi/lib/model/image_format.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Image format
|
||||
class ImageFormat {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ImageFormat._(this.value);
|
||||
enum ImageFormat {
|
||||
jpeg._(r'jpeg'),
|
||||
webp._(r'webp'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const ImageFormat._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const jpeg = ImageFormat._(r'jpeg');
|
||||
static const webp = ImageFormat._(r'webp');
|
||||
|
||||
/// List of all possible values in this [enum][ImageFormat].
|
||||
static const values = <ImageFormat>[
|
||||
jpeg,
|
||||
webp,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [ImageFormat] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static ImageFormat? fromJson(dynamic value) => ImageFormatTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [ImageFormat]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<ImageFormat> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ImageFormat>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class ImageFormatTypeTransformer {
|
||||
|
||||
const ImageFormatTypeTransformer._();
|
||||
|
||||
String encode(ImageFormat data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(ImageFormat data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ImageFormat.
|
||||
/// Returns the instance of [ImageFormat] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class ImageFormatTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ImageFormat? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is ImageFormat) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'jpeg': return ImageFormat.jpeg;
|
||||
@@ -79,7 +84,7 @@ class ImageFormatTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ImageFormatTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ImageFormatTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
44
mobile/openapi/lib/model/integrity_report.dart
generated
44
mobile/openapi/lib/model/integrity_report.dart
generated
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Integrity report type
|
||||
class IntegrityReport {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const IntegrityReport._(this.value);
|
||||
enum IntegrityReport {
|
||||
untrackedFile._(r'untracked_file'),
|
||||
missingFile._(r'missing_file'),
|
||||
checksumMismatch._(r'checksum_mismatch'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const IntegrityReport._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const untrackedFile = IntegrityReport._(r'untracked_file');
|
||||
static const missingFile = IntegrityReport._(r'missing_file');
|
||||
static const checksumMismatch = IntegrityReport._(r'checksum_mismatch');
|
||||
|
||||
/// List of all possible values in this [enum][IntegrityReport].
|
||||
static const values = <IntegrityReport>[
|
||||
untrackedFile,
|
||||
missingFile,
|
||||
checksumMismatch,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [IntegrityReport] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static IntegrityReport? fromJson(dynamic value) => IntegrityReportTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [IntegrityReport]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<IntegrityReport> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <IntegrityReport>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class IntegrityReportTypeTransformer {
|
||||
|
||||
const IntegrityReportTypeTransformer._();
|
||||
|
||||
String encode(IntegrityReport data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(IntegrityReport data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a IntegrityReport.
|
||||
/// Returns the instance of [IntegrityReport] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class IntegrityReportTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
IntegrityReport? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is IntegrityReport) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'untracked_file': return IntegrityReport.untrackedFile;
|
||||
@@ -82,7 +86,7 @@ class IntegrityReportTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [IntegrityReportTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static IntegrityReportTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
233
mobile/openapi/lib/model/job_name.dart
generated
233
mobile/openapi/lib/model/job_name.dart
generated
@@ -11,157 +11,93 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Job name
|
||||
class JobName {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const JobName._(this.value);
|
||||
enum JobName {
|
||||
assetDelete._(r'AssetDelete'),
|
||||
assetDeleteCheck._(r'AssetDeleteCheck'),
|
||||
assetDetectFacesQueueAll._(r'AssetDetectFacesQueueAll'),
|
||||
assetDetectFaces._(r'AssetDetectFaces'),
|
||||
assetDetectDuplicatesQueueAll._(r'AssetDetectDuplicatesQueueAll'),
|
||||
assetDetectDuplicates._(r'AssetDetectDuplicates'),
|
||||
assetEditThumbnailGeneration._(r'AssetEditThumbnailGeneration'),
|
||||
assetEncodeVideoQueueAll._(r'AssetEncodeVideoQueueAll'),
|
||||
assetEncodeVideo._(r'AssetEncodeVideo'),
|
||||
assetEmptyTrash._(r'AssetEmptyTrash'),
|
||||
assetExtractMetadataQueueAll._(r'AssetExtractMetadataQueueAll'),
|
||||
assetExtractMetadata._(r'AssetExtractMetadata'),
|
||||
assetFileMigration._(r'AssetFileMigration'),
|
||||
assetGenerateThumbnailsQueueAll._(r'AssetGenerateThumbnailsQueueAll'),
|
||||
assetGenerateThumbnails._(r'AssetGenerateThumbnails'),
|
||||
auditTableCleanup._(r'AuditTableCleanup'),
|
||||
databaseBackup._(r'DatabaseBackup'),
|
||||
facialRecognitionQueueAll._(r'FacialRecognitionQueueAll'),
|
||||
facialRecognition._(r'FacialRecognition'),
|
||||
fileDelete._(r'FileDelete'),
|
||||
fileMigrationQueueAll._(r'FileMigrationQueueAll'),
|
||||
libraryDeleteCheck._(r'LibraryDeleteCheck'),
|
||||
libraryDelete._(r'LibraryDelete'),
|
||||
libraryRemoveAsset._(r'LibraryRemoveAsset'),
|
||||
libraryScanAssetsQueueAll._(r'LibraryScanAssetsQueueAll'),
|
||||
librarySyncAssets._(r'LibrarySyncAssets'),
|
||||
librarySyncFilesQueueAll._(r'LibrarySyncFilesQueueAll'),
|
||||
librarySyncFiles._(r'LibrarySyncFiles'),
|
||||
libraryScanQueueAll._(r'LibraryScanQueueAll'),
|
||||
hlsSessionCleanup._(r'HlsSessionCleanup'),
|
||||
memoryCleanup._(r'MemoryCleanup'),
|
||||
memoryGenerate._(r'MemoryGenerate'),
|
||||
notificationsCleanup._(r'NotificationsCleanup'),
|
||||
notifyUserSignup._(r'NotifyUserSignup'),
|
||||
notifyAlbumInvite._(r'NotifyAlbumInvite'),
|
||||
notifyAlbumUpdate._(r'NotifyAlbumUpdate'),
|
||||
userDelete._(r'UserDelete'),
|
||||
userDeleteCheck._(r'UserDeleteCheck'),
|
||||
userSyncUsage._(r'UserSyncUsage'),
|
||||
personCleanup._(r'PersonCleanup'),
|
||||
personFileMigration._(r'PersonFileMigration'),
|
||||
personGenerateThumbnail._(r'PersonGenerateThumbnail'),
|
||||
sessionCleanup._(r'SessionCleanup'),
|
||||
sendMail._(r'SendMail'),
|
||||
sidecarQueueAll._(r'SidecarQueueAll'),
|
||||
sidecarCheck._(r'SidecarCheck'),
|
||||
sidecarWrite._(r'SidecarWrite'),
|
||||
smartSearchQueueAll._(r'SmartSearchQueueAll'),
|
||||
smartSearch._(r'SmartSearch'),
|
||||
storageTemplateMigration._(r'StorageTemplateMigration'),
|
||||
storageTemplateMigrationSingle._(r'StorageTemplateMigrationSingle'),
|
||||
tagCleanup._(r'TagCleanup'),
|
||||
versionCheck._(r'VersionCheck'),
|
||||
ocrQueueAll._(r'OcrQueueAll'),
|
||||
ocr._(r'Ocr'),
|
||||
workflowAssetTrigger._(r'WorkflowAssetTrigger'),
|
||||
integrityUntrackedFilesQueueAll._(r'IntegrityUntrackedFilesQueueAll'),
|
||||
integrityUntrackedFiles._(r'IntegrityUntrackedFiles'),
|
||||
integrityUntrackedRefresh._(r'IntegrityUntrackedRefresh'),
|
||||
integrityMissingFilesQueueAll._(r'IntegrityMissingFilesQueueAll'),
|
||||
integrityMissingFiles._(r'IntegrityMissingFiles'),
|
||||
integrityMissingFilesRefresh._(r'IntegrityMissingFilesRefresh'),
|
||||
integrityChecksumFiles._(r'IntegrityChecksumFiles'),
|
||||
integrityChecksumFilesRefresh._(r'IntegrityChecksumFilesRefresh'),
|
||||
integrityDeleteReportType._(r'IntegrityDeleteReportType'),
|
||||
integrityDeleteReports._(r'IntegrityDeleteReports'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const JobName._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const assetDelete = JobName._(r'AssetDelete');
|
||||
static const assetDeleteCheck = JobName._(r'AssetDeleteCheck');
|
||||
static const assetDetectFacesQueueAll = JobName._(r'AssetDetectFacesQueueAll');
|
||||
static const assetDetectFaces = JobName._(r'AssetDetectFaces');
|
||||
static const assetDetectDuplicatesQueueAll = JobName._(r'AssetDetectDuplicatesQueueAll');
|
||||
static const assetDetectDuplicates = JobName._(r'AssetDetectDuplicates');
|
||||
static const assetEditThumbnailGeneration = JobName._(r'AssetEditThumbnailGeneration');
|
||||
static const assetEncodeVideoQueueAll = JobName._(r'AssetEncodeVideoQueueAll');
|
||||
static const assetEncodeVideo = JobName._(r'AssetEncodeVideo');
|
||||
static const assetEmptyTrash = JobName._(r'AssetEmptyTrash');
|
||||
static const assetExtractMetadataQueueAll = JobName._(r'AssetExtractMetadataQueueAll');
|
||||
static const assetExtractMetadata = JobName._(r'AssetExtractMetadata');
|
||||
static const assetFileMigration = JobName._(r'AssetFileMigration');
|
||||
static const assetGenerateThumbnailsQueueAll = JobName._(r'AssetGenerateThumbnailsQueueAll');
|
||||
static const assetGenerateThumbnails = JobName._(r'AssetGenerateThumbnails');
|
||||
static const auditTableCleanup = JobName._(r'AuditTableCleanup');
|
||||
static const databaseBackup = JobName._(r'DatabaseBackup');
|
||||
static const facialRecognitionQueueAll = JobName._(r'FacialRecognitionQueueAll');
|
||||
static const facialRecognition = JobName._(r'FacialRecognition');
|
||||
static const fileDelete = JobName._(r'FileDelete');
|
||||
static const fileMigrationQueueAll = JobName._(r'FileMigrationQueueAll');
|
||||
static const libraryDeleteCheck = JobName._(r'LibraryDeleteCheck');
|
||||
static const libraryDelete = JobName._(r'LibraryDelete');
|
||||
static const libraryRemoveAsset = JobName._(r'LibraryRemoveAsset');
|
||||
static const libraryScanAssetsQueueAll = JobName._(r'LibraryScanAssetsQueueAll');
|
||||
static const librarySyncAssets = JobName._(r'LibrarySyncAssets');
|
||||
static const librarySyncFilesQueueAll = JobName._(r'LibrarySyncFilesQueueAll');
|
||||
static const librarySyncFiles = JobName._(r'LibrarySyncFiles');
|
||||
static const libraryScanQueueAll = JobName._(r'LibraryScanQueueAll');
|
||||
static const hlsSessionCleanup = JobName._(r'HlsSessionCleanup');
|
||||
static const memoryCleanup = JobName._(r'MemoryCleanup');
|
||||
static const memoryGenerate = JobName._(r'MemoryGenerate');
|
||||
static const notificationsCleanup = JobName._(r'NotificationsCleanup');
|
||||
static const notifyUserSignup = JobName._(r'NotifyUserSignup');
|
||||
static const notifyAlbumInvite = JobName._(r'NotifyAlbumInvite');
|
||||
static const notifyAlbumUpdate = JobName._(r'NotifyAlbumUpdate');
|
||||
static const userDelete = JobName._(r'UserDelete');
|
||||
static const userDeleteCheck = JobName._(r'UserDeleteCheck');
|
||||
static const userSyncUsage = JobName._(r'UserSyncUsage');
|
||||
static const personCleanup = JobName._(r'PersonCleanup');
|
||||
static const personFileMigration = JobName._(r'PersonFileMigration');
|
||||
static const personGenerateThumbnail = JobName._(r'PersonGenerateThumbnail');
|
||||
static const sessionCleanup = JobName._(r'SessionCleanup');
|
||||
static const sendMail = JobName._(r'SendMail');
|
||||
static const sidecarQueueAll = JobName._(r'SidecarQueueAll');
|
||||
static const sidecarCheck = JobName._(r'SidecarCheck');
|
||||
static const sidecarWrite = JobName._(r'SidecarWrite');
|
||||
static const smartSearchQueueAll = JobName._(r'SmartSearchQueueAll');
|
||||
static const smartSearch = JobName._(r'SmartSearch');
|
||||
static const storageTemplateMigration = JobName._(r'StorageTemplateMigration');
|
||||
static const storageTemplateMigrationSingle = JobName._(r'StorageTemplateMigrationSingle');
|
||||
static const tagCleanup = JobName._(r'TagCleanup');
|
||||
static const versionCheck = JobName._(r'VersionCheck');
|
||||
static const ocrQueueAll = JobName._(r'OcrQueueAll');
|
||||
static const ocr = JobName._(r'Ocr');
|
||||
static const workflowAssetTrigger = JobName._(r'WorkflowAssetTrigger');
|
||||
static const integrityUntrackedFilesQueueAll = JobName._(r'IntegrityUntrackedFilesQueueAll');
|
||||
static const integrityUntrackedFiles = JobName._(r'IntegrityUntrackedFiles');
|
||||
static const integrityUntrackedRefresh = JobName._(r'IntegrityUntrackedRefresh');
|
||||
static const integrityMissingFilesQueueAll = JobName._(r'IntegrityMissingFilesQueueAll');
|
||||
static const integrityMissingFiles = JobName._(r'IntegrityMissingFiles');
|
||||
static const integrityMissingFilesRefresh = JobName._(r'IntegrityMissingFilesRefresh');
|
||||
static const integrityChecksumFiles = JobName._(r'IntegrityChecksumFiles');
|
||||
static const integrityChecksumFilesRefresh = JobName._(r'IntegrityChecksumFilesRefresh');
|
||||
static const integrityDeleteReportType = JobName._(r'IntegrityDeleteReportType');
|
||||
static const integrityDeleteReports = JobName._(r'IntegrityDeleteReports');
|
||||
|
||||
/// List of all possible values in this [enum][JobName].
|
||||
static const values = <JobName>[
|
||||
assetDelete,
|
||||
assetDeleteCheck,
|
||||
assetDetectFacesQueueAll,
|
||||
assetDetectFaces,
|
||||
assetDetectDuplicatesQueueAll,
|
||||
assetDetectDuplicates,
|
||||
assetEditThumbnailGeneration,
|
||||
assetEncodeVideoQueueAll,
|
||||
assetEncodeVideo,
|
||||
assetEmptyTrash,
|
||||
assetExtractMetadataQueueAll,
|
||||
assetExtractMetadata,
|
||||
assetFileMigration,
|
||||
assetGenerateThumbnailsQueueAll,
|
||||
assetGenerateThumbnails,
|
||||
auditTableCleanup,
|
||||
databaseBackup,
|
||||
facialRecognitionQueueAll,
|
||||
facialRecognition,
|
||||
fileDelete,
|
||||
fileMigrationQueueAll,
|
||||
libraryDeleteCheck,
|
||||
libraryDelete,
|
||||
libraryRemoveAsset,
|
||||
libraryScanAssetsQueueAll,
|
||||
librarySyncAssets,
|
||||
librarySyncFilesQueueAll,
|
||||
librarySyncFiles,
|
||||
libraryScanQueueAll,
|
||||
hlsSessionCleanup,
|
||||
memoryCleanup,
|
||||
memoryGenerate,
|
||||
notificationsCleanup,
|
||||
notifyUserSignup,
|
||||
notifyAlbumInvite,
|
||||
notifyAlbumUpdate,
|
||||
userDelete,
|
||||
userDeleteCheck,
|
||||
userSyncUsage,
|
||||
personCleanup,
|
||||
personFileMigration,
|
||||
personGenerateThumbnail,
|
||||
sessionCleanup,
|
||||
sendMail,
|
||||
sidecarQueueAll,
|
||||
sidecarCheck,
|
||||
sidecarWrite,
|
||||
smartSearchQueueAll,
|
||||
smartSearch,
|
||||
storageTemplateMigration,
|
||||
storageTemplateMigrationSingle,
|
||||
tagCleanup,
|
||||
versionCheck,
|
||||
ocrQueueAll,
|
||||
ocr,
|
||||
workflowAssetTrigger,
|
||||
integrityUntrackedFilesQueueAll,
|
||||
integrityUntrackedFiles,
|
||||
integrityUntrackedRefresh,
|
||||
integrityMissingFilesQueueAll,
|
||||
integrityMissingFiles,
|
||||
integrityMissingFilesRefresh,
|
||||
integrityChecksumFiles,
|
||||
integrityChecksumFilesRefresh,
|
||||
integrityDeleteReportType,
|
||||
integrityDeleteReports,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [JobName] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static JobName? fromJson(dynamic value) => JobNameTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [JobName]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<JobName> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <JobName>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -183,9 +119,11 @@ class JobNameTypeTransformer {
|
||||
|
||||
const JobNameTypeTransformer._();
|
||||
|
||||
String encode(JobName data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(JobName data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a JobName.
|
||||
/// Returns the instance of [JobName] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -194,6 +132,9 @@ class JobNameTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
JobName? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is JobName) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'AssetDelete': return JobName.assetDelete;
|
||||
@@ -271,7 +212,7 @@ class JobNameTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [JobNameTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static JobNameTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
53
mobile/openapi/lib/model/log_level.dart
generated
53
mobile/openapi/lib/model/log_level.dart
generated
@@ -11,37 +11,33 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Log level
|
||||
class LogLevel {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const LogLevel._(this.value);
|
||||
enum LogLevel {
|
||||
verbose._(r'verbose'),
|
||||
debug._(r'debug'),
|
||||
log._(r'log'),
|
||||
warn._(r'warn'),
|
||||
error._(r'error'),
|
||||
fatal._(r'fatal'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const LogLevel._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const verbose = LogLevel._(r'verbose');
|
||||
static const debug = LogLevel._(r'debug');
|
||||
static const log = LogLevel._(r'log');
|
||||
static const warn = LogLevel._(r'warn');
|
||||
static const error = LogLevel._(r'error');
|
||||
static const fatal = LogLevel._(r'fatal');
|
||||
|
||||
/// List of all possible values in this [enum][LogLevel].
|
||||
static const values = <LogLevel>[
|
||||
verbose,
|
||||
debug,
|
||||
log,
|
||||
warn,
|
||||
error,
|
||||
fatal,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [LogLevel] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static LogLevel? fromJson(dynamic value) => LogLevelTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [LogLevel]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<LogLevel> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <LogLevel>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -63,9 +59,11 @@ class LogLevelTypeTransformer {
|
||||
|
||||
const LogLevelTypeTransformer._();
|
||||
|
||||
String encode(LogLevel data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(LogLevel data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a LogLevel.
|
||||
/// Returns the instance of [LogLevel] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -74,6 +72,9 @@ class LogLevelTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
LogLevel? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is LogLevel) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'verbose': return LogLevel.verbose;
|
||||
@@ -91,7 +92,7 @@ class LogLevelTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [LogLevelTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static LogLevelTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/maintenance_action.dart
generated
47
mobile/openapi/lib/model/maintenance_action.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Maintenance action
|
||||
class MaintenanceAction {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const MaintenanceAction._(this.value);
|
||||
enum MaintenanceAction {
|
||||
start._(r'start'),
|
||||
end._(r'end'),
|
||||
selectDatabaseRestore._(r'select_database_restore'),
|
||||
restoreDatabase._(r'restore_database'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const MaintenanceAction._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const start = MaintenanceAction._(r'start');
|
||||
static const end = MaintenanceAction._(r'end');
|
||||
static const selectDatabaseRestore = MaintenanceAction._(r'select_database_restore');
|
||||
static const restoreDatabase = MaintenanceAction._(r'restore_database');
|
||||
|
||||
/// List of all possible values in this [enum][MaintenanceAction].
|
||||
static const values = <MaintenanceAction>[
|
||||
start,
|
||||
end,
|
||||
selectDatabaseRestore,
|
||||
restoreDatabase,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [MaintenanceAction] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static MaintenanceAction? fromJson(dynamic value) => MaintenanceActionTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [MaintenanceAction]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<MaintenanceAction> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MaintenanceAction>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class MaintenanceActionTypeTransformer {
|
||||
|
||||
const MaintenanceActionTypeTransformer._();
|
||||
|
||||
String encode(MaintenanceAction data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(MaintenanceAction data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a MaintenanceAction.
|
||||
/// Returns the instance of [MaintenanceAction] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class MaintenanceActionTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
MaintenanceAction? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is MaintenanceAction) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'start': return MaintenanceAction.start;
|
||||
@@ -85,7 +88,7 @@ class MaintenanceActionTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [MaintenanceActionTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static MaintenanceActionTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
80
mobile/openapi/lib/model/manual_job_name.dart
generated
80
mobile/openapi/lib/model/manual_job_name.dart
generated
@@ -11,55 +11,42 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Manual job name
|
||||
class ManualJobName {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ManualJobName._(this.value);
|
||||
enum ManualJobName {
|
||||
personCleanup._(r'person-cleanup'),
|
||||
tagCleanup._(r'tag-cleanup'),
|
||||
userCleanup._(r'user-cleanup'),
|
||||
memoryCleanup._(r'memory-cleanup'),
|
||||
memoryCreate._(r'memory-create'),
|
||||
backupDatabase._(r'backup-database'),
|
||||
integrityMissingFiles._(r'integrity-missing-files'),
|
||||
integrityUntrackedFiles._(r'integrity-untracked-files'),
|
||||
integrityChecksumMismatch._(r'integrity-checksum-mismatch'),
|
||||
integrityMissingFilesRefresh._(r'integrity-missing-files-refresh'),
|
||||
integrityUntrackedFilesRefresh._(r'integrity-untracked-files-refresh'),
|
||||
integrityChecksumMismatchRefresh._(r'integrity-checksum-mismatch-refresh'),
|
||||
integrityMissingFilesDeleteAll._(r'integrity-missing-files-delete-all'),
|
||||
integrityUntrackedFilesDeleteAll._(r'integrity-untracked-files-delete-all'),
|
||||
integrityChecksumMismatchDeleteAll._(r'integrity-checksum-mismatch-delete-all'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const ManualJobName._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const personCleanup = ManualJobName._(r'person-cleanup');
|
||||
static const tagCleanup = ManualJobName._(r'tag-cleanup');
|
||||
static const userCleanup = ManualJobName._(r'user-cleanup');
|
||||
static const memoryCleanup = ManualJobName._(r'memory-cleanup');
|
||||
static const memoryCreate = ManualJobName._(r'memory-create');
|
||||
static const backupDatabase = ManualJobName._(r'backup-database');
|
||||
static const integrityMissingFiles = ManualJobName._(r'integrity-missing-files');
|
||||
static const integrityUntrackedFiles = ManualJobName._(r'integrity-untracked-files');
|
||||
static const integrityChecksumMismatch = ManualJobName._(r'integrity-checksum-mismatch');
|
||||
static const integrityMissingFilesRefresh = ManualJobName._(r'integrity-missing-files-refresh');
|
||||
static const integrityUntrackedFilesRefresh = ManualJobName._(r'integrity-untracked-files-refresh');
|
||||
static const integrityChecksumMismatchRefresh = ManualJobName._(r'integrity-checksum-mismatch-refresh');
|
||||
static const integrityMissingFilesDeleteAll = ManualJobName._(r'integrity-missing-files-delete-all');
|
||||
static const integrityUntrackedFilesDeleteAll = ManualJobName._(r'integrity-untracked-files-delete-all');
|
||||
static const integrityChecksumMismatchDeleteAll = ManualJobName._(r'integrity-checksum-mismatch-delete-all');
|
||||
|
||||
/// List of all possible values in this [enum][ManualJobName].
|
||||
static const values = <ManualJobName>[
|
||||
personCleanup,
|
||||
tagCleanup,
|
||||
userCleanup,
|
||||
memoryCleanup,
|
||||
memoryCreate,
|
||||
backupDatabase,
|
||||
integrityMissingFiles,
|
||||
integrityUntrackedFiles,
|
||||
integrityChecksumMismatch,
|
||||
integrityMissingFilesRefresh,
|
||||
integrityUntrackedFilesRefresh,
|
||||
integrityChecksumMismatchRefresh,
|
||||
integrityMissingFilesDeleteAll,
|
||||
integrityUntrackedFilesDeleteAll,
|
||||
integrityChecksumMismatchDeleteAll,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [ManualJobName] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static ManualJobName? fromJson(dynamic value) => ManualJobNameTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [ManualJobName]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<ManualJobName> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ManualJobName>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -81,9 +68,11 @@ class ManualJobNameTypeTransformer {
|
||||
|
||||
const ManualJobNameTypeTransformer._();
|
||||
|
||||
String encode(ManualJobName data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(ManualJobName data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ManualJobName.
|
||||
/// Returns the instance of [ManualJobName] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -92,6 +81,9 @@ class ManualJobNameTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ManualJobName? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is ManualJobName) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'person-cleanup': return ManualJobName.personCleanup;
|
||||
@@ -118,7 +110,7 @@ class ManualJobNameTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ManualJobNameTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ManualJobNameTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
44
mobile/openapi/lib/model/memory_search_order.dart
generated
44
mobile/openapi/lib/model/memory_search_order.dart
generated
@@ -11,31 +11,30 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Sort order
|
||||
class MemorySearchOrder {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const MemorySearchOrder._(this.value);
|
||||
enum MemorySearchOrder {
|
||||
asc._(r'asc'),
|
||||
desc._(r'desc'),
|
||||
random._(r'random'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const MemorySearchOrder._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const asc = MemorySearchOrder._(r'asc');
|
||||
static const desc = MemorySearchOrder._(r'desc');
|
||||
static const random = MemorySearchOrder._(r'random');
|
||||
|
||||
/// List of all possible values in this [enum][MemorySearchOrder].
|
||||
static const values = <MemorySearchOrder>[
|
||||
asc,
|
||||
desc,
|
||||
random,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [MemorySearchOrder] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static MemorySearchOrder? fromJson(dynamic value) => MemorySearchOrderTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [MemorySearchOrder]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<MemorySearchOrder> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemorySearchOrder>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -57,9 +56,11 @@ class MemorySearchOrderTypeTransformer {
|
||||
|
||||
const MemorySearchOrderTypeTransformer._();
|
||||
|
||||
String encode(MemorySearchOrder data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(MemorySearchOrder data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a MemorySearchOrder.
|
||||
/// Returns the instance of [MemorySearchOrder] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -68,6 +69,9 @@ class MemorySearchOrderTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
MemorySearchOrder? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is MemorySearchOrder) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'asc': return MemorySearchOrder.asc;
|
||||
@@ -82,7 +86,7 @@ class MemorySearchOrderTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [MemorySearchOrderTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static MemorySearchOrderTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
38
mobile/openapi/lib/model/memory_type.dart
generated
38
mobile/openapi/lib/model/memory_type.dart
generated
@@ -11,27 +11,28 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Memory type
|
||||
class MemoryType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const MemoryType._(this.value);
|
||||
enum MemoryType {
|
||||
onThisDay._(r'on_this_day'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const MemoryType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const onThisDay = MemoryType._(r'on_this_day');
|
||||
|
||||
/// List of all possible values in this [enum][MemoryType].
|
||||
static const values = <MemoryType>[
|
||||
onThisDay,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [MemoryType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static MemoryType? fromJson(dynamic value) => MemoryTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [MemoryType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<MemoryType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -53,9 +54,11 @@ class MemoryTypeTypeTransformer {
|
||||
|
||||
const MemoryTypeTypeTransformer._();
|
||||
|
||||
String encode(MemoryType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(MemoryType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a MemoryType.
|
||||
/// Returns the instance of [MemoryType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -64,6 +67,9 @@ class MemoryTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
MemoryType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is MemoryType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'on_this_day': return MemoryType.onThisDay;
|
||||
@@ -76,7 +82,7 @@ class MemoryTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [MemoryTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static MemoryTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/mirror_axis.dart
generated
41
mobile/openapi/lib/model/mirror_axis.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Axis to mirror along
|
||||
class MirrorAxis {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const MirrorAxis._(this.value);
|
||||
enum MirrorAxis {
|
||||
horizontal._(r'horizontal'),
|
||||
vertical._(r'vertical'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const MirrorAxis._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const horizontal = MirrorAxis._(r'horizontal');
|
||||
static const vertical = MirrorAxis._(r'vertical');
|
||||
|
||||
/// List of all possible values in this [enum][MirrorAxis].
|
||||
static const values = <MirrorAxis>[
|
||||
horizontal,
|
||||
vertical,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [MirrorAxis] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static MirrorAxis? fromJson(dynamic value) => MirrorAxisTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [MirrorAxis]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<MirrorAxis> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MirrorAxis>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class MirrorAxisTypeTransformer {
|
||||
|
||||
const MirrorAxisTypeTransformer._();
|
||||
|
||||
String encode(MirrorAxis data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(MirrorAxis data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a MirrorAxis.
|
||||
/// Returns the instance of [MirrorAxis] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class MirrorAxisTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
MirrorAxis? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is MirrorAxis) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'horizontal': return MirrorAxis.horizontal;
|
||||
@@ -79,7 +84,7 @@ class MirrorAxisTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [MirrorAxisTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static MirrorAxisTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
47
mobile/openapi/lib/model/notification_level.dart
generated
47
mobile/openapi/lib/model/notification_level.dart
generated
@@ -11,33 +11,31 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Notification level
|
||||
class NotificationLevel {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const NotificationLevel._(this.value);
|
||||
enum NotificationLevel {
|
||||
success._(r'success'),
|
||||
error._(r'error'),
|
||||
warning._(r'warning'),
|
||||
info._(r'info'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const NotificationLevel._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const success = NotificationLevel._(r'success');
|
||||
static const error = NotificationLevel._(r'error');
|
||||
static const warning = NotificationLevel._(r'warning');
|
||||
static const info = NotificationLevel._(r'info');
|
||||
|
||||
/// List of all possible values in this [enum][NotificationLevel].
|
||||
static const values = <NotificationLevel>[
|
||||
success,
|
||||
error,
|
||||
warning,
|
||||
info,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [NotificationLevel] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static NotificationLevel? fromJson(dynamic value) => NotificationLevelTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [NotificationLevel]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<NotificationLevel> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <NotificationLevel>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -59,9 +57,11 @@ class NotificationLevelTypeTransformer {
|
||||
|
||||
const NotificationLevelTypeTransformer._();
|
||||
|
||||
String encode(NotificationLevel data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(NotificationLevel data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a NotificationLevel.
|
||||
/// Returns the instance of [NotificationLevel] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -70,6 +70,9 @@ class NotificationLevelTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
NotificationLevel? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is NotificationLevel) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'success': return NotificationLevel.success;
|
||||
@@ -85,7 +88,7 @@ class NotificationLevelTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [NotificationLevelTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static NotificationLevelTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
53
mobile/openapi/lib/model/notification_type.dart
generated
53
mobile/openapi/lib/model/notification_type.dart
generated
@@ -11,37 +11,33 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Notification type
|
||||
class NotificationType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const NotificationType._(this.value);
|
||||
enum NotificationType {
|
||||
jobFailed._(r'JobFailed'),
|
||||
backupFailed._(r'BackupFailed'),
|
||||
systemMessage._(r'SystemMessage'),
|
||||
albumInvite._(r'AlbumInvite'),
|
||||
albumUpdate._(r'AlbumUpdate'),
|
||||
custom._(r'Custom'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const NotificationType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const jobFailed = NotificationType._(r'JobFailed');
|
||||
static const backupFailed = NotificationType._(r'BackupFailed');
|
||||
static const systemMessage = NotificationType._(r'SystemMessage');
|
||||
static const albumInvite = NotificationType._(r'AlbumInvite');
|
||||
static const albumUpdate = NotificationType._(r'AlbumUpdate');
|
||||
static const custom = NotificationType._(r'Custom');
|
||||
|
||||
/// List of all possible values in this [enum][NotificationType].
|
||||
static const values = <NotificationType>[
|
||||
jobFailed,
|
||||
backupFailed,
|
||||
systemMessage,
|
||||
albumInvite,
|
||||
albumUpdate,
|
||||
custom,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [NotificationType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static NotificationType? fromJson(dynamic value) => NotificationTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [NotificationType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<NotificationType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <NotificationType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -63,9 +59,11 @@ class NotificationTypeTypeTransformer {
|
||||
|
||||
const NotificationTypeTypeTransformer._();
|
||||
|
||||
String encode(NotificationType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(NotificationType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a NotificationType.
|
||||
/// Returns the instance of [NotificationType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -74,6 +72,9 @@ class NotificationTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
NotificationType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is NotificationType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'JobFailed': return NotificationType.jobFailed;
|
||||
@@ -91,7 +92,7 @@ class NotificationTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [NotificationTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static NotificationTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// OAuth token endpoint auth method
|
||||
class OAuthTokenEndpointAuthMethod {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const OAuthTokenEndpointAuthMethod._(this.value);
|
||||
enum OAuthTokenEndpointAuthMethod {
|
||||
clientSecretPost._(r'client_secret_post'),
|
||||
clientSecretBasic._(r'client_secret_basic'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const OAuthTokenEndpointAuthMethod._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const clientSecretPost = OAuthTokenEndpointAuthMethod._(r'client_secret_post');
|
||||
static const clientSecretBasic = OAuthTokenEndpointAuthMethod._(r'client_secret_basic');
|
||||
|
||||
/// List of all possible values in this [enum][OAuthTokenEndpointAuthMethod].
|
||||
static const values = <OAuthTokenEndpointAuthMethod>[
|
||||
clientSecretPost,
|
||||
clientSecretBasic,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [OAuthTokenEndpointAuthMethod] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static OAuthTokenEndpointAuthMethod? fromJson(dynamic value) => OAuthTokenEndpointAuthMethodTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [OAuthTokenEndpointAuthMethod]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<OAuthTokenEndpointAuthMethod> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <OAuthTokenEndpointAuthMethod>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class OAuthTokenEndpointAuthMethodTypeTransformer {
|
||||
|
||||
const OAuthTokenEndpointAuthMethodTypeTransformer._();
|
||||
|
||||
String encode(OAuthTokenEndpointAuthMethod data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(OAuthTokenEndpointAuthMethod data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a OAuthTokenEndpointAuthMethod.
|
||||
/// Returns the instance of [OAuthTokenEndpointAuthMethod] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class OAuthTokenEndpointAuthMethodTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
OAuthTokenEndpointAuthMethod? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is OAuthTokenEndpointAuthMethod) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'client_secret_post': return OAuthTokenEndpointAuthMethod.clientSecretPost;
|
||||
@@ -79,7 +84,7 @@ class OAuthTokenEndpointAuthMethodTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [OAuthTokenEndpointAuthMethodTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static OAuthTokenEndpointAuthMethodTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/partner_direction.dart
generated
41
mobile/openapi/lib/model/partner_direction.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Partner direction
|
||||
class PartnerDirection {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const PartnerDirection._(this.value);
|
||||
enum PartnerDirection {
|
||||
sharedBy._(r'shared-by'),
|
||||
sharedWith._(r'shared-with'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const PartnerDirection._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const sharedBy = PartnerDirection._(r'shared-by');
|
||||
static const sharedWith = PartnerDirection._(r'shared-with');
|
||||
|
||||
/// List of all possible values in this [enum][PartnerDirection].
|
||||
static const values = <PartnerDirection>[
|
||||
sharedBy,
|
||||
sharedWith,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [PartnerDirection] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static PartnerDirection? fromJson(dynamic value) => PartnerDirectionTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [PartnerDirection]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<PartnerDirection> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PartnerDirection>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class PartnerDirectionTypeTransformer {
|
||||
|
||||
const PartnerDirectionTypeTransformer._();
|
||||
|
||||
String encode(PartnerDirection data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(PartnerDirection data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a PartnerDirection.
|
||||
/// Returns the instance of [PartnerDirection] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class PartnerDirectionTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
PartnerDirection? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is PartnerDirection) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'shared-by': return PartnerDirection.sharedBy;
|
||||
@@ -79,7 +84,7 @@ class PartnerDirectionTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [PartnerDirectionTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static PartnerDirectionTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
500
mobile/openapi/lib/model/permission.dart
generated
500
mobile/openapi/lib/model/permission.dart
generated
@@ -11,335 +11,182 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// List of permissions
|
||||
class Permission {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const Permission._(this.value);
|
||||
enum Permission {
|
||||
all._(r'all'),
|
||||
activityPeriodCreate._(r'activity.create'),
|
||||
activityPeriodRead._(r'activity.read'),
|
||||
activityPeriodUpdate._(r'activity.update'),
|
||||
activityPeriodDelete._(r'activity.delete'),
|
||||
activityPeriodStatistics._(r'activity.statistics'),
|
||||
apiKeyPeriodCreate._(r'apiKey.create'),
|
||||
apiKeyPeriodRead._(r'apiKey.read'),
|
||||
apiKeyPeriodUpdate._(r'apiKey.update'),
|
||||
apiKeyPeriodDelete._(r'apiKey.delete'),
|
||||
assetPeriodRead._(r'asset.read'),
|
||||
assetPeriodUpdate._(r'asset.update'),
|
||||
assetPeriodDelete._(r'asset.delete'),
|
||||
assetPeriodStatistics._(r'asset.statistics'),
|
||||
assetPeriodShare._(r'asset.share'),
|
||||
assetPeriodView._(r'asset.view'),
|
||||
assetPeriodDownload._(r'asset.download'),
|
||||
assetPeriodUpload._(r'asset.upload'),
|
||||
assetPeriodCopy._(r'asset.copy'),
|
||||
assetPeriodDerive._(r'asset.derive'),
|
||||
assetPeriodEditPeriodGet._(r'asset.edit.get'),
|
||||
assetPeriodEditPeriodCreate._(r'asset.edit.create'),
|
||||
assetPeriodEditPeriodDelete._(r'asset.edit.delete'),
|
||||
albumPeriodCreate._(r'album.create'),
|
||||
albumPeriodRead._(r'album.read'),
|
||||
albumPeriodUpdate._(r'album.update'),
|
||||
albumPeriodDelete._(r'album.delete'),
|
||||
albumPeriodStatistics._(r'album.statistics'),
|
||||
albumPeriodShare._(r'album.share'),
|
||||
albumPeriodDownload._(r'album.download'),
|
||||
albumAssetPeriodCreate._(r'albumAsset.create'),
|
||||
albumAssetPeriodDelete._(r'albumAsset.delete'),
|
||||
albumUserPeriodCreate._(r'albumUser.create'),
|
||||
albumUserPeriodUpdate._(r'albumUser.update'),
|
||||
albumUserPeriodDelete._(r'albumUser.delete'),
|
||||
authPeriodChangePassword._(r'auth.changePassword'),
|
||||
authDevicePeriodDelete._(r'authDevice.delete'),
|
||||
archivePeriodRead._(r'archive.read'),
|
||||
backupPeriodList._(r'backup.list'),
|
||||
backupPeriodDownload._(r'backup.download'),
|
||||
backupPeriodUpload._(r'backup.upload'),
|
||||
backupPeriodDelete._(r'backup.delete'),
|
||||
duplicatePeriodRead._(r'duplicate.read'),
|
||||
duplicatePeriodDelete._(r'duplicate.delete'),
|
||||
facePeriodCreate._(r'face.create'),
|
||||
facePeriodRead._(r'face.read'),
|
||||
facePeriodUpdate._(r'face.update'),
|
||||
facePeriodDelete._(r'face.delete'),
|
||||
folderPeriodRead._(r'folder.read'),
|
||||
jobPeriodCreate._(r'job.create'),
|
||||
jobPeriodRead._(r'job.read'),
|
||||
libraryPeriodCreate._(r'library.create'),
|
||||
libraryPeriodRead._(r'library.read'),
|
||||
libraryPeriodUpdate._(r'library.update'),
|
||||
libraryPeriodDelete._(r'library.delete'),
|
||||
libraryPeriodStatistics._(r'library.statistics'),
|
||||
timelinePeriodRead._(r'timeline.read'),
|
||||
timelinePeriodDownload._(r'timeline.download'),
|
||||
maintenance._(r'maintenance'),
|
||||
mapPeriodRead._(r'map.read'),
|
||||
mapPeriodSearch._(r'map.search'),
|
||||
memoryPeriodCreate._(r'memory.create'),
|
||||
memoryPeriodRead._(r'memory.read'),
|
||||
memoryPeriodUpdate._(r'memory.update'),
|
||||
memoryPeriodDelete._(r'memory.delete'),
|
||||
memoryPeriodStatistics._(r'memory.statistics'),
|
||||
memoryAssetPeriodCreate._(r'memoryAsset.create'),
|
||||
memoryAssetPeriodDelete._(r'memoryAsset.delete'),
|
||||
notificationPeriodCreate._(r'notification.create'),
|
||||
notificationPeriodRead._(r'notification.read'),
|
||||
notificationPeriodUpdate._(r'notification.update'),
|
||||
notificationPeriodDelete._(r'notification.delete'),
|
||||
partnerPeriodCreate._(r'partner.create'),
|
||||
partnerPeriodRead._(r'partner.read'),
|
||||
partnerPeriodUpdate._(r'partner.update'),
|
||||
partnerPeriodDelete._(r'partner.delete'),
|
||||
personPeriodCreate._(r'person.create'),
|
||||
personPeriodRead._(r'person.read'),
|
||||
personPeriodUpdate._(r'person.update'),
|
||||
personPeriodDelete._(r'person.delete'),
|
||||
personPeriodStatistics._(r'person.statistics'),
|
||||
personPeriodMerge._(r'person.merge'),
|
||||
personPeriodReassign._(r'person.reassign'),
|
||||
pinCodePeriodCreate._(r'pinCode.create'),
|
||||
pinCodePeriodUpdate._(r'pinCode.update'),
|
||||
pinCodePeriodDelete._(r'pinCode.delete'),
|
||||
pluginPeriodCreate._(r'plugin.create'),
|
||||
pluginPeriodRead._(r'plugin.read'),
|
||||
pluginPeriodUpdate._(r'plugin.update'),
|
||||
pluginPeriodDelete._(r'plugin.delete'),
|
||||
serverPeriodAbout._(r'server.about'),
|
||||
serverPeriodApkLinks._(r'server.apkLinks'),
|
||||
serverPeriodStorage._(r'server.storage'),
|
||||
serverPeriodStatistics._(r'server.statistics'),
|
||||
serverPeriodVersionCheck._(r'server.versionCheck'),
|
||||
serverLicensePeriodRead._(r'serverLicense.read'),
|
||||
serverLicensePeriodUpdate._(r'serverLicense.update'),
|
||||
serverLicensePeriodDelete._(r'serverLicense.delete'),
|
||||
sessionPeriodCreate._(r'session.create'),
|
||||
sessionPeriodRead._(r'session.read'),
|
||||
sessionPeriodUpdate._(r'session.update'),
|
||||
sessionPeriodDelete._(r'session.delete'),
|
||||
sessionPeriodLock._(r'session.lock'),
|
||||
sharedLinkPeriodCreate._(r'sharedLink.create'),
|
||||
sharedLinkPeriodRead._(r'sharedLink.read'),
|
||||
sharedLinkPeriodUpdate._(r'sharedLink.update'),
|
||||
sharedLinkPeriodDelete._(r'sharedLink.delete'),
|
||||
stackPeriodCreate._(r'stack.create'),
|
||||
stackPeriodRead._(r'stack.read'),
|
||||
stackPeriodUpdate._(r'stack.update'),
|
||||
stackPeriodDelete._(r'stack.delete'),
|
||||
syncPeriodStream._(r'sync.stream'),
|
||||
syncCheckpointPeriodRead._(r'syncCheckpoint.read'),
|
||||
syncCheckpointPeriodUpdate._(r'syncCheckpoint.update'),
|
||||
syncCheckpointPeriodDelete._(r'syncCheckpoint.delete'),
|
||||
systemConfigPeriodRead._(r'systemConfig.read'),
|
||||
systemConfigPeriodUpdate._(r'systemConfig.update'),
|
||||
systemMetadataPeriodRead._(r'systemMetadata.read'),
|
||||
systemMetadataPeriodUpdate._(r'systemMetadata.update'),
|
||||
tagPeriodCreate._(r'tag.create'),
|
||||
tagPeriodRead._(r'tag.read'),
|
||||
tagPeriodUpdate._(r'tag.update'),
|
||||
tagPeriodDelete._(r'tag.delete'),
|
||||
tagPeriodAsset._(r'tag.asset'),
|
||||
userPeriodRead._(r'user.read'),
|
||||
userPeriodUpdate._(r'user.update'),
|
||||
userLicensePeriodCreate._(r'userLicense.create'),
|
||||
userLicensePeriodRead._(r'userLicense.read'),
|
||||
userLicensePeriodUpdate._(r'userLicense.update'),
|
||||
userLicensePeriodDelete._(r'userLicense.delete'),
|
||||
userOnboardingPeriodRead._(r'userOnboarding.read'),
|
||||
userOnboardingPeriodUpdate._(r'userOnboarding.update'),
|
||||
userOnboardingPeriodDelete._(r'userOnboarding.delete'),
|
||||
userPreferencePeriodRead._(r'userPreference.read'),
|
||||
userPreferencePeriodUpdate._(r'userPreference.update'),
|
||||
userProfileImagePeriodCreate._(r'userProfileImage.create'),
|
||||
userProfileImagePeriodRead._(r'userProfileImage.read'),
|
||||
userProfileImagePeriodUpdate._(r'userProfileImage.update'),
|
||||
userProfileImagePeriodDelete._(r'userProfileImage.delete'),
|
||||
queuePeriodRead._(r'queue.read'),
|
||||
queuePeriodUpdate._(r'queue.update'),
|
||||
queueJobPeriodCreate._(r'queueJob.create'),
|
||||
queueJobPeriodRead._(r'queueJob.read'),
|
||||
queueJobPeriodUpdate._(r'queueJob.update'),
|
||||
queueJobPeriodDelete._(r'queueJob.delete'),
|
||||
workflowPeriodCreate._(r'workflow.create'),
|
||||
workflowPeriodRead._(r'workflow.read'),
|
||||
workflowPeriodUpdate._(r'workflow.update'),
|
||||
workflowPeriodDelete._(r'workflow.delete'),
|
||||
adminUserPeriodCreate._(r'adminUser.create'),
|
||||
adminUserPeriodRead._(r'adminUser.read'),
|
||||
adminUserPeriodUpdate._(r'adminUser.update'),
|
||||
adminUserPeriodDelete._(r'adminUser.delete'),
|
||||
adminSessionPeriodRead._(r'adminSession.read'),
|
||||
adminAuthPeriodUnlinkAll._(r'adminAuth.unlinkAll'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const Permission._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const all = Permission._(r'all');
|
||||
static const activityPeriodCreate = Permission._(r'activity.create');
|
||||
static const activityPeriodRead = Permission._(r'activity.read');
|
||||
static const activityPeriodUpdate = Permission._(r'activity.update');
|
||||
static const activityPeriodDelete = Permission._(r'activity.delete');
|
||||
static const activityPeriodStatistics = Permission._(r'activity.statistics');
|
||||
static const apiKeyPeriodCreate = Permission._(r'apiKey.create');
|
||||
static const apiKeyPeriodRead = Permission._(r'apiKey.read');
|
||||
static const apiKeyPeriodUpdate = Permission._(r'apiKey.update');
|
||||
static const apiKeyPeriodDelete = Permission._(r'apiKey.delete');
|
||||
static const assetPeriodRead = Permission._(r'asset.read');
|
||||
static const assetPeriodUpdate = Permission._(r'asset.update');
|
||||
static const assetPeriodDelete = Permission._(r'asset.delete');
|
||||
static const assetPeriodStatistics = Permission._(r'asset.statistics');
|
||||
static const assetPeriodShare = Permission._(r'asset.share');
|
||||
static const assetPeriodView = Permission._(r'asset.view');
|
||||
static const assetPeriodDownload = Permission._(r'asset.download');
|
||||
static const assetPeriodUpload = Permission._(r'asset.upload');
|
||||
static const assetPeriodCopy = Permission._(r'asset.copy');
|
||||
static const assetPeriodDerive = Permission._(r'asset.derive');
|
||||
static const assetPeriodEditPeriodGet = Permission._(r'asset.edit.get');
|
||||
static const assetPeriodEditPeriodCreate = Permission._(r'asset.edit.create');
|
||||
static const assetPeriodEditPeriodDelete = Permission._(r'asset.edit.delete');
|
||||
static const albumPeriodCreate = Permission._(r'album.create');
|
||||
static const albumPeriodRead = Permission._(r'album.read');
|
||||
static const albumPeriodUpdate = Permission._(r'album.update');
|
||||
static const albumPeriodDelete = Permission._(r'album.delete');
|
||||
static const albumPeriodStatistics = Permission._(r'album.statistics');
|
||||
static const albumPeriodShare = Permission._(r'album.share');
|
||||
static const albumPeriodDownload = Permission._(r'album.download');
|
||||
static const albumAssetPeriodCreate = Permission._(r'albumAsset.create');
|
||||
static const albumAssetPeriodDelete = Permission._(r'albumAsset.delete');
|
||||
static const albumUserPeriodCreate = Permission._(r'albumUser.create');
|
||||
static const albumUserPeriodUpdate = Permission._(r'albumUser.update');
|
||||
static const albumUserPeriodDelete = Permission._(r'albumUser.delete');
|
||||
static const authPeriodChangePassword = Permission._(r'auth.changePassword');
|
||||
static const authDevicePeriodDelete = Permission._(r'authDevice.delete');
|
||||
static const archivePeriodRead = Permission._(r'archive.read');
|
||||
static const backupPeriodList = Permission._(r'backup.list');
|
||||
static const backupPeriodDownload = Permission._(r'backup.download');
|
||||
static const backupPeriodUpload = Permission._(r'backup.upload');
|
||||
static const backupPeriodDelete = Permission._(r'backup.delete');
|
||||
static const duplicatePeriodRead = Permission._(r'duplicate.read');
|
||||
static const duplicatePeriodDelete = Permission._(r'duplicate.delete');
|
||||
static const facePeriodCreate = Permission._(r'face.create');
|
||||
static const facePeriodRead = Permission._(r'face.read');
|
||||
static const facePeriodUpdate = Permission._(r'face.update');
|
||||
static const facePeriodDelete = Permission._(r'face.delete');
|
||||
static const folderPeriodRead = Permission._(r'folder.read');
|
||||
static const jobPeriodCreate = Permission._(r'job.create');
|
||||
static const jobPeriodRead = Permission._(r'job.read');
|
||||
static const libraryPeriodCreate = Permission._(r'library.create');
|
||||
static const libraryPeriodRead = Permission._(r'library.read');
|
||||
static const libraryPeriodUpdate = Permission._(r'library.update');
|
||||
static const libraryPeriodDelete = Permission._(r'library.delete');
|
||||
static const libraryPeriodStatistics = Permission._(r'library.statistics');
|
||||
static const timelinePeriodRead = Permission._(r'timeline.read');
|
||||
static const timelinePeriodDownload = Permission._(r'timeline.download');
|
||||
static const maintenance = Permission._(r'maintenance');
|
||||
static const mapPeriodRead = Permission._(r'map.read');
|
||||
static const mapPeriodSearch = Permission._(r'map.search');
|
||||
static const memoryPeriodCreate = Permission._(r'memory.create');
|
||||
static const memoryPeriodRead = Permission._(r'memory.read');
|
||||
static const memoryPeriodUpdate = Permission._(r'memory.update');
|
||||
static const memoryPeriodDelete = Permission._(r'memory.delete');
|
||||
static const memoryPeriodStatistics = Permission._(r'memory.statistics');
|
||||
static const memoryAssetPeriodCreate = Permission._(r'memoryAsset.create');
|
||||
static const memoryAssetPeriodDelete = Permission._(r'memoryAsset.delete');
|
||||
static const notificationPeriodCreate = Permission._(r'notification.create');
|
||||
static const notificationPeriodRead = Permission._(r'notification.read');
|
||||
static const notificationPeriodUpdate = Permission._(r'notification.update');
|
||||
static const notificationPeriodDelete = Permission._(r'notification.delete');
|
||||
static const partnerPeriodCreate = Permission._(r'partner.create');
|
||||
static const partnerPeriodRead = Permission._(r'partner.read');
|
||||
static const partnerPeriodUpdate = Permission._(r'partner.update');
|
||||
static const partnerPeriodDelete = Permission._(r'partner.delete');
|
||||
static const personPeriodCreate = Permission._(r'person.create');
|
||||
static const personPeriodRead = Permission._(r'person.read');
|
||||
static const personPeriodUpdate = Permission._(r'person.update');
|
||||
static const personPeriodDelete = Permission._(r'person.delete');
|
||||
static const personPeriodStatistics = Permission._(r'person.statistics');
|
||||
static const personPeriodMerge = Permission._(r'person.merge');
|
||||
static const personPeriodReassign = Permission._(r'person.reassign');
|
||||
static const pinCodePeriodCreate = Permission._(r'pinCode.create');
|
||||
static const pinCodePeriodUpdate = Permission._(r'pinCode.update');
|
||||
static const pinCodePeriodDelete = Permission._(r'pinCode.delete');
|
||||
static const pluginPeriodCreate = Permission._(r'plugin.create');
|
||||
static const pluginPeriodRead = Permission._(r'plugin.read');
|
||||
static const pluginPeriodUpdate = Permission._(r'plugin.update');
|
||||
static const pluginPeriodDelete = Permission._(r'plugin.delete');
|
||||
static const serverPeriodAbout = Permission._(r'server.about');
|
||||
static const serverPeriodApkLinks = Permission._(r'server.apkLinks');
|
||||
static const serverPeriodStorage = Permission._(r'server.storage');
|
||||
static const serverPeriodStatistics = Permission._(r'server.statistics');
|
||||
static const serverPeriodVersionCheck = Permission._(r'server.versionCheck');
|
||||
static const serverLicensePeriodRead = Permission._(r'serverLicense.read');
|
||||
static const serverLicensePeriodUpdate = Permission._(r'serverLicense.update');
|
||||
static const serverLicensePeriodDelete = Permission._(r'serverLicense.delete');
|
||||
static const sessionPeriodCreate = Permission._(r'session.create');
|
||||
static const sessionPeriodRead = Permission._(r'session.read');
|
||||
static const sessionPeriodUpdate = Permission._(r'session.update');
|
||||
static const sessionPeriodDelete = Permission._(r'session.delete');
|
||||
static const sessionPeriodLock = Permission._(r'session.lock');
|
||||
static const sharedLinkPeriodCreate = Permission._(r'sharedLink.create');
|
||||
static const sharedLinkPeriodRead = Permission._(r'sharedLink.read');
|
||||
static const sharedLinkPeriodUpdate = Permission._(r'sharedLink.update');
|
||||
static const sharedLinkPeriodDelete = Permission._(r'sharedLink.delete');
|
||||
static const stackPeriodCreate = Permission._(r'stack.create');
|
||||
static const stackPeriodRead = Permission._(r'stack.read');
|
||||
static const stackPeriodUpdate = Permission._(r'stack.update');
|
||||
static const stackPeriodDelete = Permission._(r'stack.delete');
|
||||
static const syncPeriodStream = Permission._(r'sync.stream');
|
||||
static const syncCheckpointPeriodRead = Permission._(r'syncCheckpoint.read');
|
||||
static const syncCheckpointPeriodUpdate = Permission._(r'syncCheckpoint.update');
|
||||
static const syncCheckpointPeriodDelete = Permission._(r'syncCheckpoint.delete');
|
||||
static const systemConfigPeriodRead = Permission._(r'systemConfig.read');
|
||||
static const systemConfigPeriodUpdate = Permission._(r'systemConfig.update');
|
||||
static const systemMetadataPeriodRead = Permission._(r'systemMetadata.read');
|
||||
static const systemMetadataPeriodUpdate = Permission._(r'systemMetadata.update');
|
||||
static const tagPeriodCreate = Permission._(r'tag.create');
|
||||
static const tagPeriodRead = Permission._(r'tag.read');
|
||||
static const tagPeriodUpdate = Permission._(r'tag.update');
|
||||
static const tagPeriodDelete = Permission._(r'tag.delete');
|
||||
static const tagPeriodAsset = Permission._(r'tag.asset');
|
||||
static const userPeriodRead = Permission._(r'user.read');
|
||||
static const userPeriodUpdate = Permission._(r'user.update');
|
||||
static const userLicensePeriodCreate = Permission._(r'userLicense.create');
|
||||
static const userLicensePeriodRead = Permission._(r'userLicense.read');
|
||||
static const userLicensePeriodUpdate = Permission._(r'userLicense.update');
|
||||
static const userLicensePeriodDelete = Permission._(r'userLicense.delete');
|
||||
static const userOnboardingPeriodRead = Permission._(r'userOnboarding.read');
|
||||
static const userOnboardingPeriodUpdate = Permission._(r'userOnboarding.update');
|
||||
static const userOnboardingPeriodDelete = Permission._(r'userOnboarding.delete');
|
||||
static const userPreferencePeriodRead = Permission._(r'userPreference.read');
|
||||
static const userPreferencePeriodUpdate = Permission._(r'userPreference.update');
|
||||
static const userProfileImagePeriodCreate = Permission._(r'userProfileImage.create');
|
||||
static const userProfileImagePeriodRead = Permission._(r'userProfileImage.read');
|
||||
static const userProfileImagePeriodUpdate = Permission._(r'userProfileImage.update');
|
||||
static const userProfileImagePeriodDelete = Permission._(r'userProfileImage.delete');
|
||||
static const queuePeriodRead = Permission._(r'queue.read');
|
||||
static const queuePeriodUpdate = Permission._(r'queue.update');
|
||||
static const queueJobPeriodCreate = Permission._(r'queueJob.create');
|
||||
static const queueJobPeriodRead = Permission._(r'queueJob.read');
|
||||
static const queueJobPeriodUpdate = Permission._(r'queueJob.update');
|
||||
static const queueJobPeriodDelete = Permission._(r'queueJob.delete');
|
||||
static const workflowPeriodCreate = Permission._(r'workflow.create');
|
||||
static const workflowPeriodRead = Permission._(r'workflow.read');
|
||||
static const workflowPeriodUpdate = Permission._(r'workflow.update');
|
||||
static const workflowPeriodDelete = Permission._(r'workflow.delete');
|
||||
static const adminUserPeriodCreate = Permission._(r'adminUser.create');
|
||||
static const adminUserPeriodRead = Permission._(r'adminUser.read');
|
||||
static const adminUserPeriodUpdate = Permission._(r'adminUser.update');
|
||||
static const adminUserPeriodDelete = Permission._(r'adminUser.delete');
|
||||
static const adminSessionPeriodRead = Permission._(r'adminSession.read');
|
||||
static const adminAuthPeriodUnlinkAll = Permission._(r'adminAuth.unlinkAll');
|
||||
|
||||
/// List of all possible values in this [enum][Permission].
|
||||
static const values = <Permission>[
|
||||
all,
|
||||
activityPeriodCreate,
|
||||
activityPeriodRead,
|
||||
activityPeriodUpdate,
|
||||
activityPeriodDelete,
|
||||
activityPeriodStatistics,
|
||||
apiKeyPeriodCreate,
|
||||
apiKeyPeriodRead,
|
||||
apiKeyPeriodUpdate,
|
||||
apiKeyPeriodDelete,
|
||||
assetPeriodRead,
|
||||
assetPeriodUpdate,
|
||||
assetPeriodDelete,
|
||||
assetPeriodStatistics,
|
||||
assetPeriodShare,
|
||||
assetPeriodView,
|
||||
assetPeriodDownload,
|
||||
assetPeriodUpload,
|
||||
assetPeriodCopy,
|
||||
assetPeriodDerive,
|
||||
assetPeriodEditPeriodGet,
|
||||
assetPeriodEditPeriodCreate,
|
||||
assetPeriodEditPeriodDelete,
|
||||
albumPeriodCreate,
|
||||
albumPeriodRead,
|
||||
albumPeriodUpdate,
|
||||
albumPeriodDelete,
|
||||
albumPeriodStatistics,
|
||||
albumPeriodShare,
|
||||
albumPeriodDownload,
|
||||
albumAssetPeriodCreate,
|
||||
albumAssetPeriodDelete,
|
||||
albumUserPeriodCreate,
|
||||
albumUserPeriodUpdate,
|
||||
albumUserPeriodDelete,
|
||||
authPeriodChangePassword,
|
||||
authDevicePeriodDelete,
|
||||
archivePeriodRead,
|
||||
backupPeriodList,
|
||||
backupPeriodDownload,
|
||||
backupPeriodUpload,
|
||||
backupPeriodDelete,
|
||||
duplicatePeriodRead,
|
||||
duplicatePeriodDelete,
|
||||
facePeriodCreate,
|
||||
facePeriodRead,
|
||||
facePeriodUpdate,
|
||||
facePeriodDelete,
|
||||
folderPeriodRead,
|
||||
jobPeriodCreate,
|
||||
jobPeriodRead,
|
||||
libraryPeriodCreate,
|
||||
libraryPeriodRead,
|
||||
libraryPeriodUpdate,
|
||||
libraryPeriodDelete,
|
||||
libraryPeriodStatistics,
|
||||
timelinePeriodRead,
|
||||
timelinePeriodDownload,
|
||||
maintenance,
|
||||
mapPeriodRead,
|
||||
mapPeriodSearch,
|
||||
memoryPeriodCreate,
|
||||
memoryPeriodRead,
|
||||
memoryPeriodUpdate,
|
||||
memoryPeriodDelete,
|
||||
memoryPeriodStatistics,
|
||||
memoryAssetPeriodCreate,
|
||||
memoryAssetPeriodDelete,
|
||||
notificationPeriodCreate,
|
||||
notificationPeriodRead,
|
||||
notificationPeriodUpdate,
|
||||
notificationPeriodDelete,
|
||||
partnerPeriodCreate,
|
||||
partnerPeriodRead,
|
||||
partnerPeriodUpdate,
|
||||
partnerPeriodDelete,
|
||||
personPeriodCreate,
|
||||
personPeriodRead,
|
||||
personPeriodUpdate,
|
||||
personPeriodDelete,
|
||||
personPeriodStatistics,
|
||||
personPeriodMerge,
|
||||
personPeriodReassign,
|
||||
pinCodePeriodCreate,
|
||||
pinCodePeriodUpdate,
|
||||
pinCodePeriodDelete,
|
||||
pluginPeriodCreate,
|
||||
pluginPeriodRead,
|
||||
pluginPeriodUpdate,
|
||||
pluginPeriodDelete,
|
||||
serverPeriodAbout,
|
||||
serverPeriodApkLinks,
|
||||
serverPeriodStorage,
|
||||
serverPeriodStatistics,
|
||||
serverPeriodVersionCheck,
|
||||
serverLicensePeriodRead,
|
||||
serverLicensePeriodUpdate,
|
||||
serverLicensePeriodDelete,
|
||||
sessionPeriodCreate,
|
||||
sessionPeriodRead,
|
||||
sessionPeriodUpdate,
|
||||
sessionPeriodDelete,
|
||||
sessionPeriodLock,
|
||||
sharedLinkPeriodCreate,
|
||||
sharedLinkPeriodRead,
|
||||
sharedLinkPeriodUpdate,
|
||||
sharedLinkPeriodDelete,
|
||||
stackPeriodCreate,
|
||||
stackPeriodRead,
|
||||
stackPeriodUpdate,
|
||||
stackPeriodDelete,
|
||||
syncPeriodStream,
|
||||
syncCheckpointPeriodRead,
|
||||
syncCheckpointPeriodUpdate,
|
||||
syncCheckpointPeriodDelete,
|
||||
systemConfigPeriodRead,
|
||||
systemConfigPeriodUpdate,
|
||||
systemMetadataPeriodRead,
|
||||
systemMetadataPeriodUpdate,
|
||||
tagPeriodCreate,
|
||||
tagPeriodRead,
|
||||
tagPeriodUpdate,
|
||||
tagPeriodDelete,
|
||||
tagPeriodAsset,
|
||||
userPeriodRead,
|
||||
userPeriodUpdate,
|
||||
userLicensePeriodCreate,
|
||||
userLicensePeriodRead,
|
||||
userLicensePeriodUpdate,
|
||||
userLicensePeriodDelete,
|
||||
userOnboardingPeriodRead,
|
||||
userOnboardingPeriodUpdate,
|
||||
userOnboardingPeriodDelete,
|
||||
userPreferencePeriodRead,
|
||||
userPreferencePeriodUpdate,
|
||||
userProfileImagePeriodCreate,
|
||||
userProfileImagePeriodRead,
|
||||
userProfileImagePeriodUpdate,
|
||||
userProfileImagePeriodDelete,
|
||||
queuePeriodRead,
|
||||
queuePeriodUpdate,
|
||||
queueJobPeriodCreate,
|
||||
queueJobPeriodRead,
|
||||
queueJobPeriodUpdate,
|
||||
queueJobPeriodDelete,
|
||||
workflowPeriodCreate,
|
||||
workflowPeriodRead,
|
||||
workflowPeriodUpdate,
|
||||
workflowPeriodDelete,
|
||||
adminUserPeriodCreate,
|
||||
adminUserPeriodRead,
|
||||
adminUserPeriodUpdate,
|
||||
adminUserPeriodDelete,
|
||||
adminSessionPeriodRead,
|
||||
adminAuthPeriodUnlinkAll,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [Permission] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static Permission? fromJson(dynamic value) => PermissionTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [Permission]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<Permission> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <Permission>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -361,9 +208,11 @@ class PermissionTypeTransformer {
|
||||
|
||||
const PermissionTypeTransformer._();
|
||||
|
||||
String encode(Permission data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(Permission data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a Permission.
|
||||
/// Returns the instance of [Permission] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -372,6 +221,9 @@ class PermissionTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
Permission? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is Permission) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'all': return Permission.all;
|
||||
@@ -538,7 +390,7 @@ class PermissionTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [PermissionTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static PermissionTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
50
mobile/openapi/lib/model/queue_command.dart
generated
50
mobile/openapi/lib/model/queue_command.dart
generated
@@ -11,35 +11,32 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Queue command to execute
|
||||
class QueueCommand {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const QueueCommand._(this.value);
|
||||
enum QueueCommand {
|
||||
start._(r'start'),
|
||||
pause._(r'pause'),
|
||||
resume._(r'resume'),
|
||||
empty._(r'empty'),
|
||||
clearFailed._(r'clear-failed'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const QueueCommand._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const start = QueueCommand._(r'start');
|
||||
static const pause = QueueCommand._(r'pause');
|
||||
static const resume = QueueCommand._(r'resume');
|
||||
static const empty = QueueCommand._(r'empty');
|
||||
static const clearFailed = QueueCommand._(r'clear-failed');
|
||||
|
||||
/// List of all possible values in this [enum][QueueCommand].
|
||||
static const values = <QueueCommand>[
|
||||
start,
|
||||
pause,
|
||||
resume,
|
||||
empty,
|
||||
clearFailed,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [QueueCommand] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static QueueCommand? fromJson(dynamic value) => QueueCommandTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [QueueCommand]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<QueueCommand> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <QueueCommand>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -61,9 +58,11 @@ class QueueCommandTypeTransformer {
|
||||
|
||||
const QueueCommandTypeTransformer._();
|
||||
|
||||
String encode(QueueCommand data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(QueueCommand data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a QueueCommand.
|
||||
/// Returns the instance of [QueueCommand] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -72,6 +71,9 @@ class QueueCommandTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
QueueCommand? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is QueueCommand) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'start': return QueueCommand.start;
|
||||
@@ -88,7 +90,7 @@ class QueueCommandTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [QueueCommandTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static QueueCommandTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
53
mobile/openapi/lib/model/queue_job_status.dart
generated
53
mobile/openapi/lib/model/queue_job_status.dart
generated
@@ -11,37 +11,33 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Queue job status
|
||||
class QueueJobStatus {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const QueueJobStatus._(this.value);
|
||||
enum QueueJobStatus {
|
||||
active._(r'active'),
|
||||
failed._(r'failed'),
|
||||
completed._(r'completed'),
|
||||
delayed._(r'delayed'),
|
||||
waiting._(r'waiting'),
|
||||
paused._(r'paused'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const QueueJobStatus._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const active = QueueJobStatus._(r'active');
|
||||
static const failed = QueueJobStatus._(r'failed');
|
||||
static const completed = QueueJobStatus._(r'completed');
|
||||
static const delayed = QueueJobStatus._(r'delayed');
|
||||
static const waiting = QueueJobStatus._(r'waiting');
|
||||
static const paused = QueueJobStatus._(r'paused');
|
||||
|
||||
/// List of all possible values in this [enum][QueueJobStatus].
|
||||
static const values = <QueueJobStatus>[
|
||||
active,
|
||||
failed,
|
||||
completed,
|
||||
delayed,
|
||||
waiting,
|
||||
paused,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [QueueJobStatus] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static QueueJobStatus? fromJson(dynamic value) => QueueJobStatusTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [QueueJobStatus]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<QueueJobStatus> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <QueueJobStatus>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -63,9 +59,11 @@ class QueueJobStatusTypeTransformer {
|
||||
|
||||
const QueueJobStatusTypeTransformer._();
|
||||
|
||||
String encode(QueueJobStatus data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(QueueJobStatus data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a QueueJobStatus.
|
||||
/// Returns the instance of [QueueJobStatus] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -74,6 +72,9 @@ class QueueJobStatusTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
QueueJobStatus? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is QueueJobStatus) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'active': return QueueJobStatus.active;
|
||||
@@ -91,7 +92,7 @@ class QueueJobStatusTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [QueueJobStatusTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static QueueJobStatusTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
92
mobile/openapi/lib/model/queue_name.dart
generated
92
mobile/openapi/lib/model/queue_name.dart
generated
@@ -11,63 +11,46 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Queue name
|
||||
class QueueName {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const QueueName._(this.value);
|
||||
enum QueueName {
|
||||
thumbnailGeneration._(r'thumbnailGeneration'),
|
||||
metadataExtraction._(r'metadataExtraction'),
|
||||
videoConversion._(r'videoConversion'),
|
||||
faceDetection._(r'faceDetection'),
|
||||
facialRecognition._(r'facialRecognition'),
|
||||
smartSearch._(r'smartSearch'),
|
||||
duplicateDetection._(r'duplicateDetection'),
|
||||
backgroundTask._(r'backgroundTask'),
|
||||
storageTemplateMigration._(r'storageTemplateMigration'),
|
||||
migration._(r'migration'),
|
||||
search._(r'search'),
|
||||
sidecar._(r'sidecar'),
|
||||
library_._(r'library'),
|
||||
notifications._(r'notifications'),
|
||||
backupDatabase._(r'backupDatabase'),
|
||||
ocr._(r'ocr'),
|
||||
workflow._(r'workflow'),
|
||||
integrityCheck._(r'integrityCheck'),
|
||||
editor._(r'editor'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const QueueName._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const thumbnailGeneration = QueueName._(r'thumbnailGeneration');
|
||||
static const metadataExtraction = QueueName._(r'metadataExtraction');
|
||||
static const videoConversion = QueueName._(r'videoConversion');
|
||||
static const faceDetection = QueueName._(r'faceDetection');
|
||||
static const facialRecognition = QueueName._(r'facialRecognition');
|
||||
static const smartSearch = QueueName._(r'smartSearch');
|
||||
static const duplicateDetection = QueueName._(r'duplicateDetection');
|
||||
static const backgroundTask = QueueName._(r'backgroundTask');
|
||||
static const storageTemplateMigration = QueueName._(r'storageTemplateMigration');
|
||||
static const migration = QueueName._(r'migration');
|
||||
static const search = QueueName._(r'search');
|
||||
static const sidecar = QueueName._(r'sidecar');
|
||||
static const library_ = QueueName._(r'library');
|
||||
static const notifications = QueueName._(r'notifications');
|
||||
static const backupDatabase = QueueName._(r'backupDatabase');
|
||||
static const ocr = QueueName._(r'ocr');
|
||||
static const workflow = QueueName._(r'workflow');
|
||||
static const integrityCheck = QueueName._(r'integrityCheck');
|
||||
static const editor = QueueName._(r'editor');
|
||||
|
||||
/// List of all possible values in this [enum][QueueName].
|
||||
static const values = <QueueName>[
|
||||
thumbnailGeneration,
|
||||
metadataExtraction,
|
||||
videoConversion,
|
||||
faceDetection,
|
||||
facialRecognition,
|
||||
smartSearch,
|
||||
duplicateDetection,
|
||||
backgroundTask,
|
||||
storageTemplateMigration,
|
||||
migration,
|
||||
search,
|
||||
sidecar,
|
||||
library_,
|
||||
notifications,
|
||||
backupDatabase,
|
||||
ocr,
|
||||
workflow,
|
||||
integrityCheck,
|
||||
editor,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [QueueName] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static QueueName? fromJson(dynamic value) => QueueNameTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [QueueName]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<QueueName> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <QueueName>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -89,9 +72,11 @@ class QueueNameTypeTransformer {
|
||||
|
||||
const QueueNameTypeTransformer._();
|
||||
|
||||
String encode(QueueName data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(QueueName data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a QueueName.
|
||||
/// Returns the instance of [QueueName] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -100,6 +85,9 @@ class QueueNameTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
QueueName? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is QueueName) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'thumbnailGeneration': return QueueName.thumbnailGeneration;
|
||||
@@ -130,7 +118,7 @@ class QueueNameTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [QueueNameTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static QueueNameTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/reaction_level.dart
generated
41
mobile/openapi/lib/model/reaction_level.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Reaction level
|
||||
class ReactionLevel {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ReactionLevel._(this.value);
|
||||
enum ReactionLevel {
|
||||
album._(r'album'),
|
||||
asset._(r'asset'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const ReactionLevel._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const album = ReactionLevel._(r'album');
|
||||
static const asset = ReactionLevel._(r'asset');
|
||||
|
||||
/// List of all possible values in this [enum][ReactionLevel].
|
||||
static const values = <ReactionLevel>[
|
||||
album,
|
||||
asset,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [ReactionLevel] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static ReactionLevel? fromJson(dynamic value) => ReactionLevelTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [ReactionLevel]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<ReactionLevel> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ReactionLevel>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class ReactionLevelTypeTransformer {
|
||||
|
||||
const ReactionLevelTypeTransformer._();
|
||||
|
||||
String encode(ReactionLevel data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(ReactionLevel data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ReactionLevel.
|
||||
/// Returns the instance of [ReactionLevel] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class ReactionLevelTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ReactionLevel? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is ReactionLevel) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'album': return ReactionLevel.album;
|
||||
@@ -79,7 +84,7 @@ class ReactionLevelTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ReactionLevelTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ReactionLevelTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/reaction_type.dart
generated
41
mobile/openapi/lib/model/reaction_type.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Reaction type
|
||||
class ReactionType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ReactionType._(this.value);
|
||||
enum ReactionType {
|
||||
comment._(r'comment'),
|
||||
like._(r'like'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const ReactionType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const comment = ReactionType._(r'comment');
|
||||
static const like = ReactionType._(r'like');
|
||||
|
||||
/// List of all possible values in this [enum][ReactionType].
|
||||
static const values = <ReactionType>[
|
||||
comment,
|
||||
like,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [ReactionType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static ReactionType? fromJson(dynamic value) => ReactionTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [ReactionType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<ReactionType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ReactionType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class ReactionTypeTypeTransformer {
|
||||
|
||||
const ReactionTypeTypeTransformer._();
|
||||
|
||||
String encode(ReactionType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(ReactionType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ReactionType.
|
||||
/// Returns the instance of [ReactionType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class ReactionTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ReactionType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is ReactionType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'comment': return ReactionType.comment;
|
||||
@@ -79,7 +84,7 @@ class ReactionTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ReactionTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ReactionTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
41
mobile/openapi/lib/model/release_channel.dart
generated
41
mobile/openapi/lib/model/release_channel.dart
generated
@@ -11,29 +11,29 @@
|
||||
part of openapi.api;
|
||||
|
||||
/// Release channel
|
||||
class ReleaseChannel {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ReleaseChannel._(this.value);
|
||||
enum ReleaseChannel {
|
||||
stable._(r'stable'),
|
||||
releaseCandidate._(r'releaseCandidate'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const ReleaseChannel._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const stable = ReleaseChannel._(r'stable');
|
||||
static const releaseCandidate = ReleaseChannel._(r'releaseCandidate');
|
||||
|
||||
/// List of all possible values in this [enum][ReleaseChannel].
|
||||
static const values = <ReleaseChannel>[
|
||||
stable,
|
||||
releaseCandidate,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [ReleaseChannel] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static ReleaseChannel? fromJson(dynamic value) => ReleaseChannelTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [ReleaseChannel]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<ReleaseChannel> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ReleaseChannel>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -55,9 +55,11 @@ class ReleaseChannelTypeTransformer {
|
||||
|
||||
const ReleaseChannelTypeTransformer._();
|
||||
|
||||
String encode(ReleaseChannel data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(ReleaseChannel data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ReleaseChannel.
|
||||
/// Returns the instance of [ReleaseChannel] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -66,6 +68,9 @@ class ReleaseChannelTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ReleaseChannel? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is ReleaseChannel) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'stable': return ReleaseChannel.stable;
|
||||
@@ -79,7 +84,7 @@ class ReleaseChannelTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ReleaseChannelTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ReleaseChannelTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
56
mobile/openapi/lib/model/release_type.dart
generated
56
mobile/openapi/lib/model/release_type.dart
generated
@@ -11,39 +11,34 @@
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class ReleaseType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const ReleaseType._(this.value);
|
||||
enum ReleaseType {
|
||||
major._(r'major'),
|
||||
premajor._(r'premajor'),
|
||||
minor._(r'minor'),
|
||||
preminor._(r'preminor'),
|
||||
patch_._(r'patch'),
|
||||
prepatch._(r'prepatch'),
|
||||
prerelease._(r'prerelease'),
|
||||
;
|
||||
|
||||
/// Instantiate a new enum with the provided value.
|
||||
const ReleaseType._(this._value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
final String _value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
String toString() => _value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const major = ReleaseType._(r'major');
|
||||
static const premajor = ReleaseType._(r'premajor');
|
||||
static const minor = ReleaseType._(r'minor');
|
||||
static const preminor = ReleaseType._(r'preminor');
|
||||
static const patch_ = ReleaseType._(r'patch');
|
||||
static const prepatch = ReleaseType._(r'prepatch');
|
||||
static const prerelease = ReleaseType._(r'prerelease');
|
||||
|
||||
/// List of all possible values in this [enum][ReleaseType].
|
||||
static const values = <ReleaseType>[
|
||||
major,
|
||||
premajor,
|
||||
minor,
|
||||
preminor,
|
||||
patch_,
|
||||
prepatch,
|
||||
prerelease,
|
||||
];
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String toJson() => _value;
|
||||
|
||||
/// Returns the instance of [ReleaseType] that was successfully decoded
|
||||
/// from the passed [value] on success, null otherwise.
|
||||
static ReleaseType? fromJson(dynamic value) => ReleaseTypeTypeTransformer().decode(value);
|
||||
|
||||
/// Returns a [List] containing instances of [ReleaseType]
|
||||
/// that were successfully decoded from the passed [JSON][json].
|
||||
static List<ReleaseType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <ReleaseType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
@@ -65,9 +60,11 @@ class ReleaseTypeTypeTransformer {
|
||||
|
||||
const ReleaseTypeTypeTransformer._();
|
||||
|
||||
String encode(ReleaseType data) => data.value;
|
||||
/// Encodes this enum as a value suitable for JSON.
|
||||
String encode(ReleaseType data) => data._value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a ReleaseType.
|
||||
/// Returns the instance of [ReleaseType] that was successfully decoded
|
||||
/// from the passed [data] value on success, null otherwise.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
@@ -76,6 +73,9 @@ class ReleaseTypeTypeTransformer {
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
ReleaseType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data is ReleaseType) {
|
||||
return data;
|
||||
}
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'major': return ReleaseType.major;
|
||||
@@ -94,7 +94,7 @@ class ReleaseTypeTypeTransformer {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [ReleaseTypeTypeTransformer] instance.
|
||||
/// The singleton instance of this transformer.
|
||||
static ReleaseTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user