diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index f0057ed77e..68b8c7c739 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/presentation/mixins/handle_clipboard_action_mixin.dar import 'package:fluffychat/presentation/mixins/paste_image_mixin.dart'; import 'package:fluffychat/presentation/model/chat/view_event_list_ui_state.dart'; import 'package:fluffychat/utils/extension/basic_event_extension.dart'; +import 'package:fluffychat/utils/extension/event_status_custom_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart'; import 'package:fluffychat/widgets/mixins/twake_context_menu_mixin.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; @@ -768,6 +769,9 @@ class ChatController extends State } void forwardEventsAction({Event? event}) async { + if (event != null && !event.status.isAvailableToForwardEvent) { + return; + } if (selectedEvents.isEmpty && event != null) { Matrix.of(context).shareContent = event.getDisplayEvent(timeline!).formatContentForwards(); @@ -809,6 +813,9 @@ class ChatController extends State void replyAction({ Event? replyTo, }) { + if (replyTo?.status.isAvailableToForwardEvent == false) { + return; + } _updateReplyEvent( event: replyTo ?? selectedEvents.first, ); @@ -1331,9 +1338,12 @@ class ChatController extends State openingPopupMenu.toggle(); } - List listHorizontalActionMenuBuilder() { + List listHorizontalActionMenuBuilder( + Event event, + ) { final listAction = [ - ChatHorizontalActionMenu.reply, + if (event.status.isAvailableToForwardEvent) + ChatHorizontalActionMenu.reply, ChatHorizontalActionMenu.more, ]; return listAction @@ -1377,7 +1387,8 @@ class ChatController extends State ChatContextMenuActions.select, if (event.isCopyable) ChatContextMenuActions.copyMessage, ChatContextMenuActions.pinChat, - ChatContextMenuActions.forward, + if (event.status.isAvailableToForwardEvent) + ChatContextMenuActions.forward, if (PlatformInfos.isWeb && event.hasAttachment) ChatContextMenuActions.downloadFile, ]; diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 718add73ca..229cbbdaa8 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -176,8 +176,8 @@ class ChatEventList extends StatelessWidget { onHover: (isHover, event) => controller.onHover(isHover, index, event), isHoverNotifier: controller.focusHover, - listHorizontalActionMenu: - controller.listHorizontalActionMenuBuilder(), + listHorizontalActionMenu: controller + .listHorizontalActionMenuBuilder(event), onMenuAction: controller.handleHorizontalActionMenu, hideKeyboardChatScreen: controller.onHideKeyboardAndEmoji, diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index 6bd9742bed..0557ad104b 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -31,51 +31,10 @@ class ChatInputRow extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: controller.selectMode - ? [ - SizedBox( - height: ChatInputRowStyle.chatInputRowHeight, - child: TextButton( - onPressed: controller.forwardEventsAction, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon(Icons.keyboard_arrow_left_outlined), - Text(L10n.of(context)!.forward), - ], - ), - ), + ? [ + ActionSelectModeWidget( + controller: controller, ), - controller.selectedEvents.length == 1 - ? controller.selectedEvents.first - .getDisplayEvent(controller.timeline!) - .status - .isSent - ? SizedBox( - height: ChatInputRowStyle.chatInputRowHeight, - child: TextButton( - onPressed: controller.replyAction, - child: Row( - children: [ - Text(L10n.of(context)!.reply), - const Icon(Icons.keyboard_arrow_right), - ], - ), - ), - ) - : SizedBox( - height: ChatInputRowStyle.chatInputRowHeight, - child: TextButton( - onPressed: controller.sendAgainAction, - child: Row( - children: [ - Text(L10n.of(context)!.tryToSendAgain), - const SizedBox(width: 4), - SvgPicture.asset(ImagePaths.icSend), - ], - ), - ), - ) - : Container(), ] : [ if (ChatInputRowStyle.responsiveUtils.isMobileOrTablet(context)) @@ -172,6 +131,81 @@ class ChatInputRow extends StatelessWidget { } } +class ActionSelectModeWidget extends StatelessWidget { + final ChatController controller; + + const ActionSelectModeWidget({ + super.key, + required this.controller, + }); + + @override + Widget build(BuildContext context) { + return Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (controller.selectedEvents.first + .getDisplayEvent(controller.timeline!) + .status + .isSent) + SizedBox( + height: ChatInputRowStyle.chatInputRowHeight, + child: TextButton( + onPressed: controller.forwardEventsAction, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Icons.keyboard_arrow_left_outlined), + Text(L10n.of(context)!.forward), + ], + ), + ), + ), + if (controller.selectedEvents.length == 1) ...[ + if (controller.selectedEvents.first + .getDisplayEvent(controller.timeline!) + .status + .isSent) ...[ + SizedBox( + height: ChatInputRowStyle.chatInputRowHeight, + child: TextButton( + onPressed: controller.replyAction, + child: Row( + children: [ + Text(L10n.of(context)!.reply), + const Icon(Icons.keyboard_arrow_right), + ], + ), + ), + ), + ] else if (controller.selectedEvents.first + .getDisplayEvent(controller.timeline!) + .status + .isError) ...[ + SizedBox( + height: ChatInputRowStyle.chatInputRowHeight, + child: TextButton( + onPressed: controller.sendAgainAction, + child: Row( + children: [ + Text(L10n.of(context)!.tryToSendAgain), + const SizedBox(width: 4), + SvgPicture.asset(ImagePaths.icSend), + ], + ), + ), + ), + ] else ...[ + const SizedBox.shrink(), + ], + ], + ], + ), + ); + } +} + class _ChatAccountPicker extends StatelessWidget { final ChatController controller; diff --git a/lib/pages/chat/events/message/message.dart b/lib/pages/chat/events/message/message.dart index c0e98cf3e3..69437a9370 100644 --- a/lib/pages/chat/events/message/message.dart +++ b/lib/pages/chat/events/message/message.dart @@ -29,16 +29,26 @@ typedef OnMenuAction = Function( TapDownDetails, ); +typedef OnSwipe = void Function(SwipeDirection); + +typedef OnHover = void Function(bool, Event); + +typedef OnSelect = void Function(Event); + +typedef OnTapAvatar = void Function(Event); + +typedef OnScrollToEventId = void Function(String); + class Message extends StatefulWidget { final Event event; final Event? previousEvent; final Event? nextEvent; final String? markedUnreadLocation; - final void Function(Event)? onSelect; - final void Function(Event)? onAvatarTap; - final void Function(String)? scrollToEventId; - final void Function(SwipeDirection)? onSwipe; - final void Function(bool, Event)? onHover; + final OnSelect? onSelect; + final OnTapAvatar? onAvatarTap; + final OnScrollToEventId? scrollToEventId; + final OnSwipe? onSwipe; + final OnHover? onHover; final ValueNotifier isHoverNotifier; final bool selected; final Timeline timeline; diff --git a/lib/utils/extension/event_status_custom_extension.dart b/lib/utils/extension/event_status_custom_extension.dart new file mode 100644 index 0000000000..5502e4d718 --- /dev/null +++ b/lib/utils/extension/event_status_custom_extension.dart @@ -0,0 +1,7 @@ +import 'package:matrix/matrix.dart'; + +extension EventStatusCustomExtension on EventStatus { + bool get isAvailableToForwardEvent { + return !isError && !isSending; + } +}