feat: Allow loading of multiple clients in main.dart

This commit is contained in:
Krille Fear 2021-09-19 11:48:23 +00:00
commit ec68d15586
26 changed files with 840 additions and 159 deletions

View file

@ -0,0 +1,99 @@
import 'package:matrix/matrix.dart';
class AccountBundles {
String prefix;
List<AccountBundle> bundles;
AccountBundles({this.prefix, this.bundles});
AccountBundles.fromJson(Map<String, dynamic> json)
: prefix = json.tryGet<String>('prefix'),
bundles = json['bundles'] is List
? json['bundles']
.map((b) {
try {
return AccountBundle.fromJson(b);
} catch (_) {
return null;
}
})
.whereType<AccountBundle>()
.toList()
: null;
Map<String, dynamic> toJson() => {
if (prefix != null) 'prefix': prefix,
if (bundles != null) 'bundles': bundles.map((v) => v.toJson()).toList(),
};
}
class AccountBundle {
String name;
int priority;
AccountBundle({this.name, this.priority});
AccountBundle.fromJson(Map<String, dynamic> json)
: name = json.tryGet<String>('name'),
priority = json.tryGet<int>('priority');
Map<String, dynamic> toJson() => <String, dynamic>{
if (name != null) 'name': name,
if (priority != null) 'priority': priority,
};
}
const accountBundlesType = 'im.fluffychat.account_bundles';
extension AccountBundlesExtension on Client {
List<AccountBundle> get accountBundles {
List<AccountBundle> ret;
if (accountData.containsKey(accountBundlesType)) {
ret = AccountBundles.fromJson(accountData[accountBundlesType].content)
.bundles;
}
ret ??= [];
if (ret.isEmpty) {
ret.add(AccountBundle(
name: userID,
priority: 0,
));
}
return ret;
}
Future<void> setAccountBundle(String name, [int priority]) async {
final data =
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
var foundBundle = false;
data.bundles ??= [];
for (final bundle in data.bundles) {
if (bundle.name == name) {
bundle.priority = priority;
foundBundle = true;
break;
}
}
if (!foundBundle) {
data.bundles.add(AccountBundle(name: name, priority: priority));
}
await setAccountData(userID, accountBundlesType, data.toJson());
}
Future<void> removeFromAccountBundle(String name) async {
if (!accountData.containsKey(accountBundlesType)) {
return; // nothing to do
}
final data =
AccountBundles.fromJson(accountData[accountBundlesType].content);
if (data.bundles == null) return;
data.bundles.removeWhere((b) => b.name == name);
await setAccountData(userID, accountBundlesType, data.toJson());
}
String get sendPrefix {
final data =
AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {});
return data.prefix;
}
}

View file

@ -0,0 +1,72 @@
import 'dart:convert';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:flutter/foundation.dart';
import 'package:matrix/encryption/utils/key_verification.dart';
import 'package:matrix/matrix.dart';
import 'famedlysdk_store.dart';
import 'matrix_sdk_extensions.dart/flutter_matrix_hive_database.dart';
abstract class ClientManager {
static const String clientNamespace = 'im.fluffychat.store.clients';
static Future<List<Client>> getClients() async {
final clientNames = <String>{};
try {
final rawClientNames = await Store().getItem(clientNamespace);
if (rawClientNames != null) {
final clientNamesList =
(jsonDecode(rawClientNames) as List).cast<String>();
clientNames.addAll(clientNamesList);
}
} catch (e, s) {
Logs().w('Client names in store are corrupted', e, s);
await Store().deleteItem(clientNamespace);
}
if (clientNames.isEmpty) clientNames.add(PlatformInfos.clientName);
final clients = clientNames.map(createClient).toList();
await Future.wait(clients.map((client) => client
.init()
.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) {
clientNames.remove(client.clientName);
clients.remove(client);
}
await Store().setItem(clientNamespace, jsonEncode(clientNames.toList()));
}
return clients;
}
static Future<void> addClientNameToStore(String clientName) async {
final clientNamesList = <String>[];
final rawClientNames = await Store().getItem(clientNamespace);
if (rawClientNames != null) {
final stored = (jsonDecode(rawClientNames) as List).cast<String>();
clientNamesList.addAll(stored);
}
clientNamesList.add(clientName);
await Store().setItem(clientNamespace, jsonEncode(clientNamesList));
}
static Client createClient(String clientName) => Client(
clientName,
enableE2eeRecovery: true,
verificationMethods: {
KeyVerificationMethod.numbers,
if (PlatformInfos.isMobile || PlatformInfos.isLinux)
KeyVerificationMethod.emoji,
},
importantStateEvents: <String>{
'im.ponies.room_emotes', // we want emotes to work properly
},
databaseBuilder: FlutterMatrixHiveStore.hiveDatabaseBuilder,
supportedLoginTypes: {
AuthenticationTypes.password,
if (PlatformInfos.isMobile || PlatformInfos.isWeb)
AuthenticationTypes.sso
},
compute: compute,
);
}