Files
Lizandro GuarnizoandClaude Sonnet 4.6 2c5b237890 feat: SMS OTP phone auth + mandatory phone verification gate
- MyUser: add isPhoneVerified field (from is_phone_verified in API)
- ApiUserRepository: signInWithPhoneNumber calls POST /auth/send-otp,
  verifyOTP calls POST /auth/phone, linkWithOTP calls POST /auth/verify-phone
  Added updateFcmToken and changePassword methods
- AuthBloc: remove Firebase PhoneVerificationService, use repository OTP flow
- app_view.dart: gate authenticated users without verified phone to
  PhoneVerifyRequiredScreen before showing HomeScreen
- welcome_screen.dart: full redesign with gradient header, logo, integrated
  OTP flow (phone → code in same screen), 60s resend timer
- PhoneVerifyRequiredScreen: new screen for users who need to verify phone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 15:53:43 -05:00

46 lines
1.5 KiB
Dart

import 'dart:async';
import 'package:flutter_bloc/flutter_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<AuthenticationEvent, AuthenticationState> {
final UserRepository userRepository;
late final StreamSubscription<MyUser?> _userSubscription;
AuthenticationBloc({required UserRepository myUserRepository})
: userRepository = myUserRepository,
super(const AuthenticationState.unknown()) {
_userSubscription = userRepository.streamUser().listen((authUser) {
add(AuthenticationUserChanged(authUser));
});
on<AuthenticationUserChanged>(_onAuthenticationUserChanged);
on<AuthenticationLogoutRequested>(_onAuthenticationLogoutRequested);
userRepository.isAuthenticated().listen((_) {});
}
void _onAuthenticationUserChanged(
AuthenticationUserChanged event, Emitter<AuthenticationState> emit) {
emit(
event.user != null
? AuthenticationState.authenticated(event.user!)
: const AuthenticationState.unauthenticated(),
);
}
void _onAuthenticationLogoutRequested(AuthenticationLogoutRequested event, Emitter<AuthenticationState> emit) async {
await userRepository.logOut();
emit(const AuthenticationState.unauthenticated());
}
@override
Future<void> close() {
_userSubscription.cancel();
return super.close();
}
}