refactor: Better UX for accepting declining invite
This commit is contained in:
parent
80997b44cf
commit
0e1874b226
3 changed files with 57 additions and 112 deletions
|
|
@ -3241,5 +3241,6 @@
|
||||||
"commandHint_logoutall": "Logout all active devices",
|
"commandHint_logoutall": "Logout all active devices",
|
||||||
"displayNavigationRail": "Show navigation rail on mobile",
|
"displayNavigationRail": "Show navigation rail on mobile",
|
||||||
"customReaction": "Custom reaction",
|
"customReaction": "Custom reaction",
|
||||||
"moreEvents": "More events"
|
"moreEvents": "More events",
|
||||||
|
"declineInvitation": "Decline invitation"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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/platform_infos.dart';
|
||||||
import 'package:fluffychat/utils/show_scaffold_dialog.dart';
|
import 'package:fluffychat/utils/show_scaffold_dialog.dart';
|
||||||
import 'package:fluffychat/utils/show_update_snackbar.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_modal_action_popup.dart';
|
||||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart';
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart';
|
||||||
|
|
@ -114,82 +113,6 @@ class ChatListController extends State<ChatList>
|
||||||
|
|
||||||
void onChatTap(Room room) async {
|
void onChatTap(Room room) async {
|
||||||
if (room.membership == Membership.invite) {
|
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<InviteAction>(
|
|
||||||
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<String>('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(
|
final joinResult = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () async {
|
future: () async {
|
||||||
|
|
@ -680,6 +603,26 @@ class ChatListController extends State<ChatList>
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
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<ChatList>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
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:
|
case ChatContextAction.leave:
|
||||||
final confirmed = await showOkCancelAlertDialog(
|
final confirmed = await showOkCancelAlertDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
|
@ -981,6 +933,5 @@ enum ChatContextAction {
|
||||||
mute,
|
mute,
|
||||||
leave,
|
leave,
|
||||||
addToSpace,
|
addToSpace,
|
||||||
|
block,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InviteAction { accept, decline, block }
|
|
||||||
|
|
|
||||||
|
|
@ -35,32 +35,6 @@ class ChatListItem extends StatelessWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<bool> 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
@ -69,7 +43,7 @@ class ChatListItem extends StatelessWidget {
|
||||||
final typingText = room.getLocalizedTypingText(context);
|
final typingText = room.getLocalizedTypingText(context);
|
||||||
final lastEvent = room.lastEvent;
|
final lastEvent = room.lastEvent;
|
||||||
final ownMessage = lastEvent?.senderId == room.client.userID;
|
final ownMessage = lastEvent?.senderId == room.client.userID;
|
||||||
final unread = room.isUnread || room.membership == Membership.invite;
|
final unread = room.isUnread;
|
||||||
final directChatMatrixId = room.directChatMatrixID;
|
final directChatMatrixId = room.directChatMatrixID;
|
||||||
final isDirectChat = directChatMatrixId != null;
|
final isDirectChat = directChatMatrixId != null;
|
||||||
final unreadBubbleSize = unread || room.hasNewMessages
|
final unreadBubbleSize = unread || room.hasNewMessages
|
||||||
|
|
@ -357,8 +331,7 @@ class ChatListItem extends StatelessWidget {
|
||||||
room.notificationCount.toString().length +
|
room.notificationCount.toString().length +
|
||||||
9,
|
9,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: room.highlightCount > 0 ||
|
color: room.highlightCount > 0
|
||||||
room.membership == Membership.invite
|
|
||||||
? theme.colorScheme.error
|
? theme.colorScheme.error
|
||||||
: hasNotifications || room.markedUnread
|
: hasNotifications || room.markedUnread
|
||||||
? theme.colorScheme.primary
|
? theme.colorScheme.primary
|
||||||
|
|
@ -369,8 +342,7 @@ class ChatListItem extends StatelessWidget {
|
||||||
? Text(
|
? Text(
|
||||||
room.notificationCount.toString(),
|
room.notificationCount.toString(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: room.highlightCount > 0 ||
|
color: room.highlightCount > 0
|
||||||
room.membership == Membership.invite
|
|
||||||
? theme.colorScheme.onError
|
? theme.colorScheme.onError
|
||||||
: hasNotifications
|
: hasNotifications
|
||||||
? theme.colorScheme.onPrimary
|
? theme.colorScheme.onPrimary
|
||||||
|
|
@ -386,7 +358,28 @@ class ChatListItem extends StatelessWidget {
|
||||||
),
|
),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
trailing: onForget == null
|
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(
|
: IconButton(
|
||||||
icon: const Icon(Icons.delete_outlined),
|
icon: const Icon(Icons.delete_outlined),
|
||||||
onPressed: onForget,
|
onPressed: onForget,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue