import * as React from 'react'; import { gCustomMessageCardEventType, gMessageAttributeTranslate, useChatContext, } from '../../chat'; import { useConfigContext } from '../../config'; import { useI18nContext } from '../../i18n'; import { ChatCustomMessageBody, ChatMessage, ChatMessageChatType, ChatMessageStatus, ChatMessageType, ChatTextMessageBody, } from '../../rename.chat'; import { Services } from '../../services'; import type { BottomSheetEmojiListRef } from '../BottomSheetEmojiList'; import { BottomSheetMenuHeader } from '../BottomSheetMenu/BottomSheetMenuHeader'; import type { ConversationDetailModelType, MessageModel, SystemMessageModel, TimeMessageModel, } from '../ConversationDetail'; import type { EmojiIconItem, PressedComponentEvent } from '../types'; import { InitMenuItemsType } from '../types'; import type { BasicActionsProps } from './types'; import { useCloseMenu } from './useCloseMenu'; export type UseMessageLongPressActionsProps = BasicActionsProps & { /** * Callback notification of copy completion. */ onCopyFinished?: (content: string) => void; /** * Callback notification of quote message for input. */ onQuoteMessageForInput?: (model: MessageModel) => void; /** * Callback notification of edit message for input. */ onEditMessageForInput?: (model: MessageModel) => void; /** * Callback notification of show report message. */ showReportMessage?: (model: MessageModel) => void; /** * Callback notification of delete message. */ onDeleteMessage?: (msg: ChatMessage) => void; /** * Callback notification of recall message. */ onRecallMessage?: (msg: ChatMessage, fromType: 'send' | 'recv') => void; /** * Callback notification of translate message. */ onTranslateMessage?: (model: MessageModel) => void; /** * Callback notification of thread message. */ onThread?: (model: MessageModel) => void; /** * Callback notification of multi selected. */ onClickedMultiSelected?: () => void; /** * Callback notification of forward message. */ onForwardMessage?: (model: MessageModel) => void; /** * Callback notification of pin message. */ onPinMessage?: (model: MessageModel) => void; }; export function useMessageLongPressActions( props: UseMessageLongPressActionsProps ) { const { menuRef, alertRef, onQuoteMessageForInput, onEditMessageForInput, showReportMessage, onDeleteMessage, onRecallMessage, onCopyFinished, onTranslateMessage, onClickedMultiSelected, onForwardMessage, onThread, onInit, onPinMessage, } = props; const { closeMenu } = useCloseMenu({ menuRef }); const { tr } = useI18nContext(); const im = useChatContext(); const { enableTranslate, enableReaction, enableThread, enableMessageQuote, enableMessageForward, enableMessageMultiSelect, enableMessagePin, messageMenuStyle, } = useConfigContext(); const isCardMessage = (msg: ChatMessage) => { if (msg.body.type === ChatMessageType.CUSTOM) { const body = msg.body as ChatCustomMessageBody; if (body.event === gCustomMessageCardEventType) { return true; } } return false; }; const header = ( emojiList: EmojiIconItem[], onFace?: (face: string) => void ) => ( ); const onShowMenu = (params: { id: string; model: SystemMessageModel | TimeMessageModel | MessageModel; emojiList?: EmojiIconItem[]; onFace?: (face: string) => void; convId: string; convType: number; comType: ConversationDetailModelType; event?: PressedComponentEvent; }) => { const { model, emojiList, onFace, convType, comType, event } = params; if (model.modelType !== 'message') { return; } let initItems = [] as InitMenuItemsType[]; const msgModel = model as MessageModel; if (model.modelType === 'message') { if (msgModel.msg.body.type === ChatMessageType.TXT) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_copy'), isHigh: false, icon: 'doc_on_doc', onClicked: () => { closeMenu(() => { const body = msgModel.msg.body as ChatTextMessageBody; Services.cbs.setString(body.content); onCopyFinished?.(body.content); }); }, }); } if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && enableMessageForward === true ) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_forward_message'), isHigh: false, icon: 'arrowshape_right', onClicked: () => { closeMenu(() => { onForwardMessage?.(model as MessageModel); }); }, }); } if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && convType === 1 && enableThread === true && msgModel.thread === undefined && (comType === 'chat' || comType === 'search') ) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_thread'), isHigh: false, icon: 'hashtag_in_bubble_fill', onClicked: () => { closeMenu(() => { onThread?.(model as MessageModel); }); }, }); } if ( msgModel.msg.body.type === ChatMessageType.TXT || msgModel.msg.body.type === ChatMessageType.VOICE || msgModel.msg.body.type === ChatMessageType.IMAGE || msgModel.msg.body.type === ChatMessageType.VIDEO || msgModel.msg.body.type === ChatMessageType.FILE || (msgModel.msg.body.type === ChatMessageType.CUSTOM && isCardMessage(msgModel.msg)) ) { if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && enableMessageQuote === true ) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_replay'), isHigh: false, icon: 'arrowshape_left', onClicked: () => { closeMenu(() => { onQuoteMessageForInput?.(model as MessageModel); }); }, }); } } if ( (msgModel.msg.body.type === ChatMessageType.TXT || msgModel.msg.body.type === ChatMessageType.VOICE || msgModel.msg.body.type === ChatMessageType.IMAGE || msgModel.msg.body.type === ChatMessageType.VIDEO || msgModel.msg.body.type === ChatMessageType.FILE) && comType !== 'thread' ) { if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && msgModel.msg.from === im.userId ) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_recall'), isHigh: false, icon: 'arrow_Uturn_anti_clockwise', onClicked: () => { closeMenu(() => { alertRef.current?.alertWithInit?.({ title: tr( '_uikit_chat_list_long_press_menu_recall_alert_title' ), buttons: [ { text: tr('cancel'), onPress: () => { alertRef.current?.close?.(); }, }, { text: tr('confirm'), isPreferred: true, onPress: () => { alertRef.current?.close?.(); const msgModel = model as MessageModel; onRecallMessage?.(msgModel.msg, 'send'); }, }, ], }); }); }, }); } } if (msgModel.msg.status === ChatMessageStatus.SUCCESS) { if ( msgModel.msg.body.type === ChatMessageType.TXT && msgModel.msg.from === im.userId ) { const textBody = msgModel.msg.body as ChatTextMessageBody; if (textBody.modifyCount === undefined || textBody.modifyCount <= 5) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_edit'), isHigh: false, icon: 'slash_in_rectangle', onClicked: () => { closeMenu(() => { onEditMessageForInput?.(model as MessageModel); }); }, }); } } } if (enableMessageMultiSelect === true) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_multi_select'), isHigh: false, icon: 'check_n_3lines', onClicked: () => { closeMenu(() => { onClickedMultiSelected?.(); }); }, }); } if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && enableMessagePin === true ) { if ( msgModel.msg.body.type === ChatMessageType.TXT && (msgModel.msg.chatType === ChatMessageChatType.GroupChat || msgModel.msg.chatType === ChatMessageChatType.PeerChat) ) { const textBody = msgModel.msg.body as ChatTextMessageBody; if (textBody.modifyCount === undefined || textBody.modifyCount <= 5) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_message_pin'), isHigh: false, icon: 'pin_2', onClicked: () => { closeMenu(() => { onPinMessage?.(model as MessageModel); }); }, }); } } } if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && enableTranslate === true ) { if (msgModel.msg.body.type === ChatMessageType.TXT) { const textBody = msgModel.msg.body as ChatTextMessageBody; if (textBody.modifyCount === undefined || textBody.modifyCount <= 5) { const msg = (model as MessageModel)?.msg; const isTranslated = msg?.attributes?.[gMessageAttributeTranslate]; initItems.push({ name: tr( '_uikit_chat_list_long_press_menu_translate', isTranslated ), isHigh: false, icon: 'a_in_arrows_round', onClicked: () => { closeMenu(() => { onTranslateMessage?.(model as MessageModel); }); }, }); } } } if ( msgModel.msg.status === ChatMessageStatus.SUCCESS && comType !== 'thread' ) { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_report'), isHigh: false, icon: 'envelope', onClicked: () => { closeMenu(() => { showReportMessage?.(msgModel); }); }, }); } if (comType !== 'thread' && comType !== 'create_thread') { initItems.push({ name: tr('_uikit_chat_list_long_press_menu_delete'), isHigh: false, icon: 'trash', onClicked: () => { closeMenu(() => { alertRef.current?.alertWithInit?.({ title: tr( '_uikit_chat_list_long_press_menu_delete_alert_title' ), message: tr( '_uikit_chat_list_long_press_menu_delete_alert_content' ), buttons: [ { text: tr('cancel'), onPress: () => { alertRef.current?.close?.(); }, }, { text: tr('confirm'), isPreferred: true, onPress: () => { alertRef.current?.close?.(); const msgModel = model as MessageModel; onDeleteMessage?.(msgModel.msg); }, }, ], }); }); }, }); } } if (initItems.length === 0) { return; } initItems = onInit ? onInit(initItems) : initItems; menuRef.current?.startShowWithProps?.({ initItems: initItems, onRequestModalClose: closeMenu, layoutType: 'left', hasCancel: false, header: emojiList && enableReaction === true ? header(emojiList, onFace) : undefined, suggestedPosition: messageMenuStyle === 'context' ? { x: event?.pressedX ?? 0, y: event?.pressedY ?? 0, } : undefined, noCoverageArea: messageMenuStyle === 'context' ? { x: event?.componentX ?? 0, y: event?.componentY ?? 0, width: event?.componentWidth ?? 0, height: event?.componentHeight ?? 0, } : undefined, }); }; return { onShowMessageLongPressActions: onShowMenu, }; } export type UseEmojiLongPressActionsProps = { menuRef: React.RefObject; }; export function useEmojiLongPressActionsProps( props: UseEmojiLongPressActionsProps ) { const { menuRef } = props; const closeMenu = React.useCallback(() => { menuRef.current?.startHide?.(); }, [menuRef]); const onShowMenu = React.useCallback( (emojiList: EmojiIconItem[], onFace?: (face: string) => void) => { menuRef.current?.startShowWithProps?.({ onRequestModalClose: closeMenu, emojiList, onFace, }); }, [closeMenu, menuRef] ); return { onShowEmojiLongPressActions: onShowMenu, }; }