Get moderation screen working
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {InterprettedLabelValueDefinition, LabelPreference} from '@atproto/api'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {msg} from '@lingui/macro'
|
||||
|
||||
import {useLabelStrings} from '#/lib/moderation/useLabelStrings'
|
||||
import {
|
||||
usePreferencesQuery,
|
||||
usePreferencesSetContentLabelMutation,
|
||||
} from '#/state/queries/preferences'
|
||||
|
||||
import {useTheme, atoms as a} from '#/alf'
|
||||
import {Text} from '#/components/Typography'
|
||||
import * as ToggleButton from '#/components/forms/ToggleButton'
|
||||
|
||||
export function SimpleModerationLabelPref({
|
||||
labelValueDefinition,
|
||||
disabled,
|
||||
}: {
|
||||
labelValueDefinition: InterprettedLabelValueDefinition
|
||||
disabled?: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
|
||||
const {identifier} = labelValueDefinition
|
||||
const {data: preferences} = usePreferencesQuery()
|
||||
const {mutate, variables} = usePreferencesSetContentLabelMutation()
|
||||
const savedPref = preferences?.moderationPrefs.labels[identifier]
|
||||
const pref = variables?.visibility ?? savedPref ?? 'warn'
|
||||
|
||||
const allLabelStrings = useLabelStrings()
|
||||
const labelStrings =
|
||||
labelValueDefinition.identifier in allLabelStrings
|
||||
? allLabelStrings[labelValueDefinition.identifier].general
|
||||
: {
|
||||
name: labelValueDefinition.identifier,
|
||||
description: `Labeled "${labelValueDefinition.identifier}"`,
|
||||
}
|
||||
|
||||
const labelOptions = {
|
||||
hide: _(msg`Hide`),
|
||||
warn: _(msg`Warn`),
|
||||
ignore: _(msg`Show`),
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
a.flex_row,
|
||||
a.justify_between,
|
||||
a.gap_sm,
|
||||
a.py_md,
|
||||
a.pl_lg,
|
||||
a.pr_md,
|
||||
a.align_center,
|
||||
]}>
|
||||
<View style={[a.gap_xs, {width: '50%'}]}>
|
||||
<Text style={[a.font_bold]}>{labelStrings.name}</Text>
|
||||
<Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
|
||||
{labelStrings.description}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={[a.justify_center, {minHeight: 35}]}>
|
||||
{!disabled && (
|
||||
<ToggleButton.Group
|
||||
label={_(
|
||||
msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`,
|
||||
)}
|
||||
values={[pref]}
|
||||
onChange={newPref =>
|
||||
mutate({
|
||||
label: identifier,
|
||||
visibility: newPref[0] as LabelPreference,
|
||||
labelerDid: undefined,
|
||||
})
|
||||
}>
|
||||
<ToggleButton.Button name="ignore" label={labelOptions.ignore}>
|
||||
{labelOptions.ignore}
|
||||
</ToggleButton.Button>
|
||||
<ToggleButton.Button name="warn" label={labelOptions.warn}>
|
||||
{labelOptions.warn}
|
||||
</ToggleButton.Button>
|
||||
<ToggleButton.Button name="hide" label={labelOptions.hide}>
|
||||
{labelOptions.hide}
|
||||
</ToggleButton.Button>
|
||||
</ToggleButton.Group>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -87,7 +87,7 @@ export function ModerationLabelPref({
|
||||
a.justify_between,
|
||||
a.gap_sm,
|
||||
a.align_center,
|
||||
t.atoms.bg_contrast_50,
|
||||
t.atoms.bg_contrast_25,
|
||||
a.px_lg,
|
||||
a.py_lg,
|
||||
a.rounded_sm,
|
||||
|
||||
@@ -128,9 +128,7 @@ export function useLabelStrings(): LabelStrings {
|
||||
porn: {
|
||||
general: {
|
||||
name: _(msg`Pornography`),
|
||||
description: _(
|
||||
msg`Images of full-frontal nudity (genitalia) in any sexualized context, or explicit sexual activity (meaning contact with genitalia or breasts) even if partially covered. Includes graphic sexual cartoons (often jokes/memes).`,
|
||||
),
|
||||
description: _(msg`Explicit sexual images.`),
|
||||
},
|
||||
account: {
|
||||
name: _(msg`Adult Content`),
|
||||
@@ -148,9 +146,7 @@ export function useLabelStrings(): LabelStrings {
|
||||
sexual: {
|
||||
general: {
|
||||
name: _(msg`Sexually Suggestive`),
|
||||
description: _(
|
||||
msg`Content that does not meet the level of "pornography", but is still sexual. Some common examples have been selfies and "hornyposting" with underwear on, or partially naked (naked but covered, eg with hands or from side perspective). Sheer/see-through nipples may end up in this category.`,
|
||||
),
|
||||
description: _(msg`Does not include nudity.`),
|
||||
},
|
||||
account: {
|
||||
name: _(msg`Suggestive Content`),
|
||||
@@ -168,9 +164,7 @@ export function useLabelStrings(): LabelStrings {
|
||||
nudity: {
|
||||
general: {
|
||||
name: _(msg`Nudity`),
|
||||
description: _(
|
||||
msg`Nudity which is not sexual, or that is primarily "artistic" in nature. For example: breastfeeding; classic art paintings and sculptures; newspaper images with some nudity; fashion modeling. "Erotic photography" is likely to end up in sexual or porn.`,
|
||||
),
|
||||
description: _(msg`Including non-sexual and artistic.`),
|
||||
},
|
||||
account: {
|
||||
name: _(msg`Adult Content`),
|
||||
@@ -187,10 +181,8 @@ export function useLabelStrings(): LabelStrings {
|
||||
},
|
||||
gore: {
|
||||
general: {
|
||||
name: _(msg`Gore`),
|
||||
description: _(
|
||||
msg`Intended for shocking images, typically involving blood or visible wounds.`,
|
||||
),
|
||||
name: _(msg`Violent / Bloody`),
|
||||
description: _(msg`Gore, self-harm, torture`),
|
||||
},
|
||||
account: {
|
||||
name: _(msg`Graphic Imagery (Gore)`),
|
||||
|
||||
@@ -4,7 +4,7 @@ import {useFocusEffect} from '@react-navigation/native'
|
||||
import {ComAtprotoLabelDefs} from '@atproto/api'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {AppBskyLabelerDefs} from '@atproto/api'
|
||||
import {AppBskyLabelerDefs, LABELS} from '@atproto/api'
|
||||
import {useSafeAreaFrame} from 'react-native-safe-area-context'
|
||||
|
||||
import {NativeStackScreenProps, CommonNavigatorParams} from '#/lib/routes/types'
|
||||
@@ -38,7 +38,7 @@ import {InlineLink, Link} from '#/components/Link'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {getModerationServiceTitle} from '#/lib/moderation'
|
||||
import * as ModerationServiceCard from '#/components/ModerationServiceCard'
|
||||
import {ModerationLabelPref} from '#/components/ModerationLabelPref'
|
||||
import {SimpleModerationLabelPref} from '#/components/ModerationLabelPref/SimpleModerationLabelPref'
|
||||
|
||||
function ErrorState({error}: {error: string}) {
|
||||
const t = useTheme()
|
||||
@@ -297,13 +297,25 @@ export function ModerationScreenInner({
|
||||
{adultContentEnabled && (
|
||||
<>
|
||||
<Divider />
|
||||
<ModerationLabelPref labelGroup="porn" />
|
||||
<SimpleModerationLabelPref
|
||||
labelValueDefinition={LABELS.porn}
|
||||
labelerDid={undefined}
|
||||
/>
|
||||
<Divider />
|
||||
<ModerationLabelPref labelGroup="suggestive" />
|
||||
<SimpleModerationLabelPref
|
||||
labelValueDefinition={LABELS.sexual}
|
||||
labelerDid={undefined}
|
||||
/>
|
||||
<Divider />
|
||||
<ModerationLabelPref labelGroup="nudity" />
|
||||
<SimpleModerationLabelPref
|
||||
labelValueDefinition={LABELS.nudity}
|
||||
labelerDid={undefined}
|
||||
/>
|
||||
<Divider />
|
||||
<ModerationLabelPref labelGroup="violence" />
|
||||
<SimpleModerationLabelPref
|
||||
labelValueDefinition={LABELS.gore}
|
||||
labelerDid={undefined}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -154,7 +154,7 @@ export function ProfileLabelsSectionInner({
|
||||
<View
|
||||
style={[
|
||||
a.pt_xl,
|
||||
a.px_xl,
|
||||
a.px_lg,
|
||||
isNative && a.border_t,
|
||||
t.atoms.border_contrast_low,
|
||||
]}>
|
||||
|
||||
Reference in New Issue
Block a user