mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {LayoutAnimation, Pressable, View} from 'react-native'
3import * as Clipboard from 'expo-clipboard'
4import {ChatBskyConvoDefs} from '@atproto-labs/api'
5import {msg} from '@lingui/macro'
6import {useLingui} from '@lingui/react'
7
8import {useChat} from 'state/messages'
9import {ConvoStatus} from 'state/messages/convo'
10import {useSession} from 'state/session'
11import * as Toast from '#/view/com/util/Toast'
12import {atoms as a, useTheme} from '#/alf'
13import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid'
14import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
15import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning'
16import * as Menu from '#/components/Menu'
17import * as Prompt from '#/components/Prompt'
18import {usePromptControl} from '#/components/Prompt'
19import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '../icons/Clipboard'
20
21export let MessageMenu = ({
22 message,
23 control,
24 hideTrigger,
25 triggerOpacity,
26}: {
27 hideTrigger?: boolean
28 triggerOpacity?: number
29 onTriggerPress?: () => void
30 message: ChatBskyConvoDefs.MessageView
31 control: Menu.MenuControlProps
32}): React.ReactNode => {
33 const {_} = useLingui()
34 const t = useTheme()
35 const {currentAccount} = useSession()
36 const chat = useChat()
37 const deleteControl = usePromptControl()
38 const retryDeleteControl = usePromptControl()
39
40 const isFromSelf = message.sender?.did === currentAccount?.did
41
42 const onCopyPostText = React.useCallback(() => {
43 // use when we have rich text
44 // const str = richTextToString(richText, true)
45
46 Clipboard.setStringAsync(message.text)
47 Toast.show(_(msg`Copied to clipboard`))
48 }, [_, message.text])
49
50 const onDelete = React.useCallback(() => {
51 if (chat.status !== ConvoStatus.Ready) return
52
53 LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
54 chat
55 .deleteMessage(message.id)
56 .then(() => Toast.show(_(msg`Message deleted`)))
57 .catch(() => retryDeleteControl.open())
58 }, [_, chat, message.id, retryDeleteControl])
59
60 const onReport = React.useCallback(() => {
61 // TODO report the message
62 }, [])
63
64 return (
65 <>
66 <Menu.Root control={control}>
67 {!hideTrigger && (
68 <View style={{opacity: triggerOpacity}}>
69 <Menu.Trigger label={_(msg`Chat settings`)}>
70 {({props, state}) => (
71 <Pressable
72 {...props}
73 style={[
74 a.p_sm,
75 a.rounded_full,
76 (state.hovered || state.pressed) && t.atoms.bg_contrast_25,
77 ]}>
78 <DotsHorizontal size="sm" style={t.atoms.text} />
79 </Pressable>
80 )}
81 </Menu.Trigger>
82 </View>
83 )}
84
85 <Menu.Outer>
86 <Menu.Group>
87 <Menu.Item
88 testID="messageDropdownCopyBtn"
89 label={_(msg`Copy message text`)}
90 onPress={onCopyPostText}>
91 <Menu.ItemText>{_(msg`Copy message text`)}</Menu.ItemText>
92 <Menu.ItemIcon icon={ClipboardIcon} position="right" />
93 </Menu.Item>
94 </Menu.Group>
95 <Menu.Divider />
96 <Menu.Group>
97 <Menu.Item
98 testID="messageDropdownDeleteBtn"
99 label={_(msg`Delete message for me`)}
100 onPress={deleteControl.open}>
101 <Menu.ItemText>{_(msg`Delete for me`)}</Menu.ItemText>
102 <Menu.ItemIcon icon={Trash} position="right" />
103 </Menu.Item>
104 {!isFromSelf && (
105 <Menu.Item
106 testID="messageDropdownReportBtn"
107 label={_(msg`Report message`)}
108 onPress={onReport}>
109 <Menu.ItemText>{_(msg`Report`)}</Menu.ItemText>
110 <Menu.ItemIcon icon={Warning} position="right" />
111 </Menu.Item>
112 )}
113 </Menu.Group>
114 </Menu.Outer>
115 </Menu.Root>
116
117 <Prompt.Basic
118 control={deleteControl}
119 title={_(msg`Delete message`)}
120 description={_(
121 msg`Are you sure you want to delete this message? The message will be deleted for you, but not for other participants.`,
122 )}
123 confirmButtonCta={_(msg`Delete`)}
124 confirmButtonColor="negative"
125 onConfirm={onDelete}
126 />
127
128 <Prompt.Basic
129 control={retryDeleteControl}
130 title={_(msg`Failed to delete message`)}
131 description={_(
132 msg`An error occurred while trying to delete the message. Please try again.`,
133 )}
134 confirmButtonCta={_(msg`Retry`)}
135 confirmButtonColor="negative"
136 onConfirm={onDelete}
137 />
138 </>
139 )
140}
141MessageMenu = React.memo(MessageMenu)