mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	Add mobile dark mode and user setting (#468)
* styling light and dark theme * Icon topbar * Fixed app bar title dark theme * Fixed issue with getting thumbnail for things * Refactor sharing page * Refactor scroll thumb * Refactor chip in auto backup indiation button * Refactor sharing page * Added theme toggle * Up version for testflight build * Refactor backup controller page * Refactor album selection page * refactor album pages * Refactor gradient color profile header * Added theme switcher * Register app theme correctly * Added locale to the app * Added translation key * Styling for bottomsheet colors * up server version * Fixed font size * Fixed overlapsed sliverappbar on photos screen
This commit is contained in:
		@@ -30,8 +30,8 @@ platform :android do
 | 
				
			|||||||
      task: 'bundle', 
 | 
					      task: 'bundle', 
 | 
				
			||||||
      build_type: 'Release',
 | 
					      build_type: 'Release',
 | 
				
			||||||
      properties: {
 | 
					      properties: {
 | 
				
			||||||
        "android.injected.version.code" => 32,
 | 
					        "android.injected.version.code" => 33,
 | 
				
			||||||
        "android.injected.version.name" => "1.22.0",
 | 
					        "android.injected.version.name" => "1.23.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')
 | 
					    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')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,7 @@
 | 
				
			|||||||
  "control_bottom_app_bar_delete": "Delete",
 | 
					  "control_bottom_app_bar_delete": "Delete",
 | 
				
			||||||
  "create_shared_album_page_share": "Share",
 | 
					  "create_shared_album_page_share": "Share",
 | 
				
			||||||
  "create_shared_album_page_create": "Create",
 | 
					  "create_shared_album_page_create": "Create",
 | 
				
			||||||
  "create_shared_album_page_share_add_assets": "ADD ASSETS",
 | 
					  "create_shared_album_page_share_add_assets": "ADD PHOTOS",
 | 
				
			||||||
  "create_shared_album_page_share_select_photos": "Select Photos",
 | 
					  "create_shared_album_page_share_select_photos": "Select Photos",
 | 
				
			||||||
  "daily_title_text_date": "E, MMM dd",
 | 
					  "daily_title_text_date": "E, MMM dd",
 | 
				
			||||||
  "daily_title_text_date_year": "E, MMM dd, yyyy",
 | 
					  "daily_title_text_date_year": "E, MMM dd, yyyy",
 | 
				
			||||||
@@ -113,5 +113,14 @@
 | 
				
			|||||||
  "library_page_new_album": "New album",
 | 
					  "library_page_new_album": "New album",
 | 
				
			||||||
  "create_album_page_untitled": "Untitled",
 | 
					  "create_album_page_untitled": "Untitled",
 | 
				
			||||||
  "share_dialog_preparing": "Preparing...",
 | 
					  "share_dialog_preparing": "Preparing...",
 | 
				
			||||||
  "control_bottom_app_bar_share": "Share"
 | 
					  "control_bottom_app_bar_share": "Share",
 | 
				
			||||||
 | 
					  "setting_pages_app_bar_settings": "Settings",
 | 
				
			||||||
 | 
					  "theme_setting_theme_title": "Theme",
 | 
				
			||||||
 | 
					  "theme_setting_theme_subtitle": "Choose the app's theme setting",
 | 
				
			||||||
 | 
					  "theme_setting_system_theme_switch": "Automatic (Follow system setting)",
 | 
				
			||||||
 | 
					  "theme_setting_dark_mode_switch": "Dark mode",
 | 
				
			||||||
 | 
					  "theme_setting_image_viewer_quality_title": "Image viewer quality",
 | 
				
			||||||
 | 
					  "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer",
 | 
				
			||||||
 | 
					  "theme_setting_three_stage_loading_title": "Enable three-stage loading",
 | 
				
			||||||
 | 
					  "theme_setting_three_stage_loading_subtitle": "The three-stage loading delivers the best quality image in exchange for a slower loading speed"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ platform :ios do
 | 
				
			|||||||
  desc "iOS Beta"
 | 
					  desc "iOS Beta"
 | 
				
			||||||
  lane :beta do
 | 
					  lane :beta do
 | 
				
			||||||
    increment_version_number(
 | 
					    increment_version_number(
 | 
				
			||||||
    version_number: "1.22.0"
 | 
					    version_number: "1.23.0"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    increment_build_number(
 | 
					    increment_build_number(
 | 
				
			||||||
      build_number: latest_testflight_build_number + 1,
 | 
					      build_number: latest_testflight_build_number + 1,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const immichBackgroundColor = Color(0xFFf6f8fe);
 | 
					Color immichBackgroundColor = const Color(0xFFf6f8fe);
 | 
				
			||||||
 | 
					Color immichDarkBackgroundColor = const Color.fromARGB(255, 0, 0, 0);
 | 
				
			||||||
 | 
					Color immichDarkThemePrimaryColor = const Color.fromARGB(255, 173, 203, 250);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@ import 'package:flutter/services.dart';
 | 
				
			|||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
 | 
					import 'package:flutter_displaymode/flutter_displaymode.dart';
 | 
				
			||||||
import 'package:hive_flutter/hive_flutter.dart';
 | 
					import 'package:hive_flutter/hive_flutter.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:immich_mobile/constants/immich_colors.dart';
 | 
					 | 
				
			||||||
import 'package:immich_mobile/modules/backup/models/hive_backup_albums.model.dart';
 | 
					import 'package:immich_mobile/modules/backup/models/hive_backup_albums.model.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
					import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
 | 
					import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
 | 
				
			||||||
@@ -19,8 +18,10 @@ import 'package:immich_mobile/shared/providers/asset.provider.dart';
 | 
				
			|||||||
import 'package:immich_mobile/shared/providers/release_info.provider.dart';
 | 
					import 'package:immich_mobile/shared/providers/release_info.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
 | 
					import 'package:immich_mobile/shared/providers/server_info.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
 | 
					import 'package:immich_mobile/shared/providers/websocket.provider.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
 | 
					import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
 | 
					import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/utils/immich_app_theme.dart';
 | 
				
			||||||
import 'constants/hive_box.dart';
 | 
					import 'constants/hive_box.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void main() async {
 | 
					void main() async {
 | 
				
			||||||
@@ -50,8 +51,11 @@ void main() async {
 | 
				
			|||||||
    Locale('da', 'DK'),
 | 
					    Locale('da', 'DK'),
 | 
				
			||||||
    Locale('de', 'DE'),
 | 
					    Locale('de', 'DE'),
 | 
				
			||||||
    Locale('es', 'ES'),
 | 
					    Locale('es', 'ES'),
 | 
				
			||||||
 | 
					    Locale('fi', 'FI'),
 | 
				
			||||||
    Locale('fr', 'FR'),
 | 
					    Locale('fr', 'FR'),
 | 
				
			||||||
    Locale('it', 'IT'),
 | 
					    Locale('it', 'IT'),
 | 
				
			||||||
 | 
					    Locale('ja', 'JP'),
 | 
				
			||||||
 | 
					    Locale('pl', 'PL')
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (kReleaseMode && Platform.isAndroid) {
 | 
					  if (kReleaseMode && Platform.isAndroid) {
 | 
				
			||||||
@@ -130,7 +134,6 @@ class ImmichAppState extends ConsumerState<ImmichApp>
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  initState() {
 | 
					  initState() {
 | 
				
			||||||
    super.initState();
 | 
					    super.initState();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    initApp().then((_) => debugPrint("App Init Completed"));
 | 
					    initApp().then((_) => debugPrint("App Init Completed"));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -155,23 +158,9 @@ class ImmichAppState extends ConsumerState<ImmichApp>
 | 
				
			|||||||
          MaterialApp.router(
 | 
					          MaterialApp.router(
 | 
				
			||||||
            title: 'Immich',
 | 
					            title: 'Immich',
 | 
				
			||||||
            debugShowCheckedModeBanner: false,
 | 
					            debugShowCheckedModeBanner: false,
 | 
				
			||||||
            theme: ThemeData(
 | 
					            themeMode: ref.watch(immichThemeProvider),
 | 
				
			||||||
              useMaterial3: true,
 | 
					            darkTheme: immichDarkTheme,
 | 
				
			||||||
              brightness: Brightness.light,
 | 
					            theme: immichLightTheme,
 | 
				
			||||||
              primarySwatch: Colors.indigo,
 | 
					 | 
				
			||||||
              fontFamily: 'WorkSans',
 | 
					 | 
				
			||||||
              snackBarTheme: const SnackBarThemeData(
 | 
					 | 
				
			||||||
                contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              scaffoldBackgroundColor: immichBackgroundColor,
 | 
					 | 
				
			||||||
              appBarTheme: const AppBarTheme(
 | 
					 | 
				
			||||||
                backgroundColor: immichBackgroundColor,
 | 
					 | 
				
			||||||
                foregroundColor: Colors.indigo,
 | 
					 | 
				
			||||||
                elevation: 1,
 | 
					 | 
				
			||||||
                centerTitle: true,
 | 
					 | 
				
			||||||
                systemOverlayStyle: SystemUiOverlayStyle.dark,
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            routeInformationParser: router.defaultRouteParser(),
 | 
					            routeInformationParser: router.defaultRouteParser(),
 | 
				
			||||||
            routerDelegate: router.delegate(
 | 
					            routerDelegate: router.delegate(
 | 
				
			||||||
              navigatorObservers: () => [TabNavigationObserver(ref: ref)],
 | 
					              navigatorObservers: () => [TabNavigationObserver(ref: ref)],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,8 @@ class AlbumActionOutlinedButton extends StatelessWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Padding(
 | 
					    return Padding(
 | 
				
			||||||
      padding: const EdgeInsets.only(right: 8.0),
 | 
					      padding: const EdgeInsets.only(right: 8.0),
 | 
				
			||||||
      child: OutlinedButton.icon(
 | 
					      child: OutlinedButton.icon(
 | 
				
			||||||
@@ -22,18 +24,22 @@ class AlbumActionOutlinedButton extends StatelessWidget {
 | 
				
			|||||||
          shape: RoundedRectangleBorder(
 | 
					          shape: RoundedRectangleBorder(
 | 
				
			||||||
            borderRadius: BorderRadius.circular(25),
 | 
					            borderRadius: BorderRadius.circular(25),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          side: const BorderSide(
 | 
					          side: BorderSide(
 | 
				
			||||||
            width: 1,
 | 
					            width: 1,
 | 
				
			||||||
            color: Color.fromARGB(255, 215, 215, 215),
 | 
					            color: isDarkTheme
 | 
				
			||||||
 | 
					                ? const Color.fromARGB(255, 63, 63, 63)
 | 
				
			||||||
 | 
					                : const Color.fromARGB(255, 206, 206, 206),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        icon: Icon(iconData, size: 15),
 | 
					        icon: Icon(
 | 
				
			||||||
 | 
					          iconData,
 | 
				
			||||||
 | 
					          size: 15,
 | 
				
			||||||
 | 
					          color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
        label: Text(
 | 
					        label: Text(
 | 
				
			||||||
          labelText,
 | 
					          labelText,
 | 
				
			||||||
          style: const TextStyle(
 | 
					          style: Theme.of(context).textTheme.labelSmall?.copyWith(
 | 
				
			||||||
            fontSize: 12,
 | 
					 | 
				
			||||||
                fontWeight: FontWeight.bold,
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
            color: Colors.black87,
 | 
					 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        onPressed: onPressed,
 | 
					        onPressed: onPressed,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,7 +52,6 @@ class AlbumThumbnailCard extends StatelessWidget {
 | 
				
			|||||||
                  album.albumName,
 | 
					                  album.albumName,
 | 
				
			||||||
                  style: const TextStyle(
 | 
					                  style: const TextStyle(
 | 
				
			||||||
                    fontWeight: FontWeight.bold,
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
                    fontSize: 12,
 | 
					 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
@@ -65,14 +64,14 @@ class AlbumThumbnailCard extends StatelessWidget {
 | 
				
			|||||||
                      ? 'album_thumbnail_card_item'
 | 
					                      ? 'album_thumbnail_card_item'
 | 
				
			||||||
                      : 'album_thumbnail_card_items',
 | 
					                      : 'album_thumbnail_card_items',
 | 
				
			||||||
                  style: const TextStyle(
 | 
					                  style: const TextStyle(
 | 
				
			||||||
                    fontSize: 10,
 | 
					                    fontSize: 12,
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ).tr(args: ['${album.assetCount}']),
 | 
					                ).tr(args: ['${album.assetCount}']),
 | 
				
			||||||
                if (album.shared)
 | 
					                if (album.shared)
 | 
				
			||||||
                  const Text(
 | 
					                  const Text(
 | 
				
			||||||
                    'album_thumbnail_card_shared',
 | 
					                    'album_thumbnail_card_shared',
 | 
				
			||||||
                    style: TextStyle(
 | 
					                    style: TextStyle(
 | 
				
			||||||
                      fontSize: 10,
 | 
					                      fontSize: 12,
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                  ).tr()
 | 
					                  ).tr()
 | 
				
			||||||
              ],
 | 
					              ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,8 @@ class AlbumTitleTextField extends ConsumerWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return TextField(
 | 
					    return TextField(
 | 
				
			||||||
      onChanged: (v) {
 | 
					      onChanged: (v) {
 | 
				
			||||||
        if (v.isEmpty) {
 | 
					        if (v.isEmpty) {
 | 
				
			||||||
@@ -51,7 +53,10 @@ class AlbumTitleTextField extends ConsumerWidget {
 | 
				
			|||||||
                  albumTitleController.clear();
 | 
					                  albumTitleController.clear();
 | 
				
			||||||
                  isAlbumTitleEmpty.value = true;
 | 
					                  isAlbumTitleEmpty.value = true;
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                icon: const Icon(Icons.cancel_rounded),
 | 
					                icon: Icon(
 | 
				
			||||||
 | 
					                  Icons.cancel_rounded,
 | 
				
			||||||
 | 
					                  color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
                splashRadius: 10,
 | 
					                splashRadius: 10,
 | 
				
			||||||
              )
 | 
					              )
 | 
				
			||||||
            : null,
 | 
					            : null,
 | 
				
			||||||
@@ -65,7 +70,9 @@ class AlbumTitleTextField extends ConsumerWidget {
 | 
				
			|||||||
        ),
 | 
					        ),
 | 
				
			||||||
        hintText: 'share_add_title'.tr(),
 | 
					        hintText: 'share_add_title'.tr(),
 | 
				
			||||||
        focusColor: Colors.grey[300],
 | 
					        focusColor: Colors.grey[300],
 | 
				
			||||||
        fillColor: Colors.grey[200],
 | 
					        fillColor: isDarkTheme
 | 
				
			||||||
 | 
					            ? const Color.fromARGB(255, 32, 33, 35)
 | 
				
			||||||
 | 
					            : Colors.grey[200],
 | 
				
			||||||
        filled: isAlbumTitleTextFieldFocus.value,
 | 
					        filled: isAlbumTitleTextFieldFocus.value,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -150,7 +150,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void _buildBottomSheet() {
 | 
					    void _buildBottomSheet() {
 | 
				
			||||||
      showModalBottomSheet(
 | 
					      showModalBottomSheet(
 | 
				
			||||||
        backgroundColor: immichBackgroundColor,
 | 
					        backgroundColor: Theme.of(context).scaffoldBackgroundColor,
 | 
				
			||||||
        isScrollControlled: false,
 | 
					        isScrollControlled: false,
 | 
				
			||||||
        context: context,
 | 
					        context: context,
 | 
				
			||||||
        builder: (context) {
 | 
					        builder: (context) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
 | 
				
			|||||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
    final titleTextEditController =
 | 
					    final titleTextEditController =
 | 
				
			||||||
        useTextEditingController(text: albumInfo.albumName);
 | 
					        useTextEditingController(text: albumInfo.albumName);
 | 
				
			||||||
 | 
					    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void onFocusModeChange() {
 | 
					    void onFocusModeChange() {
 | 
				
			||||||
      if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) {
 | 
					      if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) {
 | 
				
			||||||
@@ -65,7 +66,10 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
 | 
				
			|||||||
                onPressed: () {
 | 
					                onPressed: () {
 | 
				
			||||||
                  titleTextEditController.clear();
 | 
					                  titleTextEditController.clear();
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                icon: const Icon(Icons.cancel_rounded),
 | 
					                icon: Icon(
 | 
				
			||||||
 | 
					                  Icons.cancel_rounded,
 | 
				
			||||||
 | 
					                  color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
                splashRadius: 10,
 | 
					                splashRadius: 10,
 | 
				
			||||||
              )
 | 
					              )
 | 
				
			||||||
            : null,
 | 
					            : null,
 | 
				
			||||||
@@ -78,7 +82,9 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
 | 
				
			|||||||
          borderRadius: BorderRadius.circular(10),
 | 
					          borderRadius: BorderRadius.circular(10),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        focusColor: Colors.grey[300],
 | 
					        focusColor: Colors.grey[300],
 | 
				
			||||||
        fillColor: Colors.grey[200],
 | 
					        fillColor: isDarkTheme
 | 
				
			||||||
 | 
					            ? const Color.fromARGB(255, 32, 33, 35)
 | 
				
			||||||
 | 
					            : Colors.grey[200],
 | 
				
			||||||
        filled: titleFocusNode.hasFocus,
 | 
					        filled: titleFocusNode.hasFocus,
 | 
				
			||||||
        hintText: 'share_add_title'.tr(),
 | 
					        hintText: 'share_add_title'.tr(),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,13 +35,7 @@ class SharingSliverAppBar extends StatelessWidget {
 | 
				
			|||||||
              Expanded(
 | 
					              Expanded(
 | 
				
			||||||
                child: Padding(
 | 
					                child: Padding(
 | 
				
			||||||
                  padding: const EdgeInsets.only(right: 4.0),
 | 
					                  padding: const EdgeInsets.only(right: 4.0),
 | 
				
			||||||
                  child: TextButton.icon(
 | 
					                  child: ElevatedButton.icon(
 | 
				
			||||||
                    style: ButtonStyle(
 | 
					 | 
				
			||||||
                      backgroundColor: MaterialStateProperty.all(
 | 
					 | 
				
			||||||
                        Theme.of(context).primaryColor.withAlpha(20),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                      // foregroundColor: MaterialStateProperty.all(Colors.white),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                    onPressed: () {
 | 
					                    onPressed: () {
 | 
				
			||||||
                      AutoRouter.of(context)
 | 
					                      AutoRouter.of(context)
 | 
				
			||||||
                          .push(CreateAlbumRoute(isSharedAlbum: true));
 | 
					                          .push(CreateAlbumRoute(isSharedAlbum: true));
 | 
				
			||||||
@@ -52,8 +46,12 @@ class SharingSliverAppBar extends StatelessWidget {
 | 
				
			|||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                    label: const Text(
 | 
					                    label: const Text(
 | 
				
			||||||
                      "sharing_silver_appbar_create_shared_album",
 | 
					                      "sharing_silver_appbar_create_shared_album",
 | 
				
			||||||
                      style:
 | 
					                      maxLines: 1,
 | 
				
			||||||
                          TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
 | 
					                      style: TextStyle(
 | 
				
			||||||
 | 
					                        fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                        fontSize: 11,
 | 
				
			||||||
 | 
					                        // color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
                    ).tr(),
 | 
					                    ).tr(),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
@@ -61,13 +59,7 @@ class SharingSliverAppBar extends StatelessWidget {
 | 
				
			|||||||
              Expanded(
 | 
					              Expanded(
 | 
				
			||||||
                child: Padding(
 | 
					                child: Padding(
 | 
				
			||||||
                  padding: const EdgeInsets.only(left: 4.0),
 | 
					                  padding: const EdgeInsets.only(left: 4.0),
 | 
				
			||||||
                  child: TextButton.icon(
 | 
					                  child: ElevatedButton.icon(
 | 
				
			||||||
                    style: ButtonStyle(
 | 
					 | 
				
			||||||
                      backgroundColor: MaterialStateProperty.all(
 | 
					 | 
				
			||||||
                        Theme.of(context).primaryColor.withAlpha(20),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                      // foregroundColor: MaterialStateProperty.all(Colors.white),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                    onPressed: null,
 | 
					                    onPressed: null,
 | 
				
			||||||
                    icon: const Icon(
 | 
					                    icon: const Icon(
 | 
				
			||||||
                      Icons.swap_horizontal_circle_outlined,
 | 
					                      Icons.swap_horizontal_circle_outlined,
 | 
				
			||||||
@@ -75,8 +67,11 @@ class SharingSliverAppBar extends StatelessWidget {
 | 
				
			|||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                    label: const Text(
 | 
					                    label: const Text(
 | 
				
			||||||
                      "sharing_silver_appbar_share_partner",
 | 
					                      "sharing_silver_appbar_share_partner",
 | 
				
			||||||
                      style:
 | 
					                      style: TextStyle(
 | 
				
			||||||
                          TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
 | 
					                        fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                        fontSize: 11,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      maxLines: 1,
 | 
				
			||||||
                    ).tr(),
 | 
					                    ).tr(),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ import 'package:easy_localization/easy_localization.dart';
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter_hooks/flutter_hooks.dart';
 | 
					import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:immich_mobile/constants/immich_colors.dart';
 | 
					 | 
				
			||||||
import 'package:immich_mobile/modules/home/ui/draggable_scrollbar.dart';
 | 
					import 'package:immich_mobile/modules/home/ui/draggable_scrollbar.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 | 
					import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
 | 
					import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
 | 
				
			||||||
@@ -242,7 +241,7 @@ class AlbumViewerPage extends HookConsumerWidget {
 | 
				
			|||||||
          titleFocusNode.unfocus();
 | 
					          titleFocusNode.unfocus();
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        child: DraggableScrollbar.semicircle(
 | 
					        child: DraggableScrollbar.semicircle(
 | 
				
			||||||
          backgroundColor: Theme.of(context).primaryColor,
 | 
					          backgroundColor: Theme.of(context).hintColor,
 | 
				
			||||||
          controller: scrollController,
 | 
					          controller: scrollController,
 | 
				
			||||||
          heightScrollThumb: 48.0,
 | 
					          heightScrollThumb: 48.0,
 | 
				
			||||||
          child: CustomScrollView(
 | 
					          child: CustomScrollView(
 | 
				
			||||||
@@ -255,7 +254,7 @@ class AlbumViewerPage extends HookConsumerWidget {
 | 
				
			|||||||
                  minHeight: 50,
 | 
					                  minHeight: 50,
 | 
				
			||||||
                  maxHeight: 50,
 | 
					                  maxHeight: 50,
 | 
				
			||||||
                  child: Container(
 | 
					                  child: Container(
 | 
				
			||||||
                    color: immichBackgroundColor,
 | 
					                    color: Theme.of(context).scaffoldBackgroundColor,
 | 
				
			||||||
                    child: _buildControlButton(albumInfo),
 | 
					                    child: _buildControlButton(albumInfo),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ class AssetSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
      return Stack(
 | 
					      return Stack(
 | 
				
			||||||
        children: [
 | 
					        children: [
 | 
				
			||||||
          DraggableScrollbar.semicircle(
 | 
					          DraggableScrollbar.semicircle(
 | 
				
			||||||
            backgroundColor: Theme.of(context).primaryColor,
 | 
					            backgroundColor: Theme.of(context).hintColor,
 | 
				
			||||||
            controller: scrollController,
 | 
					            controller: scrollController,
 | 
				
			||||||
            heightScrollThumb: 48.0,
 | 
					            heightScrollThumb: 48.0,
 | 
				
			||||||
            child: CustomScrollView(
 | 
					            child: CustomScrollView(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,7 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
    final isAlbumTitleEmpty = useState(true);
 | 
					    final isAlbumTitleEmpty = useState(true);
 | 
				
			||||||
    final selectedAssets =
 | 
					    final selectedAssets =
 | 
				
			||||||
        ref.watch(assetSelectionProvider).selectedNewAssetsForAlbum;
 | 
					        ref.watch(assetSelectionProvider).selectedNewAssetsForAlbum;
 | 
				
			||||||
 | 
					    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _showSelectUserPage() {
 | 
					    _showSelectUserPage() {
 | 
				
			||||||
      AutoRouter.of(context).push(const SelectUserForSharingRoute());
 | 
					      AutoRouter.of(context).push(const SelectUserForSharingRoute());
 | 
				
			||||||
@@ -75,9 +76,12 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
        return SliverToBoxAdapter(
 | 
					        return SliverToBoxAdapter(
 | 
				
			||||||
          child: Padding(
 | 
					          child: Padding(
 | 
				
			||||||
            padding: const EdgeInsets.only(top: 200, left: 18),
 | 
					            padding: const EdgeInsets.only(top: 200, left: 18),
 | 
				
			||||||
            child: const Text(
 | 
					            child: Text(
 | 
				
			||||||
              'create_shared_album_page_share_add_assets',
 | 
					              'create_shared_album_page_share_add_assets',
 | 
				
			||||||
              style: TextStyle(fontSize: 12),
 | 
					              style: Theme.of(context).textTheme.headline2?.copyWith(
 | 
				
			||||||
 | 
					                    fontSize: 12,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.normal,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
            ).tr(),
 | 
					            ).tr(),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
@@ -96,22 +100,26 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
                alignment: Alignment.centerLeft,
 | 
					                alignment: Alignment.centerLeft,
 | 
				
			||||||
                padding:
 | 
					                padding:
 | 
				
			||||||
                    const EdgeInsets.symmetric(vertical: 22, horizontal: 16),
 | 
					                    const EdgeInsets.symmetric(vertical: 22, horizontal: 16),
 | 
				
			||||||
                side: const BorderSide(
 | 
					                side: BorderSide(
 | 
				
			||||||
                  color: Color.fromARGB(255, 206, 206, 206),
 | 
					                  color: isDarkTheme
 | 
				
			||||||
 | 
					                      ? const Color.fromARGB(255, 63, 63, 63)
 | 
				
			||||||
 | 
					                      : const Color.fromARGB(255, 206, 206, 206),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                shape: RoundedRectangleBorder(
 | 
					                shape: RoundedRectangleBorder(
 | 
				
			||||||
                  borderRadius: BorderRadius.circular(5),
 | 
					                  borderRadius: BorderRadius.circular(5),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              onPressed: _onSelectPhotosButtonPressed,
 | 
					              onPressed: _onSelectPhotosButtonPressed,
 | 
				
			||||||
              icon: const Icon(Icons.add_rounded),
 | 
					              icon: Icon(
 | 
				
			||||||
 | 
					                Icons.add_rounded,
 | 
				
			||||||
 | 
					                color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
              label: Padding(
 | 
					              label: Padding(
 | 
				
			||||||
                padding: const EdgeInsets.only(left: 8.0),
 | 
					                padding: const EdgeInsets.only(left: 8.0),
 | 
				
			||||||
                child: Text(
 | 
					                child: Text(
 | 
				
			||||||
                  'create_shared_album_page_share_select_photos',
 | 
					                  'create_shared_album_page_share_select_photos',
 | 
				
			||||||
                  style: TextStyle(
 | 
					                  style: Theme.of(context).textTheme.labelLarge?.copyWith(
 | 
				
			||||||
                        fontSize: 16,
 | 
					                        fontSize: 16,
 | 
				
			||||||
                    color: Colors.grey[700],
 | 
					 | 
				
			||||||
                        fontWeight: FontWeight.bold,
 | 
					                        fontWeight: FontWeight.bold,
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
                ).tr(),
 | 
					                ).tr(),
 | 
				
			||||||
@@ -190,6 +198,7 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
      appBar: AppBar(
 | 
					      appBar: AppBar(
 | 
				
			||||||
        elevation: 0,
 | 
					        elevation: 0,
 | 
				
			||||||
        centerTitle: false,
 | 
					        centerTitle: false,
 | 
				
			||||||
 | 
					        backgroundColor: Theme.of(context).scaffoldBackgroundColor,
 | 
				
			||||||
        leading: IconButton(
 | 
					        leading: IconButton(
 | 
				
			||||||
          onPressed: () {
 | 
					          onPressed: () {
 | 
				
			||||||
            ref.watch(assetSelectionProvider.notifier).removeAll();
 | 
					            ref.watch(assetSelectionProvider.notifier).removeAll();
 | 
				
			||||||
@@ -197,9 +206,11 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
          },
 | 
					          },
 | 
				
			||||||
          icon: const Icon(Icons.close_rounded),
 | 
					          icon: const Icon(Icons.close_rounded),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        title: const Text(
 | 
					        title: Text(
 | 
				
			||||||
          'share_create_album',
 | 
					          'share_create_album',
 | 
				
			||||||
          style: TextStyle(color: Colors.black),
 | 
					          style: Theme.of(context).textTheme.headline2?.copyWith(
 | 
				
			||||||
 | 
					                color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
        ).tr(),
 | 
					        ).tr(),
 | 
				
			||||||
        actions: [
 | 
					        actions: [
 | 
				
			||||||
          if (isSharedAlbum)
 | 
					          if (isSharedAlbum)
 | 
				
			||||||
@@ -209,8 +220,9 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
                  : null,
 | 
					                  : null,
 | 
				
			||||||
              child: Text(
 | 
					              child: Text(
 | 
				
			||||||
                'create_shared_album_page_share'.tr(),
 | 
					                'create_shared_album_page_share'.tr(),
 | 
				
			||||||
                style: const TextStyle(
 | 
					                style: TextStyle(
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  color: Theme.of(context).primaryColor,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
@@ -234,9 +246,9 @@ class CreateAlbumPage extends HookConsumerWidget {
 | 
				
			|||||||
        child: CustomScrollView(
 | 
					        child: CustomScrollView(
 | 
				
			||||||
          slivers: [
 | 
					          slivers: [
 | 
				
			||||||
            SliverAppBar(
 | 
					            SliverAppBar(
 | 
				
			||||||
 | 
					              backgroundColor: Theme.of(context).scaffoldBackgroundColor,
 | 
				
			||||||
              elevation: 5,
 | 
					              elevation: 5,
 | 
				
			||||||
              automaticallyImplyLeading: false,
 | 
					              automaticallyImplyLeading: false,
 | 
				
			||||||
              // leading: Container(),
 | 
					 | 
				
			||||||
              pinned: true,
 | 
					              pinned: true,
 | 
				
			||||||
              floating: false,
 | 
					              floating: false,
 | 
				
			||||||
              bottom: PreferredSize(
 | 
					              bottom: PreferredSize(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ class LibraryPage extends HookConsumerWidget {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Widget _buildAppBar() {
 | 
					    Widget _buildAppBar() {
 | 
				
			||||||
      return SliverAppBar(
 | 
					      return const SliverAppBar(
 | 
				
			||||||
        centerTitle: true,
 | 
					        centerTitle: true,
 | 
				
			||||||
        floating: true,
 | 
					        floating: true,
 | 
				
			||||||
        pinned: false,
 | 
					        pinned: false,
 | 
				
			||||||
@@ -35,7 +35,6 @@ class LibraryPage extends HookConsumerWidget {
 | 
				
			|||||||
            fontFamily: 'SnowburstOne',
 | 
					            fontFamily: 'SnowburstOne',
 | 
				
			||||||
            fontWeight: FontWeight.bold,
 | 
					            fontWeight: FontWeight.bold,
 | 
				
			||||||
            fontSize: 22,
 | 
					            fontSize: 22,
 | 
				
			||||||
            color: Theme.of(context).primaryColor,
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@@ -72,7 +71,6 @@ class LibraryPage extends HookConsumerWidget {
 | 
				
			|||||||
              child: const Text(
 | 
					              child: const Text(
 | 
				
			||||||
                'library_page_new_album',
 | 
					                'library_page_new_album',
 | 
				
			||||||
                style: TextStyle(
 | 
					                style: TextStyle(
 | 
				
			||||||
                  fontSize: 12,
 | 
					 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ).tr(),
 | 
					              ).tr(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -136,9 +136,9 @@ class SelectUserForSharingPage extends HookConsumerWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      appBar: AppBar(
 | 
					      appBar: AppBar(
 | 
				
			||||||
        title: const Text(
 | 
					        title: Text(
 | 
				
			||||||
          'share_invite',
 | 
					          'share_invite',
 | 
				
			||||||
          style: TextStyle(color: Colors.black),
 | 
					          style: TextStyle(color: Theme.of(context).primaryColor),
 | 
				
			||||||
        ).tr(),
 | 
					        ).tr(),
 | 
				
			||||||
        elevation: 0,
 | 
					        elevation: 0,
 | 
				
			||||||
        centerTitle: false,
 | 
					        centerTitle: false,
 | 
				
			||||||
@@ -150,11 +150,18 @@ class SelectUserForSharingPage extends HookConsumerWidget {
 | 
				
			|||||||
        ),
 | 
					        ),
 | 
				
			||||||
        actions: [
 | 
					        actions: [
 | 
				
			||||||
          TextButton(
 | 
					          TextButton(
 | 
				
			||||||
 | 
					            style: TextButton.styleFrom(
 | 
				
			||||||
 | 
					              primary: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
            onPressed:
 | 
					            onPressed:
 | 
				
			||||||
                sharedUsersList.value.isEmpty ? null : _createSharedAlbum,
 | 
					                sharedUsersList.value.isEmpty ? null : _createSharedAlbum,
 | 
				
			||||||
            child: const Text(
 | 
					            child: const Text(
 | 
				
			||||||
              "share_create_album",
 | 
					              "share_create_album",
 | 
				
			||||||
              style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
 | 
					              style: TextStyle(
 | 
				
			||||||
 | 
					                fontSize: 14,
 | 
				
			||||||
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                // color: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
            ).tr(),
 | 
					            ).tr(),
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,10 +61,8 @@ class SharingPage extends HookConsumerWidget {
 | 
				
			|||||||
                sharedAlbums[index].albumName,
 | 
					                sharedAlbums[index].albumName,
 | 
				
			||||||
                maxLines: 1,
 | 
					                maxLines: 1,
 | 
				
			||||||
                overflow: TextOverflow.ellipsis,
 | 
					                overflow: TextOverflow.ellipsis,
 | 
				
			||||||
                style: TextStyle(
 | 
					                style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
				
			||||||
                  fontSize: 16,
 | 
					 | 
				
			||||||
                      fontWeight: FontWeight.bold,
 | 
					                      fontWeight: FontWeight.bold,
 | 
				
			||||||
                  color: Colors.grey.shade800,
 | 
					 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              onTap: () {
 | 
					              onTap: () {
 | 
				
			||||||
@@ -87,7 +85,7 @@ class SharingPage extends HookConsumerWidget {
 | 
				
			|||||||
            shape: RoundedRectangleBorder(
 | 
					            shape: RoundedRectangleBorder(
 | 
				
			||||||
              borderRadius: BorderRadius.circular(10), // if you need this
 | 
					              borderRadius: BorderRadius.circular(10), // if you need this
 | 
				
			||||||
              side: const BorderSide(
 | 
					              side: const BorderSide(
 | 
				
			||||||
                color: Colors.black12,
 | 
					                color: Colors.grey,
 | 
				
			||||||
                width: 1,
 | 
					                width: 1,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
@@ -97,30 +95,26 @@ class SharingPage extends HookConsumerWidget {
 | 
				
			|||||||
              child: Column(
 | 
					              child: Column(
 | 
				
			||||||
                crossAxisAlignment: CrossAxisAlignment.start,
 | 
					                crossAxisAlignment: CrossAxisAlignment.start,
 | 
				
			||||||
                children: [
 | 
					                children: [
 | 
				
			||||||
                  Padding(
 | 
					                  const Padding(
 | 
				
			||||||
                    padding: const EdgeInsets.only(left: 5.0, bottom: 5),
 | 
					                    padding: EdgeInsets.only(left: 5.0, bottom: 5),
 | 
				
			||||||
                    child: Icon(
 | 
					                    child: Icon(
 | 
				
			||||||
                      Icons.offline_share_outlined,
 | 
					                      Icons.offline_share_outlined,
 | 
				
			||||||
                      size: 50,
 | 
					                      size: 50,
 | 
				
			||||||
                      color: Theme.of(context).primaryColor.withAlpha(200),
 | 
					                      // color: Theme.of(context).primaryColor,
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  Padding(
 | 
					                  Padding(
 | 
				
			||||||
                    padding: const EdgeInsets.all(8.0),
 | 
					                    padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
                    child: Text(
 | 
					                    child: Text(
 | 
				
			||||||
                      'sharing_page_empty_list',
 | 
					                      'sharing_page_empty_list',
 | 
				
			||||||
                      style: TextStyle(
 | 
					                      style: Theme.of(context).textTheme.headline3,
 | 
				
			||||||
                        fontSize: 12,
 | 
					 | 
				
			||||||
                        color: Theme.of(context).primaryColor,
 | 
					 | 
				
			||||||
                        fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ).tr(),
 | 
					                    ).tr(),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  Padding(
 | 
					                  Padding(
 | 
				
			||||||
                    padding: const EdgeInsets.all(8.0),
 | 
					                    padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
                    child: Text(
 | 
					                    child: Text(
 | 
				
			||||||
                      'sharing_page_description',
 | 
					                      'sharing_page_description',
 | 
				
			||||||
                      style: TextStyle(fontSize: 12, color: Colors.grey[700]),
 | 
					                      style: Theme.of(context).textTheme.bodyMedium,
 | 
				
			||||||
                    ).tr(),
 | 
					                    ).tr(),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,8 @@ import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart';
 | 
				
			|||||||
import 'package:immich_mobile/modules/asset_viewer/views/image_viewer_page.dart';
 | 
					import 'package:immich_mobile/modules/asset_viewer/views/image_viewer_page.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart';
 | 
					import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/home/services/asset.service.dart';
 | 
					import 'package:immich_mobile/modules/home/services/asset.service.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/services/app_settings.service.dart';
 | 
					import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 | 
				
			||||||
import 'package:openapi/api.dart';
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ignore: must_be_immutable
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ class AlbumInfoCard extends HookConsumerWidget {
 | 
				
			|||||||
        ref.watch(backupProvider).selectedBackupAlbums.contains(albumInfo);
 | 
					        ref.watch(backupProvider).selectedBackupAlbums.contains(albumInfo);
 | 
				
			||||||
    final bool isExcluded =
 | 
					    final bool isExcluded =
 | 
				
			||||||
        ref.watch(backupProvider).excludedBackupAlbums.contains(albumInfo);
 | 
					        ref.watch(backupProvider).excludedBackupAlbums.contains(albumInfo);
 | 
				
			||||||
 | 
					    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ColorFilter selectedFilter = ColorFilter.mode(
 | 
					    ColorFilter selectedFilter = ColorFilter.mode(
 | 
				
			||||||
      Theme.of(context).primaryColor.withAlpha(100),
 | 
					      Theme.of(context).primaryColor.withAlpha(100),
 | 
				
			||||||
@@ -39,11 +40,11 @@ class AlbumInfoCard extends HookConsumerWidget {
 | 
				
			|||||||
        return Chip(
 | 
					        return Chip(
 | 
				
			||||||
          visualDensity: VisualDensity.compact,
 | 
					          visualDensity: VisualDensity.compact,
 | 
				
			||||||
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
 | 
					          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
 | 
				
			||||||
          label: const Text(
 | 
					          label: Text(
 | 
				
			||||||
            "album_info_card_backup_album_included",
 | 
					            "album_info_card_backup_album_included",
 | 
				
			||||||
            style: TextStyle(
 | 
					            style: TextStyle(
 | 
				
			||||||
              fontSize: 10,
 | 
					              fontSize: 10,
 | 
				
			||||||
              color: Colors.white,
 | 
					              color: isDarkTheme ? Colors.black : Colors.white,
 | 
				
			||||||
              fontWeight: FontWeight.bold,
 | 
					              fontWeight: FontWeight.bold,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ).tr(),
 | 
					          ).tr(),
 | 
				
			||||||
@@ -53,11 +54,11 @@ class AlbumInfoCard extends HookConsumerWidget {
 | 
				
			|||||||
        return Chip(
 | 
					        return Chip(
 | 
				
			||||||
          visualDensity: VisualDensity.compact,
 | 
					          visualDensity: VisualDensity.compact,
 | 
				
			||||||
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
 | 
					          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
 | 
				
			||||||
          label: const Text(
 | 
					          label: Text(
 | 
				
			||||||
            "album_info_card_backup_album_excluded",
 | 
					            "album_info_card_backup_album_excluded",
 | 
				
			||||||
            style: TextStyle(
 | 
					            style: TextStyle(
 | 
				
			||||||
              fontSize: 10,
 | 
					              fontSize: 10,
 | 
				
			||||||
              color: Colors.white,
 | 
					              color: isDarkTheme ? Colors.black : Colors.white,
 | 
				
			||||||
              fontWeight: FontWeight.bold,
 | 
					              fontWeight: FontWeight.bold,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ).tr(),
 | 
					          ).tr(),
 | 
				
			||||||
@@ -141,8 +142,10 @@ class AlbumInfoCard extends HookConsumerWidget {
 | 
				
			|||||||
        margin: const EdgeInsets.all(1),
 | 
					        margin: const EdgeInsets.all(1),
 | 
				
			||||||
        shape: RoundedRectangleBorder(
 | 
					        shape: RoundedRectangleBorder(
 | 
				
			||||||
          borderRadius: BorderRadius.circular(12), // if you need this
 | 
					          borderRadius: BorderRadius.circular(12), // if you need this
 | 
				
			||||||
          side: const BorderSide(
 | 
					          side: BorderSide(
 | 
				
			||||||
            color: Color(0xFFC9C9C9),
 | 
					            color: isDarkTheme
 | 
				
			||||||
 | 
					                ? const Color.fromARGB(255, 37, 35, 35)
 | 
				
			||||||
 | 
					                : const Color(0xFFC9C9C9),
 | 
				
			||||||
            width: 1,
 | 
					            width: 1,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
@@ -219,8 +222,9 @@ class AlbumInfoCard extends HookConsumerWidget {
 | 
				
			|||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  IconButton(
 | 
					                  IconButton(
 | 
				
			||||||
                    onPressed: () {
 | 
					                    onPressed: () {
 | 
				
			||||||
                      AutoRouter.of(context)
 | 
					                      AutoRouter.of(context).push(
 | 
				
			||||||
                          .push(AlbumPreviewRoute(album: albumInfo));
 | 
					                        AlbumPreviewRoute(album: albumInfo),
 | 
				
			||||||
 | 
					                      );
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    icon: Icon(
 | 
					                    icon: Icon(
 | 
				
			||||||
                      Icons.image_outlined,
 | 
					                      Icons.image_outlined,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ class BackupInfoCard extends StatelessWidget {
 | 
				
			|||||||
          padding: const EdgeInsets.only(top: 8.0),
 | 
					          padding: const EdgeInsets.only(top: 8.0),
 | 
				
			||||||
          child: Text(
 | 
					          child: Text(
 | 
				
			||||||
            subtitle,
 | 
					            subtitle,
 | 
				
			||||||
            style: const TextStyle(color: Color(0xFF808080), fontSize: 12),
 | 
					            style: const TextStyle(fontSize: 12),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        trailing: Column(
 | 
					        trailing: Column(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
 | 
					import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			||||||
import 'package:fluttertoast/fluttertoast.dart';
 | 
					import 'package:fluttertoast/fluttertoast.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/constants/immich_colors.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
					import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/backup/ui/album_info_card.dart';
 | 
					import 'package:immich_mobile/modules/backup/ui/album_info_card.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
 | 
					import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
 | 
				
			||||||
@@ -16,6 +17,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
    final availableAlbums = ref.watch(backupProvider).availableAlbums;
 | 
					    final availableAlbums = ref.watch(backupProvider).availableAlbums;
 | 
				
			||||||
    final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums;
 | 
					    final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums;
 | 
				
			||||||
    final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums;
 | 
					    final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums;
 | 
				
			||||||
 | 
					    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(
 | 
					    useEffect(
 | 
				
			||||||
      () {
 | 
					      () {
 | 
				
			||||||
@@ -81,14 +83,16 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
              ),
 | 
					              ),
 | 
				
			||||||
              label: Text(
 | 
					              label: Text(
 | 
				
			||||||
                album.name,
 | 
					                album.name,
 | 
				
			||||||
                style: const TextStyle(
 | 
					                style: TextStyle(
 | 
				
			||||||
                  fontSize: 10,
 | 
					                  fontSize: 10,
 | 
				
			||||||
                  color: Colors.white,
 | 
					                  color: Theme.of(context).brightness == Brightness.dark
 | 
				
			||||||
 | 
					                      ? Colors.black
 | 
				
			||||||
 | 
					                      : Colors.white,
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              backgroundColor: Theme.of(context).primaryColor,
 | 
					              backgroundColor: Theme.of(context).primaryColor,
 | 
				
			||||||
              deleteIconColor: Colors.white,
 | 
					              deleteIconColor: isDarkTheme ? Colors.black : Colors.white,
 | 
				
			||||||
              deleteIcon: const Icon(
 | 
					              deleteIcon: const Icon(
 | 
				
			||||||
                Icons.cancel_rounded,
 | 
					                Icons.cancel_rounded,
 | 
				
			||||||
                size: 15,
 | 
					                size: 15,
 | 
				
			||||||
@@ -119,14 +123,15 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
              ),
 | 
					              ),
 | 
				
			||||||
              label: Text(
 | 
					              label: Text(
 | 
				
			||||||
                album.name,
 | 
					                album.name,
 | 
				
			||||||
                style: const TextStyle(
 | 
					                style: TextStyle(
 | 
				
			||||||
                  fontSize: 10,
 | 
					                  fontSize: 10,
 | 
				
			||||||
                  color: Colors.white,
 | 
					                  color: isDarkTheme ? Colors.black : immichBackgroundColor,
 | 
				
			||||||
                  fontWeight: FontWeight.bold,
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              backgroundColor: Colors.red[300],
 | 
					              backgroundColor: Colors.red[300],
 | 
				
			||||||
              deleteIconColor: Colors.white,
 | 
					              deleteIconColor:
 | 
				
			||||||
 | 
					                  isDarkTheme ? Colors.black : immichBackgroundColor,
 | 
				
			||||||
              deleteIcon: const Icon(
 | 
					              deleteIcon: const Icon(
 | 
				
			||||||
                Icons.cancel_rounded,
 | 
					                Icons.cancel_rounded,
 | 
				
			||||||
                size: 15,
 | 
					                size: 15,
 | 
				
			||||||
@@ -154,11 +159,16 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
        physics: const ClampingScrollPhysics(),
 | 
					        physics: const ClampingScrollPhysics(),
 | 
				
			||||||
        children: [
 | 
					        children: [
 | 
				
			||||||
          Padding(
 | 
					          Padding(
 | 
				
			||||||
            padding:
 | 
					            padding: const EdgeInsets.symmetric(
 | 
				
			||||||
                const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
 | 
					              vertical: 8.0,
 | 
				
			||||||
 | 
					              horizontal: 16.0,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
            child: const Text(
 | 
					            child: const Text(
 | 
				
			||||||
              "backup_album_selection_page_selection_info",
 | 
					              "backup_album_selection_page_selection_info",
 | 
				
			||||||
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
 | 
					              style: TextStyle(
 | 
				
			||||||
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                fontSize: 14,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
            ).tr(),
 | 
					            ).tr(),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          // Selected Album Chips
 | 
					          // Selected Album Chips
 | 
				
			||||||
@@ -178,9 +188,11 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
            child: Card(
 | 
					            child: Card(
 | 
				
			||||||
              margin: const EdgeInsets.all(0),
 | 
					              margin: const EdgeInsets.all(0),
 | 
				
			||||||
              shape: RoundedRectangleBorder(
 | 
					              shape: RoundedRectangleBorder(
 | 
				
			||||||
                borderRadius: BorderRadius.circular(5), // if you need this
 | 
					                borderRadius: BorderRadius.circular(5),
 | 
				
			||||||
                side: const BorderSide(
 | 
					                side: BorderSide(
 | 
				
			||||||
                  color: Color.fromARGB(255, 235, 235, 235),
 | 
					                  color: isDarkTheme
 | 
				
			||||||
 | 
					                      ? const Color.fromARGB(255, 0, 0, 0)
 | 
				
			||||||
 | 
					                      : const Color.fromARGB(255, 235, 235, 235),
 | 
				
			||||||
                  width: 1,
 | 
					                  width: 1,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
@@ -190,12 +202,11 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
                children: [
 | 
					                children: [
 | 
				
			||||||
                  ListTile(
 | 
					                  ListTile(
 | 
				
			||||||
                    visualDensity: VisualDensity.compact,
 | 
					                    visualDensity: VisualDensity.compact,
 | 
				
			||||||
                    title: Text(
 | 
					                    title: const Text(
 | 
				
			||||||
                      "backup_album_selection_page_total_assets",
 | 
					                      "backup_album_selection_page_total_assets",
 | 
				
			||||||
                      style: TextStyle(
 | 
					                      style: TextStyle(
 | 
				
			||||||
                        fontWeight: FontWeight.bold,
 | 
					                        fontWeight: FontWeight.bold,
 | 
				
			||||||
                        fontSize: 14,
 | 
					                        fontSize: 14,
 | 
				
			||||||
                        color: Colors.grey[700],
 | 
					 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
                    ).tr(),
 | 
					                    ).tr(),
 | 
				
			||||||
                    trailing: Text(
 | 
					                    trailing: Text(
 | 
				
			||||||
@@ -257,11 +268,10 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
 | 
				
			|||||||
                      content: SingleChildScrollView(
 | 
					                      content: SingleChildScrollView(
 | 
				
			||||||
                        child: ListBody(
 | 
					                        child: ListBody(
 | 
				
			||||||
                          children: [
 | 
					                          children: [
 | 
				
			||||||
                            Text(
 | 
					                            const Text(
 | 
				
			||||||
                              'backup_album_selection_page_assets_scatter',
 | 
					                              'backup_album_selection_page_assets_scatter',
 | 
				
			||||||
                              style: TextStyle(
 | 
					                              style: TextStyle(
 | 
				
			||||||
                                fontSize: 14,
 | 
					                                fontSize: 14,
 | 
				
			||||||
                                color: Colors.grey[700],
 | 
					 | 
				
			||||||
                              ),
 | 
					                              ),
 | 
				
			||||||
                            ).tr(),
 | 
					                            ).tr(),
 | 
				
			||||||
                          ],
 | 
					                          ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,7 +82,7 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ListTile _buildBackupController() {
 | 
					    ListTile _buildAutoBackupController() {
 | 
				
			||||||
      var backUpOption = authenticationState.deviceInfo.isAutoBackup
 | 
					      var backUpOption = authenticationState.deviceInfo.isAutoBackup
 | 
				
			||||||
          ? "backup_controller_page_status_on".tr()
 | 
					          ? "backup_controller_page_status_on".tr()
 | 
				
			||||||
          : "backup_controller_page_status_off".tr();
 | 
					          : "backup_controller_page_status_off".tr();
 | 
				
			||||||
@@ -114,13 +114,7 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                ).tr(),
 | 
					                ).tr(),
 | 
				
			||||||
              Padding(
 | 
					              Padding(
 | 
				
			||||||
                padding: const EdgeInsets.only(top: 8.0),
 | 
					                padding: const EdgeInsets.only(top: 8.0),
 | 
				
			||||||
                child: OutlinedButton(
 | 
					                child: ElevatedButton(
 | 
				
			||||||
                  style: OutlinedButton.styleFrom(
 | 
					 | 
				
			||||||
                    side: const BorderSide(
 | 
					 | 
				
			||||||
                      width: 1,
 | 
					 | 
				
			||||||
                      color: Color.fromARGB(255, 220, 220, 220),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  onPressed: () {
 | 
					                  onPressed: () {
 | 
				
			||||||
                    if (isAutoBackup) {
 | 
					                    if (isAutoBackup) {
 | 
				
			||||||
                      ref
 | 
					                      ref
 | 
				
			||||||
@@ -134,7 +128,10 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  child: Text(
 | 
					                  child: Text(
 | 
				
			||||||
                    backupBtnText,
 | 
					                    backupBtnText,
 | 
				
			||||||
                    style: const TextStyle(fontWeight: FontWeight.bold),
 | 
					                    style: const TextStyle(
 | 
				
			||||||
 | 
					                      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                      fontSize: 12,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              )
 | 
					              )
 | 
				
			||||||
@@ -232,33 +229,24 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
              children: [
 | 
					              children: [
 | 
				
			||||||
                const Text(
 | 
					                const Text(
 | 
				
			||||||
                  "backup_controller_page_to_backup",
 | 
					                  "backup_controller_page_to_backup",
 | 
				
			||||||
                  style: TextStyle(color: Color(0xFF808080), fontSize: 12),
 | 
					                  style: TextStyle(fontSize: 12),
 | 
				
			||||||
                ).tr(),
 | 
					                ).tr(),
 | 
				
			||||||
                _buildSelectedAlbumName(),
 | 
					                _buildSelectedAlbumName(),
 | 
				
			||||||
                _buildExcludedAlbumName()
 | 
					                _buildExcludedAlbumName()
 | 
				
			||||||
              ],
 | 
					              ],
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          trailing: OutlinedButton(
 | 
					          trailing: ElevatedButton(
 | 
				
			||||||
            style: OutlinedButton.styleFrom(
 | 
					 | 
				
			||||||
              enableFeedback: true,
 | 
					 | 
				
			||||||
              side: const BorderSide(
 | 
					 | 
				
			||||||
                width: 1,
 | 
					 | 
				
			||||||
                color: Color.fromARGB(255, 220, 220, 220),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            onPressed: () {
 | 
					            onPressed: () {
 | 
				
			||||||
              AutoRouter.of(context).push(const BackupAlbumSelectionRoute());
 | 
					              AutoRouter.of(context).push(const BackupAlbumSelectionRoute());
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            child: Padding(
 | 
					 | 
				
			||||||
              padding: const EdgeInsets.symmetric(
 | 
					 | 
				
			||||||
                vertical: 16.0,
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            child: const Text(
 | 
					            child: const Text(
 | 
				
			||||||
              "backup_controller_page_select",
 | 
					              "backup_controller_page_select",
 | 
				
			||||||
                style: TextStyle(fontWeight: FontWeight.bold),
 | 
					              style: TextStyle(
 | 
				
			||||||
              ).tr(),
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                fontSize: 12,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
 | 
					            ).tr(),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@@ -324,13 +312,13 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
              padding: const EdgeInsets.only(top: 8.0),
 | 
					              padding: const EdgeInsets.only(top: 8.0),
 | 
				
			||||||
              child: Table(
 | 
					              child: Table(
 | 
				
			||||||
                border: TableBorder.all(
 | 
					                border: TableBorder.all(
 | 
				
			||||||
                  color: Colors.black12,
 | 
					                  color: Theme.of(context).primaryColorLight,
 | 
				
			||||||
                  width: 1,
 | 
					                  width: 1,
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                children: [
 | 
					                children: [
 | 
				
			||||||
                  TableRow(
 | 
					                  TableRow(
 | 
				
			||||||
                    decoration: BoxDecoration(
 | 
					                    decoration: const BoxDecoration(
 | 
				
			||||||
                      color: Colors.grey[100],
 | 
					                        // color: Colors.grey[100],
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    children: [
 | 
					                    children: [
 | 
				
			||||||
                      TableCell(
 | 
					                      TableCell(
 | 
				
			||||||
@@ -355,8 +343,8 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  TableRow(
 | 
					                  TableRow(
 | 
				
			||||||
                    decoration: BoxDecoration(
 | 
					                    decoration: const BoxDecoration(
 | 
				
			||||||
                      color: Colors.grey[200],
 | 
					                        // color: Colors.grey[200],
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    children: [
 | 
					                    children: [
 | 
				
			||||||
                      TableCell(
 | 
					                      TableCell(
 | 
				
			||||||
@@ -384,8 +372,8 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  TableRow(
 | 
					                  TableRow(
 | 
				
			||||||
                    decoration: BoxDecoration(
 | 
					                    decoration: const BoxDecoration(
 | 
				
			||||||
                      color: Colors.grey[100],
 | 
					                        // color: Colors.grey[100],
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    children: [
 | 
					                    children: [
 | 
				
			||||||
                      TableCell(
 | 
					                      TableCell(
 | 
				
			||||||
@@ -463,7 +451,7 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                  "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}",
 | 
					                  "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}",
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            const Divider(),
 | 
					            const Divider(),
 | 
				
			||||||
            _buildBackupController(),
 | 
					            _buildAutoBackupController(),
 | 
				
			||||||
            const Divider(),
 | 
					            const Divider(),
 | 
				
			||||||
            _buildStorageInformation(),
 | 
					            _buildStorageInformation(),
 | 
				
			||||||
            const Divider(),
 | 
					            const Divider(),
 | 
				
			||||||
@@ -479,7 +467,7 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                            style: ElevatedButton.styleFrom(
 | 
					                            style: ElevatedButton.styleFrom(
 | 
				
			||||||
                              primary: Colors.red[300],
 | 
					                              primary: Colors.red[300],
 | 
				
			||||||
                              onPrimary: Colors.grey[50],
 | 
					                              onPrimary: Colors.grey[50],
 | 
				
			||||||
                              padding: const EdgeInsets.all(14),
 | 
					                              // padding: const EdgeInsets.all(14),
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            onPressed: () {
 | 
					                            onPressed: () {
 | 
				
			||||||
                              ref.read(backupProvider.notifier).cancelBackup();
 | 
					                              ref.read(backupProvider.notifier).cancelBackup();
 | 
				
			||||||
@@ -493,11 +481,6 @@ class BackupControllerPage extends HookConsumerWidget {
 | 
				
			|||||||
                            ).tr(),
 | 
					                            ).tr(),
 | 
				
			||||||
                          )
 | 
					                          )
 | 
				
			||||||
                        : ElevatedButton(
 | 
					                        : ElevatedButton(
 | 
				
			||||||
                            style: ElevatedButton.styleFrom(
 | 
					 | 
				
			||||||
                              primary: Theme.of(context).primaryColor,
 | 
					 | 
				
			||||||
                              onPrimary: Colors.grey[50],
 | 
					 | 
				
			||||||
                              padding: const EdgeInsets.all(14),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                            onPressed: shouldBackup ? startBackup : null,
 | 
					                            onPressed: shouldBackup ? startBackup : null,
 | 
				
			||||||
                            child: const Text(
 | 
					                            child: const Text(
 | 
				
			||||||
                              "backup_controller_page_start_backup",
 | 
					                              "backup_controller_page_start_backup",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,9 @@
 | 
				
			|||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
 | 
					import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import '../../../shared/providers/asset.provider.dart';
 | 
					 | 
				
			||||||
import '../providers/home_page_state.provider.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ControlBottomAppBar extends ConsumerWidget {
 | 
					class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			||||||
  const ControlBottomAppBar({Key? key}) : super(key: key);
 | 
					  const ControlBottomAppBar({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,10 +17,10 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
        height: MediaQuery.of(context).size.height * 0.15,
 | 
					        height: MediaQuery.of(context).size.height * 0.15,
 | 
				
			||||||
        decoration: BoxDecoration(
 | 
					        decoration: BoxDecoration(
 | 
				
			||||||
          borderRadius: const BorderRadius.only(
 | 
					          borderRadius: const BorderRadius.only(
 | 
				
			||||||
            topLeft: Radius.circular(15),
 | 
					            topLeft: Radius.circular(8),
 | 
				
			||||||
            topRight: Radius.circular(15),
 | 
					            topRight: Radius.circular(8),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          color: Colors.grey[300]?.withOpacity(0.98),
 | 
					          color: Theme.of(context).scaffoldBackgroundColor.withOpacity(0.95),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        child: Column(
 | 
					        child: Column(
 | 
				
			||||||
          children: [
 | 
					          children: [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,6 @@ class DailyTitleText extends ConsumerWidget {
 | 
				
			|||||||
              style: const TextStyle(
 | 
					              style: const TextStyle(
 | 
				
			||||||
                fontSize: 14,
 | 
					                fontSize: 14,
 | 
				
			||||||
                fontWeight: FontWeight.bold,
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
                color: Colors.black87,
 | 
					 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            const Spacer(),
 | 
					            const Spacer(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,21 +14,13 @@ class DisableMultiSelectButton extends ConsumerWidget {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
    return Positioned(
 | 
					    return Positioned(
 | 
				
			||||||
      top: 0,
 | 
					      top: 10,
 | 
				
			||||||
      left: 0,
 | 
					      left: 0,
 | 
				
			||||||
      child: Padding(
 | 
					      child: Padding(
 | 
				
			||||||
        padding: const EdgeInsets.only(left: 16.0, top: 46),
 | 
					        padding: const EdgeInsets.only(left: 16.0, top: 46),
 | 
				
			||||||
        child: Material(
 | 
					 | 
				
			||||||
          elevation: 20,
 | 
					 | 
				
			||||||
          borderRadius: BorderRadius.circular(35),
 | 
					 | 
				
			||||||
          child: Container(
 | 
					 | 
				
			||||||
            decoration: BoxDecoration(
 | 
					 | 
				
			||||||
              borderRadius: BorderRadius.circular(35),
 | 
					 | 
				
			||||||
              color: Colors.grey[100],
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        child: Padding(
 | 
					        child: Padding(
 | 
				
			||||||
          padding: const EdgeInsets.symmetric(horizontal: 4.0),
 | 
					          padding: const EdgeInsets.symmetric(horizontal: 4.0),
 | 
				
			||||||
              child: TextButton.icon(
 | 
					          child: ElevatedButton.icon(
 | 
				
			||||||
            onPressed: () {
 | 
					            onPressed: () {
 | 
				
			||||||
              onPressed();
 | 
					              onPressed();
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
@@ -43,8 +35,6 @@ class DisableMultiSelectButton extends ConsumerWidget {
 | 
				
			|||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,6 +30,7 @@ class ImmichSliverAppBar extends ConsumerWidget {
 | 
				
			|||||||
      floating: true,
 | 
					      floating: true,
 | 
				
			||||||
      pinned: false,
 | 
					      pinned: false,
 | 
				
			||||||
      snap: false,
 | 
					      snap: false,
 | 
				
			||||||
 | 
					      backgroundColor: Theme.of(context).appBarTheme.backgroundColor,
 | 
				
			||||||
      shape: const RoundedRectangleBorder(
 | 
					      shape: const RoundedRectangleBorder(
 | 
				
			||||||
        borderRadius: BorderRadius.all(Radius.circular(5)),
 | 
					        borderRadius: BorderRadius.all(Radius.circular(5)),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
@@ -57,7 +58,7 @@ class ImmichSliverAppBar extends ConsumerWidget {
 | 
				
			|||||||
                  child: GestureDetector(
 | 
					                  child: GestureDetector(
 | 
				
			||||||
                    onTap: () => Scaffold.of(context).openDrawer(),
 | 
					                    onTap: () => Scaffold.of(context).openDrawer(),
 | 
				
			||||||
                    child: Material(
 | 
					                    child: Material(
 | 
				
			||||||
                      color: Colors.grey[200],
 | 
					                      // color: Colors.grey[200],
 | 
				
			||||||
                      elevation: 1,
 | 
					                      elevation: 1,
 | 
				
			||||||
                      shape: RoundedRectangleBorder(
 | 
					                      shape: RoundedRectangleBorder(
 | 
				
			||||||
                        borderRadius: BorderRadius.circular(50.0),
 | 
					                        borderRadius: BorderRadius.circular(50.0),
 | 
				
			||||||
@@ -77,13 +78,12 @@ class ImmichSliverAppBar extends ConsumerWidget {
 | 
				
			|||||||
          );
 | 
					          );
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      title: Text(
 | 
					      title: const Text(
 | 
				
			||||||
        'IMMICH',
 | 
					        'IMMICH',
 | 
				
			||||||
        style: TextStyle(
 | 
					        style: TextStyle(
 | 
				
			||||||
          fontFamily: 'SnowburstOne',
 | 
					          fontFamily: 'SnowburstOne',
 | 
				
			||||||
          fontWeight: FontWeight.bold,
 | 
					          fontWeight: FontWeight.bold,
 | 
				
			||||||
          fontSize: 22,
 | 
					          fontSize: 22,
 | 
				
			||||||
          color: Theme.of(context).primaryColor,
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      actions: [
 | 
					      actions: [
 | 
				
			||||||
@@ -112,12 +112,13 @@ class ImmichSliverAppBar extends ConsumerWidget {
 | 
				
			|||||||
                  ? const Icon(Icons.backup_rounded)
 | 
					                  ? const Icon(Icons.backup_rounded)
 | 
				
			||||||
                  : Badge(
 | 
					                  : Badge(
 | 
				
			||||||
                      padding: const EdgeInsets.all(4),
 | 
					                      padding: const EdgeInsets.all(4),
 | 
				
			||||||
                      elevation: 2,
 | 
					                      elevation: 3,
 | 
				
			||||||
                      position: BadgePosition.bottomEnd(bottom: -4, end: -4),
 | 
					                      position: BadgePosition.bottomEnd(bottom: -4, end: -4),
 | 
				
			||||||
                      badgeColor: Colors.white,
 | 
					                      badgeColor: Colors.white,
 | 
				
			||||||
                      badgeContent: const Icon(
 | 
					                      badgeContent: const Icon(
 | 
				
			||||||
                        Icons.cloud_off_rounded,
 | 
					                        Icons.cloud_off_rounded,
 | 
				
			||||||
                        size: 8,
 | 
					                        size: 8,
 | 
				
			||||||
 | 
					                        color: Colors.indigo,
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
                      child: const Icon(Icons.backup_rounded),
 | 
					                      child: const Icon(Icons.backup_rounded),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ class MonthlyTitleText extends StatelessWidget {
 | 
				
			|||||||
          style: TextStyle(
 | 
					          style: TextStyle(
 | 
				
			||||||
            fontSize: 26,
 | 
					            fontSize: 26,
 | 
				
			||||||
            fontWeight: FontWeight.bold,
 | 
					            fontWeight: FontWeight.bold,
 | 
				
			||||||
            color: Theme.of(context).primaryColor,
 | 
					            color: Theme.of(context).textTheme.headline1?.color,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,17 +22,16 @@ class ProfileDrawer extends HookConsumerWidget {
 | 
				
			|||||||
          height: double.infinity,
 | 
					          height: double.infinity,
 | 
				
			||||||
          child: Icon(
 | 
					          child: Icon(
 | 
				
			||||||
            Icons.logout_rounded,
 | 
					            Icons.logout_rounded,
 | 
				
			||||||
            color: Colors.grey[700],
 | 
					            color: Theme.of(context).textTheme.labelMedium?.color,
 | 
				
			||||||
            size: 20,
 | 
					            size: 20,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        title: Text(
 | 
					        title: Text(
 | 
				
			||||||
          "profile_drawer_sign_out",
 | 
					          "profile_drawer_sign_out",
 | 
				
			||||||
          style: TextStyle(
 | 
					          style: Theme.of(context)
 | 
				
			||||||
            color: Colors.grey[700],
 | 
					              .textTheme
 | 
				
			||||||
            fontSize: 12,
 | 
					              .labelLarge
 | 
				
			||||||
            fontWeight: FontWeight.bold,
 | 
					              ?.copyWith(fontWeight: FontWeight.bold),
 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ).tr(),
 | 
					        ).tr(),
 | 
				
			||||||
        onTap: () async {
 | 
					        onTap: () async {
 | 
				
			||||||
          bool res = await ref.watch(authenticationProvider.notifier).logout();
 | 
					          bool res = await ref.watch(authenticationProvider.notifier).logout();
 | 
				
			||||||
@@ -54,17 +53,16 @@ class ProfileDrawer extends HookConsumerWidget {
 | 
				
			|||||||
          height: double.infinity,
 | 
					          height: double.infinity,
 | 
				
			||||||
          child: Icon(
 | 
					          child: Icon(
 | 
				
			||||||
            Icons.settings_rounded,
 | 
					            Icons.settings_rounded,
 | 
				
			||||||
            color: Colors.grey[700],
 | 
					            color: Theme.of(context).textTheme.labelMedium?.color,
 | 
				
			||||||
            size: 20,
 | 
					            size: 20,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        title: Text(
 | 
					        title: Text(
 | 
				
			||||||
          "profile_drawer_settings",
 | 
					          "profile_drawer_settings",
 | 
				
			||||||
          style: TextStyle(
 | 
					          style: Theme.of(context)
 | 
				
			||||||
            color: Colors.grey[700],
 | 
					              .textTheme
 | 
				
			||||||
            fontSize: 12,
 | 
					              .labelLarge
 | 
				
			||||||
            fontWeight: FontWeight.bold,
 | 
					              ?.copyWith(fontWeight: FontWeight.bold),
 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
        ).tr(),
 | 
					        ).tr(),
 | 
				
			||||||
        onTap: () {
 | 
					        onTap: () {
 | 
				
			||||||
          AutoRouter.of(context).push(const SettingsRoute());
 | 
					          AutoRouter.of(context).push(const SettingsRoute());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
 | 
				
			|||||||
    final uploadProfileImageStatus =
 | 
					    final uploadProfileImageStatus =
 | 
				
			||||||
        ref.watch(uploadProfileImageProvider).status;
 | 
					        ref.watch(uploadProfileImageProvider).status;
 | 
				
			||||||
    var dummmy = Random().nextInt(1024);
 | 
					    var dummmy = Random().nextInt(1024);
 | 
				
			||||||
 | 
					    final isDarkMode = Theme.of(context).brightness == Brightness.dark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _buildUserProfileImage() {
 | 
					    _buildUserProfileImage() {
 | 
				
			||||||
      if (authState.profileImagePath.isEmpty) {
 | 
					      if (authState.profileImagePath.isEmpty) {
 | 
				
			||||||
@@ -104,11 +105,17 @@ class ProfileDrawerHeader extends HookConsumerWidget {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return DrawerHeader(
 | 
					    return DrawerHeader(
 | 
				
			||||||
      decoration: const BoxDecoration(
 | 
					      decoration: BoxDecoration(
 | 
				
			||||||
        gradient: LinearGradient(
 | 
					        gradient: LinearGradient(
 | 
				
			||||||
          colors: [
 | 
					          colors: isDarkMode
 | 
				
			||||||
            Color.fromARGB(255, 216, 219, 238),
 | 
					              ? [
 | 
				
			||||||
            Color.fromARGB(255, 242, 242, 242),
 | 
					                  const Color.fromARGB(255, 22, 25, 48),
 | 
				
			||||||
 | 
					                  const Color.fromARGB(255, 13, 13, 13),
 | 
				
			||||||
 | 
					                  const Color.fromARGB(255, 0, 0, 0),
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					              : [
 | 
				
			||||||
 | 
					                  const Color.fromARGB(255, 216, 219, 238),
 | 
				
			||||||
 | 
					                  const Color.fromARGB(255, 242, 242, 242),
 | 
				
			||||||
                  Colors.white,
 | 
					                  Colors.white,
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
          begin: Alignment.centerRight,
 | 
					          begin: Alignment.centerRight,
 | 
				
			||||||
@@ -129,8 +136,8 @@ class ProfileDrawerHeader extends HookConsumerWidget {
 | 
				
			|||||||
                child: GestureDetector(
 | 
					                child: GestureDetector(
 | 
				
			||||||
                  onTap: _pickUserProfileImage,
 | 
					                  onTap: _pickUserProfileImage,
 | 
				
			||||||
                  child: Material(
 | 
					                  child: Material(
 | 
				
			||||||
                    color: Colors.grey[50],
 | 
					                    color: Colors.grey[100],
 | 
				
			||||||
                    elevation: 2,
 | 
					                    elevation: 3,
 | 
				
			||||||
                    shape: RoundedRectangleBorder(
 | 
					                    shape: RoundedRectangleBorder(
 | 
				
			||||||
                      borderRadius: BorderRadius.circular(50.0),
 | 
					                      borderRadius: BorderRadius.circular(50.0),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
@@ -157,7 +164,7 @@ class ProfileDrawerHeader extends HookConsumerWidget {
 | 
				
			|||||||
          ),
 | 
					          ),
 | 
				
			||||||
          Text(
 | 
					          Text(
 | 
				
			||||||
            authState.userEmail,
 | 
					            authState.userEmail,
 | 
				
			||||||
            style: TextStyle(color: Colors.grey[800], fontSize: 12),
 | 
					            style: Theme.of(context).textTheme.labelMedium,
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@ class ServerInfoBox extends HookConsumerWidget {
 | 
				
			|||||||
      padding: const EdgeInsets.all(8.0),
 | 
					      padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
      child: Card(
 | 
					      child: Card(
 | 
				
			||||||
        elevation: 0,
 | 
					        elevation: 0,
 | 
				
			||||||
        color: Colors.grey[100],
 | 
					        color: Theme.of(context).scaffoldBackgroundColor,
 | 
				
			||||||
        shape: RoundedRectangleBorder(
 | 
					        shape: RoundedRectangleBorder(
 | 
				
			||||||
          borderRadius: BorderRadius.circular(5), // if you need this
 | 
					          borderRadius: BorderRadius.circular(5), // if you need this
 | 
				
			||||||
          side: const BorderSide(
 | 
					          side: const BorderSide(
 | 
				
			||||||
@@ -65,7 +65,10 @@ class ServerInfoBox extends HookConsumerWidget {
 | 
				
			|||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              const Divider(),
 | 
					              const Divider(
 | 
				
			||||||
 | 
					                color: Color.fromARGB(101, 201, 201, 201),
 | 
				
			||||||
 | 
					                thickness: 1,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
              Row(
 | 
					              Row(
 | 
				
			||||||
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
					                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
				
			||||||
                children: [
 | 
					                children: [
 | 
				
			||||||
@@ -87,7 +90,10 @@ class ServerInfoBox extends HookConsumerWidget {
 | 
				
			|||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              const Divider(),
 | 
					              const Divider(
 | 
				
			||||||
 | 
					                color: Color.fromARGB(101, 201, 201, 201),
 | 
				
			||||||
 | 
					                thickness: 1,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
              Row(
 | 
					              Row(
 | 
				
			||||||
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
					                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
				
			||||||
                children: [
 | 
					                children: [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,9 +117,9 @@ class HomePage extends HookConsumerWidget {
 | 
				
			|||||||
              ],
 | 
					              ],
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            Padding(
 | 
					            Padding(
 | 
				
			||||||
              padding: const EdgeInsets.only(top: 50.0),
 | 
					              padding: const EdgeInsets.only(top: 60.0, bottom: 30.0),
 | 
				
			||||||
              child: DraggableScrollbar.semicircle(
 | 
					              child: DraggableScrollbar.semicircle(
 | 
				
			||||||
                backgroundColor: Theme.of(context).primaryColor,
 | 
					                backgroundColor: Theme.of(context).hintColor,
 | 
				
			||||||
                controller: scrollController,
 | 
					                controller: scrollController,
 | 
				
			||||||
                heightScrollThumb: 48.0,
 | 
					                heightScrollThumb: 48.0,
 | 
				
			||||||
                child: CustomScrollView(
 | 
					                child: CustomScrollView(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ class ThumbnailWithInfo extends StatelessWidget {
 | 
				
			|||||||
      child: Padding(
 | 
					      child: Padding(
 | 
				
			||||||
        padding: const EdgeInsets.only(right: 8.0),
 | 
					        padding: const EdgeInsets.only(right: 8.0),
 | 
				
			||||||
        child: SizedBox(
 | 
					        child: SizedBox(
 | 
				
			||||||
          width: MediaQuery.of(context).size.width / 2,
 | 
					          width: MediaQuery.of(context).size.width / 3,
 | 
				
			||||||
          child: Stack(
 | 
					          child: Stack(
 | 
				
			||||||
            alignment: Alignment.bottomCenter,
 | 
					            alignment: Alignment.bottomCenter,
 | 
				
			||||||
            children: [
 | 
					            children: [
 | 
				
			||||||
@@ -58,7 +58,7 @@ class ThumbnailWithInfo extends StatelessWidget {
 | 
				
			|||||||
                    style: const TextStyle(
 | 
					                    style: const TextStyle(
 | 
				
			||||||
                      color: Colors.white,
 | 
					                      color: Colors.white,
 | 
				
			||||||
                      fontWeight: FontWeight.bold,
 | 
					                      fontWeight: FontWeight.bold,
 | 
				
			||||||
                      fontSize: 16,
 | 
					                      fontSize: 14,
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,8 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
    AsyncValue<List<CuratedObjectsResponseDto>> curatedObjects =
 | 
					    AsyncValue<List<CuratedObjectsResponseDto>> curatedObjects =
 | 
				
			||||||
        ref.watch(getCuratedObjectProvider);
 | 
					        ref.watch(getCuratedObjectProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double imageSize = MediaQuery.of(context).size.width / 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(
 | 
					    useEffect(
 | 
				
			||||||
      () {
 | 
					      () {
 | 
				
			||||||
        searchFocusNode = FocusNode();
 | 
					        searchFocusNode = FocusNode();
 | 
				
			||||||
@@ -46,15 +48,15 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    _buildPlaces() {
 | 
					    _buildPlaces() {
 | 
				
			||||||
      return curatedLocation.when(
 | 
					      return curatedLocation.when(
 | 
				
			||||||
        loading: () => const SizedBox(
 | 
					        loading: () => SizedBox(
 | 
				
			||||||
          height: 200,
 | 
					          height: imageSize,
 | 
				
			||||||
          child: Center(child: ImmichLoadingIndicator()),
 | 
					          child: const Center(child: ImmichLoadingIndicator()),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        error: (err, stack) => Text('Error: $err'),
 | 
					        error: (err, stack) => Text('Error: $err'),
 | 
				
			||||||
        data: (curatedLocations) {
 | 
					        data: (curatedLocations) {
 | 
				
			||||||
          return curatedLocations.isNotEmpty
 | 
					          return curatedLocations.isNotEmpty
 | 
				
			||||||
              ? SizedBox(
 | 
					              ? SizedBox(
 | 
				
			||||||
                  height: MediaQuery.of(context).size.width / 2,
 | 
					                  height: imageSize,
 | 
				
			||||||
                  child: ListView.builder(
 | 
					                  child: ListView.builder(
 | 
				
			||||||
                    padding: const EdgeInsets.only(left: 16),
 | 
					                    padding: const EdgeInsets.only(left: 16),
 | 
				
			||||||
                    scrollDirection: Axis.horizontal,
 | 
					                    scrollDirection: Axis.horizontal,
 | 
				
			||||||
@@ -76,7 +78,7 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
              : SizedBox(
 | 
					              : SizedBox(
 | 
				
			||||||
                  height: MediaQuery.of(context).size.width / 2,
 | 
					                  height: imageSize,
 | 
				
			||||||
                  child: ListView.builder(
 | 
					                  child: ListView.builder(
 | 
				
			||||||
                    padding: const EdgeInsets.only(left: 16),
 | 
					                    padding: const EdgeInsets.only(left: 16),
 | 
				
			||||||
                    scrollDirection: Axis.horizontal,
 | 
					                    scrollDirection: Axis.horizontal,
 | 
				
			||||||
@@ -105,7 +107,7 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
        data: (objects) {
 | 
					        data: (objects) {
 | 
				
			||||||
          return objects.isNotEmpty
 | 
					          return objects.isNotEmpty
 | 
				
			||||||
              ? SizedBox(
 | 
					              ? SizedBox(
 | 
				
			||||||
                  height: MediaQuery.of(context).size.width / 2,
 | 
					                  height: imageSize,
 | 
				
			||||||
                  child: ListView.builder(
 | 
					                  child: ListView.builder(
 | 
				
			||||||
                    padding: const EdgeInsets.only(left: 16),
 | 
					                    padding: const EdgeInsets.only(left: 16),
 | 
				
			||||||
                    scrollDirection: Axis.horizontal,
 | 
					                    scrollDirection: Axis.horizontal,
 | 
				
			||||||
@@ -113,7 +115,7 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
                    itemBuilder: ((context, index) {
 | 
					                    itemBuilder: ((context, index) {
 | 
				
			||||||
                      var curatedObjectInfo = objects[index];
 | 
					                      var curatedObjectInfo = objects[index];
 | 
				
			||||||
                      var thumbnailRequestUrl =
 | 
					                      var thumbnailRequestUrl =
 | 
				
			||||||
                          '${box.get(serverEndpointKey)}/asset/file?aid=${curatedObjectInfo.deviceAssetId}&did=${curatedObjectInfo.deviceId}&isThumb=true';
 | 
					                          '${box.get(serverEndpointKey)}/asset/thumbnail/${curatedObjectInfo.id}';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                      return ThumbnailWithInfo(
 | 
					                      return ThumbnailWithInfo(
 | 
				
			||||||
                        imageUrl: thumbnailRequestUrl,
 | 
					                        imageUrl: thumbnailRequestUrl,
 | 
				
			||||||
@@ -131,7 +133,8 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
              : SizedBox(
 | 
					              : SizedBox(
 | 
				
			||||||
                  height: MediaQuery.of(context).size.width / 2,
 | 
					                  // height: imageSize,
 | 
				
			||||||
 | 
					                  width: imageSize,
 | 
				
			||||||
                  child: ListView.builder(
 | 
					                  child: ListView.builder(
 | 
				
			||||||
                    padding: const EdgeInsets.only(left: 16),
 | 
					                    padding: const EdgeInsets.only(left: 16),
 | 
				
			||||||
                    scrollDirection: Axis.horizontal,
 | 
					                    scrollDirection: Axis.horizontal,
 | 
				
			||||||
@@ -163,12 +166,13 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
        child: Stack(
 | 
					        child: Stack(
 | 
				
			||||||
          children: [
 | 
					          children: [
 | 
				
			||||||
            ListView(
 | 
					            ListView(
 | 
				
			||||||
 | 
					              shrinkWrap: true,
 | 
				
			||||||
              children: [
 | 
					              children: [
 | 
				
			||||||
                Padding(
 | 
					                Padding(
 | 
				
			||||||
                  padding: const EdgeInsets.all(16.0),
 | 
					                  padding: const EdgeInsets.all(16.0),
 | 
				
			||||||
                  child: const Text(
 | 
					                  child: const Text(
 | 
				
			||||||
                    "search_page_places",
 | 
					                    "search_page_places",
 | 
				
			||||||
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
 | 
					                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
 | 
				
			||||||
                  ).tr(),
 | 
					                  ).tr(),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                _buildPlaces(),
 | 
					                _buildPlaces(),
 | 
				
			||||||
@@ -176,7 +180,7 @@ class SearchPage extends HookConsumerWidget {
 | 
				
			|||||||
                  padding: const EdgeInsets.all(16.0),
 | 
					                  padding: const EdgeInsets.all(16.0),
 | 
				
			||||||
                  child: const Text(
 | 
					                  child: const Text(
 | 
				
			||||||
                    "search_page_things",
 | 
					                    "search_page_things",
 | 
				
			||||||
                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
 | 
					                    style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
 | 
				
			||||||
                  ).tr(),
 | 
					                  ).tr(),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                _buildThings()
 | 
					                _buildThings()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,7 +172,7 @@ class SearchResultPage extends HookConsumerWidget {
 | 
				
			|||||||
          });
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          return DraggableScrollbar.semicircle(
 | 
					          return DraggableScrollbar.semicircle(
 | 
				
			||||||
            backgroundColor: Theme.of(context).primaryColor,
 | 
					            backgroundColor: Theme.of(context).hintColor,
 | 
				
			||||||
            controller: scrollController,
 | 
					            controller: scrollController,
 | 
				
			||||||
            heightScrollThumb: 48.0,
 | 
					            heightScrollThumb: 48.0,
 | 
				
			||||||
            child: CustomScrollView(
 | 
					            child: CustomScrollView(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final appSettingsServiceProvider = Provider((ref) => AppSettingsService());
 | 
				
			||||||
@@ -5,7 +5,7 @@ import 'package:immich_mobile/constants/hive_box.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
enum AppSettingsEnum {
 | 
					enum AppSettingsEnum {
 | 
				
			||||||
  threeStageLoading, // true, false,
 | 
					  threeStageLoading, // true, false,
 | 
				
			||||||
  themeMode, // "light","dark"
 | 
					  themeMode, // "light","dark","system"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AppSettingsService {
 | 
					class AppSettingsService {
 | 
				
			||||||
@@ -61,8 +61,8 @@ class AppSettingsService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Default value of themeMode is "light"
 | 
					    // Default value of themeMode is "light"
 | 
				
			||||||
    if (settingType == AppSettingsEnum.themeMode) {
 | 
					    if (settingType == AppSettingsEnum.themeMode) {
 | 
				
			||||||
      hiveBox.put(settingKey, "light");
 | 
					      hiveBox.put(settingKey, "system");
 | 
				
			||||||
      return "light";
 | 
					      return "system";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,5 +75,3 @@ class AppSettingsService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
final appSettingsServiceProvider = Provider((ref) => AppSettingsService());
 | 
					 | 
				
			||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/three_stage_loading.dart';
 | 
					import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/three_stage_loading.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -8,20 +9,21 @@ class ImageViewerQualitySetting extends StatelessWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return const ExpansionTile(
 | 
					    return ExpansionTile(
 | 
				
			||||||
      title: Text(
 | 
					      textColor: Theme.of(context).primaryColor,
 | 
				
			||||||
        'Image viewer quality',
 | 
					      title: const Text(
 | 
				
			||||||
 | 
					        'theme_setting_image_viewer_quality_title',
 | 
				
			||||||
        style: TextStyle(
 | 
					        style: TextStyle(
 | 
				
			||||||
          fontWeight: FontWeight.bold,
 | 
					          fontWeight: FontWeight.bold,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ).tr(),
 | 
				
			||||||
      subtitle: Text(
 | 
					      subtitle: const Text(
 | 
				
			||||||
        'Adjust the quality of the detail image viewer',
 | 
					        'theme_setting_image_viewer_quality_subtitle',
 | 
				
			||||||
        style: TextStyle(
 | 
					        style: TextStyle(
 | 
				
			||||||
          fontSize: 13,
 | 
					          fontSize: 13,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ).tr(),
 | 
				
			||||||
      children: [
 | 
					      children: const [
 | 
				
			||||||
        ThreeStageLoading(),
 | 
					        ThreeStageLoading(),
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter_hooks/flutter_hooks.dart';
 | 
					import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/services/app_settings.service.dart';
 | 
					import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ThreeStageLoading extends HookConsumerWidget {
 | 
					class ThreeStageLoading extends HookConsumerWidget {
 | 
				
			||||||
  const ThreeStageLoading({
 | 
					  const ThreeStageLoading({
 | 
				
			||||||
@@ -35,18 +37,18 @@ class ThreeStageLoading extends HookConsumerWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return SwitchListTile.adaptive(
 | 
					    return SwitchListTile.adaptive(
 | 
				
			||||||
      title: const Text(
 | 
					      title: const Text(
 | 
				
			||||||
        "Enable three stage loading",
 | 
					        "theme_setting_three_stage_loading_title",
 | 
				
			||||||
        style: TextStyle(
 | 
					        style: TextStyle(
 | 
				
			||||||
          fontSize: 12,
 | 
					          fontSize: 12,
 | 
				
			||||||
          fontWeight: FontWeight.bold,
 | 
					          fontWeight: FontWeight.bold,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ).tr(),
 | 
				
			||||||
      subtitle: const Text(
 | 
					      subtitle: const Text(
 | 
				
			||||||
        "The three-stage loading delivers the best quality image in exchange for a slower loading speed",
 | 
					        "theme_setting_three_stage_loading_subtitle",
 | 
				
			||||||
        style: TextStyle(
 | 
					        style: TextStyle(
 | 
				
			||||||
          fontSize: 12,
 | 
					          fontSize: 12,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ).tr(),
 | 
				
			||||||
      value: isEnable.value,
 | 
					      value: isEnable.value,
 | 
				
			||||||
      onChanged: onSwitchChanged,
 | 
					      onChanged: onSwitchChanged,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										107
									
								
								mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			||||||
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/three_stage_loading.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/utils/immich_app_theme.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ThemeSetting extends HookConsumerWidget {
 | 
				
			||||||
 | 
					  const ThemeSetting({
 | 
				
			||||||
 | 
					    Key? key,
 | 
				
			||||||
 | 
					  }) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final currentTheme = useState<ThemeMode>(ThemeMode.system);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(
 | 
				
			||||||
 | 
					      () {
 | 
				
			||||||
 | 
					        currentTheme.value = ref.read(immichThemeProvider);
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      [],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ExpansionTile(
 | 
				
			||||||
 | 
					      textColor: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					      title: const Text(
 | 
				
			||||||
 | 
					        'theme_setting_theme_title',
 | 
				
			||||||
 | 
					        style: TextStyle(
 | 
				
			||||||
 | 
					          fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ).tr(),
 | 
				
			||||||
 | 
					      subtitle: const Text(
 | 
				
			||||||
 | 
					        'theme_setting_theme_subtitle',
 | 
				
			||||||
 | 
					        style: TextStyle(
 | 
				
			||||||
 | 
					          fontSize: 13,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ).tr(),
 | 
				
			||||||
 | 
					      children: [
 | 
				
			||||||
 | 
					        SwitchListTile.adaptive(
 | 
				
			||||||
 | 
					          activeColor: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					          title: const Text(
 | 
				
			||||||
 | 
					            'theme_setting_system_theme_switch',
 | 
				
			||||||
 | 
					            style: TextStyle(
 | 
				
			||||||
 | 
					              fontSize: 12.0,
 | 
				
			||||||
 | 
					              fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ).tr(),
 | 
				
			||||||
 | 
					          value: currentTheme.value == ThemeMode.system,
 | 
				
			||||||
 | 
					          onChanged: (bool isSystem) {
 | 
				
			||||||
 | 
					            var currentSystemBrightness =
 | 
				
			||||||
 | 
					                MediaQuery.of(context).platformBrightness;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (isSystem) {
 | 
				
			||||||
 | 
					              currentTheme.value = ThemeMode.system;
 | 
				
			||||||
 | 
					              ref.watch(immichThemeProvider.notifier).state = ThemeMode.system;
 | 
				
			||||||
 | 
					              ref
 | 
				
			||||||
 | 
					                  .watch(appSettingsServiceProvider)
 | 
				
			||||||
 | 
					                  .setSetting(AppSettingsEnum.themeMode, "system");
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              if (currentSystemBrightness == Brightness.light) {
 | 
				
			||||||
 | 
					                currentTheme.value = ThemeMode.light;
 | 
				
			||||||
 | 
					                ref.watch(immichThemeProvider.notifier).state = ThemeMode.light;
 | 
				
			||||||
 | 
					                ref
 | 
				
			||||||
 | 
					                    .watch(appSettingsServiceProvider)
 | 
				
			||||||
 | 
					                    .setSetting(AppSettingsEnum.themeMode, "light");
 | 
				
			||||||
 | 
					              } else if (currentSystemBrightness == Brightness.dark) {
 | 
				
			||||||
 | 
					                currentTheme.value = ThemeMode.dark;
 | 
				
			||||||
 | 
					                ref.watch(immichThemeProvider.notifier).state = ThemeMode.dark;
 | 
				
			||||||
 | 
					                ref
 | 
				
			||||||
 | 
					                    .watch(appSettingsServiceProvider)
 | 
				
			||||||
 | 
					                    .setSetting(AppSettingsEnum.themeMode, "dark");
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        if (currentTheme.value != ThemeMode.system)
 | 
				
			||||||
 | 
					          SwitchListTile.adaptive(
 | 
				
			||||||
 | 
					            activeColor: Theme.of(context).primaryColor,
 | 
				
			||||||
 | 
					            title: const Text(
 | 
				
			||||||
 | 
					              'theme_setting_dark_mode_switch',
 | 
				
			||||||
 | 
					              style: TextStyle(
 | 
				
			||||||
 | 
					                fontSize: 12.0,
 | 
				
			||||||
 | 
					                fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ).tr(),
 | 
				
			||||||
 | 
					            value: ref.watch(immichThemeProvider) == ThemeMode.dark,
 | 
				
			||||||
 | 
					            onChanged: (bool isDark) {
 | 
				
			||||||
 | 
					              if (isDark) {
 | 
				
			||||||
 | 
					                ref.watch(immichThemeProvider.notifier).state = ThemeMode.dark;
 | 
				
			||||||
 | 
					                ref
 | 
				
			||||||
 | 
					                    .watch(appSettingsServiceProvider)
 | 
				
			||||||
 | 
					                    .setSetting(AppSettingsEnum.themeMode, "dark");
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                ref.watch(immichThemeProvider.notifier).state = ThemeMode.light;
 | 
				
			||||||
 | 
					                ref
 | 
				
			||||||
 | 
					                    .watch(appSettingsServiceProvider)
 | 
				
			||||||
 | 
					                    .setSetting(AppSettingsEnum.themeMode, "light");
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart';
 | 
					import 'package:immich_mobile/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/ui/theme_setting/theme_setting.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SettingsPage extends HookConsumerWidget {
 | 
					class SettingsPage extends HookConsumerWidget {
 | 
				
			||||||
  const SettingsPage({Key? key}) : super(key: key);
 | 
					  const SettingsPage({Key? key}) : super(key: key);
 | 
				
			||||||
@@ -20,12 +22,12 @@ class SettingsPage extends HookConsumerWidget {
 | 
				
			|||||||
        automaticallyImplyLeading: false,
 | 
					        automaticallyImplyLeading: false,
 | 
				
			||||||
        centerTitle: false,
 | 
					        centerTitle: false,
 | 
				
			||||||
        title: const Text(
 | 
					        title: const Text(
 | 
				
			||||||
          'Settings',
 | 
					          'setting_pages_app_bar_settings',
 | 
				
			||||||
          style: TextStyle(
 | 
					          style: TextStyle(
 | 
				
			||||||
            fontSize: 16,
 | 
					            fontSize: 16,
 | 
				
			||||||
            fontWeight: FontWeight.bold,
 | 
					            fontWeight: FontWeight.bold,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ).tr(),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      body: ListView(
 | 
					      body: ListView(
 | 
				
			||||||
        children: [
 | 
					        children: [
 | 
				
			||||||
@@ -33,10 +35,7 @@ class SettingsPage extends HookConsumerWidget {
 | 
				
			|||||||
            context: context,
 | 
					            context: context,
 | 
				
			||||||
            tiles: [
 | 
					            tiles: [
 | 
				
			||||||
              const ImageViewerQualitySetting(),
 | 
					              const ImageViewerQualitySetting(),
 | 
				
			||||||
              const SettingListTile(
 | 
					              const ThemeSetting(),
 | 
				
			||||||
                title: 'Theme',
 | 
					 | 
				
			||||||
                subtitle: 'Choose between light and dark theme',
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
          ).toList(),
 | 
					          ).toList(),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
@@ -44,38 +43,3 @@ class SettingsPage extends HookConsumerWidget {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
class SettingListTile extends StatelessWidget {
 | 
					 | 
				
			||||||
  const SettingListTile({
 | 
					 | 
				
			||||||
    required this.title,
 | 
					 | 
				
			||||||
    required this.subtitle,
 | 
					 | 
				
			||||||
    Key? key,
 | 
					 | 
				
			||||||
  }) : super(key: key);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  final String title;
 | 
					 | 
				
			||||||
  final String subtitle;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return ListTile(
 | 
					 | 
				
			||||||
      dense: true,
 | 
					 | 
				
			||||||
      title: Text(
 | 
					 | 
				
			||||||
        title,
 | 
					 | 
				
			||||||
        style: const TextStyle(
 | 
					 | 
				
			||||||
          fontWeight: FontWeight.bold,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      subtitle: Text(
 | 
					 | 
				
			||||||
        subtitle,
 | 
					 | 
				
			||||||
        style: const TextStyle(
 | 
					 | 
				
			||||||
          fontSize: 12,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      trailing: const Icon(
 | 
					 | 
				
			||||||
        Icons.keyboard_arrow_right_rounded,
 | 
					 | 
				
			||||||
        size: 24,
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      onTap: () {},
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			|||||||
import 'package:hive_flutter/hive_flutter.dart';
 | 
					import 'package:hive_flutter/hive_flutter.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:immich_mobile/constants/hive_box.dart';
 | 
					import 'package:immich_mobile/constants/hive_box.dart';
 | 
				
			||||||
import 'package:immich_mobile/constants/immich_colors.dart';
 | 
					 | 
				
			||||||
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
					import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
 | 
					import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 | 
					import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 | 
				
			||||||
@@ -49,7 +48,6 @@ class SplashScreenPage extends HookConsumerWidget {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
      backgroundColor: immichBackgroundColor,
 | 
					 | 
				
			||||||
      body: Center(
 | 
					      body: Center(
 | 
				
			||||||
        child: Column(
 | 
					        child: Column(
 | 
				
			||||||
          mainAxisAlignment: MainAxisAlignment.center,
 | 
					          mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@ import 'package:auto_route/auto_route.dart';
 | 
				
			|||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:immich_mobile/constants/immich_colors.dart';
 | 
					 | 
				
			||||||
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 | 
					import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/routing/router.dart';
 | 
					import 'package:immich_mobile/routing/router.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,8 +35,6 @@ class TabControllerPage extends ConsumerWidget {
 | 
				
			|||||||
            bottomNavigationBar: isMultiSelectEnable
 | 
					            bottomNavigationBar: isMultiSelectEnable
 | 
				
			||||||
                ? null
 | 
					                ? null
 | 
				
			||||||
                : BottomNavigationBar(
 | 
					                : BottomNavigationBar(
 | 
				
			||||||
                    type: BottomNavigationBarType.fixed,
 | 
					 | 
				
			||||||
                    backgroundColor: immichBackgroundColor,
 | 
					 | 
				
			||||||
                    selectedLabelStyle: const TextStyle(
 | 
					                    selectedLabelStyle: const TextStyle(
 | 
				
			||||||
                      fontSize: 13,
 | 
					                      fontSize: 13,
 | 
				
			||||||
                      fontWeight: FontWeight.w600,
 | 
					                      fontWeight: FontWeight.w600,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										133
									
								
								mobile/lib/utils/immich_app_theme.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								mobile/lib/utils/immich_app_theme.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/constants/immich_colors.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final immichThemeProvider = StateProvider<ThemeMode>((ref) {
 | 
				
			||||||
 | 
					  var themeMode = ref
 | 
				
			||||||
 | 
					      .watch(appSettingsServiceProvider)
 | 
				
			||||||
 | 
					      .getSetting(AppSettingsEnum.themeMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  debugPrint("Current themeMode $themeMode");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (themeMode == "light") {
 | 
				
			||||||
 | 
					    return ThemeMode.light;
 | 
				
			||||||
 | 
					  } else if (themeMode == "dark") {
 | 
				
			||||||
 | 
					    return ThemeMode.dark;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    return ThemeMode.system;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ThemeData immichDarkTheme = ThemeData(
 | 
				
			||||||
 | 
					  useMaterial3: true,
 | 
				
			||||||
 | 
					  brightness: Brightness.dark,
 | 
				
			||||||
 | 
					  primarySwatch: Colors.indigo,
 | 
				
			||||||
 | 
					  primaryColor: immichDarkThemePrimaryColor,
 | 
				
			||||||
 | 
					  scaffoldBackgroundColor: immichDarkBackgroundColor,
 | 
				
			||||||
 | 
					  hintColor: Colors.grey[600],
 | 
				
			||||||
 | 
					  fontFamily: 'WorkSans',
 | 
				
			||||||
 | 
					  snackBarTheme: const SnackBarThemeData(
 | 
				
			||||||
 | 
					    contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  appBarTheme: AppBarTheme(
 | 
				
			||||||
 | 
					    titleTextStyle: TextStyle(
 | 
				
			||||||
 | 
					      fontFamily: 'WorkSans',
 | 
				
			||||||
 | 
					      color: immichDarkThemePrimaryColor,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    backgroundColor: const Color.fromARGB(255, 32, 33, 35),
 | 
				
			||||||
 | 
					    foregroundColor: immichDarkThemePrimaryColor,
 | 
				
			||||||
 | 
					    elevation: 1,
 | 
				
			||||||
 | 
					    centerTitle: true,
 | 
				
			||||||
 | 
					    systemOverlayStyle: SystemUiOverlayStyle.light,
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  bottomNavigationBarTheme: BottomNavigationBarThemeData(
 | 
				
			||||||
 | 
					    type: BottomNavigationBarType.fixed,
 | 
				
			||||||
 | 
					    backgroundColor: const Color.fromARGB(255, 35, 36, 37),
 | 
				
			||||||
 | 
					    selectedItemColor: immichDarkThemePrimaryColor,
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  drawerTheme: DrawerThemeData(
 | 
				
			||||||
 | 
					    backgroundColor: immichDarkBackgroundColor,
 | 
				
			||||||
 | 
					    scrimColor: Colors.white.withOpacity(0.1),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  textTheme: TextTheme(
 | 
				
			||||||
 | 
					    headline1: const TextStyle(
 | 
				
			||||||
 | 
					      fontSize: 26,
 | 
				
			||||||
 | 
					      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      color: Color.fromARGB(255, 255, 255, 255),
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    headline2: const TextStyle(
 | 
				
			||||||
 | 
					      fontSize: 14,
 | 
				
			||||||
 | 
					      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      color: Color.fromARGB(255, 148, 151, 155),
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    headline3: TextStyle(
 | 
				
			||||||
 | 
					      fontSize: 12,
 | 
				
			||||||
 | 
					      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      color: immichDarkThemePrimaryColor,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  cardColor: Colors.grey[900],
 | 
				
			||||||
 | 
					  elevatedButtonTheme: ElevatedButtonThemeData(
 | 
				
			||||||
 | 
					    style: ElevatedButton.styleFrom(
 | 
				
			||||||
 | 
					      onPrimary: Colors.black87,
 | 
				
			||||||
 | 
					      primary: immichDarkThemePrimaryColor,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ThemeData immichLightTheme = ThemeData(
 | 
				
			||||||
 | 
					  useMaterial3: true,
 | 
				
			||||||
 | 
					  brightness: Brightness.light,
 | 
				
			||||||
 | 
					  primarySwatch: Colors.indigo,
 | 
				
			||||||
 | 
					  hintColor: Colors.indigo,
 | 
				
			||||||
 | 
					  fontFamily: 'WorkSans',
 | 
				
			||||||
 | 
					  scaffoldBackgroundColor: immichBackgroundColor,
 | 
				
			||||||
 | 
					  snackBarTheme: const SnackBarThemeData(
 | 
				
			||||||
 | 
					    contentTextStyle: TextStyle(fontFamily: 'WorkSans'),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  appBarTheme: AppBarTheme(
 | 
				
			||||||
 | 
					    titleTextStyle: const TextStyle(
 | 
				
			||||||
 | 
					      fontFamily: 'WorkSans',
 | 
				
			||||||
 | 
					      color: Colors.indigo,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    backgroundColor: immichBackgroundColor,
 | 
				
			||||||
 | 
					    foregroundColor: Colors.indigo,
 | 
				
			||||||
 | 
					    elevation: 1,
 | 
				
			||||||
 | 
					    centerTitle: true,
 | 
				
			||||||
 | 
					    systemOverlayStyle: SystemUiOverlayStyle.dark,
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  bottomNavigationBarTheme: BottomNavigationBarThemeData(
 | 
				
			||||||
 | 
					    type: BottomNavigationBarType.fixed,
 | 
				
			||||||
 | 
					    backgroundColor: immichBackgroundColor,
 | 
				
			||||||
 | 
					    selectedItemColor: Colors.indigo,
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  drawerTheme: DrawerThemeData(
 | 
				
			||||||
 | 
					    backgroundColor: immichBackgroundColor,
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  textTheme: const TextTheme(
 | 
				
			||||||
 | 
					    headline1: TextStyle(
 | 
				
			||||||
 | 
					      fontSize: 26,
 | 
				
			||||||
 | 
					      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      color: Colors.indigo,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    headline2: TextStyle(
 | 
				
			||||||
 | 
					      fontSize: 14,
 | 
				
			||||||
 | 
					      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      color: Colors.black87,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    headline3: TextStyle(
 | 
				
			||||||
 | 
					      fontSize: 12,
 | 
				
			||||||
 | 
					      fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      color: Colors.indigo,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					  elevatedButtonTheme: ElevatedButtonThemeData(
 | 
				
			||||||
 | 
					    style: ElevatedButton.styleFrom(
 | 
				
			||||||
 | 
					      primary: Colors.indigo,
 | 
				
			||||||
 | 
					      onPrimary: Colors.white,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  ),
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@@ -2,7 +2,7 @@ name: immich_mobile
 | 
				
			|||||||
description: Immich - selfhosted backup media file on mobile phone
 | 
					description: Immich - selfhosted backup media file on mobile phone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
publish_to: "none"
 | 
					publish_to: "none"
 | 
				
			||||||
version: 1.22.0+32
 | 
					version: 1.23.0+33
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ">=2.17.0 <3.0.0"
 | 
					  sdk: ">=2.17.0 <3.0.0"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ export interface IServerVersion {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const serverVersion: IServerVersion = {
 | 
					export const serverVersion: IServerVersion = {
 | 
				
			||||||
  major: 1,
 | 
					  major: 1,
 | 
				
			||||||
  minor: 22,
 | 
					  minor: 23,
 | 
				
			||||||
  patch: 0,
 | 
					  patch: 0,
 | 
				
			||||||
  build: 0,
 | 
					  build: 0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user