kopia lustrzana https://gitlab.com/mysocialportal/relatica
182 wiersze
5.3 KiB
Dart
182 wiersze
5.3 KiB
Dart
import 'dart:collection';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:result_monad/result_monad.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../di_initialization.dart';
|
|
import '../friendica_client/friendica_client.dart';
|
|
import '../models/auth/credentials_intf.dart';
|
|
import '../models/auth/profile.dart';
|
|
import '../models/exec_error.dart';
|
|
import '../update_timer_initialization.dart';
|
|
import 'secrets_service.dart';
|
|
|
|
class AccountsService extends ChangeNotifier {
|
|
static final _logger = Logger('$AccountsService');
|
|
Profile? _currentProfile;
|
|
final _loggedInProfiles = <Profile>{};
|
|
final _loggedOutProfiles = <Profile>{};
|
|
var _initializing = false;
|
|
|
|
final SecretsService secretsService;
|
|
|
|
AccountsService(this.secretsService);
|
|
|
|
bool get loggedIn => _currentProfile != null;
|
|
|
|
bool get initializing => _initializing;
|
|
|
|
List<Profile> get loggedInProfiles => UnmodifiableListView(_loggedInProfiles);
|
|
|
|
List<Profile> get loggedOutProfiles =>
|
|
UnmodifiableListView(_loggedOutProfiles);
|
|
|
|
Profile get currentProfile => _currentProfile!;
|
|
|
|
FutureResult<bool, ExecError> initialize() async {
|
|
final lastActiveProfile = await _getStoredLoginState();
|
|
|
|
_initializing = true;
|
|
final result = await runCatchingAsync(() async {
|
|
final initialProfiles = secretsService.profiles;
|
|
for (final p in initialProfiles) {
|
|
if (!p.loggedIn) {
|
|
_loggedOutProfiles.add(p);
|
|
continue;
|
|
}
|
|
|
|
final pr = await signIn(p.credentials, withNotification: false);
|
|
if (pr.isSuccess) {
|
|
final profile = pr.value;
|
|
if (profile.id.isNotEmpty && profile.id == lastActiveProfile) {
|
|
_currentProfile = profile;
|
|
Future.delayed(
|
|
const Duration(seconds: 10),
|
|
() async => await executeUpdatesForProfile(profile),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_currentProfile == null && _loggedInProfiles.isNotEmpty) {
|
|
await setActiveProfile(_loggedInProfiles.first);
|
|
}
|
|
|
|
notifyListeners();
|
|
return Result.ok(loggedIn);
|
|
});
|
|
|
|
_initializing = false;
|
|
return result.execErrorCast();
|
|
}
|
|
|
|
FutureResult<Profile, ExecError> signIn(ICredentials credentials,
|
|
{bool withNotification = true}) async {
|
|
ICredentials? credentialsCache;
|
|
final result =
|
|
await credentials.signIn().andThenAsync((signedInCredentials) async {
|
|
final client =
|
|
ProfileClient(Profile.credentialsOnly(signedInCredentials));
|
|
credentialsCache = signedInCredentials;
|
|
return await client.getMyProfile();
|
|
}).andThenAsync((profileData) async {
|
|
final loginProfile = Profile(
|
|
credentials: credentialsCache!,
|
|
username: profileData.name,
|
|
serverName: credentialsCache!.serverName,
|
|
avatar: profileData.avatarUrl,
|
|
userId: profileData.id,
|
|
loggedIn: true,
|
|
);
|
|
|
|
if (_loggedInProfiles.isEmpty) {
|
|
await setActiveProfile(loginProfile,
|
|
withNotification: withNotification);
|
|
}
|
|
_loggedInProfiles.add(loginProfile);
|
|
_loggedOutProfiles.remove(loginProfile);
|
|
await secretsService.addOrUpdateProfile(loginProfile);
|
|
await updateProfileDependencyInjectors(loginProfile);
|
|
if (withNotification) {
|
|
notifyListeners();
|
|
}
|
|
return Result.ok(loginProfile);
|
|
});
|
|
|
|
if (result.isFailure) {
|
|
_logger.severe('Error signing in: ${result.error}');
|
|
}
|
|
|
|
return result.execErrorCast();
|
|
}
|
|
|
|
Future signOut(Profile profile, {bool withNotification = true}) async {
|
|
if (_currentProfile == profile) {
|
|
await clearActiveProfile(withNotification: withNotification);
|
|
}
|
|
_loggedInProfiles.remove(profile);
|
|
_loggedOutProfiles.add(profile.copyWithLoginUpdate(false));
|
|
await secretsService.addOrUpdateProfile(profile.copyWithLoginUpdate(false));
|
|
|
|
if (_loggedInProfiles.isNotEmpty) {
|
|
setActiveProfile(
|
|
_loggedInProfiles.first,
|
|
withNotification: withNotification,
|
|
);
|
|
}
|
|
|
|
if (withNotification) {
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
Future removeProfile(Profile profile, {bool withNotification = true}) async {
|
|
if (_currentProfile == profile) {
|
|
await clearActiveProfile(withNotification: withNotification);
|
|
}
|
|
_loggedInProfiles.remove(profile);
|
|
_loggedOutProfiles.remove(profile);
|
|
await secretsService.removeProfile(profile);
|
|
|
|
if (_loggedInProfiles.isNotEmpty) {
|
|
setActiveProfile(
|
|
_loggedInProfiles.first,
|
|
withNotification: withNotification,
|
|
);
|
|
}
|
|
|
|
if (withNotification) {
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
Future clearActiveProfile({bool withNotification = true}) async {
|
|
_currentProfile = null;
|
|
if (withNotification) {
|
|
notifyListeners();
|
|
}
|
|
await _saveStoredLoginState();
|
|
}
|
|
|
|
Future<void> setActiveProfile(Profile profile,
|
|
{bool withNotification = true}) async {
|
|
_currentProfile = profile;
|
|
if (withNotification) {
|
|
notifyListeners();
|
|
}
|
|
await _saveStoredLoginState();
|
|
}
|
|
|
|
Future<void> _saveStoredLoginState() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString('active_profile_id', _currentProfile?.id ?? '');
|
|
}
|
|
|
|
Future<String> _getStoredLoginState() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return prefs.getString('active_profile_id') ?? '';
|
|
}
|
|
}
|