196 lines
5.2 KiB
Dart
196 lines
5.2 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.signupStart(
|
|
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.signupVerify(
|
|
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<void> resendCode() async {
|
|
if (state.pendingEmail == null) return;
|
|
|
|
try {
|
|
await _repository.signupResend(
|
|
SignupResendRequest(email: state.pendingEmail!),
|
|
);
|
|
emit(state.copyWith(codeSent: true));
|
|
} catch (e) {
|
|
final message = e is ApiException ? e.message : e.toString();
|
|
emit(state.copyWith(errorMessage: message));
|
|
}
|
|
}
|
|
|
|
Future<void> sendCodeSilently() async {
|
|
if (!state.isStep1Valid || state.isSending) return;
|
|
|
|
emit(state.copyWith(isSending: true));
|
|
|
|
try {
|
|
final response = await _repository.signupStart(
|
|
SignupStartRequest(
|
|
username: state.username.value,
|
|
email: state.email.value,
|
|
password: state.password.value,
|
|
),
|
|
);
|
|
emit(
|
|
state.copyWith(
|
|
isSending: false,
|
|
pendingEmail: response.email,
|
|
codeSent: true,
|
|
errorMessage: null,
|
|
),
|
|
);
|
|
} catch (e) {
|
|
final message = e is ApiException ? e.message : '验证码发送失败,请重试';
|
|
emit(state.copyWith(isSending: false, errorMessage: message));
|
|
}
|
|
}
|
|
}
|