import 'package:flutter/cupertino.dart'; import 'package:shared_preferences/shared_preferences.dart'; enum ThemePreference { system, light, dark; static ThemePreference parse(String? raw) { return switch (raw) { 'light' => ThemePreference.light, 'dark' => ThemePreference.dark, _ => ThemePreference.system, }; } Brightness resolve(Brightness platform) => switch (this) { ThemePreference.system => platform, ThemePreference.light => Brightness.light, ThemePreference.dark => Brightness.dark, }; } abstract interface class ThemePreferenceStore { Future read(); Future write(String value); } class PrefsThemeStore implements ThemePreferenceStore { const PrefsThemeStore(); static const key = 'ppm_theme_preference'; @override Future read() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString(key); } @override Future write(String value) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(key, value); } } class MemoryThemeStore implements ThemePreferenceStore { MemoryThemeStore([this.value]); String? value; @override Future read() async => value; @override Future write(String next) async => value = next; } /// Survives logout: appearance is a device preference, not a session one. class ThemeController extends ChangeNotifier { ThemeController({ThemePreferenceStore? store}) : _store = store ?? const PrefsThemeStore(); final ThemePreferenceStore _store; ThemePreference _preference = ThemePreference.system; ThemePreference get preference => _preference; Brightness resolve(Brightness platform) => _preference.resolve(platform); Future restore() async { _preference = ThemePreference.parse(await _store.read()); notifyListeners(); } Future setPreference(ThemePreference value) async { if (_preference == value) return; _preference = value; notifyListeners(); await _store.write(value.name); } }