feat: add multiaccount loading

This commit is contained in:
Sorunome 2021-09-18 12:12:47 +02:00
parent 9705bf0c01
commit 74735bbd5d
No known key found for this signature in database
GPG Key ID: B19471D07FC9BE9C
3 changed files with 85 additions and 49 deletions

View File

@ -7,10 +7,10 @@ import 'package:flutter/material.dart';
class LoadingView extends StatelessWidget { class LoadingView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (Matrix.of(context).loginState != null) { if (Matrix.of(context).client.loginState != null) {
WidgetsBinding.instance.addPostFrameCallback( WidgetsBinding.instance.addPostFrameCallback(
(_) => VRouter.of(context).to( (_) => VRouter.of(context).to(
Matrix.of(context).loginState == LoginState.loggedIn Matrix.of(context).client.loginState == LoginState.loggedIn
? '/rooms' ? '/rooms'
: '/home', : '/home',
queryParameters: VRouter.of(context).queryParameters, queryParameters: VRouter.of(context).queryParameters,

View File

@ -10,7 +10,7 @@ class WaitForInitPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (Matrix.of(context).loginState == null) { if (Matrix.of(context).client.loginState == null) {
return StreamBuilder<LoginState>( return StreamBuilder<LoginState>(
stream: Matrix.of(context).client.onLoginStateChanged.stream, stream: Matrix.of(context).client.onLoginStateChanged.stream,
builder: (context, snapshot) { builder: (context, snapshot) {

View File

@ -92,12 +92,15 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
.then((_) { .then((_) {
widget.clients.add(client); widget.clients.add(client);
ClientManager.addClientNameToStore(client.clientName); ClientManager.addClientNameToStore(client.clientName);
// TODO: Connect streamsubscriptions _registerSubs(client.clientName);
}); });
} }
return client; return client;
} }
Client getClientByName(String name) => widget.clients
.firstWhere((c) => c.clientName == name, orElse: () => null);
Map<String, dynamic> get shareContent => _shareContent; Map<String, dynamic> get shareContent => _shareContent;
set shareContent(Map<String, dynamic> content) { set shareContent(Map<String, dynamic> content) {
_shareContent = content; _shareContent = content;
@ -133,15 +136,15 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
} }
} }
StreamSubscription onRoomKeyRequestSub; final onRoomKeyRequestSub = <String, StreamSubscription>{};
StreamSubscription onKeyVerificationRequestSub; final onKeyVerificationRequestSub = <String, StreamSubscription>{};
StreamSubscription onJitsiCallSub; final onJitsiCallSub = <String, StreamSubscription>{};
StreamSubscription onNotification; final onNotification = <String, StreamSubscription>{};
StreamSubscription<LoginState> onLoginStateChanged; final onLoginStateChanged = <String, StreamSubscription<LoginState>>{};
StreamSubscription<UiaRequest> onUiaRequest; final onUiaRequest = <String, StreamSubscription<UiaRequest>>{};
StreamSubscription<html.Event> onFocusSub; StreamSubscription<html.Event> onFocusSub;
StreamSubscription<html.Event> onBlurSub; StreamSubscription<html.Event> onBlurSub;
StreamSubscription<Presence> onOwnPresence; final onOwnPresence = <String, StreamSubscription<Presence>>{};
String _cachedPassword; String _cachedPassword;
String get cachedPassword { String get cachedPassword {
@ -325,21 +328,14 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
} }
} }
LoginState loginState; void _registerSubs(String name) {
final c = getClientByName(name);
void initMatrix() { if (c == null) {
// Display the app lock Logs().w(
if (PlatformInfos.isMobile) { 'Attempted to register subscriptions for non-existing client $name');
WidgetsBinding.instance.addPostFrameCallback((_) { return;
FlutterSecureStorage().read(key: SettingKeys.appLockKey).then((lock) {
if (lock?.isNotEmpty ?? false) {
AppLock.of(widget.context).enable();
AppLock.of(widget.context).showLockScreen();
} }
}); onKeyVerificationRequestSub[name] ??= c.onKeyVerificationRequest.stream
});
}
onKeyVerificationRequestSub ??= client.onKeyVerificationRequest.stream
.listen((KeyVerification request) async { .listen((KeyVerification request) async {
var hidPopup = false; var hidPopup = false;
request.onUpdate = () { request.onUpdate = () {
@ -370,51 +366,90 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
await request.rejectVerification(); await request.rejectVerification();
} }
}); });
_initWithStore(); onLoginStateChanged[name] ??= c.onLoginStateChanged.stream.listen((state) {
final loggedInWithMultipleClients = widget.clients.length > 1;
if (kIsWeb) { if (loggedInWithMultipleClients) {
onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true); // TODO: display a nicer toast
onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false); showOkAlertDialog(
} useRootNavigator: false,
onLoginStateChanged ??= client.onLoginStateChanged.stream.listen((state) { context: navigatorContext,
if (loginState != state) { title: 'Login state of client $name changed',
loginState = state; message: 'New login state: $state',
okLabel: L10n.of(widget.context).ok,
);
} else {
final isInLoginRoutes = {'/home', '/login', '/signup'} final isInLoginRoutes = {'/home', '/login', '/signup'}
.contains(widget.router.currentState.url); .contains(widget.router.currentState.url);
if (widget.router.currentState.url == '/' || if (widget.router.currentState.url == '/' ||
(state == LoginState.loggedIn) == isInLoginRoutes) { (state == LoginState.loggedIn) == isInLoginRoutes) {
widget.router.currentState.to( widget.router.currentState.to(
loginState == LoginState.loggedIn ? '/rooms' : '/home', state == LoginState.loggedIn ? '/rooms' : '/home',
queryParameters: widget.router.currentState.queryParameters, queryParameters: widget.router.currentState.queryParameters,
); );
} }
} }
}); });
// Cache and resend status message // Cache and resend status message
onOwnPresence ??= client.onPresence.stream.listen((presence) { onOwnPresence[name] ??= c.onPresence.stream.listen((presence) {
if (client.isLogged() && if (c.isLogged() &&
client.userID == presence.senderId && c.userID == presence.senderId &&
presence.presence?.statusMsg != null) { presence.presence?.statusMsg != null) {
Logs().v('Update status message: "${presence.presence.statusMsg}"'); Logs().v('Update status message: "${presence.presence.statusMsg}"');
store.setItem( store.setItem(
SettingKeys.ownStatusMessage, presence.presence.statusMsg); SettingKeys.ownStatusMessage, presence.presence.statusMsg);
} }
}); });
onUiaRequest[name] ??= c.onUiaRequest.stream.listen(_onUiaRequest);
onUiaRequest ??= client.onUiaRequest.stream.listen(_onUiaRequest);
if (PlatformInfos.isWeb || PlatformInfos.isLinux) { if (PlatformInfos.isWeb || PlatformInfos.isLinux) {
client.onSync.stream.first.then((s) { c.onSync.stream.first.then((s) {
html.Notification.requestPermission(); html.Notification.requestPermission();
onNotification ??= client.onEvent.stream onNotification[name] ??= c.onEvent.stream
.where((e) => .where((e) =>
e.type == EventUpdateType.timeline && e.type == EventUpdateType.timeline &&
[EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted] [EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted]
.contains(e.content['type']) && .contains(e.content['type']) &&
e.content['sender'] != client.userID) e.content['sender'] != c.userID)
.listen(_showLocalNotification); .listen(_showLocalNotification);
}); });
} }
}
void _cancelSubs(String name) {
onRoomKeyRequestSub[name]?.cancel();
onRoomKeyRequestSub.remove(name);
onKeyVerificationRequestSub[name]?.cancel();
onKeyVerificationRequestSub.remove(name);
onLoginStateChanged[name]?.cancel();
onLoginStateChanged.remove(name);
onOwnPresence[name]?.cancel();
onOwnPresence.remove(name);
onNotification[name]?.cancel();
onNotification.remove(name);
}
void initMatrix() {
// Display the app lock
if (PlatformInfos.isMobile) {
WidgetsBinding.instance.addPostFrameCallback((_) {
FlutterSecureStorage().read(key: SettingKeys.appLockKey).then((lock) {
if (lock?.isNotEmpty ?? false) {
AppLock.of(widget.context).enable();
AppLock.of(widget.context).showLockScreen();
}
});
});
}
_initWithStore();
for (final c in widget.clients) {
_registerSubs(c.clientName);
}
if (kIsWeb) {
onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true);
onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false);
}
if (PlatformInfos.isMobile) { if (PlatformInfos.isMobile) {
_backgroundPush = BackgroundPush( _backgroundPush = BackgroundPush(
@ -481,11 +516,12 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
onRoomKeyRequestSub?.cancel(); onRoomKeyRequestSub.values.map((s) => s.cancel());
onKeyVerificationRequestSub?.cancel(); onKeyVerificationRequestSub.values.map((s) => s.cancel());
onLoginStateChanged?.cancel(); onLoginStateChanged.values.map((s) => s.cancel());
onOwnPresence?.cancel(); onOwnPresence.values.map((s) => s.cancel());
onNotification?.cancel(); onNotification.values.map((s) => s.cancel());
onFocusSub?.cancel(); onFocusSub?.cancel();
onBlurSub?.cancel(); onBlurSub?.cancel();
_backgroundPush?.onLogin?.cancel(); _backgroundPush?.onLogin?.cancel();