diff --git a/mobile/lib/extensions/build_context_extensions.dart b/mobile/lib/extensions/build_context_extensions.dart new file mode 100644 index 0000000000..b2e6ed4720 --- /dev/null +++ b/mobile/lib/extensions/build_context_extensions.dart @@ -0,0 +1,54 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +extension ContextHelper on BuildContext { + // Returns the current size from MediaQuery + Size get size => MediaQuery.sizeOf(this); + + // Returns the current width from MediaQuery + double get width => size.width; + + // Returns the current height from MediaQuery + double get height => size.height; + + // Returns true if the app is running on a mobile device (!tablets) + bool get isMobile => width < 550; + + // Returns the current ThemeData + ThemeData get themeData => Theme.of(this); + + // Returns true if the app is using a dark theme + bool get isDarkTheme => themeData.brightness == Brightness.dark; + + // Returns the current Primary color of the Theme + Color get primaryColor => themeData.primaryColor; + + // Returns the Scaffold background color of the Theme + Color get scaffoldBackgroundColor => themeData.scaffoldBackgroundColor; + + // Returns the current TextTheme + TextTheme get textTheme => themeData.textTheme; + + // Current ColorScheme used + ColorScheme get colorScheme => themeData.colorScheme; + + // Pop-out from the current context with optional result + void pop([T? result]) => Navigator.of(this).pop(result); + + // Auto-Push new route from the current context + Future autoPush(PageRouteInfo route) => + AutoRouter.of(this).push(route); + + // Auto-Push navigate route from the current context + Future autoNavigate( + PageRouteInfo route, + ) => + AutoRouter.of(this).navigate(route); + +// Auto-Push replace route from the current context + Future autoReplace(PageRouteInfo route) => + AutoRouter.of(this).replace(route); + + // Auto-Pop from the current context + Future autoPop([T? result]) => AutoRouter.of(this).pop(result); +} diff --git a/mobile/lib/utils/builtin_extensions.dart b/mobile/lib/extensions/collection_extensions.dart similarity index 70% rename from mobile/lib/utils/builtin_extensions.dart rename to mobile/lib/extensions/collection_extensions.dart index 5b769f26fd..283726ede3 100644 --- a/mobile/lib/utils/builtin_extensions.dart +++ b/mobile/lib/extensions/collection_extensions.dart @@ -2,27 +2,6 @@ import 'dart:typed_data'; import 'package:collection/collection.dart'; -extension DurationExtension on String { - Duration? toDuration() { - try { - final parts = split(':') - .map((e) => double.parse(e).toInt()) - .toList(growable: false); - return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]); - } catch (e) { - return null; - } - } - - double toDouble() { - return double.parse(this); - } - - int toInt() { - return int.parse(this); - } -} - extension ListExtension on List { List uniqueConsecutive({ int Function(E a, E b)? compare, diff --git a/mobile/lib/utils/datetime_extensions.dart b/mobile/lib/extensions/datetime_extensions.dart similarity index 100% rename from mobile/lib/utils/datetime_extensions.dart rename to mobile/lib/extensions/datetime_extensions.dart diff --git a/mobile/lib/utils/flutter_map_extensions.dart b/mobile/lib/extensions/flutter_map_extensions.dart similarity index 100% rename from mobile/lib/utils/flutter_map_extensions.dart rename to mobile/lib/extensions/flutter_map_extensions.dart diff --git a/mobile/lib/extensions/string_extensions.dart b/mobile/lib/extensions/string_extensions.dart new file mode 100644 index 0000000000..a25ab4f508 --- /dev/null +++ b/mobile/lib/extensions/string_extensions.dart @@ -0,0 +1,30 @@ +extension StringExtension on String { + String capitalize() { + return split(" ") + .map( + (str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1), + ) + .join(" "); + } +} + +extension DurationExtension on String { + Duration? toDuration() { + try { + final parts = split(':') + .map((e) => double.parse(e).toInt()) + .toList(growable: false); + return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]); + } catch (e) { + return null; + } + } + + double toDouble() { + return double.parse(this); + } + + int toInt() { + return int.parse(this); + } +} diff --git a/mobile/lib/modules/activities/views/activities_page.dart b/mobile/lib/modules/activities/views/activities_page.dart index 106500cc97..b744fc4762 100644 --- a/mobile/lib/modules/activities/views/activities_page.dart +++ b/mobile/lib/modules/activities/views/activities_page.dart @@ -4,13 +4,14 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/activities/models/activity.model.dart'; import 'package:immich_mobile/modules/activities/providers/activity.provider.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/ui/confirm_dialog.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; import 'package:immich_mobile/shared/ui/user_circle_avatar.dart'; -import 'package:immich_mobile/utils/datetime_extensions.dart'; +import 'package:immich_mobile/extensions/datetime_extensions.dart'; import 'package:immich_mobile/utils/image_url_builder.dart'; class ActivitiesPage extends HookConsumerWidget { @@ -49,12 +50,8 @@ class ActivitiesPage extends HookConsumerWidget { ); buildTitleWithTimestamp(Activity activity, {bool leftAlign = true}) { - final textColor = Theme.of(context).brightness == Brightness.dark - ? Colors.white - : Colors.black; - final textStyle = Theme.of(context) - .textTheme - .bodyMedium + final textColor = context.isDarkTheme ? Colors.white : Colors.black; + final textStyle = context.textTheme.bodyMedium ?.copyWith(color: textColor.withOpacity(0.6)); return Row( @@ -306,7 +303,7 @@ class ActivitiesPage extends HookConsumerWidget { Align( alignment: Alignment.bottomCenter, child: Container( - color: Theme.of(context).scaffoldBackgroundColor, + color: context.scaffoldBackgroundColor, child: buildTextField(liked?.id), ), ), diff --git a/mobile/lib/modules/album/ui/add_to_album_bottom_sheet.dart b/mobile/lib/modules/album/ui/add_to_album_bottom_sheet.dart index 257dbdbaa2..650d4da0d4 100644 --- a/mobile/lib/modules/album/ui/add_to_album_bottom_sheet.dart +++ b/mobile/lib/modules/album/ui/add_to_album_bottom_sheet.dart @@ -1,8 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; @@ -95,20 +95,19 @@ class AddToAlbumBottomSheet extends HookConsumerWidget { children: [ Text( 'common_add_to_album'.tr(), - style: Theme.of(context).textTheme.displayMedium, + style: context.textTheme.displayMedium, ), TextButton.icon( icon: Icon( Icons.add, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), label: Text( 'common_create_new_album'.tr(), - style: - TextStyle(color: Theme.of(context).primaryColor), + style: TextStyle(color: context.primaryColor), ), onPressed: () { - AutoRouter.of(context).push( + context.autoPush( CreateAlbumRoute( isSharedAlbum: false, initialAssets: assets, diff --git a/mobile/lib/modules/album/ui/album_action_outlined_button.dart b/mobile/lib/modules/album/ui/album_action_outlined_button.dart index 928a50794a..eebaefc416 100644 --- a/mobile/lib/modules/album/ui/album_action_outlined_button.dart +++ b/mobile/lib/modules/album/ui/album_action_outlined_button.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class AlbumActionOutlinedButton extends StatelessWidget { final VoidCallback? onPressed; @@ -14,8 +15,6 @@ class AlbumActionOutlinedButton extends StatelessWidget { @override Widget build(BuildContext context) { - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; - return Padding( padding: const EdgeInsets.only(right: 8.0), child: OutlinedButton.icon( @@ -26,7 +25,7 @@ class AlbumActionOutlinedButton extends StatelessWidget { ), side: BorderSide( width: 1, - color: isDarkTheme + color: context.isDarkTheme ? const Color.fromARGB(255, 63, 63, 63) : const Color.fromARGB(255, 206, 206, 206), ), @@ -34,13 +33,13 @@ class AlbumActionOutlinedButton extends StatelessWidget { icon: Icon( iconData, size: 15, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), label: Text( labelText, - style: Theme.of(context).textTheme.labelSmall?.copyWith( - fontWeight: FontWeight.bold, - ), + style: context.textTheme.labelSmall?.copyWith( + fontWeight: FontWeight.bold, + ), ), onPressed: onPressed, ), diff --git a/mobile/lib/modules/album/ui/album_thumbnail_card.dart b/mobile/lib/modules/album/ui/album_thumbnail_card.dart index f37751e3e1..7d5e42b1c2 100644 --- a/mobile/lib/modules/album/ui/album_thumbnail_card.dart +++ b/mobile/lib/modules/album/ui/album_thumbnail_card.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/album.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/ui/immich_image.dart'; @@ -22,7 +23,8 @@ class AlbumThumbnailCard extends StatelessWidget { @override Widget build(BuildContext context) { - var isDarkMode = Theme.of(context).brightness == Brightness.dark; + var isDarkTheme = context.isDarkTheme; + return LayoutBuilder( builder: (context, constraints) { var cardSize = constraints.maxWidth; @@ -32,7 +34,7 @@ class AlbumThumbnailCard extends StatelessWidget { height: cardSize, width: cardSize, decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[800] : Colors.grey[200], + color: isDarkTheme ? Colors.grey[800] : Colors.grey[200], ), child: Center( child: Icon( @@ -73,14 +75,14 @@ class AlbumThumbnailCard extends StatelessWidget { style: TextStyle( fontFamily: 'WorkSans', fontSize: 12, - color: isDarkMode ? Colors.white : Colors.black, + color: isDarkTheme ? Colors.white : Colors.black, ), ), if (owner != null) const TextSpan(text: ' · '), if (owner != null) TextSpan( text: owner, - style: Theme.of(context).textTheme.labelSmall, + style: context.textTheme.labelSmall, ), ], ), @@ -114,8 +116,8 @@ class AlbumThumbnailCard extends StatelessWidget { album.name, style: TextStyle( fontWeight: FontWeight.bold, - color: isDarkMode - ? Theme.of(context).primaryColor + color: isDarkTheme + ? context.primaryColor : Colors.black, ), ), diff --git a/mobile/lib/modules/album/ui/album_thumbnail_listtile.dart b/mobile/lib/modules/album/ui/album_thumbnail_listtile.dart index c9237ea27d..38208e88c0 100644 --- a/mobile/lib/modules/album/ui/album_thumbnail_listtile.dart +++ b/mobile/lib/modules/album/ui/album_thumbnail_listtile.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/shared/models/album.dart'; import 'package:immich_mobile/shared/models/store.dart'; @@ -21,12 +21,11 @@ class AlbumThumbnailListTile extends StatelessWidget { @override Widget build(BuildContext context) { var cardSize = 68.0; - var isDarkMode = Theme.of(context).brightness == Brightness.dark; buildEmptyThumbnail() { return Container( decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[800] : Colors.grey[200], + color: context.isDarkTheme ? Colors.grey[800] : Colors.grey[200], ), child: SizedBox( height: cardSize, @@ -61,7 +60,7 @@ class AlbumThumbnailListTile extends StatelessWidget { behavior: HitTestBehavior.opaque, onTap: onTap ?? () { - AutoRouter.of(context).push(AlbumViewerRoute(albumId: album.id)); + context.autoPush(AlbumViewerRoute(albumId: album.id)); }, child: Padding( padding: const EdgeInsets.only(bottom: 12.0), diff --git a/mobile/lib/modules/album/ui/album_title_text_field.dart b/mobile/lib/modules/album/ui/album_title_text_field.dart index 38c1f681a7..57b82a80d1 100644 --- a/mobile/lib/modules/album/ui/album_title_text_field.dart +++ b/mobile/lib/modules/album/ui/album_title_text_field.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/album_title.provider.dart'; class AlbumTitleTextField extends ConsumerWidget { @@ -19,7 +20,7 @@ class AlbumTitleTextField extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; + final isDarkTheme = context.isDarkTheme; return TextField( onChanged: (v) { @@ -55,7 +56,7 @@ class AlbumTitleTextField extends ConsumerWidget { }, icon: Icon( Icons.cancel_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), splashRadius: 10, ) diff --git a/mobile/lib/modules/album/ui/album_viewer_appbar.dart b/mobile/lib/modules/album/ui/album_viewer_appbar.dart index 3843282ad7..1ac64e957e 100644 --- a/mobile/lib/modules/album/ui/album_viewer_appbar.dart +++ b/mobile/lib/modules/album/ui/album_viewer_appbar.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/activities/providers/activity.provider.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart'; @@ -58,12 +58,12 @@ class AlbumViewerAppbar extends HookConsumerWidget if (album.shared) { success = await ref.watch(sharedAlbumProvider.notifier).deleteAlbum(album); - AutoRouter.of(context) - .navigate(const TabControllerRoute(children: [SharingRoute()])); + context + .autoNavigate(const TabControllerRoute(children: [SharingRoute()])); } else { success = await ref.watch(albumProvider.notifier).deleteAlbum(album); - AutoRouter.of(context) - .navigate(const TabControllerRoute(children: [LibraryRoute()])); + context + .autoNavigate(const TabControllerRoute(children: [LibraryRoute()])); } if (!success) { ImmichToast.show( @@ -93,7 +93,7 @@ class AlbumViewerAppbar extends HookConsumerWidget child: Text( 'Cancel', style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ), @@ -107,9 +107,7 @@ class AlbumViewerAppbar extends HookConsumerWidget 'Confirm', style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).brightness == Brightness.light - ? Colors.red - : Colors.red[300], + color: !context.isDarkTheme ? Colors.red : Colors.red[300], ), ), ), @@ -130,8 +128,8 @@ class AlbumViewerAppbar extends HookConsumerWidget await ref.watch(sharedAlbumProvider.notifier).leaveAlbum(album); if (isSuccess) { - AutoRouter.of(context) - .navigate(const TabControllerRoute(children: [SharingRoute()])); + context + .autoNavigate(const TabControllerRoute(children: [SharingRoute()])); } else { Navigator.pop(context); ImmichToast.show( @@ -190,7 +188,7 @@ class AlbumViewerAppbar extends HookConsumerWidget gravity: ToastGravity.BOTTOM, ); } - Navigator.of(buildContext).pop(); + context.pop(); }, ); return const ShareDialog(); @@ -266,8 +264,7 @@ class AlbumViewerAppbar extends HookConsumerWidget ListTile( leading: const Icon(Icons.share_rounded), onTap: () { - AutoRouter.of(context) - .push(SharedLinkEditRoute(albumId: album.remoteId)); + context.autoPush(SharedLinkEditRoute(albumId: album.remoteId)); Navigator.pop(context); }, title: const Text( @@ -277,8 +274,7 @@ class AlbumViewerAppbar extends HookConsumerWidget ), ListTile( leading: const Icon(Icons.settings_rounded), - onTap: () => - AutoRouter.of(context).navigate(AlbumOptionsRoute(album: album)), + onTap: () => context.autoNavigate(AlbumOptionsRoute(album: album)), title: const Text( "translated_text_options", style: TextStyle(fontWeight: FontWeight.bold), @@ -300,7 +296,7 @@ class AlbumViewerAppbar extends HookConsumerWidget ), ]; showModalBottomSheet( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: context.scaffoldBackgroundColor, isScrollControlled: false, context: context, builder: (context) { @@ -342,7 +338,7 @@ class AlbumViewerAppbar extends HookConsumerWidget comments.toString(), style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), @@ -381,7 +377,7 @@ class AlbumViewerAppbar extends HookConsumerWidget ); } else { return IconButton( - onPressed: () async => await AutoRouter.of(context).pop(), + onPressed: () async => await context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), splashRadius: 25, ); diff --git a/mobile/lib/modules/album/ui/album_viewer_editable_title.dart b/mobile/lib/modules/album/ui/album_viewer_editable_title.dart index 8a7e46f8ca..b73748f4a3 100644 --- a/mobile/lib/modules/album/ui/album_viewer_editable_title.dart +++ b/mobile/lib/modules/album/ui/album_viewer_editable_title.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/album_viewer.provider.dart'; import 'package:immich_mobile/shared/models/album.dart'; @@ -17,7 +18,6 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final titleTextEditController = useTextEditingController(text: album.name); - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; void onFocusModeChange() { if (!titleFocusNode.hasFocus && titleTextEditController.text.isEmpty) { @@ -65,7 +65,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { }, icon: Icon( Icons.cancel_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), splashRadius: 10, ) @@ -79,14 +79,14 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { borderRadius: BorderRadius.circular(10), ), focusColor: Colors.grey[300], - fillColor: isDarkTheme + fillColor: context.isDarkTheme ? const Color.fromARGB(255, 32, 33, 35) : Colors.grey[200], filled: titleFocusNode.hasFocus, hintText: 'share_add_title'.tr(), hintStyle: TextStyle( fontSize: 28, - color: isDarkTheme ? Colors.grey[300] : Colors.grey[700], + color: context.isDarkTheme ? Colors.grey[300] : Colors.grey[700], fontWeight: FontWeight.bold, ), ), diff --git a/mobile/lib/modules/album/views/album_options_part.dart b/mobile/lib/modules/album/views/album_options_part.dart index 615fe5c7f2..88f0d7d3ca 100644 --- a/mobile/lib/modules/album/views/album_options_part.dart +++ b/mobile/lib/modules/album/views/album_options_part.dart @@ -1,9 +1,9 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -44,8 +44,9 @@ class AlbumOptionsPage extends HookConsumerWidget { await ref.read(sharedAlbumProvider.notifier).leaveAlbum(album); if (isSuccess) { - AutoRouter.of(context) - .navigate(const TabControllerRoute(children: [SharingRoute()])); + context.autoNavigate( + const TabControllerRoute(children: [SharingRoute()]), + ); } else { showErrorMessage(); } @@ -97,7 +98,7 @@ class AlbumOptionsPage extends HookConsumerWidget { } showModalBottomSheet( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: context.scaffoldBackgroundColor, isScrollControlled: false, context: context, builder: (context) { @@ -177,7 +178,7 @@ class AlbumOptionsPage extends HookConsumerWidget { buildSectionTitle(String text) { return Padding( padding: const EdgeInsets.all(16.0), - child: Text(text, style: Theme.of(context).textTheme.bodySmall), + child: Text(text, style: context.textTheme.bodySmall), ); } @@ -186,7 +187,7 @@ class AlbumOptionsPage extends HookConsumerWidget { leading: IconButton( icon: const Icon(Icons.arrow_back_ios_new_rounded), onPressed: () { - AutoRouter.of(context).pop(null); + context.autoPop(null); }, ), centerTitle: true, @@ -208,14 +209,12 @@ class AlbumOptionsPage extends HookConsumerWidget { } }, activeColor: activityEnabled.value - ? Theme.of(context).primaryColor - : Theme.of(context).disabledColor, + ? context.primaryColor + : context.themeData.disabledColor, dense: true, title: Text( "shared_album_activity_setting_title", - style: Theme.of(context) - .textTheme - .labelLarge + style: context.textTheme.labelLarge ?.copyWith(fontWeight: FontWeight.bold), ).tr(), subtitle: diff --git a/mobile/lib/modules/album/views/album_viewer_page.dart b/mobile/lib/modules/album/views/album_viewer_page.dart index e474fe877e..b123363286 100644 --- a/mobile/lib/modules/album/views/album_viewer_page.dart +++ b/mobile/lib/modules/album/views/album_viewer_page.dart @@ -1,10 +1,10 @@ import 'dart:async'; -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart'; import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart'; import 'package:immich_mobile/modules/album/services/album.service.dart'; @@ -67,7 +67,7 @@ class AlbumViewerPage extends HookConsumerWidget { /// If they exist, add to selected asset state to show they are already selected. void onAddPhotosPressed(Album albumInfo) async { AssetSelectionPageResult? returnPayload = - await AutoRouter.of(context).push( + await context.autoPush( AssetSelectionRoute( existingAssets: albumInfo.assets, canDeselect: false, @@ -97,8 +97,7 @@ class AlbumViewerPage extends HookConsumerWidget { } void onAddUsersPressed(Album album) async { - List? sharedUserIds = - await AutoRouter.of(context).push?>( + List? sharedUserIds = await context.autoPush?>( SelectAdditionalUserForSharingRoute(album: album), ); @@ -203,7 +202,7 @@ class AlbumViewerPage extends HookConsumerWidget { Widget buildSharedUserIconsRow(Album album) { return GestureDetector( onTap: () async { - await AutoRouter.of(context).push(AlbumOptionsRoute(album: album)); + await context.autoPush(AlbumOptionsRoute(album: album)); ref.invalidate(albumDetailProvider(album.id)); }, child: SizedBox( @@ -242,7 +241,7 @@ class AlbumViewerPage extends HookConsumerWidget { onActivitiesPressed(Album album) { if (album.remoteId != null) { - AutoRouter.of(context).push( + context.autoPush( ActivitiesRoute( albumId: album.remoteId!, appBarTitle: album.name, diff --git a/mobile/lib/modules/album/views/asset_selection_page.dart b/mobile/lib/modules/album/views/asset_selection_page.dart index 9c30ba80f6..c1870fe442 100644 --- a/mobile/lib/modules/album/views/asset_selection_page.dart +++ b/mobile/lib/modules/album/views/asset_selection_page.dart @@ -3,6 +3,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart'; @@ -78,7 +79,7 @@ class AssetSelectionPage extends HookConsumerWidget { canDeselect ? "share_done" : "share_add", style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ).tr(), ), diff --git a/mobile/lib/modules/album/views/create_album_page.dart b/mobile/lib/modules/album/views/create_album_page.dart index 191ce14705..8f2c4e1280 100644 --- a/mobile/lib/modules/album/views/create_album_page.dart +++ b/mobile/lib/modules/album/views/create_album_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album_title.provider.dart'; @@ -34,11 +34,11 @@ class CreateAlbumPage extends HookConsumerWidget { final selectedAssets = useState>( initialAssets != null ? Set.from(initialAssets!) : const {}, ); - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; showSelectUserPage() async { - final bool? ok = await AutoRouter.of(context) - .push(SelectUserForSharingRoute(assets: selectedAssets.value)); + final bool? ok = await context.autoPush( + SelectUserForSharingRoute(assets: selectedAssets.value), + ); if (ok == true) { selectedAssets.value = {}; } @@ -58,7 +58,7 @@ class CreateAlbumPage extends HookConsumerWidget { onSelectPhotosButtonPressed() async { AssetSelectionPageResult? selectedAsset = - await AutoRouter.of(context).push( + await context.autoPush( AssetSelectionRoute( existingAssets: selectedAssets.value, canDeselect: true, @@ -94,10 +94,10 @@ class CreateAlbumPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 200, left: 18), child: Text( 'create_shared_album_page_share_add_assets', - style: Theme.of(context).textTheme.displayMedium?.copyWith( - fontSize: 12, - fontWeight: FontWeight.normal, - ), + style: context.textTheme.displayMedium?.copyWith( + fontSize: 12, + fontWeight: FontWeight.normal, + ), ).tr(), ), ); @@ -117,7 +117,7 @@ class CreateAlbumPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(vertical: 22, horizontal: 16), side: BorderSide( - color: isDarkTheme + color: context.isDarkTheme ? const Color.fromARGB(255, 63, 63, 63) : const Color.fromARGB(255, 206, 206, 206), ), @@ -128,16 +128,16 @@ class CreateAlbumPage extends HookConsumerWidget { onPressed: onSelectPhotosButtonPressed, icon: Icon( Icons.add_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), label: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( 'create_shared_album_page_share_select_photos', - style: Theme.of(context).textTheme.labelLarge?.copyWith( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + style: context.textTheme.labelLarge?.copyWith( + fontSize: 16, + fontWeight: FontWeight.bold, + ), ).tr(), ), ), @@ -206,7 +206,7 @@ class CreateAlbumPage extends HookConsumerWidget { selectedAssets.value = {}; ref.watch(albumTitleProvider.notifier).clearAlbumTitle(); - AutoRouter.of(context).replace(AlbumViewerRoute(albumId: newAlbum.id)); + context.autoReplace(AlbumViewerRoute(albumId: newAlbum.id)); } } @@ -214,19 +214,19 @@ class CreateAlbumPage extends HookConsumerWidget { appBar: AppBar( elevation: 0, centerTitle: false, - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: context.scaffoldBackgroundColor, leading: IconButton( onPressed: () { selectedAssets.value = {}; - AutoRouter.of(context).pop(); + context.autoPop(); }, icon: const Icon(Icons.close_rounded), ), title: Text( 'share_create_album', - style: Theme.of(context).textTheme.displayMedium?.copyWith( - color: Theme.of(context).primaryColor, - ), + style: context.textTheme.displayMedium?.copyWith( + color: context.primaryColor, + ), ).tr(), actions: [ if (isSharedAlbum) @@ -239,8 +239,8 @@ class CreateAlbumPage extends HookConsumerWidget { style: TextStyle( fontWeight: FontWeight.bold, color: albumTitleController.text.isEmpty - ? Theme.of(context).disabledColor - : Theme.of(context).primaryColor, + ? context.themeData.disabledColor + : context.primaryColor, ), ), ), @@ -254,7 +254,7 @@ class CreateAlbumPage extends HookConsumerWidget { 'create_shared_album_page_create'.tr(), style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), @@ -265,7 +265,7 @@ class CreateAlbumPage extends HookConsumerWidget { child: CustomScrollView( slivers: [ SliverAppBar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: context.scaffoldBackgroundColor, elevation: 5, automaticallyImplyLeading: false, pinned: true, diff --git a/mobile/lib/modules/album/views/library_page.dart b/mobile/lib/modules/album/views/library_page.dart index 90d0956409..15229232b0 100644 --- a/mobile/lib/modules/album/views/library_page.dart +++ b/mobile/lib/modules/album/views/library_page.dart @@ -1,9 +1,9 @@ -import 'package:auto_route/auto_route.dart'; import 'package:collection/collection.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/ui/album_thumbnail_card.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -21,7 +21,7 @@ class LibraryPage extends HookConsumerWidget { final trashEnabled = ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash)); final albums = ref.watch(albumProvider); - var isDarkMode = Theme.of(context).brightness == Brightness.dark; + var isDarkTheme = context.isDarkTheme; var settings = ref.watch(appSettingsServiceProvider); useEffect( @@ -96,15 +96,14 @@ class LibraryPage extends HookConsumerWidget { padding: const EdgeInsets.only(right: 12.0), child: Icon( Icons.check, - color: selected - ? Theme.of(context).primaryColor - : Colors.transparent, + color: + selected ? context.primaryColor : Colors.transparent, ), ), Text( option, style: TextStyle( - color: selected ? Theme.of(context).primaryColor : null, + color: selected ? context.primaryColor : null, fontSize: 12.0, ), ), @@ -122,13 +121,13 @@ class LibraryPage extends HookConsumerWidget { Icon( Icons.swap_vert_rounded, size: 18, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), Text( options[selectedAlbumSortOrder.value], style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontSize: 12.0, ), ), @@ -140,7 +139,7 @@ class LibraryPage extends HookConsumerWidget { Widget buildCreateAlbumButton() { return GestureDetector( onTap: () { - AutoRouter.of(context).push(CreateAlbumRoute(isSharedAlbum: false)); + context.autoPush(CreateAlbumRoute(isSharedAlbum: false)); }, child: Padding( padding: const EdgeInsets.only(bottom: 32), @@ -152,18 +151,18 @@ class LibraryPage extends HookConsumerWidget { child: Container( decoration: BoxDecoration( border: Border.all( - color: isDarkMode + color: isDarkTheme ? const Color.fromARGB(255, 53, 53, 53) : const Color.fromARGB(255, 203, 203, 203), ), - color: isDarkMode ? Colors.grey[900] : Colors.grey[50], + color: isDarkTheme ? Colors.grey[900] : Colors.grey[50], borderRadius: BorderRadius.circular(20), ), child: Center( child: Icon( Icons.add_rounded, size: 28, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), @@ -201,21 +200,21 @@ class LibraryPage extends HookConsumerWidget { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 13.0, - color: isDarkMode ? Colors.white : Colors.grey[800], + color: isDarkTheme ? Colors.white : Colors.grey[800], ), ), ), style: OutlinedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), - backgroundColor: isDarkMode ? Colors.grey[900] : Colors.grey[50], + backgroundColor: isDarkTheme ? Colors.grey[900] : Colors.grey[50], side: BorderSide( - color: isDarkMode ? Colors.grey[800]! : Colors.grey[300]!, + color: isDarkTheme ? Colors.grey[800]! : Colors.grey[300]!, ), alignment: Alignment.centerLeft, ), icon: Icon( icon, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ); @@ -228,7 +227,7 @@ class LibraryPage extends HookConsumerWidget { Widget? shareTrashButton() { return trashEnabled ? InkWell( - onTap: () => AutoRouter.of(context).push(const TrashRoute()), + onTap: () => context.autoPush(const TrashRoute()), borderRadius: BorderRadius.circular(12), child: const Icon( Icons.delete_rounded, @@ -257,12 +256,12 @@ class LibraryPage extends HookConsumerWidget { children: [ buildLibraryNavButton( "library_page_favorites".tr(), Icons.favorite_border, () { - AutoRouter.of(context).navigate(const FavoritesRoute()); + context.autoNavigate(const FavoritesRoute()); }), const SizedBox(width: 12.0), buildLibraryNavButton( "library_page_archive".tr(), Icons.archive_outlined, () { - AutoRouter.of(context).navigate(const ArchiveRoute()); + context.autoNavigate(const ArchiveRoute()); }), ], ), @@ -306,7 +305,7 @@ class LibraryPage extends HookConsumerWidget { return AlbumThumbnailCard( album: sorted[index - 1], - onTap: () => AutoRouter.of(context).push( + onTap: () => context.autoPush( AlbumViewerRoute( albumId: sorted[index - 1].id, ), @@ -348,7 +347,7 @@ class LibraryPage extends HookConsumerWidget { childCount: local.length, (context, index) => AlbumThumbnailCard( album: local[index], - onTap: () => AutoRouter.of(context).push( + onTap: () => context.autoPush( AlbumViewerRoute( albumId: local[index].id, ), diff --git a/mobile/lib/modules/album/views/select_additional_user_for_sharing_page.dart b/mobile/lib/modules/album/views/select_additional_user_for_sharing_page.dart index e13637d23d..b91197d282 100644 --- a/mobile/lib/modules/album/views/select_additional_user_for_sharing_page.dart +++ b/mobile/lib/modules/album/views/select_additional_user_for_sharing_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart'; import 'package:immich_mobile/shared/models/album.dart'; import 'package:immich_mobile/shared/models/user.dart'; @@ -22,14 +22,13 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { final sharedUsersList = useState>({}); addNewUsersHandler() { - AutoRouter.of(context) - .pop(sharedUsersList.value.map((e) => e.id).toList()); + context.autoPop(sharedUsersList.value.map((e) => e.id).toList()); } buildTileIcon(User user) { if (sharedUsersList.value.contains(user)) { return CircleAvatar( - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: context.primaryColor, child: const Icon( Icons.check_rounded, size: 25, @@ -50,7 +49,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Chip( - backgroundColor: Theme.of(context).primaryColor.withOpacity(0.15), + backgroundColor: context.primaryColor.withOpacity(0.15), label: Text( user.email, style: const TextStyle( @@ -124,7 +123,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { leading: IconButton( icon: const Icon(Icons.close_rounded), onPressed: () { - AutoRouter.of(context).pop(null); + context.autoPop(null); }, ), actions: [ diff --git a/mobile/lib/modules/album/views/select_user_for_sharing_page.dart b/mobile/lib/modules/album/views/select_user_for_sharing_page.dart index fe6cef4016..61ced47e22 100644 --- a/mobile/lib/modules/album/views/select_user_for_sharing_page.dart +++ b/mobile/lib/modules/album/views/select_user_for_sharing_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/album_title.provider.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart'; @@ -35,9 +35,9 @@ class SelectUserForSharingPage extends HookConsumerWidget { await ref.watch(sharedAlbumProvider.notifier).getAllSharedAlbums(); // ref.watch(assetSelectionProvider.notifier).removeAll(); ref.watch(albumTitleProvider.notifier).clearAlbumTitle(); - AutoRouter.of(context).pop(true); - AutoRouter.of(context) - .navigate(const TabControllerRoute(children: [SharingRoute()])); + context.autoPop(true); + context + .autoNavigate(const TabControllerRoute(children: [SharingRoute()])); } ScaffoldMessenger( @@ -50,7 +50,7 @@ class SelectUserForSharingPage extends HookConsumerWidget { buildTileIcon(User user) { if (sharedUsersList.value.contains(user)) { return CircleAvatar( - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: context.primaryColor, child: const Icon( Icons.check_rounded, size: 25, @@ -71,7 +71,7 @@ class SelectUserForSharingPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Chip( - backgroundColor: Theme.of(context).primaryColor.withOpacity(0.15), + backgroundColor: context.primaryColor.withOpacity(0.15), label: Text( user.email, style: const TextStyle( @@ -139,20 +139,20 @@ class SelectUserForSharingPage extends HookConsumerWidget { appBar: AppBar( title: Text( 'share_invite', - style: TextStyle(color: Theme.of(context).primaryColor), + style: TextStyle(color: context.primaryColor), ).tr(), elevation: 0, centerTitle: false, leading: IconButton( icon: const Icon(Icons.close_rounded), onPressed: () async { - AutoRouter.of(context).pop(); + context.autoPop(); }, ), actions: [ TextButton( style: TextButton.styleFrom( - foregroundColor: Theme.of(context).primaryColor, + foregroundColor: context.primaryColor, ), onPressed: sharedUsersList.value.isEmpty ? null : createSharedAlbum, child: const Text( @@ -160,7 +160,7 @@ class SelectUserForSharingPage extends HookConsumerWidget { style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, - // color: Theme.of(context).primaryColor, + // color: context.primaryColor, ), ).tr(), ), diff --git a/mobile/lib/modules/album/views/sharing_page.dart b/mobile/lib/modules/album/views/sharing_page.dart index 5e74aef679..3061289a97 100644 --- a/mobile/lib/modules/album/views/sharing_page.dart +++ b/mobile/lib/modules/album/views/sharing_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; import 'package:immich_mobile/modules/album/ui/album_thumbnail_card.dart'; import 'package:immich_mobile/modules/partner/providers/partner.provider.dart'; @@ -21,7 +21,6 @@ class SharingPage extends HookConsumerWidget { final List sharedAlbums = ref.watch(sharedAlbumProvider); final userId = ref.watch(currentUserProvider)?.id; final partner = ref.watch(partnerSharedWithProvider); - var isDarkMode = Theme.of(context).brightness == Brightness.dark; useEffect( () { @@ -47,8 +46,9 @@ class SharingPage extends HookConsumerWidget { album: sharedAlbums[index], showOwner: true, onTap: () { - AutoRouter.of(context) - .push(AlbumViewerRoute(albumId: sharedAlbums[index].id)); + context.autoPush( + AlbumViewerRoute(albumId: sharedAlbums[index].id), + ); }, ); }, @@ -79,12 +79,11 @@ class SharingPage extends HookConsumerWidget { album.name, maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.bold, - color: isDarkMode - ? Theme.of(context).primaryColor - : Colors.black, - ), + style: context.textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.bold, + color: + context.isDarkTheme ? context.primaryColor : Colors.black, + ), ), subtitle: isOwner ? Text( @@ -103,8 +102,9 @@ class SharingPage extends HookConsumerWidget { ) : null, onTap: () { - AutoRouter.of(context) - .push(AlbumViewerRoute(albumId: sharedAlbums[index].id)); + context.autoPush( + AlbumViewerRoute(albumId: sharedAlbums[index].id), + ); }, ); }, @@ -127,8 +127,7 @@ class SharingPage extends HookConsumerWidget { Expanded( child: ElevatedButton.icon( onPressed: () { - AutoRouter.of(context) - .push(CreateAlbumRoute(isSharedAlbum: true)); + context.autoPush(CreateAlbumRoute(isSharedAlbum: true)); }, icon: const Icon( Icons.photo_album_outlined, @@ -147,8 +146,7 @@ class SharingPage extends HookConsumerWidget { const SizedBox(width: 12.0), Expanded( child: ElevatedButton.icon( - onPressed: () => - AutoRouter.of(context).push(const SharedLinkRoute()), + onPressed: () => context.autoPush(const SharedLinkRoute()), icon: const Icon( Icons.link, size: 20, @@ -191,21 +189,21 @@ class SharingPage extends HookConsumerWidget { child: Icon( Icons.insert_photo_rounded, size: 50, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( 'sharing_page_empty_list', - style: Theme.of(context).textTheme.displaySmall, + style: context.textTheme.displaySmall, ).tr(), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( 'sharing_page_description', - style: Theme.of(context).textTheme.bodyMedium, + style: context.textTheme.bodyMedium, ).tr(), ), ], @@ -218,7 +216,7 @@ class SharingPage extends HookConsumerWidget { Widget sharePartnerButton() { return InkWell( - onTap: () => AutoRouter.of(context).push(const PartnerRoute()), + onTap: () => context.autoPush(const PartnerRoute()), borderRadius: BorderRadius.circular(12), child: const Icon( Icons.swap_horizontal_circle_rounded, diff --git a/mobile/lib/modules/archive/views/archive_page.dart b/mobile/lib/modules/archive/views/archive_page.dart index 2e1c1cd4a6..06270afc1a 100644 --- a/mobile/lib/modules/archive/views/archive_page.dart +++ b/mobile/lib/modules/archive/views/archive_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/archive/providers/archive_asset_provider.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/shared/models/asset.dart'; @@ -30,7 +30,7 @@ class ArchivePage extends HookConsumerWidget { AppBar buildAppBar(String count) { return AppBar( leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), centerTitle: true, diff --git a/mobile/lib/modules/asset_viewer/providers/image_viewer_page_state.provider.dart b/mobile/lib/modules/asset_viewer/providers/image_viewer_page_state.provider.dart index 6df633f12f..b7f6ee0950 100644 --- a/mobile/lib/modules/asset_viewer/providers/image_viewer_page_state.provider.dart +++ b/mobile/lib/modules/asset_viewer/providers/image_viewer_page_state.provider.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/services/album.service.dart'; import 'package:immich_mobile/modules/asset_viewer/models/image_viewer_page_state.model.dart'; import 'package:immich_mobile/modules/asset_viewer/services/image_viewer.service.dart'; @@ -67,7 +68,7 @@ class ImageViewerStateNotifier extends StateNotifier { gravity: ToastGravity.BOTTOM, ); } - Navigator.of(buildContext).pop(); + context.pop(); }, ); return const ShareDialog(); diff --git a/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart index 441492c39b..97b955b5f3 100644 --- a/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart +++ b/mobile/lib/modules/asset_viewer/ui/advanced_bottom_sheet.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/asset.dart'; class AdvancedBottomSheet extends HookConsumerWidget { @@ -11,8 +12,6 @@ class AdvancedBottomSheet extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - var isDarkMode = Theme.of(context).brightness == Brightness.dark; - return SingleChildScrollView( child: Card( shape: const RoundedRectangleBorder( @@ -40,7 +39,9 @@ class AdvancedBottomSheet extends HookConsumerWidget { const SizedBox(height: 32.0), Container( decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[900] : Colors.grey[200], + color: context.isDarkTheme + ? Colors.grey[900] + : Colors.grey[200], borderRadius: BorderRadius.circular(15.0), ), child: Padding( @@ -70,7 +71,7 @@ class AdvancedBottomSheet extends HookConsumerWidget { icon: Icon( Icons.copy, size: 16.0, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), diff --git a/mobile/lib/modules/asset_viewer/ui/description_input.dart b/mobile/lib/modules/asset_viewer/ui/description_input.dart index e00739faf8..a8cb62524c 100644 --- a/mobile/lib/modules/asset_viewer/ui/description_input.dart +++ b/mobile/lib/modules/asset_viewer/ui/description_input.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/asset_description.provider.dart'; import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/providers/user.provider.dart'; @@ -19,8 +20,7 @@ class DescriptionInput extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; - final textColor = isDarkTheme ? Colors.white : Colors.black; + final textColor = context.isDarkTheme ? Colors.white : Colors.black; final controller = useTextEditingController(); final focusNode = useFocusNode(); final isFocus = useState(false); diff --git a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart index f194738a2c..4f2fbf50d6 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart @@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:timezone/timezone.dart'; import 'package:immich_mobile/modules/asset_viewer/ui/description_input.dart'; import 'package:immich_mobile/modules/map/ui/map_thumbnail.dart'; @@ -28,7 +29,7 @@ class ExifBottomSheet extends HookConsumerWidget { exifInfo.longitude != 0; String formatTimeZone(Duration d) => - "GMT${d.isNegative ? '-': '+'}${d.inHours.abs().toString().padLeft(2, '0')}:${d.inMinutes.abs().remainder(60).toString().padLeft(2, '0')}"; + "GMT${d.isNegative ? '-' : '+'}${d.inHours.abs().toString().padLeft(2, '0')}:${d.inMinutes.abs().remainder(60).toString().padLeft(2, '0')}"; String get formattedDateTime { DateTime dt = asset.fileCreatedAt.toLocal(); @@ -41,10 +42,16 @@ class ExifBottomSheet extends HookConsumerWidget { final location = getLocation(asset.exifInfo!.timeZone!); dt = TZDateTime.from(dt, location); } on LocationNotFoundException { - RegExp re = RegExp(r'^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$', caseSensitive: false); + RegExp re = RegExp( + r'^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$', + caseSensitive: false, + ); final m = re.firstMatch(asset.exifInfo!.timeZone!); if (m != null) { - final duration = Duration(hours: int.parse(m.group(1) ?? '0'), minutes: int.parse(m.group(2) ?? '0')); + final duration = Duration( + hours: int.parse(m.group(1) ?? '0'), + minutes: int.parse(m.group(2) ?? '0'), + ); dt = dt.add(duration); timeZone = formatTimeZone(duration); } @@ -105,8 +112,7 @@ class ExifBottomSheet extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final assetWithExif = ref.watch(assetDetailProvider(asset)); final exifInfo = (assetWithExif.value ?? asset).exifInfo; - var isDarkTheme = Theme.of(context).brightness == Brightness.dark; - var textColor = isDarkTheme ? Colors.white : Colors.black; + var textColor = context.isDarkTheme ? Colors.white : Colors.black; buildMap() { return Padding( @@ -322,9 +328,14 @@ class ExifBottomSheet extends HookConsumerWidget { fontWeight: FontWeight.bold, ), ), - subtitle: exifInfo.f != null || exifInfo.exposureSeconds != null || exifInfo.mm != null || exifInfo.iso != null ? Text( - "ƒ/${exifInfo.fNumber} ${exifInfo.exposureTime} ${exifInfo.focalLength} mm ISO ${exifInfo.iso ?? ''} ", - ) : null, + subtitle: exifInfo.f != null || + exifInfo.exposureSeconds != null || + exifInfo.mm != null || + exifInfo.iso != null + ? Text( + "ƒ/${exifInfo.fNumber} ${exifInfo.exposureTime} ${exifInfo.focalLength} mm ISO ${exifInfo.iso ?? ''} ", + ) + : null, ), ], ); @@ -393,7 +404,7 @@ class ExifBottomSheet extends HookConsumerWidget { data: (data) => DescriptionInput(asset: data), error: (error, stackTrace) => Icon( Icons.image_not_supported_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), loading: () => const SizedBox( width: 75, diff --git a/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart b/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart index 95965f6d87..3e6dfe2ee8 100644 --- a/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart +++ b/mobile/lib/modules/asset_viewer/ui/top_control_app_bar.dart @@ -1,6 +1,6 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/activities/providers/activity.provider.dart'; import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/providers/asset.provider.dart'; @@ -147,7 +147,7 @@ class TopControlAppBar extends HookConsumerWidget { Widget buildBackButton() { return IconButton( onPressed: () { - AutoRouter.of(context).pop(); + context.autoPop(); }, icon: Icon( Icons.arrow_back_ios_new_rounded, diff --git a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart index f8acef5888..bdb2bb50ca 100644 --- a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart +++ b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart @@ -8,6 +8,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/asset_stack.provider.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/show_controls.provider.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/video_player_controls_provider.dart'; @@ -209,7 +210,7 @@ class GalleryViewerPage extends HookConsumerWidget { if (isDeleted && isParent) { if (totalAssets == 1) { // Handle only one asset - AutoRouter.of(context).pop(); + context.autoPop(); } else { // Go to next page otherwise controller.nextPage( @@ -293,7 +294,7 @@ class GalleryViewerPage extends HookConsumerWidget { final ratio = d.dy / max(d.dx.abs(), 1); if (d.dy > sensitivity && ratio > ratioThreshold) { - AutoRouter.of(context).pop(); + context.autoPop(); } else if (d.dy < -sensitivity && ratio < -ratioThreshold) { showInfo(); } @@ -308,7 +309,7 @@ class GalleryViewerPage extends HookConsumerWidget { .watch(assetProvider.notifier) .toggleArchive([asset], !asset.isArchived); if (isParent) { - AutoRouter.of(context).pop(); + context.autoPop(); return; } removeAssetFromStack(); @@ -331,7 +332,7 @@ class GalleryViewerPage extends HookConsumerWidget { handleActivities() { if (sharedAlbumId != null) { - AutoRouter.of(context).push( + context.autoPush( ActivitiesRoute( albumId: sharedAlbumId!, assetId: asset().remoteId, @@ -514,7 +515,7 @@ class GalleryViewerPage extends HookConsumerWidget { stackElements.elementAt(stackIndex.value), ); Navigator.pop(ctx); - AutoRouter.of(context).pop(); + context.autoPop(); }, title: const Text( "viewer_stack_use_as_main_asset", @@ -541,7 +542,7 @@ class GalleryViewerPage extends HookConsumerWidget { childrenToRemove: [currentAsset], ); Navigator.pop(ctx); - AutoRouter.of(context).pop(); + context.autoPop(); } else { await ref.read(assetStackServiceProvider).updateStack( currentAsset, @@ -569,7 +570,7 @@ class GalleryViewerPage extends HookConsumerWidget { childrenToRemove: stack, ); Navigator.pop(ctx); - AutoRouter.of(context).pop(); + context.autoPop(); }, title: const Text( "viewer_unstack", @@ -829,8 +830,8 @@ class GalleryViewerPage extends HookConsumerWidget { placeholder: Image( image: provider, fit: BoxFit.fitWidth, - height: MediaQuery.of(context).size.height, - width: MediaQuery.of(context).size.width, + height: context.height, + width: context.width, alignment: Alignment.center, ), onVideoEnded: () { diff --git a/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart b/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart index a56d65595d..ad929a8c5e 100644 --- a/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart +++ b/mobile/lib/modules/asset_viewer/views/video_viewer_page.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:chewie/chewie.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/asset_viewer/models/image_viewer_page_state.model.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/image_viewer_page_state.provider.dart'; import 'package:immich_mobile/modules/asset_viewer/ui/video_player_controls.dart'; @@ -44,7 +45,7 @@ class VideoViewerPage extends HookConsumerWidget { ), error: (error, stackTrace) => Icon( Icons.image_not_supported_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), loading: () => const Center( child: SizedBox( @@ -74,8 +75,8 @@ class VideoViewerPage extends HookConsumerWidget { ), if (downloadAssetStatus == DownloadAssetStatus.loading) SizedBox( - height: MediaQuery.of(context).size.height, - width: MediaQuery.of(context).size.width, + height: context.height, + width: context.width, child: const Center( child: ImmichLoadingIndicator(), ), @@ -205,8 +206,8 @@ class _VideoPlayerState extends State { ); } else { return SizedBox( - height: MediaQuery.of(context).size.height, - width: MediaQuery.of(context).size.width, + height: context.height, + width: context.width, child: Center( child: Stack( children: [ diff --git a/mobile/lib/modules/backup/ui/album_info_card.dart b/mobile/lib/modules/backup/ui/album_info_card.dart index eaace503ee..4df62090bf 100644 --- a/mobile/lib/modules/backup/ui/album_info_card.dart +++ b/mobile/lib/modules/backup/ui/album_info_card.dart @@ -1,9 +1,9 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/models/available_album.model.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -22,10 +22,10 @@ class AlbumInfoCard extends HookConsumerWidget { ref.watch(backupProvider).selectedBackupAlbums.contains(albumInfo); final bool isExcluded = ref.watch(backupProvider).excludedBackupAlbums.contains(albumInfo); - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; + final isDarkTheme = context.isDarkTheme; ColorFilter selectedFilter = ColorFilter.mode( - Theme.of(context).primaryColor.withAlpha(100), + context.primaryColor.withAlpha(100), BlendMode.darken, ); ColorFilter excludedFilter = @@ -46,7 +46,7 @@ class AlbumInfoCard extends HookConsumerWidget { fontWeight: FontWeight.bold, ), ).tr(), - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: context.primaryColor, ); } else if (isExcluded) { return Chip( @@ -194,7 +194,7 @@ class AlbumInfoCard extends HookConsumerWidget { albumInfo.name, style: TextStyle( fontSize: 14, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ), @@ -224,13 +224,13 @@ class AlbumInfoCard extends HookConsumerWidget { ), IconButton( onPressed: () { - AutoRouter.of(context).push( + context.autoPush( AlbumPreviewRoute(album: albumInfo.albumEntity), ); }, icon: Icon( Icons.image_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, size: 24, ), splashRadius: 25, diff --git a/mobile/lib/modules/backup/ui/album_info_list_tile.dart b/mobile/lib/modules/backup/ui/album_info_list_tile.dart index 88141a0158..e19827bf90 100644 --- a/mobile/lib/modules/backup/ui/album_info_list_tile.dart +++ b/mobile/lib/modules/backup/ui/album_info_list_tile.dart @@ -1,10 +1,10 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/models/available_album.model.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -25,14 +25,13 @@ class AlbumInfoListTile extends HookConsumerWidget { ref.watch(backupProvider).excludedBackupAlbums.contains(albumInfo); ColorFilter selectedFilter = ColorFilter.mode( - Theme.of(context).primaryColor.withAlpha(100), + context.primaryColor.withAlpha(100), BlendMode.darken, ); ColorFilter excludedFilter = ColorFilter.mode(Colors.red.withAlpha(75), BlendMode.darken); ColorFilter unselectedFilter = const ColorFilter.mode(Colors.black, BlendMode.color); - var isDarkTheme = Theme.of(context).brightness == Brightness.dark; var assetCount = useState(0); @@ -56,11 +55,11 @@ class AlbumInfoListTile extends HookConsumerWidget { buildTileColor() { if (isSelected) { - return isDarkTheme - ? Theme.of(context).primaryColor.withAlpha(100) - : Theme.of(context).primaryColor.withAlpha(25); + return context.isDarkTheme + ? context.primaryColor.withAlpha(100) + : context.primaryColor.withAlpha(25); } else if (isExcluded) { - return isDarkTheme + return context.isDarkTheme ? Colors.red[300]?.withAlpha(150) : Colors.red[100]?.withAlpha(150); } else { @@ -159,13 +158,13 @@ class AlbumInfoListTile extends HookConsumerWidget { subtitle: Text(assetCount.value.toString()), trailing: IconButton( onPressed: () { - AutoRouter.of(context).push( + context.autoPush( AlbumPreviewRoute(album: albumInfo.albumEntity), ); }, icon: Icon( Icons.image_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, size: 24, ), splashRadius: 25, diff --git a/mobile/lib/modules/backup/ui/backup_info_card.dart b/mobile/lib/modules/backup/ui/backup_info_card.dart index bf52c79e6e..a398bc83ef 100644 --- a/mobile/lib/modules/backup/ui/backup_info_card.dart +++ b/mobile/lib/modules/backup/ui/backup_info_card.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class BackupInfoCard extends StatelessWidget { final String title; @@ -14,13 +15,11 @@ class BackupInfoCard extends StatelessWidget { @override Widget build(BuildContext context) { - var isDarkMode = Theme.of(context).brightness == Brightness.dark; - return Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), // if you need this side: BorderSide( - color: isDarkMode + color: context.isDarkTheme ? const Color.fromARGB(255, 56, 56, 56) : Colors.black12, width: 1, diff --git a/mobile/lib/modules/backup/ui/current_backup_asset_info_box.dart b/mobile/lib/modules/backup/ui/current_backup_asset_info_box.dart index 23bdf11edf..0ddc6beaf0 100644 --- a/mobile/lib/modules/backup/ui/current_backup_asset_info_box.dart +++ b/mobile/lib/modules/backup/ui/current_backup_asset_info_box.dart @@ -1,9 +1,9 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/models/backup_state.model.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/modules/backup/providers/error_backup_list.provider.dart'; @@ -53,7 +53,7 @@ class CurrentUploadingAssetInfoBox extends HookConsumerWidget { ), backgroundColor: Colors.white, onPressed: () { - AutoRouter.of(context).push(const FailedBackupStatusRoute()); + context.autoPush(const FailedBackupStatusRoute()); }, ); } @@ -61,7 +61,7 @@ class CurrentUploadingAssetInfoBox extends HookConsumerWidget { Widget buildAssetInfoTable() { return Table( border: TableBorder.all( - color: Theme.of(context).primaryColorLight, + color: context.themeData.primaryColorLight, width: 1, ), children: [ @@ -176,7 +176,7 @@ class CurrentUploadingAssetInfoBox extends HookConsumerWidget { onTap: () => isShowThumbnail.value = true, child: Icon( Icons.image_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, size: 30, ), ), @@ -206,7 +206,7 @@ class CurrentUploadingAssetInfoBox extends HookConsumerWidget { minHeight: 10.0, value: uploadProgress / 100.0, backgroundColor: Colors.grey, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), Text( diff --git a/mobile/lib/modules/backup/ui/ios_debug_info_tile.dart b/mobile/lib/modules/backup/ui/ios_debug_info_tile.dart index 9ab92104ed..283c329b68 100644 --- a/mobile/lib/modules/backup/ui/ios_debug_info_tile.dart +++ b/mobile/lib/modules/backup/ui/ios_debug_info_tile.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/providers/ios_background_settings.provider.dart'; import 'package:intl/intl.dart'; @@ -43,7 +44,7 @@ class IosDebugInfoTile extends HookConsumerWidget { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), subtitle: Text( @@ -54,7 +55,7 @@ class IosDebugInfoTile extends HookConsumerWidget { ), leading: Icon( Icons.bug_report, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ); } diff --git a/mobile/lib/modules/backup/views/album_preview_page.dart b/mobile/lib/modules/backup/views/album_preview_page.dart index 27ca79082b..cdb0204ecd 100644 --- a/mobile/lib/modules/backup/views/album_preview_page.dart +++ b/mobile/lib/modules/backup/views/album_preview_page.dart @@ -1,9 +1,9 @@ import 'dart:typed_data'; -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; import 'package:photo_manager/photo_manager.dart'; @@ -53,7 +53,7 @@ class AlbumPreviewPage extends HookConsumerWidget { ], ), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_new_rounded), ), ), diff --git a/mobile/lib/modules/backup/views/backup_album_selection_page.dart b/mobile/lib/modules/backup/views/backup_album_selection_page.dart index 9e4118038e..e259bf1376 100644 --- a/mobile/lib/modules/backup/views/backup_album_selection_page.dart +++ b/mobile/lib/modules/backup/views/backup_album_selection_page.dart @@ -1,10 +1,10 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/immich_colors.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.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_list_tile.dart'; @@ -18,7 +18,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { // final availableAlbums = ref.watch(backupProvider).availableAlbums; final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums; final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums; - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; + final isDarkTheme = context.isDarkTheme; final allAlbums = ref.watch(backupProvider).availableAlbums; // Albums which are displayed to the user @@ -118,7 +118,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { fontWeight: FontWeight.bold, ), ), - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: context.primaryColor, deleteIconColor: isDarkTheme ? Colors.black : Colors.white, deleteIcon: const Icon( Icons.cancel_rounded, @@ -211,7 +211,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), title: const Text( @@ -315,7 +315,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { "backup_album_selection_page_albums_tap", style: TextStyle( fontSize: 12, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ).tr(), @@ -325,7 +325,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { icon: Icon( Icons.info, size: 20, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), onPressed: () { // show the dialog @@ -342,7 +342,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ).tr(), content: SingleChildScrollView( diff --git a/mobile/lib/modules/backup/views/backup_controller_page.dart b/mobile/lib/modules/backup/views/backup_controller_page.dart index 9dc40ecede..fa8fac1d6b 100644 --- a/mobile/lib/modules/backup/views/backup_controller_page.dart +++ b/mobile/lib/modules/backup/views/backup_controller_page.dart @@ -1,11 +1,11 @@ import 'dart:io'; -import 'package:auto_route/auto_route.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/background_service/background.service.dart'; import 'package:immich_mobile/modules/backup/providers/error_backup_list.provider.dart'; import 'package:immich_mobile/modules/backup/providers/ios_background_settings.provider.dart'; @@ -49,7 +49,6 @@ class BackupControllerPage extends HookConsumerWidget { !hasExclusiveAccess ? false : true; - var isDarkMode = Theme.of(context).brightness == Brightness.dark; final checkInProgress = useState(false); useEffect( @@ -151,7 +150,7 @@ class BackupControllerPage extends HookConsumerWidget { return ListTile( leading: Icon( Icons.warning_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), title: const Text( "Check for corrupt asset backups", @@ -187,7 +186,7 @@ class BackupControllerPage extends HookConsumerWidget { leading: isAutoBackup ? Icon( Icons.cloud_done_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ) : const Icon(Icons.cloud_off_rounded), title: Text( @@ -266,7 +265,7 @@ class BackupControllerPage extends HookConsumerWidget { style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), ).tr(), onPressed: () { - Navigator.of(context).pop(); + context.pop(); }, ), ], @@ -279,7 +278,7 @@ class BackupControllerPage extends HookConsumerWidget { final bool isBackgroundEnabled = backupState.backgroundBackup; final bool isWifiRequired = backupState.backupRequireWifi; final bool isChargingRequired = backupState.backupRequireCharging; - final Color activeColor = Theme.of(context).primaryColor; + final Color activeColor = context.primaryColor; String formatBackupDelaySliderValue(double v) { if (v == 0.0) { @@ -410,7 +409,7 @@ class BackupControllerPage extends HookConsumerWidget { max: 3.0, divisions: 3, label: formatBackupDelaySliderValue(triggerDelay.value), - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, ), ), ElevatedButton( @@ -511,7 +510,7 @@ class BackupControllerPage extends HookConsumerWidget { child: Text( text.trim().substring(0, text.length - 2), style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontSize: 12, fontWeight: FontWeight.bold, ), @@ -523,7 +522,7 @@ class BackupControllerPage extends HookConsumerWidget { child: Text( "backup_controller_page_none_selected".tr(), style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontSize: 12, fontWeight: FontWeight.bold, ), @@ -562,7 +561,7 @@ class BackupControllerPage extends HookConsumerWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), side: BorderSide( - color: isDarkMode + color: context.isDarkTheme ? const Color.fromARGB(255, 56, 56, 56) : Colors.black12, width: 1, @@ -592,7 +591,7 @@ class BackupControllerPage extends HookConsumerWidget { ), trailing: ElevatedButton( onPressed: () { - AutoRouter.of(context).push(const BackupAlbumSelectionRoute()); + context.autoPush(const BackupAlbumSelectionRoute()); }, child: const Text( "backup_controller_page_select", @@ -678,7 +677,7 @@ class BackupControllerPage extends HookConsumerWidget { leading: IconButton( onPressed: () { ref.watch(websocketProvider.notifier).listenUploadEvent(); - AutoRouter.of(context).pop(true); + context.autoPop(true); }, splashRadius: 24, icon: const Icon( diff --git a/mobile/lib/modules/backup/views/failed_backup_status_page.dart b/mobile/lib/modules/backup/views/failed_backup_status_page.dart index c55383cf3a..433ed34204 100644 --- a/mobile/lib/modules/backup/views/failed_backup_status_page.dart +++ b/mobile/lib/modules/backup/views/failed_backup_status_page.dart @@ -1,6 +1,6 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/providers/error_backup_list.provider.dart'; import 'package:intl/intl.dart'; import 'package:photo_manager/photo_manager.dart'; @@ -20,7 +20,7 @@ class FailedBackupStatusPage extends HookConsumerWidget { ), leading: IconButton( onPressed: () { - AutoRouter.of(context).pop(true); + context.autoPop(true); }, splashRadius: 24, icon: const Icon( @@ -114,7 +114,7 @@ class FailedBackupStatusPage extends HookConsumerWidget { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), diff --git a/mobile/lib/modules/favorite/views/favorites_page.dart b/mobile/lib/modules/favorite/views/favorites_page.dart index 62f8763bbc..1636113968 100644 --- a/mobile/lib/modules/favorite/views/favorites_page.dart +++ b/mobile/lib/modules/favorite/views/favorites_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/shared/models/asset.dart'; @@ -28,7 +28,7 @@ class FavoritesPage extends HookConsumerWidget { AppBar buildAppBar() { return AppBar( leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), centerTitle: true, diff --git a/mobile/lib/modules/home/ui/asset_grid/group_divider_title.dart b/mobile/lib/modules/home/ui/asset_grid/group_divider_title.dart index d63b0631e0..acb176aaae 100644 --- a/mobile/lib/modules/home/ui/asset_grid/group_divider_title.dart +++ b/mobile/lib/modules/home/ui/asset_grid/group_divider_title.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class GroupDividerTitle extends ConsumerWidget { const GroupDividerTitle({ @@ -51,7 +52,7 @@ class GroupDividerTitle extends ConsumerWidget { child: multiselectEnabled && selected ? Icon( Icons.check_circle_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ) : const Icon( Icons.check_circle_outline_rounded, diff --git a/mobile/lib/modules/home/ui/asset_grid/immich_asset_grid_view.dart b/mobile/lib/modules/home/ui/asset_grid/immich_asset_grid_view.dart index 3b900a5f14..27b9f9d3dc 100644 --- a/mobile/lib/modules/home/ui/asset_grid/immich_asset_grid_view.dart +++ b/mobile/lib/modules/home/ui/asset_grid/immich_asset_grid_view.dart @@ -4,10 +4,11 @@ import 'dart:math'; import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/scroll_notifier.provider.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart'; import 'package:immich_mobile/shared/models/asset.dart'; -import 'package:immich_mobile/utils/builtin_extensions.dart'; +import 'package:immich_mobile/extensions/collection_extensions.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import 'asset_grid_data_structure.dart'; import 'group_divider_title.dart'; @@ -224,7 +225,7 @@ class ImmichAssetGridViewState extends State { style: TextStyle( fontSize: 26, fontWeight: FontWeight.bold, - color: Theme.of(context).textTheme.displayLarge?.color, + color: context.textTheme.displayLarge?.color, ), ), ); @@ -372,7 +373,7 @@ class ImmichAssetGridViewState extends State { scrollStateListener: dragScrolling, itemPositionsListener: _itemPositionsListener, controller: _itemScrollController, - backgroundColor: Theme.of(context).hintColor, + backgroundColor: context.themeData.hintColor, labelTextBuilder: _labelBuilder, labelConstraints: const BoxConstraints(maxHeight: 28), scrollbarAnimationDuration: const Duration(milliseconds: 300), diff --git a/mobile/lib/modules/home/ui/asset_grid/thumbnail_image.dart b/mobile/lib/modules/home/ui/asset_grid/thumbnail_image.dart index 16423b3b49..c99e08fb3b 100644 --- a/mobile/lib/modules/home/ui/asset_grid/thumbnail_image.dart +++ b/mobile/lib/modules/home/ui/asset_grid/thumbnail_image.dart @@ -1,6 +1,6 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/ui/immich_image.dart'; @@ -43,9 +43,9 @@ class ThumbnailImage extends StatelessWidget { @override Widget build(BuildContext context) { - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; - final assetContainerColor = - isDarkTheme ? Colors.blueGrey : Theme.of(context).primaryColorLight; + final assetContainerColor = context.isDarkTheme + ? Colors.blueGrey + : context.themeData.primaryColorLight; // Assets from response DTOs do not have an isar id, querying which would give us the default autoIncrement id final isFromDto = asset.id == Isar.autoIncrement; @@ -58,7 +58,7 @@ class ThumbnailImage extends StatelessWidget { ), child: Icon( Icons.check_circle_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ); } else { @@ -178,7 +178,7 @@ class ThumbnailImage extends StatelessWidget { onSelect?.call(); } } else { - AutoRouter.of(context).push( + context.autoPush( GalleryViewerRoute( initialIndex: index, loadAsset: loadAsset, diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart index 4f6e2706d3..e9283218ca 100644 --- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart +++ b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/ui/add_to_album_sliverlist.dart'; import 'package:immich_mobile/modules/home/models/selection_state.dart'; import 'package:immich_mobile/modules/home/ui/delete_dialog.dart'; @@ -42,7 +43,6 @@ class ControlBottomAppBar extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - var isDarkMode = Theme.of(context).brightness == Brightness.dark; var hasRemote = selectionAssetState.hasRemote || selectionAssetState.hasMerged; var hasLocal = selectionAssetState.hasLocal; @@ -128,7 +128,7 @@ class ControlBottomAppBar extends ConsumerWidget { ScrollController scrollController, ) { return Card( - color: isDarkMode ? Colors.grey[900] : Colors.grey[100], + color: context.isDarkTheme ? Colors.grey[900] : Colors.grey[100], surfaceTintColor: Colors.transparent, elevation: 18.0, shape: const RoundedRectangleBorder( @@ -211,12 +211,12 @@ class AddToAlbumTitleRow extends StatelessWidget { onPressed: onCreateNewAlbum, icon: Icon( Icons.add, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), label: Text( "common_create_new_album", style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14, ), diff --git a/mobile/lib/modules/home/views/home_page.dart b/mobile/lib/modules/home/views/home_page.dart index d41022a298..eb26ea077c 100644 --- a/mobile/lib/modules/home/views/home_page.dart +++ b/mobile/lib/modules/home/views/home_page.dart @@ -1,12 +1,12 @@ import 'dart:async'; -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart'; import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart'; @@ -106,8 +106,7 @@ class HomePage extends HookConsumerWidget { handleShareAssets(ref, context, selection.value.toList()); } else { final ids = remoteOnlySelection().map((e) => e.remoteId!); - AutoRouter.of(context) - .push(SharedLinkEditRoute(assetsList: ids.toList())); + context.autoPush(SharedLinkEditRoute(assetsList: ids.toList())); } processing.value = false; selectionEnabledHook.value = false; @@ -243,7 +242,7 @@ class HomePage extends HookConsumerWidget { ref.watch(sharedAlbumProvider.notifier).getAllSharedAlbums(); selectionEnabledHook.value = false; - AutoRouter.of(context).push(AlbumViewerRoute(albumId: result.id)); + context.autoPush(AlbumViewerRoute(albumId: result.id)); } } finally { processing.value = false; @@ -300,7 +299,7 @@ class HomePage extends HookConsumerWidget { style: TextStyle( fontWeight: FontWeight.w600, fontSize: 16, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ).tr(), ), diff --git a/mobile/lib/modules/login/ui/change_password_form.dart b/mobile/lib/modules/login/ui/change_password_form.dart index b7db83b3fa..884a26b6da 100644 --- a/mobile/lib/modules/login/ui/change_password_form.dart +++ b/mobile/lib/modules/login/ui/change_password_form.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/modules/backup/providers/manual_upload.provider.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; @@ -37,7 +38,7 @@ class ChangePasswordForm extends HookConsumerWidget { style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), Padding( @@ -191,7 +192,7 @@ class ChangePasswordButton extends ConsumerWidget { return ElevatedButton( style: ElevatedButton.styleFrom( visualDensity: VisualDensity.standard, - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: context.primaryColor, foregroundColor: Colors.grey[50], elevation: 2, padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25), diff --git a/mobile/lib/modules/login/ui/login_form.dart b/mobile/lib/modules/login/ui/login_form.dart index 58c7feec22..5cdcbe0341 100644 --- a/mobile/lib/modules/login/ui/login_form.dart +++ b/mobile/lib/modules/login/ui/login_form.dart @@ -1,9 +1,9 @@ import 'dart:io'; -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/login/providers/oauth.provider.dart'; import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -150,7 +150,7 @@ class LoginForm extends HookConsumerWidget { // Resume backup (if enable) then navigate if (ref.read(authenticationProvider).shouldChangePassword && !ref.read(authenticationProvider).isAdmin) { - AutoRouter.of(context).push(const ChangePasswordRoute()); + context.autoPush(const ChangePasswordRoute()); } else { final hasPermission = await ref .read(galleryPermissionNotifier.notifier) @@ -159,7 +159,7 @@ class LoginForm extends HookConsumerWidget { // Don't resume the backup until we have gallery permission ref.read(backupProvider.notifier).resumeBackup(); } - AutoRouter.of(context).replace(const TabControllerRoute()); + context.autoReplace(const TabControllerRoute()); } } else { ImmichToast.show( @@ -212,9 +212,7 @@ class LoginForm extends HookConsumerWidget { if (permission.isGranted || permission.isLimited) { ref.watch(backupProvider.notifier).resumeBackup(); } - AutoRouter.of(context).replace( - const TabControllerRoute(), - ); + context.autoReplace(const TabControllerRoute()); } else { ImmichToast.show( context: context, @@ -260,8 +258,7 @@ class LoginForm extends HookConsumerWidget { ), ), ), - onPressed: () => - AutoRouter.of(context).push(const SettingsRoute()), + onPressed: () => context.autoPush(const SettingsRoute()), icon: const Icon(Icons.settings_rounded), label: const SizedBox.shrink(), ), @@ -303,7 +300,7 @@ class LoginForm extends HookConsumerWidget { children: [ Text( serverEndpointController.text, - style: Theme.of(context).textTheme.displaySmall, + style: context.textTheme.displaySmall, textAlign: TextAlign.center, ), if (isPasswordLoginEnable.value) ...[ @@ -339,8 +336,7 @@ class LoginForm extends HookConsumerWidget { horizontal: 16.0, ), child: Divider( - color: Brightness.dark == - Theme.of(context).brightness + color: context.isDarkTheme ? Colors.white : Colors.black, ), @@ -588,7 +584,7 @@ class OAuthLoginButton extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return ElevatedButton.icon( style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor.withAlpha(230), + backgroundColor: context.primaryColor.withAlpha(230), padding: const EdgeInsets.symmetric(vertical: 12), ), onPressed: onPressed, diff --git a/mobile/lib/modules/login/views/login_page.dart b/mobile/lib/modules/login/views/login_page.dart index 98778736e3..4e1b9a6dff 100644 --- a/mobile/lib/modules/login/views/login_page.dart +++ b/mobile/lib/modules/login/views/login_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/login/ui/login_form.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -47,13 +47,13 @@ class LoginPage extends HookConsumerWidget { child: Text( 'Logs', style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, fontFamily: "Inconsolata", ), ), onTap: () { - AutoRouter.of(context).push(const AppLogRoute()); + context.autoPush(const AppLogRoute()); }, ), ], diff --git a/mobile/lib/modules/map/ui/map_page_app_bar.dart b/mobile/lib/modules/map/ui/map_page_app_bar.dart index e9ed75cb1d..ce426cf037 100644 --- a/mobile/lib/modules/map/ui/map_page_app_bar.dart +++ b/mobile/lib/modules/map/ui/map_page_app_bar.dart @@ -1,8 +1,8 @@ import 'dart:io'; -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/disable_multi_select_button.dart'; import 'package:immich_mobile/modules/map/ui/map_settings_dialog.dart'; @@ -30,7 +30,7 @@ class MapAppBar extends HookWidget implements PreferredSizeWidget { Padding( padding: const EdgeInsets.only(left: 15, top: 15), child: ElevatedButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), style: ElevatedButton.styleFrom( shape: const CircleBorder(), padding: const EdgeInsets.all(12), diff --git a/mobile/lib/modules/map/ui/map_page_bottom_sheet.dart b/mobile/lib/modules/map/ui/map_page_bottom_sheet.dart index 2f71ac950c..0d0dfb4126 100644 --- a/mobile/lib/modules/map/ui/map_page_bottom_sheet.dart +++ b/mobile/lib/modules/map/ui/map_page_bottom_sheet.dart @@ -5,6 +5,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/render_list.provider.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; @@ -56,10 +57,10 @@ class AssetsInBoundBottomSheetState extends ConsumerState { @override Widget build(BuildContext context) { - final isDarkMode = Theme.of(context).brightness == Brightness.dark; + final isDarkTheme = context.isDarkTheme; final bottomPadding = Platform.isAndroid ? MediaQuery.of(context).padding.bottom - 10 : 0.0; - final maxHeight = MediaQuery.of(context).size.height - bottomPadding; + final maxHeight = context.height - bottomPadding; final isSheetScrolled = useState(false); final isSheetExpanded = useState(false); final assetsInBound = useState([]); @@ -136,7 +137,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState { SizedBox( height: 150, width: 150, - child: isDarkMode + child: isDarkTheme ? const InvertionFilter( child: SaturationFilter( saturation: -1, @@ -155,7 +156,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState { "map_zoom_to_see_photos".tr(), style: TextStyle( fontSize: 20, - color: Theme.of(context).textTheme.displayLarge?.color, + color: context.textTheme.displayLarge?.color, ), ), ], @@ -181,7 +182,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState { height: 60, width: double.infinity, decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[900] : Colors.grey[100], + color: isDarkTheme ? Colors.grey[900] : Colors.grey[100], ), child: Stack( children: [ @@ -196,17 +197,14 @@ class AssetsInBoundBottomSheetState extends ConsumerState { textToDisplay, style: TextStyle( fontSize: 16, - color: Theme.of(context).textTheme.displayLarge?.color, + color: context.textTheme.displayLarge?.color, fontWeight: FontWeight.bold, ), ), Divider( height: 10, - color: Theme.of(context) - .textTheme - .displayLarge - ?.color - ?.withOpacity(0.5), + color: + context.textTheme.displayLarge?.color?.withOpacity(0.5), ), ], ), @@ -217,7 +215,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState { child: IconButton( icon: Icon( Icons.map_outlined, - color: Theme.of(context).textTheme.displayLarge?.color, + color: context.textTheme.displayLarge?.color, ), iconSize: 20, tooltip: 'Zoom to bounds', @@ -265,7 +263,7 @@ class AssetsInBoundBottomSheetState extends ConsumerState { ScrollController scrollController, ) { return Card( - color: isDarkMode ? Colors.grey[900] : Colors.grey[100], + color: isDarkTheme ? Colors.grey[900] : Colors.grey[100], surfaceTintColor: Colors.transparent, elevation: 18.0, margin: const EdgeInsets.all(0), diff --git a/mobile/lib/modules/map/ui/map_settings_dialog.dart b/mobile/lib/modules/map/ui/map_settings_dialog.dart index f8a308b35f..b7503cd525 100644 --- a/mobile/lib/modules/map/ui/map_settings_dialog.dart +++ b/mobile/lib/modules/map/ui/map_settings_dialog.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/map/providers/map_state.provider.dart'; class MapSettingsDialog extends HookConsumerWidget { @@ -15,7 +16,7 @@ class MapSettingsDialog extends HookConsumerWidget { final showFavoriteOnly = useState(mapSettings.showFavoriteOnly); final showIncludeArchived = useState(mapSettings.includeArchived); final showRelativeDate = useState(mapSettings.relativeTime); - final ThemeData theme = Theme.of(context); + final ThemeData theme = context.themeData; Widget buildMapThemeSetting() { return SwitchListTile.adaptive( @@ -125,7 +126,7 @@ class MapSettingsDialog extends HookConsumerWidget { List getDialogActions() { return [ TextButton( - onPressed: () => Navigator.of(context).pop(), + onPressed: () => context.pop(), style: TextButton.styleFrom( backgroundColor: mapSettings.isDarkTheme ? Colors.grey[100] : Colors.grey[700], @@ -146,7 +147,7 @@ class MapSettingsDialog extends HookConsumerWidget { mapSettingsNotifier.setRelativeTime(showRelativeDate.value); mapSettingsNotifier .switchIncludeArchived(showIncludeArchived.value); - Navigator.of(context).pop(); + context.pop(); }, style: TextButton.styleFrom( backgroundColor: theme.primaryColor, @@ -178,7 +179,7 @@ class MapSettingsDialog extends HookConsumerWidget { width: double.maxFinite, child: ConstrainedBox( constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.6, + maxHeight: context.height * 0.6, ), child: ListView( shrinkWrap: true, diff --git a/mobile/lib/modules/map/views/map_page.dart b/mobile/lib/modules/map/views/map_page.dart index 74ab2ffee0..b03c13e366 100644 --- a/mobile/lib/modules/map/views/map_page.dart +++ b/mobile/lib/modules/map/views/map_page.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:math' as math; -import 'package:auto_route/auto_route.dart'; import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -12,6 +11,7 @@ import 'package:flutter_map_heatmap/flutter_map_heatmap.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:geolocator/geolocator.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/map/models/map_page_event.model.dart'; import 'package:immich_mobile/modules/map/providers/map_marker.provider.dart'; import 'package:immich_mobile/modules/map/providers/map_state.provider.dart'; @@ -24,7 +24,7 @@ import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; import 'package:immich_mobile/shared/ui/immich_toast.dart'; import 'package:immich_mobile/utils/debounce.dart'; -import 'package:immich_mobile/utils/flutter_map_extensions.dart'; +import 'package:immich_mobile/extensions/flutter_map_extensions.dart'; import 'package:immich_mobile/utils/immich_app_theme.dart'; import 'package:immich_mobile/utils/selection_handlers.dart'; import 'package:latlong2/latlong.dart'; @@ -101,7 +101,7 @@ class MapPageState extends ConsumerState { } void openAssetInViewer(Asset asset) { - AutoRouter.of(context).push( + context.autoPush( GalleryViewerRoute( initialIndex: 0, loadAsset: (index) => asset, @@ -474,8 +474,8 @@ class MapPageState extends ConsumerState { ), if (showLoadingIndicator.value || isLoading) Positioned( - top: MediaQuery.of(context).size.height * 0.35, - left: MediaQuery.of(context).size.width * 0.425, + top: context.height * 0.35, + left: context.width * 0.425, child: const ImmichLoadingIndicator(), ), ], diff --git a/mobile/lib/modules/memories/ui/memory_lane.dart b/mobile/lib/modules/memories/ui/memory_lane.dart index dcd8036512..65f0c65258 100644 --- a/mobile/lib/modules/memories/ui/memory_lane.dart +++ b/mobile/lib/modules/memories/ui/memory_lane.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/memories/providers/memory.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/shared/ui/immich_image.dart'; @@ -31,7 +31,7 @@ class MemoryLane extends HookConsumerWidget { child: GestureDetector( onTap: () { HapticFeedback.heavyImpact(); - AutoRouter.of(context).push( + context.autoPush( MemoryRoute( memories: memories, memoryIndex: index, diff --git a/mobile/lib/modules/memories/views/memory_page.dart b/mobile/lib/modules/memories/views/memory_page.dart index a1aae5156a..ca88ed04d9 100644 --- a/mobile/lib/modules/memories/views/memory_page.dart +++ b/mobile/lib/modules/memories/views/memory_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/memories/models/memory.dart'; import 'package:immich_mobile/modules/memories/ui/memory_card.dart'; import 'package:immich_mobile/shared/models/asset.dart'; @@ -182,14 +182,14 @@ class MemoryPage extends HookConsumerWidget { currentMemory.value.assets.length; if (isLastAsset && (offset > notification.metrics.maxScrollExtent + 150)) { - AutoRouter.of(context).pop(); + context.autoPop(); return true; } } // Horizontal scroll handling if (notification.depth == 1 && (offset > notification.metrics.maxScrollExtent + 100)) { - AutoRouter.of(context).pop(); + context.autoPop(); return true; } } @@ -244,7 +244,7 @@ class MemoryPage extends HookConsumerWidget { child: MemoryCard( asset: asset, onTap: () => toNextAsset(index), - onClose: () => AutoRouter.of(context).pop(), + onClose: () => context.autoPop(), rightCornerText: assetProgress.value, title: memories[mIndex].title, showTitle: index == 0, diff --git a/mobile/lib/modules/onboarding/views/permission_onboarding_page.dart b/mobile/lib/modules/onboarding/views/permission_onboarding_page.dart index efbbc78a3c..e1fd05dabb 100644 --- a/mobile/lib/modules/onboarding/views/permission_onboarding_page.dart +++ b/mobile/lib/modules/onboarding/views/permission_onboarding_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart'; @@ -11,7 +11,6 @@ import 'package:immich_mobile/shared/ui/immich_title_text.dart'; import 'package:permission_handler/permission_handler.dart'; class PermissionOnboardingPage extends HookConsumerWidget { - const PermissionOnboardingPage({super.key}); @override @@ -21,13 +20,10 @@ class PermissionOnboardingPage extends HookConsumerWidget { // Navigate to the main Tab Controller when permission is granted void goToHome() { // Resume backup (if enable) then navigate - ref.watch(backupProvider.notifier).resumeBackup() - .catchError((error) { + ref.watch(backupProvider.notifier).resumeBackup().catchError((error) { debugPrint('PermissionOnboardingPage error: $error'); }); - AutoRouter.of(context).replace( - const TabControllerRoute(), - ); + context.autoReplace(const TabControllerRoute()); } // When the permission is denied, we show a request permission page @@ -38,21 +34,21 @@ class PermissionOnboardingPage extends HookConsumerWidget { children: [ Text( 'permission_onboarding_request', - style: Theme.of(context).textTheme.titleMedium, + style: context.textTheme.titleMedium, textAlign: TextAlign.center, ).tr(), const SizedBox(height: 18), ElevatedButton( onPressed: () => ref - .read(galleryPermissionNotifier.notifier) - .requestGalleryPermission() - .then((permission) async { - if (permission.isGranted) { - // If permission is limited, we will show the limited - // permission page - goToHome(); - } - }), + .read(galleryPermissionNotifier.notifier) + .requestGalleryPermission() + .then((permission) async { + if (permission.isGranted) { + // If permission is limited, we will show the limited + // permission page + goToHome(); + } + }), child: const Text( 'permission_onboarding_grant_permission', ).tr(), @@ -70,7 +66,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { children: [ Text( 'permission_onboarding_permission_granted', - style: Theme.of(context).textTheme.titleMedium, + style: context.textTheme.titleMedium, textAlign: TextAlign.center, ).tr(), const SizedBox(height: 18), @@ -90,14 +86,15 @@ class PermissionOnboardingPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.warning_outlined, + const Icon( + Icons.warning_outlined, color: Colors.yellow, size: 48, ), const SizedBox(height: 8), Text( 'permission_onboarding_permission_limited', - style: Theme.of(context).textTheme.titleMedium, + style: context.textTheme.titleMedium, textAlign: TextAlign.center, ).tr(), const SizedBox(height: 18), @@ -123,14 +120,15 @@ class PermissionOnboardingPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.warning_outlined, + const Icon( + Icons.warning_outlined, color: Colors.red, size: 48, ), const SizedBox(height: 8), Text( 'permission_onboarding_permission_denied', - style: Theme.of(context).textTheme.titleMedium, + style: context.textTheme.titleMedium, textAlign: TextAlign.center, ).tr(), const SizedBox(height: 18), @@ -186,13 +184,10 @@ class PermissionOnboardingPage extends HookConsumerWidget { child: const Text('permission_onboarding_log_out').tr(), onPressed: () { ref.read(authenticationProvider.notifier).logout(); - AutoRouter.of(context).replace( - const LoginRoute(), - ); + context.autoReplace(const LoginRoute()); }, ), ], - ), ), ), diff --git a/mobile/lib/modules/partner/ui/partner_list.dart b/mobile/lib/modules/partner/ui/partner_list.dart index 64db045b15..b1111fdcf6 100644 --- a/mobile/lib/modules/partner/ui/partner_list.dart +++ b/mobile/lib/modules/partner/ui/partner_list.dart @@ -1,6 +1,6 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/shared/models/user.dart'; import 'package:immich_mobile/shared/ui/user_avatar.dart'; @@ -28,10 +28,10 @@ class PartnerList extends HookConsumerWidget { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), - onTap: () => AutoRouter.of(context).push(PartnerDetailRoute(partner: p)), + onTap: () => context.autoPush((PartnerDetailRoute(partner: p))), ); } } diff --git a/mobile/lib/modules/search/ui/curated_people_row.dart b/mobile/lib/modules/search/ui/curated_people_row.dart index 8a65c25f79..aec6188d4a 100644 --- a/mobile/lib/modules/search/ui/curated_people_row.dart +++ b/mobile/lib/modules/search/ui/curated_people_row.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart'; import 'package:immich_mobile/shared/models/store.dart'; @@ -85,7 +86,7 @@ class CuratedPeopleRow extends StatelessWidget { "Add name", style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), diff --git a/mobile/lib/modules/search/ui/curated_places_row.dart b/mobile/lib/modules/search/ui/curated_places_row.dart index 000c9f4a12..9c6324daab 100644 --- a/mobile/lib/modules/search/ui/curated_places_row.dart +++ b/mobile/lib/modules/search/ui/curated_places_row.dart @@ -1,5 +1,5 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/map/ui/map_thumbnail.dart'; import 'package:immich_mobile/modules/search/ui/curated_row.dart'; import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart'; @@ -25,7 +25,7 @@ class CuratedPlacesRow extends CuratedRow { final int actualContentIndex = isMapEnabled ? 1 : 0; Widget buildMapThumbnail() { return GestureDetector( - onTap: () => AutoRouter.of(context).push( + onTap: () => context.autoPush( const MapRoute(), ), child: SizedBox( @@ -43,7 +43,7 @@ class CuratedPlacesRow extends CuratedRow { ), height: imageSize, showAttribution: false, - isDarkTheme: Theme.of(context).brightness == Brightness.dark, + isDarkTheme: context.isDarkTheme, ), ), Padding( diff --git a/mobile/lib/modules/search/ui/explore_grid.dart b/mobile/lib/modules/search/ui/explore_grid.dart index 12f8ec6a1e..984f65a401 100644 --- a/mobile/lib/modules/search/ui/explore_grid.dart +++ b/mobile/lib/modules/search/ui/explore_grid.dart @@ -1,5 +1,5 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -50,13 +50,13 @@ class ExploreGrid extends StatelessWidget { borderRadius: 0, onTap: () { isPeople - ? AutoRouter.of(context).push( + ? context.autoPush( PersonResultRoute( personId: content.id, personName: content.label, ), ) - : AutoRouter.of(context).push( + : context.autoPush( SearchResultRoute(searchTerm: 'm:${content.label}'), ); }, diff --git a/mobile/lib/modules/search/ui/immich_search_bar.dart b/mobile/lib/modules/search/ui/immich_search_bar.dart index 5ab4bc9644..d34a78a77a 100644 --- a/mobile/lib/modules/search/ui/immich_search_bar.dart +++ b/mobile/lib/modules/search/ui/immich_search_bar.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; class ImmichSearchBar extends HookConsumerWidget @@ -57,11 +58,11 @@ class ImmichSearchBar extends HookConsumerWidget }, decoration: InputDecoration( hintText: 'search_bar_hint'.tr(), - hintStyle: Theme.of(context).textTheme.titleSmall?.copyWith( - color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5), - fontWeight: FontWeight.w500, - fontSize: 14, - ), + hintStyle: context.textTheme.titleSmall?.copyWith( + color: context.themeData.colorScheme.onSurface.withOpacity(0.5), + fontWeight: FontWeight.w500, + fontSize: 14, + ), enabledBorder: const UnderlineInputBorder( borderSide: BorderSide(color: Colors.transparent), ), diff --git a/mobile/lib/modules/search/ui/person_name_edit_form.dart b/mobile/lib/modules/search/ui/person_name_edit_form.dart index f60824b5fb..0dbb03825d 100644 --- a/mobile/lib/modules/search/ui/person_name_edit_form.dart +++ b/mobile/lib/modules/search/ui/person_name_edit_form.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/providers/people.provider.dart'; class PersonNameEditFormResult { @@ -71,7 +72,7 @@ class PersonNameEditForm extends HookConsumerWidget { child: Text( "Save", style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ), diff --git a/mobile/lib/modules/search/ui/search_row_title.dart b/mobile/lib/modules/search/ui/search_row_title.dart index 5448874e30..df0f902f98 100644 --- a/mobile/lib/modules/search/ui/search_row_title.dart +++ b/mobile/lib/modules/search/ui/search_row_title.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class SearchRowTitle extends StatelessWidget { final Function() onViewAllPressed; @@ -26,14 +27,14 @@ class SearchRowTitle extends StatelessWidget { children: [ Text( title, - style: Theme.of(context).textTheme.titleSmall, + style: context.textTheme.titleSmall, ), TextButton( onPressed: onViewAllPressed, child: Text( 'search_page_view_all_button', style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14.0, ), diff --git a/mobile/lib/modules/search/ui/search_suggestion_list.dart b/mobile/lib/modules/search/ui/search_suggestion_list.dart index b66be410fd..b5f5029c30 100644 --- a/mobile/lib/modules/search/ui/search_suggestion_list.dart +++ b/mobile/lib/modules/search/ui/search_suggestion_list.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; class SearchSuggestionList extends ConsumerWidget { @@ -13,17 +14,16 @@ class SearchSuggestionList extends ConsumerWidget { final searchTerm = ref.watch(searchPageStateProvider).searchTerm; final searchSuggestion = ref.watch(searchPageStateProvider).searchSuggestion; - var isDarkTheme = Theme.of(context).brightness == Brightness.dark; return Container( color: searchTerm.isEmpty ? Colors.black.withOpacity(0.5) - : Theme.of(context).scaffoldBackgroundColor, + : context.scaffoldBackgroundColor, child: CustomScrollView( slivers: [ SliverToBoxAdapter( child: Container( - color: isDarkTheme ? Colors.grey[800] : Colors.grey[100], + color: context.isDarkTheme ? Colors.grey[800] : Colors.grey[100], child: Padding( padding: const EdgeInsets.all(16.0), child: RichText( @@ -31,14 +31,14 @@ class SearchSuggestionList extends ConsumerWidget { children: [ TextSpan( text: 'search_suggestion_list_smart_search_hint_1'.tr(), - style: Theme.of(context).textTheme.bodyMedium, + style: context.textTheme.bodyMedium, ), TextSpan( text: 'search_suggestion_list_smart_search_hint_2'.tr(), - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: Theme.of(context).primaryColor, - fontWeight: FontWeight.bold, - ), + style: context.textTheme.bodyMedium?.copyWith( + color: context.primaryColor, + fontWeight: FontWeight.bold, + ), ), ], ), diff --git a/mobile/lib/modules/search/ui/thumbnail_with_info.dart b/mobile/lib/modules/search/ui/thumbnail_with_info.dart index bbb7e6834c..16714d8306 100644 --- a/mobile/lib/modules/search/ui/thumbnail_with_info.dart +++ b/mobile/lib/modules/search/ui/thumbnail_with_info.dart @@ -1,7 +1,8 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/store.dart'; -import 'package:immich_mobile/utils/capitalize.dart'; +import 'package:immich_mobile/extensions/string_extensions.dart'; // ignore: must_be_immutable class ThumbnailWithInfo extends StatelessWidget { @@ -22,8 +23,8 @@ class ThumbnailWithInfo extends StatelessWidget { @override Widget build(BuildContext context) { - var isDarkMode = Theme.of(context).brightness == Brightness.dark; - var textAndIconColor = isDarkMode ? Colors.grey[100] : Colors.grey[700]; + var textAndIconColor = + context.isDarkTheme ? Colors.grey[100] : Colors.grey[700]; return GestureDetector( onTap: () { onTap(); @@ -34,7 +35,7 @@ class ThumbnailWithInfo extends StatelessWidget { Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(borderRadius), - color: isDarkMode ? Colors.grey[900] : Colors.grey[100], + color: context.isDarkTheme ? Colors.grey[900] : Colors.grey[100], ), child: imageUrl != null ? ClipRRect( diff --git a/mobile/lib/modules/search/views/all_motion_videos_page.dart b/mobile/lib/modules/search/views/all_motion_videos_page.dart index ba990a7da4..2ad53ec456 100644 --- a/mobile/lib/modules/search/views/all_motion_videos_page.dart +++ b/mobile/lib/modules/search/views/all_motion_videos_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/search/providers/all_motion_photos.provider.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; @@ -17,7 +17,7 @@ class AllMotionPhotosPage extends HookConsumerWidget { appBar: AppBar( title: const Text('motion_photos_page_title').tr(), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), ), diff --git a/mobile/lib/modules/search/views/all_people_page.dart b/mobile/lib/modules/search/views/all_people_page.dart index d3361fc30a..3cbedc949f 100644 --- a/mobile/lib/modules/search/views/all_people_page.dart +++ b/mobile/lib/modules/search/views/all_people_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/providers/people.provider.dart'; import 'package:immich_mobile/modules/search/ui/explore_grid.dart'; @@ -19,13 +19,13 @@ class AllPeoplePage extends HookConsumerWidget { title: Text( 'all_people_page_title', style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16.0, ), ).tr(), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), ), diff --git a/mobile/lib/modules/search/views/all_videos_page.dart b/mobile/lib/modules/search/views/all_videos_page.dart index 9461869aed..beb604fd0d 100644 --- a/mobile/lib/modules/search/views/all_videos_page.dart +++ b/mobile/lib/modules/search/views/all_videos_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/search/providers/all_video_assets.provider.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; @@ -17,7 +17,7 @@ class AllVideosPage extends HookConsumerWidget { appBar: AppBar( title: const Text('all_videos_page_title').tr(), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), ), diff --git a/mobile/lib/modules/search/views/curated_location_page.dart b/mobile/lib/modules/search/views/curated_location_page.dart index 59e4c3a875..d9176e1788 100644 --- a/mobile/lib/modules/search/views/curated_location_page.dart +++ b/mobile/lib/modules/search/views/curated_location_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; import 'package:immich_mobile/modules/search/ui/explore_grid.dart'; @@ -21,13 +21,13 @@ class CuratedLocationPage extends HookConsumerWidget { title: Text( 'curated_location_page_title', style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16.0, ), ).tr(), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), ), diff --git a/mobile/lib/modules/search/views/person_result_page.dart b/mobile/lib/modules/search/views/person_result_page.dart index 01483f0bd3..bec5e4f1b2 100644 --- a/mobile/lib/modules/search/views/person_result_page.dart +++ b/mobile/lib/modules/search/views/person_result_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/search/providers/people.provider.dart'; import 'package:immich_mobile/modules/search/ui/person_name_edit_form.dart'; @@ -40,7 +40,7 @@ class PersonResultPage extends HookConsumerWidget { void buildBottomSheet() { showModalBottomSheet( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: context.scaffoldBackgroundColor, isScrollControlled: false, context: context, useSafeArea: true, @@ -73,13 +73,13 @@ class PersonResultPage extends HookConsumerWidget { children: [ Text( 'Add a name', - style: Theme.of(context).textTheme.titleSmall?.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), + style: context.textTheme.titleSmall?.copyWith( + color: context.themeData.colorScheme.secondary, + ), ), Text( 'Find them fast by name with search', - style: Theme.of(context).textTheme.labelSmall, + style: context.textTheme.labelSmall, ), ], ), @@ -91,7 +91,7 @@ class PersonResultPage extends HookConsumerWidget { children: [ Text( name.value, - style: Theme.of(context).textTheme.titleLarge, + style: context.textTheme.titleLarge, ), ], ); @@ -101,7 +101,7 @@ class PersonResultPage extends HookConsumerWidget { appBar: AppBar( title: Text(name.value), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), actions: [ diff --git a/mobile/lib/modules/search/views/recently_added_page.dart b/mobile/lib/modules/search/views/recently_added_page.dart index fc079fbfc2..55e9206152 100644 --- a/mobile/lib/modules/search/views/recently_added_page.dart +++ b/mobile/lib/modules/search/views/recently_added_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/search/providers/recently_added.provider.dart'; import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart'; @@ -17,7 +17,7 @@ class RecentlyAddedPage extends HookConsumerWidget { appBar: AppBar( title: const Text('recently_added_page_title').tr(), leading: IconButton( - onPressed: () => AutoRouter.of(context).pop(), + onPressed: () => context.autoPop(), icon: const Icon(Icons.arrow_back_ios_rounded), ), ), diff --git a/mobile/lib/modules/search/views/search_page.dart b/mobile/lib/modules/search/views/search_page.dart index 41984106df..c06db53a3f 100644 --- a/mobile/lib/modules/search/views/search_page.dart +++ b/mobile/lib/modules/search/views/search_page.dart @@ -1,9 +1,9 @@ import 'dart:math' as math; -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/providers/people.provider.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; @@ -30,15 +30,14 @@ class SearchPage extends HookConsumerWidget { final curatedPeople = ref.watch(getCuratedPeopleProvider); final isMapEnabled = ref.watch(serverInfoProvider.select((v) => v.serverFeatures.map)); - var isDarkTheme = Theme.of(context).brightness == Brightness.dark; - double imageSize = math.min(MediaQuery.of(context).size.width / 3, 150); + double imageSize = math.min(context.width / 3, 150); TextStyle categoryTitleStyle = const TextStyle( fontWeight: FontWeight.bold, fontSize: 14.0, ); - Color categoryIconColor = isDarkTheme ? Colors.white : Colors.black; + Color categoryIconColor = context.isDarkTheme ? Colors.white : Colors.black; useEffect( () { @@ -52,7 +51,7 @@ class SearchPage extends HookConsumerWidget { searchFocusNode.unfocus(); ref.watch(searchPageStateProvider.notifier).disableSearch(); - AutoRouter.of(context).push( + context.autoPush( SearchResultRoute( searchTerm: searchTerm, ), @@ -88,7 +87,7 @@ class SearchPage extends HookConsumerWidget { .take(12) .toList(), onTap: (content, index) { - AutoRouter.of(context).push( + context.autoPush( PersonResultRoute( personId: content.id, personName: content.label, @@ -121,7 +120,7 @@ class SearchPage extends HookConsumerWidget { .toList(), imageSize: imageSize, onTap: (content, index) { - AutoRouter.of(context).push( + context.autoPush( SearchResultRoute( searchTerm: 'm:${content.label}', ), @@ -148,16 +147,14 @@ class SearchPage extends HookConsumerWidget { children: [ SearchRowTitle( title: "search_page_people".tr(), - onViewAllPressed: () => AutoRouter.of(context).push( - const AllPeopleRoute(), - ), + onViewAllPressed: () => + context.autoPush(const AllPeopleRoute()), ), buildPeople(), SearchRowTitle( title: "search_page_places".tr(), - onViewAllPressed: () => AutoRouter.of(context).push( - const CuratedLocationRoute(), - ), + onViewAllPressed: () => + context.autoPush(const CuratedLocationRoute()), top: 0, ), const SizedBox(height: 10.0), @@ -167,7 +164,7 @@ class SearchPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( 'search_page_your_activity', - style: Theme.of(context).textTheme.titleSmall, + style: context.textTheme.titleSmall, ).tr(), ), ListTile( @@ -178,9 +175,7 @@ class SearchPage extends HookConsumerWidget { title: Text('search_page_favorites', style: categoryTitleStyle) .tr(), - onTap: () => AutoRouter.of(context).push( - const FavoritesRoute(), - ), + onTap: () => context.autoPush(const FavoritesRoute()), ), const CategoryDivider(), ListTile( @@ -192,16 +187,14 @@ class SearchPage extends HookConsumerWidget { 'search_page_recently_added', style: categoryTitleStyle, ).tr(), - onTap: () => AutoRouter.of(context).push( - const RecentlyAddedRoute(), - ), + onTap: () => context.autoPush(const RecentlyAddedRoute()), ), const SizedBox(height: 24.0), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( 'search_page_categories', - style: Theme.of(context).textTheme.titleSmall, + style: context.textTheme.titleSmall, ).tr(), ), ListTile( @@ -210,7 +203,7 @@ class SearchPage extends HookConsumerWidget { Icons.screenshot, color: categoryIconColor, ), - onTap: () => AutoRouter.of(context).push( + onTap: () => context.autoPush( SearchResultRoute( searchTerm: 'screenshots', ), @@ -224,7 +217,7 @@ class SearchPage extends HookConsumerWidget { Icons.photo_camera_front_outlined, color: categoryIconColor, ), - onTap: () => AutoRouter.of(context).push( + onTap: () => context.autoPush( SearchResultRoute( searchTerm: 'selfies', ), @@ -238,9 +231,7 @@ class SearchPage extends HookConsumerWidget { Icons.play_circle_outline, color: categoryIconColor, ), - onTap: () => AutoRouter.of(context).push( - const AllVideosRoute(), - ), + onTap: () => context.autoPush(const AllVideosRoute()), ), const CategoryDivider(), ListTile( @@ -252,9 +243,7 @@ class SearchPage extends HookConsumerWidget { Icons.motion_photos_on_outlined, color: categoryIconColor, ), - onTap: () => AutoRouter.of(context).push( - const AllMotionPhotosRoute(), - ), + onTap: () => context.autoPush(const AllMotionPhotosRoute()), ), ], ), diff --git a/mobile/lib/modules/search/views/search_result_page.dart b/mobile/lib/modules/search/views/search_result_page.dart index d6b1ea9a9e..fd16c2c06b 100644 --- a/mobile/lib/modules/search/views/search_result_page.dart +++ b/mobile/lib/modules/search/views/search_result_page.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/search/providers/search_page_state.provider.dart'; import 'package:immich_mobile/modules/search/providers/search_result_page.provider.dart'; @@ -38,7 +38,6 @@ class SearchResultPage extends HookConsumerWidget { final searchTermController = useTextEditingController(text: ""); final isNewSearch = useState(false); final currentSearchTerm = useState(searchTerm); - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; final isDisplayDateGroup = useState(true); FocusNode? searchFocusNode; @@ -112,8 +111,9 @@ class SearchResultPage extends HookConsumerWidget { hintStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 16.0, - color: - isDarkTheme ? Colors.grey[500] : Colors.black.withOpacity(0.5), + color: context.isDarkTheme + ? Colors.grey[500] + : Colors.black.withOpacity(0.5), ), ), ); @@ -130,7 +130,7 @@ class SearchResultPage extends HookConsumerWidget { Text( currentSearchTerm.value, style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontSize: 13, fontWeight: FontWeight.bold, ), @@ -138,12 +138,12 @@ class SearchResultPage extends HookConsumerWidget { ), Icon( Icons.close_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, size: 20, ), ], ), - backgroundColor: Theme.of(context).primaryColor.withAlpha(50), + backgroundColor: context.primaryColor.withAlpha(50), ); } @@ -185,7 +185,7 @@ class SearchResultPage extends HookConsumerWidget { if (isNewSearch.value) { isNewSearch.value = false; } else { - AutoRouter.of(context).pop(true); + context.autoPop(true); } }, icon: const Icon(Icons.arrow_back_ios_rounded), diff --git a/mobile/lib/modules/settings/ui/advanced_settings/advanced_settings.dart b/mobile/lib/modules/settings/ui/advanced_settings/advanced_settings.dart index 3c8d47d1e0..83bf4bb948 100644 --- a/mobile/lib/modules/settings/ui/advanced_settings/advanced_settings.dart +++ b/mobile/lib/modules/settings/ui/advanced_settings/advanced_settings.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' show useEffect, useState; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; @@ -43,7 +44,7 @@ class AdvancedSettings extends HookConsumerWidget { final logLevel = Level.LEVELS[levelId.value].name; return ExpansionTile( - textColor: Theme.of(context).primaryColor, + textColor: context.primaryColor, title: const Text( "advanced_settings_tile_title", style: TextStyle( @@ -86,7 +87,7 @@ class AdvancedSettings extends HookConsumerWidget { min: 1.0, divisions: 7, label: logLevel, - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, ), ), SettingsSwitchListTile( diff --git a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart index 8ff719da33..856935ccb5 100644 --- a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart +++ b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart'; import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; @@ -50,12 +51,10 @@ class LayoutSettings extends HookConsumerWidget { return Column( children: [ SwitchListTile.adaptive( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( "asset_list_layout_settings_dynamic_layout_title", - style: Theme.of(context) - .textTheme - .labelLarge + style: context.textTheme.labelLarge ?.copyWith(fontWeight: FontWeight.bold), ).tr(), onChanged: switchChanged, @@ -75,10 +74,10 @@ class LayoutSettings extends HookConsumerWidget { ).tr(), ), RadioListTile( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( "asset_list_layout_settings_group_by_month_day", - style: Theme.of(context).textTheme.labelLarge, + style: context.textTheme.labelLarge, ).tr(), value: GroupAssetsBy.day, groupValue: groupBy.value, @@ -86,10 +85,10 @@ class LayoutSettings extends HookConsumerWidget { controlAffinity: ListTileControlAffinity.trailing, ), RadioListTile( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( "asset_list_layout_settings_group_by_month", - style: Theme.of(context).textTheme.labelLarge, + style: context.textTheme.labelLarge, ).tr(), value: GroupAssetsBy.month, groupValue: groupBy.value, @@ -97,10 +96,10 @@ class LayoutSettings extends HookConsumerWidget { controlAffinity: ListTileControlAffinity.trailing, ), RadioListTile( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( "asset_list_layout_settings_group_automatically", - style: Theme.of(context).textTheme.labelLarge, + style: context.textTheme.labelLarge, ).tr(), value: GroupAssetsBy.auto, groupValue: groupBy.value, diff --git a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_settings.dart b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_settings.dart index ef7afb0432..a7a2f8b958 100644 --- a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_settings.dart +++ b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_settings.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart'; import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart'; import 'asset_list_tiles_per_row.dart'; @@ -12,7 +13,7 @@ class AssetListSettings extends StatelessWidget { @override Widget build(BuildContext context) { return ExpansionTile( - textColor: Theme.of(context).primaryColor, + textColor: context.primaryColor, title: const Text( 'asset_list_settings_title', style: TextStyle( diff --git a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart index ae0e021482..50896fe0b6 100644 --- a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart +++ b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; @@ -33,13 +34,11 @@ class StorageIndicator extends HookConsumerWidget { ); return SwitchListTile.adaptive( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( "theme_setting_asset_list_storage_indicator_title", - style: Theme.of(context) - .textTheme - .labelLarge - ?.copyWith(fontWeight: FontWeight.bold), + style: + context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold), ).tr(), onChanged: switchChanged, value: showStorageIndicator.value, diff --git a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_tiles_per_row.dart b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_tiles_per_row.dart index 89ac79133a..5693e2a5fc 100644 --- a/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_tiles_per_row.dart +++ b/mobile/lib/modules/settings/ui/asset_list_settings/asset_list_tiles_per_row.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; @@ -51,7 +52,7 @@ class TilesPerRow extends HookConsumerWidget { max: 6, divisions: 4, label: "${itemsValue.value.toInt()}", - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, ), ], ); diff --git a/mobile/lib/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart b/mobile/lib/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart index 123c7cd00d..d0b86a186a 100644 --- a/mobile/lib/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart +++ b/mobile/lib/modules/settings/ui/image_viewer_quality_setting/image_viewer_quality_setting.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.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:immich_mobile/modules/settings/ui/settings_switch_list_tile.dart'; @@ -26,7 +27,7 @@ class ImageViewerQualitySetting extends HookConsumerWidget { ); return ExpansionTile( - textColor: Theme.of(context).primaryColor, + textColor: context.primaryColor, title: const Text( 'theme_setting_image_viewer_quality_title', style: TextStyle( diff --git a/mobile/lib/modules/settings/ui/local_storage_settings/local_storage_settings.dart b/mobile/lib/modules/settings/ui/local_storage_settings/local_storage_settings.dart index a9321a56ef..cd753de31f 100644 --- a/mobile/lib/modules/settings/ui/local_storage_settings/local_storage_settings.dart +++ b/mobile/lib/modules/settings/ui/local_storage_settings/local_storage_settings.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' show useEffect, useState; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/models/duplicated_asset.model.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/shared/providers/db.provider.dart'; @@ -25,7 +26,7 @@ class LocalStorageSettings extends HookConsumerWidget { } return ExpansionTile( - textColor: Theme.of(context).primaryColor, + textColor: context.primaryColor, title: const Text( "cache_settings_tile_title", style: TextStyle( @@ -42,9 +43,7 @@ class LocalStorageSettings extends HookConsumerWidget { ListTile( title: Text( "Duplicated Assets (${cacheItemCount.value})", - style: Theme.of(context) - .textTheme - .labelLarge + style: context.textTheme.labelLarge ?.copyWith(fontWeight: FontWeight.bold), ).tr(), subtitle: const Text( diff --git a/mobile/lib/modules/settings/ui/notification_setting/notification_setting.dart b/mobile/lib/modules/settings/ui/notification_setting/notification_setting.dart index 5f00cd0d95..747c541d45 100644 --- a/mobile/lib/modules/settings/ui/notification_setting/notification_setting.dart +++ b/mobile/lib/modules/settings/ui/notification_setting/notification_setting.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; import 'package:immich_mobile/modules/settings/providers/notification_permission.provider.dart'; import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; @@ -49,12 +50,12 @@ class NotificationSetting extends HookConsumerWidget { actions: [ TextButton( child: const Text('notification_permission_dialog_cancel').tr(), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => context.pop(), ), TextButton( child: const Text('notification_permission_dialog_settings').tr(), onPressed: () { - Navigator.of(context).pop(); + context.pop(); openAppSettings(); }, ), @@ -65,7 +66,7 @@ class NotificationSetting extends HookConsumerWidget { final String formattedValue = _formatSliderValue(sliderValue.value); return ExpansionTile( - textColor: Theme.of(context).primaryColor, + textColor: context.primaryColor, title: const Text( 'setting_notifications_title', style: TextStyle( @@ -84,9 +85,7 @@ class NotificationSetting extends HookConsumerWidget { leading: const Icon(Icons.notifications_outlined), title: Text( 'notification_permission_list_tile_title', - style: Theme.of(context) - .textTheme - .labelLarge + style: context.textTheme.labelLarge ?.copyWith(fontWeight: FontWeight.bold), ).tr(), subtitle: Column( @@ -94,7 +93,7 @@ class NotificationSetting extends HookConsumerWidget { children: [ Text( 'notification_permission_list_tile_content', - style: Theme.of(context).textTheme.labelMedium, + style: context.textTheme.labelMedium, ).tr(), const SizedBox(height: 8), ElevatedButton( @@ -149,7 +148,7 @@ class NotificationSetting extends HookConsumerWidget { max: 5.0, divisions: 5, label: formattedValue, - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, ), ), ], diff --git a/mobile/lib/modules/settings/ui/settings_switch_list_tile.dart b/mobile/lib/modules/settings/ui/settings_switch_list_tile.dart index c6fff19f69..e66e6319c9 100644 --- a/mobile/lib/modules/settings/ui/settings_switch_list_tile.dart +++ b/mobile/lib/modules/settings/ui/settings_switch_list_tile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; class SettingsSwitchListTile extends StatelessWidget { @@ -23,7 +24,7 @@ class SettingsSwitchListTile extends StatelessWidget { @override Widget build(BuildContext context) { return SwitchListTile.adaptive( - selectedTileColor: enabled ? null : Theme.of(context).disabledColor, + selectedTileColor: enabled ? null : context.themeData.disabledColor, value: valueNotifier.value, onChanged: (bool value) { if (enabled) { @@ -34,16 +35,13 @@ class SettingsSwitchListTile extends StatelessWidget { onChanged!(value); } }, - activeColor: enabled - ? Theme.of(context).primaryColor - : Theme.of(context).disabledColor, + activeColor: + enabled ? context.primaryColor : context.themeData.disabledColor, dense: true, title: Text( title, - style: Theme.of(context) - .textTheme - .labelLarge - ?.copyWith(fontWeight: FontWeight.bold), + style: + context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold), ), subtitle: subtitle != null ? Text(subtitle!) : null, ); diff --git a/mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart b/mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart index 2e3b7134cc..fd25873cd8 100644 --- a/mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart +++ b/mobile/lib/modules/settings/ui/theme_setting/theme_setting.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.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:immich_mobile/utils/immich_app_theme.dart'; @@ -24,7 +25,7 @@ class ThemeSetting extends HookConsumerWidget { ); return ExpansionTile( - textColor: Theme.of(context).primaryColor, + textColor: context.primaryColor, title: const Text( 'theme_setting_theme_title', style: TextStyle( @@ -39,12 +40,10 @@ class ThemeSetting extends HookConsumerWidget { ).tr(), children: [ SwitchListTile.adaptive( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( 'theme_setting_system_theme_switch', - style: Theme.of(context) - .textTheme - .labelLarge + style: context.textTheme.labelLarge ?.copyWith(fontWeight: FontWeight.bold), ).tr(), value: currentTheme.value == ThemeMode.system, @@ -77,12 +76,10 @@ class ThemeSetting extends HookConsumerWidget { ), if (currentTheme.value != ThemeMode.system) SwitchListTile.adaptive( - activeColor: Theme.of(context).primaryColor, + activeColor: context.primaryColor, title: Text( 'theme_setting_dark_mode_switch', - style: Theme.of(context) - .textTheme - .labelLarge + style: context.textTheme.labelLarge ?.copyWith(fontWeight: FontWeight.bold), ).tr(), value: ref.watch(immichThemeProvider) == ThemeMode.dark, diff --git a/mobile/lib/modules/shared_link/ui/shared_link_item.dart b/mobile/lib/modules/shared_link/ui/shared_link_item.dart index 907006f77d..5b14c4ab11 100644 --- a/mobile/lib/modules/shared_link/ui/shared_link_item.dart +++ b/mobile/lib/modules/shared_link/ui/shared_link_item.dart @@ -1,9 +1,9 @@ import 'dart:math' as math; -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart'; import 'package:immich_mobile/modules/shared_link/models/shared_link.dart'; import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart'; @@ -58,12 +58,12 @@ class SharedLinkItem extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final themeData = Theme.of(context); + final themeData = context.themeData; final isDarkMode = themeData.brightness == Brightness.dark; final thumbnailUrl = sharedLink.thumbAssetId != null ? getThumbnailUrlForRemoteId(sharedLink.thumbAssetId!) : null; - final imageSize = math.min(MediaQuery.of(context).size.width / 4, 100.0); + final imageSize = math.min(context.width / 4, 100.0); void copyShareLinkToClipboard() { final serverUrl = getServerUrl(); @@ -194,8 +194,8 @@ class SharedLinkItem extends ConsumerWidget { tapTargetSize: MaterialTapTargetSize.shrinkWrap, // the '2023' part ), - onPressed: () => AutoRouter.of(context) - .push(SharedLinkEditRoute(existingLink: sharedLink)), + onPressed: () => + context.autoPush(SharedLinkEditRoute(existingLink: sharedLink)), ), IconButton( splashRadius: 25, diff --git a/mobile/lib/modules/shared_link/views/shared_link_edit_page.dart b/mobile/lib/modules/shared_link/views/shared_link_edit_page.dart index 27178917ab..71f2648c0a 100644 --- a/mobile/lib/modules/shared_link/views/shared_link_edit_page.dart +++ b/mobile/lib/modules/shared_link/views/shared_link_edit_page.dart @@ -1,10 +1,10 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/shared_link/models/shared_link.dart'; import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart'; import 'package:immich_mobile/modules/shared_link/services/shared_link.service.dart'; @@ -26,7 +26,7 @@ class SharedLinkEditPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { const padding = 20.0; - final themeData = Theme.of(context); + final themeData = context.themeData; final descriptionController = useTextEditingController(text: existingLink?.description ?? ""); final descriptionFocusNode = useFocusNode(); @@ -215,7 +215,7 @@ class SharedLinkEditPage extends HookConsumerWidget { ).tr(), enableSearch: false, enableFilter: false, - width: MediaQuery.of(context).size.width - 40, + width: context.width - 40, initialSelection: expiryAfter.value, enabled: newShareLink.value.isEmpty && (existingLink == null || editExpiry.value), @@ -307,7 +307,7 @@ class SharedLinkEditPage extends HookConsumerWidget { alignment: Alignment.bottomRight, child: ElevatedButton( onPressed: () { - AutoRouter.of(context).pop(); + context.autoPop(); }, child: const Text( "Done", @@ -403,7 +403,7 @@ class SharedLinkEditPage extends HookConsumerWidget { changeExpiry: changeExpiry, ); ref.invalidate(sharedLinksStateProvider); - AutoRouter.of(context).pop(); + context.autoPop(); } return Scaffold( diff --git a/mobile/lib/modules/shared_link/views/shared_link_page.dart b/mobile/lib/modules/shared_link/views/shared_link_page.dart index 19bede4bdc..04f57a48b3 100644 --- a/mobile/lib/modules/shared_link/views/shared_link_page.dart +++ b/mobile/lib/modules/shared_link/views/shared_link_page.dart @@ -2,6 +2,7 @@ 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/shared_link/models/shared_link.dart'; import 'package:immich_mobile/modules/shared_link/providers/shared_link.provider.dart'; import 'package:immich_mobile/modules/shared_link/ui/shared_link_item.dart'; @@ -52,7 +53,7 @@ class SharedLinkPage extends HookConsumerWidget { child: Icon( Icons.link_off, size: 100, - color: Theme.of(context).iconTheme.color?.withOpacity(0.5), + color: context.themeData.iconTheme.color?.withOpacity(0.5), ), ), ), diff --git a/mobile/lib/modules/trash/views/trash_page.dart b/mobile/lib/modules/trash/views/trash_page.dart index 8c128b61dc..ad365189ea 100644 --- a/mobile/lib/modules/trash/views/trash_page.dart +++ b/mobile/lib/modules/trash/views/trash_page.dart @@ -1,9 +1,9 @@ -import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; import 'package:immich_mobile/modules/home/ui/delete_dialog.dart'; import 'package:immich_mobile/modules/trash/providers/trashed_asset.provider.dart'; @@ -137,7 +137,7 @@ class TrashPage extends HookConsumerWidget { return AppBar( leading: IconButton( onPressed: !selectionEnabledHook.value - ? () => AutoRouter.of(context).pop() + ? () => context.autoPop() : () { selectionEnabledHook.value = false; selection.value = {}; @@ -177,7 +177,7 @@ class TrashPage extends HookConsumerWidget { child: SizedBox( height: 64, child: Container( - color: Theme.of(context).canvasColor, + color: context.themeData.canvasColor, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ diff --git a/mobile/lib/shared/models/asset.dart b/mobile/lib/shared/models/asset.dart index e1a3f24cd1..d1a985e5f4 100644 --- a/mobile/lib/shared/models/asset.dart +++ b/mobile/lib/shared/models/asset.dart @@ -6,7 +6,7 @@ import 'package:immich_mobile/utils/hash.dart'; import 'package:isar/isar.dart'; import 'package:openapi/api.dart'; import 'package:photo_manager/photo_manager.dart'; -import 'package:immich_mobile/utils/builtin_extensions.dart'; +import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:path/path.dart' as p; part 'asset.g.dart'; diff --git a/mobile/lib/shared/services/hash.service.dart b/mobile/lib/shared/services/hash.service.dart index ee272cf5ff..914c8bc287 100644 --- a/mobile/lib/shared/services/hash.service.dart +++ b/mobile/lib/shared/services/hash.service.dart @@ -10,7 +10,7 @@ import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/models/device_asset.dart'; import 'package:immich_mobile/shared/models/ios_device_asset.dart'; import 'package:immich_mobile/shared/providers/db.provider.dart'; -import 'package:immich_mobile/utils/builtin_extensions.dart'; +import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:isar/isar.dart'; import 'package:logging/logging.dart'; import 'package:photo_manager/photo_manager.dart'; diff --git a/mobile/lib/shared/services/sync.service.dart b/mobile/lib/shared/services/sync.service.dart index 19fc076e48..fb9888258d 100644 --- a/mobile/lib/shared/services/sync.service.dart +++ b/mobile/lib/shared/services/sync.service.dart @@ -11,7 +11,7 @@ import 'package:immich_mobile/shared/models/user.dart'; import 'package:immich_mobile/shared/providers/db.provider.dart'; import 'package:immich_mobile/shared/services/hash.service.dart'; import 'package:immich_mobile/utils/async_mutex.dart'; -import 'package:immich_mobile/utils/builtin_extensions.dart'; +import 'package:immich_mobile/extensions/collection_extensions.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:isar/isar.dart'; import 'package:logging/logging.dart'; diff --git a/mobile/lib/shared/ui/app_bar_dialog/app_bar_dialog.dart b/mobile/lib/shared/ui/app_bar_dialog/app_bar_dialog.dart index ede1138379..60ee135b89 100644 --- a/mobile/lib/shared/ui/app_bar_dialog/app_bar_dialog.dart +++ b/mobile/lib/shared/ui/app_bar_dialog/app_bar_dialog.dart @@ -1,8 +1,8 @@ -import 'package:auto_route/auto_route.dart'; 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/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/models/backup_state.model.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/modules/backup/providers/manual_upload.provider.dart'; @@ -22,9 +22,8 @@ class ImmichAppBarDialog extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { BackUpState backupState = ref.watch(backupProvider); - final theme = Theme.of(context); - bool isDarkTheme = theme.brightness == Brightness.dark; - bool isHorizontal = MediaQuery.of(context).size.width > 600; + final theme = context.themeData; + bool isHorizontal = !context.isMobile; final horizontalPadding = isHorizontal ? 100.0 : 20.0; final user = ref.watch(currentUserProvider); @@ -40,7 +39,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { return Row( children: [ InkWell( - onTap: () => Navigator.of(context).pop(), + onTap: () => context.pop(), child: const Icon( Icons.close, size: 20, @@ -54,7 +53,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { style: TextStyle( fontFamily: 'SnowburstOne', fontWeight: FontWeight.bold, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontSize: 15, ), ), @@ -90,7 +89,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { return buildActionButton( Icons.settings_rounded, "profile_drawer_settings", - () => AutoRouter.of(context).push(const SettingsRoute()), + () => context.autoPush(const SettingsRoute()), ); } @@ -98,7 +97,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { return buildActionButton( Icons.assignment_outlined, "profile_drawer_app_logs", - () => AutoRouter.of(context).push(const AppLogRoute()), + () => context.autoPush(const AppLogRoute()), ); } @@ -121,7 +120,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { ref.watch(backupProvider.notifier).cancelBackup(); ref.watch(assetProvider.notifier).clearAllAsset(); ref.watch(websocketProvider.notifier).disconnect(); - AutoRouter.of(context).replace(const LoginRoute()); + context.autoReplace(const LoginRoute()); }, ); }, @@ -136,8 +135,8 @@ class ImmichAppBarDialog extends HookConsumerWidget { child: Container( padding: const EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( - color: isDarkTheme - ? Theme.of(context).scaffoldBackgroundColor + color: context.isDarkTheme + ? context.scaffoldBackgroundColor : const Color.fromARGB(255, 225, 229, 240), ), child: ListTile( @@ -191,7 +190,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { children: [ InkWell( onTap: () { - Navigator.of(context).pop(); + context.pop(); launchUrl( Uri.parse('https://immich.app'), mode: LaunchMode.externalApplication, @@ -199,7 +198,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { }, child: Text( "profile_drawer_documentation", - style: Theme.of(context).textTheme.bodySmall, + style: context.textTheme.bodySmall, ).tr(), ), const SizedBox( @@ -211,7 +210,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { ), InkWell( onTap: () { - Navigator.of(context).pop(); + context.pop(); launchUrl( Uri.parse('https://github.com/immich-app/immich'), mode: LaunchMode.externalApplication, @@ -219,7 +218,7 @@ class ImmichAppBarDialog extends HookConsumerWidget { }, child: Text( "profile_drawer_github", - style: Theme.of(context).textTheme.bodySmall, + style: context.textTheme.bodySmall, ).tr(), ), ], diff --git a/mobile/lib/shared/ui/app_bar_dialog/app_bar_profile_info.dart b/mobile/lib/shared/ui/app_bar_dialog/app_bar_profile_info.dart index d58699d5c0..4f1f7db86d 100644 --- a/mobile/lib/shared/ui/app_bar_dialog/app_bar_profile_info.dart +++ b/mobile/lib/shared/ui/app_bar_dialog/app_bar_profile_info.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/home/providers/upload_profile_image.provider.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/ui/user_circle_avatar.dart'; @@ -18,7 +19,6 @@ class AppBarProfileInfoBox extends HookConsumerWidget { AuthenticationState authState = ref.watch(authenticationProvider); final uploadProfileImageStatus = ref.watch(uploadProfileImageProvider).status; - final isDarkMode = Theme.of(context).brightness == Brightness.dark; final user = Store.tryGet(StoreKey.currentUser); buildUserProfileImage() { @@ -91,8 +91,8 @@ class AppBarProfileInfoBox extends HookConsumerWidget { child: Container( width: double.infinity, decoration: BoxDecoration( - color: Theme.of(context).brightness == Brightness.dark - ? Theme.of(context).scaffoldBackgroundColor + color: context.isDarkTheme + ? context.scaffoldBackgroundColor : const Color.fromARGB(255, 225, 229, 240), borderRadius: const BorderRadius.only( topLeft: Radius.circular(10), @@ -111,7 +111,9 @@ class AppBarProfileInfoBox extends HookConsumerWidget { bottom: -5, right: -8, child: Material( - color: isDarkMode ? Colors.blueGrey[800] : Colors.white, + color: context.isDarkTheme + ? Colors.blueGrey[800] + : Colors.white, elevation: 3, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50.0), @@ -120,7 +122,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget { padding: const EdgeInsets.all(5.0), child: Icon( Icons.camera_alt_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, size: 14, ), ), @@ -132,16 +134,16 @@ class AppBarProfileInfoBox extends HookConsumerWidget { title: Text( "${authState.firstName} ${authState.lastName}", style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16, ), ), subtitle: Text( authState.userEmail, - style: Theme.of(context).textTheme.labelMedium?.copyWith( - fontSize: 12, - ), + style: context.textTheme.labelMedium?.copyWith( + fontSize: 12, + ), ), ), ), diff --git a/mobile/lib/shared/ui/app_bar_dialog/app_bar_server_info.dart b/mobile/lib/shared/ui/app_bar_dialog/app_bar_server_info.dart index fa4a73536e..fef9e1daab 100644 --- a/mobile/lib/shared/ui/app_bar_dialog/app_bar_server_info.dart +++ b/mobile/lib/shared/ui/app_bar_dialog/app_bar_server_info.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/server_info/server_info.model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:immich_mobile/shared/providers/server_info.provider.dart'; @@ -39,8 +40,8 @@ class AppBarServerInfo extends HookConsumerWidget { padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0), child: Container( decoration: BoxDecoration( - color: Theme.of(context).brightness == Brightness.dark - ? Theme.of(context).scaffoldBackgroundColor + color: context.isDarkTheme + ? context.scaffoldBackgroundColor : const Color.fromARGB(255, 225, 229, 240), borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(10), @@ -61,7 +62,7 @@ class AppBarServerInfo extends HookConsumerWidget { textAlign: TextAlign.center, style: TextStyle( fontSize: 11, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.w600, ), ), @@ -83,7 +84,7 @@ class AppBarServerInfo extends HookConsumerWidget { "server_info_box_app_version".tr(), style: TextStyle( fontSize: 11, - color: Theme.of(context).textTheme.labelSmall?.color, + color: context.textTheme.labelSmall?.color, fontWeight: FontWeight.bold, ), ), @@ -97,10 +98,7 @@ class AppBarServerInfo extends HookConsumerWidget { "${appInfo.value["version"]} build.${appInfo.value["buildNumber"]}", style: TextStyle( fontSize: 11, - color: Theme.of(context) - .textTheme - .labelSmall - ?.color + color: context.textTheme.labelSmall?.color ?.withOpacity(0.5), fontWeight: FontWeight.bold, ), @@ -126,7 +124,7 @@ class AppBarServerInfo extends HookConsumerWidget { "server_info_box_server_version".tr(), style: TextStyle( fontSize: 11, - color: Theme.of(context).textTheme.labelSmall?.color, + color: context.textTheme.labelSmall?.color, fontWeight: FontWeight.bold, ), ), @@ -142,10 +140,7 @@ class AppBarServerInfo extends HookConsumerWidget { : "?", style: TextStyle( fontSize: 11, - color: Theme.of(context) - .textTheme - .labelSmall - ?.color + color: context.textTheme.labelSmall?.color ?.withOpacity(0.5), fontWeight: FontWeight.bold, ), @@ -171,7 +166,7 @@ class AppBarServerInfo extends HookConsumerWidget { "server_info_box_server_url".tr(), style: TextStyle( fontSize: 11, - color: Theme.of(context).textTheme.labelSmall?.color, + color: context.textTheme.labelSmall?.color, fontWeight: FontWeight.bold, ), ), @@ -185,14 +180,12 @@ class AppBarServerInfo extends HookConsumerWidget { child: Tooltip( verticalOffset: 0, decoration: BoxDecoration( - color: - Theme.of(context).primaryColor.withOpacity(0.9), + color: context.primaryColor.withOpacity(0.9), borderRadius: BorderRadius.circular(10), ), textStyle: TextStyle( - color: Theme.of(context).brightness == Brightness.dark - ? Colors.black - : Colors.white, + color: + context.isDarkTheme ? Colors.black : Colors.white, fontWeight: FontWeight.bold, ), message: getServerUrl() ?? '--', @@ -202,10 +195,7 @@ class AppBarServerInfo extends HookConsumerWidget { getServerUrl() ?? '--', style: TextStyle( fontSize: 11, - color: Theme.of(context) - .textTheme - .labelSmall - ?.color + color: context.textTheme.labelSmall?.color ?.withOpacity(0.5), fontWeight: FontWeight.bold, overflow: TextOverflow.ellipsis, diff --git a/mobile/lib/shared/ui/confirm_dialog.dart b/mobile/lib/shared/ui/confirm_dialog.dart index 773007f73c..4dd3cabbf2 100644 --- a/mobile/lib/shared/ui/confirm_dialog.dart +++ b/mobile/lib/shared/ui/confirm_dialog.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class ConfirmDialog extends ConsumerWidget { final Function onOk; @@ -26,11 +27,11 @@ class ConfirmDialog extends ConsumerWidget { content: Text(content).tr(), actions: [ TextButton( - onPressed: () => Navigator.of(context).pop(false), + onPressed: () => context.pop(false), child: Text( cancel, style: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ).tr(), @@ -38,7 +39,7 @@ class ConfirmDialog extends ConsumerWidget { TextButton( onPressed: () { onOk(); - Navigator.of(context).pop(true); + context.pop(true); }, child: Text( ok, diff --git a/mobile/lib/shared/ui/immich_app_bar.dart b/mobile/lib/shared/ui/immich_app_bar.dart index 3510931f6b..bbf5a48a00 100644 --- a/mobile/lib/shared/ui/immich_app_bar.dart +++ b/mobile/lib/shared/ui/immich_app_bar.dart @@ -1,6 +1,6 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/ui/app_bar_dialog/app_bar_dialog.dart'; import 'package:immich_mobile/shared/ui/user_circle_avatar.dart'; @@ -28,7 +28,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { final ServerInfo serverInfoState = ref.watch(serverInfoProvider); AuthenticationState authState = ref.watch(authenticationProvider); final user = Store.tryGet(StoreKey.currentUser); - final isDarkMode = Theme.of(context).brightness == Brightness.dark; + final isDarkTheme = context.isDarkTheme; const widgetSize = 30.0; buildProfileIndicator() { @@ -70,7 +70,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { } getBackupBadgeIcon() { - final iconColor = isDarkMode ? Colors.white : Colors.black; + final iconColor = isDarkTheme ? Colors.white : Colors.black; if (isEnableAutoBackup) { if (backupState.backupProgress == BackUpProgressEnum.inProgress) { @@ -104,10 +104,10 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { buildBackupIndicator() { final indicatorIcon = getBackupBadgeIcon(); - final badgeBackground = isDarkMode ? Colors.blueGrey[800] : Colors.white; + final badgeBackground = isDarkTheme ? Colors.blueGrey[800] : Colors.white; return InkWell( - onTap: () => AutoRouter.of(context).push(const BackupControllerRoute()), + onTap: () => context.autoPush(const BackupControllerRoute()), borderRadius: BorderRadius.circular(12), child: Badge( label: Container( @@ -116,7 +116,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { decoration: BoxDecoration( color: badgeBackground, border: Border.all( - color: isDarkMode ? Colors.black : Colors.grey, + color: isDarkTheme ? Colors.black : Colors.grey, ), borderRadius: BorderRadius.circular(widgetSize / 2), ), @@ -129,14 +129,14 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { child: Icon( Icons.backup_rounded, size: widgetSize, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ); } return AppBar( - backgroundColor: Theme.of(context).appBarTheme.backgroundColor, + backgroundColor: context.themeData.appBarTheme.backgroundColor, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(5), diff --git a/mobile/lib/shared/ui/immich_image.dart b/mobile/lib/shared/ui/immich_image.dart index 8b505f5561..985219d6eb 100644 --- a/mobile/lib/shared/ui/immich_image.dart +++ b/mobile/lib/shared/ui/immich_image.dart @@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/utils/image_url_builder.dart'; @@ -86,7 +87,7 @@ class ImmichImage extends StatelessWidget { } return Icon( Icons.image_not_supported_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ); }, ); @@ -137,7 +138,7 @@ class ImmichImage extends StatelessWidget { } return Icon( Icons.image_not_supported_outlined, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ); }, ); diff --git a/mobile/lib/shared/ui/immich_loading_indicator.dart b/mobile/lib/shared/ui/immich_loading_indicator.dart index 98ddb8f47e..db5dd3c199 100644 --- a/mobile/lib/shared/ui/immich_loading_indicator.dart +++ b/mobile/lib/shared/ui/immich_loading_indicator.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class ImmichLoadingIndicator extends StatelessWidget { final double? borderRadius; @@ -14,7 +15,7 @@ class ImmichLoadingIndicator extends StatelessWidget { height: 60, width: 60, decoration: BoxDecoration( - color: Theme.of(context).primaryColor.withAlpha(200), + color: context.primaryColor.withAlpha(200), borderRadius: BorderRadius.circular(borderRadius ?? 10), ), padding: const EdgeInsets.all(15), diff --git a/mobile/lib/shared/ui/immich_title_text.dart b/mobile/lib/shared/ui/immich_title_text.dart index 7f633a0e6f..3ef0501dd3 100644 --- a/mobile/lib/shared/ui/immich_title_text.dart +++ b/mobile/lib/shared/ui/immich_title_text.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; class ImmichTitleText extends StatelessWidget { final double fontSize; @@ -18,9 +19,8 @@ class ImmichTitleText extends StatelessWidget { fontFamily: 'SnowburstOne', fontWeight: FontWeight.bold, fontSize: fontSize, - color: color ?? Theme.of(context).primaryColor, + color: color ?? context.primaryColor, ), ); } - } diff --git a/mobile/lib/shared/ui/immich_toast.dart b/mobile/lib/shared/ui/immich_toast.dart index 3f15c13a2a..25a0e65fa5 100644 --- a/mobile/lib/shared/ui/immich_toast.dart +++ b/mobile/lib/shared/ui/immich_toast.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; enum ToastType { info, success, error } @@ -11,14 +12,13 @@ class ImmichToast { ToastGravity gravity = ToastGravity.TOP, int durationInSecond = 3, }) { - final isDarkTheme = Theme.of(context).brightness == Brightness.dark; final fToast = FToast(); fToast.init(context); Color getColor(ToastType type, BuildContext context) { switch (type) { case ToastType.info: - return Theme.of(context).primaryColor; + return context.primaryColor; case ToastType.success: return const Color.fromARGB(255, 78, 140, 124); case ToastType.error: @@ -31,7 +31,7 @@ class ImmichToast { case ToastType.info: return Icon( Icons.info_outline_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ); case ToastType.success: return const Icon( @@ -51,7 +51,7 @@ class ImmichToast { padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(5.0), - color: isDarkTheme ? Colors.grey[900] : Colors.grey[50], + color: context.isDarkTheme ? Colors.grey[900] : Colors.grey[50], border: Border.all( color: Colors.black12, width: 1, diff --git a/mobile/lib/shared/ui/user_avatar.dart b/mobile/lib/shared/ui/user_avatar.dart index c736e8f900..382e44effe 100644 --- a/mobile/lib/shared/ui/user_avatar.dart +++ b/mobile/lib/shared/ui/user_avatar.dart @@ -1,5 +1,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/models/user.dart'; @@ -10,7 +11,7 @@ Widget userAvatar(BuildContext context, User u, {double? radius}) { final lastNameFirstLetter = u.lastName.isNotEmpty ? u.lastName[0] : ""; return CircleAvatar( radius: radius, - backgroundColor: Theme.of(context).primaryColor.withAlpha(50), + backgroundColor: context.primaryColor.withAlpha(50), foregroundImage: CachedNetworkImageProvider( url, headers: {"Authorization": "Bearer ${Store.get(StoreKey.accessToken)}"}, diff --git a/mobile/lib/shared/ui/user_circle_avatar.dart b/mobile/lib/shared/ui/user_circle_avatar.dart index df50d5071a..98df36265c 100644 --- a/mobile/lib/shared/ui/user_circle_avatar.dart +++ b/mobile/lib/shared/ui/user_circle_avatar.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/store.dart'; import 'package:immich_mobile/shared/models/user.dart'; import 'package:immich_mobile/shared/ui/transparent_image.dart'; @@ -45,15 +46,13 @@ class UserCircleAvatar extends ConsumerWidget { user.firstName[0].toUpperCase(), style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).brightness == Brightness.dark - ? Colors.black - : Colors.white, + color: context.isDarkTheme ? Colors.black : Colors.white, ), ); return CircleAvatar( backgroundColor: useRandomBackgroundColor ? randomColors[Random().nextInt(randomColors.length)] - : Theme.of(context).primaryColor, + : context.primaryColor, radius: radius, child: user.profileImagePath == "" ? textIcon diff --git a/mobile/lib/shared/views/app_log_detail_page.dart b/mobile/lib/shared/views/app_log_detail_page.dart index 0963605b43..f8ddf51918 100644 --- a/mobile/lib/shared/views/app_log_detail_page.dart +++ b/mobile/lib/shared/views/app_log_detail_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/logger_message.model.dart'; import 'package:flutter/services.dart'; @@ -10,7 +11,7 @@ class AppLogDetailPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - var isDarkMode = Theme.of(context).brightness == Brightness.dark; + var isDarkTheme = context.isDarkTheme; buildStackMessage(String stackTrace) { return Padding( @@ -28,7 +29,7 @@ class AppLogDetailPage extends HookConsumerWidget { "STACK TRACES", style: TextStyle( fontSize: 12.0, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ), @@ -45,14 +46,14 @@ class AppLogDetailPage extends HookConsumerWidget { icon: Icon( Icons.copy, size: 16.0, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ], ), Container( decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[900] : Colors.grey[200], + color: isDarkTheme ? Colors.grey[900] : Colors.grey[200], borderRadius: BorderRadius.circular(15.0), ), child: Padding( @@ -88,7 +89,7 @@ class AppLogDetailPage extends HookConsumerWidget { "MESSAGE", style: TextStyle( fontSize: 12.0, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ), @@ -104,14 +105,14 @@ class AppLogDetailPage extends HookConsumerWidget { icon: Icon( Icons.copy, size: 16.0, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ], ), Container( decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[900] : Colors.grey[200], + color: isDarkTheme ? Colors.grey[900] : Colors.grey[200], borderRadius: BorderRadius.circular(15.0), ), child: Padding( @@ -143,14 +144,14 @@ class AppLogDetailPage extends HookConsumerWidget { "FROM", style: TextStyle( fontSize: 12.0, - color: Theme.of(context).primaryColor, + color: context.primaryColor, fontWeight: FontWeight.bold, ), ), ), Container( decoration: BoxDecoration( - color: isDarkMode ? Colors.grey[900] : Colors.grey[200], + color: isDarkTheme ? Colors.grey[900] : Colors.grey[200], borderRadius: BorderRadius.circular(15.0), ), child: Padding( diff --git a/mobile/lib/shared/views/app_log_page.dart b/mobile/lib/shared/views/app_log_page.dart index a8dfc6ec44..9d1dca19fa 100644 --- a/mobile/lib/shared/views/app_log_page.dart +++ b/mobile/lib/shared/views/app_log_page.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/shared/models/logger_message.model.dart'; import 'package:immich_mobile/shared/services/immich_logger.service.dart'; @@ -16,6 +16,7 @@ class AppLogPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final immichLogger = ImmichLogger(); final logMessages = useState(immichLogger.messages); + final isDarkTheme = context.isDarkTheme; Widget colorStatusIndicator(Color color) { return Column( @@ -36,7 +37,7 @@ class AppLogPage extends HookConsumerWidget { Widget buildLeadingIcon(LogLevel level) { switch (level) { case LogLevel.INFO: - return colorStatusIndicator(Theme.of(context).primaryColor); + return colorStatusIndicator(context.primaryColor); case LogLevel.SEVERE: return colorStatusIndicator(Colors.redAccent); @@ -52,15 +53,15 @@ class AppLogPage extends HookConsumerWidget { case LogLevel.INFO: return Colors.transparent; case LogLevel.SEVERE: - return Theme.of(context).brightness == Brightness.dark + return isDarkTheme ? Colors.redAccent.withOpacity(0.25) : Colors.redAccent.withOpacity(0.075); case LogLevel.WARNING: - return Theme.of(context).brightness == Brightness.dark + return isDarkTheme ? Colors.orangeAccent.withOpacity(0.25) : Colors.orangeAccent.withOpacity(0.075); default: - return Theme.of(context).primaryColor.withOpacity(0.1); + return context.primaryColor.withOpacity(0.1); } } @@ -79,7 +80,7 @@ class AppLogPage extends HookConsumerWidget { IconButton( icon: Icon( Icons.delete_outline_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, semanticLabel: "Clear logs", size: 20.0, ), @@ -91,7 +92,7 @@ class AppLogPage extends HookConsumerWidget { IconButton( icon: Icon( Icons.share_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, semanticLabel: "Share logs", size: 20.0, ), @@ -102,7 +103,7 @@ class AppLogPage extends HookConsumerWidget { ], leading: IconButton( onPressed: () { - AutoRouter.of(context).pop(); + context.autoPop(); }, icon: const Icon( Icons.arrow_back_ios_new_rounded, @@ -115,16 +116,14 @@ class AppLogPage extends HookConsumerWidget { separatorBuilder: (context, index) { return Divider( height: 0, - color: Theme.of(context).brightness == Brightness.dark - ? Colors.white70 - : Colors.grey[600], + color: isDarkTheme ? Colors.white70 : Colors.grey[600], ); }, itemCount: logMessages.value.length, itemBuilder: (context, index) { var logMessage = logMessages.value[index]; return ListTile( - onTap: () => AutoRouter.of(context).push( + onTap: () => context.autoPush( AppLogDetailRoute( logMessage: logMessage, ), @@ -140,9 +139,7 @@ class AppLogPage extends HookConsumerWidget { TextSpan( text: "#$index ", style: TextStyle( - color: Theme.of(context).brightness == Brightness.dark - ? Colors.white70 - : Colors.grey[600], + color: isDarkTheme ? Colors.white70 : Colors.grey[600], fontSize: 14.0, fontWeight: FontWeight.bold, ), @@ -170,7 +167,7 @@ class AppLogPage extends HookConsumerWidget { ), ); } - + /// Truncate the log message to a certain number of lines /// @param int maxLines - Max number of lines to truncate String truncateLogMessage(String message, int maxLines) { diff --git a/mobile/lib/shared/views/splash_screen.dart b/mobile/lib/shared/views/splash_screen.dart index bd419bc020..2f493d16a4 100644 --- a/mobile/lib/shared/views/splash_screen.dart +++ b/mobile/lib/shared/views/splash_screen.dart @@ -1,7 +1,7 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/backup/providers/backup.provider.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart'; @@ -51,7 +51,7 @@ class SplashScreenPage extends HookConsumerWidget { // If the device is offline and there is a currentUser stored locallly // Proceed into the app if (deviceIsOffline && Store.tryGet(StoreKey.currentUser) != null) { - AutoRouter.of(context).replace(const TabControllerRoute()); + context.autoReplace(const TabControllerRoute()); } else if (isSuccess) { // If device was able to login through the internet successfully final hasPermission = @@ -60,10 +60,10 @@ class SplashScreenPage extends HookConsumerWidget { // Resume backup (if enable) then navigate ref.watch(backupProvider.notifier).resumeBackup(); } - AutoRouter.of(context).replace(const TabControllerRoute()); + context.autoReplace(const TabControllerRoute()); } else { // User was unable to login through either offline or online methods - AutoRouter.of(context).replace(const LoginRoute()); + context.autoReplace(const LoginRoute()); } } @@ -72,7 +72,7 @@ class SplashScreenPage extends HookConsumerWidget { if (serverUrl != null && accessToken != null) { performLoggingIn(); } else { - AutoRouter.of(context).replace(const LoginRoute()); + context.autoReplace(const LoginRoute()); } return null; }, diff --git a/mobile/lib/shared/views/tab_controller_page.dart b/mobile/lib/shared/views/tab_controller_page.dart index 8e72ce900f..2b9d625651 100644 --- a/mobile/lib/shared/views/tab_controller_page.dart +++ b/mobile/lib/shared/views/tab_controller_page.dart @@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/asset_viewer/providers/scroll_notifier.provider.dart'; import 'package:immich_mobile/modules/home/providers/multiselect.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -31,7 +32,7 @@ class TabControllerPage extends HookConsumerWidget { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - Theme.of(context).primaryColor, + context.primaryColor, ), ), ), @@ -55,10 +56,10 @@ class TabControllerPage extends HookConsumerWidget { ref.read(tabProvider.notifier).state = TabEnum.values[index]; }, selectedIconTheme: IconThemeData( - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), selectedLabelTextStyle: TextStyle( - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), useIndicator: false, destinations: [ @@ -116,7 +117,7 @@ class TabControllerPage extends HookConsumerWidget { selectedIcon: buildIcon( Icon( Icons.photo_library, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), @@ -127,7 +128,7 @@ class TabControllerPage extends HookConsumerWidget { ), selectedIcon: Icon( Icons.search, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), NavigationDestination( @@ -137,7 +138,7 @@ class TabControllerPage extends HookConsumerWidget { ), selectedIcon: Icon( Icons.group, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), NavigationDestination( @@ -148,7 +149,7 @@ class TabControllerPage extends HookConsumerWidget { selectedIcon: buildIcon( Icon( Icons.photo_album_rounded, - color: Theme.of(context).primaryColor, + color: context.primaryColor, ), ), ), diff --git a/mobile/lib/utils/capitalize.dart b/mobile/lib/utils/capitalize.dart deleted file mode 100644 index 80b10cc582..0000000000 --- a/mobile/lib/utils/capitalize.dart +++ /dev/null @@ -1,9 +0,0 @@ -extension StringExtension on String { - String capitalize() { - return split(" ") - .map( - (str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1), - ) - .join(" "); - } -} diff --git a/mobile/lib/utils/selection_handlers.dart b/mobile/lib/utils/selection_handlers.dart index 511dcf81ea..5d13d20a28 100644 --- a/mobile/lib/utils/selection_handlers.dart +++ b/mobile/lib/utils/selection_handlers.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/providers/asset.provider.dart'; import 'package:immich_mobile/shared/services/share.service.dart'; @@ -26,7 +27,7 @@ void handleShareAssets( gravity: ToastGravity.BOTTOM, ); } - Navigator.of(buildContext).pop(); + context.pop(); }, ); return const ShareDialog(); diff --git a/mobile/test/builtin_extensions_test.dart b/mobile/test/builtin_extensions_test.dart index 875a20fb06..9fc729774a 100644 --- a/mobile/test/builtin_extensions_test.dart +++ b/mobile/test/builtin_extensions_test.dart @@ -1,5 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:immich_mobile/utils/builtin_extensions.dart'; +import 'package:immich_mobile/extensions/collection_extensions.dart'; +import 'package:immich_mobile/extensions/string_extensions.dart'; void main() { group('Test toDuration', () {