Files
jizhi/frontend/lib/shared/services/session_store.dart
T
2026-07-24 23:11:20 +08:00

206 lines
7.4 KiB
Dart

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<void> 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<void> 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<void> 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<void> 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<void> 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<void> 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<void> 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<void> markNeedsReauth() async {
if (!isAccount || _needsReauth) return;
_needsReauth = true;
final preferences = _preferences ??= await SharedPreferences.getInstance();
await preferences.setBool('session_needs_reauth', true);
notifyListeners();
}
Future<void> 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 ?? '此功能需要登录并连接网络后使用');
}
}
}