From 68dd01c4a0f5facaac6dde436736a26b7e921a8d Mon Sep 17 00:00:00 2001 From: jld3103 Date: Sat, 29 Jul 2023 22:55:58 +0200 Subject: [PATCH 1/2] refactor(neon): Await active account --- packages/neon/neon/lib/src/app.dart | 2 +- packages/neon/neon/lib/src/blocs/accounts.dart | 8 ++++---- packages/neon/neon/lib/src/pages/account_settings.dart | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/neon/neon/lib/src/app.dart b/packages/neon/neon/lib/src/app.dart index ab6224ed..4a9ce8d4 100644 --- a/packages/neon/neon/lib/src/app.dart +++ b/packages/neon/neon/lib/src/app.dart @@ -227,7 +227,7 @@ class _NeonAppState extends State with WidgetsBindingObserver, tray.Tra } final matches = _appRegex.allMatches(shortcutType); - final activeAccount = _accountsBloc.activeAccount.valueOrNull; + final activeAccount = await _accountsBloc.activeAccount.first; if (matches.isNotEmpty && activeAccount != null) { await _openAppFromExternal(activeAccount, matches.first.group(1)!); } diff --git a/packages/neon/neon/lib/src/blocs/accounts.dart b/packages/neon/neon/lib/src/blocs/accounts.dart index 407f9426..d79fae77 100644 --- a/packages/neon/neon/lib/src/blocs/accounts.dart +++ b/packages/neon/neon/lib/src/blocs/accounts.dart @@ -130,7 +130,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState BehaviorSubject> accounts = BehaviorSubject>.seeded([]); @override - BehaviorSubject activeAccount = BehaviorSubject.seeded(null) + BehaviorSubject activeAccount = BehaviorSubject() ..distinct((final current, final next) => current?.id != next?.id); @override @@ -191,10 +191,10 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState /// The currently active account. /// - /// Equivalent to activeAccount.value but throws a [StateError] when no user is logged in. + /// Equivalent to activeAccount.valueOrNull but throws a [StateError] when no user is logged in. @visibleForTesting Account get aa { - final aa = activeAccount.value; + final aa = activeAccount.valueOrNull; if (aa == null) { throw StateError('No user is logged in.'); @@ -204,7 +204,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState } /// Whether accounts are logged in. - bool get hasAccounts => activeAccount.value != null; + bool get hasAccounts => activeAccount.valueOrNull != null; /// The options for the [activeAccount]. /// diff --git a/packages/neon/neon/lib/src/pages/account_settings.dart b/packages/neon/neon/lib/src/pages/account_settings.dart index 618af5f4..21e752c4 100644 --- a/packages/neon/neon/lib/src/pages/account_settings.dart +++ b/packages/neon/neon/lib/src/pages/account_settings.dart @@ -41,7 +41,7 @@ class AccountSettingsPage extends StatelessWidget { context, AppLocalizations.of(context).accountOptionsRemoveConfirm(account.client.humanReadableID), )) { - final isActive = bloc.activeAccount.value == account; + final isActive = bloc.activeAccount.valueOrNull == account; bloc.removeAccount(account); From df2bd488540642202278c9ebf3fb2b1fb7343311 Mon Sep 17 00:00:00 2001 From: jld3103 Date: Sat, 29 Jul 2023 23:10:35 +0200 Subject: [PATCH 2/2] fix(neon): Prevent race condition setting active app --- packages/neon/neon/lib/src/blocs/apps.dart | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/neon/neon/lib/src/blocs/apps.dart b/packages/neon/neon/lib/src/blocs/apps.dart index 4ba93dc3..3ea9b0e6 100644 --- a/packages/neon/neon/lib/src/blocs/apps.dart +++ b/packages/neon/neon/lib/src/blocs/apps.dart @@ -19,7 +19,11 @@ import 'package:rxdart/rxdart.dart'; typedef NextcloudApp = CoreNavigationApps_Ocs_Data; abstract class AppsBlocEvents { - void setActiveApp(final String appID); + /// Sets the active app using the [appID]. + /// + /// If the app is already the active app nothing will happen. + /// When using [skipAlreadySet] nothing will be done if there already is an active app. + void setActiveApp(final String appID, {final bool skipAlreadySet = false}); } abstract class AppsBlocStates { @@ -57,8 +61,8 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates final options = _accountsBloc.getOptionsFor(_account); final initialApp = options.initialApp.value ?? _getInitialAppFallback(); - if (!activeApp.hasValue && initialApp != null) { - await setActiveApp(initialApp); + if (initialApp != null) { + await setActiveApp(initialApp, skipAlreadySet: true); } unawaited(_checkCompatibility()); @@ -201,7 +205,7 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates } @override - Future setActiveApp(final String appID) async { + Future setActiveApp(final String appID, {final bool skipAlreadySet = false}) async { if (appID == AppIDs.notifications) { openNotifications.add(null); return; @@ -210,7 +214,7 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates final apps = await appImplementations.firstWhere((final a) => a.hasData); final app = apps.requireData.tryFind(appID); if (app != null) { - if (activeApp.valueOrNull?.id != appID) { + if ((!activeApp.hasValue || !skipAlreadySet) && activeApp.valueOrNull?.id != appID) { activeApp.add(app); } } else {