Collapse label appeal flow into ModerationDetailsDialog
Labels on your own posts previously rendered twice: once as normal label chips and again as an ominous "1 content label" pill whose only purpose was reaching the appeal dialog. Move the Appeal button into ModerationDetailsDialog (shown only when the label targets your own account or content and was not self-applied), extract AppealForm into its own module, and remove the redundant per-post pill. The account-level pill on the profile header is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import {useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type ComAtprotoLabelDefs, ToolsOzoneReportDefs} from '@atproto/api'
|
||||
import {XRPCError} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useMutation} from '@tanstack/react-query'
|
||||
|
||||
import {useLabelSubject} from '#/lib/moderation'
|
||||
import {useLabelInfo} from '#/lib/moderation/useLabelInfo'
|
||||
import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {atoms as a, useBreakpoints} from '#/alf'
|
||||
import {Admonition} from '#/components/Admonition'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_ANDROID} from '#/env'
|
||||
|
||||
export function AppealForm({
|
||||
label,
|
||||
control,
|
||||
onPressBack,
|
||||
}: {
|
||||
label: ComAtprotoLabelDefs.Label
|
||||
control: Dialog.DialogOuterProps['control']
|
||||
onPressBack: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {labeler, strings} = useLabelInfo(label)
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const [details, setDetails] = useState('')
|
||||
const {subject} = useLabelSubject({label})
|
||||
const isAccountReport = 'did' in subject
|
||||
const agent = useAgent()
|
||||
const sourceName = labeler
|
||||
? sanitizeHandle(labeler.creator.handle, '@')
|
||||
: label.src
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const {mutate, isPending} = useMutation({
|
||||
mutationFn: async () => {
|
||||
const $type = !isAccountReport
|
||||
? 'com.atproto.repo.strongRef'
|
||||
: 'com.atproto.admin.defs#repoRef'
|
||||
await agent.createModerationReport(
|
||||
{
|
||||
reasonType: ToolsOzoneReportDefs.REASONAPPEAL,
|
||||
subject: {
|
||||
$type,
|
||||
...subject,
|
||||
},
|
||||
reason: details,
|
||||
},
|
||||
{
|
||||
encoding: 'application/json',
|
||||
headers: {
|
||||
'atproto-proxy': `${label.src}#atproto_labeler`,
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
onError: err => {
|
||||
if (err instanceof XRPCError && err.error === 'AlreadyAppealed') {
|
||||
setError(
|
||||
_(
|
||||
msg`You've already appealed this label and it's being reviewed by our moderation team.`,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
setError(_(msg`Failed to submit appeal, please try again.`))
|
||||
}
|
||||
logger.error('Failed to submit label appeal', {message: err})
|
||||
},
|
||||
onSuccess: () => {
|
||||
control.close()
|
||||
Toast.show(_(msg({message: 'Appeal submitted', context: 'toast'})))
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = () => mutate()
|
||||
|
||||
return (
|
||||
<>
|
||||
<View>
|
||||
<Text style={[a.text_2xl, a.font_semi_bold, a.pb_xs, a.leading_tight]}>
|
||||
<Trans>Appeal "{strings.name}" label</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_md, a.leading_snug]}>
|
||||
<Trans>
|
||||
This appeal will be sent to{' '}
|
||||
<InlineLinkText
|
||||
label={sourceName}
|
||||
to={makeProfileLink(
|
||||
labeler ? labeler.creator : {did: label.src, handle: ''},
|
||||
)}
|
||||
onPress={() => control.close()}
|
||||
style={[a.text_md, a.leading_snug]}>
|
||||
{sourceName}
|
||||
</InlineLinkText>
|
||||
.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
{error && (
|
||||
<Admonition type="error" style={[a.mt_sm]}>
|
||||
{error}
|
||||
</Admonition>
|
||||
)}
|
||||
<View style={[a.my_md]}>
|
||||
<Dialog.Input
|
||||
label={_(msg`Text input field`)}
|
||||
placeholder={_(
|
||||
msg`Please explain why you think this label was incorrectly applied by ${
|
||||
labeler ? sanitizeHandle(labeler.creator.handle, '@') : label.src
|
||||
}`,
|
||||
)}
|
||||
value={details}
|
||||
onChangeText={setDetails}
|
||||
autoFocus={true}
|
||||
numberOfLines={3}
|
||||
multiline
|
||||
maxLength={300}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={
|
||||
gtMobile
|
||||
? [a.flex_row, a.justify_between]
|
||||
: [{flexDirection: 'column-reverse'}, a.gap_sm]
|
||||
}>
|
||||
<Button
|
||||
testID="backBtn"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="large"
|
||||
onPress={onPressBack}
|
||||
label={_(msg`Back`)}>
|
||||
<ButtonText>{_(msg`Back`)}</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
testID="submitBtn"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={onSubmit}
|
||||
label={_(msg`Submit`)}>
|
||||
<ButtonText>{_(msg`Submit`)}</ButtonText>
|
||||
{isPending && <ButtonIcon icon={Loader} />}
|
||||
</Button>
|
||||
</View>
|
||||
{IS_ANDROID && <View style={{height: 300}} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {type StyleProp, View, type ViewStyle} from 'react-native'
|
||||
import {type AppBskyFeedDefs, type ComAtprotoLabelDefs} from '@atproto/api'
|
||||
import {type ComAtprotoLabelDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Plural} from '@lingui/react/macro'
|
||||
@@ -19,12 +19,10 @@ import {
|
||||
} from '#/components/moderation/LabelsOnMeDialog'
|
||||
|
||||
export function LabelsOnMe({
|
||||
type,
|
||||
labels,
|
||||
size,
|
||||
style,
|
||||
}: {
|
||||
type: 'account' | 'content'
|
||||
labels: ComAtprotoLabelDefs.Label[] | undefined
|
||||
size?: ButtonSize
|
||||
style?: StyleProp<ViewStyle>
|
||||
@@ -47,7 +45,7 @@ export function LabelsOnMe({
|
||||
|
||||
return (
|
||||
<View style={[a.flex_row, style]}>
|
||||
<LabelsOnMeDialog control={control} labels={labels} type={type} />
|
||||
<LabelsOnMeDialog control={control} labels={labels} type="account" />
|
||||
|
||||
<Button
|
||||
variant="solid"
|
||||
@@ -59,37 +57,13 @@ export function LabelsOnMe({
|
||||
}}>
|
||||
<ButtonIcon position="left" icon={CircleInfo} />
|
||||
<ButtonText style={[a.leading_snug]}>
|
||||
{type === 'account' ? (
|
||||
<Plural
|
||||
value={labels.length}
|
||||
one="# account label"
|
||||
other="# account labels"
|
||||
/>
|
||||
) : (
|
||||
<Plural
|
||||
value={labels.length}
|
||||
one="# content label"
|
||||
other="# content labels"
|
||||
/>
|
||||
)}
|
||||
<Plural
|
||||
value={labels.length}
|
||||
one="# account label"
|
||||
other="# account labels"
|
||||
/>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export function LabelsOnMyPost({
|
||||
post,
|
||||
style,
|
||||
}: {
|
||||
post: AppBskyFeedDefs.PostView
|
||||
style?: StyleProp<ViewStyle>
|
||||
}) {
|
||||
const {currentAccount} = useSession()
|
||||
if (post.author.did !== currentAccount?.did) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<LabelsOnMe type="content" labels={post.labels} size="tiny" style={style} />
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
import {useCallback, useMemo, useState} from 'react'
|
||||
import {useMemo, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type ComAtprotoLabelDefs, ToolsOzoneReportDefs} from '@atproto/api'
|
||||
import {XRPCError} from '@atproto/api'
|
||||
import {type ComAtprotoLabelDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import {useMutation} from '@tanstack/react-query'
|
||||
|
||||
import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
||||
import {useLabelSubject} from '#/lib/moderation'
|
||||
import {useLabelInfo} from '#/lib/moderation/useLabelInfo'
|
||||
import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent, useSession} from '#/state/session'
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import {useSession} from '#/state/session'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {AppealForm} from '#/components/moderation/AppealForm'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_ANDROID} from '#/env'
|
||||
import {Admonition} from '../Admonition'
|
||||
import {Divider} from '../Divider'
|
||||
import {Loader} from '../Loader'
|
||||
|
||||
export {useDialogControl as useLabelsOnMeDialogControl} from '#/components/Dialog'
|
||||
|
||||
@@ -211,141 +204,3 @@ function Label({
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function AppealForm({
|
||||
label,
|
||||
control,
|
||||
onPressBack,
|
||||
}: {
|
||||
label: ComAtprotoLabelDefs.Label
|
||||
control: Dialog.DialogOuterProps['control']
|
||||
onPressBack: () => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const {labeler, strings} = useLabelInfo(label)
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const [details, setDetails] = useState('')
|
||||
const {subject} = useLabelSubject({label})
|
||||
const isAccountReport = 'did' in subject
|
||||
const agent = useAgent()
|
||||
const sourceName = labeler
|
||||
? sanitizeHandle(labeler.creator.handle, '@')
|
||||
: label.src
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
const {mutate, isPending} = useMutation({
|
||||
mutationFn: async () => {
|
||||
const $type = !isAccountReport
|
||||
? 'com.atproto.repo.strongRef'
|
||||
: 'com.atproto.admin.defs#repoRef'
|
||||
await agent.createModerationReport(
|
||||
{
|
||||
reasonType: ToolsOzoneReportDefs.REASONAPPEAL,
|
||||
subject: {
|
||||
$type,
|
||||
...subject,
|
||||
},
|
||||
reason: details,
|
||||
},
|
||||
{
|
||||
encoding: 'application/json',
|
||||
headers: {
|
||||
'atproto-proxy': `${label.src}#atproto_labeler`,
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
onError: err => {
|
||||
if (err instanceof XRPCError && err.error === 'AlreadyAppealed') {
|
||||
setError(
|
||||
_(
|
||||
msg`You've already appealed this label and it's being reviewed by our moderation team.`,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
setError(_(msg`Failed to submit appeal, please try again.`))
|
||||
}
|
||||
logger.error('Failed to submit label appeal', {message: err})
|
||||
},
|
||||
onSuccess: () => {
|
||||
control.close()
|
||||
Toast.show(_(msg({message: 'Appeal submitted', context: 'toast'})))
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = useCallback(() => mutate(), [mutate])
|
||||
|
||||
return (
|
||||
<>
|
||||
<View>
|
||||
<Text style={[a.text_2xl, a.font_semi_bold, a.pb_xs, a.leading_tight]}>
|
||||
<Trans>Appeal "{strings.name}" label</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_md, a.leading_snug]}>
|
||||
<Trans>
|
||||
This appeal will be sent to{' '}
|
||||
<InlineLinkText
|
||||
label={sourceName}
|
||||
to={makeProfileLink(
|
||||
labeler ? labeler.creator : {did: label.src, handle: ''},
|
||||
)}
|
||||
onPress={() => control.close()}
|
||||
style={[a.text_md, a.leading_snug]}>
|
||||
{sourceName}
|
||||
</InlineLinkText>
|
||||
.
|
||||
</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
{error && (
|
||||
<Admonition type="error" style={[a.mt_sm]}>
|
||||
{error}
|
||||
</Admonition>
|
||||
)}
|
||||
<View style={[a.my_md]}>
|
||||
<Dialog.Input
|
||||
label={_(msg`Text input field`)}
|
||||
placeholder={_(
|
||||
msg`Please explain why you think this label was incorrectly applied by ${
|
||||
labeler ? sanitizeHandle(labeler.creator.handle, '@') : label.src
|
||||
}`,
|
||||
)}
|
||||
value={details}
|
||||
onChangeText={setDetails}
|
||||
autoFocus={true}
|
||||
numberOfLines={3}
|
||||
multiline
|
||||
maxLength={300}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={
|
||||
gtMobile
|
||||
? [a.flex_row, a.justify_between]
|
||||
: [{flexDirection: 'column-reverse'}, a.gap_sm]
|
||||
}>
|
||||
<Button
|
||||
testID="backBtn"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="large"
|
||||
onPress={onPressBack}
|
||||
label={_(msg`Back`)}>
|
||||
<ButtonText>{_(msg`Back`)}</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
testID="submitBtn"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="large"
|
||||
onPress={onSubmit}
|
||||
label={_(msg`Submit`)}>
|
||||
<ButtonText>{_(msg`Submit`)}</ButtonText>
|
||||
{isPending && <ButtonIcon icon={Loader} />}
|
||||
</Button>
|
||||
</View>
|
||||
{IS_ANDROID && <View style={{height: 300}} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type ModerationCause} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
@@ -11,8 +12,10 @@ import {listUriToHref} from '#/lib/strings/url-helpers'
|
||||
import {useSession} from '#/state/session'
|
||||
import {atoms as a, useGutters, useTheme, web} from '#/alf'
|
||||
import {Admonition} from '#/components/Admonition'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import {AppealForm} from '#/components/moderation/AppealForm'
|
||||
import {type AppModerationCause} from '#/components/Pills'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
@@ -47,6 +50,18 @@ function ModerationDetailsDialogInner({
|
||||
const desc = useModerationCauseDescription(modcause)
|
||||
const {currentAccount} = useSession()
|
||||
const timeDiff = useGetTimeAgo({future: true})
|
||||
const [isAppealing, setIsAppealing] = useState(false)
|
||||
|
||||
/*
|
||||
* Appeal eligibility: only for label causes on content belonging to the
|
||||
* current user, where the label was not self-applied.
|
||||
*/
|
||||
const canAppeal =
|
||||
modcause?.type === 'label' &&
|
||||
!!currentAccount &&
|
||||
modcause.label.src !== currentAccount.did &&
|
||||
(modcause.label.uri === currentAccount.did ||
|
||||
modcause.label.uri.startsWith(`at://${currentAccount.did}/`))
|
||||
|
||||
let name
|
||||
let description
|
||||
@@ -137,6 +152,23 @@ function ModerationDetailsDialogInner({
|
||||
const sourceName =
|
||||
desc.source || desc.sourceDisplayName || _(msg`an unknown labeler`)
|
||||
|
||||
if (isAppealing && modcause?.type === 'label') {
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Appeal label`)}
|
||||
style={web({
|
||||
maxWidth: 460,
|
||||
})}>
|
||||
<AppealForm
|
||||
label={modcause.label}
|
||||
control={control}
|
||||
onPressBack={() => setIsAppealing(false)}
|
||||
/>
|
||||
<Dialog.Close />
|
||||
</Dialog.ScrollableInner>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Moderation details`)}
|
||||
@@ -228,6 +260,20 @@ function ModerationDetailsDialogInner({
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
{canAppeal && (
|
||||
<View style={[a.flex_row, a.justify_end, a.mt_sm]}>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
label={_(msg`Appeal this label`)}
|
||||
onPress={() => setIsAppealing(true)}>
|
||||
<ButtonText>
|
||||
<Trans>Appeal</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -42,7 +42,6 @@ import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Tra
|
||||
import {GalleryBleed} from '#/components/images/Gallery'
|
||||
import {Link} from '#/components/Link'
|
||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '#/components/moderation/PostAlerts'
|
||||
import {type AppModerationCause} from '#/components/Pills'
|
||||
import {Embed, PostEmbedViewContext} from '#/components/Post/Embed'
|
||||
@@ -384,7 +383,6 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
|
||||
</View>
|
||||
</View>
|
||||
<View style={[a.pb_sm]}>
|
||||
<LabelsOnMyPost post={post} style={[a.pb_sm]} />
|
||||
<ContentHider
|
||||
modui={moderation.ui('contentView')}
|
||||
ignoreMute
|
||||
|
||||
@@ -36,7 +36,6 @@ import {
|
||||
GalleryBleed,
|
||||
maybeApplyGalleryOffsetStyles,
|
||||
} from '#/components/images/Gallery'
|
||||
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '#/components/moderation/PostAlerts'
|
||||
import {PostHider} from '#/components/moderation/PostHider'
|
||||
import {type AppModerationCause} from '#/components/Pills'
|
||||
@@ -310,7 +309,6 @@ const ThreadItemPostInner = memo(function ThreadItemPostInner({
|
||||
}),
|
||||
]}
|
||||
/>
|
||||
<LabelsOnMyPost post={post} style={[a.pb_xs]} />
|
||||
<PostAlerts
|
||||
modui={moderation.ui('contentList')}
|
||||
style={[a.pb_2xs]}
|
||||
|
||||
@@ -33,7 +33,6 @@ import {DebugFieldDisplay} from '#/components/DebugFieldDisplay'
|
||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||
import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash'
|
||||
import {GalleryBleed} from '#/components/images/Gallery'
|
||||
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '#/components/moderation/PostAlerts'
|
||||
import {PostHider} from '#/components/moderation/PostHider'
|
||||
import {type AppModerationCause} from '#/components/Pills'
|
||||
@@ -340,7 +339,6 @@ const ThreadItemTreePostInner = memo(function ThreadItemTreePostInner({
|
||||
<View style={[a.flex_row]}>
|
||||
<ThreadItemTreeReplyChildReplyLine item={item} />
|
||||
<View style={[a.flex_1, a.pl_2xs]}>
|
||||
<LabelsOnMyPost post={post} style={[a.pb_2xs]} />
|
||||
<PostAlerts
|
||||
modui={moderation.ui('contentList')}
|
||||
style={[a.pb_2xs]}
|
||||
|
||||
@@ -228,7 +228,6 @@ let ProfileHeaderShell = ({
|
||||
{!isPlaceholderProfile &&
|
||||
(isMe ? (
|
||||
<LabelsOnMe
|
||||
type="account"
|
||||
labels={profile.labels}
|
||||
style={[
|
||||
a.px_lg,
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
maybeApplyGalleryOffsetStyles,
|
||||
} from '#/components/images/Gallery'
|
||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '#/components/moderation/PostAlerts'
|
||||
import {Embed, PostEmbedViewContext} from '#/components/Post/Embed'
|
||||
import {PostRepliedTo} from '#/components/Post/PostRepliedTo'
|
||||
@@ -215,7 +214,6 @@ function PostInner({
|
||||
{replyAuthorDid !== '' && (
|
||||
<PostRepliedTo parentAuthor={replyAuthorDid} />
|
||||
)}
|
||||
<LabelsOnMyPost post={post} />
|
||||
<ContentHider
|
||||
modui={moderation.ui('contentView')}
|
||||
style={styles.contentHider}
|
||||
|
||||
@@ -39,7 +39,6 @@ import {
|
||||
maybeApplyGalleryOffsetStyles,
|
||||
} from '#/components/images/Gallery'
|
||||
import {ContentHider} from '#/components/moderation/ContentHider'
|
||||
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
|
||||
import {PostAlerts} from '#/components/moderation/PostAlerts'
|
||||
import {type AppModerationCause} from '#/components/Pills'
|
||||
import {Embed} from '#/components/Post/Embed'
|
||||
@@ -420,7 +419,6 @@ let FeedItemInner = ({
|
||||
isParentNotFound={isParentNotFound}
|
||||
/>
|
||||
)}
|
||||
<LabelsOnMyPost post={post} />
|
||||
<PostContent
|
||||
moderation={moderation}
|
||||
richText={richText}
|
||||
|
||||
Reference in New Issue
Block a user