feat: Implement support chat functionality, add 2FA verification screen and routing, and update dependencies.
This commit is contained in:
@@ -16,6 +16,9 @@ class AuthState {
|
||||
final String? errorMessage;
|
||||
final List<FieldError> fieldErrors;
|
||||
final String registeredEmail;
|
||||
final bool requiresTwoFactor;
|
||||
final String? tempToken;
|
||||
final String? twoFactorEmail;
|
||||
|
||||
const AuthState({
|
||||
this.status = AuthStatus.initial,
|
||||
@@ -23,6 +26,9 @@ class AuthState {
|
||||
this.errorMessage,
|
||||
this.fieldErrors = const [],
|
||||
this.registeredEmail = '',
|
||||
this.requiresTwoFactor = false,
|
||||
this.tempToken,
|
||||
this.twoFactorEmail,
|
||||
});
|
||||
|
||||
AuthState copyWith({
|
||||
@@ -31,6 +37,9 @@ class AuthState {
|
||||
String? errorMessage,
|
||||
List<FieldError>? fieldErrors,
|
||||
String? registeredEmail,
|
||||
bool? requiresTwoFactor,
|
||||
String? tempToken,
|
||||
String? twoFactorEmail,
|
||||
}) {
|
||||
return AuthState(
|
||||
status: status ?? this.status,
|
||||
@@ -38,6 +47,9 @@ class AuthState {
|
||||
errorMessage: errorMessage,
|
||||
fieldErrors: fieldErrors ?? this.fieldErrors,
|
||||
registeredEmail: registeredEmail ?? this.registeredEmail,
|
||||
requiresTwoFactor: requiresTwoFactor ?? this.requiresTwoFactor,
|
||||
tempToken: tempToken ?? this.tempToken,
|
||||
twoFactorEmail: twoFactorEmail ?? this.twoFactorEmail,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,8 +124,10 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
|
||||
if (result['requiresTwoFactor'] == true) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.error,
|
||||
errorMessage: '2FA verification required',
|
||||
status: AuthStatus.initial,
|
||||
requiresTwoFactor: true,
|
||||
tempToken: result['tempToken'] as String?,
|
||||
twoFactorEmail: email,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -189,6 +203,74 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> verifyTwoFactor(String token) async {
|
||||
final tempToken = state.tempToken;
|
||||
if (tempToken == null) return;
|
||||
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.loading,
|
||||
errorMessage: null,
|
||||
);
|
||||
|
||||
try {
|
||||
final authResponse = await _repository.verifyTwoFactor(
|
||||
tempToken: tempToken,
|
||||
token: token,
|
||||
);
|
||||
state = AuthState(
|
||||
status: AuthStatus.authenticated,
|
||||
user: authResponse.user,
|
||||
);
|
||||
_initPushNotifications();
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.initial,
|
||||
errorMessage: e.message,
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.initial,
|
||||
errorMessage: 'Verification failed. Please try again.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> verifyBackupCode(String backupCode) async {
|
||||
final tempToken = state.tempToken;
|
||||
if (tempToken == null) return;
|
||||
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.loading,
|
||||
errorMessage: null,
|
||||
);
|
||||
|
||||
try {
|
||||
final authResponse = await _repository.verifyBackupCode(
|
||||
tempToken: tempToken,
|
||||
backupCode: backupCode,
|
||||
);
|
||||
state = AuthState(
|
||||
status: AuthStatus.authenticated,
|
||||
user: authResponse.user,
|
||||
);
|
||||
_initPushNotifications();
|
||||
} on ApiException catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.initial,
|
||||
errorMessage: e.message,
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(
|
||||
status: AuthStatus.initial,
|
||||
errorMessage: 'Verification failed. Please try again.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void clearTwoFactor() {
|
||||
state = const AuthState();
|
||||
}
|
||||
|
||||
void _initPushNotifications() {
|
||||
final push = PushNotificationService();
|
||||
push.initialize().then((_) => push.registerAfterLogin());
|
||||
|
||||
Reference in New Issue
Block a user