D.3.2 三态保存指示器: - 未保存 (灰色) → 保存中 (琥珀色脉冲点) → 已保存 (绿色点) - _PulsingDot 动画组件,800ms 呼吸效果 - 点击'完成'时显示保存中状态 D.3.3 工具栏触摸目标: - BoxConstraints 36x36 → 44x44,符合 WCAG 标准 D.3.4 主题偏好持久化: - SettingsBloc 接受 SharedPreferences,保存/恢复 themeMode - NuanjiApp 改为 StatefulWidget,异步初始化 SharedPreferences - 启动时显示 loading,初始化完成后渲染 app
74 lines
1.9 KiB
Dart
74 lines
1.9 KiB
Dart
// 设置 BLoC — 主题切换 + 应用设置管理
|
||
//
|
||
// ChangeNotifier 模式(同 MoodBloc),通过 ListenableBuilder 消费。
|
||
// 主题偏好持久化到 SharedPreferences。
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:shared_preferences/shared_preferences.dart';
|
||
|
||
const _kThemeMode = 'settings_theme_mode';
|
||
|
||
// ===== State =====
|
||
|
||
/// 设置页面状态
|
||
class SettingsState {
|
||
final ThemeMode themeMode;
|
||
final bool isLoading;
|
||
|
||
const SettingsState({
|
||
this.themeMode = ThemeMode.system,
|
||
this.isLoading = false,
|
||
});
|
||
|
||
SettingsState copyWith({ThemeMode? themeMode, bool? isLoading}) =>
|
||
SettingsState(
|
||
themeMode: themeMode ?? this.themeMode,
|
||
isLoading: isLoading ?? this.isLoading,
|
||
);
|
||
}
|
||
|
||
// ===== BLoC =====
|
||
|
||
/// 设置管理器 — 全局单例,在 NuanjiApp 中创建
|
||
class SettingsBloc extends ChangeNotifier {
|
||
SettingsBloc({SharedPreferences? prefs}) : _prefs = prefs {
|
||
_loadSavedTheme();
|
||
}
|
||
|
||
final SharedPreferences? _prefs;
|
||
SettingsState _state = const SettingsState();
|
||
SettingsState get state => _state;
|
||
|
||
/// 从 SharedPreferences 恢复保存的主题
|
||
void _loadSavedTheme() {
|
||
if (_prefs == null) return;
|
||
final saved = _prefs?.getString(_kThemeMode);
|
||
if (saved != null) {
|
||
final mode = switch (saved) {
|
||
'light' => ThemeMode.light,
|
||
'dark' => ThemeMode.dark,
|
||
_ => ThemeMode.system,
|
||
};
|
||
_state = _state.copyWith(themeMode: mode);
|
||
notifyListeners();
|
||
}
|
||
}
|
||
|
||
/// 切换主题模式
|
||
void changeTheme(ThemeMode mode) {
|
||
_state = _state.copyWith(themeMode: mode);
|
||
notifyListeners();
|
||
_prefs?.setString(_kThemeMode, mode.name);
|
||
}
|
||
|
||
/// 循环切换: system → light → dark → system
|
||
void cycleTheme() {
|
||
final next = switch (_state.themeMode) {
|
||
ThemeMode.system => ThemeMode.light,
|
||
ThemeMode.light => ThemeMode.dark,
|
||
ThemeMode.dark => ThemeMode.system,
|
||
};
|
||
changeTheme(next);
|
||
}
|
||
}
|