Merge branch 'main' of https://github.com/immich-app/immich into feat/cli-e2e

This commit is contained in:
Jonathan Jogenfors 2023-11-20 23:48:28 +01:00
commit f6889c4d45
110 changed files with 687 additions and 856 deletions

14
cli/package-lock.json generated
View file

@ -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": {}
},

View file

@ -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",

View file

@ -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).

View file

@ -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).

View file

@ -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).

View file

@ -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).

View file

@ -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).

View file

@ -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

View file

@ -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()

View file

@ -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]

View file

@ -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"

View file

@ -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')

View file

@ -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>

View file

@ -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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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;

View file

@ -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>

View file

@ -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,

View file

@ -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>

View file

@ -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,

View file

@ -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,
),
),
),

View file

@ -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(),
),
];

View file

@ -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);

View file

@ -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(),

View file

@ -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,
),
);
}

View file

@ -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)

View file

@ -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(),
],
),

View file

@ -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(),
),

View file

@ -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,

View file

@ -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,
),

View file

@ -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(),
],
),
),

View file

@ -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(),
],

View file

@ -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(),
),

View file

@ -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(),

View file

@ -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(

View file

@ -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,
),
),
);

View file

@ -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,

View file

@ -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,
),
),
),
),

View file

@ -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,
),
);
}

View file

@ -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,
),
),
),

View file

@ -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,
),
),

View file

@ -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,
),
),

View file

@ -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,
),
),
],

View file

@ -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),

View file

@ -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(),
),

View file

@ -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(),

View file

@ -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(),

View file

@ -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(),
],
)

View file

@ -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(

View file

@ -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(

View file

@ -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,

View file

@ -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(),

View file

@ -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,

View file

@ -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(

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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,
);
}
}

View file

@ -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(

View file

@ -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(

View file

@ -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,
),
),

View file

@ -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(),
),

View file

@ -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,

View file

@ -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),
),
),
),

View file

@ -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,

View file

@ -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],
),
),
),

View file

@ -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

View file

@ -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"

View file

@ -1,2 +1,2 @@
#!/usr/bin/env bash
node ./node_modules/immich/bin/index "$@"
node ./node_modules/@immich/cli/dist/index "$@"

View file

@ -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
View file

@ -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",

View file

@ -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",

View file

@ -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,
};
};

View file

@ -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);

View file

@ -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,
};
}),

View file

@ -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' },

View file

@ -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'],

View file

@ -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;

View file

@ -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[]>;

View file

@ -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,

View file

@ -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;
}

View file

@ -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

View file

@ -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,
}),
};

View file

@ -181,6 +181,9 @@ export const sharedLinkStub = {
sharedUsers: [],
sharedLinks: [],
isActivityEnabled: true,
startDate: today,
endDate: today,
assetCount: 1,
assets: [
{
id: 'id_1',

View file

@ -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
View file

@ -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"

View file

@ -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",

View file

@ -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