mnemo_cards/lib/managers/user_manager.dart
2024-06-16 22:01:33 +03:00

162 lines
4.8 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:auto_route/auto_route.dart';
import 'package:dio/dio.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:mnemo_cards/di/locator.dart';
import 'package:mnemo_cards/main.dart';
import 'package:mnemo_cards/managers/repository/http_repository.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:rxdart/rxdart.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:device_info_plus/device_info_plus.dart';
import '../domain/router/app_router.dart';
import '../domain/router/app_router.gr.dart';
import '../features/analytics/analytics.dart';
import 'user_state_holder.dart';
class UserManager {
CompositeSubscription? _subscription;
final HttpRepository _repository;
GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
// 'https://www.googleapis.com/auth/contacts.readonly',
],
// clientId: '01767851968-dvbvmte4m90dkqitp013s4nd5c0df1n8.apps.googleusercontent.com',
// "701767851968-bud97rud1d9qtqju96addn31nhm0oofu.apps.googleusercontent.com",
);
late final SharedPreferences? _sharedPreferences;
final UserStateHolder userStateHolder;
UserManager(this._repository) : userStateHolder = UserStateHolder();
bool get hasUser => userStateHolder.user != null;
Future<void> login() async {
if (await _googleSignIn.isSignedIn()) {
await _googleSignIn.signOut();
}
final account = await _googleSignIn.signIn();
await Future.delayed(Duration(milliseconds: 300));
}
Future<void> logout() async {
if (await _googleSignIn.isSignedIn()) {
await _googleSignIn.signOut();
}
Analytics.logout(userStateHolder.user);
userStateHolder.clear();
}
Future<void> _createUser(
String externalId,
ExternalIdType idType,
String? name,
) async {
final (user, token) =
await _repository.createOrGetUser(externalId, idType, name);
_setAuthToken(token);
userStateHolder.setUser(user);
}
void _setAuthToken(String authToken) async {
_repository.setAuthToken(authToken);
await _sharedPreferences!.setString('authToken', authToken);
}
void _clearAuthToken() async {
await _sharedPreferences!.remove('authToken');
}
Future<PromoCodeDto> applyPromocode(String code) async {
final data = await _repository.applyPromocode(code);
return data;
}
Future<UserDto?> updateUser() async {
String? authToken = _sharedPreferences!.getString('authToken');
if (authToken != null) {
_setAuthToken(authToken);
try {
final fetchedUser = await _repository.getUser();
userStateHolder.setUser(fetchedUser!);
return fetchedUser;
} catch (e) {
_clearAuthToken();
AppRouter.openAuthOrProfile();
}
}
// not creating empty user
// if (Platform.isAndroid) {
// final deviceInfoPlugin = DeviceInfoPlugin();
// final deviceInfo = await deviceInfoPlugin.androidInfo;
// final id = deviceInfo.id;
// await _createUser(id, ExternalIdType.device);
// }
return null;
}
Future<void> init() async {
_sharedPreferences = await SharedPreferences.getInstance();
try {
await updateUser();
} on Object catch (e, s) {
log('User manager init error', error: e, stackTrace: s);
}
_subscription = CompositeSubscription()
..add(_googleSignIn.onCurrentUserChanged
.startWith(_googleSignIn.currentUser)
.distinct((p, n) => p?.id == n?.id)
.listen((account) async {
if (account != null) {
final name = account.displayName;
final token =
await account.authentication.then((value) => value.idToken);
Analytics.login(ExternalIdType.google);
await _createUser(token!, ExternalIdType.google, name);
}
}))
..add(userStateHolder.asNullableStream
.distinct((a, b) => a?.id == b?.id)
.listen((user) async {
try {
if (user == null) {
AppRouter.openAuthOrProfile();
} else {
try {
AppRouter.closeAuthPage();
await locator.previewPackPoller.poll();
await locator.packManager.clearCache();
await locator.packUpdater.updateAvailablePacks();
} catch (err) {
log(err.toString());
}
}
} catch (e) {
log(e.toString());
_clearAuthToken();
if (e is DioException) {
if (e.response?.statusCode == 401) {
appRouter.push(
PageRouteInfo(ProfilePage.name),
);
}
}
}
}));
}
Future<void> dispose() async {
await _subscription?.cancel();
_subscription = null;
}
}
enum ExternalIdType { google, device }