diff --git a/web/utils/tooltip-utils.js b/web/utils/tooltip-utils.js --- a/web/utils/tooltip-utils.js +++ b/web/utils/tooltip-utils.js @@ -9,7 +9,7 @@ threadHasPermission, useSidebarExistsOrCanBeCreated, } from 'lib/shared/thread-utils'; -import { isComposableMessageType } from 'lib/types/message-types'; +import { isComposableMessageType, messageTypes } from 'lib/types/message-types'; import type { ThreadInfo } from 'lib/types/thread-types'; import { threadPermissions } from 'lib/types/thread-types'; import { longAbsoluteDate } from 'lib/utils/date-utils'; @@ -29,6 +29,7 @@ useOnClickPendingSidebar, useOnClickThread, } from '../selectors/thread-selectors'; +import SWMansionIcon from '../SWMansionIcon.react'; import { calculateMaxTextWidth } from '../utils/text-utils'; export const tooltipPositions = Object.freeze({ @@ -410,16 +411,37 @@ }, [addReply, item.messageInfo.type, messageInfo, threadInfo]); } +function useMessageCopyAction( + item: ChatMessageInfoItem, +): ?MessageTooltipAction { + const { messageInfo } = item; + return React.useMemo(() => { + if (messageInfo.type !== messageTypes.TEXT) { + return null; + } + const buttonContent = ; + const onClick = async () => { + await navigator.clipboard.writeText(messageInfo.text); + }; + return { + actionButtonContent: buttonContent, + onClick, + label: 'Copy', + }; + }, [messageInfo]); +} + function useMessageTooltipActions( item: ChatMessageInfoItem, threadInfo: ThreadInfo, ): $ReadOnlyArray { const sidebarAction = useMessageTooltipSidebarAction(item, threadInfo); const replyAction = useMessageTooltipReplyAction(item, threadInfo); - return React.useMemo(() => [replyAction, sidebarAction].filter(Boolean), [ - replyAction, - sidebarAction, - ]); + const copyAction = useMessageCopyAction(item); + return React.useMemo( + () => [replyAction, sidebarAction, copyAction].filter(Boolean), + [replyAction, sidebarAction, copyAction], + ); } type UseMessageTooltipArgs = {