292 lines
8.2 KiB
Dart
292 lines
8.2 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:isar/isar.dart';
|
||
|
||
import '../../data/models/schema.dart';
|
||
|
||
/// 语言设置枚举
|
||
enum LanguageType {
|
||
system, // 跟随系统
|
||
chineseSimple, // 简体中文
|
||
chineseTraditional, // 繁体中文
|
||
english, // 英文
|
||
arabic, // 阿拉伯语(RTL 支持)
|
||
}
|
||
|
||
/// 设置提供者
|
||
final settingsProvider = StateNotifierProvider<SettingsNotifier, AppSettings>(
|
||
(ref) => SettingsNotifier(),
|
||
);
|
||
|
||
/// 应用设置数据模型
|
||
class AppSettings {
|
||
final ThemeModeType themeMode;
|
||
final LanguageType language;
|
||
final double gridSize;
|
||
final bool showGrid;
|
||
final bool snapToGrid;
|
||
final bool autoSave;
|
||
final int autoSaveIntervalMinutes;
|
||
final bool enableAnimations;
|
||
final bool enableAntialiasing;
|
||
final RenderQuality renderQuality;
|
||
|
||
AppSettings({
|
||
this.themeMode = ThemeModeType.system,
|
||
this.language = LanguageType.system,
|
||
this.gridSize = 10.0,
|
||
this.showGrid = true,
|
||
this.snapToGrid = true,
|
||
this.autoSave = true,
|
||
this.autoSaveIntervalMinutes = 5,
|
||
this.enableAnimations = true,
|
||
this.enableAntialiasing = true,
|
||
this.renderQuality = RenderQuality.balanced,
|
||
});
|
||
|
||
AppSettings copyWith({
|
||
ThemeModeType? themeMode,
|
||
LanguageType? language,
|
||
double? gridSize,
|
||
bool? showGrid,
|
||
bool? snapToGrid,
|
||
bool? autoSave,
|
||
int? autoSaveIntervalMinutes,
|
||
bool? enableAnimations,
|
||
bool? enableAntialiasing,
|
||
RenderQuality? renderQuality,
|
||
}) {
|
||
return AppSettings(
|
||
themeMode: themeMode ?? this.themeMode,
|
||
language: language ?? this.language,
|
||
gridSize: gridSize ?? this.gridSize,
|
||
showGrid: showGrid ?? this.showGrid,
|
||
snapToGrid: snapToGrid ?? this.snapToGrid,
|
||
autoSave: autoSave ?? this.autoSave,
|
||
autoSaveIntervalMinutes: autoSaveIntervalMinutes ?? this.autoSaveIntervalMinutes,
|
||
enableAnimations: enableAnimations ?? this.enableAnimations,
|
||
enableAntialiasing: enableAntialiasing ?? this.enableAntialiasing,
|
||
renderQuality: renderQuality ?? this.renderQuality,
|
||
);
|
||
}
|
||
|
||
/// 获取对应的 Locale
|
||
Locale? get locale {
|
||
switch (language) {
|
||
case LanguageType.system:
|
||
return null; // 使用系统语言
|
||
case LanguageType.chineseSimple:
|
||
return const Locale('zh', 'CN');
|
||
case LanguageType.chineseTraditional:
|
||
return const Locale('zh', 'TW');
|
||
case LanguageType.english:
|
||
return const Locale('en', 'US');
|
||
case LanguageType.arabic:
|
||
return const Locale('ar', 'SA');
|
||
}
|
||
}
|
||
|
||
/// 判断是否为 RTL 语言
|
||
bool get isRtl {
|
||
return language == LanguageType.arabic;
|
||
}
|
||
|
||
/// 获取语言显示名称
|
||
String get languageDisplayName {
|
||
switch (language) {
|
||
case LanguageType.system:
|
||
return '系统语言';
|
||
case LanguageType.chineseSimple:
|
||
return '简体中文';
|
||
case LanguageType.chineseTraditional:
|
||
return '繁體中文';
|
||
case LanguageType.english:
|
||
return 'English';
|
||
case LanguageType.arabic:
|
||
return 'العربية';
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 渲染质量枚举
|
||
enum RenderQuality {
|
||
high, // 高质量
|
||
balanced, // 平衡
|
||
performance // 性能模式
|
||
}
|
||
|
||
/// 主题模式枚举(从 eda_theme 导入或重新定义)
|
||
enum ThemeModeType {
|
||
system,
|
||
light,
|
||
dark,
|
||
}
|
||
|
||
/// 设置状态管理器
|
||
class SettingsNotifier extends StateNotifier<AppSettings> {
|
||
SettingsNotifier() : super(AppSettings());
|
||
|
||
Isar? _isar;
|
||
|
||
/// 初始化 Isar 数据库
|
||
void initIsar(Isar isar) {
|
||
_isar = isar;
|
||
_loadSettings();
|
||
}
|
||
|
||
/// 从本地存储加载设置
|
||
Future<void> _loadSettings() async {
|
||
if (_isar == null) return;
|
||
|
||
try {
|
||
final settings = await _isar.settings.filter().idEqualTo('app_settings').findFirst();
|
||
if (settings != null) {
|
||
state = AppSettings(
|
||
themeMode: ThemeModeType.values.firstWhere(
|
||
(e) => e.name == settings.themeMode,
|
||
orElse: () => ThemeModeType.system,
|
||
),
|
||
language: LanguageType.values.firstWhere(
|
||
(e) => e.name == settings.language,
|
||
orElse: () => LanguageType.system,
|
||
),
|
||
gridSize: settings.gridSize,
|
||
showGrid: settings.showGrid,
|
||
snapToGrid: settings.snapToGrid,
|
||
autoSave: settings.autoSave,
|
||
autoSaveIntervalMinutes: settings.autoSaveInterval,
|
||
enableAnimations: settings.enableAnimations,
|
||
enableAntialiasing: settings.enableAntialiasing,
|
||
renderQuality: RenderQuality.values.firstWhere(
|
||
(e) => e.name == settings.renderQuality,
|
||
orElse: () => RenderQuality.balanced,
|
||
),
|
||
);
|
||
}
|
||
} catch (e) {
|
||
debugPrint('加载设置失败:$e');
|
||
}
|
||
}
|
||
|
||
/// 保存设置到本地存储
|
||
Future<void> _saveSettings() async {
|
||
if (_isar == null) return;
|
||
|
||
try {
|
||
final settings = Settings()
|
||
..id = 'app_settings'
|
||
..themeMode = state.themeMode.name
|
||
..language = state.language.name
|
||
..gridSize = state.gridSize
|
||
..showGrid = state.showGrid
|
||
..snapToGrid = state.snapToGrid
|
||
..autoSave = state.autoSave
|
||
..autoSaveInterval = state.autoSaveIntervalMinutes
|
||
..enableAnimations = state.enableAnimations
|
||
..enableAntialiasing = state.enableAntialiasing
|
||
..renderQuality = state.renderQuality.name;
|
||
|
||
await _isar.writeTxn(() => _isar!.settings.put(settings));
|
||
} catch (e) {
|
||
debugPrint('保存设置失败:$e');
|
||
}
|
||
}
|
||
|
||
/// 设置主题模式
|
||
Future<void> setThemeMode(ThemeModeType mode) async {
|
||
state = state.copyWith(themeMode: mode);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 切换深色模式
|
||
Future<void> toggleDarkMode() async {
|
||
final newMode = state.themeMode == ThemeModeType.dark
|
||
? ThemeModeType.light
|
||
: ThemeModeType.dark;
|
||
await setThemeMode(newMode);
|
||
}
|
||
|
||
/// 设置语言
|
||
Future<void> setLanguage(LanguageType language) async {
|
||
state = state.copyWith(language: language);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 设置网格大小
|
||
Future<void> setGridSize(double size) async {
|
||
state = state.copyWith(gridSize: size);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 切换网格显示
|
||
Future<void> toggleShowGrid() async {
|
||
state = state.copyWith(showGrid: !state.showGrid);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 切换网格吸附
|
||
Future<void> toggleSnapToGrid() async {
|
||
state = state.copyWith(snapToGrid: !state.snapToGrid);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 设置自动保存
|
||
Future<void> setAutoSave(bool enabled) async {
|
||
state = state.copyWith(autoSave: enabled);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 设置自动保存间隔
|
||
Future<void> setAutoSaveInterval(int minutes) async {
|
||
state = state.copyWith(autoSaveIntervalMinutes: minutes);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 切换动画
|
||
Future<void> toggleAnimations() async {
|
||
state = state.copyWith(enableAnimations: !state.enableAnimations);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 切换抗锯齿
|
||
Future<void> toggleAntialiasing() async {
|
||
state = state.copyWith(enableAntialiasing: !state.enableAntialiasing);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 设置渲染质量
|
||
Future<void> setRenderQuality(RenderQuality quality) async {
|
||
state = state.copyWith(renderQuality: quality);
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 重置为默认设置
|
||
Future<void> resetToDefaults() async {
|
||
state = AppSettings();
|
||
await _saveSettings();
|
||
}
|
||
|
||
/// 获取对应的 Flutter ThemeMode
|
||
ThemeMode get flutterThemeMode {
|
||
switch (state.themeMode) {
|
||
case ThemeModeType.system:
|
||
return ThemeMode.system;
|
||
case ThemeModeType.light:
|
||
return ThemeMode.light;
|
||
case ThemeModeType.dark:
|
||
return ThemeMode.dark;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 语言选项提供者(用于 UI 显示)
|
||
final languageOptionsProvider = Provider<List<MapEntry<LanguageType, String>>>(
|
||
(ref) => [
|
||
const MapEntry(LanguageType.system, '系统语言 / System'),
|
||
const MapEntry(LanguageType.chineseSimple, '简体中文'),
|
||
const MapEntry(LanguageType.chineseTraditional, '繁體中文'),
|
||
const MapEntry(LanguageType.english, 'English'),
|
||
const MapEntry(LanguageType.arabic, 'العربية'),
|
||
],
|
||
);
|