300a50b69a
Phase 3 tasks 3-7 (parallel wave): composer/post pipeline on pdsClient/appviewClient with structural+instance blob guards and a golden CID fixture test; chat Convo/EventBus/queries on the dedicated chat client; preferences sugar to SDK actions on the PDS client; remaining state/queries producers (usePostThread unspecced flip, video scoped-token clients, notifications, starter packs, lists) to client.call; UI runtime sweep (AtUri from @atproto/syntax, moderation fns from @bsky.app/sdk/moderation, SDK RichText, ozone reason tokens, guard rewrites via #/types/bsky). Intermediate checkpoint (hooks skipped): ~114 typecheck errors remain in cross-boundary consumer files, resolved by the type-only codemod next. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
132 lines
4.0 KiB
TypeScript
132 lines
4.0 KiB
TypeScript
import {useCallback, useMemo} from 'react'
|
||
import {View} from 'react-native'
|
||
import {type ModerationDecision} from '@bsky.app/sdk/moderation'
|
||
import {Trans, useLingui} from '@lingui/react/macro'
|
||
|
||
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||
import {useProfileBlockMutationQueue} from '#/state/queries/profile'
|
||
import {atoms as a, useTheme} from '#/alf'
|
||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||
import {useDialogControl} from '#/components/Dialog'
|
||
import {BlockedByListDialog} from '#/components/dms/BlockedByListDialog'
|
||
import {LeaveConvoPrompt} from '#/components/dms/LeaveConvoPrompt'
|
||
import {ArrowBoxLeft_Stroke2_Corner0_Rounded as LeaveIcon} from '#/components/icons/ArrowBoxLeft'
|
||
import {
|
||
PersonCheck_Stroke2_Corner0_Rounded as PersonCheckIcon,
|
||
PersonX_Stroke2_Corner0_Rounded as PersonXIcon,
|
||
} from '#/components/icons/Person'
|
||
import {Text} from '#/components/Typography'
|
||
import type * as bsky from '#/types/bsky'
|
||
|
||
export function MessagesListBlockedFooter({
|
||
recipient: initialRecipient,
|
||
convoId,
|
||
moderation,
|
||
isGroup,
|
||
}: {
|
||
recipient: bsky.profile.AnyProfileView
|
||
convoId: string
|
||
moderation: ModerationDecision
|
||
isGroup: boolean
|
||
}) {
|
||
const t = useTheme()
|
||
const {t: l} = useLingui()
|
||
const recipient = useProfileShadow(initialRecipient)
|
||
const [_queueBlock, queueUnblock] = useProfileBlockMutationQueue(recipient)
|
||
|
||
const leaveConvoControl = useDialogControl()
|
||
const blockedByListControl = useDialogControl()
|
||
|
||
const {listBlocks, userBlock} = useMemo(() => {
|
||
const modui = moderation.ui('profileView')
|
||
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,
|
||
}
|
||
}, [moderation])
|
||
|
||
const isBlocking = !!userBlock || !!listBlocks.length
|
||
|
||
const onUnblockPress = useCallback(() => {
|
||
if (listBlocks.length) {
|
||
blockedByListControl.open()
|
||
} else {
|
||
void queueUnblock()
|
||
}
|
||
}, [blockedByListControl, listBlocks, queueUnblock])
|
||
|
||
return (
|
||
<View style={[a.p_md]}>
|
||
<View
|
||
style={[
|
||
a.align_center,
|
||
a.justify_center,
|
||
a.p_lg,
|
||
t.atoms.bg_contrast_50,
|
||
{borderRadius: 40},
|
||
]}>
|
||
<PersonXIcon fill={t.atoms.text.color} size="lg" style={[a.mb_xs]} />
|
||
<Text
|
||
style={[
|
||
a.mb_xs,
|
||
a.text_center,
|
||
a.text_md,
|
||
a.font_semi_bold,
|
||
t.atoms.text,
|
||
]}>
|
||
{isGroup
|
||
? l`You are blocking the chat owner`
|
||
: isBlocking
|
||
? l`You are blocking this person`
|
||
: l`This person is blocking you`}
|
||
</Text>
|
||
<Text
|
||
style={[
|
||
a.text_center,
|
||
a.text_sm,
|
||
a.leading_snug,
|
||
t.atoms.text_contrast_high,
|
||
]}>
|
||
<Trans>You can read chat history but can’t send new messages.</Trans>
|
||
</Text>
|
||
{isBlocking ? (
|
||
<Button
|
||
label={l`Unblock`}
|
||
color="secondary_inverted"
|
||
size="large"
|
||
style={[a.mt_lg, a.w_full]}
|
||
onPress={onUnblockPress}>
|
||
<ButtonIcon icon={PersonCheckIcon} />
|
||
<ButtonText>
|
||
<Trans>Unblock</Trans>
|
||
</ButtonText>
|
||
</Button>
|
||
) : null}
|
||
<Button
|
||
label={l`Leave chat`}
|
||
color="secondary_inverted"
|
||
size="large"
|
||
style={[a.mt_lg, a.w_full]}
|
||
onPress={leaveConvoControl.open}>
|
||
<ButtonIcon icon={LeaveIcon} />
|
||
<ButtonText>
|
||
<Trans>Leave chat</Trans>
|
||
</ButtonText>
|
||
</Button>
|
||
<LeaveConvoPrompt
|
||
control={leaveConvoControl}
|
||
currentScreen="conversation"
|
||
convoId={convoId}
|
||
/>
|
||
<BlockedByListDialog
|
||
control={blockedByListControl}
|
||
listBlocks={listBlocks}
|
||
/>
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|