import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:syncrow_app/features/auth/model/login_with_email_model.dart'; import 'package:syncrow_app/features/auth/model/token.dart'; import 'package:syncrow_app/features/auth/model/user_model.dart'; import 'package:syncrow_app/navigation/navigation_service.dart'; import 'package:syncrow_app/navigation/routing_constants.dart'; import 'package:syncrow_app/services/api/authentication_api.dart'; part 'auth_state.dart'; class AuthCubit extends Cubit { AuthCubit() : super(AuthInitial()) { getTokenAndValidate(); } static AuthCubit get(context) => BlocProvider.of(context); final TextEditingController emailController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); final loginFormKey = GlobalKey(); bool isPasswordVisible = false; static GlobalKey formKey = GlobalKey(); void changePasswordVisibility() { isPasswordVisible = !isPasswordVisible; emit(AuthPasswordVisibilityChanged()); } bool agreeToTerms = false; void changeAgreeToTerms() { agreeToTerms = !agreeToTerms; emit(AuthAgreeToTermsChanged()); } static UserModel? user; static Token token = Token.emptyConstructor(); /////////////////////////////////////VALIDATORS///////////////////////////////////// String? passwordValidator(String? value) { if (value != null) { if (value.isNotEmpty) { if (value.length >= 6) { return null; //TODO uncomment this code when the password validation is needed // if (RegExp( // r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$') // .hasMatch(value)) { // return null; // } else { // return 'Password must contain at least one uppercase letter, one lowercase letter, one number and one special character'; // } } else { return 'Password must be at least 6 characters'; } } else { return 'Please enter your password'; } } return null; } String? emailAddressValidator(String? value) { if (value != null && value.isNotEmpty && value != "") { if (checkValidityOfEmail(value)) { if (loginFormKey.currentState != null) { loginFormKey.currentState!.save(); } return null; } else { return 'Please enter a valid email'; } } else { return 'Email address is required'; } } bool checkValidityOfEmail(String? email) { if (email != null) { return RegExp( r"^[a-zA-Z0-9]+([.!#$%&'*+/=?^_`{|}~-]?[a-zA-Z0-9]+)*@[a-zA-Z0-9]+([.-]?[a-zA-Z0-9]+)*\.[a-zA-Z0-9]{2,}$") .hasMatch(email); } else { return false; } } /////////////////////////////////////API CALLS///////////////////////////////////// login() async { emit(AuthLoginLoading()); try { token = await AuthenticationAPI.loginWithEmail( model: LoginWithEmailModel( email: emailController.text.toLowerCase(), password: passwordController.text, ), ); } catch (failure) { emit(AuthLoginError(message: failure.toString())); return; } if (token.accessTokenIsNotEmpty) { FlutterSecureStorage storage = const FlutterSecureStorage(); await storage.write( key: Token.loginAccessTokenKey, value: token.accessToken); const FlutterSecureStorage().write( key: UserModel.userUuidKey, value: Token.decodeToken(token.accessToken)['uuid'].toString()); user = UserModel.fromToken(token); emailController.clear(); passwordController.clear(); emit(AuthLoginSuccess()); } else { emit(AuthLoginError(message: 'Something went wrong')); } } logout() async { emit(AuthLogoutLoading()); try { FlutterSecureStorage storage = const FlutterSecureStorage(); await storage.delete(key: Token.loginAccessTokenKey); NavigationService.navigatorKey.currentState! .popAndPushNamed(Routes.authLogin); emit(AuthLogoutSuccess()); } catch (failure) { emit(AuthLogoutError(message: failure.toString())); return; } } getTokenAndValidate() async { emit(AuthTokenLoading()); final value = await const FlutterSecureStorage().read(key: Token.loginAccessTokenKey); if (value == null) { emit(AuthTokenError(message: "Token not found")); return; } final tokenData = Token.decodeToken(value); if (tokenData.containsKey('exp')) { final exp = tokenData['exp'] ?? 0; final currentTime = DateTime.now().millisecondsSinceEpoch ~/ 1000; if (currentTime < exp) { emit(AuthTokenSuccess()); } else { emit(AuthTokenError(message: "Token expired")); } } else { emit(AuthTokenError(message: "Something went wrong")); } } }