diff options
Diffstat (limited to 'src/components/dms/ConvoMenu.tsx')
-rw-r--r-- | src/components/dms/ConvoMenu.tsx | 94 |
1 files changed, 83 insertions, 11 deletions
diff --git a/src/components/dms/ConvoMenu.tsx b/src/components/dms/ConvoMenu.tsx index 0a1d3f01c..16e8d98c6 100644 --- a/src/components/dms/ConvoMenu.tsx +++ b/src/components/dms/ConvoMenu.tsx @@ -1,19 +1,27 @@ import React, {useCallback} from 'react' import {Keyboard, Pressable, View} from 'react-native' -import {AppBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api' +import { + AppBskyActorDefs, + ChatBskyConvoDefs, + ModerationDecision, +} from '@atproto/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 {listUriToHref} from '#/lib/strings/url-helpers' +import {Shadow} from '#/state/cache/types' import { useConvoQuery, useMarkAsReadMutation, } from '#/state/queries/messages/conversation' import {useLeaveConvo} from '#/state/queries/messages/leave-conversation' import {useMuteConvo} from '#/state/queries/messages/mute-conversation' +import {useProfileBlockMutationQueue} from '#/state/queries/profile' import * as Toast from '#/view/com/util/Toast' import {atoms as a, useTheme} from '#/alf' +import * as Dialog from '#/components/Dialog' 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' @@ -22,8 +30,10 @@ import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Perso 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 {InlineLinkText} from '#/components/Link' import * as Menu from '#/components/Menu' import * as Prompt from '#/components/Prompt' +import {Text} from '#/components/Typography' import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '../icons/Bubble' let ConvoMenu = ({ @@ -34,22 +44,35 @@ let ConvoMenu = ({ showMarkAsRead, hideTrigger, triggerOpacity, + moderation, }: { convo: ChatBskyConvoDefs.ConvoView - profile: AppBskyActorDefs.ProfileViewBasic - onUpdateConvo?: (convo: ChatBskyConvoDefs.ConvoView) => void + profile: Shadow<AppBskyActorDefs.ProfileViewBasic> control?: Menu.MenuControlProps currentScreen: 'list' | 'conversation' showMarkAsRead?: boolean hideTrigger?: boolean triggerOpacity?: number + moderation: ModerationDecision }): React.ReactNode => { const navigation = useNavigation<NavigationProp>() const {_} = useLingui() const t = useTheme() const leaveConvoControl = Prompt.usePromptControl() const reportControl = Prompt.usePromptControl() + const blockedByListControl = Prompt.usePromptControl() const {mutate: markAsRead} = useMarkAsReadMutation() + const modui = moderation.ui('profileView') + const {listBlocks, userBlock} = React.useMemo(() => { + const blocks = modui.alerts.filter(alert => alert.type === 'blocking') + const listBlocks = blocks.filter(alert => alert.source.type === 'list') + const userBlock = blocks.find(alert => alert.source.type === 'user') + return { + listBlocks, + userBlock, + } + }, [modui]) + const isBlocking = !!userBlock || !!listBlocks.length const {data: convo} = useConvoQuery(initialConvo) @@ -70,6 +93,21 @@ let ConvoMenu = ({ }, }) + const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile) + + const toggleBlock = React.useCallback(() => { + if (listBlocks.length) { + blockedByListControl.open() + return + } + + if (userBlock) { + queueUnblock() + } else { + queueBlock() + } + }, [userBlock, listBlocks, blockedByListControl, queueBlock, queueUnblock]) + const {mutate: leaveConvo} = useLeaveConvo(convo?.id, { onSuccess: () => { if (currentScreen === 'conversation') { @@ -146,18 +184,16 @@ let ConvoMenu = ({ </Menu.Item> </Menu.Group> <Menu.Divider /> - {/* TODO(samuel): implement this */} <Menu.Group> <Menu.Item - label={_(msg`Block account`)} - onPress={() => {}} - disabled> + label={ + isBlocking ? _(msg`Unblock account`) : _(msg`Block account`) + } + onPress={toggleBlock}> <Menu.ItemText> - <Trans>Block account</Trans> + {isBlocking ? _(msg`Unblock account`) : _(msg`Block account`)} </Menu.ItemText> - <Menu.ItemIcon - icon={profile.viewer?.blocking ? PersonCheck : PersonX} - /> + <Menu.ItemIcon icon={isBlocking ? PersonX : PersonCheck} /> </Menu.Item> <Menu.Item label={_(msg`Report conversation`)} @@ -202,6 +238,42 @@ let ConvoMenu = ({ confirmButtonCta={_(msg`I understand`)} onConfirm={noop} /> + + <Prompt.Outer control={blockedByListControl} testID="blockedByListDialog"> + <Prompt.TitleText>{_(msg`User blocked by list`)}</Prompt.TitleText> + + <View style={[a.gap_sm, a.pb_lg]}> + <Text + selectable + style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high]}> + {_( + msg`This account is blocked by one or more of your moderation lists. To unblock, please visit the lists directly and remove this user.`, + )}{' '} + </Text> + + <Text style={[a.text_md, a.leading_snug, t.atoms.text_contrast_high]}> + {_(msg`Lists blocking this user:`)}{' '} + {listBlocks.map((block, i) => + block.source.type === 'list' ? ( + <React.Fragment key={block.source.list.uri}> + {i === 0 ? null : ', '} + <InlineLinkText + to={listUriToHref(block.source.list.uri)} + style={[a.text_md, a.leading_snug]}> + {block.source.list.name} + </InlineLinkText> + </React.Fragment> + ) : null, + )} + </Text> + </View> + + <Prompt.Actions> + <Prompt.Cancel cta={_(msg`I understand`)} /> + </Prompt.Actions> + + <Dialog.Close /> + </Prompt.Outer> </> ) } |