Files
prosappco/lib/blocs/auth_bloc/auth_bloc.dart
T

235 lines
7.9 KiB
Dart

import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:user_repository/user_repository.dart';
part 'auth_event.dart';
part 'auth_state.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final UserRepository _userRepository;
final PhoneVerificationService phoneVerificationService =
PhoneVerificationService();
String? _verificationId;
AuthBloc({required UserRepository userRepository})
: _userRepository = userRepository,
super(AuthStateInitial()) {
on<AuthEventLoginOAuth>(_onAuthEventLoginOAuth);
on<AuthEventVerifyOAuth>(_onAuthEventVerifyOAuth);
on<AuthEventAddEmailAndPassword>(_onAuthEventAddEmailAndPassword);
on<AuthEventUpdatePassword>(_updatePassword);
on<LinkWithPhoneNumber>(_linkWithPhoneNumber);
on<LinkWithPhoneNumberOtp>(_linkWithPhoneNumberOtp);
}
void _onAuthEventLoginOAuth(
AuthEventLoginOAuth event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
await _userRepository.signInWithPhoneNumber(event.phone);
emit(const AuthStateVerifyOAuth(false));
} catch (e) {
emit(const AuthStateFailure());
}
}
void _onAuthEventVerifyOAuth(
AuthEventVerifyOAuth event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
final bool isVerified = await _userRepository.verifyOTP(event.code);
if (isVerified) {
emit(AuthStateSuccess());
} else {
emit(const AuthStateVerifyOAuth(true));
}
} catch (e) {
emit(const AuthStateFailure());
}
}
void _onAuthEventAddEmailAndPassword(
AuthEventAddEmailAndPassword event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
final String? error = await _userRepository.addEmailAndPassword(
event.email, event.password);
if (error == null) {
emit(AuthStateSuccess());
} else {
if (error == 'requires-recent-login') {
emit(AuthStateRequiresRecentLogin());
} else if (error == 'email-already-in-use') {
emit(AuthStateEmailAlreadyInUse());
} else {
emit(const AuthStateFailure());
}
}
} catch (e) {
emit(const AuthStateFailure());
}
}
void _updatePassword(
AuthEventUpdatePassword event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
final error = await _userRepository.updatePassword(
event.actualPassword, event.password);
if (error == null) {
emit(AuthStateSuccess());
} else {
switch (error) {
case UpdatePassworErros.credentialsWrong:
emit(const AuthStateFailure(message: "Contraseña incorrecta"));
break;
case UpdatePassworErros.userNotFound:
emit(const AuthStateFailure(message: "Usuario no encontrado"));
break;
case UpdatePassworErros.unknown:
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
break;
}
}
} catch (e) {
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
}
}
void _linkWithPhoneNumber(
LinkWithPhoneNumber event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
await for (PhoneAuthEvent event
in phoneVerificationService.verifyPhoneNumber(event.phoneNumber)) {
switch (event.type) {
case PhoneAuthEventType.verificationCompleted:
AuthCredential credential = event.data;
print('Verificación completada. Credencial: $credential');
break;
case PhoneAuthEventType.verificationFailed:
FirebaseAuthException exception = event.data;
print('Verificación fallida. Excepción: $exception');
emit(AuthStateFailure(message: "Error inesperado. 🥸 $exception"));
return; // Detener la ejecución aquí
case PhoneAuthEventType.codeAutoRetrievalTimeout:
String verificationId = event.data;
print(
'Tiempo de espera agotado para recuperar el código. ID: $verificationId');
emit(const AuthStateFailure(
message: "Tiempo de espera agotado. 🥸",
));
break;
case PhoneAuthEventType.codeSent:
Map<String, dynamic> eventData = event.data;
String verificationId = eventData['verificationId'];
int? resendToken = eventData['resendToken'];
print(
'Código enviado. ID: $verificationId, resendToken: $resendToken');
_verificationId = verificationId;
emit(const AuthStateVerifyOAuth(false));
break;
}
}
} catch (e) {
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
}
}
void _linkWithPhoneNumber3(
LinkWithPhoneNumber event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
StreamSubscription<PhoneAuthEvent> subscription = phoneVerificationService
.verifyPhoneNumber(event.phoneNumber)
.listen((event) async {
switch (event.type) {
case PhoneAuthEventType.verificationCompleted:
AuthCredential credential = event.data;
print('Verificación completada. Credencial: $credential');
break;
case PhoneAuthEventType.verificationFailed:
FirebaseAuthException exception = event.data;
print('Verificación fallida. Excepción: $exception');
break;
case PhoneAuthEventType.codeAutoRetrievalTimeout:
String verificationId = event.data;
print(
'Tiempo de espera agotado para recuperar el código. ID: $verificationId');
break;
case PhoneAuthEventType.codeSent:
Map<String, dynamic> eventData = event.data;
String verificationId = eventData['verificationId'];
int? resendToken = eventData['resendToken'];
print(
'Código enviado. ID: $verificationId, resendToken: $resendToken');
_verificationId = verificationId;
emit(const AuthStateVerifyOAuth(false));
break;
}
if (event.type == PhoneAuthEventType.verificationFailed) {
// Detener la suscripción si la verificación falla
// subscription.cancel();
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
}
});
// await _userRepository
} catch (e) {
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
}
}
void _linkWithPhoneNumberOtp(
LinkWithPhoneNumberOtp event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
final bool isVerified = await _userRepository.linkWithOTP(
event.phoneNumber, _verificationId!, event.code);
if (isVerified) {
emit(AuthStateSuccess());
} else {
emit(const AuthStateVerifyOAuth(true));
}
} catch (e) {
if (e is FirebaseAuthException) {
switch (e.code) {
case "invalid-verification-code":
emit(const AuthStateFailure(
message: "Código de verificación incorrecto. 🥸",
));
break;
case "provider-already-linked":
emit(const AuthStateFailure(
message: "Cuenta ya vinculada. 🥸",
));
break;
case "credential-already-in-use":
emit(const AuthStateFailure(
message:
"Este numero ya se encuentra registrado con otra cuenta. 🥸",
));
break;
default:
emit(AuthStateFailure(message: "Error inesperado. 🥸 $e"));
break;
}
} else {
emit(AuthStateFailure(message: "Error inesperado. 🥸 $e"));
}
}
}
}