19aa33a609
- Add CacheScope provider in UserProfileCacheRepository tests - Remove catch blocks that swallowed errors in _loadHistory/_loadMoreHistory - Errors now properly propagate to switchUser() caller
103 lines
2.8 KiB
Dart
103 lines
2.8 KiB
Dart
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import '../../../../core/logging/logger.dart';
|
|
import '../../data/repositories/auth_repository.dart';
|
|
import 'auth_event.dart';
|
|
import 'auth_state.dart';
|
|
|
|
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|
final AuthRepository _repository;
|
|
final Logger _logger = getLogger('features.auth.bloc');
|
|
|
|
AuthBloc(this._repository) : super(AuthInitial()) {
|
|
on<AuthStarted>(_onStarted);
|
|
on<AuthLoggedIn>(_onLoggedIn);
|
|
on<AuthLoggedOut>(_onLoggedOut);
|
|
on<AuthSessionInvalidated>(_onSessionInvalidated);
|
|
}
|
|
|
|
Future<void> _onStarted(AuthStarted event, Emitter<AuthState> emit) async {
|
|
emit(AuthLoading());
|
|
try {
|
|
final refreshToken = await _repository.getRefreshToken();
|
|
if (refreshToken != null) {
|
|
final response = await _repository.refreshSession(refreshToken);
|
|
emit(
|
|
AuthAuthenticated(
|
|
user: AuthUser(id: response.user.id, phone: response.user.phone),
|
|
),
|
|
);
|
|
return;
|
|
}
|
|
emit(
|
|
const AuthUnauthenticated(reason: AuthUnauthenticatedReason.signedOut),
|
|
);
|
|
} catch (e, stackTrace) {
|
|
_logger.error(
|
|
message: 'Session refresh failed',
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
try {
|
|
await _repository.clearSessionLocalOnly();
|
|
} catch (e, stackTrace) {
|
|
_logger.error(
|
|
message: 'Failed to clear local session',
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
} finally {
|
|
emit(
|
|
const AuthUnauthenticated(
|
|
reason: AuthUnauthenticatedReason.startupRecoveryFailed,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
void _onLoggedIn(AuthLoggedIn event, Emitter<AuthState> emit) {
|
|
_logger.info(message: 'User logged in', extra: {'user_id': event.user.id});
|
|
emit(AuthAuthenticated(user: event.user));
|
|
}
|
|
|
|
Future<void> _onLoggedOut(
|
|
AuthLoggedOut event,
|
|
Emitter<AuthState> emit,
|
|
) async {
|
|
try {
|
|
await _repository.deleteSession();
|
|
_logger.info(message: 'User logged out');
|
|
} catch (e, stackTrace) {
|
|
_logger.error(
|
|
message: 'Failed to delete session on logout',
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
} finally {
|
|
emit(
|
|
const AuthUnauthenticated(reason: AuthUnauthenticatedReason.signedOut),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSessionInvalidated(
|
|
AuthSessionInvalidated event,
|
|
Emitter<AuthState> emit,
|
|
) async {
|
|
_logger.warning(message: 'Session invalidated by server');
|
|
try {
|
|
await _repository.clearSessionLocalOnly();
|
|
} catch (e, stackTrace) {
|
|
_logger.error(
|
|
message: 'Failed to clear local session',
|
|
error: e,
|
|
stackTrace: stackTrace,
|
|
);
|
|
} finally {
|
|
emit(
|
|
const AuthUnauthenticated(reason: AuthUnauthenticatedReason.expired),
|
|
);
|
|
}
|
|
}
|
|
}
|