2023-12-29 15:19:59 +00:00
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:desktop_notifications/desktop_notifications.dart';
|
2021-09-19 11:48:23 +00:00
|
|
|
import 'package:flutter/foundation.dart';
|
2021-10-26 16:50:34 +00:00
|
|
|
|
2023-12-08 09:17:21 +00:00
|
|
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
2021-09-19 12:22:26 +00:00
|
|
|
import 'package:hive_flutter/hive_flutter.dart';
|
2021-09-19 11:48:23 +00:00
|
|
|
import 'package:matrix/encryption/utils/key_verification.dart';
|
|
|
|
import 'package:matrix/matrix.dart';
|
2021-11-16 14:44:09 +00:00
|
|
|
import 'package:path_provider/path_provider.dart';
|
2023-11-01 17:00:10 +00:00
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
2023-12-08 09:17:21 +00:00
|
|
|
import 'package:universal_html/html.dart' as html;
|
2021-09-19 11:48:23 +00:00
|
|
|
|
2023-12-08 09:17:21 +00:00
|
|
|
import 'package:fluffychat/config/app_config.dart';
|
2022-06-17 20:17:41 +00:00
|
|
|
import 'package:fluffychat/utils/custom_http_client.dart';
|
2022-04-14 08:37:56 +00:00
|
|
|
import 'package:fluffychat/utils/custom_image_resizer.dart';
|
2022-12-30 16:54:01 +00:00
|
|
|
import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart';
|
2021-10-26 16:50:34 +00:00
|
|
|
import 'package:fluffychat/utils/platform_infos.dart';
|
2023-11-22 06:51:16 +00:00
|
|
|
import 'matrix_sdk_extensions/flutter_matrix_sdk_database_builder.dart';
|
2021-09-19 11:48:23 +00:00
|
|
|
|
|
|
|
abstract class ClientManager {
|
|
|
|
static const String clientNamespace = 'im.fluffychat.store.clients';
|
2023-11-01 17:00:10 +00:00
|
|
|
static Future<List<Client>> getClients({
|
|
|
|
bool initialize = true,
|
|
|
|
required SharedPreferences store,
|
|
|
|
}) async {
|
2021-09-19 12:22:26 +00:00
|
|
|
if (PlatformInfos.isLinux) {
|
|
|
|
Hive.init((await getApplicationSupportDirectory()).path);
|
|
|
|
} else {
|
|
|
|
await Hive.initFlutter();
|
|
|
|
}
|
2021-09-19 11:48:23 +00:00
|
|
|
final clientNames = <String>{};
|
|
|
|
try {
|
2023-11-01 17:00:10 +00:00
|
|
|
final clientNamesList = store.getStringList(clientNamespace) ?? [];
|
|
|
|
clientNames.addAll(clientNamesList);
|
2021-09-19 11:48:23 +00:00
|
|
|
} catch (e, s) {
|
|
|
|
Logs().w('Client names in store are corrupted', e, s);
|
2023-11-01 17:00:10 +00:00
|
|
|
await store.remove(clientNamespace);
|
2021-09-19 11:48:23 +00:00
|
|
|
}
|
2021-09-21 07:00:42 +00:00
|
|
|
if (clientNames.isEmpty) {
|
|
|
|
clientNames.add(PlatformInfos.clientName);
|
2023-11-01 17:00:10 +00:00
|
|
|
await store.setStringList(clientNamespace, clientNames.toList());
|
2021-09-21 07:00:42 +00:00
|
|
|
}
|
2021-09-19 11:48:23 +00:00
|
|
|
final clients = clientNames.map(createClient).toList();
|
2022-04-14 05:34:55 +00:00
|
|
|
if (initialize) {
|
2023-12-08 09:17:21 +00:00
|
|
|
FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin;
|
2023-03-02 09:57:52 +00:00
|
|
|
await Future.wait(
|
|
|
|
clients.map(
|
|
|
|
(client) => client
|
|
|
|
.init(
|
|
|
|
waitForFirstSync: false,
|
|
|
|
waitUntilLoadCompletedLoaded: false,
|
2023-12-08 09:17:21 +00:00
|
|
|
onMigration: () {
|
|
|
|
sendMigrationNotification(
|
|
|
|
flutterLocalNotificationsPlugin ??=
|
|
|
|
FlutterLocalNotificationsPlugin(),
|
|
|
|
);
|
|
|
|
},
|
2023-03-02 09:57:52 +00:00
|
|
|
)
|
|
|
|
.catchError(
|
|
|
|
(e, s) => Logs().e('Unable to initialize client', e, s),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
2023-12-08 09:17:21 +00:00
|
|
|
flutterLocalNotificationsPlugin?.cancel(0);
|
2022-04-14 05:34:55 +00:00
|
|
|
}
|
2021-09-19 11:48:23 +00:00
|
|
|
if (clients.length > 1 && clients.any((c) => !c.isLogged())) {
|
|
|
|
final loggedOutClients = clients.where((c) => !c.isLogged()).toList();
|
|
|
|
for (final client in loggedOutClients) {
|
2021-09-20 09:52:02 +00:00
|
|
|
Logs().w(
|
2023-03-02 09:57:52 +00:00
|
|
|
'Multi account is enabled but client ${client.userID} is not logged in. Removing...',
|
|
|
|
);
|
2021-09-19 11:48:23 +00:00
|
|
|
clientNames.remove(client.clientName);
|
|
|
|
clients.remove(client);
|
|
|
|
}
|
2023-11-01 17:00:10 +00:00
|
|
|
await store.setStringList(clientNamespace, clientNames.toList());
|
2021-09-19 11:48:23 +00:00
|
|
|
}
|
|
|
|
return clients;
|
|
|
|
}
|
|
|
|
|
2023-11-01 17:00:10 +00:00
|
|
|
static Future<void> addClientNameToStore(
|
|
|
|
String clientName,
|
|
|
|
SharedPreferences store,
|
|
|
|
) async {
|
|
|
|
final clientNamesList = store.getStringList(clientNamespace) ?? [];
|
2021-09-19 11:48:23 +00:00
|
|
|
clientNamesList.add(clientName);
|
2023-11-01 17:00:10 +00:00
|
|
|
await store.setStringList(clientNamespace, clientNamesList);
|
2021-09-19 11:48:23 +00:00
|
|
|
}
|
|
|
|
|
2023-11-01 17:00:10 +00:00
|
|
|
static Future<void> removeClientNameFromStore(
|
|
|
|
String clientName,
|
|
|
|
SharedPreferences store,
|
|
|
|
) async {
|
|
|
|
final clientNamesList = store.getStringList(clientNamespace) ?? [];
|
2021-11-24 17:39:40 +00:00
|
|
|
clientNamesList.remove(clientName);
|
2023-11-01 17:00:10 +00:00
|
|
|
await store.setStringList(clientNamespace, clientNamesList);
|
2021-11-24 17:39:40 +00:00
|
|
|
}
|
|
|
|
|
2022-08-14 14:31:36 +00:00
|
|
|
static NativeImplementations get nativeImplementations => kIsWeb
|
2022-08-14 15:19:27 +00:00
|
|
|
? const NativeImplementationsDummy()
|
2022-08-14 14:31:36 +00:00
|
|
|
: NativeImplementationsIsolate(compute);
|
|
|
|
|
2022-06-17 20:17:41 +00:00
|
|
|
static Client createClient(String clientName) {
|
|
|
|
return Client(
|
|
|
|
clientName,
|
2022-06-21 12:50:27 +00:00
|
|
|
httpClient:
|
|
|
|
PlatformInfos.isAndroid ? CustomHttpClient.createHTTPClient() : null,
|
2022-06-17 20:17:41 +00:00
|
|
|
verificationMethods: {
|
|
|
|
KeyVerificationMethod.numbers,
|
|
|
|
if (kIsWeb || PlatformInfos.isMobile || PlatformInfos.isLinux)
|
|
|
|
KeyVerificationMethod.emoji,
|
|
|
|
},
|
|
|
|
importantStateEvents: <String>{
|
|
|
|
// To make room emotes work
|
|
|
|
'im.ponies.room_emotes',
|
|
|
|
},
|
2022-07-29 10:49:26 +00:00
|
|
|
logLevel: kReleaseMode ? Level.warning : Level.verbose,
|
2023-11-22 06:51:16 +00:00
|
|
|
databaseBuilder: flutterMatrixSdkDatabaseBuilder,
|
|
|
|
legacyDatabaseBuilder: FlutterHiveCollectionsDatabase.databaseBuilder,
|
2022-06-17 20:17:41 +00:00
|
|
|
supportedLoginTypes: {
|
|
|
|
AuthenticationTypes.password,
|
2023-03-26 09:20:54 +00:00
|
|
|
AuthenticationTypes.sso,
|
2022-06-17 20:17:41 +00:00
|
|
|
},
|
2022-08-14 14:31:36 +00:00
|
|
|
nativeImplementations: nativeImplementations,
|
2022-06-17 20:17:41 +00:00
|
|
|
customImageResizer: PlatformInfos.isMobile ? customImageResizer : null,
|
2023-12-04 07:59:53 +00:00
|
|
|
enableDehydratedDevices: true,
|
2022-06-17 20:17:41 +00:00
|
|
|
);
|
|
|
|
}
|
2023-12-08 09:17:21 +00:00
|
|
|
|
|
|
|
static void sendMigrationNotification(
|
|
|
|
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin,
|
|
|
|
) async {
|
2023-12-22 09:10:51 +00:00
|
|
|
final l10n = lookupL10n(PlatformDispatcher.instance.locale);
|
2023-12-08 09:17:21 +00:00
|
|
|
|
|
|
|
if (kIsWeb) {
|
|
|
|
html.Notification(
|
|
|
|
l10n.databaseMigrationTitle,
|
|
|
|
body: l10n.databaseMigrationBody,
|
|
|
|
);
|
2023-12-22 09:10:51 +00:00
|
|
|
return;
|
2023-12-08 09:17:21 +00:00
|
|
|
}
|
2023-12-29 15:19:59 +00:00
|
|
|
if (Platform.isLinux) {
|
|
|
|
await NotificationsClient().notify(
|
|
|
|
l10n.databaseMigrationTitle,
|
|
|
|
body: l10n.databaseMigrationBody,
|
|
|
|
appName: AppConfig.applicationName,
|
|
|
|
hints: [
|
|
|
|
NotificationHint.soundName('message-new-instant'),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2023-12-08 09:17:21 +00:00
|
|
|
|
|
|
|
await flutterLocalNotificationsPlugin.initialize(
|
|
|
|
const InitializationSettings(
|
|
|
|
android: AndroidInitializationSettings('notifications_icon'),
|
|
|
|
iOS: DarwinInitializationSettings(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
flutterLocalNotificationsPlugin.show(
|
|
|
|
0,
|
|
|
|
l10n.databaseMigrationTitle,
|
|
|
|
l10n.databaseMigrationBody,
|
|
|
|
const NotificationDetails(
|
|
|
|
android: AndroidNotificationDetails(
|
|
|
|
AppConfig.pushNotificationsChannelId,
|
|
|
|
AppConfig.pushNotificationsChannelName,
|
|
|
|
channelDescription: AppConfig.pushNotificationsChannelDescription,
|
|
|
|
importance: Importance.max,
|
|
|
|
priority: Priority.max,
|
|
|
|
fullScreenIntent: true, // To show notification popup
|
|
|
|
showProgress: true,
|
|
|
|
),
|
2023-12-22 09:10:51 +00:00
|
|
|
iOS: DarwinNotificationDetails(sound: 'notification.caf'),
|
2023-12-08 09:17:21 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2021-09-19 11:48:23 +00:00
|
|
|
}
|