2024-05-22 20:48:44 +00:00
|
|
|
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/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';
|
2024-05-28 21:25:51 +00:00
|
|
|
import '../features/analytics/analytics.dart';
|
2024-05-22 20:48:44 +00:00
|
|
|
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();
|
|
|
|
|
}
|
2024-05-28 21:25:51 +00:00
|
|
|
Analytics.logout(userStateHolder.user);
|
2024-05-22 20:48:44 +00:00
|
|
|
userStateHolder.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _createUser(
|
|
|
|
|
String externalId,
|
|
|
|
|
ExternalIdType idType,
|
|
|
|
|
String? name,
|
|
|
|
|
) async {
|
2024-05-28 21:25:51 +00:00
|
|
|
final (user, token) =
|
|
|
|
|
await _repository.createOrGetUser(externalId, idType, name);
|
|
|
|
|
_setAuthToken(token);
|
|
|
|
|
userStateHolder.setUser(user);
|
2024-05-22 20:48:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _setAuthToken(String authToken) async {
|
|
|
|
|
_repository.setAuthToken(authToken);
|
|
|
|
|
await _sharedPreferences!.setString('authToken', authToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _clearAuthToken() async {
|
|
|
|
|
await _sharedPreferences!.remove('authToken');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _updateUser() async {
|
|
|
|
|
String? authToken = _sharedPreferences!.getString('authToken');
|
|
|
|
|
if (authToken != null) {
|
|
|
|
|
_setAuthToken(authToken);
|
|
|
|
|
try {
|
|
|
|
|
final fetchedUser = await _repository.getUser();
|
|
|
|
|
userStateHolder.setUser(fetchedUser!);
|
|
|
|
|
return;
|
|
|
|
|
} 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);
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> init() async {
|
|
|
|
|
_sharedPreferences = await SharedPreferences.getInstance();
|
|
|
|
|
|
|
|
|
|
//todo add ios
|
|
|
|
|
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);
|
2024-05-28 21:25:51 +00:00
|
|
|
Analytics.login(ExternalIdType.google);
|
2024-05-22 20:48:44 +00:00
|
|
|
await _createUser(token!, ExternalIdType.google, name);
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
..add(Stream.periodic(Duration(seconds: 10)).listen((_) async {
|
|
|
|
|
try {
|
|
|
|
|
if (userStateHolder.user == null) {
|
|
|
|
|
await _updateUser();
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(e.toString());
|
|
|
|
|
_clearAuthToken();
|
|
|
|
|
if (e is DioException) {
|
|
|
|
|
if (e.response?.statusCode == 401) {
|
|
|
|
|
appRouter.push(
|
|
|
|
|
PageRouteInfo(ProfilePage.name),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
..add(
|
|
|
|
|
userStateHolder.asNullableStream
|
|
|
|
|
.map((user) => user != null)
|
|
|
|
|
.distinct()
|
|
|
|
|
.listen((hasUser) {
|
|
|
|
|
if (hasUser) {
|
|
|
|
|
appRouter.replace(PageRouteInfo(HomePage.name));
|
|
|
|
|
} else {
|
|
|
|
|
AppRouter.openAuthOrProfile();
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> dispose() async {
|
|
|
|
|
await _subscription?.cancel();
|
|
|
|
|
_subscription = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ExternalIdType { google, device }
|