import 'dart:convert'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'auth_provider.dart'; class ElderModePreferences { final bool enabled; final bool largeTextEnabled; final bool voiceInputEnabled; const ElderModePreferences({ this.enabled = false, this.largeTextEnabled = true, this.voiceInputEnabled = true, }); ElderModePreferences copyWith({ bool? enabled, bool? largeTextEnabled, bool? voiceInputEnabled, }) { return ElderModePreferences( enabled: enabled ?? this.enabled, largeTextEnabled: largeTextEnabled ?? this.largeTextEnabled, voiceInputEnabled: voiceInputEnabled ?? this.voiceInputEnabled, ); } Map toJson() => { 'schemaVersion': 1, 'enabled': enabled, 'largeTextEnabled': largeTextEnabled, 'voiceInputEnabled': voiceInputEnabled, }; factory ElderModePreferences.fromJson(Map json) { return ElderModePreferences( enabled: json['enabled'] == true, largeTextEnabled: json['largeTextEnabled'] != false, voiceInputEnabled: json['voiceInputEnabled'] != false, ); } } class ElderModeState { final ElderModePreferences preferences; final bool isLoaded; final bool isSaving; final String? error; const ElderModeState({ this.preferences = const ElderModePreferences(), this.isLoaded = false, this.isSaving = false, this.error, }); bool get isEnabled => preferences.enabled; bool get useLargeText => isEnabled && preferences.largeTextEnabled; ElderModeState copyWith({ ElderModePreferences? preferences, bool? isLoaded, bool? isSaving, String? error, bool clearError = false, }) { return ElderModeState( preferences: preferences ?? this.preferences, isLoaded: isLoaded ?? this.isLoaded, isSaving: isSaving ?? this.isSaving, error: clearError ? null : error ?? this.error, ); } } final elderModeProvider = NotifierProvider( ElderModeNotifier.new, ); class ElderModeNotifier extends Notifier { static const _storageKeyPrefix = 'accessibility_preferences_v1:user_'; String? _currentUserId; @override ElderModeState build() { final userId = ref.watch( authProvider.select((state) => state.user?.id), ); _currentUserId = userId; if (userId == null || userId.isEmpty) { return const ElderModeState(isLoaded: true); } Future.microtask(_load); return const ElderModeState(); } String get _storageKey => '$_storageKeyPrefix$_currentUserId'; Future _load() async { if (_currentUserId == null || _currentUserId!.isEmpty) return; try { final raw = await ref.read(localDbProvider).read(_storageKey); if (raw == null || raw.trim().isEmpty) { state = state.copyWith(isLoaded: true, clearError: true); return; } final decoded = jsonDecode(raw); if (decoded is! Map) throw const FormatException('invalid preferences'); state = state.copyWith( preferences: ElderModePreferences.fromJson( Map.from(decoded), ), isLoaded: true, clearError: true, ); } catch (_) { state = state.copyWith(isLoaded: true, error: '长辈模式设置读取失败,已使用默认设置'); } } Future enable() => _save(state.preferences.copyWith(enabled: true, largeTextEnabled: true)); Future disable() => _save(state.preferences.copyWith(enabled: false)); Future setLargeTextEnabled(bool enabled) => _save(state.preferences.copyWith(largeTextEnabled: enabled)); Future setVoiceInputEnabled(bool enabled) => _save(state.preferences.copyWith(voiceInputEnabled: enabled)); Future _save(ElderModePreferences next) async { if (_currentUserId == null || _currentUserId!.isEmpty) { state = state.copyWith( isLoaded: true, error: '请先登录后再调整长辈模式', ); return false; } final previous = state.preferences; state = state.copyWith( preferences: next, isLoaded: true, isSaving: true, clearError: true, ); try { await ref.read(localDbProvider).write(_storageKey, jsonEncode(next)); state = state.copyWith(isSaving: false, clearError: true); return true; } catch (_) { state = state.copyWith( preferences: previous, isSaving: false, error: '保存失败,请稍后重试', ); return false; } } }