From ef1ba878c5529b17df6f0083135cfdb03a302d3c Mon Sep 17 00:00:00 2001 From: Alex Rintt <51419598+alexrintt@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:25:07 -0300 Subject: [PATCH] Completely migrate to Material You + Dynamic Colors --- lib/pages/home_page.dart | 39 +- lib/pages/settings_page.dart | 358 +++++---------- lib/screens/app_list_screen.dart | 24 +- lib/screens/background_task_list_screen.dart | 20 +- lib/screens/file_list_screen.dart | 8 +- lib/stores/settings_store.dart | 11 - lib/stores/theme_store.dart | 410 ++++-------------- lib/utils/context_confirm.dart | 2 +- lib/utils/please_translate_me_extension.dart | 4 + lib/widgets/apk_file_menu_options.dart | 3 +- lib/widgets/apk_list_progress_stepper.dart | 1 - lib/widgets/app_list_tile.dart | 39 +- .../background_task_list_contextual_menu.dart | 4 +- lib/widgets/bottom_navigation.dart | 33 +- lib/widgets/file_list_contextual_menu.dart | 2 +- lib/widgets/installed_app_menu_options.dart | 2 +- lib/widgets/main_action_popup_menu.dart | 2 +- lib/widgets/sliver_app_bar.dart | 1 - lib/widgets/sliver_app_bar_translucent.dart | 91 ++-- lib/widgets/sliver_app_top_bar.dart | 13 +- pubspec.lock | 2 +- pubspec.yaml | 1 + 22 files changed, 318 insertions(+), 752 deletions(-) create mode 100644 lib/utils/please_translate_me_extension.dart diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index cb1bad2..0c21b55 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -10,7 +10,7 @@ import '../widgets/bottom_navigation.dart'; extension BottomSpacer on BuildContext { Widget get bottomSpacer => Padding( padding: EdgeInsets.only( - bottom: theme.navigationBarTheme.height!, + bottom: theme.navigationBarTheme.height ?? kToolbarHeight * 2, ), ); @@ -44,6 +44,31 @@ class _HomePageState extends State with BottomNavigationStoreMixin { ); } + late PageController _pageController; + + @override + void initState() { + super.initState(); + + _pageController = PageController(); + + bottomNavigationStore.addListener(() { + if (_pageController.hasClients) { + if (_pageController.page!.toInt() != + bottomNavigationStore.currentIndex) { + _pageController.jumpToPage(bottomNavigationStore.currentIndex); + } + } + }); + } + + @override + void dispose() { + _pageController.dispose(); + + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -57,11 +82,13 @@ class _HomePageState extends State with BottomNavigationStoreMixin { }, ), extendBody: true, - body: Stack( - children: [ - _buildTab(const AppListScreen(), 0), - _buildTab(const BackgroundTaskListScreen(), 1), - _buildTab(const FileListScreen(), 2), + body: PageView( + controller: _pageController, + physics: const NeverScrollableScrollPhysics(), + children: const [ + AppListScreen(), + BackgroundTaskListScreen(), + FileListScreen(), ], ), ); diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart index 470560e..66a74c0 100644 --- a/lib/pages/settings_page.dart +++ b/lib/pages/settings_page.dart @@ -39,6 +39,7 @@ class _SettingsPageState extends State animation: settingsStore, builder: (BuildContext context, Widget? child) { return SliverAppBarTranslucent( + large: true, pinned: !settingsStore.getBoolPreference( SettingsBoolPreference.hideAppBarOnScroll, ), @@ -51,14 +52,9 @@ class _SettingsPageState extends State size: kDefaultIconSize, color: context.isDark ? null : context.primaryColor, ), - onPressed: () => Navigator.pop(context), + onPressed: () => Navigator.maybePop(context), ), - title: Text( - context.strings.settings, - style: context.theme.appBarTheme.titleTextStyle!.copyWith( - color: context.theme.textTheme.labelSmall!.color, - ), - ), + title: Text(context.strings.settings), actions: [ AppIconButton( icon: Icon( @@ -89,19 +85,16 @@ class _SettingsPageState extends State [ SettingsTileTitle(context.strings.export), const ExportLocationSettingsTile(), - const HorizontalRule(), SettingsTileTitle(context.strings.display), const AppThemeSettingsTile(), // const AppFontFamilySettingsTile(), const AppLocalizationSettingsTile(), - const HorizontalRule(), SettingsTileTitle(context.strings.behaviorPreferences), AppBooleanPreferencesSettingsTile( values: SettingsBoolPreference.filterBy( category: SettingsBoolPreferenceCategory.behavior, ), ), - const HorizontalRule(), SettingsTileTitle(context.strings.appearancePreferences), const AppOverscrollPhysicsTile(), AppBooleanPreferencesSettingsTile( @@ -109,13 +102,8 @@ class _SettingsPageState extends State category: SettingsBoolPreferenceCategory.appearance, ), ), - const HorizontalRule(), - SettingsTileTitle(context.strings.donate), - const DonationSettingsTile(), - const HorizontalRule(), SettingsTileTitle(context.strings.links), const RelatedLinks(), - const HorizontalRule(), const Padding( padding: EdgeInsets.all(k20dp), child: Center(child: AnimatedAppName()), @@ -178,14 +166,9 @@ class _RelatedLinksState extends State ), buildTile( title: context.strings.followMeOnGitHub, - onTap: openThisLink('https://github.com/alexrintt'), + onTap: openThisLink('https://tree.alexrintt.io'), description: '@alexrintt', ), - buildTile( - title: context.strings.githubRepository, - onTap: openThisLink('https://github.com/alexrintt/kanade'), - description: 'github.com/alexrintt/kanade', - ), buildTile( title: context.strings.packageAndVersion, onTap: copyThisText(_packageVersion), @@ -208,30 +191,28 @@ class _ExportLocationSettingsTileState extends State with SettingsStoreMixin { @override Widget build(BuildContext context) { - return InkWell( - onTap: settingsStore.requestExportLocation, - child: AnimatedBuilder( - animation: settingsStore, - builder: (BuildContext context, Widget? child) { - final String? exportLocation = stringifyTreeUri( - settingsStore.exportLocation, - ); + return AnimatedBuilder( + animation: settingsStore, + builder: (BuildContext context, Widget? child) { + final String? exportLocation = stringifyTreeUri( + settingsStore.exportLocation, + ); - return AppListTile( - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - leading: Icon(AppIcons.folder.data, size: AppIcons.folder.size), - title: Text(context.strings.selectOutputFolder), - subtitle: Text(exportLocation ?? context.strings.notDefined), - trailing: Icon( - AppIcons.chevronRight.data, - size: AppIcons.chevronRight.size, - ), - ); - }, - ), + return AppListTile( + onTap: settingsStore.requestExportLocation, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, + ), + enableFeedback: true, + leading: Icon(AppIcons.folder.data, size: AppIcons.folder.size), + title: Text(context.strings.selectOutputFolder), + subtitle: Text(exportLocation ?? context.strings.notDefined), + trailing: Icon( + AppIcons.chevronRight.data, + size: AppIcons.chevronRight.size, + ), + ); + }, ); } } @@ -247,29 +228,27 @@ class _AppThemeSettingsTileState extends State with ThemeStoreMixin { @override Widget build(BuildContext context) { - return InkWell( + return AppListTile( onTap: () { showDialog( context: context, builder: (BuildContext context) => const ChangeThemeDialog(), ); }, - child: AppListTile( - tileColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - leading: Icon(AppIcons.styling.data, size: AppIcons.styling.size), - title: Text(context.strings.theme), - subtitle: AnimatedBuilder( - animation: themeStore, - builder: (BuildContext context, Widget? child) { - return Text( - themeStore.currentTheme.getNameString(context.strings), - ); - }, - ), + tileColor: Colors.transparent, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, + ), + enableFeedback: true, + leading: Icon(AppIcons.styling.data, size: AppIcons.styling.size), + title: Text(context.strings.theme), + subtitle: AnimatedBuilder( + animation: themeStore, + builder: (BuildContext context, Widget? child) { + return Text( + themeStore.currentTheme.getNameString(context.strings), + ); + }, ), ); } @@ -318,7 +297,7 @@ class _AppOverscrollPhysicsTileState extends State with ThemeStoreMixin { @override Widget build(BuildContext context) { - return InkWell( + return AppListTile( onTap: () { showDialog( context: context, @@ -326,22 +305,19 @@ class _AppOverscrollPhysicsTileState extends State const ChangeOverscrollPhysicsDialog(), ); }, - child: AppListTile( - tileColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - title: Text(context.strings.overscrollIndicator), - subtitle: AnimatedBuilder( - animation: themeStore, - builder: (BuildContext context, Widget? child) { - return Text( - themeStore.currentOverscrollPhysics - .getNameString(context.strings), - ); - }, - ), + tileColor: Colors.transparent, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, + ), + enableFeedback: true, + title: Text(context.strings.overscrollIndicator), + subtitle: AnimatedBuilder( + animation: themeStore, + builder: (BuildContext context, Widget? child) { + return Text( + themeStore.currentOverscrollPhysics.getNameString(context.strings), + ); + }, ), ); } @@ -394,7 +370,7 @@ class _AppFontFamilySettingsTileState extends State with ThemeStoreMixin { @override Widget build(BuildContext context) { - return InkWell( + return AppListTile( onTap: () { showDialog( context: context, @@ -402,22 +378,20 @@ class _AppFontFamilySettingsTileState extends State const ChangeThemeFontFamilyDialog(), ); }, - child: AppListTile( - tileColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - leading: Icon(AppIcons.fontFamily.data, size: AppIcons.fontFamily.size), - title: Text(context.strings.fontFamily), - subtitle: AnimatedBuilder( - animation: themeStore, - builder: (BuildContext context, Widget? child) { - return Text( - themeStore.currentFontFamily.fontKey, - ); - }, - ), + tileColor: Colors.transparent, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, + ), + enableFeedback: true, + leading: Icon(AppIcons.fontFamily.data, size: AppIcons.fontFamily.size), + title: Text(context.strings.fontFamily), + subtitle: AnimatedBuilder( + animation: themeStore, + builder: (BuildContext context, Widget? child) { + return Text( + themeStore.currentFontFamily.fontKey, + ); + }, ), ); } @@ -467,18 +441,15 @@ mixin BasicTileBuilderMixin on State { VoidCallback? onTap, VoidCallback? onLongPress, }) { - return InkWell( + return AppListTile( onTap: onTap, - onLongPress: onLongPress, - child: AppListTile( - tileColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - title: Text(title), - subtitle: description != null ? Text(description) : null, + tileColor: Colors.transparent, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, ), + enableFeedback: true, + title: Text(title), + subtitle: description != null ? Text(description) : null, ); } @@ -493,56 +464,6 @@ mixin BasicTileBuilderMixin on State { } } -class DonationSettingsTile extends StatefulWidget { - const DonationSettingsTile({super.key}); - - @override - State createState() => _DonationSettingsTileState(); -} - -class _DonationSettingsTileState extends State - with BasicTileBuilderMixin { - final String _btcAddress = 'bc1qacmk9z48m7upaaq2jl80u6dxsyld443jdjufv9'; - final Uri _livePix = Uri.parse('https://livepix.gg/alexrintt'); - final Uri _githubSponsor = Uri.parse('https://github.com/sponsors/alexrintt'); - final Uri _kofi = Uri.parse('https://ko-fi.com/alexrintt'); - - @override - Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - buildTile( - title: context.strings.donateOnGitHub, - onTap: openThisLink(_githubSponsor.toString()), - description: _githubSponsor.host + _githubSponsor.path, - ), - buildTile( - title: context.strings.donateOnKofi, - onTap: openThisLink(_kofi.toString()), - description: _kofi.host + _kofi.path, - ), - buildTile( - title: context.strings.donateUsingPix, - onTap: openThisLink(_livePix.toString()), - description: _livePix.host + _livePix.path, - ), - buildTile( - title: context.strings.donateUsingBtc, - onLongPress: copyThisText(_btcAddress), - onTap: copyThisText(_btcAddress), - description: _btcAddress, - ), - buildTile( - title: context.strings.otherDonationMethods, - onTap: openThisLink('https://donate.alexrintt.io'), - description: 'donate.alexrintt.io', - ), - ], - ); - } -} - class AppBooleanPreferencesSettingsTile extends StatefulWidget { const AppBooleanPreferencesSettingsTile({super.key, required this.values}); @@ -564,65 +485,26 @@ class _AppBooleanPreferencesSettingsTileState mainAxisSize: MainAxisSize.min, children: [ for (final SettingsBoolPreference preference in widget.values) - InkWell( + AppListTile( + tileColor: Colors.transparent, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, + ), onTap: () => settingsStore.toggleBoolPreference(preference), - child: AppListTile( - tileColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - isThreeLine: true, - trailing: Switch( - trackColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.selected)) { - return context.primaryColor; - } - return context.scaffoldBackgroundColor; - }, - ), - overlayColor: MaterialStateProperty.resolveWith( - (Set states) { - return context.theme.highlightColor; - }, - ), - thumbColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.selected)) { - if (context.isDark) { - return context.theme.disabledColor; - } - return context.theme.dividerColor; - } - - return context.isDark - ? context.theme.disabledColor - : context.theme.disabledColor.withOpacity(.2); - }, - ), - splashRadius: k12dp, - thumbIcon: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.selected)) { - return Icon(Icons.check, color: context.primaryColor); - } - return null; - }, - ), - activeColor: context.primaryColor, - value: settingsStore.getBoolPreference(preference), - onChanged: (bool value) => settingsStore - .setBoolPreference(preference, value: value), - ), - title: Text(preference.getNameString(context.strings)), - subtitle: Text( - preference.getDescriptionString(context.strings), - style: context.textTheme.labelLarge!.copyWith( - color: context.isDark - ? context.theme.disabledColor - : context.theme.disabledColor.withOpacity(.35), - ), + enableFeedback: true, + isThreeLine: true, + trailing: Switch( + value: settingsStore.getBoolPreference(preference), + onChanged: (bool value) => + settingsStore.setBoolPreference(preference, value: value), + ), + title: Text(preference.getNameString(context.strings)), + subtitle: Text( + preference.getDescriptionString(context.strings), + style: context.textTheme.labelLarge!.copyWith( + color: context.isDark + ? context.theme.disabledColor + : context.theme.disabledColor.withOpacity(.35), ), ), ), @@ -645,7 +527,7 @@ class _AppLocalizationSettingsTileState extends State with LocalizationStoreMixin { @override Widget build(BuildContext context) { - return InkWell( + return AppListTile( onTap: () { showDialog( context: context, @@ -653,32 +535,30 @@ class _AppLocalizationSettingsTileState const ChangeAppLocalizationDialog(), ); }, - child: AppListTile( - tileColor: Colors.transparent, - contentPadding: const EdgeInsets.symmetric( - horizontal: k10dp, - ), - enableFeedback: true, - leading: Icon(AppIcons.language.data, size: AppIcons.language.size), - title: Text(context.strings.language), - subtitle: AnimatedBuilder( - animation: localizationStore, - builder: (BuildContext context, Widget? child) { - if (localizationStore.fixedLocale == null) { - String systemLanguageNotSupportedWarn = ''; - - if (!localizationStore.isSystemLocalizationSupported) { - systemLanguageNotSupportedWarn = - ', ${localizationStore.deviceLocale.fullName} ${context.strings.isNotSupportedYet}'; - } - - return Text( - '${context.strings.followTheSystem} (${localizationStore.locale.fullName}$systemLanguageNotSupportedWarn)', - ); + tileColor: Colors.transparent, + contentPadding: const EdgeInsets.symmetric( + horizontal: k10dp, + ), + enableFeedback: true, + leading: Icon(AppIcons.language.data, size: AppIcons.language.size), + title: Text(context.strings.language), + subtitle: AnimatedBuilder( + animation: localizationStore, + builder: (BuildContext context, Widget? child) { + if (localizationStore.fixedLocale == null) { + String systemLanguageNotSupportedWarn = ''; + + if (!localizationStore.isSystemLocalizationSupported) { + systemLanguageNotSupportedWarn = + ', ${localizationStore.deviceLocale.fullName} ${context.strings.isNotSupportedYet}'; } - return Text(localizationStore.fixedLocale!.fullName); - }, - ), + + return Text( + '${context.strings.followTheSystem} (${localizationStore.locale.fullName}$systemLanguageNotSupportedWarn)', + ); + } + return Text(localizationStore.fixedLocale!.fullName); + }, ), ); } diff --git a/lib/screens/app_list_screen.dart b/lib/screens/app_list_screen.dart index 634da6e..a2b4d89 100644 --- a/lib/screens/app_list_screen.dart +++ b/lib/screens/app_list_screen.dart @@ -21,10 +21,10 @@ import '../widgets/animated_flip_counter.dart'; import '../widgets/app_list_contextual_menu.dart'; import '../widgets/device_app_tile.dart'; import '../widgets/drag_select_scroll_notifier.dart'; +import '../widgets/installed_app_menu_options.dart'; import '../widgets/loading.dart'; import '../widgets/looks_empty_here.dart'; import '../widgets/multi_animated_builder.dart'; -import '../widgets/installed_app_menu_options.dart'; class AppListScreen extends StatefulWidget { const AppListScreen({super.key}); @@ -33,13 +33,19 @@ class AppListScreen extends StatefulWidget { State createState() => _AppListScreenState(); } -class _AppListScreenState extends State { +class _AppListScreenState extends State + with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { + super.build(context); + return const AppListScreenProvider( child: AppListScreenConsumer(), ); } + + @override + bool get wantKeepAlive => true; } class AppListScreenProvider extends StatefulWidget { @@ -221,16 +227,7 @@ class _MainAppListState extends State ) { return FilterChip( padding: const EdgeInsets.all(k2dp), - label: Text( - text, - style: TextStyle( - color: settingsStore.getBoolPreference(preference) - ? context.scaffoldBackgroundColor - : null, - ), - ), - backgroundColor: context.dividerColor, - selectedColor: context.primaryColor, + label: Text(text), onSelected: (bool value) async { final bool displaySystemApps = settingsStore .getBoolPreference(SettingsBoolPreference.displaySystemApps); @@ -315,9 +312,6 @@ class _MainAppListState extends State duration: const Duration(milliseconds: 500), count: store.collection.length, curve: Curves.easeInOut, - textStyle: TextStyle( - color: context.primaryColor.withOpacity(.3), - ), ), backgroundColor: context.theme.canvasColor, ), diff --git a/lib/screens/background_task_list_screen.dart b/lib/screens/background_task_list_screen.dart index 641f421..60d4d8f 100644 --- a/lib/screens/background_task_list_screen.dart +++ b/lib/screens/background_task_list_screen.dart @@ -33,13 +33,19 @@ class BackgroundTaskListScreen extends StatefulWidget { _BackgroundTaskListScreenState(); } -class _BackgroundTaskListScreenState extends State { +class _BackgroundTaskListScreenState extends State + with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { + super.build(context); + return const BackgroundTaskListScreenProvider( child: BackgroundTaskListScreenConsumer(), ); } + + @override + bool get wantKeepAlive => true; } class BackgroundTaskListScreenProvider extends StatefulWidget { @@ -231,16 +237,8 @@ class _BackgroundTaskTileState extends State } return widget.isSelected - ? Icon( - AppIcons.checkboxSelected.data, - size: kDefaultIconSize, - color: context.primaryColor, - ) - : Icon( - AppIcons.checkboxUnselected.data, - size: kDefaultIconSize, - color: context.primaryColor, - ); + ? Icon(AppIcons.checkboxSelected.data, size: kDefaultIconSize) + : Icon(AppIcons.checkboxUnselected.data, size: kDefaultIconSize); } Widget _buildLeading() => PackageImageUri(uri: widget.task.apkIconUri); diff --git a/lib/screens/file_list_screen.dart b/lib/screens/file_list_screen.dart index 7dacf4b..8e4efae 100644 --- a/lib/screens/file_list_screen.dart +++ b/lib/screens/file_list_screen.dart @@ -49,14 +49,20 @@ class FileListScreenProvider extends StatefulWidget { State createState() => _FileListScreenProviderState(); } -class _FileListScreenProviderState extends State { +class _FileListScreenProviderState extends State + with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { + super.build(context); + return ChangeNotifierProvider( create: (BuildContext context) => getIt(), child: const FileListScreenConsumer(), ); } + + @override + bool get wantKeepAlive => true; } class FileListScreenConsumer extends StatefulWidget { diff --git a/lib/stores/settings_store.dart b/lib/stores/settings_store.dart index 2f1f9f4..dba9308 100644 --- a/lib/stores/settings_store.dart +++ b/lib/stores/settings_store.dart @@ -28,9 +28,6 @@ class SettingsStore extends ChangeNotifier { bool get shouldConfirmIrreversibleActions => getBoolPreference(SettingsBoolPreference.confirmIrreversibleActions); - bool get transparentNavigationBar => - getBoolPreference(SettingsBoolPreference.transparentNavigationBar); - bool get shouldExtractWithSingleClick => getBoolPreference(SettingsBoolPreference.extractWithSingleClick); @@ -171,10 +168,6 @@ enum SettingsBoolPreference { defaultValue: true, category: SettingsBoolPreferenceCategory.behavior, ), - transparentNavigationBar( - defaultValue: false, - category: SettingsBoolPreferenceCategory.appearance, - ), hideAppBarOnScroll( defaultValue: true, category: SettingsBoolPreferenceCategory.appearance, @@ -217,8 +210,6 @@ enum SettingsBoolPreference { return strings.displayBuiltInApps; case SettingsBoolPreference.displayUserInstalledApps: return strings.displayUserInstalledApps; - case SettingsBoolPreference.transparentNavigationBar: - return strings.transparentNavigationBar; } } @@ -234,8 +225,6 @@ enum SettingsBoolPreference { return strings.displayBuiltInAppsExplanation; case SettingsBoolPreference.displayUserInstalledApps: return strings.displayUserInstalledAppsExplanation; - case SettingsBoolPreference.transparentNavigationBar: - return strings.transparentNavigationBarExplanation; case SettingsBoolPreference.extractWithSingleClick: return strings.extractWithSingleClickExplanation; } diff --git a/lib/stores/theme_store.dart b/lib/stores/theme_store.dart index a845a9e..6a23c2b 100644 --- a/lib/stores/theme_store.dart +++ b/lib/stores/theme_store.dart @@ -1,40 +1,30 @@ import 'dart:ui'; +import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_shared_tools/flutter_shared_tools.dart'; +import 'package:material_color_utilities/material_color_utilities.dart'; import '../setup.dart'; import '../widgets/no_glow_scroll_behavior.dart'; import 'key_value_storage.dart'; enum AppTheme { - fullDark, darkDimmed, - darkSimple, defaultLight, - greenDark, - redDark, followSystem; String getNameString(AppLocalizations strings) { switch (this) { case AppTheme.darkDimmed: return strings.darkDimmed; - case AppTheme.darkSimple: - return strings.darkSimple; case AppTheme.defaultLight: return strings.light; case AppTheme.followSystem: return strings.followTheSystem; - case AppTheme.fullDark: - return strings.fullDark; - case AppTheme.greenDark: - return strings.greenDark; - case AppTheme.redDark: - return strings.redDark; } } @@ -78,12 +68,66 @@ class ThemeStore extends ChangeNotifier { ScrollBehavior get scrollBehavior => _currentOverscrollPhysics.behavior; + late (ColorScheme?, ColorScheme?) _platformAdaptiveColorPalettes; + Future load() async { + await _loadOSPalette(); await _loadAppFontFamily(); await _loadAppTheme(); await _loadOverscrollPhysics(); } + // Platform messages are asynchronous, so we initialize in an async method. + Future<(ColorScheme?, ColorScheme?)> + _getPlatformDynamicColorPalettes() async { + try { + final CorePalette? corePalette = + await DynamicColorPlugin.getCorePalette(); + + if (corePalette != null) { + debugPrint('dynamic_color: Core palette detected.'); + + return ( + corePalette.toColorScheme(), + corePalette.toColorScheme(brightness: Brightness.dark) + ); + } + } on PlatformException { + debugPrint('dynamic_color: Failed to obtain core palette.'); + } + + try { + final Color? accentColor = await DynamicColorPlugin.getAccentColor(); + + if (accentColor != null) { + debugPrint('dynamic_color: Accent color detected.'); + + return ( + ColorScheme.fromSeed( + seedColor: accentColor, + brightness: Brightness.light, + ), + ColorScheme.fromSeed( + seedColor: accentColor, + brightness: Brightness.dark, + ), + ); + } + } on PlatformException { + debugPrint('dynamic_color: Failed to obtain accent color.'); + } + + debugPrint('dynamic_color: Dynamic color not detected on this device.'); + + return (null, null); + } + + Future _loadOSPalette() async { + final (ColorScheme?, ColorScheme?) p = + await _getPlatformDynamicColorPalettes(); + _platformAdaptiveColorPalettes = p; + } + Future _loadOverscrollPhysics() async { final String? previousOverscrollPhysics = await _keyValueStorage.get(_kAppScrollBehaviorStorageKey); @@ -144,156 +188,41 @@ class ThemeStore extends ChangeNotifier { } ThemeData _darkDimmedThemeData() { - const Color kCardColor = Color(0xFF25262E); - const Color kBackgroundColor = Color(0xFF25262E); - const Color selectedTileColor = Color.fromARGB(255, 34, 35, 43); - - const Color kCanvasColor = Color(0xff282931); - const Color kPrimaryColor = Color(0xffb8b9c5); - const Color kSecondaryColor = Colors.black; + final (ColorScheme? _, ColorScheme? darkAdaptivePalette) = + _platformAdaptiveColorPalettes; return createThemeData( - canvasColor: kCanvasColor, - backgroundColor: kBackgroundColor, - cardColor: kCardColor, - primaryColor: kPrimaryColor, - secondaryColor: kSecondaryColor, - textColor: const Color.fromARGB(255, 176, 178, 206), - headlineColor: Colors.white, - disabledColor: const Color(0xff535466), - selectedTileColor: selectedTileColor, - base: ThemeData.dark(), - fontFamily: _currentFontFamily, + base: ThemeData.from( + useMaterial3: true, + colorScheme: darkAdaptivePalette ?? + ColorScheme.fromSeed( + seedColor: Colors.blue, + brightness: Brightness.dark, + ), + ), ); } ThemeData _defaultDarkThemeData() { - const Color kCardColor = Color(0xFF313338); - const Color kBackgroundColor = Color(0xFF2B2D31); - const Color selectedTileColor = Color(0xff1E1F22); + final (ColorScheme? _, ColorScheme? darkAdaptivePalette) = + _platformAdaptiveColorPalettes; - const Color kCanvasColor = Color(0xff313338); - const Color kPrimaryColor = Color(0xffb8b9c5); - const Color kSecondaryColor = Colors.black; - - return createThemeData( - canvasColor: kCanvasColor, - backgroundColor: kBackgroundColor, - cardColor: kCardColor, - primaryColor: kPrimaryColor, - secondaryColor: kSecondaryColor, - textColor: const Color.fromARGB(255, 176, 177, 206), - headlineColor: Colors.white, - disabledColor: const Color(0xff535466), - selectedTileColor: selectedTileColor, - base: ThemeData.dark(), - fontFamily: _currentFontFamily, - ); + return _darkDimmedThemeData(); } ThemeData _defaultLightThemeData() { - const Color kBackgroundColor = Color(0xffe8e8e8); - const Color selectedTileColor = kBackgroundColor; - const Color kCardColor = Color(0xfff7f2f9); - const Color kCanvasColor = Color(0xfff7f2f9); - const MaterialColor kPrimaryColor = MaterialColor( - 0xff262626, - { - 50: Color(0xff262626), - 100: Color(0xff262626), - 200: Color(0xff262626), - 300: Color(0xff262626), - 400: Color(0xff262626), - 500: Color(0xff262626), - 600: Color(0xff262626), - 700: Color(0xff262626), - 800: Color(0xff262626), - 900: Color(0xff262626), - }, - ); - const MaterialColor kSecondaryColor = Colors.blue; - - return createThemeData( - canvasColor: kCanvasColor, - backgroundColor: kBackgroundColor, - cardColor: kCardColor, - primaryColor: kPrimaryColor, - secondaryColor: kSecondaryColor, - textColor: Colors.black, - headlineColor: const Color(0xff111111), - selectedTileColor: selectedTileColor, - disabledColor: Colors.black87, - base: ThemeData.light(), - fontFamily: _currentFontFamily, - ); - } - - ThemeData _fullDarkThemeData() { - const Color kBackgroundColor = Color.fromARGB(255, 8, 8, 8); - const Color kCardColor = kBackgroundColor; - const Color kPrimaryColor = Color(0xFFFFFFFF); - const Color kCanvasColor = Color.fromARGB(255, 14, 14, 14); - const Color kSelectedTileColor = Color.fromARGB(255, 24, 24, 24); - const Color kSecondaryColor = Colors.white; + final (ColorScheme? lightAdaptivePalette, ColorScheme? _) = + _platformAdaptiveColorPalettes; return createThemeData( - canvasColor: kCanvasColor, - backgroundColor: kBackgroundColor, - cardColor: kCardColor, - primaryColor: kPrimaryColor, - secondaryColor: kSecondaryColor, - textColor: Colors.white70, - headlineColor: Colors.white, - disabledColor: const Color.fromARGB(255, 78, 78, 78), - selectedTileColor: kSelectedTileColor, - base: ThemeData.dark(), - fontFamily: _currentFontFamily, - ); - } - - ThemeData _darkGreenThemeData() { - const Color kBackgroundColor = Color.fromARGB(255, 8, 8, 8); - const Color kCardColor = kBackgroundColor; - const Color kPrimaryColor = Color(0xFF69F0AE); - const Color kCanvasColor = Color.fromARGB(255, 10, 14, 10); - const Color selectedTileColor = Color.fromARGB(255, 15, 25, 15); - const MaterialColor kSecondaryColor = Colors.green; - - return createThemeData( - canvasColor: kCanvasColor, - backgroundColor: kBackgroundColor, - cardColor: kCardColor, - primaryColor: kPrimaryColor, - secondaryColor: kSecondaryColor, - textColor: kPrimaryColor.withOpacity(0.7), - headlineColor: kPrimaryColor, - disabledColor: const Color.fromARGB(255, 44, 75, 59), - selectedTileColor: selectedTileColor, - base: ThemeData.dark(), - fontFamily: _currentFontFamily, - ); - } - - ThemeData _darkBloodThemeData() { - const Color kBackgroundColor = Color.fromARGB(255, 8, 8, 8); - const Color kCardColor = kBackgroundColor; - const Color kPrimaryColor = Color(0xFFFF5252); - const Color kCanvasColor = Color.fromARGB(255, 15, 10, 10); - const Color selectedTileColor = Color.fromARGB(255, 25, 15, 15); - const Color kSecondaryColor = kPrimaryColor; - - return createThemeData( - canvasColor: kCanvasColor, - backgroundColor: kBackgroundColor, - cardColor: kCardColor, - primaryColor: kPrimaryColor, - secondaryColor: kSecondaryColor, - textColor: kPrimaryColor.withOpacity(0.7), - headlineColor: kPrimaryColor, - disabledColor: const Color.fromARGB(255, 87, 36, 36), - selectedTileColor: selectedTileColor, - base: ThemeData.dark(), - fontFamily: _currentFontFamily, + base: ThemeData.from( + useMaterial3: true, + colorScheme: lightAdaptivePalette ?? + ColorScheme.fromSeed( + seedColor: Colors.blue, + // brightness: Brightness.light, + ), + ), ); } @@ -303,18 +232,11 @@ class ThemeStore extends ChangeNotifier { return _darkDimmedThemeData(); case AppTheme.defaultLight: return _defaultLightThemeData(); - case AppTheme.fullDark: - return _fullDarkThemeData(); - case AppTheme.greenDark: - return _darkGreenThemeData(); - case AppTheme.redDark: - return _darkBloodThemeData(); + case AppTheme.followSystem: return currentThemeBrightness == Brightness.dark ? _defaultDarkThemeData() : _defaultLightThemeData(); - case AppTheme.darkSimple: - return _defaultDarkThemeData(); } } @@ -324,16 +246,8 @@ class ThemeStore extends ChangeNotifier { return Brightness.dark; case AppTheme.defaultLight: return Brightness.light; - case AppTheme.fullDark: - return Brightness.dark; - case AppTheme.greenDark: - return Brightness.dark; - case AppTheme.redDark: - return Brightness.dark; case AppTheme.followSystem: return SchedulerBinding.instance.platformDispatcher.platformBrightness; - case AppTheme.darkSimple: - return Brightness.dark; } } @@ -370,8 +284,8 @@ class ThemeStore extends ChangeNotifier { } enum AppFontFamily { - robotoMono('Roboto Mono', 1, displayable: true), - inconsolata('Inconsolata', 1, displayable: true), + robotoMono('Roboto Mono', 1, displayable: false), + inconsolata('Inconsolata', 1, displayable: false), // This font is used in the logo only, so it is not displayable. forward('Forward', 1, displayable: false); @@ -449,165 +363,7 @@ enum OverscrollPhysics { } ThemeData createThemeData({ - required AppFontFamily fontFamily, - required Color backgroundColor, - required Color cardColor, - required Color canvasColor, required ThemeData base, - required Color secondaryColor, - required Color primaryColor, - required Color textColor, - required Color disabledColor, - required Color headlineColor, - required Color selectedTileColor, }) { - // final String fontFamilyName = fontFamily.fontKey; - - final TextTheme textTheme = - base.textTheme.merge(Typography.material2021().black).apply( - // fontFamily: fontFamilyName, - bodyColor: textColor, - ); - - return base.copyWith( - bottomAppBarTheme: base.bottomAppBarTheme.copyWith( - elevation: 0, - color: canvasColor, - surfaceTintColor: Colors.transparent, - ), - chipTheme: base.chipTheme.copyWith( - // shadowColor: Colors.transparent, - // surfaceTintColor: Colors.transparent, - // elevation: , - backgroundColor: canvasColor, - selectedColor: disabledColor, - // elevation: 0.0, - // pressElevation: 0.0, - side: BorderSide.none, - shape: ContinuousRectangleBorder( - borderRadius: BorderRadius.circular(k8dp), - side: const BorderSide( - color: Colors.transparent, - width: 0.0, - ), - ), - ), - textButtonTheme: TextButtonThemeData( - style: (base.textButtonTheme.style ?? const ButtonStyle()).copyWith( - foregroundColor: - MaterialStateProperty.resolveWith((_) => textColor), - surfaceTintColor: MaterialStateProperty.resolveWith( - (_) => Colors.transparent, - ), - overlayColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.isNotEmpty) { - return canvasColor; - } - return null; - }, - ), - ), - ), - scaffoldBackgroundColor: backgroundColor, - disabledColor: disabledColor, - textTheme: textTheme, - primaryColor: primaryColor, - dividerColor: disabledColor.withOpacity(.2), - dividerTheme: base.dividerTheme.copyWith( - color: disabledColor, - ), - appBarTheme: base.appBarTheme.copyWith( - surfaceTintColor: Colors.transparent, - backgroundColor: cardColor, - shadowColor: backgroundColor, - elevation: 0, - scrolledUnderElevation: 1, - centerTitle: true, - titleTextStyle: - (base.appBarTheme.titleTextStyle ?? textTheme.displayLarge)! - .copyWith(color: textColor, fontSize: k8dp), - iconTheme: (base.appBarTheme.iconTheme ?? const IconThemeData.fallback()) - .copyWith( - color: textColor, - ), - systemOverlayStyle: SystemUiOverlayStyle( - statusBarBrightness: base.brightness.inverse, - statusBarColor: Colors.transparent, - ), - ), - listTileTheme: base.listTileTheme.copyWith( - iconColor: textColor.withOpacity(0.8), - textColor: textColor, - titleTextStyle: - base.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.bold), - enableFeedback: true, - selectedTileColor: selectedTileColor, - ), - splashColor: primaryColor.withOpacity(0.2), - highlightColor: primaryColor.withOpacity(0.2), - radioTheme: base.radioTheme.copyWith( - fillColor: MaterialStateProperty.all(primaryColor), - ), - popupMenuTheme: base.popupMenuTheme.copyWith(elevation: 0), - bottomSheetTheme: base.bottomSheetTheme.copyWith( - backgroundColor: backgroundColor, - elevation: 0, - modalBackgroundColor: backgroundColor, - surfaceTintColor: Colors.transparent, - modalElevation: 0, - shape: const ContinuousRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(k20dp), - topRight: Radius.circular(k20dp), - ), - ), - // modalBarrierColor: Colors.black.withOpacity(.75), - ), - dialogTheme: base.dialogTheme.copyWith( - surfaceTintColor: Colors.transparent, - ), - navigationBarTheme: base.navigationBarTheme.copyWith( - backgroundColor: canvasColor, - elevation: 10, - height: kToolbarHeight * 1.3, - surfaceTintColor: Colors.transparent, - shadowColor: backgroundColor, - indicatorColor: primaryColor, - labelTextStyle: MaterialStateProperty.resolveWith( - (Set states) { - return textTheme.labelLarge!.copyWith(color: primaryColor); - }, - ), - iconTheme: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.selected)) { - return base.iconTheme.copyWith(color: backgroundColor); - } - return base.iconTheme.copyWith(color: primaryColor); - }, - ), - labelBehavior: NavigationDestinationLabelBehavior.alwaysShow, - ), - dialogBackgroundColor: backgroundColor, - canvasColor: canvasColor, - cardColor: cardColor, - tooltipTheme: base.tooltipTheme.copyWith( - textStyle: TextStyle(color: backgroundColor), - decoration: BoxDecoration( - color: textColor, - borderRadius: BorderRadius.circular(k1dp), - ), - ), - cardTheme: base.cardTheme.copyWith( - shadowColor: backgroundColor, - ), - colorScheme: base.colorScheme.copyWith( - primary: primaryColor, - secondary: secondaryColor, - background: backgroundColor, - outline: disabledColor, - ), - useMaterial3: true, - ); + return base.copyWith(useMaterial3: true); } diff --git a/lib/utils/context_confirm.dart b/lib/utils/context_confirm.dart index 685ad47..7ca4391 100644 --- a/lib/utils/context_confirm.dart +++ b/lib/utils/context_confirm.dart @@ -37,7 +37,7 @@ Future showConfirmationModal({ }, child: Text( context.strings.confirm, - style: const TextStyle(color: Colors.red), + style: TextStyle(color: context.colorScheme.error), ), ), ], diff --git a/lib/utils/please_translate_me_extension.dart b/lib/utils/please_translate_me_extension.dart new file mode 100644 index 0000000..dbf9d8b --- /dev/null +++ b/lib/utils/please_translate_me_extension.dart @@ -0,0 +1,4 @@ +extension PleaseTranslateMe on String { + // Getter to easy identify hardcoded strings that needs a translation. + String get pleaseTranslateMe => this; +} diff --git a/lib/widgets/apk_file_menu_options.dart b/lib/widgets/apk_file_menu_options.dart index 1bbb08e..ad6f134 100644 --- a/lib/widgets/apk_file_menu_options.dart +++ b/lib/widgets/apk_file_menu_options.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_shared_tools/flutter_shared_tools.dart'; import 'package:shared_storage/shared_storage.dart'; import '../stores/device_apps_store.dart'; @@ -185,7 +186,7 @@ class _ApkFileMenuOptionsState extends State icon: Icon( AppIcons.delete.data, size: kDefaultIconSize, - color: Colors.red, + color: context.colorScheme.error, ), tooltip: context.strings.delete, onTap: () { diff --git a/lib/widgets/apk_list_progress_stepper.dart b/lib/widgets/apk_list_progress_stepper.dart index 65614f1..d3d054e 100644 --- a/lib/widgets/apk_list_progress_stepper.dart +++ b/lib/widgets/apk_list_progress_stepper.dart @@ -163,7 +163,6 @@ class _StorageRequirementsProgressStepperState child: Stepper( dividerColor: context.theme.disabledColor, indexedTextColor: context.isDark ? context.primaryColor : null, - elevation: 0, controlsBuilder: _buildStepperControls, currentStep: _currentStep, stepIconBuilder: diff --git a/lib/widgets/app_list_tile.dart b/lib/widgets/app_list_tile.dart index 4197b8d..59e6b0d 100644 --- a/lib/widgets/app_list_tile.dart +++ b/lib/widgets/app_list_tile.dart @@ -4,6 +4,7 @@ import 'package:flutter_shared_tools/flutter_shared_tools.dart'; import '../stores/settings_store.dart'; import '../utils/app_icons.dart'; import '../utils/app_localization_strings.dart'; +import '../utils/please_translate_me_extension.dart'; import 'app_icon_button.dart'; const Size kLeadingSize = Size.square(55); @@ -328,7 +329,7 @@ class _AppListTileState extends State with SettingsStoreMixin { widget.onPopupMenuTapped != null) { child = AppIconButton( icon: Icon(AppIcons.more.data, size: AppIcons.more.size), - tooltip: 'Show more options', + tooltip: 'Show more options'.pleaseTranslateMe, onTap: () { if (widget.popupMenuBuilder != null) { showModalBottomSheet( @@ -360,18 +361,9 @@ class _AppListTileState extends State with SettingsStoreMixin { } ShapeBorder? get _defaultShape { - if (!widget.flat) { - return ContinuousRectangleBorder( - borderRadius: BorderRadius.circular(k8dp), - ); - } return null; } - Color? get _defaultTileColor { - return widget.flat ? null : context.theme.canvasColor; - } - @override Widget build(BuildContext context) { Widget child = AnimatedBuilder( @@ -386,28 +378,14 @@ class _AppListTileState extends State with SettingsStoreMixin { dense: widget.dense, visualDensity: widget.visualDensity ?? VisualDensity.compact, shape: widget.shape ?? _defaultShape, - style: widget.style, - selectedColor: widget.selectedColor, - iconColor: widget.iconColor, - textColor: widget.textColor, - contentPadding: widget.contentPadding ?? const EdgeInsets.all(k4dp), enabled: widget.enabled, - onTap: widget.onTap, - onLongPress: widget.onLongPress, - onFocusChange: widget.onFocusChange, + onTap: widget.flat ? widget.onTap : null, + onLongPress: widget.flat ? widget.onLongPress : null, mouseCursor: widget.mouseCursor, selected: widget.selected, - focusColor: widget.focusColor, - hoverColor: widget.hoverColor, - splashColor: widget.splashColor, - focusNode: widget.focusNode, - autofocus: widget.autofocus, - tileColor: widget.tileColor ?? _defaultTileColor, + tileColor: widget.tileColor, selectedTileColor: widget.selectedTileColor, - enableFeedback: widget.enableFeedback, horizontalTitleGap: widget.horizontalTitleGap, - minVerticalPadding: widget.minVerticalPadding, - minLeadingWidth: widget.minLeadingWidth, ); }, ); @@ -417,7 +395,12 @@ class _AppListTileState extends State with SettingsStoreMixin { padding: const EdgeInsets.symmetric(horizontal: k3dp), child: Card( shape: _defaultShape, - child: child, + clipBehavior: Clip.hardEdge, + child: InkWell( + onTap: widget.onTap, + onLongPress: widget.onLongPress, + child: child, + ), ), ); } diff --git a/lib/widgets/background_task_list_contextual_menu.dart b/lib/widgets/background_task_list_contextual_menu.dart index 38b8090..d0b59f9 100644 --- a/lib/widgets/background_task_list_contextual_menu.dart +++ b/lib/widgets/background_task_list_contextual_menu.dart @@ -68,7 +68,7 @@ class _BackgroundTaskListContextualMenuState icon: Icon( AppIcons.delete.data, size: kDefaultIconSize, - color: Colors.red, + color: context.colorScheme.error, ), ), AppIconButton( @@ -138,7 +138,7 @@ class _BackgroundTaskListContextualMenuState ? AppIcons.delete.data : AppIcons.x.data, size: kDefaultIconSize, - color: Colors.red, + color: context.colorScheme.error, ), tooltip: context.strings.remove, onTap: () async { diff --git a/lib/widgets/bottom_navigation.dart b/lib/widgets/bottom_navigation.dart index 76d3c82..5c7ad85 100644 --- a/lib/widgets/bottom_navigation.dart +++ b/lib/widgets/bottom_navigation.dart @@ -1,7 +1,4 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; -import 'package:flutter_shared_tools/flutter_shared_tools.dart'; import '../stores/background_task_store.dart'; import '../stores/settings_store.dart'; @@ -37,15 +34,7 @@ class _BottomNavigationState extends State backgroundTaskStore, ], builder: (BuildContext context, Widget? child) { - final bool transparentNavigationBar = - settingsStore.transparentNavigationBar; - - Widget navigationBar = NavigationBar( - backgroundColor: transparentNavigationBar ? Colors.transparent : null, - shadowColor: transparentNavigationBar ? Colors.transparent : null, - surfaceTintColor: - transparentNavigationBar ? Colors.transparent : null, - elevation: transparentNavigationBar ? 0.0 : null, + final Widget navigationBar = NavigationBar( selectedIndex: widget.index, onDestinationSelected: _select, destinations: [ @@ -77,26 +66,6 @@ class _BottomNavigationState extends State ], ); - if (transparentNavigationBar) { - navigationBar = Container( - decoration: BoxDecoration( - border: Border( - top: BorderSide( - color: context.primaryColor, - width: 2, - ), - ), - ), - height: context.theme.navigationBarTheme.height, - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: k3dp, sigmaY: k3dp), - child: navigationBar, - ), - ), - ); - } - return navigationBar; }, ); diff --git a/lib/widgets/file_list_contextual_menu.dart b/lib/widgets/file_list_contextual_menu.dart index afff2c1..278ea45 100644 --- a/lib/widgets/file_list_contextual_menu.dart +++ b/lib/widgets/file_list_contextual_menu.dart @@ -65,7 +65,7 @@ class _FileListContextualMenuState extends State icon: Icon( AppIcons.delete.data, size: kDefaultIconSize, - color: Colors.red, + color: context.colorScheme.error, ), ), AppIconButton( diff --git a/lib/widgets/installed_app_menu_options.dart b/lib/widgets/installed_app_menu_options.dart index 10d58d9..8df8151 100644 --- a/lib/widgets/installed_app_menu_options.dart +++ b/lib/widgets/installed_app_menu_options.dart @@ -220,7 +220,7 @@ class _InstalledAppMenuOptionsState extends State icon: Icon( AppIcons.delete.data, size: kDefaultIconSize, - color: Colors.red, + color: context.colorScheme.error, ), onTap: () { context.pop(); diff --git a/lib/widgets/main_action_popup_menu.dart b/lib/widgets/main_action_popup_menu.dart index 494f6b2..2d73d63 100644 --- a/lib/widgets/main_action_popup_menu.dart +++ b/lib/widgets/main_action_popup_menu.dart @@ -42,6 +42,7 @@ class _MainActionPopupMenu extends State const double kChipSpacing = k4dp; return Dialog( + backgroundColor: context.colorScheme.background, clipBehavior: Clip.hardEdge, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -117,7 +118,6 @@ class ActionButton extends StatelessWidget { @override Widget build(BuildContext context) { - // return Container(color: Colors.red, width: 100, height: 50); Widget result = RawChip( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, diff --git a/lib/widgets/sliver_app_bar.dart b/lib/widgets/sliver_app_bar.dart index 6595020..510124c 100644 --- a/lib/widgets/sliver_app_bar.dart +++ b/lib/widgets/sliver_app_bar.dart @@ -1347,7 +1347,6 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { ) : flexibleSpace, bottom: bottom, - elevation: isScrolledUnder ? elevation : 0.0, scrolledUnderElevation: scrolledUnderElevation, shadowColor: shadowColor, surfaceTintColor: surfaceTintColor, diff --git a/lib/widgets/sliver_app_bar_translucent.dart b/lib/widgets/sliver_app_bar_translucent.dart index 306bc46..b9d0a9f 100644 --- a/lib/widgets/sliver_app_bar_translucent.dart +++ b/lib/widgets/sliver_app_bar_translucent.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/material.dart' hide SliverAppBar; import 'package:flutter_shared_tools/flutter_shared_tools.dart'; @@ -23,9 +21,9 @@ class SliverAppBarTranslucent extends StatefulWidget { this.foregroundColor, this.translucentBorderWidth = 2, this.translucentBlurSigma = 4, - this.translucentBackgroundColor, this.leading, this.automaticallyImplyLeading = false, + this.large = false, }); final Color? backgroundColor; @@ -44,10 +42,7 @@ class SliverAppBarTranslucent extends StatefulWidget { final double translucentBlurSigma; final Widget? leading; final bool automaticallyImplyLeading; - - /// Default to transparent. The background color of the app bar when the app bar - /// is translucent, the alpha channel will be ignored. - final Color? translucentBackgroundColor; + final bool large; @override State createState() => @@ -56,67 +51,43 @@ class SliverAppBarTranslucent extends StatefulWidget { class _SliverAppBarTranslucentState extends State with SettingsStoreMixin { - Color get _translucentBackgroundColor => - widget.translucentBackgroundColor ?? Colors.transparent; - @override Widget build(BuildContext context) { - return AnimatedBuilder( - animation: settingsStore, - builder: (BuildContext context, Widget? child) => SliverAppBar( + if (widget.large) { + return SliverAppBar.large( automaticallyImplyLeading: widget.automaticallyImplyLeading, leading: widget.leading, - wrapperBuilder: (BuildContext context, Widget appBar) { - if (settingsStore.transparentNavigationBar) { - return Container( - decoration: BoxDecoration( - color: _translucentBackgroundColor == Colors.transparent - ? null - : _translucentBackgroundColor.withOpacity(.4), - border: Border( - bottom: BorderSide( - color: context.primaryColor, - width: widget.translucentBorderWidth, - ), - ), - ), - child: ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur( - sigmaX: widget.translucentBlurSigma, - sigmaY: widget.translucentBlurSigma, - ), - child: appBar, - ), - ), - ); - } - return appBar; - }, titleSpacing: widget.titleSpacing ?? k10dp, - scrolledUnderElevation: settingsStore.transparentNavigationBar - ? 0.0 - : widget.scrolledUnderElevation, - backgroundColor: settingsStore.transparentNavigationBar - ? Colors.transparent - : widget.backgroundColor, - elevation: - settingsStore.transparentNavigationBar ? 0.0 : widget.elevation, - shadowColor: settingsStore.transparentNavigationBar - ? Colors.transparent - : widget.shadowColor, - surfaceTintColor: settingsStore.transparentNavigationBar - ? Colors.transparent - : widget.surfaceTintColor, - foregroundColor: settingsStore.transparentNavigationBar - ? Colors.transparent - : widget.foregroundColor, + scrolledUnderElevation: widget.scrolledUnderElevation, + backgroundColor: widget.backgroundColor, + elevation: widget.elevation, + shadowColor: widget.shadowColor, + surfaceTintColor: widget.surfaceTintColor, + foregroundColor: widget.foregroundColor, title: widget.title, bottom: widget.bottom, actions: widget.actions, - floating: widget.floating, - pinned: widget.pinned, - ), + // Large implies this config: + // floating: false, + // pinned: true, + ); + } + + return SliverAppBar( + automaticallyImplyLeading: widget.automaticallyImplyLeading, + leading: widget.leading, + titleSpacing: widget.titleSpacing ?? k10dp, + scrolledUnderElevation: widget.scrolledUnderElevation, + backgroundColor: widget.backgroundColor, + elevation: widget.elevation, + shadowColor: widget.shadowColor, + surfaceTintColor: widget.surfaceTintColor, + foregroundColor: widget.foregroundColor, + title: widget.title, + bottom: widget.bottom, + actions: widget.actions, + floating: widget.floating, + pinned: widget.pinned, ); } } diff --git a/lib/widgets/sliver_app_top_bar.dart b/lib/widgets/sliver_app_top_bar.dart index 26624cc..73b388e 100644 --- a/lib/widgets/sliver_app_top_bar.dart +++ b/lib/widgets/sliver_app_top_bar.dart @@ -39,19 +39,8 @@ class _SliverAppBarGlobalState extends State @override Widget build(BuildContext context) { return SliverAppBarTranslucent( - scrolledUnderElevation: - settingsStore.transparentNavigationBar ? 0.0 : null, titleSpacing: k10dp, - backgroundColor: settingsStore.transparentNavigationBar - ? Colors.transparent - : widget.backgroundColor, - elevation: settingsStore.transparentNavigationBar ? 0.0 : null, - shadowColor: - settingsStore.transparentNavigationBar ? Colors.transparent : null, - surfaceTintColor: - settingsStore.transparentNavigationBar ? Colors.transparent : null, - foregroundColor: - settingsStore.transparentNavigationBar ? Colors.transparent : null, + backgroundColor: widget.backgroundColor, title: const SizedBox( height: kToolbarHeight, child: Align( diff --git a/pubspec.lock b/pubspec.lock index c553eab..e73b11e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -492,7 +492,7 @@ packages: source: hosted version: "0.12.16" material_color_utilities: - dependency: transitive + dependency: "direct main" description: name: material_color_utilities sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" diff --git a/pubspec.yaml b/pubspec.yaml index 42028c5..f4e2109 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -52,6 +52,7 @@ dependencies: get_it: ^7.2.0 intl: ^0.18.0 json_annotation: ^4.8.0 + material_color_utilities: ^0.5.0 nanoid: ^1.0.0 package_info_plus: ^3.0.1 path: ^1.8.2