67 lines
2.2 KiB
Dart
67 lines
2.2 KiB
Dart
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:shuffle/features/auth/domain/auth_failure.dart';
|
|
import 'package:shuffle/features/auth/domain/resend_origin.dart';
|
|
import 'package:shuffle/features/auth/domain/validation/email_format.dart';
|
|
import 'package:shuffle/features/auth/presentation/providers/auth_providers.dart';
|
|
|
|
part 'resend_controller.freezed.dart';
|
|
part 'resend_controller.g.dart';
|
|
|
|
@freezed
|
|
abstract class ResendState with _$ResendState {
|
|
const factory ResendState({
|
|
@Default(false) bool isSending,
|
|
|
|
/// The last request counts as sent (also for `emailSendLimited` and server
|
|
/// failures from the check-email screen, F12/F13).
|
|
@Default(false) bool sent,
|
|
AuthFailure? failure,
|
|
|
|
/// Only for an address typed in by the user.
|
|
EmailError? emailError,
|
|
}) = _ResendState;
|
|
}
|
|
|
|
/// "Resend email" for the confirmation (KTO-01 Kriterium 6, F12).
|
|
///
|
|
/// The caller states where the request comes from: only there the controller
|
|
/// decides (`resendFailureFor`): `emailSendLimited` is shown at login and
|
|
/// treated as success on the check-email screen; `unexpected` (e.g. SMTP
|
|
/// outage) is shown at login (account proven) and neutral on check-email.
|
|
@riverpod
|
|
class ResendController extends _$ResendController {
|
|
@override
|
|
ResendState build() => const ResendState();
|
|
|
|
void clearEmailError() {
|
|
if (state.emailError != null) {
|
|
state = state.copyWith(emailError: null);
|
|
}
|
|
}
|
|
|
|
Future<void> resend(String email, {required ResendOrigin origin}) async {
|
|
if (state.isSending) {
|
|
return;
|
|
}
|
|
final normalized = EmailFormat.normalize(email);
|
|
final emailError = EmailFormat.validate(normalized);
|
|
if (emailError != null) {
|
|
state = ResendState(emailError: emailError);
|
|
return;
|
|
}
|
|
|
|
state = const ResendState(isSending: true);
|
|
final result = await ref
|
|
.read(authRepositoryProvider)
|
|
.resendConfirmation(normalized);
|
|
if (!ref.mounted) {
|
|
return;
|
|
}
|
|
final raw = result.errorOrNull;
|
|
final failure = raw == null ? null : resendFailureFor(raw, origin);
|
|
state = failure == null
|
|
? const ResendState(sent: true)
|
|
: ResendState(failure: failure);
|
|
}
|
|
}
|