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 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); } }