From f8c837cf1a19b3829144879d5ab7592aa6e08a9f Mon Sep 17 00:00:00 2001 From: Micah Morrison Date: Wed, 13 Dec 2023 12:20:16 -0500 Subject: [PATCH 1/3] Fix a couple logout issues --- lib/user/pages/user_page.dart | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/user/pages/user_page.dart b/lib/user/pages/user_page.dart index 7da539017..292f304ee 100644 --- a/lib/user/pages/user_page.dart +++ b/lib/user/pages/user_page.dart @@ -4,7 +4,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:swipeable_page_route/swipeable_page_route.dart'; import 'package:thunder/account/bloc/account_bloc.dart'; +import 'package:thunder/account/models/account.dart'; import 'package:thunder/account/utils/profiles.dart'; +import 'package:thunder/core/auth/bloc/auth_bloc.dart'; import 'package:thunder/shared/primitive_wrapper.dart'; import 'package:thunder/shared/snackbar.dart'; import 'package:thunder/thunder/bloc/thunder_bloc.dart'; @@ -47,7 +49,33 @@ class _UserPageState extends State { scrolledUnderElevation: 0, leading: widget.isAccountUser ? IconButton( - onPressed: () => showLogOutDialog(context), + onPressed: () async { + final ThunderBloc thunderBloc = context.read(); + final AuthBloc authBloc = context.read(); + + final String? currentAccountId = authBloc.state.account?.id; + + if (await showLogOutDialog(context) && context.mounted) { + final List anonymousInstances = thunderBloc.state.anonymousInstances; + final List accounts = (await Account.accounts()).where((account) => account.id != currentAccountId).toList(); + + await Future.delayed(const Duration(milliseconds: 1000), () async { + if (anonymousInstances.isNotEmpty) { + // Switch to an anonymous instance + thunderBloc.add(OnSetCurrentAnonymousInstance(anonymousInstances.last)); + authBloc.add(InstanceChanged(instance: anonymousInstances.last)); + } else if (accounts.isNotEmpty) { + // Switch to an account + authBloc.add(SwitchAccount(accountId: accounts.last.id)); + } else { + // No accounts and no anonymous instances left. Create a new one. + authBloc.add(const LogOutOfAllAccounts()); + thunderBloc.add(const OnAddAnonymousInstance('lemmy.ml')); + thunderBloc.add(const OnSetCurrentAnonymousInstance('lemmy.ml')); + } + }); + } + }, icon: Icon( Icons.logout, semanticLabel: AppLocalizations.of(context)!.logOut, From ecd4c5450472f3485e7d71f9a6bea14a6028ac0a Mon Sep 17 00:00:00 2001 From: Micah Morrison Date: Tue, 19 Dec 2023 14:50:12 -0500 Subject: [PATCH 2/3] Show modal when logging out of account --- lib/account/utils/profiles.dart | 6 +- lib/account/widgets/profile_modal_body.dart | 89 +++++++++++++++------ lib/user/pages/user_page.dart | 28 +------ 3 files changed, 70 insertions(+), 53 deletions(-) diff --git a/lib/account/utils/profiles.dart b/lib/account/utils/profiles.dart index 6849aeefb..b860bacb6 100644 --- a/lib/account/utils/profiles.dart +++ b/lib/account/utils/profiles.dart @@ -6,7 +6,7 @@ import 'package:thunder/core/auth/bloc/auth_bloc.dart'; import 'package:thunder/thunder/bloc/thunder_bloc.dart'; import 'package:thunder/account/widgets/profile_modal_body.dart'; -void showProfileModalSheet(BuildContext context) { +void showProfileModalSheet(BuildContext context, {bool logOutOfActiveAccount = false}) { AuthBloc authBloc = context.read(); ThunderBloc thunderBloc = context.read(); @@ -20,9 +20,9 @@ void showProfileModalSheet(BuildContext context) { BlocProvider.value(value: authBloc), BlocProvider.value(value: thunderBloc), ], - child: const FractionallySizedBox( + child: FractionallySizedBox( heightFactor: 0.9, - child: ProfileModalBody(), + child: ProfileModalBody(logOutOfActiveAccount: logOutOfActiveAccount), ), ); }, diff --git a/lib/account/widgets/profile_modal_body.dart b/lib/account/widgets/profile_modal_body.dart index ad6615b68..78a01298c 100644 --- a/lib/account/widgets/profile_modal_body.dart +++ b/lib/account/widgets/profile_modal_body.dart @@ -17,8 +17,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ProfileModalBody extends StatefulWidget { final bool anonymous; + final bool logOutOfActiveAccount; - const ProfileModalBody({super.key, this.anonymous = false}); + const ProfileModalBody({super.key, this.anonymous = false, this.logOutOfActiveAccount = false}); static final GlobalKey shellNavigatorKey = GlobalKey(); @@ -40,7 +41,14 @@ class _ProfileModalBodyState extends State { return Navigator( key: ProfileModalBody.shellNavigatorKey, onPopPage: (route, result) => false, - pages: [MaterialPage(child: ProfileSelect(pushRegister: pushRegister))], + pages: [ + MaterialPage( + child: ProfileSelect( + pushRegister: pushRegister, + logOutOfActiveAccount: widget.logOutOfActiveAccount, + ), + ) + ], onGenerateRoute: _onGenerateRoute, ); } @@ -49,7 +57,10 @@ class _ProfileModalBodyState extends State { late Widget page; switch (settings.name) { case '/': - page = ProfileSelect(pushRegister: pushRegister); + page = ProfileSelect( + pushRegister: pushRegister, + logOutOfActiveAccount: widget.logOutOfActiveAccount, + ); break; case '/login': @@ -68,7 +79,13 @@ class _ProfileModalBodyState extends State { class ProfileSelect extends StatefulWidget { final void Function({bool anonymous}) pushRegister; - ProfileSelect({Key? key, required this.pushRegister}) : super(key: key); + final bool logOutOfActiveAccount; + + const ProfileSelect({ + super.key, + required this.pushRegister, + this.logOutOfActiveAccount = false, + }); @override State createState() => _ProfileSelectState(); @@ -82,6 +99,18 @@ class _ProfileSelectState extends State { // Represents the ID of the account/instance we're currently logging out of / removing String? loggingOutId; + @override + void initState() { + super.initState(); + + if (widget.logOutOfActiveAccount) { + WidgetsBinding.instance.addPostFrameCallback((_) async { + await Future.delayed(const Duration(milliseconds: 250)); + _logOutOfActiveAccount(); + }); + } + } + @override Widget build(BuildContext context) { final theme = Theme.of(context); @@ -295,25 +324,7 @@ class _ProfileSelectState extends State { child: CircularProgressIndicator(), ) : Icon(Icons.logout, semanticLabel: AppLocalizations.of(context)!.logOut), - onPressed: () async { - if (await showLogOutDialog(context)) { - setState(() => loggingOutId = accounts![index].account.id); - - await Future.delayed(const Duration(milliseconds: 1000), () { - if ((anonymousInstances?.length ?? 0) > 0) { - context.read().add(OnSetCurrentAnonymousInstance(anonymousInstances!.last.instance)); - context.read().add(InstanceChanged(instance: anonymousInstances!.last.instance)); - } else { - context.read().add(SwitchAccount(accountId: accounts!.lastWhere((account) => account.account.id != currentAccountId).account.id)); - } - - setState(() { - accounts = null; - loggingOutId = null; - }); - }); - } - }, + onPressed: () => _logOutOfActiveAccount(activeAccountId: accounts![index].account.id), ) : IconButton( icon: loggingOutId == accounts![index].account.id @@ -527,6 +538,38 @@ class _ProfileSelectState extends State { ); } + Future _logOutOfActiveAccount({String? activeAccountId}) async { + activeAccountId ??= context.read().state.account?.id; + + final AuthBloc authBloc = context.read(); + final ThunderBloc thunderBloc = context.read(); + + final List accountsNotCurrent = (await Account.accounts()).where((a) => a.id != activeAccountId).toList(); + + if (context.mounted && activeAccountId != null && await showLogOutDialog(context)) { + setState(() => loggingOutId = activeAccountId); + + await Future.delayed(const Duration(milliseconds: 1000), () { + if ((anonymousInstances?.length ?? 0) > 0) { + thunderBloc.add(OnSetCurrentAnonymousInstance(anonymousInstances!.last.instance)); + authBloc.add(InstanceChanged(instance: anonymousInstances!.last.instance)); + } else if (accountsNotCurrent.isNotEmpty) { + authBloc.add(SwitchAccount(accountId: accountsNotCurrent.last.id)); + } else { + // No accounts and no anonymous instances left. Create a new one. + authBloc.add(const LogOutOfAllAccounts()); + thunderBloc.add(const OnAddAnonymousInstance('lemmy.ml')); + thunderBloc.add(const OnSetCurrentAnonymousInstance('lemmy.ml')); + } + + setState(() { + accounts = null; + loggingOutId = null; + }); + }); + } + } + Future fetchAccounts() async { List accounts = await Account.accounts(); diff --git a/lib/user/pages/user_page.dart b/lib/user/pages/user_page.dart index 292f304ee..0b6ca502d 100644 --- a/lib/user/pages/user_page.dart +++ b/lib/user/pages/user_page.dart @@ -49,33 +49,7 @@ class _UserPageState extends State { scrolledUnderElevation: 0, leading: widget.isAccountUser ? IconButton( - onPressed: () async { - final ThunderBloc thunderBloc = context.read(); - final AuthBloc authBloc = context.read(); - - final String? currentAccountId = authBloc.state.account?.id; - - if (await showLogOutDialog(context) && context.mounted) { - final List anonymousInstances = thunderBloc.state.anonymousInstances; - final List accounts = (await Account.accounts()).where((account) => account.id != currentAccountId).toList(); - - await Future.delayed(const Duration(milliseconds: 1000), () async { - if (anonymousInstances.isNotEmpty) { - // Switch to an anonymous instance - thunderBloc.add(OnSetCurrentAnonymousInstance(anonymousInstances.last)); - authBloc.add(InstanceChanged(instance: anonymousInstances.last)); - } else if (accounts.isNotEmpty) { - // Switch to an account - authBloc.add(SwitchAccount(accountId: accounts.last.id)); - } else { - // No accounts and no anonymous instances left. Create a new one. - authBloc.add(const LogOutOfAllAccounts()); - thunderBloc.add(const OnAddAnonymousInstance('lemmy.ml')); - thunderBloc.add(const OnSetCurrentAnonymousInstance('lemmy.ml')); - } - }); - } - }, + onPressed: () => showProfileModalSheet(context, logOutOfActiveAccount: true), icon: Icon( Icons.logout, semanticLabel: AppLocalizations.of(context)!.logOut, From 8fcdd7f9a1fa3dccb3cb2bd0901a0ae8853ea573 Mon Sep 17 00:00:00 2001 From: Micah Morrison Date: Thu, 4 Jan 2024 08:21:02 -0500 Subject: [PATCH 3/3] Rename flag --- lib/account/utils/profiles.dart | 4 ++-- lib/account/widgets/profile_modal_body.dart | 14 +++++++------- lib/user/pages/user_page.dart | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/account/utils/profiles.dart b/lib/account/utils/profiles.dart index b860bacb6..50060c596 100644 --- a/lib/account/utils/profiles.dart +++ b/lib/account/utils/profiles.dart @@ -6,7 +6,7 @@ import 'package:thunder/core/auth/bloc/auth_bloc.dart'; import 'package:thunder/thunder/bloc/thunder_bloc.dart'; import 'package:thunder/account/widgets/profile_modal_body.dart'; -void showProfileModalSheet(BuildContext context, {bool logOutOfActiveAccount = false}) { +void showProfileModalSheet(BuildContext context, {bool showLogoutDialog = false}) { AuthBloc authBloc = context.read(); ThunderBloc thunderBloc = context.read(); @@ -22,7 +22,7 @@ void showProfileModalSheet(BuildContext context, {bool logOutOfActiveAccount = f ], child: FractionallySizedBox( heightFactor: 0.9, - child: ProfileModalBody(logOutOfActiveAccount: logOutOfActiveAccount), + child: ProfileModalBody(showLogoutDialog: showLogoutDialog), ), ); }, diff --git a/lib/account/widgets/profile_modal_body.dart b/lib/account/widgets/profile_modal_body.dart index 78a01298c..118094796 100644 --- a/lib/account/widgets/profile_modal_body.dart +++ b/lib/account/widgets/profile_modal_body.dart @@ -17,9 +17,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ProfileModalBody extends StatefulWidget { final bool anonymous; - final bool logOutOfActiveAccount; + final bool showLogoutDialog; - const ProfileModalBody({super.key, this.anonymous = false, this.logOutOfActiveAccount = false}); + const ProfileModalBody({super.key, this.anonymous = false, this.showLogoutDialog = false}); static final GlobalKey shellNavigatorKey = GlobalKey(); @@ -45,7 +45,7 @@ class _ProfileModalBodyState extends State { MaterialPage( child: ProfileSelect( pushRegister: pushRegister, - logOutOfActiveAccount: widget.logOutOfActiveAccount, + showLogoutDialog: widget.showLogoutDialog, ), ) ], @@ -59,7 +59,7 @@ class _ProfileModalBodyState extends State { case '/': page = ProfileSelect( pushRegister: pushRegister, - logOutOfActiveAccount: widget.logOutOfActiveAccount, + showLogoutDialog: widget.showLogoutDialog, ); break; @@ -79,12 +79,12 @@ class _ProfileModalBodyState extends State { class ProfileSelect extends StatefulWidget { final void Function({bool anonymous}) pushRegister; - final bool logOutOfActiveAccount; + final bool showLogoutDialog; const ProfileSelect({ super.key, required this.pushRegister, - this.logOutOfActiveAccount = false, + this.showLogoutDialog = false, }); @override @@ -103,7 +103,7 @@ class _ProfileSelectState extends State { void initState() { super.initState(); - if (widget.logOutOfActiveAccount) { + if (widget.showLogoutDialog) { WidgetsBinding.instance.addPostFrameCallback((_) async { await Future.delayed(const Duration(milliseconds: 250)); _logOutOfActiveAccount(); diff --git a/lib/user/pages/user_page.dart b/lib/user/pages/user_page.dart index 0b6ca502d..1d5e34969 100644 --- a/lib/user/pages/user_page.dart +++ b/lib/user/pages/user_page.dart @@ -49,7 +49,7 @@ class _UserPageState extends State { scrolledUnderElevation: 0, leading: widget.isAccountUser ? IconButton( - onPressed: () => showProfileModalSheet(context, logOutOfActiveAccount: true), + onPressed: () => showProfileModalSheet(context, showLogoutDialog: true), icon: Icon( Icons.logout, semanticLabel: AppLocalizations.of(context)!.logOut,