Files
nj/app/lib/features/profile/bloc/settings_bloc.dart
iven ec8a04c80a
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
feat(app): D.3 中等优先级 UX 改进 — 保存指示器 + 触摸目标 + 主题持久化
D.3.2 三态保存指示器:
- 未保存 (灰色) → 保存中 (琥珀色脉冲点) → 已保存 (绿色点)
- _PulsingDot 动画组件,800ms 呼吸效果
- 点击'完成'时显示保存中状态

D.3.3 工具栏触摸目标:
- BoxConstraints 36x36 → 44x44,符合 WCAG 标准

D.3.4 主题偏好持久化:
- SettingsBloc 接受 SharedPreferences,保存/恢复 themeMode
- NuanjiApp 改为 StatefulWidget,异步初始化 SharedPreferences
- 启动时显示 loading,初始化完成后渲染 app
2026-06-07 13:50:34 +08:00

74 lines
1.9 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 设置 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);
}
}