2424// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2525// SOFTWARE.
2626///
27- /// Authors: Tony Chen
27+ /// Authors: Tony Chen, Graham Williams
2828
2929library ;
3030
3131import 'package:flutter/material.dart' ;
3232import 'package:flutter/scheduler.dart' ;
3333
34+ import 'package:shared_preferences/shared_preferences.dart' ;
35+
3436import 'package:solidui/src/widgets/solid_preferences_models.dart' ;
3537
38+ /// SharedPreferences key for persisting the theme mode across app restarts.
39+
40+ const _kThemeModeKey = 'solidui_theme_mode' ;
41+
3642/// Notifier for managing theme state across the application.
37- /// The theme always starts in System mode.
43+ ///
44+ /// Theme is persisted across app restarts using SharedPreferences. On first
45+ /// launch (no saved preference) the theme defaults to System mode.
3846
3947class SolidThemeNotifier extends ChangeNotifier {
4048 ThemeMode _themeMode = ThemeMode .system;
@@ -52,36 +60,54 @@ class SolidThemeNotifier extends ChangeNotifier {
5260
5361 bool get isInitialized => _isInitialized;
5462
55- /// Initialises the notifier.
56- /// Theme always starts in System mode.
63+ /// Initialises the notifier by loading the persisted theme preference.
64+ ///
65+ /// Must be awaited before the first build so that the correct theme is
66+ /// applied without a flash:
67+ ///
68+ /// ```dart
69+ /// Future<void> _initTheme() async {
70+ /// await _themeNotifier.initialize();
71+ /// if (mounted) setState(() {});
72+ /// }
73+ /// ```
5774
5875 Future <void > initialize () async {
5976 if (_isInitialized) return ;
6077
61- _themeMode = ThemeMode .system;
78+ // Load previously saved theme mode from SharedPreferences.
79+ final prefs = await SharedPreferences .getInstance ();
80+ final saved = prefs.getString (_kThemeModeKey);
81+ _themeMode = _themeModeFromString (saved);
6282 _isInitialized = true ;
6383 notifyListeners ();
6484 }
6585
66- /// Sets a specific theme mode.
86+ /// Sets a specific theme mode and persists it to SharedPreferences .
6787
6888 void setThemeMode (ThemeMode themeMode) {
6989 if (_themeMode == themeMode) return ;
7090
7191 _themeMode = themeMode;
7292 notifyListeners ();
93+
94+ // Persist asynchronously — fire and forget is safe here since
95+ // SharedPreferences writes are fast and non-critical.
96+ SharedPreferences .getInstance ().then (
97+ (prefs) => prefs.setString (_kThemeModeKey, _themeModeToString (themeMode)),
98+ );
7399 }
74100
75- /// Toggles between System mode and the opposite of current system mode.
101+ /// Toggles between System mode and the opposite of the current system mode.
76102 ///
77- /// When in System mode, switches to the opposite of current system
78- /// mode. When in Light or Dark mode, switches back to System mode.
103+ /// When in System mode, switches to the opposite of the current system
104+ /// brightness. When in Light or Dark mode, switches back to System mode.
105+ /// The selected mode is persisted via [setThemeMode] .
79106
80107 void toggleTheme () {
81108 switch (_themeMode) {
82109 case ThemeMode .system:
83110 // Detect current system brightness and switch to the opposite mode.
84-
85111 final systemBrightness =
86112 SchedulerBinding .instance.platformDispatcher.platformBrightness;
87113 if (systemBrightness == Brightness .light) {
@@ -94,7 +120,6 @@ class SolidThemeNotifier extends ChangeNotifier {
94120 case ThemeMode .light:
95121 case ThemeMode .dark:
96122 // Switch back to System mode.
97-
98123 setThemeMode (ThemeMode .system);
99124 break ;
100125 }
@@ -127,6 +152,20 @@ class SolidThemeNotifier extends ChangeNotifier {
127152 ''' ;
128153 }
129154 }
155+
156+ // ── Serialisation helpers ─────────────────────────────────────────────────
157+
158+ static String _themeModeToString (ThemeMode mode) => switch (mode) {
159+ ThemeMode .light => 'light' ,
160+ ThemeMode .dark => 'dark' ,
161+ ThemeMode .system => 'system' ,
162+ };
163+
164+ static ThemeMode _themeModeFromString (String ? value) => switch (value) {
165+ 'light' => ThemeMode .light,
166+ 'dark' => ThemeMode .dark,
167+ _ => ThemeMode .system, // default for null or unrecognised values
168+ };
130169}
131170
132171/// Global instance of the theme notifier.
0 commit comments