diff --git a/src/components/dms/MessageMenu.tsx b/src/components/dms/MessageMenu.tsx new file mode 100644 index 0000000000..0e267159a7 --- /dev/null +++ b/src/components/dms/MessageMenu.tsx @@ -0,0 +1,173 @@ +import React from 'react' +import {Pressable} from 'react-native' +import {AppBskyActorDefs} from '@atproto/api' +import {ChatBskyConvoDefs} from '@atproto-labs/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useNavigation} from '@react-navigation/native' + +import {NavigationProp} from '#/lib/routes/types' +import {useLeaveConvo} from '#/state/queries/messages/leave-conversation' +import { + useMuteConvo, + useUnmuteConvo, +} from '#/state/queries/messages/mute-conversation' +import * as Toast from '#/view/com/util/Toast' +import {atoms as a, useTheme} from '#/alf' +import {ArrowBoxLeft_Stroke2_Corner0_Rounded as ArrowBoxLeft} from '#/components/icons/ArrowBoxLeft' +import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid' +import {Flag_Stroke2_Corner0_Rounded as Flag} from '#/components/icons/Flag' +import {Mute_Stroke2_Corner0_Rounded as Mute} from '#/components/icons/Mute' +import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person' +import {PersonCheck_Stroke2_Corner0_Rounded as PersonCheck} from '#/components/icons/PersonCheck' +import {PersonX_Stroke2_Corner0_Rounded as PersonX} from '#/components/icons/PersonX' +import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker' +import * as Menu from '#/components/Menu' +import * as Prompt from '#/components/Prompt' + +let ConvoMenu = ({ + convo, + profile, + onUpdateConvo, + control, + hideTrigger, +}: { + convo: ChatBskyConvoDefs.ConvoView + profile: AppBskyActorDefs.ProfileViewBasic + onUpdateConvo?: (convo: ChatBskyConvoDefs.ConvoView) => void + control?: Menu.MenuControlProps + hideTrigger?: boolean +}): React.ReactNode => { + const navigation = useNavigation() + const {_} = useLingui() + const t = useTheme() + const leaveConvoControl = Prompt.usePromptControl() + + const onNavigateToProfile = useCallback(() => { + navigation.navigate('Profile', {name: profile.did}) + }, [navigation, profile.did]) + + const {mutate: muteConvo} = useMuteConvo(convo.id, { + onSuccess: data => { + onUpdateConvo?.(data.convo) + Toast.show(_(msg`Chat muted`)) + }, + onError: () => { + Toast.show(_(msg`Could not mute chat`)) + }, + }) + + const {mutate: unmuteConvo} = useUnmuteConvo(convo.id, { + onSuccess: data => { + onUpdateConvo?.(data.convo) + Toast.show(_(msg`Chat unmuted`)) + }, + onError: () => { + Toast.show(_(msg`Could not unmute chat`)) + }, + }) + + const {mutate: leaveConvo} = useLeaveConvo(convo.id, { + onSuccess: () => { + navigation.popToTop() + }, + onError: () => { + Toast.show(_(msg`Could not leave chat`)) + }, + }) + + return ( + <> + + {!hideTrigger && ( + + {({props, state}) => ( + + + + )} + + )} + + + + + Go to profile + + + + (convo?.muted ? unmuteConvo() : muteConvo())}> + + {convo?.muted ? ( + Unmute notifications + ) : ( + Mute notifications + )} + + + + + {/* TODO(samuel): implement these */} + + {}} + disabled> + + Block account + + + + {}} + disabled> + + Report account + + + + + + + + Leave conversation + + + + + + + + leaveConvo()} + /> + + ) +} +ConvoMenu = React.memo(ConvoMenu) + +export {ConvoMenu} diff --git a/src/screens/Messages/Conversation/MessageItem.tsx b/src/screens/Messages/Conversation/MessageItem.tsx index ba10978e8b..4ffdae13ec 100644 --- a/src/screens/Messages/Conversation/MessageItem.tsx +++ b/src/screens/Messages/Conversation/MessageItem.tsx @@ -1,14 +1,20 @@ import React, {useCallback, useMemo} from 'react' -import {StyleProp, TextStyle, View} from 'react-native' +import {Pressable, StyleProp, TextStyle, View} from 'react-native' import {ChatBskyConvoDefs} from '@atproto-labs/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useSession} from '#/state/session' +import {useHaptics} from 'lib/haptics' +import {isNative, isWeb} from 'platform/detection' import {TimeElapsed} from '#/view/com/util/TimeElapsed' import {atoms as a, useTheme} from '#/alf' import {Text} from '#/components/Typography' +function onPressPlaceholder() { + // Placeholder onPress function +} + export function MessageItem({ item, next, @@ -21,6 +27,7 @@ export function MessageItem({ }) { const t = useTheme() const {currentAccount} = useSession() + const playHaptic = useHaptics() const isFromSelf = item.sender?.did === currentAccount?.did @@ -48,8 +55,19 @@ export function MessageItem({ return true }, [item, next, isFromSelf, isNextFromSelf]) + const onOpenMenu = React.useCallback(() => { + if (isNative) { + playHaptic() + } + + // Open menu + }, [playHaptic]) + return ( - + - + ) }