import 'package:flutter/foundation.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:matrix/encryption/utils/key_verification.dart'; import 'package:matrix/matrix.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:fluffychat/utils/custom_http_client.dart'; import 'package:fluffychat/utils/custom_image_resizer.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'matrix_sdk_extensions/flutter_matrix_sdk_database_builder.dart'; abstract class ClientManager { static const String clientNamespace = 'im.fluffychat.store.clients'; static Future> getClients({ bool initialize = true, required SharedPreferences store, }) async { if (PlatformInfos.isLinux) { Hive.init((await getApplicationSupportDirectory()).path); } else { await Hive.initFlutter(); } final clientNames = {}; try { final clientNamesList = store.getStringList(clientNamespace) ?? []; clientNames.addAll(clientNamesList); } catch (e, s) { Logs().w('Client names in store are corrupted', e, s); await store.remove(clientNamespace); } if (clientNames.isEmpty) { clientNames.add(PlatformInfos.clientName); await store.setStringList(clientNamespace, clientNames.toList()); } final clients = clientNames.map(createClient).toList(); if (initialize) { await Future.wait( clients.map( (client) => client .init( waitForFirstSync: false, waitUntilLoadCompletedLoaded: false, ) .catchError( (e, s) => Logs().e('Unable to initialize client', e, s), ), ), ); } if (clients.length > 1 && clients.any((c) => !c.isLogged())) { final loggedOutClients = clients.where((c) => !c.isLogged()).toList(); for (final client in loggedOutClients) { Logs().w( 'Multi account is enabled but client ${client.userID} is not logged in. Removing...', ); clientNames.remove(client.clientName); clients.remove(client); } await store.setStringList(clientNamespace, clientNames.toList()); } return clients; } static Future addClientNameToStore( String clientName, SharedPreferences store, ) async { final clientNamesList = store.getStringList(clientNamespace) ?? []; clientNamesList.add(clientName); await store.setStringList(clientNamespace, clientNamesList); } static Future removeClientNameFromStore( String clientName, SharedPreferences store, ) async { final clientNamesList = store.getStringList(clientNamespace) ?? []; clientNamesList.remove(clientName); await store.setStringList(clientNamespace, clientNamesList); } static NativeImplementations get nativeImplementations => kIsWeb ? const NativeImplementationsDummy() : NativeImplementationsIsolate(compute); static Client createClient(String clientName) { return Client( clientName, httpClient: PlatformInfos.isAndroid ? CustomHttpClient.createHTTPClient() : null, verificationMethods: { KeyVerificationMethod.numbers, if (kIsWeb || PlatformInfos.isMobile || PlatformInfos.isLinux) KeyVerificationMethod.emoji, }, importantStateEvents: { // To make room emotes work 'im.ponies.room_emotes', // To check which story room we can post in EventTypes.RoomPowerLevels, }, logLevel: kReleaseMode ? Level.warning : Level.verbose, databaseBuilder: flutterMatrixSdkDatabaseBuilder, legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder, supportedLoginTypes: { AuthenticationTypes.password, AuthenticationTypes.sso, }, nativeImplementations: nativeImplementations, customImageResizer: PlatformInfos.isMobile ? customImageResizer : null, enableDehydratedDevices: true, ); } }