settings fully working

This commit is contained in:
Henry Hiles 2026-07-17 00:16:04 -04:00
commit 2bf1e629b7
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
4 changed files with 79 additions and 21 deletions

View file

@ -96,7 +96,15 @@ class App extends StatelessWidget {
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
// Use indigo to work around bugs in theme generation // Use indigo to work around bugs in theme generation
theme: (lightDynamic ?? ColorScheme.fromSeed(seedColor: Colors.indigo)) theme:
(ref
.watch(SettingsController.provider)
.maybeWhen(
orElse: () => lightDynamic,
data: (settings) =>
settings.useDynamicTheming ? lightDynamic : null,
) ??
ColorScheme.fromSeed(seedColor: Colors.indigo))
.getTheme( .getTheme(
ref ref
.watch(SettingsController.provider) .watch(SettingsController.provider)
@ -106,7 +114,13 @@ class App extends StatelessWidget {
), ),
), ),
darkTheme: darkTheme:
(darkDynamic ?? (ref
.watch(SettingsController.provider)
.maybeWhen(
orElse: () => darkDynamic,
data: (settings) =>
settings.useDynamicTheming ? darkDynamic : null,
) ??
ColorScheme.fromSeed( ColorScheme.fromSeed(
seedColor: Colors.indigo, seedColor: Colors.indigo,
brightness: Brightness.dark, brightness: Brightness.dark,

View file

@ -7,6 +7,7 @@ part "settings.g.dart";
abstract class Settings with _$Settings { abstract class Settings with _$Settings {
const factory Settings({ const factory Settings({
@Default(ThemeMode.light) ThemeMode theme, @Default(ThemeMode.light) ThemeMode theme,
@Default(true) bool useDynamicTheming,
@Default(false) bool useSystemFont, @Default(false) bool useSystemFont,
}) = _Settings; }) = _Settings;

View file

@ -1,3 +1,5 @@
import "dart:io";
import "package:collection/collection.dart"; import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart"; import "package:flutter/material.dart";
@ -36,7 +38,7 @@ class SettingsPage extends ConsumerWidget {
description: description:
"Toggle between Light Mode, Dark Mode, and System themes.", "Toggle between Light Mode, Dark Mode, and System themes.",
builder: (title, description) => DialogListTile<ThemeMode>( builder: (title, description) => DialogListTile<ThemeMode>(
icon: Icon(Icons.palette), icon: Icon(Icons.contrast),
title: title, title: title,
subtitle: Text(description), subtitle: Text(description),
initialValue: settings.theme, initialValue: settings.theme,
@ -48,6 +50,27 @@ class SettingsPage extends ConsumerWidget {
.onError(showError), .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( Setting(
title: "Use System Font", title: "Use System Font",
description: description:
@ -118,8 +141,7 @@ class SettingsPage extends ConsumerWidget {
context, context,
).colorScheme.primaryContainer, ).colorScheme.primaryContainer,
itemCount: categories.length, itemCount: categories.length,
onTap: (index) => onTap: (index) => Navigator.of(context).push(
Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (context) => Scaffold( builder: (context) => Scaffold(
appBar: AppBar( appBar: AppBar(
@ -127,7 +149,26 @@ class SettingsPage extends ConsumerWidget {
categories[index].title, categories[index].title,
), ),
), ),
body: ListView(), 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(),
),
), ),
), ),
), ),

View file

@ -35,6 +35,7 @@ class DialogListTile<T> extends ConsumerWidget {
enabledBorder: InputBorder.none, enabledBorder: InputBorder.none,
), ),
child: ListTile( child: ListTile(
enabled: onChanged != null,
onTap: () => showDialog( onTap: () => showDialog(
context: context, context: context,
builder: (context) => RadioDialog<T>( builder: (context) => RadioDialog<T>(
@ -57,6 +58,7 @@ class DialogListTile<T> extends ConsumerWidget {
label: Text( label: Text(
field.value == null ? "None" : getName(field.value as T), field.value == null ? "None" : getName(field.value as T),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: onChanged == null ? .new(color: Colors.grey) : null,
), ),
), ),
), ),