feat(socail): finished registration and ligin via social media

This commit is contained in:
misha
2025-10-15 14:21:43 +03:00
parent 9281213ea1
commit e073bd3f97
12 changed files with 187 additions and 201 deletions

View File

@@ -25,19 +25,4 @@ class AuthCubit extends Cubit<AuthState> {
return false;
}
}
Future<bool> getTokenBySocial({required String provider, required String accessToken}) async {
emit(const AuthState.loading());
try {
final token = (await authRepository.getTokenBySocial(provider: provider, accessToken: accessToken)).token;
emit(AuthState.loaded(token: token));
await TokenStorage.saveTokenInStorage(token);
return true;
} catch (e) {
log(e.toString());
showErrorToast('Не удалось войти через $provider');
emit(AuthState.error(errorMessage: '$e'));
return false;
}
}
}

View File

@@ -1,4 +1,5 @@
import 'dart:developer';
import 'package:eatvio_app/core/token_storage.dart';
import 'package:eatvio_app/features/auth/presentation/bloc/oauth_cubit/oauth_state.dart';
import 'package:eatvio_app/features/auth/repositories/auth_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -8,24 +9,27 @@ class OAuthCubit extends Cubit<OAuthState> {
OAuthCubit({required this.authRepository}) : super(const OAuthState());
Future<void> getOAuthLogin({required String provider, required String accessToken, required String refreshToken}) async {
Future<void> signInViaSocialMedia({required String provider, required String accessToken, required String refreshToken, required String clientId}) async {
try {
log('OAuthCubit: Starting OAuth login for provider: $provider');
emit(const OAuthState.loading());
log('OAuthCubit: Emitted loading state');
final tokenModel = await authRepository.getOAuthLogin(provider: provider, accessToken: accessToken, refreshToken: refreshToken);
final tokenModel = await authRepository.signInViaSocialMedia(
provider: provider,
accessToken: accessToken,
refreshToken: refreshToken,
clientId: clientId,
);
log('OAuthCubit: Got token model: ${tokenModel.token}');
TokenStorage.saveTokenInStorage(tokenModel.token);
emit(OAuthState.loaded(token: tokenModel.token));
log('OAuthCubit: Emitted loaded state');
} catch (e) {
log('OAuthCubit: Error occurred: $e');
emit(OAuthState.error(errorMessage: e.toString()));
log('OAuthCubit: Emitted error state');
}
}
Future<void> getOAuthToken({
Future<void> signUpViaSocialMedia({
required String provider,
required String accessToken,
required String id,
@@ -38,10 +42,11 @@ class OAuthCubit extends Cubit<OAuthState> {
required String gender,
required int weight,
required int height,
required String clientId,
}) async {
try {
emit(const OAuthState.loading());
final token = await authRepository.getOAuthToken(
final token = await authRepository.signUpViaSocialMedia(
provider: provider,
accessToken: accessToken,
id: id,
@@ -54,7 +59,9 @@ class OAuthCubit extends Cubit<OAuthState> {
gender: gender,
weight: weight,
height: height,
clientId: clientId,
);
TokenStorage.saveTokenInStorage(token);
emit(OAuthState.loaded(token: token));
} catch (e) {
emit(OAuthState.error(errorMessage: e.toString()));

View File

@@ -1,5 +1,3 @@
// ignore_for_file: unused_element, duplicate_ignore
import 'dart:async';
import 'dart:developer';
import 'package:eatvio_app/app_keys.dart';
@@ -95,6 +93,138 @@ class _AuthScreenState extends State<AuthScreen> {
AppRouter.navigatorKey.currentContext?.go('/feed-screen', extra: {'needToInitializeWebSocket': false});
}
void _onVkPressed() async {
try {
log('VK button pressed');
final context = AppRouter.navigatorKey.currentContext;
if (context == null) {
log('Context is null');
return;
}
log('Getting VK auth result');
final authResult = await SocialAuthFacade.signInWithVkAndFetchProfile(context: context);
if (authResult == null) {
log('VK auth result is null');
return;
}
log('VK auth result received, trying OAuth login');
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'vk');
} else {
log('Context is not mounted');
}
} catch (e) {
log('VK button error: $e');
}
}
void _onOkPressed() async {
try {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
final authResult = await SocialAuthFacade.signInWithOkAndFetchProfile();
if (authResult == null) {
return;
}
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'vk');
}
} catch (e) {
log(e.toString());
}
}
void _onMailRuPressed() async {
try {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
final authResult = await SocialAuthFacade.signInWithMailRuAndFetchProfile();
if (authResult == null) {
return;
}
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'vk');
}
} catch (e) {
log(e.toString());
}
}
void _onYandexPressed() async {
try {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
final authResult = await SocialAuthFacade.signInWithYandex();
if (authResult == null) return;
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'yandex');
}
} catch (e) {
log(e.toString());
}
}
Future<void> _tryOAuthLogin(BuildContext context, AuthResultEntity authResult, String provider) async {
log('Starting OAuth login for provider: $provider');
try {
final oauthCubit = CubitRegistrations.sl<OAuthCubit>();
StreamSubscription? subscription;
subscription = oauthCubit.stream.listen((state) {
log('OAuth state changed: ${state.runtimeType}');
if (state is OAuthStateLoaded) {
log('OAuth login successful, navigating to main screen');
subscription?.cancel();
_reconnectAfterAuth();
} else if (state is OAuthStateError) {
log('OAuth login failed: ${state.errorMessage}');
subscription?.cancel();
AppRouter.navigateToRegisterViaSocial(authResult: authResult, provider: provider);
}
});
log('Calling getOAuthLogin with provider: $provider');
await oauthCubit.signInViaSocialMedia(
provider: provider,
accessToken: authResult.accessToken,
refreshToken: authResult.refreshToken ?? '',
clientId: authResult.clientId,
);
} catch (e) {
log('OAuth login error in catch block: $e');
AppRouter.navigateToRegisterViaSocial(authResult: authResult, provider: provider);
}
}
Future<void> _reconnectAfterAuth() async {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
try {
await sl<WsManager>().clear();
await sl<WsManager>().initialize();
await sl<ProfileAvatarCubit>().getMyProfile();
await sl<ChatsCubit>().getChatRoomsWithLoading();
await sl<ChatsCubit>().connectToWebSocket();
await sl<NotificationsCubit>().getNotifications();
await sl<NotificationsCubit>().connectToWebSocket();
await sl<FirebaseApi>().registerPushToken();
showSuccessToast('Успешный вход');
} catch (e) {
log(e.toString());
}
AppRouter.navigatorKey.currentContext?.go('/feed-screen', extra: {'needToInitializeWebSocket': false});
}
@override
Widget build(BuildContext context) {
var shortestSide = MediaQuery.sizeOf(context).shortestSide;
@@ -129,7 +259,6 @@ class _AuthScreenState extends State<AuthScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Social auth buttons at the top (outlined)
const Center(child: Text('Авторизация через')),
const SizedBox(height: 12),
Row(
@@ -405,143 +534,3 @@ class _SocialButton extends StatelessWidget {
);
}
}
void _onVkPressed() async {
try {
log('VK button pressed');
final context = AppRouter.navigatorKey.currentContext;
if (context == null) {
log('Context is null');
return;
}
log('Getting VK auth result');
final authResult = await SocialAuthFacade.signInWithVkAndFetchProfile(context: context);
if (authResult == null) {
log('VK auth result is null');
return;
}
log('VK auth result received, trying OAuth login');
// Пробуем сначала авторизоваться через новый API
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'vk');
} else {
log('Context is not mounted');
}
} catch (e) {
log('VK button error: $e');
}
}
void _onOkPressed() async {
try {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
final authResult = await SocialAuthFacade.signInWithOkAndFetchProfile();
if (authResult == null) {
return;
}
// Пробуем сначала авторизоваться через новый API
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'ok');
}
} catch (e) {
log(e.toString());
}
}
void _onMailRuPressed() async {
try {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
final authResult = await SocialAuthFacade.signInWithMailRuAndFetchProfile();
if (authResult == null) {
return;
}
// Пробуем сначала авторизоваться через новый API
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'mailru');
}
} catch (e) {
log(e.toString());
}
}
void _onYandexPressed() async {
try {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
final authResult = await SocialAuthFacade.signInWithYandex();
if (authResult == null) return;
// Пробуем сначала авторизоваться через новый API
if (context.mounted) {
await _tryOAuthLogin(context, authResult, 'yandex');
}
} catch (e) {
log(e.toString());
}
}
/// Пробует авторизоваться через новый OAuth login API
/// Если получает ошибку (включая 422 - пользователь не найден), переходит к регистрации
Future<void> _tryOAuthLogin(BuildContext context, AuthResultEntity authResult, String provider) async {
log('Starting OAuth login for provider: $provider');
try {
// Создаем OAuth cubit
final oauthCubit = CubitRegistrations.sl<OAuthCubit>();
StreamSubscription? subscription;
// Слушаем изменения состояния
subscription = oauthCubit.stream.listen((state) {
log('OAuth state changed: ${state.runtimeType}');
if (state is OAuthStateLoaded) {
// Успешная авторизация - переходим на главный экран
log('OAuth login successful, navigating to main screen');
subscription?.cancel();
_reconnectAfterAuth();
} else if (state is OAuthStateError) {
// Ошибка авторизации (включая 422 - пользователь не найден) - переходим к регистрации
log('OAuth login failed: ${state.errorMessage}');
subscription?.cancel();
AppRouter.navigateToRegisterViaSocial(authResult: authResult, provider: provider);
}
});
// Пробуем авторизоваться
log('Calling getOAuthLogin with provider: $provider');
await oauthCubit.getOAuthLogin(provider: provider, accessToken: authResult.accessToken, refreshToken: authResult.refreshToken ?? '');
// Ждем немного, чтобы состояние успело обновиться
await Future.delayed(const Duration(milliseconds: 100));
} catch (e) {
// В случае любой ошибки (включая 422 - пользователь не найден) переходим к регистрации
log('OAuth login error in catch block: $e');
AppRouter.navigateToRegisterViaSocial(authResult: authResult, provider: provider);
}
}
Future<void> _reconnectAfterAuth() async {
final context = AppRouter.navigatorKey.currentContext;
if (context == null) return;
try {
await sl<WsManager>().clear();
await sl<WsManager>().initialize();
await sl<ProfileAvatarCubit>().getMyProfile();
await sl<ChatsCubit>().getChatRoomsWithLoading();
await sl<ChatsCubit>().connectToWebSocket();
await sl<NotificationsCubit>().getNotifications();
await sl<NotificationsCubit>().connectToWebSocket();
await sl<FirebaseApi>().registerPushToken();
showSuccessToast('Успешный вход');
} catch (_) {}
AppRouter.navigatorKey.currentContext?.go('/feed-screen', extra: {'needToInitializeWebSocket': false});
}

View File

@@ -439,6 +439,7 @@ class _RegisterViaSocialScreenState extends State<RegisterViaSocialScreen> {
}
void _handleRegistration(BuildContext context) {
final clientID = widget.authResult?.clientId;
// Валидация полей
if (firstNameController.text.isEmpty ||
lastNameController.text.isEmpty ||
@@ -465,8 +466,9 @@ class _RegisterViaSocialScreenState extends State<RegisterViaSocialScreen> {
// Очищаем номер телефона от маски для отправки
final cleanPhone = phoneController.text.replaceAll(RegExp(r'[^\d+]'), '');
if (clientID == null) return;
// Вызываем OAuth регистрацию
context.read<OAuthCubit>().getOAuthToken(
context.read<OAuthCubit>().signUpViaSocialMedia(
provider: widget.provider ?? 'social',
accessToken: widget.authResult?.accessToken ?? 'dummy_token',
id: widget.authResult?.userId ?? 'dummy_id',
@@ -479,6 +481,7 @@ class _RegisterViaSocialScreenState extends State<RegisterViaSocialScreen> {
gender: isMaleSelected ? 'М' : 'Ж',
weight: weight,
height: height,
clientId: clientID,
);
}
}