import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:miaoji_zhang/shared/services/local_database.dart'; class OnlineFeatureRequiredException implements Exception { final String message; const OnlineFeatureRequiredException([this.message = '此功能需要登录并连接网络后使用']); @override String toString() => message; } class SessionStore extends ChangeNotifier { SessionStore._(); static final instance = SessionStore._(); SharedPreferences? _preferences; String _mode = 'none'; int? _userId; String? _username; String? _nickname; String _appMode = 'normal'; bool _onboardingDone = true; bool _cloudSyncEnabled = true; bool _needsReauth = false; bool _aiEnabled = false; bool get isGuest => _mode == 'guest'; bool get isAccount => _mode == 'account' && _userId != null; bool get hasSession => isGuest || isAccount; bool get cloudSyncEnabled => isAccount && _cloudSyncEnabled; bool get needsReauth => _needsReauth; bool get aiEnabled => isAccount && _aiEnabled; bool get shouldUseLocalOnly => isGuest || !cloudSyncEnabled || needsReauth; int? get userId => _userId; String? get username => _username; String? get nickname => _nickname; String get appMode => _appMode; bool get onboardingDone => _onboardingDone; String get namespace => isGuest ? 'guest' : 'user_${_userId ?? 'none'}'; Future initialize() async { _preferences ??= await SharedPreferences.getInstance(); final preferences = _preferences!; _mode = preferences.getString('session_mode') ?? 'none'; _userId = preferences.getInt('session_user_id'); _username = preferences.getString('session_username'); _nickname = preferences.getString('session_nickname'); _appMode = preferences.getString('session_app_mode') ?? 'normal'; _onboardingDone = preferences.getBool('session_onboarding_done') ?? true; _cloudSyncEnabled = preferences.getBool('session_cloud_sync') ?? true; _needsReauth = preferences.getBool('session_needs_reauth') ?? false; _aiEnabled = preferences.getBool('session_ai_enabled') ?? (_mode == 'account'); if (hasSession) { await LocalDatabase.instance.openNamespace(namespace); } else if (_mode != 'none') { _mode = 'none'; await preferences.setString('session_mode', 'none'); } } Future startGuest() async { final preferences = _preferences ??= await SharedPreferences.getInstance(); _mode = 'guest'; _userId = null; _username = '游客'; _nickname = '游客'; _appMode = 'normal'; _onboardingDone = true; _cloudSyncEnabled = false; _needsReauth = false; _aiEnabled = false; await preferences.setString('session_mode', _mode); await preferences.remove('session_user_id'); await preferences.setString('session_username', _username!); await preferences.setString('session_nickname', _nickname!); await preferences.setString('session_app_mode', _appMode); await preferences.setBool('session_onboarding_done', true); await preferences.setBool('session_cloud_sync', false); await preferences.setBool('session_needs_reauth', false); await LocalDatabase.instance.openNamespace(namespace); notifyListeners(); } Future activateAccount({ required int userId, required String username, String? nickname, required String appMode, required bool onboardingDone, required bool aiEnabled, }) async { final preferences = _preferences ??= await SharedPreferences.getInstance(); _mode = 'account'; _userId = userId; _username = username; _nickname = nickname; _appMode = appMode; _onboardingDone = onboardingDone; _aiEnabled = aiEnabled; _cloudSyncEnabled = preferences.getBool('cloud_sync_user_$userId') ?? true; _needsReauth = false; await preferences.setString('session_mode', _mode); await preferences.setInt('session_user_id', userId); await preferences.setString('session_username', username); if (nickname == null) { await preferences.remove('session_nickname'); } else { await preferences.setString('session_nickname', nickname); } await preferences.setString('session_app_mode', appMode); await preferences.setBool('session_onboarding_done', onboardingDone); await preferences.setBool('session_ai_enabled', aiEnabled); await preferences.setBool('session_cloud_sync', _cloudSyncEnabled); await preferences.setBool('session_needs_reauth', false); await LocalDatabase.instance.openNamespace(namespace); notifyListeners(); } Future updateNickname(String? nickname) async { _nickname = nickname; notifyListeners(); final preferences = _preferences ??= await SharedPreferences.getInstance(); if (nickname == null) { await preferences.remove('session_nickname'); } else { await preferences.setString('session_nickname', nickname); } } Future updateCachedProfile({ required String appMode, required bool onboardingDone, String? nickname, bool? aiEnabled, }) async { _appMode = appMode; _onboardingDone = onboardingDone; _nickname = nickname ?? _nickname; _aiEnabled = aiEnabled ?? _aiEnabled; final preferences = _preferences ??= await SharedPreferences.getInstance(); await preferences.setString('session_app_mode', _appMode); await preferences.setBool('session_onboarding_done', _onboardingDone); await preferences.setBool('session_ai_enabled', _aiEnabled); if (_nickname != null) { await preferences.setString('session_nickname', _nickname!); } notifyListeners(); } Future setAiEnabled(bool enabled) async { if (_aiEnabled == enabled) return; _aiEnabled = enabled; if (!enabled) _appMode = 'normal'; final preferences = _preferences ??= await SharedPreferences.getInstance(); await preferences.setBool('session_ai_enabled', enabled); if (!enabled) await preferences.setString('session_app_mode', 'normal'); notifyListeners(); } Future setCloudSyncEnabled(bool enabled) async { if (!isAccount) return; _cloudSyncEnabled = enabled; final preferences = _preferences ??= await SharedPreferences.getInstance(); await preferences.setBool('session_cloud_sync', enabled); await preferences.setBool('cloud_sync_user_$_userId', enabled); notifyListeners(); } Future markNeedsReauth() async { if (!isAccount || _needsReauth) return; _needsReauth = true; final preferences = _preferences ??= await SharedPreferences.getInstance(); await preferences.setBool('session_needs_reauth', true); notifyListeners(); } Future clearActiveSession() async { final preferences = _preferences ??= await SharedPreferences.getInstance(); _mode = 'none'; _userId = null; _username = null; _nickname = null; _appMode = 'normal'; _onboardingDone = true; _cloudSyncEnabled = true; _needsReauth = false; _aiEnabled = false; await preferences.setString('session_mode', 'none'); await preferences.remove('session_user_id'); await preferences.remove('session_username'); await preferences.remove('session_nickname'); await preferences.remove('session_needs_reauth'); LocalDatabase.instance.close(); notifyListeners(); } void requireOnline([String? message]) { if (shouldUseLocalOnly) { throw OnlineFeatureRequiredException(message ?? '此功能需要登录并连接网络后使用'); } } }