feat: legacy mobile apps created

This commit is contained in:
Achintha Isuru
2025-12-02 23:51:04 -05:00
parent 850441ca64
commit 8e7753b324
1519 changed files with 0 additions and 16 deletions

View File

@@ -0,0 +1,219 @@
import 'dart:async';
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow/core/application/common/validators/phone_validator.dart';
import 'package:krow/core/application/di/injectable.dart';
import 'package:krow/core/sevices/auth_state_service/auth_service.dart';
part 'auth_event.dart';
part 'auth_state.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final FirebaseAuth _auth = FirebaseAuth.instance;
String? phone;
int? resendToken;
String? verificationId;
AuthBloc() : super(AuthState()) {
on<AuthTypeChangedEvent>(_onTypeChanged);
on<AuthSendSmsEvent>(_onSendSms);
on<AuthSendSmsToPhoneEvent>(_onSendSmsToCurrentPhone);
on<AuthPhoneChangedEvent>(_onPhoneChanged);
on<PhoneVerificationCompletedEvent>(_onPhoneVerificationCompleted);
on<PhoneVerificationFailedEvent>(_onPhoneVerificationFailed);
on<CodeSentEvent>(_onCodeSent);
on<CodeAutoRetrievalTimeoutEvent>(_onCodeAutoRetrievalTimeout);
on<AuthEventResendUpdateTimer>(_onUpdateTimer);
on<AuthEventConfirmCode>(_onConfirmCode);
on<SignInWithInitialLink>(_onSignInWithInitialLink);
}
FutureOr<void> _onTypeChanged(
AuthTypeChangedEvent event,
Emitter<AuthState> emit,
) {
emit(state.copyWith(authType: event.authType));
}
FutureOr<void> _onPhoneChanged(
AuthPhoneChangedEvent event,
Emitter<AuthState> emit,
) {
emit(state.copyWith(phoneError: null));
}
Future<void> _handleSendingSmsToPhoneNumber(
String? phone,
Emitter<AuthState> emit,
) async {
if (state.resendTimeout > 0) return;
if (phone != null) {
var phoneValidationResult = PhoneValidator.validate(phone);
if (phoneValidationResult != null) {
return emit(state.copyWith(phoneError: phoneValidationResult));
}
resendToken = null;
verificationId = null;
this.phone = phone;
}
emit(state.copyWith(isLoading: true));
try {
await _auth.verifyPhoneNumber(
forceResendingToken: resendToken,
phoneNumber: phone,
verificationCompleted: (PhoneAuthCredential credential) {
add(PhoneVerificationCompletedEvent(credential));
},
verificationFailed: (FirebaseAuthException e) {
add(PhoneVerificationFailedEvent(e.message));
},
codeSent: (String verificationId, int? resendToken) {
this.verificationId = verificationId;
this.resendToken = resendToken;
add(CodeSentEvent(verificationId, resendToken));
},
codeAutoRetrievalTimeout: (String verificationId) {
if (isClosed) return;
add(CodeAutoRetrievalTimeoutEvent(verificationId));
},
);
} catch (e) {
emit(
state.copyWith(
isLoading: false,
phoneError: 'Invalid phone number'.tr(),
),
);
}
}
Future<void> _onSendSms(
AuthSendSmsEvent event,
Emitter<AuthState> emit,
) async {
return _handleSendingSmsToPhoneNumber(event.phone, emit);
}
FutureOr<void> _onSendSmsToCurrentPhone(
AuthSendSmsToPhoneEvent event,
Emitter<AuthState> emit,
) async {
return _handleSendingSmsToPhoneNumber(
phone = event.userPhone,
emit,
);
}
Future<void> _onConfirmCode(
AuthEventConfirmCode event,
Emitter<AuthState> emit,
) async {
emit(state.copyWith(isLoading: true));
PhoneAuthCredential credential = PhoneAuthProvider.credential(
verificationId: verificationId ?? '',
smsCode: event.smsCode,
);
add(PhoneVerificationCompletedEvent(credential));
}
FutureOr<void> _onUpdateTimer(
AuthEventResendUpdateTimer event,
Emitter<AuthState> emit,
) {
emit(state.copyWith(
resendTimeout: event.seconds, codeError: state.codeError));
}
FutureOr<void> _onPhoneVerificationCompleted(
PhoneVerificationCompletedEvent event,
Emitter<AuthState> emit,
) async {
try {
await _auth.signInWithCredential(event.credential);
emit(state.copyWith(
isLoading: false,
autentificated: true,
));
} catch (e) {
emit(state.copyWith(
isLoading: false,
codeError: 'Invalid code'.tr(),
));
}
}
FutureOr<void> _onPhoneVerificationFailed(
PhoneVerificationFailedEvent event,
Emitter<AuthState> emit,
) {
emit(state.copyWith(
isLoading: false,
phoneError: event.error,
));
}
FutureOr<void> _onCodeSent(
CodeSentEvent event,
Emitter<AuthState> emit,
) {
emit(
state.copyWith(
needNavigateToCodeVerification: true,
resendTimeout: 30,
),
);
_startRetryTimer();
}
FutureOr<void> _onCodeAutoRetrievalTimeout(
CodeAutoRetrievalTimeoutEvent event,
Emitter<AuthState> emit,
) {}
void _startRetryTimer() {
var current = 30;
Timer.periodic(const Duration(seconds: 1), (timer) {
if (current <= 0) {
timer.cancel();
} else {
current--;
if (isClosed) {
timer.cancel();
return;
}
add(AuthEventResendUpdateTimer(current));
}
});
}
FutureOr<void> _onSignInWithInitialLink(
SignInWithInitialLink event,
Emitter<AuthState> emit,
) async {
try {
await getIt<AuthService>().signInWithEmailLink(link: event.initialLink);
emit(
state.copyWith(
isLoading: false,
autentificated: true,
),
);
} catch (except) {
log('Failed to authenticate with Initial Link', error: except);
}
}
}

View File

@@ -0,0 +1,71 @@
part of 'auth_bloc.dart';
@immutable
sealed class AuthEvent {
const AuthEvent();
}
class AuthTypeChangedEvent extends AuthEvent {
final AuthType authType;
const AuthTypeChangedEvent(this.authType);
}
class AuthPhoneChangedEvent extends AuthEvent {
const AuthPhoneChangedEvent();
}
class AuthSendSmsEvent extends AuthEvent {
final String? phone;
const AuthSendSmsEvent(this.phone);
}
class AuthSendSmsToPhoneEvent extends AuthEvent {
const AuthSendSmsToPhoneEvent(this.userPhone);
final String userPhone;
}
class PhoneVerificationCompletedEvent extends AuthEvent {
final PhoneAuthCredential credential;
const PhoneVerificationCompletedEvent(this.credential);
}
class PhoneVerificationFailedEvent extends AuthEvent {
final String? error;
const PhoneVerificationFailedEvent(this.error);
}
class CodeSentEvent extends AuthEvent {
final String verificationId;
final int? resendToken;
const CodeSentEvent(this.verificationId, this.resendToken);
}
class CodeAutoRetrievalTimeoutEvent extends AuthEvent {
final String verificationId;
const CodeAutoRetrievalTimeoutEvent(this.verificationId);
}
class AuthEventResendUpdateTimer extends AuthEvent {
final int seconds;
const AuthEventResendUpdateTimer(this.seconds);
}
class AuthEventConfirmCode extends AuthEvent {
final String smsCode;
const AuthEventConfirmCode(this.smsCode);
}
class SignInWithInitialLink extends AuthEvent {
const SignInWithInitialLink({required this.initialLink});
final Uri initialLink;
}

View File

@@ -0,0 +1,47 @@
part of 'auth_bloc.dart';
enum AuthType { login, register }
class AuthState {
final AuthType? authType;
final String? phoneError;
String? codeError;
final bool needClearPhone;
final bool needNavigateToCodeVerification;
final bool isLoading;
final bool autentificated;
final int resendTimeout;
AuthState({
this.phoneError,
this.codeError,
this.needClearPhone = false,
this.needNavigateToCodeVerification = false,
this.isLoading = false,
this.authType,
this.autentificated = false,
this.resendTimeout = 0,
});
AuthState copyWith({
AuthType? authType,
String? phoneError,
String? codeError,
bool? needClearPhone,
bool? needNavigateToCodeVerification,
bool? isLoading,
bool? autentificated,
int? resendTimeout,
}) {
return AuthState(
authType: authType ?? this.authType,
phoneError: phoneError,
codeError: codeError,
needClearPhone: needClearPhone ?? false,
needNavigateToCodeVerification: needNavigateToCodeVerification ?? false,
isLoading: isLoading ?? false,
autentificated: autentificated ?? false,
resendTimeout: resendTimeout ?? this.resendTimeout,
);
}
}