From 4c7b30c18b55e74224ad1a223a2058ea4a13cc1f Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Fri, 4 Sep 2026 12:06:01 -0700 Subject: [PATCH] chore(mobile): move settings components to UI package (#31272) --- .../extensions/build_context_extensions.dart | 69 +------------------ mobile/lib/extensions/theme_extensions.dart | 18 +---- mobile/lib/pages/common/settings.page.dart | 8 +-- .../widgets/settings/advanced_settings.dart | 5 +- .../asset_list_group_settings.dart | 3 +- .../asset_list_layout_settings.dart | 3 +- .../asset_list_settings.dart | 3 +- .../asset_viewer_settings.dart | 2 +- .../image_viewer_quality_setting.dart | 3 +- .../image_viewer_tap_to_navigate_setting.dart | 3 +- .../slideshow_settings.dart | 6 +- .../video_viewer_settings.dart | 3 +- .../backup_settings/backup_settings.dart | 4 +- .../sync_status_and_actions.dart | 3 +- .../networking_settings.dart | 3 +- .../settings/notification_setting.dart | 3 +- .../preference_settings/haptic_setting.dart | 3 +- .../preference_setting.dart | 2 +- .../preference_settings/share_setting.dart | 3 +- .../preference_settings/theme_setting.dart | 3 +- .../extensions/build_context_extensions.dart | 67 ++++++++++++++++++ .../ui/lib/extensions/theme_extensions.dart | 16 +++++ mobile/packages/ui/lib/immich_ui.dart | 1 + .../settings/setting_group_title.dart | 4 +- .../settings/setting_list_tile.dart | 2 +- .../lib/src/components/settings/settings.dart | 10 +++ .../settings/settings_action_tile.dart | 2 +- .../settings/settings_button_list_tile.dart | 4 +- .../components}/settings/settings_card.dart | 15 ++-- .../settings/settings_radio_list_tile.dart | 2 +- .../settings/settings_slider_list_tile.dart | 2 +- .../settings/settings_sub_page_scaffold.dart | 0 .../settings/settings_sub_title.dart | 2 +- .../settings/settings_switch_list_tile.dart | 4 +- 34 files changed, 134 insertions(+), 147 deletions(-) create mode 100644 mobile/packages/ui/lib/extensions/build_context_extensions.dart create mode 100644 mobile/packages/ui/lib/extensions/theme_extensions.dart rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/setting_group_title.dart (89%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/setting_list_tile.dart (92%) create mode 100644 mobile/packages/ui/lib/src/components/settings/settings.dart rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_action_tile.dart (97%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_button_list_tile.dart (91%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_card.dart (77%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_radio_list_tile.dart (94%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_slider_list_tile.dart (94%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_sub_page_scaffold.dart (100%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_sub_title.dart (86%) rename mobile/{lib/widgets => packages/ui/lib/src/components}/settings/settings_switch_list_tile.dart (93%) diff --git a/mobile/lib/extensions/build_context_extensions.dart b/mobile/lib/extensions/build_context_extensions.dart index 0a35bc1a8..8dd268f74 100644 --- a/mobile/lib/extensions/build_context_extensions.dart +++ b/mobile/lib/extensions/build_context_extensions.dart @@ -1,67 +1,2 @@ -import 'package:flutter/material.dart'; - -extension ContextHelper on BuildContext { - // Returns the current padding from MediaQuery - EdgeInsets get padding => MediaQuery.paddingOf(this); - - // Returns the current view insets from MediaQuery - EdgeInsets get viewInsets => MediaQuery.viewInsetsOf(this); - - // Returns the current width from MediaQuery - double get width => MediaQuery.sizeOf(this).width; - - // Returns the current height from MediaQuery - double get height => MediaQuery.sizeOf(this).height; - - // Returns the current size from MediaQuery - Size get sizeData => MediaQuery.sizeOf(this); - - // Returns true if the app is running on a mobile device (!tablets) - bool get isMobile => width < 550; - - // Returns the current device pixel ratio from MediaQuery - double get devicePixelRatio => MediaQuery.devicePixelRatioOf(this); - - // Returns the current orientation from MediaQuery - Orientation get orientation => MediaQuery.orientationOf(this); - - // Returns the current platform brightness from MediaQuery - Brightness get platformBrightness => MediaQuery.platformBrightnessOf(this); - - // 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.colorScheme.primary; - Color get logoYellow => const Color.fromARGB(255, 255, 184, 0); - Color get logoRed => const Color.fromARGB(255, 230, 65, 30); - Color get logoPink => const Color.fromARGB(255, 222, 127, 179); - Color get logoGreen => const Color.fromARGB(255, 49, 164, 82); - - // Returns the Scaffold background color of the Theme - Color get scaffoldBackgroundColor => colorScheme.surface; - - // Returns the current TextTheme - TextTheme get textTheme => themeData.textTheme; - - // Current ColorScheme used - ColorScheme get colorScheme => themeData.colorScheme; - - // Navigate by pushing or popping routes from the current context - NavigatorState get navigator => Navigator.of(this); - - // Showing material banners from the current context - ScaffoldMessengerState get scaffoldMessenger => ScaffoldMessenger.of(this); - - // Pop-out from the current context with optional result - void pop([T? result]) => Navigator.of(this).pop(result); - - // Managing focus within the widget tree from the current context - FocusScopeNode get focusScope => FocusScope.of(this); - - // Show SnackBars from the current context - void showSnackBar(SnackBar snackBar) => ScaffoldMessenger.of(this).showSnackBar(snackBar); -} +// TODO: Remove +export 'package:immich_ui/extensions/build_context_extensions.dart'; diff --git a/mobile/lib/extensions/theme_extensions.dart b/mobile/lib/extensions/theme_extensions.dart index 332dc58fc..c990c845e 100644 --- a/mobile/lib/extensions/theme_extensions.dart +++ b/mobile/lib/extensions/theme_extensions.dart @@ -1,16 +1,2 @@ -import 'package:flutter/material.dart'; - -extension ImmichColorSchemeExtensions on ColorScheme { - bool get _isDarkMode => brightness == Brightness.dark; - Color get onSurfaceSecondary => _isDarkMode ? onSurface.darken(amount: .3) : onSurface.lighten(amount: .3); -} - -extension ColorExtensions on Color { - Color lighten({double amount = 0.1}) { - return Color.alphaBlend(Colors.white.withValues(alpha: amount), this); - } - - Color darken({double amount = 0.1}) { - return Color.alphaBlend(Colors.black.withValues(alpha: amount), this); - } -} +// TODO: Remove +export 'package:immich_ui/extensions/theme_extensions.dart'; diff --git a/mobile/lib/pages/common/settings.page.dart b/mobile/lib/pages/common/settings.page.dart index bd13d900e..02b07bce8 100644 --- a/mobile/lib/pages/common/settings.page.dart +++ b/mobile/lib/pages/common/settings.page.dart @@ -14,7 +14,7 @@ import 'package:immich_mobile/widgets/settings/language_settings.dart'; import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart'; import 'package:immich_mobile/widgets/settings/notification_setting.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/preference_setting.dart'; -import 'package:immich_mobile/widgets/settings/settings_card.dart'; +import 'package:immich_ui/immich_ui.dart'; enum SettingSection { advanced(Icons.build_outlined), @@ -97,7 +97,7 @@ class _MobileLayout extends StatelessWidget { icon: Icons.sync_outlined, title: context.t.sync_status, subtitle: context.t.sync_status_subtitle, - settingRoute: const SyncStatusRoute(), + onTap: () => context.pushRoute(const SyncStatusRoute()), ), ] : [ @@ -105,7 +105,7 @@ class _MobileLayout extends StatelessWidget { title: setting.title(context.t), subtitle: setting.subtitle(context.t), icon: setting.icon, - settingRoute: SettingsSubRoute(section: setting), + onTap: () => context.pushRoute(SettingsSubRoute(section: setting)), ), ], ) @@ -115,7 +115,7 @@ class _MobileLayout extends StatelessWidget { icon: Icons.auto_awesome_outlined, title: context.t.whats_new, subtitle: context.t.whats_new_settings_subtitle, - settingRoute: const WhatsNewRoute(), + onTap: () => context.pushRoute(const WhatsNewRoute()), ), ); return ListView(padding: const EdgeInsets.only(top: 10.0, bottom: 60), children: [...settings]); diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index 44a992345..11f2dc67d 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -16,11 +16,8 @@ import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:immich_mobile/widgets/settings/custom_proxy_headers_settings/custom_proxy_headers_settings.dart'; -import 'package:immich_mobile/widgets/settings/settings_action_tile.dart'; -import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; import 'package:immich_mobile/widgets/settings/ssl_client_cert_settings.dart'; +import 'package:immich_ui/immich_ui.dart'; import 'package:logging/logging.dart'; class AdvancedSettings extends HookConsumerWidget { diff --git a/mobile/lib/widgets/settings/asset_list_settings/asset_list_group_settings.dart b/mobile/lib/widgets/settings/asset_list_settings/asset_list_group_settings.dart index a68ad0fe5..3ee93911a 100644 --- a/mobile/lib/widgets/settings/asset_list_settings/asset_list_group_settings.dart +++ b/mobile/lib/widgets/settings/asset_list_settings/asset_list_group_settings.dart @@ -8,8 +8,7 @@ import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_radio_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class GroupSettings extends HookConsumerWidget { const GroupSettings({super.key}); diff --git a/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart b/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart index 651cc4365..970f17cab 100644 --- a/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart +++ b/mobile/lib/widgets/settings/asset_list_settings/asset_list_layout_settings.dart @@ -6,8 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class LayoutSettings extends HookConsumerWidget { const LayoutSettings({super.key}); diff --git a/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart b/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart index 08fe897c5..de32179c3 100644 --- a/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart +++ b/mobile/lib/widgets/settings/asset_list_settings/asset_list_settings.dart @@ -8,8 +8,7 @@ import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_group_settings.dart'; import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_layout_settings.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class AssetListSettings extends HookConsumerWidget { const AssetListSettings({super.key}); diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart b/mobile/lib/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart index 25829327e..abe910812 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart @@ -3,7 +3,7 @@ import 'package:immich_mobile/widgets/settings/asset_viewer_settings/image_viewe import 'package:immich_mobile/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart'; import 'package:immich_mobile/widgets/settings/asset_viewer_settings/slideshow_settings.dart'; import 'package:immich_mobile/widgets/settings/asset_viewer_settings/video_viewer_settings.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; +import 'package:immich_ui/immich_ui.dart'; class AssetViewerSettings extends StatelessWidget { const AssetViewerSettings({super.key}); diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart index 5b5917add..71218ee79 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_quality_setting.dart @@ -6,8 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class ImageViewerQualitySetting extends HookConsumerWidget { const ImageViewerQualitySetting({super.key}); diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart index f8dc6b0e1..908eb84f1 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/image_viewer_tap_to_navigate_setting.dart @@ -5,8 +5,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class ImageViewerTapToNavigateSetting extends HookConsumerWidget { const ImageViewerTapToNavigateSetting({super.key}); diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart b/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart index 72d1685d3..23cc7c293 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/slideshow_settings.dart @@ -6,11 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_radio_list_tile.dart'; -import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class SlideshowSettings extends HookConsumerWidget { const SlideshowSettings({super.key}); diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart b/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart index bb14d4b32..a0a897622 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart @@ -5,8 +5,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class VideoViewerSettings extends HookConsumerWidget { const VideoViewerSettings({super.key}); diff --git a/mobile/lib/widgets/settings/backup_settings/backup_settings.dart b/mobile/lib/widgets/settings/backup_settings/backup_settings.dart index b506489c4..b6a1ce4ca 100644 --- a/mobile/lib/widgets/settings/backup_settings/backup_settings.dart +++ b/mobile/lib/widgets/settings/backup_settings/backup_settings.dart @@ -14,9 +14,7 @@ import 'package:immich_mobile/providers/backup/backup_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/setting_list_tile.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; +import 'package:immich_ui/immich_ui.dart'; class BackupSettings extends StatelessWidget { const BackupSettings({super.key}); diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart index a0193dbcd..291d68f78 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -20,8 +20,7 @@ import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/sync_status.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/widgets/settings/beta_sync_settings/entity_count_tile.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/setting_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; diff --git a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart index 80b0b78fc..a07037fe6 100644 --- a/mobile/lib/widgets/settings/networking_settings/networking_settings.dart +++ b/mobile/lib/widgets/settings/networking_settings/networking_settings.dart @@ -11,8 +11,7 @@ import 'package:immich_mobile/providers/network.provider.dart'; import 'package:immich_mobile/utils/url_helper.dart'; import 'package:immich_mobile/widgets/settings/networking_settings/external_network_preference.dart'; import 'package:immich_mobile/widgets/settings/networking_settings/local_network_preference.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class NetworkingSettings extends HookConsumerWidget { const NetworkingSettings({super.key}); diff --git a/mobile/lib/widgets/settings/notification_setting.dart b/mobile/lib/widgets/settings/notification_setting.dart index c3d175999..59ec3235b 100644 --- a/mobile/lib/widgets/settings/notification_setting.dart +++ b/mobile/lib/widgets/settings/notification_setting.dart @@ -5,8 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/permission.provider.dart'; -import 'package:immich_mobile/widgets/settings/settings_button_list_tile.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; +import 'package:immich_ui/immich_ui.dart'; import 'package:permission_handler/permission_handler.dart'; class NotificationSetting extends HookConsumerWidget { diff --git a/mobile/lib/widgets/settings/preference_settings/haptic_setting.dart b/mobile/lib/widgets/settings/preference_settings/haptic_setting.dart index 9aaae683a..7c455f607 100644 --- a/mobile/lib/widgets/settings/preference_settings/haptic_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/haptic_setting.dart @@ -3,8 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class HapticSetting extends HookWidget { const HapticSetting({super.key}); diff --git a/mobile/lib/widgets/settings/preference_settings/preference_setting.dart b/mobile/lib/widgets/settings/preference_settings/preference_setting.dart index afb3b478f..dcb851b07 100644 --- a/mobile/lib/widgets/settings/preference_settings/preference_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/preference_setting.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/haptic_setting.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/share_setting.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/theme_setting.dart'; -import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; +import 'package:immich_ui/immich_ui.dart'; class PreferenceSetting extends StatelessWidget { const PreferenceSetting({super.key}); diff --git a/mobile/lib/widgets/settings/preference_settings/share_setting.dart b/mobile/lib/widgets/settings/preference_settings/share_setting.dart index 188170302..5dfc4abd4 100644 --- a/mobile/lib/widgets/settings/preference_settings/share_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/share_setting.dart @@ -8,8 +8,7 @@ import 'package:immich_mobile/domain/models/settings_key.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_radio_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class ShareSetting extends HookConsumerWidget { const ShareSetting({super.key}); diff --git a/mobile/lib/widgets/settings/preference_settings/theme_setting.dart b/mobile/lib/widgets/settings/preference_settings/theme_setting.dart index cf1a22c45..f1d3e7ae9 100644 --- a/mobile/lib/widgets/settings/preference_settings/theme_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/theme_setting.dart @@ -7,8 +7,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/widgets/settings/preference_settings/primary_color_setting.dart'; -import 'package:immich_mobile/widgets/settings/setting_group_title.dart'; -import 'package:immich_mobile/widgets/settings/settings_switch_list_tile.dart'; +import 'package:immich_ui/immich_ui.dart'; class ThemeSetting extends HookConsumerWidget { const ThemeSetting({super.key}); diff --git a/mobile/packages/ui/lib/extensions/build_context_extensions.dart b/mobile/packages/ui/lib/extensions/build_context_extensions.dart new file mode 100644 index 000000000..0a35bc1a8 --- /dev/null +++ b/mobile/packages/ui/lib/extensions/build_context_extensions.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; + +extension ContextHelper on BuildContext { + // Returns the current padding from MediaQuery + EdgeInsets get padding => MediaQuery.paddingOf(this); + + // Returns the current view insets from MediaQuery + EdgeInsets get viewInsets => MediaQuery.viewInsetsOf(this); + + // Returns the current width from MediaQuery + double get width => MediaQuery.sizeOf(this).width; + + // Returns the current height from MediaQuery + double get height => MediaQuery.sizeOf(this).height; + + // Returns the current size from MediaQuery + Size get sizeData => MediaQuery.sizeOf(this); + + // Returns true if the app is running on a mobile device (!tablets) + bool get isMobile => width < 550; + + // Returns the current device pixel ratio from MediaQuery + double get devicePixelRatio => MediaQuery.devicePixelRatioOf(this); + + // Returns the current orientation from MediaQuery + Orientation get orientation => MediaQuery.orientationOf(this); + + // Returns the current platform brightness from MediaQuery + Brightness get platformBrightness => MediaQuery.platformBrightnessOf(this); + + // 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.colorScheme.primary; + Color get logoYellow => const Color.fromARGB(255, 255, 184, 0); + Color get logoRed => const Color.fromARGB(255, 230, 65, 30); + Color get logoPink => const Color.fromARGB(255, 222, 127, 179); + Color get logoGreen => const Color.fromARGB(255, 49, 164, 82); + + // Returns the Scaffold background color of the Theme + Color get scaffoldBackgroundColor => colorScheme.surface; + + // Returns the current TextTheme + TextTheme get textTheme => themeData.textTheme; + + // Current ColorScheme used + ColorScheme get colorScheme => themeData.colorScheme; + + // Navigate by pushing or popping routes from the current context + NavigatorState get navigator => Navigator.of(this); + + // Showing material banners from the current context + ScaffoldMessengerState get scaffoldMessenger => ScaffoldMessenger.of(this); + + // Pop-out from the current context with optional result + void pop([T? result]) => Navigator.of(this).pop(result); + + // Managing focus within the widget tree from the current context + FocusScopeNode get focusScope => FocusScope.of(this); + + // Show SnackBars from the current context + void showSnackBar(SnackBar snackBar) => ScaffoldMessenger.of(this).showSnackBar(snackBar); +} diff --git a/mobile/packages/ui/lib/extensions/theme_extensions.dart b/mobile/packages/ui/lib/extensions/theme_extensions.dart new file mode 100644 index 000000000..332dc58fc --- /dev/null +++ b/mobile/packages/ui/lib/extensions/theme_extensions.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +extension ImmichColorSchemeExtensions on ColorScheme { + bool get _isDarkMode => brightness == Brightness.dark; + Color get onSurfaceSecondary => _isDarkMode ? onSurface.darken(amount: .3) : onSurface.lighten(amount: .3); +} + +extension ColorExtensions on Color { + Color lighten({double amount = 0.1}) { + return Color.alphaBlend(Colors.white.withValues(alpha: amount), this); + } + + Color darken({double amount = 0.1}) { + return Color.alphaBlend(Colors.black.withValues(alpha: amount), this); + } +} diff --git a/mobile/packages/ui/lib/immich_ui.dart b/mobile/packages/ui/lib/immich_ui.dart index 85875717a..061fa2ecf 100644 --- a/mobile/packages/ui/lib/immich_ui.dart +++ b/mobile/packages/ui/lib/immich_ui.dart @@ -7,6 +7,7 @@ export 'src/components/formatted_text.dart'; export 'src/components/icon_button.dart'; export 'src/components/menu_item.dart'; export 'src/components/password_input.dart'; +export 'src/components/settings/settings.dart'; export 'src/components/text_button.dart'; export 'src/components/text_input.dart'; export 'src/components/url_input.dart'; diff --git a/mobile/lib/widgets/settings/setting_group_title.dart b/mobile/packages/ui/lib/src/components/settings/setting_group_title.dart similarity index 89% rename from mobile/lib/widgets/settings/setting_group_title.dart rename to mobile/packages/ui/lib/src/components/settings/setting_group_title.dart index 48b1a9bfb..b758077bb 100644 --- a/mobile/lib/widgets/settings/setting_group_title.dart +++ b/mobile/packages/ui/lib/src/components/settings/setting_group_title.dart @@ -1,6 +1,6 @@ import 'package:flutter/widgets.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/theme_extensions.dart'; class SettingGroupTitle extends StatelessWidget { final String title; diff --git a/mobile/lib/widgets/settings/setting_list_tile.dart b/mobile/packages/ui/lib/src/components/settings/setting_list_tile.dart similarity index 92% rename from mobile/lib/widgets/settings/setting_list_tile.dart rename to mobile/packages/ui/lib/src/components/settings/setting_list_tile.dart index 17f44f8a8..f0072e9c3 100644 --- a/mobile/lib/widgets/settings/setting_list_tile.dart +++ b/mobile/packages/ui/lib/src/components/settings/setting_list_tile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; class SettingListTile extends StatelessWidget { final String title; diff --git a/mobile/packages/ui/lib/src/components/settings/settings.dart b/mobile/packages/ui/lib/src/components/settings/settings.dart new file mode 100644 index 000000000..681065a38 --- /dev/null +++ b/mobile/packages/ui/lib/src/components/settings/settings.dart @@ -0,0 +1,10 @@ +export 'setting_group_title.dart'; +export 'setting_list_tile.dart'; +export 'settings_action_tile.dart'; +export 'settings_button_list_tile.dart'; +export 'settings_card.dart'; +export 'settings_radio_list_tile.dart'; +export 'settings_slider_list_tile.dart'; +export 'settings_sub_page_scaffold.dart'; +export 'settings_sub_title.dart'; +export 'settings_switch_list_tile.dart'; diff --git a/mobile/lib/widgets/settings/settings_action_tile.dart b/mobile/packages/ui/lib/src/components/settings/settings_action_tile.dart similarity index 97% rename from mobile/lib/widgets/settings/settings_action_tile.dart rename to mobile/packages/ui/lib/src/components/settings/settings_action_tile.dart index b2b5988fa..f4c7cb0c4 100644 --- a/mobile/lib/widgets/settings/settings_action_tile.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_action_tile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_ui/extensions/theme_extensions.dart'; class SettingsActionTile extends StatelessWidget { const SettingsActionTile({ diff --git a/mobile/lib/widgets/settings/settings_button_list_tile.dart b/mobile/packages/ui/lib/src/components/settings/settings_button_list_tile.dart similarity index 91% rename from mobile/lib/widgets/settings/settings_button_list_tile.dart rename to mobile/packages/ui/lib/src/components/settings/settings_button_list_tile.dart index 1e06c0b2b..08a9f091b 100644 --- a/mobile/lib/widgets/settings/settings_button_list_tile.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_button_list_tile.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/theme_extensions.dart'; class SettingsButtonListTile extends StatelessWidget { final IconData icon; diff --git a/mobile/lib/widgets/settings/settings_card.dart b/mobile/packages/ui/lib/src/components/settings/settings_card.dart similarity index 77% rename from mobile/lib/widgets/settings/settings_card.dart rename to mobile/packages/ui/lib/src/components/settings/settings_card.dart index b5dcaac1c..7ff09eed4 100644 --- a/mobile/lib/widgets/settings/settings_card.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_card.dart @@ -1,20 +1,13 @@ -import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; class SettingsCard extends StatelessWidget { - const SettingsCard({ - super.key, - required this.icon, - required this.title, - required this.subtitle, - required this.settingRoute, - }); + const SettingsCard({super.key, required this.icon, required this.title, required this.subtitle, required this.onTap}); final IconData icon; final String title; final String subtitle; - final PageRouteInfo settingRoute; + final Function() onTap; @override Widget build(BuildContext context) { @@ -38,7 +31,7 @@ class SettingsCard extends StatelessWidget { ), title: Text(title, style: context.textTheme.titleMedium!.copyWith(color: context.primaryColor)), subtitle: Text(subtitle, style: context.textTheme.bodyMedium), - onTap: () => context.pushRoute(settingRoute), + onTap: onTap, ), ), ); diff --git a/mobile/lib/widgets/settings/settings_radio_list_tile.dart b/mobile/packages/ui/lib/src/components/settings/settings_radio_list_tile.dart similarity index 94% rename from mobile/lib/widgets/settings/settings_radio_list_tile.dart rename to mobile/packages/ui/lib/src/components/settings/settings_radio_list_tile.dart index 6b02a6515..d6ab7d952 100644 --- a/mobile/lib/widgets/settings/settings_radio_list_tile.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_radio_list_tile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; class SettingsRadioGroup { final String title; diff --git a/mobile/lib/widgets/settings/settings_slider_list_tile.dart b/mobile/packages/ui/lib/src/components/settings/settings_slider_list_tile.dart similarity index 94% rename from mobile/lib/widgets/settings/settings_slider_list_tile.dart rename to mobile/packages/ui/lib/src/components/settings/settings_slider_list_tile.dart index 500591bad..8bca699e7 100644 --- a/mobile/lib/widgets/settings/settings_slider_list_tile.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_slider_list_tile.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; class SettingsSliderListTile extends StatelessWidget { final ValueNotifier valueNotifier; diff --git a/mobile/lib/widgets/settings/settings_sub_page_scaffold.dart b/mobile/packages/ui/lib/src/components/settings/settings_sub_page_scaffold.dart similarity index 100% rename from mobile/lib/widgets/settings/settings_sub_page_scaffold.dart rename to mobile/packages/ui/lib/src/components/settings/settings_sub_page_scaffold.dart diff --git a/mobile/lib/widgets/settings/settings_sub_title.dart b/mobile/packages/ui/lib/src/components/settings/settings_sub_title.dart similarity index 86% rename from mobile/lib/widgets/settings/settings_sub_title.dart rename to mobile/packages/ui/lib/src/components/settings/settings_sub_title.dart index d98f1929b..a747776cb 100644 --- a/mobile/lib/widgets/settings/settings_sub_title.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_sub_title.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; class SettingsSubTitle extends StatelessWidget { final String title; diff --git a/mobile/lib/widgets/settings/settings_switch_list_tile.dart b/mobile/packages/ui/lib/src/components/settings/settings_switch_list_tile.dart similarity index 93% rename from mobile/lib/widgets/settings/settings_switch_list_tile.dart rename to mobile/packages/ui/lib/src/components/settings/settings_switch_list_tile.dart index 4d358fa2b..22a381e69 100644 --- a/mobile/lib/widgets/settings/settings_switch_list_tile.dart +++ b/mobile/packages/ui/lib/src/components/settings/settings_switch_list_tile.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/theme_extensions.dart'; +import 'package:immich_ui/extensions/build_context_extensions.dart'; +import 'package:immich_ui/extensions/theme_extensions.dart'; class SettingsSwitchListTile extends StatelessWidget { final ValueNotifier valueNotifier;