diff --git a/lib/main.dart b/lib/main.dart index 161f544..a0af48f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'widgets/widgets.dart'; /// Studio's own build version. Bump on every UI commit so the /// running app self-identifies — visible in the sidebar header /// and quick-glance proof that you're seeing the current build. -const String kStudioVersion = '0.7.2'; +const String kStudioVersion = '0.7.3'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -45,23 +45,32 @@ class StudioApp extends StatefulWidget { } class StudioAppState extends State { - late ThemeModeValue _mode; - - ThemeModeValue get mode => _mode; + /// Exposed so any descendant can listen via + /// `ValueListenableBuilder` and rebuild instantly when the + /// theme flips. setState alone wouldn't propagate through + /// `MaterialApp(home: const StudioShell())` because the + /// const child's element doesn't get a `didUpdateWidget`. + late final ValueNotifier modeNotifier; Future setMode(ThemeModeValue m) async { - setState(() => _mode = m); + modeNotifier.value = m; await HubService.instance.saveThemeMode(m); } @override void initState() { super.initState(); - _mode = widget.initialThemeMode; + modeNotifier = ValueNotifier(widget.initialThemeMode); } - ThemeMode _flutterMode() { - switch (_mode) { + @override + void dispose() { + modeNotifier.dispose(); + super.dispose(); + } + + ThemeMode _flutterMode(ThemeModeValue v) { + switch (v) { case ThemeModeValue.system: return ThemeMode.system; case ThemeModeValue.light: @@ -73,13 +82,16 @@ class StudioAppState extends State { @override Widget build(BuildContext context) { - return MaterialApp( - title: 'F∆I Studio', - debugShowCheckedModeBanner: false, - theme: FaiTheme.light(), - darkTheme: FaiTheme.dark(), - themeMode: _flutterMode(), - home: const StudioShell(), + return ValueListenableBuilder( + valueListenable: modeNotifier, + builder: (_, mode, _) => MaterialApp( + title: 'F∆I Studio', + debugShowCheckedModeBanner: false, + theme: FaiTheme.light(), + darkTheme: FaiTheme.dark(), + themeMode: _flutterMode(mode), + home: const StudioShell(), + ), ); } } @@ -436,28 +448,33 @@ class _ThemeToggle extends StatelessWidget { @override Widget build(BuildContext context) { final app = StudioApp.of(context); - final mode = app?.mode ?? ThemeModeValue.system; - final icon = switch (mode) { - ThemeModeValue.system => Icons.brightness_auto_outlined, - ThemeModeValue.light => Icons.light_mode_outlined, - ThemeModeValue.dark => Icons.dark_mode_outlined, - }; - final tooltip = switch (mode) { - ThemeModeValue.system => 'theme: follow system', - ThemeModeValue.light => 'theme: light', - ThemeModeValue.dark => 'theme: dark', - }; - return IconButton( - icon: Icon(icon, size: 16), - tooltip: tooltip, - visualDensity: VisualDensity.compact, - onPressed: () { - final next = switch (mode) { - ThemeModeValue.system => ThemeModeValue.light, - ThemeModeValue.light => ThemeModeValue.dark, - ThemeModeValue.dark => ThemeModeValue.system, + if (app == null) return const SizedBox.shrink(); + return ValueListenableBuilder( + valueListenable: app.modeNotifier, + builder: (_, mode, _) { + final icon = switch (mode) { + ThemeModeValue.system => Icons.brightness_auto_outlined, + ThemeModeValue.light => Icons.light_mode_outlined, + ThemeModeValue.dark => Icons.dark_mode_outlined, }; - app?.setMode(next); + final tooltip = switch (mode) { + ThemeModeValue.system => 'theme: follow system', + ThemeModeValue.light => 'theme: light', + ThemeModeValue.dark => 'theme: dark', + }; + return IconButton( + icon: Icon(icon, size: 16), + tooltip: tooltip, + visualDensity: VisualDensity.compact, + onPressed: () { + final next = switch (mode) { + ThemeModeValue.system => ThemeModeValue.light, + ThemeModeValue.light => ThemeModeValue.dark, + ThemeModeValue.dark => ThemeModeValue.system, + }; + app.setMode(next); + }, + ); }, ); } diff --git a/pubspec.yaml b/pubspec.yaml index c74ed6d..2d7b23c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: fai_studio description: "F∆I Studio — desktop GUI for the F∆I hub" publish_to: 'none' -version: 0.7.2 +version: 0.7.3 environment: sdk: ^3.11.0-200.1.beta