Merge branch 'main' of https://github.com/immich-app/immich into feat/cli-e2e
This commit is contained in:
commit
f6889c4d45
110 changed files with 687 additions and 856 deletions
14
cli/package-lock.json
generated
14
cli/package-lock.json
generated
|
@ -35,7 +35,7 @@
|
|||
"@typescript-eslint/parser": "^5.48.1",
|
||||
"chai": "^4.3.7",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-jest": "^27.2.2",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-unicorn": "^47.0.0",
|
||||
|
@ -3275,9 +3275,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-config-prettier": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
|
||||
"integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
|
||||
"integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
|
@ -9872,9 +9872,9 @@
|
|||
}
|
||||
},
|
||||
"eslint-config-prettier": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
|
||||
"integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
|
||||
"integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"@typescript-eslint/parser": "^5.48.1",
|
||||
"chai": "^4.3.7",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-jest": "^27.2.2",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-unicorn": "^47.0.0",
|
||||
|
|
2
cli/src/api/open-api/api.ts
generated
2
cli/src/api/open-api/api.ts
generated
|
@ -4,7 +4,7 @@
|
|||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.87.0
|
||||
* The version of the OpenAPI document: 1.88.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
|
2
cli/src/api/open-api/base.ts
generated
2
cli/src/api/open-api/base.ts
generated
|
@ -4,7 +4,7 @@
|
|||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.87.0
|
||||
* The version of the OpenAPI document: 1.88.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
|
2
cli/src/api/open-api/common.ts
generated
2
cli/src/api/open-api/common.ts
generated
|
@ -4,7 +4,7 @@
|
|||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.87.0
|
||||
* The version of the OpenAPI document: 1.88.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
|
2
cli/src/api/open-api/configuration.ts
generated
2
cli/src/api/open-api/configuration.ts
generated
|
@ -4,7 +4,7 @@
|
|||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.87.0
|
||||
* The version of the OpenAPI document: 1.88.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
|
2
cli/src/api/open-api/index.ts
generated
2
cli/src/api/open-api/index.ts
generated
|
@ -4,7 +4,7 @@
|
|||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.87.0
|
||||
* The version of the OpenAPI document: 1.88.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
|
|
@ -15,7 +15,7 @@ If you are looking to import your Google Photos takeout, we recommed this commun
|
|||
|
||||
## Requirements
|
||||
|
||||
- Node.js 18 or above
|
||||
- Node.js 20.0 or above
|
||||
- Npm
|
||||
|
||||
## Installation
|
||||
|
|
|
@ -24,7 +24,7 @@ from .schemas import (
|
|||
TextResponse,
|
||||
)
|
||||
|
||||
MultiPartParser.max_file_size = 2**24 # spools to disk if payload is 16 MiB or larger
|
||||
MultiPartParser.max_file_size = 2**26 # spools to disk if payload is 64 MiB or larger
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
|
|
52
machine-learning/poetry.lock
generated
52
machine-learning/poetry.lock
generated
|
@ -1,4 +1,4 @@
|
|||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiocache"
|
||||
|
@ -2408,35 +2408,35 @@ reference = ["Pillow", "google-re2"]
|
|||
|
||||
[[package]]
|
||||
name = "onnxruntime"
|
||||
version = "1.16.1"
|
||||
version = "1.16.2"
|
||||
description = "ONNX Runtime is a runtime accelerator for Machine Learning models"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "onnxruntime-1.16.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:28b2c7f444b4119950b69370801cd66067f403d19cbaf2a444735d7c269cce4a"},
|
||||
{file = "onnxruntime-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c24e04f33e7899f6aebb03ed51e51d346c1f906b05c5569d58ac9a12d38a2f58"},
|
||||
{file = "onnxruntime-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fa93b166f2d97063dc9f33c5118c5729a4a5dd5617296b6dbef42f9047b3e81"},
|
||||
{file = "onnxruntime-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:042dd9201b3016ee18f8f8bc4609baf11ff34ca1ff489c0a46bcd30919bf883d"},
|
||||
{file = "onnxruntime-1.16.1-cp310-cp310-win32.whl", hash = "sha256:c20aa0591f305012f1b21aad607ed96917c86ae7aede4a4dd95824b3d124ceb7"},
|
||||
{file = "onnxruntime-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:5581873e578917bea76d6434ee7337e28195d03488dcf72d161d08e9398c6249"},
|
||||
{file = "onnxruntime-1.16.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:ef8c0c8abf5f309aa1caf35941380839dc5f7a2fa53da533be4a3f254993f120"},
|
||||
{file = "onnxruntime-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e680380bea35a137cbc3efd67a17486e96972901192ad3026ee79c8d8fe264f7"},
|
||||
{file = "onnxruntime-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e62cc38ce1a669013d0a596d984762dc9c67c56f60ecfeee0d5ad36da5863f6"},
|
||||
{file = "onnxruntime-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:025c7a4d57bd2e63b8a0f84ad3df53e419e3df1cc72d63184f2aae807b17c13c"},
|
||||
{file = "onnxruntime-1.16.1-cp311-cp311-win32.whl", hash = "sha256:9ad074057fa8d028df248b5668514088cb0937b6ac5954073b7fb9b2891ffc8c"},
|
||||
{file = "onnxruntime-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:d5e43a3478bffc01f817ecf826de7b25a2ca1bca8547d70888594ab80a77ad24"},
|
||||
{file = "onnxruntime-1.16.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:3aef4d70b0930e29a8943eab248cd1565664458d3a62b2276bd11181f28fd0a3"},
|
||||
{file = "onnxruntime-1.16.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:55a7b843a57c8ca0c8ff169428137958146081d5d76f1a6dd444c4ffcd37c3c2"},
|
||||
{file = "onnxruntime-1.16.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c631af1941bf3b5f7d063d24c04aacce8cff0794e157c497e315e89ac5ad7b"},
|
||||
{file = "onnxruntime-1.16.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671f296c3d5c233f601e97a10ab5a1dd8e65ba35c7b7b0c253332aba9dff330"},
|
||||
{file = "onnxruntime-1.16.1-cp38-cp38-win32.whl", hash = "sha256:eb3802305023dd05e16848d4e22b41f8147247894309c0c27122aaa08793b3d2"},
|
||||
{file = "onnxruntime-1.16.1-cp38-cp38-win_amd64.whl", hash = "sha256:fecfb07443d09d271b1487f401fbdf1ba0c829af6fd4fe8f6af25f71190e7eb9"},
|
||||
{file = "onnxruntime-1.16.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:de3e12094234db6545c67adbf801874b4eb91e9f299bda34c62967ef0050960f"},
|
||||
{file = "onnxruntime-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ff723c2a5621b5e7103f3be84d5aae1e03a20621e72219dddceae81f65f240af"},
|
||||
{file = "onnxruntime-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14a7fb3073aaf6b462e3d7fb433320f7700558a8892e5021780522dc4574292a"},
|
||||
{file = "onnxruntime-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:963159f1f699b0454cd72fcef3276c8a1aab9389a7b301bcd8e320fb9d9e8597"},
|
||||
{file = "onnxruntime-1.16.1-cp39-cp39-win32.whl", hash = "sha256:85771adb75190db9364b25ddec353ebf07635b83eb94b64ed014f1f6d57a3857"},
|
||||
{file = "onnxruntime-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:d32d2b30799c1f950123c60ae8390818381fd5f88bdf3627eeca10071c155dc5"},
|
||||
{file = "onnxruntime-1.16.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:e19316bb15c29ca0397e78861ee7cdb4db763ac5c53eaa83169bcdcb1149878c"},
|
||||
{file = "onnxruntime-1.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:773f6d99d1e6a58936a55a4933c66674241dace9ec4bab71664cdfa170a7cd87"},
|
||||
{file = "onnxruntime-1.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b8df9583a6e874f1983b85a361d22c205c96e926626eb486d3e69d72642f79"},
|
||||
{file = "onnxruntime-1.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ceef600de846997e3ef5f9af956ae87c88d84d6e925c3e9d435ce17ea223568f"},
|
||||
{file = "onnxruntime-1.16.2-cp310-cp310-win32.whl", hash = "sha256:4fed41edb766c6adea6c34f1eb63a344d697fd4625133e5e48f23950bce60803"},
|
||||
{file = "onnxruntime-1.16.2-cp310-cp310-win_amd64.whl", hash = "sha256:9fc410ec220804fb384e7cb4fd68c474d89da11a1b68184db2001d64ba1477a9"},
|
||||
{file = "onnxruntime-1.16.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:aa09d8d9d9a4dc2f6647b5135bb540da36e2d78206aaf14140ba73e05928c4f8"},
|
||||
{file = "onnxruntime-1.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68f8d3347f11fcc6256266c562e4314b8c6da3e30fc275052a2ab693540b17fd"},
|
||||
{file = "onnxruntime-1.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16217fa87d3482300a91036f9b499c85215a3b495de1ef9a68cbcf3df1a7c548"},
|
||||
{file = "onnxruntime-1.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6b7046005442fcd09b86647bdc9a85d60c1367cb36ce7f16b942744cf27fe4"},
|
||||
{file = "onnxruntime-1.16.2-cp311-cp311-win32.whl", hash = "sha256:773c231e526f815b8a3f3549d216cd8fed4c9e226e9e16e86af1b69a4bd29b58"},
|
||||
{file = "onnxruntime-1.16.2-cp311-cp311-win_amd64.whl", hash = "sha256:90e83a93b3d946c4a1d9dcbae286350accb0d80512d7c1b85953a444d19c0058"},
|
||||
{file = "onnxruntime-1.16.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:8616f56905775dd8beeae11cf145542fff06c38cd97bfe9afe0c4a66142fc6d5"},
|
||||
{file = "onnxruntime-1.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9f5e1d5ca5560044896edb2ad79113f863dc7daa804a26787c7b21c2a96d41e7"},
|
||||
{file = "onnxruntime-1.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97ce538ffb668c4897e7500a586c150a045869876e0234e0611c4e4f428be63"},
|
||||
{file = "onnxruntime-1.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cadf175baa782599f36586c23f84fe12b02702ceb59be57dbd8eefc6cc13cc4"},
|
||||
{file = "onnxruntime-1.16.2-cp38-cp38-win32.whl", hash = "sha256:0ffd3b8a3039be713476b8783d254564976664c9b51ec70e7fb5d3e2832bf0f0"},
|
||||
{file = "onnxruntime-1.16.2-cp38-cp38-win_amd64.whl", hash = "sha256:e2211f336e83819edbf174dcf56de35b0dcbfc6c92d3b685c8d85fba19bdf97d"},
|
||||
{file = "onnxruntime-1.16.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:98a49bda980bcf819f8d9be880e3e7ba8a1df66aa5ce4fc7bb68ba9acf1fc7ad"},
|
||||
{file = "onnxruntime-1.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f1e90fa0f43e988cd043e5a4b1eb77eda6cbd7523f316d93d36b33ff1ceb91f"},
|
||||
{file = "onnxruntime-1.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0cbdb7df8078b2e8d9804de948963961eb8c6f417ef35ed243455162a9a065c"},
|
||||
{file = "onnxruntime-1.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93c1cbd885c5fe0018b982c9dabe3cc3531416a3b50d0958a291605b32fe3ce"},
|
||||
{file = "onnxruntime-1.16.2-cp39-cp39-win32.whl", hash = "sha256:713101b65d74438f380f5ea2475ce4f6026171e6229100e5be2baa92519fca17"},
|
||||
{file = "onnxruntime-1.16.2-cp39-cp39-win_amd64.whl", hash = "sha256:3382934f9d86060b6bacd3eb4633c5ff904be2c99d3a7fb7faf2828381b15928"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "machine-learning"
|
||||
version = "1.87.0"
|
||||
version = "1.88.0"
|
||||
description = ""
|
||||
authors = ["Hau Tran <alex.tran1502@gmail.com>"]
|
||||
readme = "README.md"
|
||||
|
|
|
@ -35,8 +35,8 @@ platform :android do
|
|||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 111,
|
||||
"android.injected.version.name" => "1.87.0",
|
||||
"android.injected.version.code" => 112,
|
||||
"android.injected.version.name" => "1.88.0",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000219">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000263">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="67.071569">
|
||||
<testcase classname="fastlane.lanes" name="1: bundleRelease" time="80.37488">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="29.991184">
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="25.830358">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
"login_password_changed_success": "Password updated successfully",
|
||||
"map_assets_in_bounds": {
|
||||
"one": "{} photo",
|
||||
"many": "{} photos"
|
||||
"other": "{} photos"
|
||||
},
|
||||
"map_cannot_get_user_location": "Cannot get user's location",
|
||||
"map_location_dialog_cancel": "Cancel",
|
||||
|
@ -396,7 +396,7 @@
|
|||
"sharing_page_album": "Shared albums",
|
||||
"sharing_page_description": "Create shared albums to share photos and videos with people in your network.",
|
||||
"sharing_page_empty_list": "EMPTY LIST",
|
||||
"sharing_silver_appbar_create_shared_album": "Create shared album",
|
||||
"sharing_silver_appbar_create_shared_album": "New shared album",
|
||||
"sharing_silver_appbar_shared_links": "Shared links",
|
||||
"sharing_silver_appbar_share_partner": "Share with partner",
|
||||
"tab_controller_nav_library": "Library",
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mobile/fonts/overpass/Overpass-Bold.ttf
Normal file
BIN
mobile/fonts/overpass/Overpass-Bold.ttf
Normal file
Binary file not shown.
BIN
mobile/fonts/overpass/Overpass-Italic.ttf
Normal file
BIN
mobile/fonts/overpass/Overpass-Italic.ttf
Normal file
Binary file not shown.
BIN
mobile/fonts/overpass/Overpass-Medium.ttf
Normal file
BIN
mobile/fonts/overpass/Overpass-Medium.ttf
Normal file
Binary file not shown.
BIN
mobile/fonts/overpass/Overpass-Regular.ttf
Normal file
BIN
mobile/fonts/overpass/Overpass-Regular.ttf
Normal file
Binary file not shown.
BIN
mobile/fonts/overpass/Overpass-SemiBold.ttf
Normal file
BIN
mobile/fonts/overpass/Overpass-SemiBold.ttf
Normal file
Binary file not shown.
BIN
mobile/fonts/overpass/OverpassMono.ttf
Normal file
BIN
mobile/fonts/overpass/OverpassMono.ttf
Normal file
Binary file not shown.
|
@ -379,7 +379,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 127;
|
||||
CURRENT_PROJECT_VERSION = 128;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
@ -515,7 +515,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 127;
|
||||
CURRENT_PROJECT_VERSION = 128;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
@ -543,7 +543,7 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 127;
|
||||
CURRENT_PROJECT_VERSION = 128;
|
||||
DEVELOPMENT_TEAM = 2F67MQ8R79;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
|
|
@ -54,11 +54,11 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.87.0</string>
|
||||
<string>1.88.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>127</string>
|
||||
<string>128</string>
|
||||
<key>FLTEnableImpeller</key>
|
||||
<true />
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
|
|
@ -19,7 +19,7 @@ platform :ios do
|
|||
desc "iOS Beta"
|
||||
lane :beta do
|
||||
increment_version_number(
|
||||
version_number: "1.87.0"
|
||||
version_number: "1.88.0"
|
||||
)
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
|
|
|
@ -5,32 +5,32 @@
|
|||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000245">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000267">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.162192">
|
||||
<testcase classname="fastlane.lanes" name="1: increment_version_number" time="0.193021">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="5.082136">
|
||||
<testcase classname="fastlane.lanes" name="2: latest_testflight_build_number" time="5.987435">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.181105">
|
||||
<testcase classname="fastlane.lanes" name="3: increment_build_number" time="0.181886">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="4: build_app" time="99.633247">
|
||||
<testcase classname="fastlane.lanes" name="4: build_app" time="105.510332">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="62.690406">
|
||||
<testcase classname="fastlane.lanes" name="5: upload_to_testflight" time="65.714015">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class AlbumActionOutlinedButton extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
padding: const EdgeInsets.only(right: 16.0),
|
||||
child: OutlinedButton.icon(
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
|
||||
|
@ -32,13 +32,13 @@ class AlbumActionOutlinedButton extends StatelessWidget {
|
|||
),
|
||||
icon: Icon(
|
||||
iconData,
|
||||
size: 15,
|
||||
size: 18,
|
||||
color: context.primaryColor,
|
||||
),
|
||||
label: Text(
|
||||
labelText,
|
||||
style: context.textTheme.labelSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
|
|
|
@ -72,17 +72,13 @@ class AlbumThumbnailCard extends StatelessWidget {
|
|||
.tr(args: ['${album.assetCount}'])
|
||||
: 'album_thumbnail_card_items'
|
||||
.tr(args: ['${album.assetCount}']),
|
||||
style: TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
fontSize: 12,
|
||||
color: isDarkTheme ? Colors.white : Colors.black,
|
||||
),
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
if (owner != null) const TextSpan(text: ' · '),
|
||||
if (owner != null)
|
||||
TextSpan(
|
||||
text: owner,
|
||||
style: context.textTheme.labelSmall,
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -114,11 +110,9 @@ class AlbumThumbnailCard extends StatelessWidget {
|
|||
width: cardSize,
|
||||
child: Text(
|
||||
album.name,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isDarkTheme
|
||||
? context.primaryColor
|
||||
: Colors.black,
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -210,7 +210,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
leading: const Icon(Icons.ios_share_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_to',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onShareAssetsTo(),
|
||||
),
|
||||
|
@ -219,7 +219,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
leading: const Icon(Icons.delete_sweep_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_remove',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onRemoveFromAlbumPressed(),
|
||||
)
|
||||
|
@ -232,7 +232,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
leading: const Icon(Icons.delete_forever_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_delete',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onDeleteAlbumPressed(),
|
||||
)
|
||||
|
@ -240,7 +240,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
leading: const Icon(Icons.person_remove_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_leave',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onLeaveAlbumPressed(),
|
||||
),
|
||||
|
@ -258,7 +258,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
},
|
||||
title: const Text(
|
||||
"album_viewer_page_share_add_users",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
),
|
||||
ListTile(
|
||||
|
@ -269,7 +269,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
},
|
||||
title: const Text(
|
||||
"control_bottom_app_bar_share",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
),
|
||||
ListTile(
|
||||
|
@ -277,7 +277,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
onTap: () => context.autoNavigate(AlbumOptionsRoute(album: album)),
|
||||
title: const Text(
|
||||
"translated_text_options",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
),
|
||||
];
|
||||
|
@ -291,7 +291,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||
},
|
||||
title: const Text(
|
||||
"share_add_photos",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
),
|
||||
];
|
||||
|
|
|
@ -44,7 +44,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
|||
}
|
||||
},
|
||||
focusNode: titleFocusNode,
|
||||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.headlineMedium,
|
||||
controller: titleTextEditController,
|
||||
onTap: () {
|
||||
FocusScope.of(context).requestFocus(titleFocusNode);
|
||||
|
|
|
@ -91,7 +91,8 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||
actions = [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.person_remove_rounded),
|
||||
title: const Text("shared_album_section_people_remove_user").tr(),
|
||||
title: const Text("shared_album_section_people_action_remove_user")
|
||||
.tr(),
|
||||
onTap: () => removeUserFromAlbum(user),
|
||||
),
|
||||
];
|
||||
|
@ -122,18 +123,16 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||
title: Text(
|
||||
album.owner.value?.name ?? "",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
album.owner.value?.email ?? "",
|
||||
style: TextStyle(color: Colors.grey[500]),
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
trailing: const Text(
|
||||
trailing: Text(
|
||||
"shared_album_section_people_owner_label",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
);
|
||||
}
|
||||
|
@ -152,12 +151,12 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||
title: Text(
|
||||
user.name,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
user.email,
|
||||
style: TextStyle(color: Colors.grey[500]),
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
trailing: userId == user.id || isOwner
|
||||
? const Icon(Icons.more_horiz_rounded)
|
||||
|
@ -209,11 +208,15 @@ class AlbumOptionsPage extends HookConsumerWidget {
|
|||
dense: true,
|
||||
title: Text(
|
||||
"shared_album_activity_setting_title",
|
||||
style: context.textTheme.labelLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.titleMedium
|
||||
?.copyWith(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
subtitle: Text(
|
||||
"shared_album_activity_setting_subtitle",
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.textTheme.labelLarge?.color?.withAlpha(175),
|
||||
),
|
||||
).tr(),
|
||||
subtitle:
|
||||
const Text("shared_album_activity_setting_subtitle").tr(),
|
||||
),
|
||||
buildSectionTitle("shared_album_section_people_title".tr()),
|
||||
buildOwnerInfo(),
|
||||
|
|
|
@ -153,10 +153,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
album.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.headlineMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -191,10 +188,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||
),
|
||||
child: Text(
|
||||
dateRangeText,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -94,10 +94,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(top: 200, left: 18),
|
||||
child: Text(
|
||||
'create_shared_album_page_share_add_assets',
|
||||
style: context.textTheme.displayMedium?.copyWith(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
),
|
||||
);
|
||||
|
@ -119,7 +116,7 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||
side: BorderSide(
|
||||
color: context.isDarkTheme
|
||||
? const Color.fromARGB(255, 63, 63, 63)
|
||||
: const Color.fromARGB(255, 206, 206, 206),
|
||||
: const Color.fromARGB(255, 129, 129, 129),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
|
@ -134,9 +131,8 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
'create_shared_album_page_share_select_photos',
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.titleMedium?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
@ -222,11 +218,8 @@ class CreateAlbumPage extends HookConsumerWidget {
|
|||
},
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
),
|
||||
title: Text(
|
||||
title: const Text(
|
||||
'share_create_album',
|
||||
style: context.textTheme.displayMedium?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
actions: [
|
||||
if (isSharedAlbum)
|
||||
|
|
|
@ -125,10 +125,8 @@ class LibraryPage extends HookConsumerWidget {
|
|||
),
|
||||
Text(
|
||||
options[selectedAlbumSortOrder.value],
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontSize: 12.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -172,11 +170,9 @@ class LibraryPage extends HookConsumerWidget {
|
|||
top: 8.0,
|
||||
bottom: 16,
|
||||
),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'library_page_new_album',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
|
@ -198,9 +194,9 @@ class LibraryPage extends HookConsumerWidget {
|
|||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 13.0,
|
||||
color: isDarkTheme ? Colors.white : Colors.grey[800],
|
||||
color: context.isDarkTheme
|
||||
? Colors.white
|
||||
: Colors.black.withAlpha(200),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -278,9 +274,11 @@ class LibraryPage extends HookConsumerWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
Text(
|
||||
'library_page_albums',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
buildSortButton(),
|
||||
],
|
||||
|
@ -326,9 +324,11 @@ class LibraryPage extends HookConsumerWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
Text(
|
||||
'library_page_device_albums',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -80,25 +80,20 @@ class SharingPage extends HookConsumerWidget {
|
|||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
context.isDarkTheme ? context.primaryColor : Colors.black,
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
subtitle: isOwner
|
||||
? Text(
|
||||
'album_thumbnail_owned'.tr(),
|
||||
style: const TextStyle(
|
||||
fontSize: 12.0,
|
||||
),
|
||||
style: context.textTheme.bodyMedium,
|
||||
)
|
||||
: album.ownerName != null
|
||||
? Text(
|
||||
'album_thumbnail_shared_by'
|
||||
.tr(args: [album.ownerName!]),
|
||||
style: const TextStyle(
|
||||
fontSize: 12.0,
|
||||
),
|
||||
style: context.textTheme.bodyMedium,
|
||||
)
|
||||
: null,
|
||||
onTap: () {
|
||||
|
@ -137,8 +132,8 @@ class SharingPage extends HookConsumerWidget {
|
|||
"sharing_silver_appbar_create_shared_album",
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
@ -154,8 +149,8 @@ class SharingPage extends HookConsumerWidget {
|
|||
label: const Text(
|
||||
"sharing_silver_appbar_shared_links",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
),
|
||||
maxLines: 1,
|
||||
).tr(),
|
||||
|
@ -236,9 +231,11 @@ class SharingPage extends HookConsumerWidget {
|
|||
SliverPadding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: const Text(
|
||||
child: Text(
|
||||
"partner_page_title",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
|
@ -246,10 +243,10 @@ class SharingPage extends HookConsumerWidget {
|
|||
SliverPadding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: const Text(
|
||||
child: Text(
|
||||
"sharing_page_album",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
|
|
@ -93,15 +93,11 @@ class DescriptionInput extends HookConsumerWidget {
|
|||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
controller: controller,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'description_input_hint_text'.tr(),
|
||||
border: InputBorder.none,
|
||||
hintStyle: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 12,
|
||||
hintStyle: context.textTheme.labelLarge?.copyWith(
|
||||
color: textColor.withOpacity(0.5),
|
||||
),
|
||||
suffixIcon: suffixIcon,
|
||||
|
|
|
@ -193,21 +193,15 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
children: [
|
||||
Text(
|
||||
"exif_bottom_sheet_location",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: textColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelMedium?.copyWith(
|
||||
color: context.textTheme.labelMedium?.color?.withAlpha(200),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
).tr(),
|
||||
buildMap(),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: textColor,
|
||||
fontFamily: 'WorkSans',
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
children: [
|
||||
if (exifInfo != null && exifInfo.city != null)
|
||||
TextSpan(
|
||||
|
@ -228,7 +222,9 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
),
|
||||
Text(
|
||||
"${exifInfo!.latitude!.toStringAsFixed(4)}, ${exifInfo.longitude!.toStringAsFixed(4)}",
|
||||
style: const TextStyle(fontSize: 12),
|
||||
style: context.textTheme.labelMedium?.copyWith(
|
||||
color: context.textTheme.labelMedium?.color?.withAlpha(150),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -258,10 +254,7 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
titleAlignment: ListTileTitleAlignment.center,
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: textColor,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
),
|
||||
subtitle: subtitle,
|
||||
);
|
||||
|
@ -278,7 +271,7 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
// There is both filename and size information
|
||||
return createImagePropertiesListStyle(
|
||||
asset.fileName,
|
||||
Text(imgSizeString),
|
||||
Text(imgSizeString, style: context.textTheme.bodySmall),
|
||||
);
|
||||
} else if (imgSizeString != null && asset.fileName.isEmpty) {
|
||||
// There is only size information
|
||||
|
@ -305,10 +298,9 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
"exif_bottom_sheet_details",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: textColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelMedium?.copyWith(
|
||||
color: context.textTheme.labelMedium?.color?.withAlpha(200),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
@ -323,10 +315,7 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
),
|
||||
title: Text(
|
||||
"${exifInfo!.make} ${exifInfo.model}",
|
||||
style: TextStyle(
|
||||
color: textColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
),
|
||||
subtitle: exifInfo.f != null ||
|
||||
exifInfo.exposureSeconds != null ||
|
||||
|
@ -334,6 +323,7 @@ class ExifBottomSheet extends HookConsumerWidget {
|
|||
exifInfo.iso != null
|
||||
? Text(
|
||||
"ƒ/${exifInfo.fNumber} ${exifInfo.exposureTime} ${exifInfo.focalLength} mm ISO ${exifInfo.iso ?? ''} ",
|
||||
style: context.textTheme.bodySmall,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
|
|
|
@ -28,17 +28,17 @@ class BackupInfoCard extends StatelessWidget {
|
|||
elevation: 0,
|
||||
borderOnForeground: false,
|
||||
child: ListTile(
|
||||
minVerticalPadding: 15,
|
||||
minVerticalPadding: 18,
|
||||
isThreeLine: true,
|
||||
title: Text(
|
||||
title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
style: context.textTheme.titleMedium,
|
||||
),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
padding: const EdgeInsets.only(top: 4.0, right: 18.0),
|
||||
child: Text(
|
||||
subtitle,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
trailing: Column(
|
||||
|
@ -46,9 +46,12 @@ class BackupInfoCard extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
info,
|
||||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.titleLarge,
|
||||
),
|
||||
const Text("backup_info_card_assets").tr(),
|
||||
Text(
|
||||
"backup_info_card_assets",
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -188,9 +188,9 @@ class CurrentUploadingAssetInfoBox extends HookConsumerWidget {
|
|||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
Text(
|
||||
"backup_controller_page_uploading_file_info",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
style: context.textTheme.titleSmall,
|
||||
).tr(),
|
||||
if (ref.watch(errorBackupListProvider).isNotEmpty) buildErrorChip(),
|
||||
],
|
||||
|
|
|
@ -100,7 +100,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
|||
label: Text(
|
||||
album.name,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontSize: 12,
|
||||
color: isDarkTheme ? Colors.black : Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
@ -134,7 +134,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
|||
label: Text(
|
||||
album.name,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontSize: 12,
|
||||
color: isDarkTheme ? Colors.black : immichBackgroundColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
@ -203,7 +203,6 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
|||
),
|
||||
title: const Text(
|
||||
"backup_album_selection_page_select_albums",
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
elevation: 0,
|
||||
),
|
||||
|
@ -219,12 +218,9 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
|||
vertical: 8.0,
|
||||
horizontal: 16.0,
|
||||
),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
"backup_album_selection_page_selection_info",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
style: context.textTheme.titleSmall,
|
||||
).tr(),
|
||||
),
|
||||
// Selected Album Chips
|
||||
|
@ -250,19 +246,14 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
|
|||
.toString(),
|
||||
],
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
style: context.textTheme.titleSmall,
|
||||
),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Text(
|
||||
"backup_album_selection_page_albums_tap",
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
|
|
@ -193,7 +193,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
: const Icon(Icons.cloud_off_rounded),
|
||||
title: Text(
|
||||
backUpOption,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
style: context.textTheme.titleSmall,
|
||||
),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
|
@ -213,9 +213,8 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
.setAutoBackup(!isAutoBackup),
|
||||
child: Text(
|
||||
backupBtnText,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.isDarkTheme ? Colors.black : Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -335,7 +334,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
isBackgroundEnabled
|
||||
? "backup_controller_page_background_is_on"
|
||||
: "backup_controller_page_background_is_off",
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
style: context.textTheme.titleSmall,
|
||||
).tr(),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -426,9 +425,8 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
isBackgroundEnabled
|
||||
? "backup_controller_page_background_turn_off"
|
||||
: "backup_controller_page_background_turn_on",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.isDarkTheme ? Colors.black : Colors.white,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
@ -511,10 +509,8 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
text.trim().substring(0, text.length - 2),
|
||||
style: TextStyle(
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -523,10 +519,8 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"backup_controller_page_none_selected".tr(),
|
||||
style: TextStyle(
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -546,10 +540,8 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
text.trim().substring(0, text.length - 2),
|
||||
style: TextStyle(
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: Colors.red[300],
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -559,55 +551,57 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
}
|
||||
|
||||
buildFolderSelectionTile() {
|
||||
return Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
side: BorderSide(
|
||||
color: context.isDarkTheme
|
||||
? const Color.fromARGB(255, 56, 56, 56)
|
||||
: Colors.black12,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
elevation: 0,
|
||||
borderOnForeground: false,
|
||||
child: ListTile(
|
||||
minVerticalPadding: 15,
|
||||
title: const Text(
|
||||
"backup_controller_page_albums",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
).tr(),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
"backup_controller_page_to_backup",
|
||||
style: TextStyle(fontSize: 12),
|
||||
).tr(),
|
||||
buildSelectedAlbumName(),
|
||||
buildExcludedAlbumName(),
|
||||
],
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
side: BorderSide(
|
||||
color: context.isDarkTheme
|
||||
? const Color.fromARGB(255, 56, 56, 56)
|
||||
: Colors.black12,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
trailing: ElevatedButton(
|
||||
onPressed: () async {
|
||||
await context.autoPush(const BackupAlbumSelectionRoute());
|
||||
// waited until returning from selection
|
||||
await ref
|
||||
.read(backupProvider.notifier)
|
||||
.backupAlbumSelectionDone();
|
||||
// waited until backup albums are stored in DB
|
||||
ref.read(albumProvider.notifier).getDeviceAlbums();
|
||||
},
|
||||
child: const Text(
|
||||
"backup_controller_page_select",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
elevation: 0,
|
||||
borderOnForeground: false,
|
||||
child: ListTile(
|
||||
minVerticalPadding: 18,
|
||||
title: Text(
|
||||
"backup_controller_page_albums",
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"backup_controller_page_to_backup",
|
||||
style: context.textTheme.bodyMedium,
|
||||
).tr(),
|
||||
buildSelectedAlbumName(),
|
||||
buildExcludedAlbumName(),
|
||||
],
|
||||
),
|
||||
),
|
||||
trailing: ElevatedButton(
|
||||
onPressed: () async {
|
||||
await context.autoPush(const BackupAlbumSelectionRoute());
|
||||
// waited until returning from selection
|
||||
await ref
|
||||
.read(backupProvider.notifier)
|
||||
.backupAlbumSelectionDone();
|
||||
// waited until backup albums are stored in DB
|
||||
ref.read(albumProvider.notifier).getDeviceAlbums();
|
||||
},
|
||||
child: const Text(
|
||||
"backup_controller_page_select",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -657,7 +651,7 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
child: const Text(
|
||||
"backup_controller_page_start_backup",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
|
@ -680,7 +674,6 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
elevation: 0,
|
||||
title: const Text(
|
||||
"backup_controller_page_backup",
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
|
@ -735,7 +728,6 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||
if (showBackupFix) const Divider(),
|
||||
if (showBackupFix) buildCheckCorruptBackups(),
|
||||
const Divider(),
|
||||
const Divider(),
|
||||
const CurrentUploadingAssetInfoBox(),
|
||||
if (!hasExclusiveAccess) buildBackgroundBackupInfo(),
|
||||
buildBackupButton(),
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
|
||||
|
||||
class GroupDividerTitle extends ConsumerWidget {
|
||||
class GroupDividerTitle extends HookConsumerWidget {
|
||||
const GroupDividerTitle({
|
||||
Key? key,
|
||||
required this.text,
|
||||
|
@ -21,6 +25,18 @@ class GroupDividerTitle extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final appSettingService = ref.watch(appSettingsServiceProvider);
|
||||
final groupBy = useState(GroupAssetsBy.day);
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
groupBy.value = GroupAssetsBy.values[
|
||||
appSettingService.getSetting<int>(AppSettingsEnum.groupAssetsBy)];
|
||||
return null;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
void handleTitleIconClick() {
|
||||
HapticFeedback.heavyImpact();
|
||||
if (selected) {
|
||||
|
@ -31,8 +47,8 @@ class GroupDividerTitle extends ConsumerWidget {
|
|||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 12.0,
|
||||
padding: EdgeInsets.only(
|
||||
top: groupBy.value == GroupAssetsBy.month ? 32.0 : 16.0,
|
||||
bottom: 16.0,
|
||||
left: 12.0,
|
||||
right: 12.0,
|
||||
|
@ -41,10 +57,14 @@ class GroupDividerTitle extends ConsumerWidget {
|
|||
children: [
|
||||
Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: groupBy.value == GroupAssetsBy.month
|
||||
? context.textTheme.bodyLarge?.copyWith(
|
||||
fontSize: 24.0,
|
||||
)
|
||||
: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.textTheme.labelLarge?.color?.withAlpha(250),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
GestureDetector(
|
||||
|
|
|
@ -222,10 +222,9 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
|
|||
padding: const EdgeInsets.only(left: 12.0, top: 24.0),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: context.textTheme.displayLarge?.color,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -179,7 +179,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState<MapPageBottomSheet> {
|
|||
? "map_assets_in_bounds".plural(assetsInBound.value.length)
|
||||
: "map_no_assets_in_bounds".tr();
|
||||
final dragHandle = Container(
|
||||
height: 60,
|
||||
height: 70,
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: isDarkTheme ? Colors.grey[900] : Colors.grey[100],
|
||||
|
@ -195,11 +195,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState<MapPageBottomSheet> {
|
|||
const SizedBox(height: 15),
|
||||
Text(
|
||||
textToDisplay,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: context.textTheme.displayLarge?.color,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.bodyLarge,
|
||||
),
|
||||
Divider(
|
||||
height: 10,
|
||||
|
|
|
@ -134,12 +134,16 @@ class MapSettingsDialog extends HookConsumerWidget {
|
|||
backgroundColor:
|
||||
mapSettings.isDarkTheme ? Colors.grey[100] : Colors.grey[700],
|
||||
),
|
||||
child: Text(
|
||||
"map_settings_dialog_cancel".tr(),
|
||||
style: theme.textTheme.labelSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
mapSettings.isDarkTheme ? Colors.grey[900] : Colors.grey[100],
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
"map_settings_dialog_cancel".tr(),
|
||||
style: theme.textTheme.labelLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: mapSettings.isDarkTheme
|
||||
? Colors.grey[900]
|
||||
: Colors.grey[100],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -155,11 +159,14 @@ class MapSettingsDialog extends HookConsumerWidget {
|
|||
style: TextButton.styleFrom(
|
||||
backgroundColor: theme.primaryColor,
|
||||
),
|
||||
child: Text(
|
||||
"map_settings_dialog_save".tr(),
|
||||
style: theme.textTheme.labelSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: theme.primaryTextTheme.labelLarge?.color,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
"map_settings_dialog_save".tr(),
|
||||
style: theme.textTheme.labelLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: theme.primaryTextTheme.labelLarge?.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:ui';
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/models/store.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_image.dart';
|
||||
|
@ -34,10 +35,9 @@ class MemoryCard extends HookConsumerWidget {
|
|||
buildTitle() {
|
||||
return Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
style: context.textTheme.headlineMedium?.copyWith(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ class MemoryLane extends HookConsumerWidget {
|
|||
clipBehavior: Clip.hardEdge,
|
||||
child: ColorFiltered(
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.black.withOpacity(0.1),
|
||||
Colors.black.withOpacity(0.2),
|
||||
BlendMode.darken,
|
||||
),
|
||||
child: ImmichImage(
|
||||
|
@ -71,9 +71,9 @@ class MemoryLane extends HookConsumerWidget {
|
|||
child: Text(
|
||||
memory.title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -138,8 +138,8 @@ class MemoryPage extends HookConsumerWidget {
|
|||
memory.title,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[400],
|
||||
fontSize: 11.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 13.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
|
@ -148,7 +148,7 @@ class MemoryPage extends HookConsumerWidget {
|
|||
),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14.0,
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -28,15 +28,11 @@ class PartnerList extends HookConsumerWidget {
|
|||
leading: userAvatar(context, p, radius: 24),
|
||||
title: Text(
|
||||
"${p.name}'s photos",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
),
|
||||
trailing: Text(
|
||||
"View all",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -84,8 +84,7 @@ class CuratedPeopleRow extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"Add name",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
),
|
||||
|
@ -98,10 +97,7 @@ class CuratedPeopleRow extends StatelessWidget {
|
|||
person.label,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 13.0,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -58,10 +58,8 @@ class ImmichSearchBar extends HookConsumerWidget
|
|||
},
|
||||
decoration: InputDecoration(
|
||||
hintText: 'search_bar_hint'.tr(),
|
||||
hintStyle: context.textTheme.titleSmall?.copyWith(
|
||||
color: context.themeData.colorScheme.onSurface.withOpacity(0.5),
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
hintStyle: context.textTheme.bodyLarge?.copyWith(
|
||||
color: context.themeData.colorScheme.onSurface.withOpacity(0.75),
|
||||
),
|
||||
enabledBorder: const UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.transparent),
|
||||
|
|
|
@ -27,16 +27,16 @@ class SearchRowTitle extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: context.textTheme.titleSmall,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: onViewAllPressed,
|
||||
child: Text(
|
||||
'search_page_view_all_button',
|
||||
style: TextStyle(
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14.0,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
|
|
@ -15,13 +15,8 @@ class AllPeoplePage extends HookConsumerWidget {
|
|||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
title: const Text(
|
||||
'all_people_page_title',
|
||||
style: TextStyle(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16.0,
|
||||
),
|
||||
).tr(),
|
||||
leading: IconButton(
|
||||
onPressed: () => context.autoPop(),
|
||||
|
|
|
@ -18,13 +18,8 @@ class CuratedLocationPage extends HookConsumerWidget {
|
|||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
title: const Text(
|
||||
'curated_location_page_title',
|
||||
style: TextStyle(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16.0,
|
||||
),
|
||||
).tr(),
|
||||
leading: IconButton(
|
||||
onPressed: () => context.autoPop(),
|
||||
|
|
|
@ -76,13 +76,13 @@ class PersonResultPage extends HookConsumerWidget {
|
|||
children: [
|
||||
Text(
|
||||
'search_page_person_add_name_title',
|
||||
style: context.textTheme.titleSmall?.copyWith(
|
||||
color: context.themeData.colorScheme.secondary,
|
||||
style: context.textTheme.titleMedium?.copyWith(
|
||||
color: context.primaryColor,
|
||||
),
|
||||
).tr(),
|
||||
Text(
|
||||
'search_page_person_add_name_subtitle',
|
||||
style: context.textTheme.labelSmall,
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -33,8 +33,8 @@ class SearchPage extends HookConsumerWidget {
|
|||
double imageSize = math.min(context.width / 3, 150);
|
||||
|
||||
TextStyle categoryTitleStyle = const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 15.0,
|
||||
);
|
||||
|
||||
Color categoryIconColor = context.isDarkTheme ? Colors.white : Colors.black;
|
||||
|
@ -156,7 +156,9 @@ class SearchPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'search_page_your_activity',
|
||||
style: context.textTheme.titleSmall,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
ListTile(
|
||||
|
@ -186,11 +188,15 @@ class SearchPage extends HookConsumerWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
'search_page_categories',
|
||||
style: context.textTheme.titleSmall,
|
||||
style: context.textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
ListTile(
|
||||
title: Text('search_page_screenshots', style: categoryTitleStyle).tr(),
|
||||
title:
|
||||
Text('search_page_screenshots', style: categoryTitleStyle)
|
||||
.tr(),
|
||||
leading: Icon(
|
||||
Icons.screenshot,
|
||||
color: categoryIconColor,
|
||||
|
@ -255,7 +261,7 @@ class CategoryDivider extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 72,
|
||||
left: 56,
|
||||
right: 16,
|
||||
),
|
||||
child: Divider(
|
||||
|
|
|
@ -45,17 +45,12 @@ class AdvancedSettings extends HookConsumerWidget {
|
|||
|
||||
return ExpansionTile(
|
||||
textColor: context.primaryColor,
|
||||
title: const Text(
|
||||
title: Text(
|
||||
"advanced_settings_tile_title",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
"advanced_settings_tile_subtitle",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: [
|
||||
SettingsSwitchListTile(
|
||||
|
|
|
@ -54,8 +54,7 @@ class LayoutSettings extends HookConsumerWidget {
|
|||
activeColor: context.primaryColor,
|
||||
title: Text(
|
||||
"asset_list_layout_settings_dynamic_layout_title",
|
||||
style: context.textTheme.labelLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
onChanged: switchChanged,
|
||||
value: useDynamicLayout.value,
|
||||
|
|
|
@ -14,17 +14,12 @@ class AssetListSettings extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return ExpansionTile(
|
||||
textColor: context.primaryColor,
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'asset_list_settings_title',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
'asset_list_settings_subtitle',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: const [
|
||||
TilesPerRow(),
|
||||
|
|
|
@ -37,8 +37,7 @@ class StorageIndicator extends HookConsumerWidget {
|
|||
activeColor: context.primaryColor,
|
||||
title: Text(
|
||||
"theme_setting_asset_list_storage_indicator_title",
|
||||
style:
|
||||
context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(),
|
||||
onChanged: switchChanged,
|
||||
value: showStorageIndicator.value,
|
||||
|
|
|
@ -37,12 +37,9 @@ class TilesPerRow extends HookConsumerWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ListTile(
|
||||
title: const Text(
|
||||
title: Text(
|
||||
"theme_setting_asset_list_tiles_per_row_title",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.labelLarge,
|
||||
).tr(args: ["${itemsValue.value.toInt()}"]),
|
||||
),
|
||||
Slider(
|
||||
|
|
|
@ -28,22 +28,19 @@ class ImageViewerQualitySetting extends HookConsumerWidget {
|
|||
|
||||
return ExpansionTile(
|
||||
textColor: context.primaryColor,
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'theme_setting_image_viewer_quality_title',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
'theme_setting_image_viewer_quality_subtitle',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: [
|
||||
ListTile(
|
||||
title: const Text('setting_image_viewer_help').tr(),
|
||||
dense: true,
|
||||
title: Text(
|
||||
'setting_image_viewer_help',
|
||||
style: context.textTheme.bodyMedium,
|
||||
).tr(),
|
||||
),
|
||||
SettingsSwitchListTile(
|
||||
appSettingService: settings,
|
||||
|
|
|
@ -27,30 +27,21 @@ class LocalStorageSettings extends HookConsumerWidget {
|
|||
|
||||
return ExpansionTile(
|
||||
textColor: context.primaryColor,
|
||||
title: const Text(
|
||||
title: Text(
|
||||
"cache_settings_tile_title",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
"cache_settings_tile_subtitle",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
"cache_settings_duplicated_assets_title",
|
||||
style: context.textTheme.labelLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.titleSmall,
|
||||
).tr(args: ["${cacheItemCount.value}"]),
|
||||
subtitle: const Text(
|
||||
"cache_settings_duplicated_assets_subtitle",
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
trailing: TextButton(
|
||||
onPressed: cacheItemCount.value > 0 ? clearCache : null,
|
||||
|
|
|
@ -67,17 +67,12 @@ class NotificationSetting extends HookConsumerWidget {
|
|||
final String formattedValue = _formatSliderValue(sliderValue.value);
|
||||
return ExpansionTile(
|
||||
textColor: context.primaryColor,
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'setting_notifications_title',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
'setting_notifications_subtitle',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: [
|
||||
if (!hasPermission)
|
||||
|
|
|
@ -40,10 +40,14 @@ class SettingsSwitchListTile extends StatelessWidget {
|
|||
dense: true,
|
||||
title: Text(
|
||||
title,
|
||||
style:
|
||||
context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
style: context.textTheme.titleSmall,
|
||||
),
|
||||
subtitle: subtitle != null ? Text(subtitle!) : null,
|
||||
subtitle: subtitle != null
|
||||
? Text(
|
||||
subtitle!,
|
||||
style: context.textTheme.bodyMedium,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,17 +26,12 @@ class ThemeSetting extends HookConsumerWidget {
|
|||
|
||||
return ExpansionTile(
|
||||
textColor: context.primaryColor,
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'theme_setting_theme_title',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: context.textTheme.titleMedium,
|
||||
).tr(),
|
||||
subtitle: const Text(
|
||||
'theme_setting_theme_subtitle',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
),
|
||||
).tr(),
|
||||
children: [
|
||||
SwitchListTile.adaptive(
|
||||
|
|
|
@ -27,10 +27,6 @@ class SettingsPage extends HookConsumerWidget {
|
|||
centerTitle: false,
|
||||
title: const Text(
|
||||
'setting_pages_app_bar_settings',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
body: ListView(
|
||||
|
|
|
@ -148,8 +148,8 @@ class SharedLinkItem extends ConsumerWidget {
|
|||
label: Text(
|
||||
labelText,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: isDarkMode ? Colors.black : Colors.white,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -67,12 +67,10 @@ class SharedLinkPage extends HookConsumerWidget {
|
|||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0, top: 16.0, bottom: 30.0),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
"shared_link_manage_links",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.bold,
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
color: context.textTheme.labelLarge?.color?.withAlpha(200),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
|
|
|
@ -54,7 +54,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
fontFamily: 'SnowburstOne',
|
||||
fontWeight: FontWeight.bold,
|
||||
color: context.primaryColor,
|
||||
fontSize: 15,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -72,14 +72,15 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
leading: SizedBox(
|
||||
child: Icon(
|
||||
icon,
|
||||
color: theme.textTheme.labelMedium?.color,
|
||||
color: theme.textTheme.labelLarge?.color?.withAlpha(250),
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
text,
|
||||
style:
|
||||
theme.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||
style: theme.textTheme.labelLarge?.copyWith(
|
||||
color: theme.textTheme.labelLarge?.color?.withAlpha(250),
|
||||
),
|
||||
).tr(),
|
||||
onTap: onTap,
|
||||
);
|
||||
|
@ -145,9 +146,11 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
Icons.storage_rounded,
|
||||
color: theme.primaryColor,
|
||||
),
|
||||
title: const Text(
|
||||
title: Text(
|
||||
"backup_controller_page_server_storage",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
).tr(),
|
||||
isThreeLine: true,
|
||||
subtitle: Padding(
|
||||
|
@ -230,7 +233,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
clipBehavior: Clip.hardEdge,
|
||||
alignment: Alignment.topCenter,
|
||||
insetPadding: EdgeInsets.only(
|
||||
top: isHorizontal ? 20 : 60,
|
||||
top: isHorizontal ? 20 : 40,
|
||||
left: horizontalPadding,
|
||||
right: horizontalPadding,
|
||||
bottom: isHorizontal ? 20 : 100,
|
||||
|
|
|
@ -31,8 +31,8 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
|||
}
|
||||
|
||||
final userImage = UserCircleAvatar(
|
||||
radius: 20,
|
||||
size: 40,
|
||||
radius: 22,
|
||||
size: 44,
|
||||
user: user,
|
||||
);
|
||||
|
||||
|
@ -119,16 +119,15 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
|||
),
|
||||
title: Text(
|
||||
authState.name,
|
||||
style: TextStyle(
|
||||
style: context.textTheme.titleMedium?.copyWith(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
authState.userEmail,
|
||||
style: context.textTheme.labelMedium?.copyWith(
|
||||
fontSize: 12,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: context.textTheme.bodySmall?.color?.withAlpha(200),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -18,6 +18,8 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
ServerInfo serverInfoState = ref.watch(serverInfoProvider);
|
||||
|
||||
final appInfo = useState({});
|
||||
const titleFontSize = 12.0;
|
||||
const contentFontSize = 11.0;
|
||||
|
||||
getPackageInfo() async {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
|
@ -63,7 +65,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -83,9 +85,9 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
child: Text(
|
||||
"server_info_box_app_version".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: titleFontSize,
|
||||
color: context.textTheme.labelSmall?.color,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -97,7 +99,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
child: Text(
|
||||
"${appInfo.value["version"]} build.${appInfo.value["buildNumber"]}",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -123,9 +125,9 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
child: Text(
|
||||
"server_info_box_server_version".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: titleFontSize,
|
||||
color: context.textTheme.labelSmall?.color,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -139,7 +141,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
? "${serverInfoState.serverVersion.major}.${serverInfoState.serverVersion.minor}.${serverInfoState.serverVersion.patch}"
|
||||
: "--",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -165,9 +167,9 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
child: Text(
|
||||
"server_info_box_server_url".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: titleFontSize,
|
||||
color: context.textTheme.labelSmall?.color,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -194,7 +196,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
child: Text(
|
||||
getServerUrl() ?? '--',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -234,9 +236,9 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
Text(
|
||||
"server_info_box_latest_release".tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: titleFontSize,
|
||||
color: context.textTheme.labelSmall?.color,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -252,7 +254,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
? "${serverInfoState.latestVersion.major}.${serverInfoState.latestVersion.minor}.${serverInfoState.latestVersion.patch}"
|
||||
: "--",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: contentFontSize,
|
||||
color: context.textTheme.labelSmall?.color
|
||||
?.withOpacity(0.5),
|
||||
fontWeight: FontWeight.bold,
|
||||
|
|
|
@ -38,11 +38,11 @@ ThemeData immichLightTheme = ThemeData(
|
|||
hintColor: Colors.indigo,
|
||||
focusColor: Colors.indigo,
|
||||
splashColor: Colors.indigo.withOpacity(0.15),
|
||||
fontFamily: 'WorkSans',
|
||||
fontFamily: 'Overpass',
|
||||
scaffoldBackgroundColor: immichBackgroundColor,
|
||||
snackBarTheme: const SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
fontFamily: 'Overpass',
|
||||
color: Colors.indigo,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
@ -50,7 +50,7 @@ ThemeData immichLightTheme = ThemeData(
|
|||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
titleTextStyle: const TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
fontFamily: 'Overpass',
|
||||
color: Colors.indigo,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
|
@ -125,9 +125,9 @@ ThemeData immichLightTheme = ThemeData(
|
|||
surfaceTintColor: Colors.transparent,
|
||||
labelTextStyle: MaterialStatePropertyAll(
|
||||
TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey[700],
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey[800],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -160,10 +160,10 @@ ThemeData immichDarkTheme = ThemeData(
|
|||
primaryColor: immichDarkThemePrimaryColor,
|
||||
scaffoldBackgroundColor: immichDarkBackgroundColor,
|
||||
hintColor: Colors.grey[600],
|
||||
fontFamily: 'WorkSans',
|
||||
fontFamily: 'Overpass',
|
||||
snackBarTheme: SnackBarThemeData(
|
||||
contentTextStyle: TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
fontFamily: 'Overpass',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
@ -176,7 +176,7 @@ ThemeData immichDarkTheme = ThemeData(
|
|||
),
|
||||
appBarTheme: AppBarTheme(
|
||||
titleTextStyle: TextStyle(
|
||||
fontFamily: 'WorkSans',
|
||||
fontFamily: 'Overpass',
|
||||
color: immichDarkThemePrimaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
|
@ -249,9 +249,9 @@ ThemeData immichDarkTheme = ThemeData(
|
|||
surfaceTintColor: Colors.transparent,
|
||||
labelTextStyle: MaterialStatePropertyAll(
|
||||
TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey[500],
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey[300],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
2
mobile/openapi/README.md
generated
2
mobile/openapi/README.md
generated
|
@ -3,7 +3,7 @@ Immich API
|
|||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 1.87.0
|
||||
- API version: 1.88.0
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
## Requirements
|
||||
|
|
|
@ -2,7 +2,7 @@ name: immich_mobile
|
|||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: "none"
|
||||
version: 1.87.0+111
|
||||
version: 1.88.0+112
|
||||
isar_version: &isar_version 3.1.0+1
|
||||
|
||||
environment:
|
||||
|
@ -97,27 +97,28 @@ flutter:
|
|||
- assets/
|
||||
- assets/i18n/
|
||||
fonts:
|
||||
- family: WorkSans
|
||||
fonts:
|
||||
- asset: fonts/WorkSans.ttf
|
||||
- asset: fonts/WorkSans-Italic.ttf
|
||||
style: italic
|
||||
# - asset: fonts/WorkSans-Medium.ttf
|
||||
# weight: 500
|
||||
# - asset: fonts/WorkSans-SemiBold.ttf
|
||||
# weight: 600
|
||||
# - asset: fonts/WorkSans-Bold.ttf
|
||||
# weight: 700
|
||||
# - asset: fonts/WorkSans-ExtraBold.ttf
|
||||
# weight: 800
|
||||
# - asset: fonts/WorkSans-Black.ttf
|
||||
# weight: 900
|
||||
- family: SnowburstOne
|
||||
fonts:
|
||||
- asset: fonts/SnowburstOne.ttf
|
||||
- family: Inconsolata
|
||||
fonts:
|
||||
- asset: fonts/Inconsolata-Regular.ttf
|
||||
- family: Overpass
|
||||
fonts:
|
||||
- asset: fonts/overpass/Overpass-Regular.ttf
|
||||
weight: 400
|
||||
- asset: fonts/overpass/Overpass-Italic.ttf
|
||||
style: italic
|
||||
- asset: fonts/overpass/Overpass-Medium.ttf
|
||||
weight: 500
|
||||
- asset: fonts/overpass/Overpass-SemiBold.ttf
|
||||
weight: 600
|
||||
- asset: fonts/overpass/Overpass-Bold.ttf
|
||||
weight: 700
|
||||
- family: OverpassMono
|
||||
fonts:
|
||||
- asset: fonts/overpass/OverpassMono.ttf
|
||||
|
||||
flutter_icons:
|
||||
image_path_android: "assets/immich-logo-no-outline.png"
|
||||
image_path_ios: "assets/immich-logo-no-outline.png"
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
node ./node_modules/immich/bin/index "$@"
|
||||
node ./node_modules/@immich/cli/dist/index "$@"
|
||||
|
|
|
@ -6052,7 +6052,7 @@
|
|||
"info": {
|
||||
"title": "Immich",
|
||||
"description": "Immich API",
|
||||
"version": "1.87.0",
|
||||
"version": "1.88.0",
|
||||
"contact": {}
|
||||
},
|
||||
"tags": [],
|
||||
|
|
333
server/package-lock.json
generated
333
server/package-lock.json
generated
|
@ -1,15 +1,16 @@
|
|||
{
|
||||
"name": "immich",
|
||||
"version": "1.87.0",
|
||||
"version": "1.88.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immich",
|
||||
"version": "1.87.0",
|
||||
"version": "1.88.0",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.22.11",
|
||||
"@immich/cli": "^2.0.3",
|
||||
"@nestjs/bullmq": "^10.0.1",
|
||||
"@nestjs/common": "^10.2.2",
|
||||
"@nestjs/config": "^3.0.0",
|
||||
|
@ -35,7 +36,6 @@
|
|||
"glob": "^10.3.3",
|
||||
"handlebars": "^4.7.8",
|
||||
"i18n-iso-countries": "^7.6.0",
|
||||
"immich": "^0.41.0",
|
||||
"ioredis": "^5.3.2",
|
||||
"joi": "^17.10.0",
|
||||
"local-reverse-geocoder": "0.16.5",
|
||||
|
@ -1053,6 +1053,31 @@
|
|||
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@immich/cli": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@immich/cli/-/cli-2.0.3.tgz",
|
||||
"integrity": "sha512-G1G192hcyWY/v/tHMNSo6cedDhcMCKaONeSbzP55Ti+3nqza5Et5PS5kXEfXPIQySLiD1ilaD8nbnP3iF42dUw==",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.2",
|
||||
"byte-size": "^8.1.1",
|
||||
"cli-progress": "^3.12.0",
|
||||
"commander": "^11.0.0",
|
||||
"form-data": "^4.0.0",
|
||||
"glob": "^10.3.1",
|
||||
"yaml": "^2.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"immich": "dist/index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@immich/cli/node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@ioredis/commands": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||
|
@ -4397,6 +4422,14 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/byte-size": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/byte-size/-/byte-size-8.1.1.tgz",
|
||||
"integrity": "sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
|
@ -5495,15 +5528,6 @@
|
|||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/docker-compose/node_modules/yaml": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
|
||||
"integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/docker-modem": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz",
|
||||
|
@ -6272,19 +6296,6 @@
|
|||
"bser": "2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/fdir": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-5.3.0.tgz",
|
||||
"integrity": "sha512-BtE53+jaa7nNHT+gPdfU6cFAXOJUWDs2b5GFox8dtl6zLXmfNf/N6im69b9nqNNwDyl27mpIWX8qR7AafWzSdQ==",
|
||||
"peerDependencies": {
|
||||
"picomatch": "2.x"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"picomatch": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
|
@ -7107,105 +7118,6 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immich": {
|
||||
"version": "0.41.0",
|
||||
"resolved": "https://registry.npmjs.org/immich/-/immich-0.41.0.tgz",
|
||||
"integrity": "sha512-F+DIJ41/1L4Cqs0NqubcD2qttYcxTs32DCZS2l6U7d+a4SVtbxYwtEkvljSKACka1vokmHetpveGyRau2FdZ8w==",
|
||||
"dependencies": {
|
||||
"axios": "^0.26.0",
|
||||
"chalk": "^2.4.1",
|
||||
"cli-progress": "^3.10.0",
|
||||
"commander": "^9.0.0",
|
||||
"fdir": "^5.2.0",
|
||||
"form-data": "^4.0.0",
|
||||
"mime-types": "^2.1.34",
|
||||
"p-limit": "3.1.0",
|
||||
"systeminformation": "^5.11.6"
|
||||
},
|
||||
"bin": {
|
||||
"immich": "bin/index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/axios": {
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.14.8"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"node_modules/immich/node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/immich/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -9468,6 +9380,7 @@
|
|||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
},
|
||||
|
@ -9742,7 +9655,7 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
|
@ -11289,31 +11202,6 @@
|
|||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/systeminformation": {
|
||||
"version": "5.21.9",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.9.tgz",
|
||||
"integrity": "sha512-7pI4mu9P/2MGDV0T49B52E7IULBGj+kRVk6JSYUj5qfAk7N7C7aNX15fXziqrbgZntc6/jjYzWeb/x41jhg/eA==",
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
"win32",
|
||||
"freebsd",
|
||||
"openbsd",
|
||||
"netbsd",
|
||||
"sunos",
|
||||
"android"
|
||||
],
|
||||
"bin": {
|
||||
"systeminformation": "lib/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "Buy me a coffee",
|
||||
"url": "https://www.buymeacoffee.com/systeminfo"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
|
@ -12888,6 +12776,14 @@
|
|||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
|
||||
"integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
|
@ -12934,6 +12830,7 @@
|
|||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
@ -13669,6 +13566,27 @@
|
|||
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
|
||||
"dev": true
|
||||
},
|
||||
"@immich/cli": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@immich/cli/-/cli-2.0.3.tgz",
|
||||
"integrity": "sha512-G1G192hcyWY/v/tHMNSo6cedDhcMCKaONeSbzP55Ti+3nqza5Et5PS5kXEfXPIQySLiD1ilaD8nbnP3iF42dUw==",
|
||||
"requires": {
|
||||
"axios": "^1.6.2",
|
||||
"byte-size": "^8.1.1",
|
||||
"cli-progress": "^3.12.0",
|
||||
"commander": "^11.0.0",
|
||||
"form-data": "^4.0.0",
|
||||
"glob": "^10.3.1",
|
||||
"yaml": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@ioredis/commands": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||
|
@ -16230,6 +16148,11 @@
|
|||
"integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"byte-size": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/byte-size/-/byte-size-8.1.1.tgz",
|
||||
"integrity": "sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg=="
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
|
@ -16994,14 +16917,6 @@
|
|||
"dev": true,
|
||||
"requires": {
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
|
||||
"integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"docker-modem": {
|
||||
|
@ -17606,12 +17521,6 @@
|
|||
"bser": "2.1.1"
|
||||
}
|
||||
},
|
||||
"fdir": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-5.3.0.tgz",
|
||||
"integrity": "sha512-BtE53+jaa7nNHT+gPdfU6cFAXOJUWDs2b5GFox8dtl6zLXmfNf/N6im69b9nqNNwDyl27mpIWX8qR7AafWzSdQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
|
@ -18195,86 +18104,6 @@
|
|||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"immich": {
|
||||
"version": "0.41.0",
|
||||
"resolved": "https://registry.npmjs.org/immich/-/immich-0.41.0.tgz",
|
||||
"integrity": "sha512-F+DIJ41/1L4Cqs0NqubcD2qttYcxTs32DCZS2l6U7d+a4SVtbxYwtEkvljSKACka1vokmHetpveGyRau2FdZ8w==",
|
||||
"requires": {
|
||||
"axios": "^0.26.0",
|
||||
"chalk": "^2.4.1",
|
||||
"cli-progress": "^3.10.0",
|
||||
"commander": "^9.0.0",
|
||||
"fdir": "^5.2.0",
|
||||
"form-data": "^4.0.0",
|
||||
"mime-types": "^2.1.34",
|
||||
"p-limit": "3.1.0",
|
||||
"systeminformation": "^5.11.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.8"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -19982,6 +19811,7 @@
|
|||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yocto-queue": "^0.1.0"
|
||||
}
|
||||
|
@ -20188,7 +20018,7 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"pirates": {
|
||||
"version": "4.0.6",
|
||||
|
@ -21330,11 +21160,6 @@
|
|||
"tslib": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"systeminformation": {
|
||||
"version": "5.21.9",
|
||||
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.9.tgz",
|
||||
"integrity": "sha512-7pI4mu9P/2MGDV0T49B52E7IULBGj+kRVk6JSYUj5qfAk7N7C7aNX15fXziqrbgZntc6/jjYzWeb/x41jhg/eA=="
|
||||
},
|
||||
"tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
|
@ -22417,6 +22242,11 @@
|
|||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"dev": true
|
||||
},
|
||||
"yaml": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
|
||||
"integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
|
@ -22452,7 +22282,8 @@
|
|||
"yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"zip-stream": {
|
||||
"version": "5.0.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "immich",
|
||||
"version": "1.87.0",
|
||||
"version": "1.88.0",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
@ -65,7 +65,7 @@
|
|||
"glob": "^10.3.3",
|
||||
"handlebars": "^4.7.8",
|
||||
"i18n-iso-countries": "^7.6.0",
|
||||
"immich": "^0.41.0",
|
||||
"@immich/cli": "^2.0.3",
|
||||
"ioredis": "^5.3.2",
|
||||
"joi": "^17.10.0",
|
||||
"local-reverse-geocoder": "0.16.5",
|
||||
|
|
|
@ -37,15 +37,6 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean): AlbumRespons
|
|||
const hasSharedLink = entity.sharedLinks?.length > 0;
|
||||
const hasSharedUser = sharedUsers.length > 0;
|
||||
|
||||
let startDate = assets.at(0)?.fileCreatedAt || undefined;
|
||||
let endDate = assets.at(-1)?.fileCreatedAt || undefined;
|
||||
// Swap dates if start date is greater than end date.
|
||||
if (startDate && endDate && startDate > endDate) {
|
||||
const temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
return {
|
||||
albumName: entity.albumName,
|
||||
description: entity.description,
|
||||
|
@ -58,10 +49,10 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean): AlbumRespons
|
|||
sharedUsers,
|
||||
shared: hasSharedUser || hasSharedLink,
|
||||
hasSharedLink,
|
||||
startDate,
|
||||
endDate,
|
||||
startDate: entity.startDate ? entity.startDate : undefined,
|
||||
endDate: entity.endDate ? entity.endDate : undefined,
|
||||
assets: (withAssets ? assets : []).map((asset) => mapAsset(asset)),
|
||||
assetCount: entity.assets?.length || 0,
|
||||
assetCount: entity.assetCount,
|
||||
isActivityEnabled: entity.isActivityEnabled,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -58,10 +58,6 @@ describe(AlbumService.name, () => {
|
|||
describe('getAll', () => {
|
||||
it('gets list of albums for auth user', async () => {
|
||||
albumMock.getOwned.mockResolvedValue([albumStub.empty, albumStub.sharedWithUser]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([
|
||||
{ albumId: albumStub.empty.id, assetCount: 0 },
|
||||
{ albumId: albumStub.sharedWithUser.id, assetCount: 0 },
|
||||
]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([]);
|
||||
|
||||
const result = await sut.getAll(authStub.admin, {});
|
||||
|
@ -72,7 +68,6 @@ describe(AlbumService.name, () => {
|
|||
|
||||
it('gets list of albums that have a specific asset', async () => {
|
||||
albumMock.getByAssetId.mockResolvedValue([albumStub.oneAsset]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([{ albumId: albumStub.oneAsset.id, assetCount: 1 }]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([]);
|
||||
|
||||
const result = await sut.getAll(authStub.admin, { assetId: albumStub.oneAsset.id });
|
||||
|
@ -83,7 +78,6 @@ describe(AlbumService.name, () => {
|
|||
|
||||
it('gets list of albums that are shared', async () => {
|
||||
albumMock.getShared.mockResolvedValue([albumStub.sharedWithUser]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([{ albumId: albumStub.sharedWithUser.id, assetCount: 0 }]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([]);
|
||||
|
||||
const result = await sut.getAll(authStub.admin, { shared: true });
|
||||
|
@ -94,7 +88,6 @@ describe(AlbumService.name, () => {
|
|||
|
||||
it('gets list of albums that are NOT shared', async () => {
|
||||
albumMock.getNotShared.mockResolvedValue([albumStub.empty]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([{ albumId: albumStub.empty.id, assetCount: 0 }]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([]);
|
||||
|
||||
const result = await sut.getAll(authStub.admin, { shared: false });
|
||||
|
@ -106,7 +99,6 @@ describe(AlbumService.name, () => {
|
|||
|
||||
it('counts assets correctly', async () => {
|
||||
albumMock.getOwned.mockResolvedValue([albumStub.oneAsset]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([{ albumId: albumStub.oneAsset.id, assetCount: 1 }]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([]);
|
||||
|
||||
const result = await sut.getAll(authStub.admin, {});
|
||||
|
@ -118,9 +110,6 @@ describe(AlbumService.name, () => {
|
|||
|
||||
it('updates the album thumbnail by listing all albums', async () => {
|
||||
albumMock.getOwned.mockResolvedValue([albumStub.oneAssetInvalidThumbnail]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([
|
||||
{ albumId: albumStub.oneAssetInvalidThumbnail.id, assetCount: 1 },
|
||||
]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([albumStub.oneAssetInvalidThumbnail.id]);
|
||||
albumMock.update.mockResolvedValue(albumStub.oneAssetValidThumbnail);
|
||||
assetMock.getFirstAssetForAlbumId.mockResolvedValue(albumStub.oneAssetInvalidThumbnail.assets[0]);
|
||||
|
@ -134,9 +123,6 @@ describe(AlbumService.name, () => {
|
|||
|
||||
it('removes the thumbnail for an empty album', async () => {
|
||||
albumMock.getOwned.mockResolvedValue([albumStub.emptyWithInvalidThumbnail]);
|
||||
albumMock.getAssetCountForIds.mockResolvedValue([
|
||||
{ albumId: albumStub.emptyWithInvalidThumbnail.id, assetCount: 1 },
|
||||
]);
|
||||
albumMock.getInvalidThumbnail.mockResolvedValue([albumStub.emptyWithInvalidThumbnail.id]);
|
||||
albumMock.update.mockResolvedValue(albumStub.emptyWithValidThumbnail);
|
||||
assetMock.getFirstAssetForAlbumId.mockResolvedValue(null);
|
||||
|
|
|
@ -66,21 +66,12 @@ export class AlbumService {
|
|||
albums = await this.albumRepository.getOwned(ownerId);
|
||||
}
|
||||
|
||||
// Get asset count for each album. Then map the result to an object:
|
||||
// { [albumId]: assetCount }
|
||||
const albumsAssetCount = await this.albumRepository.getAssetCountForIds(albums.map((album) => album.id));
|
||||
const albumsAssetCountObj = albumsAssetCount.reduce((obj: Record<string, number>, { albumId, assetCount }) => {
|
||||
obj[albumId] = assetCount;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
return Promise.all(
|
||||
albums.map(async (album) => {
|
||||
const lastModifiedAsset = await this.assetRepository.getLastUpdatedAssetForAlbumId(album.id);
|
||||
return {
|
||||
...mapAlbumWithoutAssets(album),
|
||||
sharedLinks: undefined,
|
||||
assetCount: albumsAssetCountObj[album.id],
|
||||
lastModifiedAssetTimestamp: lastModifiedAsset?.fileModifiedAt,
|
||||
};
|
||||
}),
|
||||
|
|
|
@ -7,6 +7,7 @@ describe('mimeTypes', () => {
|
|||
{ mimetype: 'image/ari', extension: '.ari' },
|
||||
{ mimetype: 'image/arw', extension: '.arw' },
|
||||
{ mimetype: 'image/avif', extension: '.avif' },
|
||||
{ mimetype: 'image/bmp', extension: '.bmp' },
|
||||
{ mimetype: 'image/cap', extension: '.cap' },
|
||||
{ mimetype: 'image/cin', extension: '.cin' },
|
||||
{ mimetype: 'image/cr2', extension: '.cr2' },
|
||||
|
|
|
@ -63,6 +63,7 @@ const image: Record<string, string[]> = {
|
|||
'.ari': ['image/ari', 'image/x-arriflex-ari'],
|
||||
'.arw': ['image/arw', 'image/x-sony-arw'],
|
||||
'.avif': ['image/avif'],
|
||||
'.bmp': ['image/bmp'],
|
||||
'.cap': ['image/cap', 'image/x-phaseone-cap'],
|
||||
'.cin': ['image/cin', 'image/x-phantom-cin'],
|
||||
'.cr2': ['image/cr2', 'image/x-canon-cr2'],
|
||||
|
|
|
@ -39,7 +39,7 @@ interface DirectoryEntry {
|
|||
type ExifEntityWithoutGeocodeAndTypeOrm = Omit<
|
||||
ExifEntity,
|
||||
'city' | 'state' | 'country' | 'description' | 'exifTextSearchableColumn'
|
||||
>;
|
||||
> & { dateTimeOriginal: Date };
|
||||
|
||||
const exifDate = (dt: ExifDateTime | string | undefined) => (dt instanceof ExifDateTime ? dt?.toDate() : null);
|
||||
const tzOffset = (dt: ExifDateTime | string | undefined) => (dt instanceof ExifDateTime ? dt?.tzoffsetMinutes : null);
|
||||
|
@ -181,7 +181,7 @@ export class MetadataService {
|
|||
await this.applyReverseGeocoding(asset, exifData);
|
||||
await this.assetRepository.upsertExif(exifData);
|
||||
|
||||
const dateTimeOriginal = exifDate(firstDateTime(tags as Tags)) ?? exifData.dateTimeOriginal;
|
||||
const dateTimeOriginal = exifData.dateTimeOriginal;
|
||||
let localDateTime = dateTimeOriginal ?? undefined;
|
||||
|
||||
const timeZoneOffset = tzOffset(firstDateTime(tags as Tags)) ?? 0;
|
||||
|
|
|
@ -30,7 +30,6 @@ export interface IAlbumRepository {
|
|||
hasAsset(asset: AlbumAsset): Promise<boolean>;
|
||||
removeAsset(assetId: string): Promise<void>;
|
||||
removeAssets(assets: AlbumAssets): Promise<void>;
|
||||
getAssetCountForIds(ids: string[]): Promise<AlbumAssetCount[]>;
|
||||
getInvalidThumbnail(): Promise<string[]>;
|
||||
getOwned(ownerId: string): Promise<AlbumEntity[]>;
|
||||
getShared(ownerId: string): Promise<AlbumEntity[]>;
|
||||
|
|
|
@ -40,7 +40,7 @@ export function mapSharedLink(sharedLink: SharedLinkEntity): SharedLinkResponseD
|
|||
createdAt: sharedLink.createdAt,
|
||||
expiresAt: sharedLink.expiresAt,
|
||||
assets: assets.map((asset) => mapAsset(asset)),
|
||||
album: sharedLink.album ? mapAlbumWithoutAssets(sharedLink.album) : undefined,
|
||||
album: sharedLink.album?.id ? mapAlbumWithoutAssets(sharedLink.album) : undefined,
|
||||
allowUpload: sharedLink.allowUpload,
|
||||
allowDownload: sharedLink.allowDownload,
|
||||
showMetadata: sharedLink.showExif,
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
VirtualColumn,
|
||||
} from 'typeorm';
|
||||
import { AssetEntity } from './asset.entity';
|
||||
import { SharedLinkEntity } from './shared-link.entity';
|
||||
|
@ -59,4 +60,34 @@ export class AlbumEntity {
|
|||
|
||||
@Column({ default: true })
|
||||
isActivityEnabled!: boolean;
|
||||
|
||||
@VirtualColumn({
|
||||
query: (alias) => `
|
||||
SELECT MIN(assets."fileCreatedAt")
|
||||
FROM "assets" assets
|
||||
JOIN "albums_assets_assets" aa ON aa."assetsId" = assets.id
|
||||
WHERE aa."albumsId" = ${alias}.id
|
||||
`,
|
||||
})
|
||||
startDate!: Date | null;
|
||||
|
||||
@VirtualColumn({
|
||||
query: (alias) => `
|
||||
SELECT MAX(assets."fileCreatedAt")
|
||||
FROM "assets" assets
|
||||
JOIN "albums_assets_assets" aa ON aa."assetsId" = assets.id
|
||||
WHERE aa."albumsId" = ${alias}.id
|
||||
`,
|
||||
})
|
||||
endDate!: Date | null;
|
||||
|
||||
@VirtualColumn({
|
||||
query: (alias) => `
|
||||
SELECT COUNT(assets."id")
|
||||
FROM "assets" assets
|
||||
JOIN "albums_assets_assets" aa ON aa."assetsId" = assets.id
|
||||
WHERE aa."albumsId" = ${alias}.id
|
||||
`,
|
||||
})
|
||||
assetCount!: number;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AlbumAsset, AlbumAssetCount, AlbumAssets, AlbumInfoOptions, IAlbumRepository } from '@app/domain';
|
||||
import { AlbumAsset, AlbumAssets, AlbumInfoOptions, IAlbumRepository } from '@app/domain';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
|
||||
|
@ -59,28 +59,6 @@ export class AlbumRepository implements IAlbumRepository {
|
|||
});
|
||||
}
|
||||
|
||||
async getAssetCountForIds(ids: string[]): Promise<AlbumAssetCount[]> {
|
||||
// Guard against running invalid query when ids list is empty.
|
||||
if (!ids.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Only possible with query builder because of GROUP BY.
|
||||
const countByAlbums = await this.repository
|
||||
.createQueryBuilder('album')
|
||||
.select('album.id')
|
||||
.addSelect('COUNT(albums_assets.assetsId)', 'asset_count')
|
||||
.leftJoin('albums_assets_assets', 'albums_assets', 'albums_assets.albumsId = album.id')
|
||||
.where('album.id IN (:...ids)', { ids })
|
||||
.groupBy('album.id')
|
||||
.getRawMany();
|
||||
|
||||
return countByAlbums.map<AlbumAssetCount>((albumCount) => ({
|
||||
albumId: albumCount['album_id'],
|
||||
assetCount: Number(albumCount['asset_count']),
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the album IDs that have an invalid thumbnail, when:
|
||||
* - Thumbnail references an asset outside the album
|
||||
|
|
30
server/test/fixtures/album.stub.ts
vendored
30
server/test/fixtures/album.stub.ts
vendored
|
@ -19,6 +19,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
assetCount: 0,
|
||||
}),
|
||||
sharedWithUser: Object.freeze<AlbumEntity>({
|
||||
id: 'album-2',
|
||||
|
@ -35,6 +38,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [userStub.user1],
|
||||
isActivityEnabled: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
assetCount: 0,
|
||||
}),
|
||||
sharedWithMultiple: Object.freeze<AlbumEntity>({
|
||||
id: 'album-3',
|
||||
|
@ -51,6 +57,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [userStub.user1, userStub.user2],
|
||||
isActivityEnabled: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
assetCount: 0,
|
||||
}),
|
||||
sharedWithAdmin: Object.freeze<AlbumEntity>({
|
||||
id: 'album-3',
|
||||
|
@ -67,6 +76,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [userStub.admin],
|
||||
isActivityEnabled: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
assetCount: 0,
|
||||
}),
|
||||
oneAsset: Object.freeze<AlbumEntity>({
|
||||
id: 'album-4',
|
||||
|
@ -83,6 +95,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: assetStub.image.fileCreatedAt,
|
||||
endDate: assetStub.image.fileCreatedAt,
|
||||
assetCount: 1,
|
||||
}),
|
||||
twoAssets: Object.freeze<AlbumEntity>({
|
||||
id: 'album-4a',
|
||||
|
@ -99,6 +114,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: assetStub.withLocation.fileCreatedAt,
|
||||
endDate: assetStub.image.fileCreatedAt,
|
||||
assetCount: 2,
|
||||
}),
|
||||
emptyWithInvalidThumbnail: Object.freeze<AlbumEntity>({
|
||||
id: 'album-5',
|
||||
|
@ -115,6 +133,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
assetCount: 0,
|
||||
}),
|
||||
emptyWithValidThumbnail: Object.freeze<AlbumEntity>({
|
||||
id: 'album-5',
|
||||
|
@ -131,6 +152,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
assetCount: 0,
|
||||
}),
|
||||
oneAssetInvalidThumbnail: Object.freeze<AlbumEntity>({
|
||||
id: 'album-6',
|
||||
|
@ -147,6 +171,9 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: assetStub.image.fileCreatedAt,
|
||||
endDate: assetStub.image.fileCreatedAt,
|
||||
assetCount: 1,
|
||||
}),
|
||||
oneAssetValidThumbnail: Object.freeze<AlbumEntity>({
|
||||
id: 'album-6',
|
||||
|
@ -163,5 +190,8 @@ export const albumStub = {
|
|||
sharedLinks: [],
|
||||
sharedUsers: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: assetStub.image.fileCreatedAt,
|
||||
endDate: assetStub.image.fileCreatedAt,
|
||||
assetCount: 1,
|
||||
}),
|
||||
};
|
||||
|
|
3
server/test/fixtures/shared-link.stub.ts
vendored
3
server/test/fixtures/shared-link.stub.ts
vendored
|
@ -181,6 +181,9 @@ export const sharedLinkStub = {
|
|||
sharedUsers: [],
|
||||
sharedLinks: [],
|
||||
isActivityEnabled: true,
|
||||
startDate: today,
|
||||
endDate: today,
|
||||
assetCount: 1,
|
||||
assets: [
|
||||
{
|
||||
id: 'id_1',
|
||||
|
|
|
@ -5,7 +5,6 @@ export const newAlbumRepositoryMock = (): jest.Mocked<IAlbumRepository> => {
|
|||
getById: jest.fn(),
|
||||
getByIds: jest.fn(),
|
||||
getByAssetId: jest.fn(),
|
||||
getAssetCountForIds: jest.fn(),
|
||||
getInvalidThumbnail: jest.fn(),
|
||||
getOwned: jest.fn(),
|
||||
getShared: jest.fn(),
|
||||
|
|
8
web/package-lock.json
generated
8
web/package-lock.json
generated
|
@ -45,7 +45,7 @@
|
|||
"autoprefixer": "^10.4.13",
|
||||
"babel-jest": "^29.4.3",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-svelte": "^2.30.0",
|
||||
"factory.ts": "^1.3.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
|
@ -5503,9 +5503,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-config-prettier": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
|
||||
"integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==",
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
|
||||
"integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"autoprefixer": "^10.4.13",
|
||||
"babel-jest": "^29.4.3",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-svelte": "^2.30.0",
|
||||
"factory.ts": "^1.3.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
|
|
2
web/src/api/open-api/api.ts
generated
2
web/src/api/open-api/api.ts
generated
|
@ -4,7 +4,7 @@
|
|||
* Immich
|
||||
* Immich API
|
||||
*
|
||||
* The version of the OpenAPI document: 1.87.0
|
||||
* The version of the OpenAPI document: 1.88.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue