Skip to content

Commit

Permalink
TW-529: Hide/show context menu and handle when click on item
Browse files Browse the repository at this point in the history
  • Loading branch information
nqhhdev committed Aug 29, 2023
1 parent 8d50088 commit b8f684c
Show file tree
Hide file tree
Showing 6 changed files with 705 additions and 502 deletions.
5 changes: 4 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2682,5 +2682,8 @@
"adminPanel": "Admin Panel",
"rejectInvite" : "No thanks, delete",
"acceptInvite" : "Yes please, join",
"askToInvite": " wants you to join this chat. What do you say?"
"askToInvite": " wants you to join this chat. What do you say?",
"select" : "Select",
"copyMessageText" : "Copy message text",
"pinMessage" : "Pin message"
}
150 changes: 149 additions & 1 deletion lib/pages/chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import 'package:fluffychat/domain/model/download_file/download_file_for_preview_
import 'package:fluffychat/domain/model/preview_file/document_uti.dart';
import 'package:fluffychat/domain/model/preview_file/supported_preview_file_types.dart';
import 'package:fluffychat/domain/usecase/download_file_for_preview_interactor.dart';
import 'package:fluffychat/pages/chat/chat_horizontal_action_menu.dart';
import 'package:fluffychat/pages/chat/chat_view.dart';
import 'package:fluffychat/pages/chat/context_item_chat_action.dart';
import 'package:fluffychat/pages/chat/dialog_accept_invite_widget.dart';
import 'package:fluffychat/pages/chat/event_info_dialog.dart';
import 'package:fluffychat/pages/chat/recording_dialog.dart';
Expand All @@ -22,6 +24,7 @@ import 'package:fluffychat/presentation/mixins/media_picker_mixin.dart';
import 'package:fluffychat/presentation/mixins/send_files_mixin.dart';
import 'package:fluffychat/presentation/model/forward/forward_argument.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/utils/extension/build_context_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/ios_badge_client_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/network_connection_service.dart';
Expand All @@ -30,6 +33,8 @@ import 'package:fluffychat/utils/permission_service.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/utils/responsive/responsive_utils.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:fluffychat/widgets/mixins/popup_context_menu_action_mixin.dart';
import 'package:fluffychat/widgets/mixins/popup_menu_widget_mixin.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -67,7 +72,12 @@ class Chat extends StatefulWidget {
}

class ChatController extends State<Chat>
with CommonMediaPickerMixin, MediaPickerMixin, SendFilesMixin {
with
CommonMediaPickerMixin,
MediaPickerMixin,
SendFilesMixin,
PopupContextMenuActionMixin,
PopupMenuWidgetMixin {
final NetworkConnectionService networkConnectionService =
getIt.get<NetworkConnectionService>();

Expand All @@ -85,6 +95,7 @@ class ChatController extends State<Chat>

final AutoScrollController scrollController = AutoScrollController();
final AutoScrollController forwardListController = AutoScrollController();
final ValueNotifier<String?> focusHover = ValueNotifier(null);

FocusNode inputFocus = FocusNode();

Expand Down Expand Up @@ -1286,6 +1297,143 @@ class ChatController extends State<Chat>
);
}

void onHover(bool isHovered, int index, Event event) {
if (timeline!.events[index - 1].eventId == event.eventId &&
!responsive.isMobile(context) &&
!selectMode) {
focusHover.value = isHovered ? event.eventId : null;
}
}

List<ContextMenuItemChatAction> listHorizontalActionMenuBuilder() {
final listAction = [
ChatHorizontalActionMenu.reply,
ChatHorizontalActionMenu.forward,
ChatHorizontalActionMenu.more,
];
return listAction
.map(
(action) => ContextMenuItemChatAction(
action,
action.getContextMenuItemState(),
),
)
.toList();
}

void handleHorizontalActionMenu(
BuildContext context,
ChatHorizontalActionMenu actions,
Event event,
) {
switch (actions) {
case ChatHorizontalActionMenu.reply:
replyAction(replyTo: event);
break;
case ChatHorizontalActionMenu.forward:
onSelectMessage(event);
forwardEventsAction();
break;
case ChatHorizontalActionMenu.more:
handleContextMenuAction(context, event);
break;
}
}

List<PopupMenuEntry> _popupMenuActionTile(
BuildContext context,
Event event,
) {
return [
_buildSelectPopupMenuItem(context, event),
_buildCopyMessagePopupMenuItem(context, event),
_buildPinMessagePopupMenuItem(context, event),
_buildForwardPopupMenuItem(context, event),
];
}

PopupMenuEntry _buildSelectPopupMenuItem(
BuildContext context,
Event event,
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
context,
L10n.of(context)!.select,
iconAction: Icons.check_circle_outline,
onCallbackAction: () {
onSelectMessage(event);
},
),
);
}

PopupMenuEntry _buildCopyMessagePopupMenuItem(
BuildContext context,
Event event,
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
context,
L10n.of(context)!.copyMessageText,
iconAction: Icons.content_copy,
onCallbackAction: () {
onSelectMessage(event);
copyEventsAction();
},
),
);
}

PopupMenuEntry _buildPinMessagePopupMenuItem(
BuildContext context,
Event event,
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
context,
L10n.of(context)!.pinMessage,
iconAction: Icons.push_pin,
onCallbackAction: () {
onSelectMessage(event);
pinEvent();
},
),
);
}

PopupMenuEntry _buildForwardPopupMenuItem(
BuildContext context,
Event event,
) {
return PopupMenuItem(
padding: EdgeInsets.zero,
child: popupItem(
context,
L10n.of(context)!.forward,
iconAction: Icons.shortcut,
onCallbackAction: () {
onSelectMessage(event);
forwardEventsAction();
},
),
);
}

void handleContextMenuAction(
BuildContext context,
Event event,
) {
openPopupMenuAction(
context,
context.getCurrentRelativeRectOfWidget(),
_popupMenuActionTile(context, event),
);
}

@override
Widget build(BuildContext context) {
return ChatView(this, key: widget.key);
Expand Down
16 changes: 11 additions & 5 deletions lib/pages/chat/chat_event_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ class ChatEventList extends StatelessWidget {
controller: controller.scrollController,
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int i) {
(BuildContext context, int index) {
// Footer to display typing indicator and read receipts:
if (i == 0) {
if (index == 0) {
return const SizedBox.shrink();
}
// Request history button or progress indicator:
if (i == controller.timeline!.events.length + 1) {
if (index == controller.timeline!.events.length + 1) {
if (controller.timeline!.isRequestingHistory) {
return const Center(
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
Expand All @@ -88,12 +88,12 @@ class ChatEventList extends StatelessWidget {
}

// The message at this index:
final currentEventIndex = i - 1;
final currentEventIndex = index - 1;
final event = controller.timeline!.events[currentEventIndex];
final previousEvent = currentEventIndex > 0
? controller.timeline!.events[currentEventIndex - 1]
: null;
final nextEvent = i < controller.timeline!.events.length
final nextEvent = index < controller.timeline!.events.length
? controller.timeline!.events[currentEventIndex + 1]
: null;
return AutoScrollTag(
Expand Down Expand Up @@ -125,6 +125,12 @@ class ChatEventList extends StatelessWidget {
previousEvent: previousEvent,
nextEvent: nextEvent,
controller: controller,
onHover: (isHover, event) =>
controller.onHover(isHover, index, event),
isHover: controller.focusHover,
listHorizontalActionMenu:
controller.listHorizontalActionMenuBuilder(),
onMenuAction: controller.handleHorizontalActionMenu,
)
: Container(),
);
Expand Down
Loading

0 comments on commit b8f684c

Please sign in to comment.