From 9441a2cdd3e863f80695f0128a23d4b66af3d161 Mon Sep 17 00:00:00 2001 From: Dr-Blank <64108942+Dr-Blank@users.noreply.github.com> Date: Sat, 5 Oct 2024 06:52:27 -0400 Subject: [PATCH] feat: add theme settings route and update theme management in app settings --- lib/main.dart | 20 +- lib/router/constants.dart | 5 + lib/router/router.dart | 8 + lib/settings/app_settings_provider.dart | 5 - lib/settings/app_settings_provider.g.dart | 2 +- lib/settings/models/app_settings.dart | 6 +- lib/settings/models/app_settings.freezed.dart | 105 ++------ lib/settings/models/app_settings.g.dart | 20 +- lib/settings/view/app_settings_page.dart | 31 +-- lib/settings/view/theme_settings_page.dart | 230 ++++++++++++++++++ 10 files changed, 301 insertions(+), 131 deletions(-) create mode 100644 lib/settings/view/theme_settings_page.dart diff --git a/lib/main.dart b/lib/main.dart index 528c2a7..5469747 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -66,12 +66,14 @@ class MyApp extends ConsumerWidget { lightColorScheme = lightDynamic.harmonized(); darkColorScheme = darkDynamic.harmonized(); } else { - lightColorScheme = brandLightColorScheme; - darkColorScheme = brandDarkColorScheme; + lightColorScheme = brandLightColorScheme.harmonized(); + darkColorScheme = brandDarkColorScheme.harmonized(); } // set the background and surface colors to pure black in the amoled theme if (themeSettings.highContrast) { + lightColorScheme = + lightColorScheme.copyWith(surface: Colors.white).harmonized(); darkColorScheme = darkColorScheme.copyWith(surface: Colors.black).harmonized(); } @@ -85,15 +87,25 @@ class MyApp extends ConsumerWidget { colorScheme: darkColorScheme, brightness: Brightness.dark, ); + final themeLightHighContrast = themeLight.copyWith( + colorScheme: + lightColorScheme.copyWith(surface: Colors.white).harmonized(), + ); + final themeDarkHighContrast = themeDark.copyWith( + colorScheme: + darkColorScheme.copyWith(surface: Colors.black).harmonized(), + ); try { return MaterialApp.router( // debugShowCheckedModeBanner: false, theme: themeLight, darkTheme: themeDark, - themeMode: - themeSettings.isDarkMode ? ThemeMode.dark : ThemeMode.light, + themeMode: themeSettings.themeMode, + highContrastTheme: themeLightHighContrast, + highContrastDarkTheme: themeDarkHighContrast, routerConfig: routerConfig, + themeAnimationCurve: Curves.easeInOut, ); } catch (e) { debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 9d01c29..f36d706 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -27,6 +27,11 @@ class Routes { pathName: 'config', name: 'settings', ); + static const themeSettings = _SimpleRoute( + pathName: 'theme', + name: 'themeSettings', + parentRoute: settings, + ); static const autoSleepTimerSettings = _SimpleRoute( pathName: 'autoSleepTimer', name: 'autoSleepTimerSettings', diff --git a/lib/router/router.dart b/lib/router/router.dart index c5b1a67..5e9f71e 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -17,6 +17,7 @@ import 'package:vaani/settings/view/auto_sleep_timer_settings_page.dart'; import 'package:vaani/settings/view/notification_settings_page.dart'; import 'package:vaani/settings/view/player_settings_page.dart'; import 'package:vaani/settings/view/shake_detector_settings_page.dart'; +import 'package:vaani/settings/view/theme_settings_page.dart'; import 'scaffold_with_nav_bar.dart'; import 'transitions/slide.dart'; @@ -178,6 +179,13 @@ class MyAppRouter { // builder: (context, state) => const AppSettingsPage(), pageBuilder: defaultPageBuilder(const AppSettingsPage()), routes: [ + GoRoute( + path: Routes.themeSettings.pathName, + name: Routes.themeSettings.name, + pageBuilder: defaultPageBuilder( + const ThemeSettingsPage(), + ), + ), GoRoute( path: Routes.autoSleepTimerSettings.pathName, name: Routes.autoSleepTimerSettings.name, diff --git a/lib/settings/app_settings_provider.dart b/lib/settings/app_settings_provider.dart index 6d61774..b86e736 100644 --- a/lib/settings/app_settings_provider.dart +++ b/lib/settings/app_settings_provider.dart @@ -47,11 +47,6 @@ class AppSettings extends _$AppSettings { _logger.fine('wrote settings to box: $state'); } - void toggleDarkMode() { - state = state.copyWith - .themeSettings(isDarkMode: !state.themeSettings.isDarkMode); - } - void update(model.AppSettings newSettings) { state = newSettings; } diff --git a/lib/settings/app_settings_provider.g.dart b/lib/settings/app_settings_provider.g.dart index df95738..85d58cd 100644 --- a/lib/settings/app_settings_provider.g.dart +++ b/lib/settings/app_settings_provider.g.dart @@ -6,7 +6,7 @@ part of 'app_settings_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$appSettingsHash() => r'f51d55f117692d4fb9f4b4febf02906c0953d334'; +String _$appSettingsHash() => r'314d7936f54550f57d308056a99230402342a6d0'; /// See also [AppSettings]. @ProviderFor(AppSettings) diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index cf6a8a0..1d1a53e 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -25,19 +25,15 @@ class AppSettings with _$AppSettings { _$AppSettingsFromJson(json); } -enum ThemeType { light, dark, system } - @freezed class ThemeSettings with _$ThemeSettings { const factory ThemeSettings({ - @Default(true) bool isDarkMode, - @Default(ThemeType.system) ThemeType themeType, + @Default(ThemeMode.system) ThemeMode themeMode, @Default(false) bool highContrast, @Default(true) bool useMaterialThemeFromSystem, @Default('#FF311B92') String customThemeColor, @Default(true) bool useMaterialThemeOfPlayingItem, @Default(true) bool useMaterialThemeOnItemPage, - @Default(true) bool useCurrentPlayerThemeThroughoutApp, }) = _ThemeSettings; factory ThemeSettings.fromJson(Map json) => diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index 9db9469..7ea9500 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -378,15 +378,12 @@ ThemeSettings _$ThemeSettingsFromJson(Map json) { /// @nodoc mixin _$ThemeSettings { - bool get isDarkMode => throw _privateConstructorUsedError; - ThemeType get themeType => throw _privateConstructorUsedError; + ThemeMode get themeMode => throw _privateConstructorUsedError; bool get highContrast => throw _privateConstructorUsedError; bool get useMaterialThemeFromSystem => throw _privateConstructorUsedError; String get customThemeColor => throw _privateConstructorUsedError; bool get useMaterialThemeOfPlayingItem => throw _privateConstructorUsedError; bool get useMaterialThemeOnItemPage => throw _privateConstructorUsedError; - bool get useCurrentPlayerThemeThroughoutApp => - throw _privateConstructorUsedError; /// Serializes this ThemeSettings to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -405,14 +402,12 @@ abstract class $ThemeSettingsCopyWith<$Res> { _$ThemeSettingsCopyWithImpl<$Res, ThemeSettings>; @useResult $Res call( - {bool isDarkMode, - ThemeType themeType, + {ThemeMode themeMode, bool highContrast, bool useMaterialThemeFromSystem, String customThemeColor, bool useMaterialThemeOfPlayingItem, - bool useMaterialThemeOnItemPage, - bool useCurrentPlayerThemeThroughoutApp}); + bool useMaterialThemeOnItemPage}); } /// @nodoc @@ -430,24 +425,18 @@ class _$ThemeSettingsCopyWithImpl<$Res, $Val extends ThemeSettings> @pragma('vm:prefer-inline') @override $Res call({ - Object? isDarkMode = null, - Object? themeType = null, + Object? themeMode = null, Object? highContrast = null, Object? useMaterialThemeFromSystem = null, Object? customThemeColor = null, Object? useMaterialThemeOfPlayingItem = null, Object? useMaterialThemeOnItemPage = null, - Object? useCurrentPlayerThemeThroughoutApp = null, }) { return _then(_value.copyWith( - isDarkMode: null == isDarkMode - ? _value.isDarkMode - : isDarkMode // ignore: cast_nullable_to_non_nullable - as bool, - themeType: null == themeType - ? _value.themeType - : themeType // ignore: cast_nullable_to_non_nullable - as ThemeType, + themeMode: null == themeMode + ? _value.themeMode + : themeMode // ignore: cast_nullable_to_non_nullable + as ThemeMode, highContrast: null == highContrast ? _value.highContrast : highContrast // ignore: cast_nullable_to_non_nullable @@ -468,11 +457,6 @@ class _$ThemeSettingsCopyWithImpl<$Res, $Val extends ThemeSettings> ? _value.useMaterialThemeOnItemPage : useMaterialThemeOnItemPage // ignore: cast_nullable_to_non_nullable as bool, - useCurrentPlayerThemeThroughoutApp: null == - useCurrentPlayerThemeThroughoutApp - ? _value.useCurrentPlayerThemeThroughoutApp - : useCurrentPlayerThemeThroughoutApp // ignore: cast_nullable_to_non_nullable - as bool, ) as $Val); } } @@ -486,14 +470,12 @@ abstract class _$$ThemeSettingsImplCopyWith<$Res> @override @useResult $Res call( - {bool isDarkMode, - ThemeType themeType, + {ThemeMode themeMode, bool highContrast, bool useMaterialThemeFromSystem, String customThemeColor, bool useMaterialThemeOfPlayingItem, - bool useMaterialThemeOnItemPage, - bool useCurrentPlayerThemeThroughoutApp}); + bool useMaterialThemeOnItemPage}); } /// @nodoc @@ -509,24 +491,18 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? isDarkMode = null, - Object? themeType = null, + Object? themeMode = null, Object? highContrast = null, Object? useMaterialThemeFromSystem = null, Object? customThemeColor = null, Object? useMaterialThemeOfPlayingItem = null, Object? useMaterialThemeOnItemPage = null, - Object? useCurrentPlayerThemeThroughoutApp = null, }) { return _then(_$ThemeSettingsImpl( - isDarkMode: null == isDarkMode - ? _value.isDarkMode - : isDarkMode // ignore: cast_nullable_to_non_nullable - as bool, - themeType: null == themeType - ? _value.themeType - : themeType // ignore: cast_nullable_to_non_nullable - as ThemeType, + themeMode: null == themeMode + ? _value.themeMode + : themeMode // ignore: cast_nullable_to_non_nullable + as ThemeMode, highContrast: null == highContrast ? _value.highContrast : highContrast // ignore: cast_nullable_to_non_nullable @@ -547,11 +523,6 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res> ? _value.useMaterialThemeOnItemPage : useMaterialThemeOnItemPage // ignore: cast_nullable_to_non_nullable as bool, - useCurrentPlayerThemeThroughoutApp: null == - useCurrentPlayerThemeThroughoutApp - ? _value.useCurrentPlayerThemeThroughoutApp - : useCurrentPlayerThemeThroughoutApp // ignore: cast_nullable_to_non_nullable - as bool, )); } } @@ -560,24 +531,19 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res> @JsonSerializable() class _$ThemeSettingsImpl implements _ThemeSettings { const _$ThemeSettingsImpl( - {this.isDarkMode = true, - this.themeType = ThemeType.system, + {this.themeMode = ThemeMode.system, this.highContrast = false, this.useMaterialThemeFromSystem = true, this.customThemeColor = '#FF311B92', this.useMaterialThemeOfPlayingItem = true, - this.useMaterialThemeOnItemPage = true, - this.useCurrentPlayerThemeThroughoutApp = true}); + this.useMaterialThemeOnItemPage = true}); factory _$ThemeSettingsImpl.fromJson(Map json) => _$$ThemeSettingsImplFromJson(json); @override @JsonKey() - final bool isDarkMode; - @override - @JsonKey() - final ThemeType themeType; + final ThemeMode themeMode; @override @JsonKey() final bool highContrast; @@ -593,13 +559,10 @@ class _$ThemeSettingsImpl implements _ThemeSettings { @override @JsonKey() final bool useMaterialThemeOnItemPage; - @override - @JsonKey() - final bool useCurrentPlayerThemeThroughoutApp; @override String toString() { - return 'ThemeSettings(isDarkMode: $isDarkMode, themeType: $themeType, highContrast: $highContrast, useMaterialThemeFromSystem: $useMaterialThemeFromSystem, customThemeColor: $customThemeColor, useMaterialThemeOfPlayingItem: $useMaterialThemeOfPlayingItem, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp: $useCurrentPlayerThemeThroughoutApp)'; + return 'ThemeSettings(themeMode: $themeMode, highContrast: $highContrast, useMaterialThemeFromSystem: $useMaterialThemeFromSystem, customThemeColor: $customThemeColor, useMaterialThemeOfPlayingItem: $useMaterialThemeOfPlayingItem, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage)'; } @override @@ -607,10 +570,8 @@ class _$ThemeSettingsImpl implements _ThemeSettings { return identical(this, other) || (other.runtimeType == runtimeType && other is _$ThemeSettingsImpl && - (identical(other.isDarkMode, isDarkMode) || - other.isDarkMode == isDarkMode) && - (identical(other.themeType, themeType) || - other.themeType == themeType) && + (identical(other.themeMode, themeMode) || + other.themeMode == themeMode) && (identical(other.highContrast, highContrast) || other.highContrast == highContrast) && (identical(other.useMaterialThemeFromSystem, @@ -626,25 +587,19 @@ class _$ThemeSettingsImpl implements _ThemeSettings { (identical(other.useMaterialThemeOnItemPage, useMaterialThemeOnItemPage) || other.useMaterialThemeOnItemPage == - useMaterialThemeOnItemPage) && - (identical(other.useCurrentPlayerThemeThroughoutApp, - useCurrentPlayerThemeThroughoutApp) || - other.useCurrentPlayerThemeThroughoutApp == - useCurrentPlayerThemeThroughoutApp)); + useMaterialThemeOnItemPage)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode => Object.hash( runtimeType, - isDarkMode, - themeType, + themeMode, highContrast, useMaterialThemeFromSystem, customThemeColor, useMaterialThemeOfPlayingItem, - useMaterialThemeOnItemPage, - useCurrentPlayerThemeThroughoutApp); + useMaterialThemeOnItemPage); /// Create a copy of ThemeSettings /// with the given fields replaced by the non-null parameter values. @@ -664,22 +619,18 @@ class _$ThemeSettingsImpl implements _ThemeSettings { abstract class _ThemeSettings implements ThemeSettings { const factory _ThemeSettings( - {final bool isDarkMode, - final ThemeType themeType, + {final ThemeMode themeMode, final bool highContrast, final bool useMaterialThemeFromSystem, final String customThemeColor, final bool useMaterialThemeOfPlayingItem, - final bool useMaterialThemeOnItemPage, - final bool useCurrentPlayerThemeThroughoutApp}) = _$ThemeSettingsImpl; + final bool useMaterialThemeOnItemPage}) = _$ThemeSettingsImpl; factory _ThemeSettings.fromJson(Map json) = _$ThemeSettingsImpl.fromJson; @override - bool get isDarkMode; - @override - ThemeType get themeType; + ThemeMode get themeMode; @override bool get highContrast; @override @@ -690,8 +641,6 @@ abstract class _ThemeSettings implements ThemeSettings { bool get useMaterialThemeOfPlayingItem; @override bool get useMaterialThemeOnItemPage; - @override - bool get useCurrentPlayerThemeThroughoutApp; /// Create a copy of ThemeSettings /// with the given fields replaced by the non-null parameter values. diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 65921af..8ab998e 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -46,9 +46,8 @@ Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => _$ThemeSettingsImpl( - isDarkMode: json['isDarkMode'] as bool? ?? true, - themeType: $enumDecodeNullable(_$ThemeTypeEnumMap, json['themeType']) ?? - ThemeType.system, + themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ?? + ThemeMode.system, highContrast: json['highContrast'] as bool? ?? false, useMaterialThemeFromSystem: json['useMaterialThemeFromSystem'] as bool? ?? true, @@ -57,27 +56,22 @@ _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => json['useMaterialThemeOfPlayingItem'] as bool? ?? true, useMaterialThemeOnItemPage: json['useMaterialThemeOnItemPage'] as bool? ?? true, - useCurrentPlayerThemeThroughoutApp: - json['useCurrentPlayerThemeThroughoutApp'] as bool? ?? true, ); Map _$$ThemeSettingsImplToJson(_$ThemeSettingsImpl instance) => { - 'isDarkMode': instance.isDarkMode, - 'themeType': _$ThemeTypeEnumMap[instance.themeType]!, + 'themeMode': _$ThemeModeEnumMap[instance.themeMode]!, 'highContrast': instance.highContrast, 'useMaterialThemeFromSystem': instance.useMaterialThemeFromSystem, 'customThemeColor': instance.customThemeColor, 'useMaterialThemeOfPlayingItem': instance.useMaterialThemeOfPlayingItem, 'useMaterialThemeOnItemPage': instance.useMaterialThemeOnItemPage, - 'useCurrentPlayerThemeThroughoutApp': - instance.useCurrentPlayerThemeThroughoutApp, }; -const _$ThemeTypeEnumMap = { - ThemeType.light: 'light', - ThemeType.dark: 'dark', - ThemeType.system: 'system', +const _$ThemeModeEnumMap = { + ThemeMode.system: 'system', + ThemeMode.light: 'light', + ThemeMode.dark: 'dark', }; _$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map json) => diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index 77afaae..cfc1c3d 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -43,33 +43,14 @@ class AppSettingsPage extends HookConsumerWidget { style: Theme.of(context).textTheme.titleLarge, ), tiles: [ - SettingsTile.switchTile( - initialValue: appSettings.themeSettings.isDarkMode, - title: const Text('Dark Mode'), - description: const Text('we all know dark mode is better'), - leading: appSettings.themeSettings.isDarkMode - ? const Icon(Icons.dark_mode) - : const Icon(Icons.light_mode), - onToggle: (value) { - ref.read(appSettingsProvider.notifier).toggleDarkMode(); - }, - ), - SettingsTile.switchTile( - initialValue: - appSettings.themeSettings.useMaterialThemeOnItemPage, - title: const Text('Adaptive Theme on Item Page'), + SettingsTile.navigation( + leading: const Icon(Icons.color_lens), + title: const Text('Theme Settings'), description: const Text( - 'get fancy with the colors on the item page at the cost of some performance', + 'Customize the app theme', ), - leading: appSettings.themeSettings.useMaterialThemeOnItemPage - ? const Icon(Icons.auto_fix_high) - : const Icon(Icons.auto_fix_off), - onToggle: (value) { - ref.read(appSettingsProvider.notifier).update( - appSettings.copyWith.themeSettings( - useMaterialThemeOnItemPage: value, - ), - ); + onPressed: (context) { + context.pushNamed(Routes.themeSettings.name); }, ), ], diff --git a/lib/settings/view/theme_settings_page.dart b/lib/settings/view/theme_settings_page.dart new file mode 100644 index 0000000..b6fe4e9 --- /dev/null +++ b/lib/settings/view/theme_settings_page.dart @@ -0,0 +1,230 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart'; +import 'package:vaani/shared/extensions/enum.dart'; + +class ThemeSettingsPage extends HookConsumerWidget { + const ThemeSettingsPage({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final appSettings = ref.watch(appSettingsProvider); + final themeSettings = appSettings.themeSettings; + final primaryColor = Theme.of(context).colorScheme.primary; + + return SimpleSettingsPage( + title: const Text('Theme Settings'), + sections: [ + SettingsSection( + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + tiles: [ + // choose system , light or dark theme + SettingsTile.navigation( + title: const Text('Theme Mode'), + description: Text.rich( + TextSpan( + text: themeSettings.themeMode == ThemeMode.system + ? 'Using mode from ' + : 'Using ', + children: [ + TextSpan( + text: themeSettings.themeMode.pascalCase, + style: TextStyle( + color: primaryColor, + ), + ), + if (themeSettings.themeMode != ThemeMode.system) + const TextSpan(text: ' mode'), + ], + ), + ), + leading: const Icon(Icons.color_lens), + trailing: themeSettings.themeMode == ThemeMode.system + ? const Icon(Icons.auto_awesome) + : themeSettings.themeMode == ThemeMode.light + ? const Icon(Icons.light_mode) + : const Icon(Icons.dark_mode), + onPressed: (context) async { + final themeMode = await showDialog( + context: context, + builder: (context) { + return SimpleDialog( + title: const Text('Select Theme Mode'), + children: [ + SimpleDialogOption( + onPressed: () { + Navigator.pop(context, ThemeMode.system); + }, + child: const Text('System'), + ), + SimpleDialogOption( + onPressed: () { + Navigator.pop(context, ThemeMode.light); + }, + child: const Text('Light'), + ), + SimpleDialogOption( + onPressed: () { + Navigator.pop(context, ThemeMode.dark); + }, + child: const Text('Dark'), + ), + ], + ); + }, + ); + if (themeMode != null) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + themeMode: themeMode, + ), + ); + } + }, + ), + + // high contrast mode + SettingsTile.switchTile( + leading: themeSettings.highContrast + ? const Icon(Icons.accessibility) + : const Icon(Icons.accessibility_new_outlined), + initialValue: themeSettings.highContrast, + title: const Text('High Contrast Mode'), + description: const Text( + 'Increase the contrast between the background and the text', + ), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + highContrast: value, + ), + ); + }, + ), + + // use material theme from system + SettingsTile.switchTile( + initialValue: themeSettings.useMaterialThemeFromSystem, + title: Platform.isAndroid + ? const Text('Use Material You') + : const Text('Material Theme from System'), + description: const Text( + 'Use the system theme colors for the app', + ), + leading: themeSettings.useMaterialThemeFromSystem + ? const Icon(Icons.auto_awesome) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useMaterialThemeFromSystem: value, + ), + ); + }, + ), + + // TODO choose the primary color + // SettingsTile.navigation( + // title: const Text('Primary Color'), + // description: const Text( + // 'Choose the primary color for the app', + // ), + // leading: const Icon(Icons.colorize), + // trailing: Icon( + // Icons.circle, + // color: themeSettings.customThemeColor.toColor(), + // ), + // onPressed: (context) async { + // final selectedColor = await showDialog( + // context: context, + // builder: (context) { + // return SimpleDialog( + // title: const Text('Select Primary Color'), + // children: [ + // for (final color in Colors.primaries) + // SimpleDialogOption( + // onPressed: () { + // Navigator.pop(context, color); + // }, + // child: Container( + // color: color, + // height: 48, + // ), + // ), + // ], + // ); + // }, + // ); + // if (selectedColor != null) { + // ref.read(appSettingsProvider.notifier).update( + // appSettings.copyWith.themeSettings( + // customThemeColor: selectedColor.toHexString(), + // ), + // ); + // } + // }, + // ), + + // use theme throughout the app when playing item + SettingsTile.switchTile( + initialValue: themeSettings.useMaterialThemeOfPlayingItem, + title: const Text('Adapt theme from currently playing item'), + description: const Text( + 'Use the theme colors from the currently playing item for the app', + ), + leading: themeSettings.useMaterialThemeOfPlayingItem + ? const Icon(Icons.auto_fix_high) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useMaterialThemeOfPlayingItem: value, + ), + ); + }, + ), + + SettingsTile.switchTile( + initialValue: themeSettings.useMaterialThemeOnItemPage, + title: const Text('Adaptive Theme on Item Page'), + description: const Text( + 'get fancy with the colors on the item page at the cost of some performance', + ), + leading: themeSettings.useMaterialThemeOnItemPage + ? const Icon(Icons.auto_fix_high) + : const Icon(Icons.auto_fix_off), + onToggle: (value) { + ref.read(appSettingsProvider.notifier).update( + appSettings.copyWith.themeSettings( + useMaterialThemeOnItemPage: value, + ), + ); + }, + ), + ], + ), + ], + ); + } +} + +extension ColorExtension on Color { + String toHexString() { + return '#${value.toRadixString(16).substring(2)}'; + } +} + +extension StringExtension on String { + Color toColor() { + return Color(int.parse('0xff$substring(1)')); + } +}