Skip to content

Commit ead6401

Browse files
committed
feat(authentication): implement cooldown for sign-in code requests
- Add cooldown functionality to prevent frequent code requests - Introduce new AuthenticationStatus.state: requestCodeCooldown - Implement timer to transition out of cooldown after 60 seconds - Update UI feedback during cooldown period
1 parent 098c5a2 commit ead6401

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

lib/authentication/bloc/authentication_bloc.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import 'package:equatable/equatable.dart';
2020
part 'authentication_event.dart';
2121
part 'authentication_state.dart';
2222

23+
const _requestCodeCooldownDuration = Duration(seconds: 60);
24+
2325
/// {@template authentication_bloc}
2426
/// Bloc responsible for managing the authentication state of the application.
2527
/// {@endtemplate}
@@ -40,6 +42,7 @@ class AuthenticationBloc
4042
);
4143
on<AuthenticationVerifyCodeRequested>(_onAuthenticationVerifyCodeRequested);
4244
on<AuthenticationSignOutRequested>(_onAuthenticationSignOutRequested);
45+
on<AuthenticationCooldownCompleted>(_onAuthenticationCooldownCompleted);
4346
}
4447

4548
final AuthRepository _authenticationRepository;
@@ -72,18 +75,32 @@ class AuthenticationBloc
7275
AuthenticationRequestSignInCodeRequested event,
7376
Emitter<AuthenticationState> emit,
7477
) async {
78+
// Prevent request if already in cooldown
79+
if (state.status == AuthenticationStatus.requestCodeCooldown) return;
80+
7581
emit(state.copyWith(status: AuthenticationStatus.requestCodeLoading));
7682
try {
7783
await _authenticationRepository.requestSignInCode(
7884
event.email,
7985
isDashboardLogin: true,
8086
);
87+
final cooldownEndTime = DateTime.now().add(_requestCodeCooldownDuration);
8188
emit(
8289
state.copyWith(
8390
status: AuthenticationStatus.codeSentSuccess,
8491
email: event.email,
92+
cooldownEndTime: cooldownEndTime,
8593
),
8694
);
95+
// Transition to cooldown state after a brief moment
96+
await Future<void>.delayed(const Duration(milliseconds: 100));
97+
emit(state.copyWith(status: AuthenticationStatus.requestCodeCooldown));
98+
99+
// Start a timer to transition out of cooldown
100+
Timer(
101+
_requestCodeCooldownDuration,
102+
() => add(const AuthenticationCooldownCompleted()),
103+
);
87104
} on InvalidInputException catch (e) {
88105
emit(state.copyWith(status: AuthenticationStatus.failure, exception: e));
89106
} on UnauthorizedException catch (e) {
@@ -181,6 +198,15 @@ class AuthenticationBloc
181198
}
182199
}
183200

201+
void _onAuthenticationCooldownCompleted(
202+
AuthenticationCooldownCompleted event,
203+
Emitter<AuthenticationState> emit,
204+
) {
205+
if (state.status == AuthenticationStatus.requestCodeCooldown) {
206+
emit(state.copyWith(status: AuthenticationStatus.initial));
207+
}
208+
}
209+
184210
@override
185211
Future<void> close() {
186212
_userAuthSubscription.cancel();

0 commit comments

Comments
 (0)