Rework the moderationlabelpref

This commit is contained in:
Paul Frazee
2024-03-09 17:50:29 -08:00
parent af124516b3
commit c7e20a4b3d
5 changed files with 112 additions and 202 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ function ButtonInner({children}: React.PropsWithChildren<{}>) {
native({
paddingBottom: 10,
}),
a.px_sm,
a.px_md,
t.atoms.bg,
t.atoms.border_contrast_low,
baseStyles,
+89 -184
View File
@@ -5,10 +5,7 @@ import {useLingui} from '@lingui/react'
import {msg, Trans} from '@lingui/macro'
import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings'
import {
useLabelBehaviorDescription,
useLabelLongBehaviorDescription,
} from '#/lib/moderation/useLabelBehaviorDescription'
import {useLabelBehaviorDescription} from '#/lib/moderation/useLabelBehaviorDescription'
import {
usePreferencesQuery,
usePreferencesSetContentLabelMutation,
@@ -19,11 +16,8 @@ import {useTheme, atoms as a} from '#/alf'
import {Text} from '#/components/Typography'
import {InlineLink} from '#/components/Link'
import * as Dialog from '#/components/Dialog'
import {Button} from '#/components/Button'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '../icons/CircleInfo'
import {SettingsGear2_Stroke2_Corner0_Rounded as Gear} from '../icons/Gear'
import * as Toggle from '#/components/forms/Toggle'
import {Divider} from '#/components/Divider'
import * as ToggleButton from '#/components/forms/ToggleButton'
export function ModerationLabelPref({
labelValueDefinition,
@@ -52,18 +46,34 @@ export function ModerationLabelPref({
savedPref ??
labelValueDefinition.defaultSetting ??
'warn'
const [selected, setSelected] = React.useState<LabelPreference[]>([pref])
const settingDesc = useLabelBehaviorDescription(labelValueDefinition, pref)
const hideLabel = useLabelLongBehaviorDescription(
labelValueDefinition,
'hide',
// does the 'warn' setting make sense for this label?
const canWarn = !(
labelValueDefinition.blurs === 'none' &&
labelValueDefinition.severity === 'none'
)
const warnLabel = useLabelLongBehaviorDescription(
// is this label adult only?
const adultOnly = labelValueDefinition.flags.includes('adult')
// is this label disabled because it's adult only?
const adultDisabled =
adultOnly && !preferences?.moderationPrefs.adultContentEnabled
// are there any reasons we cant configure this label here?
const cantConfigure = isGlobalLabel || adultDisabled
// adjust the pref based on whether warn is available
let prefAdjusted = pref
if (!canWarn && pref === 'warn') {
prefAdjusted = 'ignore'
}
// grab localized descriptions of the label and its settings
const currentPrefLabel = useLabelBehaviorDescription(
labelValueDefinition,
'warn',
prefAdjusted,
)
const ignoreLabel = useLabelLongBehaviorDescription(
const hideLabel = useLabelBehaviorDescription(labelValueDefinition, 'hide')
const warnLabel = useLabelBehaviorDescription(labelValueDefinition, 'warn')
const ignoreLabel = useLabelBehaviorDescription(
labelValueDefinition,
'ignore',
)
@@ -74,178 +84,73 @@ export function ModerationLabelPref({
labelValueDefinition,
)
const canWarn = !(
labelValueDefinition.blurs === 'none' &&
labelValueDefinition.severity === 'none'
)
const adultOnly = labelValueDefinition.flags.includes('adult')
const adultDisabled =
adultOnly && !preferences?.moderationPrefs.adultContentEnabled
const cantConfigure = isGlobalLabel || adultDisabled
const onSettingChange = React.useCallback(
(newPrefs: LabelPreference[]) => {
setSelected(newPrefs)
mutate({label: identifier, visibility: newPrefs[0], labelerDid})
},
[mutate, labelerDid, identifier],
)
const settings = [
{
pref: 'hide',
label: hideLabel,
},
canWarn && {
pref: 'warn',
label: warnLabel,
},
{
pref: 'ignore',
label: ignoreLabel,
},
].filter(Boolean) as {
pref: LabelPreference
label: string
}[]
return (
<>
<Button
onPress={() => control.open()}
label={settingDesc}
disabled={disabled}>
{({hovered, focused, pressed}) => (
<View
style={[
a.w_full,
a.flex_row,
a.justify_between,
a.gap_sm,
a.align_start,
a.px_lg,
a.py_lg,
a.rounded_sm,
t.atoms.bg_contrast_25,
(hovered || focused || pressed) && [t.atoms.bg_contrast_50],
]}>
<View style={[a.gap_xs]}>
<Text style={[a.font_bold]}>{labelStrings.name}</Text>
<Text
style={[t.atoms.text_contrast_medium, a.leading_snug]}
numberOfLines={1}>
{labelStrings.description}
</Text>
</View>
<View style={[a.flex_row, a.gap_sm, a.px_lg, a.py_lg, a.justify_between]}>
<View style={[a.gap_xs, a.flex_1]}>
<Text style={[a.font_bold]}>{labelStrings.name}</Text>
<Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
{labelStrings.description}
</Text>
{!disabled && (
<View
style={[
a.flex_row,
a.align_center,
a.justify_end,
a.gap_xs,
a.rounded_2xs,
]}>
<Text style={[t.atoms.text_contrast_medium, a.font_semibold]}>
{settingDesc}
</Text>
<Gear size="sm" fill={t.atoms.text_contrast_low.color} />
</View>
)}
{cantConfigure && (
<View style={[a.flex_row, a.gap_xs, a.align_center, a.mt_xs]}>
<CircleInfo size="sm" fill={t.atoms.text_contrast_high.color} />
<Text style={[t.atoms.text_contrast_high, a.font_semibold]}>
{adultDisabled ? (
<Trans>Adult content is disabled.</Trans>
) : isGlobalLabel ? (
<Trans>
Configured in{' '}
<InlineLink
to="/moderation"
onPress={() => control.close()}
style={a.text_sm}>
moderation settings
</InlineLink>
.
</Trans>
) : null}
</Text>
</View>
)}
</Button>
<Dialog.Outer control={control}>
<Dialog.Handle />
<Dialog.Inner
label={_(msg`Settings for ${labelValueDefinition.identifier}`)}
style={[a.gap_sm]}>
<Text style={[a.text_2xl, a.font_bold, a.pb_xs, t.atoms.text]}>
{labelStrings.name}
</View>
{disabled ? (
<></>
) : cantConfigure ? (
<View style={[{minHeight: 35}, a.px_sm, a.py_md]}>
<Text style={[a.font_bold, t.atoms.text_contrast_medium]}>
{currentPrefLabel}
</Text>
<Text style={[a.text_md, a.pb_sm, t.atoms.text_contrast_medium]}>
{labelStrings.description}
</Text>
{cantConfigure && (
<View
style={[
a.flex_row,
a.gap_xs,
a.align_center,
a.py_md,
a.px_lg,
a.rounded_sm,
t.atoms.bg_contrast_25,
]}>
<CircleInfo size="md" fill={t.atoms.text_contrast_medium.color} />
<Text style={[t.atoms.text_contrast_medium]}>
{adultDisabled ? (
<Trans>
Adult content must be enabled to configure this label.
</Trans>
) : isGlobalLabel ? (
<Trans>
{labelStrings.name} is configured in your{' '}
<InlineLink
to="/moderation"
onPress={() => control.close()}
style={a.text_md}>
global moderation settings
</InlineLink>
.
</Trans>
) : null}
</Text>
</View>
)}
{!cantConfigure && (
<Toggle.Group<LabelPreference>
type="radio"
values={selected}
onChange={onSettingChange}
label={_(
msg`Configure filtering settings for ${labelStrings.name}`,
)}>
<View
style={[
a.rounded_md,
a.overflow_hidden,
t.atoms.bg_contrast_25,
]}>
{settings.map((s, i) => (
<>
{i !== 0 && <Divider />}
<Toggle.Item name={s.pref} label={s.label}>
<View
style={[
a.flex_1,
a.flex_row,
a.align_center,
a.gap_md,
a.py_md,
a.px_lg,
t.atoms.bg_contrast_25,
]}>
<Toggle.Radio />
<Text>{s.label}</Text>
</View>
</Toggle.Item>
</>
))}
</View>
</Toggle.Group>
)}
<Dialog.Close />
</Dialog.Inner>
</Dialog.Outer>
</>
</View>
) : (
<View style={[{minHeight: 35}]}>
<ToggleButton.Group
label={_(
msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`,
)}
values={[prefAdjusted]}
onChange={newPref =>
mutate({
label: identifier,
visibility: newPref[0] as LabelPreference,
labelerDid,
})
}>
<ToggleButton.Button name="ignore" label={ignoreLabel}>
{ignoreLabel}
</ToggleButton.Button>
{canWarn && (
<ToggleButton.Button name="warn" label={warnLabel}>
{warnLabel}
</ToggleButton.Button>
)}
<ToggleButton.Button name="hide" label={hideLabel}>
{hideLabel}
</ToggleButton.Button>
</ToggleButton.Group>
</View>
)}
</View>
)
}
@@ -8,23 +8,18 @@ export function useLabelBehaviorDescription(
) {
const {_} = useLingui()
if (pref === 'ignore') {
return _(msg`Disabled`)
return _(msg`Off`)
}
if (labelValueDef.blurs === 'content') {
if (labelValueDef.blurs === 'content' || labelValueDef.blurs === 'media') {
if (pref === 'hide') {
return _(msg`Hide`)
}
return _(msg`Warn`)
} else if (labelValueDef.blurs === 'media') {
if (pref === 'hide') {
return _(msg`Hide`)
}
return _(msg`Blur images`)
} else if (labelValueDef.severity === 'alert') {
if (pref === 'hide') {
return _(msg`Hide`)
}
return _(msg`Show warning`)
return _(msg`Warn`)
} else if (labelValueDef.severity === 'inform') {
if (pref === 'hide') {
return _(msg`Hide`)
@@ -67,7 +67,7 @@ export function ModerationOption({
]}
layout={Layout.easing(Easing.ease).duration(200)}
entering={isMounted.current ? FadeIn : undefined}>
<View style={[a.gap_xs, {width: '50%'}]}>
<View style={[a.gap_xs, a.flex_1]}>
<Text style={[a.font_bold]}>{labelStrings.name}</Text>
<Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
{labelStrings.description}
+18 -8
View File
@@ -20,6 +20,7 @@ import {isNative} from '#/platform/detection'
import {useTheme, atoms as a} from '#/alf'
import {Text} from '#/components/Typography'
import {Loader} from '#/components/Loader'
import {Divider} from '#/components/Divider'
import {CenteredView, ScrollView} from '#/view/com/util/Views'
import {ErrorState} from '../ErrorState'
import {ModerationLabelPref} from '#/components/moderation/ModerationLabelPref'
@@ -191,15 +192,24 @@ export function ProfileLabelsSectionInner({
) : null}
</View>
{labelDefs.length > 0 && (
<View style={[a.mt_xl, a.gap_sm]}>
{labelDefs.map(labelDef => {
<View
style={[
a.mt_xl,
a.w_full,
a.rounded_md,
a.overflow_hidden,
t.atoms.bg_contrast_25,
]}>
{labelDefs.map((labelDef, i) => {
return (
<ModerationLabelPref
key={labelDef.identifier}
disabled={isSubscribed ? undefined : true}
labelValueDefinition={labelDef}
labelerDid={labelerInfo.creator.did}
/>
<React.Fragment key={labelDef.identifier}>
{i !== 0 && <Divider />}
<ModerationLabelPref
disabled={isSubscribed ? undefined : true}
labelValueDefinition={labelDef}
labelerDid={labelerInfo.creator.did}
/>
</React.Fragment>
)
})}
</View>