diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 97fdc78ef..6666ad317 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -3241,5 +3241,6 @@ "commandHint_logoutall": "Logout all active devices", "displayNavigationRail": "Show navigation rail on mobile", "customReaction": "Custom reaction", - "moreEvents": "More events" + "moreEvents": "More events", + "declineInvitation": "Decline invitation" } diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 1b07b0758..7d64f13d1 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -20,7 +20,6 @@ import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/show_scaffold_dialog.dart'; import 'package:fluffychat/utils/show_update_snackbar.dart'; -import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_modal_action_popup.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart'; @@ -114,82 +113,6 @@ class ChatListController extends State void onChatTap(Room room) async { if (room.membership == Membership.invite) { - final theme = Theme.of(context); - final inviteEvent = room.getState( - EventTypes.RoomMember, - room.client.userID!, - ); - final matrixLocals = MatrixLocals(L10n.of(context)); - final action = await showAdaptiveDialog( - context: context, - builder: (context) => AlertDialog.adaptive( - title: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), - child: Center( - child: Text( - room.getLocalizedDisplayname(matrixLocals), - textAlign: TextAlign.center, - ), - ), - ), - content: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256, maxHeight: 256), - child: Text( - inviteEvent == null - ? L10n.of(context).inviteForMe - : inviteEvent.content.tryGet('reason') ?? - L10n.of(context).youInvitedBy( - room - .unsafeGetUserFromMemoryOrFallback( - inviteEvent.senderId, - ) - .calcDisplayname(i18n: matrixLocals), - ), - textAlign: TextAlign.center, - ), - ), - actions: [ - AdaptiveDialogAction( - onPressed: () => Navigator.of(context).pop(InviteAction.accept), - bigButtons: true, - child: Text(L10n.of(context).accept), - ), - AdaptiveDialogAction( - onPressed: () => Navigator.of(context).pop(InviteAction.decline), - bigButtons: true, - child: Text( - L10n.of(context).decline, - style: TextStyle(color: theme.colorScheme.error), - ), - ), - AdaptiveDialogAction( - onPressed: () => Navigator.of(context).pop(InviteAction.block), - bigButtons: true, - child: Text( - L10n.of(context).block, - style: TextStyle(color: theme.colorScheme.error), - ), - ), - ], - ), - ); - switch (action) { - case null: - return; - case InviteAction.accept: - break; - case InviteAction.decline: - await showFutureLoadingDialog( - context: context, - future: () => room.leave(), - ); - return; - case InviteAction.block: - final userId = inviteEvent?.senderId; - context.go('/rooms/settings/security/ignorelist', extra: userId); - return; - } - if (!mounted) return; final joinResult = await showFutureLoadingDialog( context: context, future: () async { @@ -680,6 +603,26 @@ class ChatListController extends State ], ), ), + if (room.membership == Membership.invite) + PopupMenuItem( + value: ChatContextAction.block, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.block_outlined, + color: Theme.of(context).colorScheme.onErrorContainer, + ), + const SizedBox(width: 12), + Text( + L10n.of(context).block, + style: TextStyle( + color: Theme.of(context).colorScheme.onErrorContainer, + ), + ), + ], + ), + ), ], ); @@ -715,6 +658,15 @@ class ChatListController extends State ), ); return; + case ChatContextAction.block: + final inviteEvent = room.getState( + EventTypes.RoomMember, + room.client.userID!, + ); + context.go( + '/rooms/settings/security/ignorelist', + extra: inviteEvent?.senderId, + ); case ChatContextAction.leave: final confirmed = await showOkCancelAlertDialog( context: context, @@ -981,6 +933,5 @@ enum ChatContextAction { mute, leave, addToSpace, + block, } - -enum InviteAction { accept, decline, block } diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 6ee2ee941..639ccd5b4 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -35,32 +35,6 @@ class ChatListItem extends StatelessWidget { super.key, }); - Future archiveAction(BuildContext context) async { - { - if ([Membership.leave, Membership.ban].contains(room.membership)) { - final forgetResult = await showFutureLoadingDialog( - context: context, - future: () => room.forget(), - ); - return forgetResult.isValue; - } - final confirmed = await showOkCancelAlertDialog( - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).leave, - cancelLabel: L10n.of(context).cancel, - message: L10n.of(context).archiveRoomDescription, - isDestructive: true, - ); - if (confirmed != OkCancelResult.ok) return false; - final leaveResult = await showFutureLoadingDialog( - context: context, - future: () => room.leave(), - ); - return leaveResult.isValue; - } - } - @override Widget build(BuildContext context) { final theme = Theme.of(context); @@ -69,7 +43,7 @@ class ChatListItem extends StatelessWidget { final typingText = room.getLocalizedTypingText(context); final lastEvent = room.lastEvent; final ownMessage = lastEvent?.senderId == room.client.userID; - final unread = room.isUnread || room.membership == Membership.invite; + final unread = room.isUnread; final directChatMatrixId = room.directChatMatrixID; final isDirectChat = directChatMatrixId != null; final unreadBubbleSize = unread || room.hasNewMessages @@ -357,8 +331,7 @@ class ChatListItem extends StatelessWidget { room.notificationCount.toString().length + 9, decoration: BoxDecoration( - color: room.highlightCount > 0 || - room.membership == Membership.invite + color: room.highlightCount > 0 ? theme.colorScheme.error : hasNotifications || room.markedUnread ? theme.colorScheme.primary @@ -369,8 +342,7 @@ class ChatListItem extends StatelessWidget { ? Text( room.notificationCount.toString(), style: TextStyle( - color: room.highlightCount > 0 || - room.membership == Membership.invite + color: room.highlightCount > 0 ? theme.colorScheme.onError : hasNotifications ? theme.colorScheme.onPrimary @@ -386,7 +358,28 @@ class ChatListItem extends StatelessWidget { ), onTap: onTap, trailing: onForget == null - ? null + ? room.membership == Membership.invite + ? IconButton( + tooltip: L10n.of(context).declineInvitation, + icon: const Icon(Icons.delete_forever_outlined), + color: theme.colorScheme.error, + onPressed: () async { + final consent = await showOkCancelAlertDialog( + context: context, + title: L10n.of(context).declineInvitation, + message: L10n.of(context).areYouSure, + okLabel: L10n.of(context).yes, + isDestructive: true, + ); + if (consent != OkCancelResult.ok) return; + if (!context.mounted) return; + await showFutureLoadingDialog( + context: context, + future: room.leave, + ); + }, + ) + : null : IconButton( icon: const Icon(Icons.delete_outlined), onPressed: onForget,