import 'dart:async'; import 'package:authentication_repository/authentication_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:meta/meta.dart'; import 'package:user_repository/user_repository.dart'; part 'authentication_event.dart'; part 'authentication_state.dart'; class AuthenticationBloc extends Bloc { AuthenticationBloc({ @required AuthenticationRepository authenticationRepository, @required UserRepository userRepository, }) : assert(authenticationRepository != null), assert(userRepository != null), _authenticationRepository = authenticationRepository, _userRepository = userRepository, super(const AuthenticationState.unknown()) { _authenticationStatusSubscription = _authenticationRepository.status.listen( (status) => add(AuthenticationStatusChanged(status)), ); } final AuthenticationRepository _authenticationRepository; final UserRepository _userRepository; StreamSubscription _authenticationStatusSubscription; @override Stream mapEventToState( AuthenticationEvent event, ) async* { if (event is AuthenticationStatusChanged) { yield await _mapAuthenticationStatusChangedToState(event); } else if (event is AuthenticationLogoutRequested) { _authenticationRepository.logOut(); } } @override Future close() { _authenticationStatusSubscription?.cancel(); _authenticationRepository.dispose(); return super.close(); } Future _mapAuthenticationStatusChangedToState( AuthenticationStatusChanged event, ) async { switch (event.status) { case AuthenticationStatus.unauthenticated: return const AuthenticationState.unauthenticated(); case AuthenticationStatus.authenticated: final user = await _tryGetUser(); return user != null ? AuthenticationState.authenticated(user) : const AuthenticationState.unauthenticated(); default: return const AuthenticationState.unknown(); } } Future _tryGetUser() async { try { final user = await _userRepository.getUser(); return user; } on Exception { return null; } } }