Implement new label config controls (wip)

This commit is contained in:
Paul Frazee
2024-03-04 16:00:15 -08:00
parent 4d0dc7438b
commit f99307033c
7 changed files with 116 additions and 72 deletions
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" d="M4.213 6.886c-.673-1.35.334-2.889 1.806-2.889H17.98c1.472 0 2.479 1.539 1.806 2.89l-5.982 11.997c-.74 1.484-2.87 1.484-3.61 0L4.213 6.886Z"/></svg>

After

Width:  |  Height:  |  Size: 240 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M12.86 4.494a.995.995 0 0 0-1.72 0L4.14 16.502A.996.996 0 0 0 4.999 18h14.003a.996.996 0 0 0 .86-1.498L12.86 4.494ZM9.413 3.487c1.155-1.983 4.019-1.983 5.174 0l7.002 12.007C22.753 17.491 21.314 20 19.002 20H4.998c-2.312 0-3.751-2.509-2.587-4.506L9.413 3.487ZM12 8.019a1 1 0 0 1 1 1v2.994a1 1 0 1 1-2 0V9.02a1 1 0 0 1 1-1Z" clip-rule="evenodd"/><rect width="2.5" height="2.5" x="10.75" y="13.75" fill="#000" rx="1.25"/></svg>

After

Width:  |  Height:  |  Size: 537 B

+23 -45
View File
@@ -1,14 +1,14 @@
import React from 'react'
import {View} from 'react-native'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {InterprettedLabelValueDefinition} from '@atproto/api'
import {useLabelStrings} from '#/lib/moderation/useLabelStrings'
import {useLabelBehaviorDescription} from '#/lib/moderation/useLabelBehaviorDescription'
import {useTheme, atoms as a} from '#/alf'
import {Text} from '#/components/Typography'
import * as ToggleButton from '#/components/forms/ToggleButton'
import {Button, ButtonText, ButtonIcon} from '#/components/Button'
import {ArrowTriangleBottom_Stroke2_Corner1_Rounded as ArrowTriangleBottom} from '../icons/ArrowTriangle'
export function ModerationLabelPref({
labelValueDefinition,
@@ -19,64 +19,42 @@ export function ModerationLabelPref({
}) {
console.log({labelValueDefinition})
const t = useTheme()
const {_} = useLingui()
const allLabelStrings = useLabelStrings()
const labelStrings = labelValueDefinition.locales[0] // TODO look up locale
? labelValueDefinition.locales[0]
: labelValueDefinition.identifier in allLabelStrings
? allLabelStrings[labelValueDefinition.identifier].general
: {
general: {
name: labelValueDefinition.identifier,
description: `Labeled "${labelValueDefinition.identifier}"`,
},
name: labelValueDefinition.identifier,
description: `Labeled "${labelValueDefinition.identifier}"`,
}
const settingDesc = useLabelBehaviorDescription(labelValueDefinition, 'hide')
// TODO add onChange behavior when mod prefs are updated
const labelOptions = {
hide: _(msg`Hide`),
warn: _(msg`Warn`),
show: _(msg`Ignore`),
}
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%'}]}>
<View style={[a.flex_row, a.justify_between, a.gap_lg, a.align_center]}>
<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>
</View>
<View style={[a.justify_center, {minHeight: 35}]}>
{!disabled && (
<ToggleButton.Group
label={_(
msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`,
)}
values={['hide']}
onChange={() => {}}>
<ToggleButton.Button name="show" label={labelOptions.show}>
{labelOptions.show}
</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>
{!disabled && (
<View
style={[
a.flex_row,
a.align_center,
a.justify_end,
a.gap_xs,
{width: 125},
]}>
<Text style={[{color: t.palette.primary_500}, a.font_semibold]}>
{settingDesc}
</Text>
<ArrowTriangleBottom width={8} fill={t.palette.primary_500} />
</View>
)}
</View>
)
}
+5
View File
@@ -0,0 +1,5 @@
import {createSinglePathSVG} from './TEMPLATE'
export const ArrowTriangleBottom_Stroke2_Corner1_Rounded = createSinglePathSVG({
path: 'M4.213 6.886c-.673-1.35.334-2.889 1.806-2.889H17.98c1.472 0 2.479 1.539 1.806 2.89l-5.982 11.997c-.74 1.484-2.87 1.484-3.61 0L4.213 6.886Z',
})
@@ -0,0 +1,37 @@
import React from 'react'
import Svg, {Path, Rect} from 'react-native-svg'
import {useCommonSVGProps, Props} from '#/components/icons/common'
export const TriangleExclamation_Stroke2_Corner2_Rounded = React.forwardRef<
Svg,
Props
>(function LogoImpl(props, ref) {
const {fill, size, style, ...rest} = useCommonSVGProps(props)
return (
<Svg
fill="none"
{...rest}
ref={ref}
viewBox="0 0 24 24"
width={size}
height={size}
style={[style]}>
<Path
fill={fill}
fillRule="evenodd"
clipRule="evenodd"
d="M12.86 4.494a.995.995 0 0 0-1.72 0L4.14 16.502A.996.996 0 0 0 4.999 18h14.003a.996.996 0 0 0 .86-1.498L12.86 4.494ZM9.413 3.487c1.155-1.983 4.019-1.983 5.174 0l7.002 12.007C22.753 17.491 21.314 20 19.002 20H4.998c-2.312 0-3.751-2.509-2.587-4.506L9.413 3.487ZM12 8.019a1 1 0 0 1 1 1v2.994a1 1 0 1 1-2 0V9.02a1 1 0 0 1 1-1Z"
/>
<Rect
width="2.5"
height="2.5"
x="10.75"
y="13.75"
fill={fill}
rx="1.25"
/>
</Svg>
)
})
@@ -0,0 +1,39 @@
import {InterprettedLabelValueDefinition, LabelPreference} from '@atproto/api'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
export function useLabelBehaviorDescription(
labelValueDef: InterprettedLabelValueDefinition,
pref: LabelPreference,
) {
const {_} = useLingui()
if (pref === 'ignore') {
return _(msg`Disabled`)
}
if (labelValueDef.blurs === 'content') {
if (pref === 'hide') {
return _(msg`Hide content`)
}
return _(msg`Warn content`)
} else if (labelValueDef.blurs === 'media') {
if (pref === 'hide') {
return _(msg`Hide images`)
}
return _(msg`Warn images`)
} else if (labelValueDef.severity === 'alert') {
if (pref === 'hide') {
return _(msg`Filter from feeds`)
}
return _(msg`Show warning`)
} else if (labelValueDef.severity === 'inform') {
if (pref === 'hide') {
return _(msg`Filter from feeds`)
}
return _(msg`Show badge`)
} else {
if (pref === 'hide') {
return _(msg`Filter from feeds`)
}
return _(msg`Disabled`)
}
}
+10 -27
View File
@@ -80,11 +80,10 @@ export function ProfileLabelsSectionInner({
}) {
const {_} = useLingui()
const t = useTheme()
const isEnabled = Boolean(
moderationOpts.prefs.mods.find(mod => mod.did === labelerInfo.creator.did),
)
const hasSession = true // TODO
const {labelValues} = labelerInfo.policies
const isSubscribed = moderationOpts.prefs.mods.find(
mod => mod.did === labelerInfo.creator.did,
)
const labelDefs = React.useMemo(() => {
const customDefs = interpretLabelValueDefinitions(labelerInfo)
return labelValues
@@ -94,24 +93,6 @@ export function ProfileLabelsSectionInner({
) as InterprettedLabelValueDefinition[]
}, [labelerInfo, labelValues])
const {mutateAsync: toggleSubscription, variables} =
useLabelerSubscriptionMutation()
const isSubscribed =
variables?.subscribe ??
moderationOpts.prefs.mods.find(mod => mod.did === labelerInfo.creator.did)
const onPressSubscribe = React.useCallback(async () => {
try {
await toggleSubscription({
did: labelerInfo.creator.did,
subscribe: !isSubscribed,
})
} catch (e: any) {
// setSubscriptionError(e.message)
logger.error(`Failed to subscribe to labeler`, {message: e.message})
}
}, [toggleSubscription, isSubscribed, labelerInfo])
return (
<ScrollView
scrollEventThrottle={1}
@@ -164,12 +145,14 @@ export function ProfileLabelsSectionInner({
]}>
{labelDefs.map((labelDef, i) => {
return (
<React.Fragment key={labelDef?.identifier}>
<React.Fragment key={labelDef.identifier}>
{i !== 0 && <Divider />}
<ModerationLabelPref
disabled={isEnabled ? undefined : true}
labelValueDefinition={labelDef}
/>
<View style={[a.py_lg, a.px_md]}>
<ModerationLabelPref
disabled={isSubscribed ? undefined : true}
labelValueDefinition={labelDef}
/>
</View>
</React.Fragment>
)
})}