191 lines
6.7 KiB
Dart
191 lines
6.7 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import '../../../../core/storage/secure_storage.dart';
|
||
import '../../../../core/storage/storage_keys.dart';
|
||
import '../../../../core/di/injection_container.dart';
|
||
import '../../../../core/telemetry/telemetry_service.dart';
|
||
import '../../../../core/sentry/sentry_service.dart';
|
||
|
||
enum AuthStatus {
|
||
initial,
|
||
checking,
|
||
authenticated,
|
||
unauthenticated,
|
||
}
|
||
|
||
class AuthState {
|
||
final AuthStatus status;
|
||
final String? walletAddress;
|
||
final bool isWalletCreated;
|
||
final bool isFirstLaunch;
|
||
final bool hasSeenGuide;
|
||
final String? errorMessage;
|
||
// 新增:账号是否已创建(但钱包可能还未就绪)
|
||
final bool isAccountCreated;
|
||
// 新增:钱包是否已就绪
|
||
final bool isWalletReady;
|
||
// 新增:用户序列号(用于跳转到备份助记词页面)
|
||
final String? userSerialNum;
|
||
// 新增:推荐码
|
||
final String? referralCode;
|
||
|
||
const AuthState({
|
||
this.status = AuthStatus.initial,
|
||
this.walletAddress,
|
||
this.isWalletCreated = false,
|
||
this.isFirstLaunch = true,
|
||
this.hasSeenGuide = false,
|
||
this.errorMessage,
|
||
this.isAccountCreated = false,
|
||
this.isWalletReady = false,
|
||
this.userSerialNum,
|
||
this.referralCode,
|
||
});
|
||
|
||
AuthState copyWith({
|
||
AuthStatus? status,
|
||
String? walletAddress,
|
||
bool? isWalletCreated,
|
||
bool? isFirstLaunch,
|
||
bool? hasSeenGuide,
|
||
String? errorMessage,
|
||
bool? isAccountCreated,
|
||
bool? isWalletReady,
|
||
String? userSerialNum,
|
||
String? referralCode,
|
||
}) {
|
||
return AuthState(
|
||
status: status ?? this.status,
|
||
walletAddress: walletAddress ?? this.walletAddress,
|
||
isWalletCreated: isWalletCreated ?? this.isWalletCreated,
|
||
isFirstLaunch: isFirstLaunch ?? this.isFirstLaunch,
|
||
hasSeenGuide: hasSeenGuide ?? this.hasSeenGuide,
|
||
errorMessage: errorMessage,
|
||
isAccountCreated: isAccountCreated ?? this.isAccountCreated,
|
||
isWalletReady: isWalletReady ?? this.isWalletReady,
|
||
userSerialNum: userSerialNum ?? this.userSerialNum,
|
||
referralCode: referralCode ?? this.referralCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
class AuthNotifier extends StateNotifier<AuthState> {
|
||
final SecureStorage _secureStorage;
|
||
|
||
AuthNotifier(this._secureStorage) : super(const AuthState());
|
||
|
||
Future<void> checkAuthStatus() async {
|
||
state = state.copyWith(status: AuthStatus.checking);
|
||
|
||
try {
|
||
// 检查是否首次启动
|
||
final isFirstLaunchStr = await _secureStorage.read(key: StorageKeys.isFirstLaunch);
|
||
final isFirstLaunch = isFirstLaunchStr == null || isFirstLaunchStr != 'false';
|
||
|
||
// 检查账号是否已创建
|
||
final isAccountCreatedStr = await _secureStorage.read(key: StorageKeys.isAccountCreated);
|
||
final isAccountCreated = isAccountCreatedStr == 'true';
|
||
|
||
// 检查钱包是否已就绪
|
||
final isWalletReadyStr = await _secureStorage.read(key: StorageKeys.isWalletReady);
|
||
final isWalletReady = isWalletReadyStr == 'true';
|
||
|
||
// 检查助记词是否已备份
|
||
final isMnemonicBackedUpStr = await _secureStorage.read(key: StorageKeys.isMnemonicBackedUp);
|
||
final isMnemonicBackedUp = isMnemonicBackedUpStr == 'true';
|
||
|
||
// 获取用户序列号和推荐码(用于跳转到备份页面)
|
||
final userSerialNum = await _secureStorage.read(key: StorageKeys.userSerialNum);
|
||
final referralCode = await _secureStorage.read(key: StorageKeys.referralCode);
|
||
|
||
// 旧版兼容:检查旧的 walletAddress 字段
|
||
final walletAddress = await _secureStorage.read(key: StorageKeys.walletAddress);
|
||
final hasLegacyWallet = walletAddress != null && walletAddress.isNotEmpty;
|
||
|
||
// 综合判断钱包是否已创建完成
|
||
// 1. 新版:isWalletReady == true 且 isMnemonicBackedUp == true
|
||
// 2. 旧版兼容:有 walletAddress
|
||
final isWalletCreated = (isWalletReady && isMnemonicBackedUp) || hasLegacyWallet;
|
||
|
||
if (isWalletCreated) {
|
||
// 钱包已创建且备份完成,进入主页面
|
||
state = state.copyWith(
|
||
status: AuthStatus.authenticated,
|
||
walletAddress: walletAddress,
|
||
isWalletCreated: true,
|
||
isAccountCreated: true,
|
||
isWalletReady: true,
|
||
isFirstLaunch: false,
|
||
hasSeenGuide: true,
|
||
userSerialNum: userSerialNum,
|
||
referralCode: referralCode,
|
||
);
|
||
// 设置遥测服务的用户ID(使用userSerialNum,如D25121400005)
|
||
if (userSerialNum != null && TelemetryService().isInitialized) {
|
||
TelemetryService().setUserId(userSerialNum);
|
||
}
|
||
// 设置 Sentry 用户信息
|
||
if (userSerialNum != null && SentryService().isInitialized) {
|
||
SentryService().setUser(userId: userSerialNum);
|
||
}
|
||
} else if (isAccountCreated) {
|
||
// 账号已创建但钱包未完成(可能正在生成或未备份)
|
||
state = state.copyWith(
|
||
status: AuthStatus.unauthenticated,
|
||
isWalletCreated: false,
|
||
isAccountCreated: true,
|
||
isWalletReady: isWalletReady,
|
||
isFirstLaunch: false,
|
||
hasSeenGuide: true,
|
||
userSerialNum: userSerialNum,
|
||
referralCode: referralCode,
|
||
);
|
||
} else {
|
||
// 账号未创建
|
||
state = state.copyWith(
|
||
status: AuthStatus.unauthenticated,
|
||
isWalletCreated: false,
|
||
isAccountCreated: false,
|
||
isWalletReady: false,
|
||
isFirstLaunch: isFirstLaunch,
|
||
hasSeenGuide: !isFirstLaunch,
|
||
);
|
||
}
|
||
} catch (e) {
|
||
state = state.copyWith(
|
||
status: AuthStatus.unauthenticated,
|
||
errorMessage: e.toString(),
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 标记已查看向导页
|
||
Future<void> markGuideAsSeen() async {
|
||
await _secureStorage.write(key: StorageKeys.isFirstLaunch, value: 'false');
|
||
state = state.copyWith(
|
||
isFirstLaunch: false,
|
||
hasSeenGuide: true,
|
||
);
|
||
}
|
||
|
||
Future<void> saveWallet(String walletAddress, String privateKey) async {
|
||
await _secureStorage.write(key: StorageKeys.walletAddress, value: walletAddress);
|
||
await _secureStorage.write(key: StorageKeys.privateKey, value: privateKey);
|
||
|
||
state = state.copyWith(
|
||
status: AuthStatus.authenticated,
|
||
walletAddress: walletAddress,
|
||
isWalletCreated: true,
|
||
);
|
||
}
|
||
|
||
Future<void> logout() async {
|
||
await _secureStorage.deleteAll();
|
||
state = const AuthState(status: AuthStatus.unauthenticated);
|
||
}
|
||
}
|
||
|
||
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
|
||
final secureStorage = ref.watch(secureStorageProvider);
|
||
return AuthNotifier(secureStorage);
|
||
});
|