Skip to content

Commit

Permalink
[🐴] Block Info (#4068)
Browse files Browse the repository at this point in the history
* get the damn thing in there 😮‍💨

* more cleanup and little fixes

another nit

nit

small annoyance

add a comment

only use `scrollTo` when necessary

remove now unnecessary styles

* move padding out

* add unblock function

* rm need for moderationpts

* ?

* ??

* extract leaveconvoprompt

* move `setHasScrolled` to `onContentSizeChanged`

* account for block footer

* wrap up

nit

make sure recipient is loaded before showing

refactor to hide chat input

typo squigglie

add report dialog

finalize delete

implement custom animation

add configurable replace animation

add leave convo to block options

* correct functionality for report

* moev component to another file

* maybe...

* fix chat item

* improve

* remove unused gtmobile

* nit

* more cleanup

* more cleanup

* fix merge

* fix header

* few more changes

* nit

* remove old
  • Loading branch information
haileyok authored May 17, 2024
1 parent 1b47ea7 commit d02e088
Show file tree
Hide file tree
Showing 13 changed files with 600 additions and 281 deletions.
5 changes: 4 additions & 1 deletion src/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,10 @@ function MessagesTabNavigator() {
<MessagesTab.Screen
name="Messages"
getComponent={() => MessagesScreen}
options={{requireAuth: true}}
options={({route}) => ({
requireAuth: true,
animationTypeForReplace: route.params?.animation ?? 'push',
})}
/>
{commonScreens(MessagesTab as typeof HomeTab)}
</MessagesTab.Navigator>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export function Basic({
confirmButtonCta,
onConfirm,
confirmButtonColor,
showCancel = true,
}: React.PropsWithChildren<{
control: Dialog.DialogOuterProps['control']
title: string
Expand All @@ -187,6 +188,7 @@ export function Basic({
*/
onConfirm: () => void
confirmButtonColor?: ButtonColor
showCancel?: boolean
}>) {
return (
<Outer control={control} testID="confirmModal">
Expand All @@ -199,7 +201,7 @@ export function Basic({
color={confirmButtonColor}
testID="confirmBtn"
/>
<Cancel cta={cancelButtonCta} />
{showCancel && <Cancel cta={cancelButtonCta} />}
</Actions>
</Outer>
)
Expand Down
62 changes: 62 additions & 0 deletions src/components/dms/BlockedByListDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react'
import {View} from 'react-native'
import {ModerationCause} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'

import {listUriToHref} from 'lib/strings/url-helpers'
import {atoms as a, useTheme} from '#/alf'
import * as Dialog from '#/components/Dialog'
import {DialogControlProps} from '#/components/Dialog'
import {InlineLinkText} from '#/components/Link'
import * as Prompt from '#/components/Prompt'
import {Text} from '#/components/Typography'

export function BlockedByListDialog({
control,
listBlocks,
}: {
control: DialogControlProps
listBlocks: ModerationCause[]
}) {
const {_} = useLingui()
const t = useTheme()

return (
<Prompt.Outer control={control} 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.Action cta={_(msg`I understand`)} onPress={() => {}} />
</Prompt.Actions>

<Dialog.Close />
</Prompt.Outer>
)
}
104 changes: 19 additions & 85 deletions src/components/dms/ConvoMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ import {Keyboard, Pressable, View} from 'react-native'
import {
AppBskyActorDefs,
ChatBskyConvoDefs,
ModerationDecision,
ModerationCause,
} 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 {BlockedByListDialog} from '#/components/dms/BlockedByListDialog'
import {LeaveConvoPrompt} from '#/components/dms/LeaveConvoPrompt'
import {ReportConversationPrompt} from '#/components/dms/ReportConversationPrompt'
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'
Expand All @@ -30,10 +30,8 @@ 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 = ({
Expand All @@ -44,7 +42,7 @@ let ConvoMenu = ({
showMarkAsRead,
hideTrigger,
triggerOpacity,
moderation,
blockInfo,
}: {
convo: ChatBskyConvoDefs.ConvoView
profile: Shadow<AppBskyActorDefs.ProfileViewBasic>
Expand All @@ -53,7 +51,10 @@ let ConvoMenu = ({
showMarkAsRead?: boolean
hideTrigger?: boolean
triggerOpacity?: number
moderation: ModerationDecision
blockInfo: {
listBlocks: ModerationCause[]
userBlock?: ModerationCause
}
}): React.ReactNode => {
const navigation = useNavigation<NavigationProp>()
const {_} = useLingui()
Expand All @@ -62,17 +63,9 @@ let ConvoMenu = ({
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 {listBlocks, userBlock} = blockInfo
const isBlocking = userBlock || !!listBlocks.length

const {data: convo} = useConvoQuery(initialConvo)

Expand Down Expand Up @@ -108,17 +101,6 @@ let ConvoMenu = ({
}
}, [userBlock, listBlocks, blockedByListControl, queueBlock, queueUnblock])

const {mutate: leaveConvo} = useLeaveConvo(convo?.id, {
onSuccess: () => {
if (currentScreen === 'conversation') {
navigation.replace('Messages')
}
},
onError: () => {
Toast.show(_(msg`Could not leave chat`))
},
})

return (
<>
<Menu.Root control={control}>
Expand Down Expand Up @@ -218,67 +200,19 @@ let ConvoMenu = ({
</Menu.Outer>
</Menu.Root>

<Prompt.Basic
<LeaveConvoPrompt
control={leaveConvoControl}
title={_(msg`Leave conversation`)}
description={_(
msg`Are you sure you want to leave this conversation? Your messages will be deleted for you, but not for the other participant.`,
)}
confirmButtonCta={_(msg`Leave`)}
confirmButtonColor="negative"
onConfirm={() => leaveConvo()}
convoId={convo.id}
currentScreen={currentScreen}
/>

<Prompt.Basic
control={reportControl}
title={_(msg`Report conversation`)}
description={_(
msg`To report a conversation, please report one of its messages via the conversation screen. This lets our moderators understand the context of your issue.`,
)}
confirmButtonCta={_(msg`I understand`)}
onConfirm={noop}
<ReportConversationPrompt control={reportControl} />
<BlockedByListDialog
control={blockedByListControl}
listBlocks={listBlocks}
/>

<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>
</>
)
}
ConvoMenu = React.memo(ConvoMenu)

export {ConvoMenu}

function noop() {}
55 changes: 55 additions & 0 deletions src/components/dms/LeaveConvoPrompt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'

import {NavigationProp} from 'lib/routes/types'
import {isNative} from 'platform/detection'
import {useLeaveConvo} from 'state/queries/messages/leave-conversation'
import * as Toast from 'view/com/util/Toast'
import {DialogOuterProps} from '#/components/Dialog'
import * as Prompt from '#/components/Prompt'

export function LeaveConvoPrompt({
control,
convoId,
currentScreen,
}: {
control: DialogOuterProps['control']
convoId: string
currentScreen: 'list' | 'conversation'
}) {
const {_} = useLingui()
const navigation = useNavigation<NavigationProp>()

const {mutate: leaveConvo} = useLeaveConvo(convoId, {
onSuccess: () => {
if (currentScreen === 'conversation') {
navigation.replace(
'Messages',
isNative
? {
animation: 'pop',
}
: {},
)
}
},
onError: () => {
Toast.show(_(msg`Could not leave chat`))
},
})

return (
<Prompt.Basic
control={control}
title={_(msg`Leave conversation`)}
description={_(
msg`Are you sure you want to leave this conversation? Your messages will be deleted for you, but not for the other participant.`,
)}
confirmButtonCta={_(msg`Leave`)}
confirmButtonColor="negative"
onConfirm={leaveConvo}
/>
)
}
2 changes: 1 addition & 1 deletion src/components/dms/MessageItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ let MessageItem = ({
}, [message.text, message.facets])

return (
<View>
<View style={[isFromSelf ? a.mr_md : a.ml_md]}>
<ActionsWrapper isFromSelf={isFromSelf} message={message}>
<View
style={[
Expand Down
Loading

0 comments on commit d02e088

Please sign in to comment.