Initial commit
This commit is contained in:
188
lib/utils/client_manager.dart
Normal file
188
lib/utils/client_manager.dart
Normal file
@@ -0,0 +1,188 @@
|
||||
// SPDX-FileCopyrightText: 2019-Present Christian Kußowski
|
||||
// SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:tatchat/config/app_config.dart';
|
||||
import 'package:tatchat/config/setting_keys.dart';
|
||||
import 'package:tatchat/l10n/l10n.dart';
|
||||
import 'package:tatchat/utils/custom_http_client.dart';
|
||||
import 'package:tatchat/utils/custom_image_resizer.dart';
|
||||
import 'package:tatchat/utils/init_with_restore.dart';
|
||||
import 'package:tatchat/utils/matrix_live_kit_calls/matrix_live_kit_call_member.dart';
|
||||
import 'package:tatchat/utils/platform_infos.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod;
|
||||
import 'package:matrix/encryption/utils/key_verification.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
|
||||
import 'matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart';
|
||||
|
||||
abstract class ClientManager {
|
||||
static const String clientNamespace = 'im.fluffychat.store.clients';
|
||||
|
||||
static Future<List<Client>> getClients({
|
||||
bool initialize = true,
|
||||
required SharedPreferences store,
|
||||
}) async {
|
||||
final clientNames = <String>{};
|
||||
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.appDisplayName);
|
||||
await store.setStringList(clientNamespace, clientNames.toList());
|
||||
}
|
||||
final clients = await Future.wait(
|
||||
clientNames.map((name) => createClient(name, store)),
|
||||
);
|
||||
if (initialize) {
|
||||
await Future.wait(
|
||||
clients.map(
|
||||
(client) => client
|
||||
.initWithRestore(
|
||||
onMigration: () async {
|
||||
final l10n = await lookupL10n(
|
||||
PlatformDispatcher.instance.locale,
|
||||
);
|
||||
sendInitNotification(
|
||||
l10n.databaseMigrationTitle,
|
||||
l10n.databaseMigrationBody,
|
||||
);
|
||||
},
|
||||
)
|
||||
.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<void> addClientNameToStore(
|
||||
String clientName,
|
||||
SharedPreferences store,
|
||||
) async {
|
||||
final clientNamesList = store.getStringList(clientNamespace) ?? [];
|
||||
clientNamesList.add(clientName);
|
||||
await store.setStringList(clientNamespace, clientNamesList);
|
||||
}
|
||||
|
||||
static Future<void> removeClientNameFromStore(
|
||||
String clientName,
|
||||
SharedPreferences store,
|
||||
) async {
|
||||
final clientNamesList = store.getStringList(clientNamespace) ?? [];
|
||||
clientNamesList.remove(clientName);
|
||||
await store.setStringList(clientNamespace, clientNamesList);
|
||||
}
|
||||
|
||||
static NativeImplementations get nativeImplementations => kIsWeb
|
||||
? NativeImplementationsWebWorker(
|
||||
Uri.parse('native_executor.js'),
|
||||
timeout: const Duration(minutes: 1),
|
||||
)
|
||||
: NativeImplementationsIsolate(
|
||||
compute,
|
||||
vodozemacInit: () => vod.init(
|
||||
wasmPath:
|
||||
'./assets/assets/vodozemac/${AppConfig.vodozemacVersion}/',
|
||||
),
|
||||
);
|
||||
|
||||
static Future<Client> createClient(
|
||||
String clientName,
|
||||
SharedPreferences store,
|
||||
) async {
|
||||
final shareKeysWith = AppSettings.shareKeysWith.value;
|
||||
final enableSoftLogout = AppSettings.enableSoftLogout.value;
|
||||
|
||||
return Client(
|
||||
clientName,
|
||||
httpClient: CustomHttpClient.createHTTPClient(),
|
||||
verificationMethods: {
|
||||
KeyVerificationMethod.numbers,
|
||||
if (kIsWeb || PlatformInfos.isMobile || PlatformInfos.isLinux)
|
||||
KeyVerificationMethod.emoji,
|
||||
},
|
||||
importantStateEvents: <String>{
|
||||
// To make room emotes work
|
||||
'im.ponies.room_emotes',
|
||||
// To display call state in chat list
|
||||
MatrixRtcCallMember.eventType,
|
||||
},
|
||||
customImageResizer: PlatformInfos.supportsCustomImageResizer
|
||||
? customImageResizer
|
||||
: null,
|
||||
logLevel: Level.verbose,
|
||||
database: await flutterMatrixSdkDatabaseBuilder(clientName),
|
||||
supportedLoginTypes: {
|
||||
AuthenticationTypes.password,
|
||||
AuthenticationTypes.sso,
|
||||
},
|
||||
nativeImplementations: nativeImplementations,
|
||||
defaultNetworkRequestTimeout: const Duration(minutes: 30),
|
||||
enableDehydratedDevices: true,
|
||||
shareKeysWith:
|
||||
ShareKeysWith.values.singleWhereOrNull(
|
||||
(share) => share.name == shareKeysWith,
|
||||
) ??
|
||||
ShareKeysWith.all,
|
||||
onSoftLogout: enableSoftLogout ? (c) => c.refreshAccessToken() : null,
|
||||
sendTimelineEventTimeout: Duration(
|
||||
seconds: AppSettings.sendTimelineEventTimeout.value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> sendInitNotification(String title, String body) async {
|
||||
if (kIsWeb) {
|
||||
html.Notification(title, body: body);
|
||||
return;
|
||||
}
|
||||
|
||||
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
settings: const InitializationSettings(
|
||||
android: AndroidInitializationSettings('notifications_icon'),
|
||||
iOS: DarwinInitializationSettings(),
|
||||
),
|
||||
);
|
||||
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
id: 0,
|
||||
title: title,
|
||||
body: body,
|
||||
notificationDetails: const NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'error_message',
|
||||
'Error Messages',
|
||||
importance: Importance.high,
|
||||
priority: Priority.max,
|
||||
),
|
||||
iOS: DarwinNotificationDetails(sound: 'notification.caf'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user