import {type StyleProp, View, type ViewStyle} from 'react-native' import { type AppBskyFeedDefs, type ComAtprotoLabelDefs, type ModerationCause, type ModerationUI, } from '@atproto/api' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' import { filterUserFacingLabels, getModerationCauseKey, unique, } from '#/lib/moderation' import {useSession} from '#/state/session' import {atoms as a} from '#/alf' import { LabelsOnMeDialog, useLabelsOnMeDialogControl, } from '#/components/moderation/LabelsOnMeDialog' import * as Pills from '#/components/Pills' export function PostAlerts({ post, modui, view = 'compact', style, additionalCauses, }: { post?: AppBskyFeedDefs.PostView modui: ModerationUI /** * Expanded views (e.g. the thread anchor post) render larger pills and * surface the "+n" additional labels pill. Compact views (feeds, replies) * keep the alerts minimal. */ view?: 'expanded' | 'compact' includeMute?: boolean style?: StyleProp additionalCauses?: ModerationCause[] | Pills.AppModerationCause[] }) { const {currentAccount} = useSession() const size: Pills.CommonProps['size'] = view === 'expanded' ? 'lg' : 'sm' const alerts = modui.alerts.filter(unique) const informs = modui.informs.filter(unique) /* * The "+n" pill surfaces labels for the author to review and appeal, so it * only applies when the viewer is the author, and only in expanded views. * It renders even when no other moderation is visible, since it may be the * author's only entry point to appeal labels on their content. */ const isOwnPost = !!post && post.author.did === currentAccount?.did const allLabels: ComAtprotoLabelDefs.Label[] = isOwnPost && view === 'expanded' ? [ ...(post.labels ?? []), /* * Account labels appear on Profile. We don't show them here unless the * user's mod settings are configured such that the labels land in the * modui handling. */ // ...(post.author.labels ?? []) ] : [] /* * Labels that the moderation system already surfaces in this context - * whether as an alert, an inform, or a blur handled by ContentHider - should * not be repeated in the "+n" pill. */ const shownCauses = [...alerts, ...informs, ...modui.blurs] const additionalLabels = filterUserFacingLabels( allLabels, currentAccount?.did, ).filter(label => shownCauses.every( cause => cause.type !== 'label' || cause.label.val !== label.val || cause.label.src !== label.src || cause.label.uri !== label.uri, ), ) if ( !modui.alert && !modui.inform && !additionalCauses?.length && !additionalLabels.length ) { return null } return ( {alerts.map(cause => ( ))} {informs.map(cause => ( ))} {additionalCauses?.map(cause => ( ))} {additionalLabels.length ? ( 0 || informs.length > 0 || (additionalCauses?.length ?? 0) > 0 } /> ) : null} ) } function AdditionalLabels({ labels, size, hasPrecedingPills, }: { labels: ComAtprotoLabelDefs.Label[] size?: Pills.CommonProps['size'] /** * The compact "+n" syntax only makes sense as a continuation of other * pills. When this pill stands alone, spell it out. */ hasPrecedingPills: boolean }) { const {t: l} = useLingui() const control = useLabelsOnMeDialogControl() return ( { control.open() }} /> ) }