From 74735bbd5d056b4fe7daf8a2445b86bdd0f084af Mon Sep 17 00:00:00 2001 From: Sorunome Date: Sat, 18 Sep 2021 12:12:47 +0200 Subject: [PATCH] feat: add multiaccount loading --- lib/widgets/layouts/loading_view.dart | 4 +- lib/widgets/layouts/wait_for_login.dart | 2 +- lib/widgets/matrix.dart | 128 +++++++++++++++--------- 3 files changed, 85 insertions(+), 49 deletions(-) diff --git a/lib/widgets/layouts/loading_view.dart b/lib/widgets/layouts/loading_view.dart index fa755065..defa8064 100644 --- a/lib/widgets/layouts/loading_view.dart +++ b/lib/widgets/layouts/loading_view.dart @@ -7,10 +7,10 @@ import 'package:flutter/material.dart'; class LoadingView extends StatelessWidget { @override Widget build(BuildContext context) { - if (Matrix.of(context).loginState != null) { + if (Matrix.of(context).client.loginState != null) { WidgetsBinding.instance.addPostFrameCallback( (_) => VRouter.of(context).to( - Matrix.of(context).loginState == LoginState.loggedIn + Matrix.of(context).client.loginState == LoginState.loggedIn ? '/rooms' : '/home', queryParameters: VRouter.of(context).queryParameters, diff --git a/lib/widgets/layouts/wait_for_login.dart b/lib/widgets/layouts/wait_for_login.dart index 29a42f84..1193cb76 100644 --- a/lib/widgets/layouts/wait_for_login.dart +++ b/lib/widgets/layouts/wait_for_login.dart @@ -10,7 +10,7 @@ class WaitForInitPage extends StatelessWidget { @override Widget build(BuildContext context) { - if (Matrix.of(context).loginState == null) { + if (Matrix.of(context).client.loginState == null) { return StreamBuilder( stream: Matrix.of(context).client.onLoginStateChanged.stream, builder: (context, snapshot) { diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index 6481fa89..03e6f132 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -92,12 +92,15 @@ class MatrixState extends State with WidgetsBindingObserver { .then((_) { widget.clients.add(client); ClientManager.addClientNameToStore(client.clientName); - // TODO: Connect streamsubscriptions + _registerSubs(client.clientName); }); } return client; } + Client getClientByName(String name) => widget.clients + .firstWhere((c) => c.clientName == name, orElse: () => null); + Map get shareContent => _shareContent; set shareContent(Map content) { _shareContent = content; @@ -133,15 +136,15 @@ class MatrixState extends State with WidgetsBindingObserver { } } - StreamSubscription onRoomKeyRequestSub; - StreamSubscription onKeyVerificationRequestSub; - StreamSubscription onJitsiCallSub; - StreamSubscription onNotification; - StreamSubscription onLoginStateChanged; - StreamSubscription onUiaRequest; + final onRoomKeyRequestSub = {}; + final onKeyVerificationRequestSub = {}; + final onJitsiCallSub = {}; + final onNotification = {}; + final onLoginStateChanged = >{}; + final onUiaRequest = >{}; StreamSubscription onFocusSub; StreamSubscription onBlurSub; - StreamSubscription onOwnPresence; + final onOwnPresence = >{}; String _cachedPassword; String get cachedPassword { @@ -325,21 +328,14 @@ class MatrixState extends State with WidgetsBindingObserver { } } - LoginState loginState; - - 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(); - } - }); - }); + void _registerSubs(String name) { + final c = getClientByName(name); + if (c == null) { + Logs().w( + 'Attempted to register subscriptions for non-existing client $name'); + return; } - onKeyVerificationRequestSub ??= client.onKeyVerificationRequest.stream + onKeyVerificationRequestSub[name] ??= c.onKeyVerificationRequest.stream .listen((KeyVerification request) async { var hidPopup = false; request.onUpdate = () { @@ -370,51 +366,90 @@ class MatrixState extends State with WidgetsBindingObserver { await request.rejectVerification(); } }); - _initWithStore(); - - if (kIsWeb) { - onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true); - onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false); - } - onLoginStateChanged ??= client.onLoginStateChanged.stream.listen((state) { - if (loginState != state) { - loginState = state; + onLoginStateChanged[name] ??= c.onLoginStateChanged.stream.listen((state) { + final loggedInWithMultipleClients = widget.clients.length > 1; + if (loggedInWithMultipleClients) { + // TODO: display a nicer toast + showOkAlertDialog( + useRootNavigator: false, + context: navigatorContext, + title: 'Login state of client $name changed', + message: 'New login state: $state', + okLabel: L10n.of(widget.context).ok, + ); + } else { final isInLoginRoutes = {'/home', '/login', '/signup'} .contains(widget.router.currentState.url); if (widget.router.currentState.url == '/' || (state == LoginState.loggedIn) == isInLoginRoutes) { widget.router.currentState.to( - loginState == LoginState.loggedIn ? '/rooms' : '/home', + state == LoginState.loggedIn ? '/rooms' : '/home', queryParameters: widget.router.currentState.queryParameters, ); } } }); - // Cache and resend status message - onOwnPresence ??= client.onPresence.stream.listen((presence) { - if (client.isLogged() && - client.userID == presence.senderId && + onOwnPresence[name] ??= c.onPresence.stream.listen((presence) { + if (c.isLogged() && + c.userID == presence.senderId && presence.presence?.statusMsg != null) { Logs().v('Update status message: "${presence.presence.statusMsg}"'); store.setItem( SettingKeys.ownStatusMessage, presence.presence.statusMsg); } }); - - onUiaRequest ??= client.onUiaRequest.stream.listen(_onUiaRequest); + onUiaRequest[name] ??= c.onUiaRequest.stream.listen(_onUiaRequest); if (PlatformInfos.isWeb || PlatformInfos.isLinux) { - client.onSync.stream.first.then((s) { + c.onSync.stream.first.then((s) { html.Notification.requestPermission(); - onNotification ??= client.onEvent.stream + onNotification[name] ??= c.onEvent.stream .where((e) => e.type == EventUpdateType.timeline && [EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted] .contains(e.content['type']) && - e.content['sender'] != client.userID) + e.content['sender'] != c.userID) .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) { _backgroundPush = BackgroundPush( @@ -481,11 +516,12 @@ class MatrixState extends State with WidgetsBindingObserver { void dispose() { WidgetsBinding.instance.removeObserver(this); - onRoomKeyRequestSub?.cancel(); - onKeyVerificationRequestSub?.cancel(); - onLoginStateChanged?.cancel(); - onOwnPresence?.cancel(); - onNotification?.cancel(); + onRoomKeyRequestSub.values.map((s) => s.cancel()); + onKeyVerificationRequestSub.values.map((s) => s.cancel()); + onLoginStateChanged.values.map((s) => s.cancel()); + onOwnPresence.values.map((s) => s.cancel()); + onNotification.values.map((s) => s.cancel()); + onFocusSub?.cancel(); onBlurSub?.cancel(); _backgroundPush?.onLogin?.cancel();