Files
social-app/apps/lib/features/auth/presentation/cubits/register_cubit.dart
T

228 lines
6.0 KiB
Dart

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:formz/formz.dart';
import 'package:equatable/equatable.dart';
import '../../../../core/api/api_exception.dart';
import '../../../../core/form_inputs/form_inputs.dart';
import '../../data/auth_repository.dart';
import '../../data/models/signup_request.dart';
import '../../data/models/auth_response.dart';
class RegisterState extends Equatable {
final Username username;
final Email email;
final Password password;
final VerificationCode verificationCode;
final FormzSubmissionStatus status;
final String? errorMessage;
final String? pendingEmail;
final bool codeSent;
final bool isSending;
const RegisterState({
this.username = const Username.pure(),
this.email = const Email.pure(),
this.password = const Password.pure(),
this.verificationCode = const VerificationCode.pure(),
this.status = FormzSubmissionStatus.initial,
this.errorMessage,
this.pendingEmail,
this.codeSent = false,
this.isSending = false,
});
bool get isStep1Valid =>
username.isValid && email.isValid && password.isValid;
bool get isStep2Valid => verificationCode.isValid;
RegisterState copyWith({
Username? username,
Email? email,
Password? password,
VerificationCode? verificationCode,
FormzSubmissionStatus? status,
String? errorMessage,
String? pendingEmail,
bool? codeSent,
bool? isSending,
}) {
return RegisterState(
username: username ?? this.username,
email: email ?? this.email,
password: password ?? this.password,
verificationCode: verificationCode ?? this.verificationCode,
status: status ?? this.status,
errorMessage: errorMessage,
pendingEmail: pendingEmail ?? this.pendingEmail,
codeSent: codeSent ?? this.codeSent,
isSending: isSending ?? this.isSending,
);
}
@override
List<Object?> get props => [
username,
email,
password,
verificationCode,
status,
errorMessage,
pendingEmail,
codeSent,
isSending,
];
}
class RegisterCubit extends Cubit<RegisterState> {
final AuthRepository _repository;
RegisterCubit(this._repository) : super(const RegisterState());
void usernameChanged(String value) {
emit(state.copyWith(username: Username.dirty(value)));
}
void emailChanged(String value) {
emit(state.copyWith(email: Email.dirty(value)));
}
void passwordChanged(String value) {
emit(state.copyWith(password: Password.dirty(value)));
}
void verificationCodeChanged(String value) {
emit(state.copyWith(verificationCode: VerificationCode.dirty(value)));
}
Future<bool> submitStep1() async {
if (!state.isStep1Valid) return false;
emit(state.copyWith(status: FormzSubmissionStatus.inProgress));
try {
final response = await _repository.createVerification(
SignupStartRequest(
username: state.username.value,
email: state.email.value,
password: state.password.value,
),
);
emit(
state.copyWith(
status: FormzSubmissionStatus.success,
pendingEmail: response.email,
codeSent: true,
),
);
return true;
} catch (e) {
final message = e is ApiException ? e.message : e.toString();
emit(
state.copyWith(
status: FormzSubmissionStatus.failure,
errorMessage: message,
),
);
return false;
}
}
Future<AuthResponse?> submitStep2() async {
if (!state.isStep2Valid || state.pendingEmail == null) return null;
emit(state.copyWith(status: FormzSubmissionStatus.inProgress));
try {
final response = await _repository.verifyVerification(
SignupVerifyRequest(
email: state.pendingEmail!,
token: state.verificationCode.value,
),
);
emit(state.copyWith(status: FormzSubmissionStatus.success));
return response;
} catch (e) {
final message = e is ApiException ? e.message : e.toString();
emit(
state.copyWith(
status: FormzSubmissionStatus.failure,
errorMessage: message,
),
);
return null;
}
}
Future<bool> resendCode() async {
if (state.pendingEmail == null) {
emit(
state.copyWith(
status: FormzSubmissionStatus.failure,
errorMessage: '验证码发送失败,请返回上一步重试',
),
);
return false;
}
emit(state.copyWith(status: FormzSubmissionStatus.inProgress));
try {
await _repository.resendVerification(
SignupResendRequest(email: state.pendingEmail!),
);
emit(
state.copyWith(status: FormzSubmissionStatus.success, codeSent: true),
);
return true;
} catch (e) {
final message = e is ApiException ? e.message : '验证码发送失败,请重试';
emit(
state.copyWith(
status: FormzSubmissionStatus.failure,
errorMessage: message,
),
);
return false;
}
}
Future<void> sendCodeSilently() async {
if (!state.isStep1Valid || state.isSending) return;
emit(
state.copyWith(
isSending: true,
status: FormzSubmissionStatus.inProgress,
errorMessage: null,
),
);
try {
final response = await _repository.createVerification(
SignupStartRequest(
username: state.username.value,
email: state.email.value,
password: state.password.value,
),
);
emit(
state.copyWith(
isSending: false,
status: FormzSubmissionStatus.success,
pendingEmail: response.email,
codeSent: true,
errorMessage: null,
),
);
} catch (e) {
final message = e is ApiException ? e.message : '验证码发送失败,请重试';
emit(
state.copyWith(
isSending: false,
status: FormzSubmissionStatus.failure,
errorMessage: message,
),
);
}
}
}