feat(ui): theme-mode toggle (system / light / dark) with persistence
Three-way switch in the sidebar footer next to the settings gear. Cycles system → light → dark → system. Choice persists via shared_preferences across app launches; restored before the first frame so there's no theme flicker on startup. The icon changes per state (auto / sun / moon) and the tooltip spells it out so the cycling behaviour is discoverable. - StudioApp is now stateful; exposes StudioApp.of(context) to let descendants flip the theme without prop-drilling. - ThemeModeValue enum lives in data/hub.dart so the persistence layer stays free of flutter/material imports. Bumps fai_studio 0.6.0 -> 0.7.0. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
b3fdd69139
commit
671194c105
3 changed files with 119 additions and 29 deletions
|
|
@ -52,6 +52,22 @@ class HubService {
|
|||
await prefs.setBool(_kSecureKey, endpoint.secure);
|
||||
}
|
||||
|
||||
static const _kThemeKey = 'theme.mode';
|
||||
|
||||
/// Read the persisted theme mode (system / light / dark) for
|
||||
/// initial app startup. Defaults to system.
|
||||
Future<ThemeModeValue> loadThemeMode() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final raw = prefs.getString(_kThemeKey);
|
||||
return ThemeModeValue.fromWire(raw) ?? ThemeModeValue.system;
|
||||
}
|
||||
|
||||
/// Persist the theme mode the user chose.
|
||||
Future<void> saveThemeMode(ThemeModeValue mode) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_kThemeKey, mode.wire);
|
||||
}
|
||||
|
||||
Future<bool> healthy() => _client.healthy();
|
||||
|
||||
Future<List<ModuleSummary>> listModules() async {
|
||||
|
|
@ -216,6 +232,24 @@ class ServiceEntry {
|
|||
});
|
||||
}
|
||||
|
||||
/// Three-way switch persisted across launches.
|
||||
enum ThemeModeValue {
|
||||
system('system'),
|
||||
light('light'),
|
||||
dark('dark');
|
||||
|
||||
final String wire;
|
||||
const ThemeModeValue(this.wire);
|
||||
|
||||
static ThemeModeValue? fromWire(String? s) {
|
||||
if (s == null) return null;
|
||||
for (final v in values) {
|
||||
if (v.wire == s) return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// UI-side type, decoupled from the proto wire type so pages
|
||||
/// don't import protobuf packages.
|
||||
class ModuleSummary {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue