From c4785ef96e13d02b217dce4e777269c0e895507d Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 21 Mar 2025 18:29:14 +0200 Subject: New `ContextMenu` menu type for DM messages (#8014) * get context menu somewhat working ish * take screenshot rather than double rendering * get animations somewhat working * get transform animation working * rm log * upwards safe area * get working on android * get android working once and for all * fix positioning on both platforms * use dark blur on ios always, fix dark mode * allow closing with hardware back press * try and fix type error * add note about ts-ignore * round post * add image capture error handling * extract magic numbers * set explicit embed width, rm top margin * Message embed width tweaks * Format * fix position of embeds * same as above for web --------- Co-authored-by: Eric Bailey --- src/components/dms/MessageContextMenu.tsx | 151 ++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/components/dms/MessageContextMenu.tsx (limited to 'src/components/dms/MessageContextMenu.tsx') diff --git a/src/components/dms/MessageContextMenu.tsx b/src/components/dms/MessageContextMenu.tsx new file mode 100644 index 000000000..b5542690f --- /dev/null +++ b/src/components/dms/MessageContextMenu.tsx @@ -0,0 +1,151 @@ +import React from 'react' +import {LayoutAnimation} from 'react-native' +import * as Clipboard from 'expo-clipboard' +import {ChatBskyConvoDefs, RichText} from '@atproto/api' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {useOpenLink} from '#/lib/hooks/useOpenLink' +import {richTextToString} from '#/lib/strings/rich-text-helpers' +import {getTranslatorLink} from '#/locale/helpers' +import {useConvoActive} from '#/state/messages/convo' +import {useLanguagePrefs} from '#/state/preferences' +import {useSession} from '#/state/session' +import * as Toast from '#/view/com/util/Toast' +import * as ContextMenu from '#/components/ContextMenu' +import {TriggerProps} from '#/components/ContextMenu/types' +import {ReportDialog} from '#/components/dms/ReportDialog' +import {BubbleQuestion_Stroke2_Corner0_Rounded as Translate} from '#/components/icons/Bubble' +import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard' +import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash' +import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning' +import * as Prompt from '#/components/Prompt' +import {usePromptControl} from '#/components/Prompt' + +export let MessageContextMenu = ({ + message, + children, +}: { + message: ChatBskyConvoDefs.MessageView + children: TriggerProps['children'] +}): React.ReactNode => { + const {_} = useLingui() + const {currentAccount} = useSession() + const convo = useConvoActive() + const deleteControl = usePromptControl() + const reportControl = usePromptControl() + const langPrefs = useLanguagePrefs() + const openLink = useOpenLink() + + const isFromSelf = message.sender?.did === currentAccount?.did + + const onCopyMessage = React.useCallback(() => { + const str = richTextToString( + new RichText({ + text: message.text, + facets: message.facets, + }), + true, + ) + + Clipboard.setStringAsync(str) + Toast.show(_(msg`Copied to clipboard`), 'clipboard-check') + }, [_, message.text, message.facets]) + + const onPressTranslateMessage = React.useCallback(() => { + const translatorUrl = getTranslatorLink( + message.text, + langPrefs.primaryLanguage, + ) + openLink(translatorUrl, true) + }, [langPrefs.primaryLanguage, message.text, openLink]) + + const onDelete = React.useCallback(() => { + LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) + convo + .deleteMessage(message.id) + .then(() => + Toast.show(_(msg({message: 'Message deleted', context: 'toast'}))), + ) + .catch(() => Toast.show(_(msg`Failed to delete message`))) + }, [_, convo, message.id]) + + const sender = convo.convo.members.find( + member => member.did === message.sender.did, + ) + + return ( + <> + + + {children} + + + + {message.text.length > 0 && ( + <> + + {_(msg`Translate`)} + + + + + {_(msg`Copy message text`)} + + + + + + )} + deleteControl.open()}> + {_(msg`Delete for me`)} + + + {!isFromSelf && ( + reportControl.open()}> + {_(msg`Report`)} + + + )} + + + + + + + + ) +} +MessageContextMenu = React.memo(MessageContextMenu) -- cgit 1.4.1