Files

130 lines
3.6 KiB
Dart
Raw Permalink Normal View History

2026-07-14 11:11:36 +08:00
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'shared/settings_persistence.dart';
enum HeaderMode { solid, frosted }
enum StartupPage { home, servers, aggregated, discover, settings }
const String kStartupPageKey = 'smplayer.startup_page';
StartupPage parseStartupPage(String? s) => switch (s) {
'servers' => StartupPage.servers,
'aggregated' => StartupPage.aggregated,
'discover' => StartupPage.discover,
'settings' => StartupPage.settings,
_ => StartupPage.home,
};
String startupPageToStr(StartupPage p) => switch (p) {
StartupPage.home => 'home',
StartupPage.servers => 'servers',
StartupPage.aggregated => 'aggregated',
StartupPage.discover => 'discover',
StartupPage.settings => 'settings',
};
String startupPagePath(StartupPage p) => switch (p) {
StartupPage.home => '/',
StartupPage.servers => '/servers',
StartupPage.aggregated => '/aggregated',
StartupPage.discover => '/discover',
StartupPage.settings => '/settings',
};
class AppearanceState {
final ThemeMode themeMode;
final HeaderMode headerMode;
final StartupPage startupPage;
const AppearanceState({
this.themeMode = ThemeMode.system,
this.headerMode = HeaderMode.frosted,
this.startupPage = StartupPage.home,
});
AppearanceState copyWith({
ThemeMode? themeMode,
HeaderMode? headerMode,
StartupPage? startupPage,
}) => AppearanceState(
themeMode: themeMode ?? this.themeMode,
headerMode: headerMode ?? this.headerMode,
startupPage: startupPage ?? this.startupPage,
);
}
class AppearanceNotifier extends AsyncNotifier<AppearanceState>
with SettingsPersistence {
static const _keyMode = 'smplayer.theme_mode';
static const _keyHeader = 'smplayer.header_mode';
@override
Future<AppearanceState> build() async {
final prefs = await getPrefs();
final raw = prefs.getString(_keyMode) ?? 'system';
final rawHeader = prefs.getString(_keyHeader) ?? 'frosted';
return AppearanceState(
themeMode: _parse(raw),
headerMode: _parseHeader(rawHeader),
startupPage: parseStartupPage(prefs.getString(kStartupPageKey)),
);
}
static ThemeMode _parse(String s) => switch (s) {
'light' => ThemeMode.light,
'dark' => ThemeMode.dark,
_ => ThemeMode.system,
};
static String _toStr(ThemeMode m) => switch (m) {
ThemeMode.light => 'light',
ThemeMode.dark => 'dark',
ThemeMode.system => 'system',
};
static HeaderMode _parseHeader(String s) => switch (s) {
'solid' => HeaderMode.solid,
'frosted' => HeaderMode.frosted,
_ => HeaderMode.frosted,
};
static String _headerToStr(HeaderMode m) => switch (m) {
HeaderMode.solid => 'solid',
HeaderMode.frosted => 'frosted',
};
Future<void> setThemeMode(ThemeMode mode) async {
final current = state.value ?? const AppearanceState();
state = AsyncValue.data(current.copyWith(themeMode: mode));
await persistField(_keyMode, _toStr(mode));
}
Future<void> setHeaderMode(HeaderMode mode) async {
final current = state.value ?? const AppearanceState();
state = AsyncValue.data(current.copyWith(headerMode: mode));
await persistField(_keyHeader, _headerToStr(mode));
}
Future<void> setStartupPage(StartupPage page) async {
final current = state.value ?? const AppearanceState();
state = AsyncValue.data(current.copyWith(startupPage: page));
await persistField(kStartupPageKey, startupPageToStr(page));
}
}
final initialLocationProvider = Provider<String>((_) => '/');
final appearanceProvider =
AsyncNotifierProvider<AppearanceNotifier, AppearanceState>(
AppearanceNotifier.new,
);