feat: Allow loading of multiple clients in main.dart
parent
fe4dd064d1
commit
ec68d15586
@ -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;
|
||||
}
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
import 'package:fluffychat/pages/views/empty_page_view.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../matrix.dart';
|
||||
|
||||
class WaitForInitPage extends StatelessWidget {
|
||||
final Widget page;
|
||||
const WaitForInitPage(this.page, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (Matrix.of(context).loginState == null) {
|
||||
return StreamBuilder<LoginState>(
|
||||
stream: Matrix.of(context).client.onLoginStateChanged.stream,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return EmptyPage(loading: true);
|
||||
}
|
||||
return page;
|
||||
});
|
||||
}
|
||||
return page;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue