diff --git a/lib/main.dart b/lib/main.dart index d568f6d..ed48759 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -96,17 +96,31 @@ class App extends StatelessWidget { navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, // Use indigo to work around bugs in theme generation - theme: (lightDynamic ?? ColorScheme.fromSeed(seedColor: Colors.indigo)) - .getTheme( - ref - .watch(SettingsController.provider) - .maybeWhen( - orElse: () => true, - data: (settings) => settings.useSystemFont, - ), - ), + theme: + (ref + .watch(SettingsController.provider) + .maybeWhen( + orElse: () => lightDynamic, + data: (settings) => + settings.useDynamicTheming ? lightDynamic : null, + ) ?? + ColorScheme.fromSeed(seedColor: Colors.indigo)) + .getTheme( + ref + .watch(SettingsController.provider) + .maybeWhen( + orElse: () => true, + data: (settings) => settings.useSystemFont, + ), + ), darkTheme: - (darkDynamic ?? + (ref + .watch(SettingsController.provider) + .maybeWhen( + orElse: () => darkDynamic, + data: (settings) => + settings.useDynamicTheming ? darkDynamic : null, + ) ?? ColorScheme.fromSeed( seedColor: Colors.indigo, brightness: Brightness.dark, diff --git a/lib/models/settings.dart b/lib/models/settings.dart index aafa23a..f7e67d1 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -7,6 +7,7 @@ part "settings.g.dart"; abstract class Settings with _$Settings { const factory Settings({ @Default(ThemeMode.light) ThemeMode theme, + @Default(true) bool useDynamicTheming, @Default(false) bool useSystemFont, }) = _Settings; diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart index 3a4a3ff..216bc0b 100644 --- a/lib/pages/settings_page.dart +++ b/lib/pages/settings_page.dart @@ -1,3 +1,5 @@ +import "dart:io"; + import "package:collection/collection.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter/material.dart"; @@ -36,7 +38,7 @@ class SettingsPage extends ConsumerWidget { description: "Toggle between Light Mode, Dark Mode, and System themes.", builder: (title, description) => DialogListTile( - icon: Icon(Icons.palette), + icon: Icon(Icons.contrast), title: title, subtitle: Text(description), initialValue: settings.theme, @@ -48,6 +50,27 @@ class SettingsPage extends ConsumerWidget { .onError(showError), ), ), + Setting( + title: "Use Dynamic Theme", + description: + "Toggle on or off Dynamic Theme. Only available on Android, Linux, Windows, or MacOS.", + builder: (title, description) => SwitchListTile( + title: Text(title), + subtitle: Text(description), + secondary: Icon(Icons.palette), + value: settings.useDynamicTheming, + onChanged: + (Platform.isAndroid || + Platform.isLinux || + Platform.isMacOS || + Platform.isWindows) + ? (value) => ref + .watch(SettingsController.provider.notifier) + .set(settings.copyWith(useDynamicTheming: value)) + .onError(showError) + : null, + ), + ), Setting( title: "Use System Font", description: @@ -118,19 +141,37 @@ class SettingsPage extends ConsumerWidget { context, ).colorScheme.primaryContainer, itemCount: categories.length, - onTap: (index) => - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => Scaffold( - appBar: AppBar( - title: Text( - categories[index].title, - ), - ), - body: ListView(), + onTap: (index) => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => Scaffold( + appBar: AppBar( + title: Text( + categories[index].title, ), ), + body: SuperListView( + padding: .symmetric( + vertical: 12, + horizontal: 8, + ), + children: buildCategories(settings) + .values + .flattenedToList[selected.value] + .settings + .map( + (setting) => Padding( + padding: .only(bottom: 4), + child: setting.builder( + setting.title, + setting.description, + ), + ), + ) + .toList(), + ), ), + ), + ), itemBuilder: (context, index) => ListTile( leading: Icon(categories[index].icon), title: Text(categories[index].title), diff --git a/lib/widgets/settings/dialog_list_tile.dart b/lib/widgets/settings/dialog_list_tile.dart index 89b9159..f0a236c 100644 --- a/lib/widgets/settings/dialog_list_tile.dart +++ b/lib/widgets/settings/dialog_list_tile.dart @@ -35,6 +35,7 @@ class DialogListTile extends ConsumerWidget { enabledBorder: InputBorder.none, ), child: ListTile( + enabled: onChanged != null, onTap: () => showDialog( context: context, builder: (context) => RadioDialog( @@ -57,6 +58,7 @@ class DialogListTile extends ConsumerWidget { label: Text( field.value == null ? "None" : getName(field.value as T), overflow: TextOverflow.ellipsis, + style: onChanged == null ? .new(color: Colors.grey) : null, ), ), ),