Update ModDebug to be a bit more intuitive and support custom labels
This commit is contained in:
+391
-162
@@ -10,11 +10,12 @@ import {
|
|||||||
AppBskyActorDefs,
|
AppBskyActorDefs,
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
LabelTarget,
|
|
||||||
LabelPreference,
|
LabelPreference,
|
||||||
ModerationDecision,
|
ModerationDecision,
|
||||||
ModerationBehavior,
|
ModerationBehavior,
|
||||||
RichText,
|
RichText,
|
||||||
|
ComAtprotoLabelDefs,
|
||||||
|
interpretLabelValueDefinition,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {moderationOptsOverrideContext} from '#/state/queries/preferences'
|
import {moderationOptsOverrideContext} from '#/state/queries/preferences'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
@@ -30,6 +31,7 @@ import {H1, H3, P, Text} from '#/components/Typography'
|
|||||||
import {useLabelStrings} from '#/lib/moderation/useLabelStrings'
|
import {useLabelStrings} from '#/lib/moderation/useLabelStrings'
|
||||||
import * as Toggle from '#/components/forms/Toggle'
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
import * as ToggleButton from '#/components/forms/ToggleButton'
|
import * as ToggleButton from '#/components/forms/ToggleButton'
|
||||||
|
import * as TextField from '#/components/forms/TextField'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
||||||
import {
|
import {
|
||||||
@@ -42,22 +44,12 @@ import {ProfileCard} from '../com/profile/ProfileCard'
|
|||||||
import {FeedItem} from '../com/posts/FeedItem'
|
import {FeedItem} from '../com/posts/FeedItem'
|
||||||
import {FeedItem as NotifFeedItem} from '../com/notifications/FeedItem'
|
import {FeedItem as NotifFeedItem} from '../com/notifications/FeedItem'
|
||||||
import {PostThreadItem} from '../com/post-thread/PostThreadItem'
|
import {PostThreadItem} from '../com/post-thread/PostThreadItem'
|
||||||
|
import {Divider} from '#/components/Divider'
|
||||||
|
|
||||||
const LABEL_VALUES: (keyof typeof LABELS)[] = Object.keys(
|
const LABEL_VALUES: (keyof typeof LABELS)[] = Object.keys(
|
||||||
LABELS,
|
LABELS,
|
||||||
) as (keyof typeof LABELS)[]
|
) as (keyof typeof LABELS)[]
|
||||||
|
|
||||||
const MOCK_MOD_PREFS = {
|
|
||||||
adultContentEnabled: true,
|
|
||||||
labelGroups: {},
|
|
||||||
mods: [
|
|
||||||
{
|
|
||||||
did: 'did:plc:fake-labeler',
|
|
||||||
labels: {},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DebugModScreen = ({}: NativeStackScreenProps<
|
export const DebugModScreen = ({}: NativeStackScreenProps<
|
||||||
CommonNavigatorParams,
|
CommonNavigatorParams,
|
||||||
'DebugMod'
|
'DebugMod'
|
||||||
@@ -68,6 +60,20 @@ export const DebugModScreen = ({}: NativeStackScreenProps<
|
|||||||
const [label, setLabel] = React.useState<string[]>([LABEL_VALUES[0]])
|
const [label, setLabel] = React.useState<string[]>([LABEL_VALUES[0]])
|
||||||
const [target, setTarget] = React.useState<string[]>(['account'])
|
const [target, setTarget] = React.useState<string[]>(['account'])
|
||||||
const [visibility, setVisiblity] = React.useState<string[]>(['hide'])
|
const [visibility, setVisiblity] = React.useState<string[]>(['hide'])
|
||||||
|
const [customLabelDef, setCustomLabelDef] =
|
||||||
|
React.useState<ComAtprotoLabelDefs.LabelValueDefinition>({
|
||||||
|
identifier: 'x-custom',
|
||||||
|
blurs: 'content',
|
||||||
|
severity: 'alert',
|
||||||
|
locales: [
|
||||||
|
{
|
||||||
|
lang: 'en',
|
||||||
|
name: 'Custom label',
|
||||||
|
description: 'A custom label created in this test environment',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
const [view, setView] = React.useState<string[]>(['post'])
|
||||||
const labelStrings = useLabelStrings()
|
const labelStrings = useLabelStrings()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
@@ -226,14 +232,22 @@ export const DebugModScreen = ({}: NativeStackScreenProps<
|
|||||||
return {
|
return {
|
||||||
userDid: isLoggedOut ? '' : isTargetMe ? did : 'did:web:alice.test',
|
userDid: isLoggedOut ? '' : isTargetMe ? did : 'did:web:alice.test',
|
||||||
prefs: {
|
prefs: {
|
||||||
...MOCK_MOD_PREFS,
|
|
||||||
adultContentEnabled: !noAdult,
|
adultContentEnabled: !noAdult,
|
||||||
labels: {
|
labels: {
|
||||||
[label[0]]: visibility[0] as LabelPreference,
|
[label[0]]: visibility[0] as LabelPreference,
|
||||||
},
|
},
|
||||||
|
mods: [
|
||||||
|
{
|
||||||
|
did: 'did:plc:fake-labeler',
|
||||||
|
labels: {[label[0]]: visibility[0] as LabelPreference},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
labelDefs: {
|
||||||
|
'did:plc:fake-labeler': [interpretLabelValueDefinition(customLabelDef)],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}, [label, visibility, noAdult, isLoggedOut, isTargetMe, did])
|
}, [label, visibility, noAdult, isLoggedOut, isTargetMe, did, customLabelDef])
|
||||||
|
|
||||||
const profileModeration = React.useMemo(() => {
|
const profileModeration = React.useMemo(() => {
|
||||||
return moderateProfile(profile, modOpts)
|
return moderateProfile(profile, modOpts)
|
||||||
@@ -248,8 +262,6 @@ export const DebugModScreen = ({}: NativeStackScreenProps<
|
|||||||
<CenteredView style={[t.atoms.bg, a.px_lg, a.py_lg]}>
|
<CenteredView style={[t.atoms.bg, a.px_lg, a.py_lg]}>
|
||||||
<H1 style={[a.text_5xl, a.font_bold, a.pb_lg]}>Moderation states</H1>
|
<H1 style={[a.text_5xl, a.font_bold, a.pb_lg]}>Moderation states</H1>
|
||||||
|
|
||||||
<Heading title="Config" />
|
|
||||||
|
|
||||||
<Heading title="" subtitle="Scenario" />
|
<Heading title="" subtitle="Scenario" />
|
||||||
<ToggleButton.Group
|
<ToggleButton.Group
|
||||||
label="Scenario"
|
label="Scenario"
|
||||||
@@ -268,169 +280,291 @@ export const DebugModScreen = ({}: NativeStackScreenProps<
|
|||||||
|
|
||||||
{scenario[0] === 'label' && (
|
{scenario[0] === 'label' && (
|
||||||
<>
|
<>
|
||||||
<Toggle.Group
|
<View
|
||||||
label="Toggle"
|
style={[
|
||||||
type="checkbox"
|
a.border,
|
||||||
values={scenarioSwitches}
|
a.rounded_sm,
|
||||||
onChange={setScenarioSwitches}>
|
a.mt_lg,
|
||||||
<View style={[a.gap_md, a.flex_row, a.flex_wrap, a.pt_md]}>
|
a.mb_lg,
|
||||||
<Toggle.Item name="targetMe" label="Target is me">
|
a.p_lg,
|
||||||
<Toggle.Checkbox />
|
t.atoms.border_contrast_medium,
|
||||||
<Toggle.Label>Target is me</Toggle.Label>
|
]}>
|
||||||
</Toggle.Item>
|
<Toggle.Group
|
||||||
<Toggle.Item name="following" label="Following target">
|
label="Toggle"
|
||||||
<Toggle.Checkbox />
|
type="radio"
|
||||||
<Toggle.Label>Following target</Toggle.Label>
|
values={label}
|
||||||
</Toggle.Item>
|
onChange={setLabel}>
|
||||||
<Toggle.Item name="selfLabel" label="Self label">
|
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
|
||||||
<Toggle.Checkbox />
|
{LABEL_VALUES.map(labelValue => {
|
||||||
<Toggle.Label>Self label</Toggle.Label>
|
let targetFixed = target[0]
|
||||||
</Toggle.Item>
|
if (
|
||||||
<Toggle.Item name="noAdult" label="Adult disabled">
|
targetFixed !== 'account' &&
|
||||||
<Toggle.Checkbox />
|
targetFixed !== 'profile'
|
||||||
<Toggle.Label>Adult disabled</Toggle.Label>
|
) {
|
||||||
</Toggle.Item>
|
targetFixed = 'content'
|
||||||
<Toggle.Item name="loggedOut" label="Logged out">
|
}
|
||||||
<Toggle.Checkbox />
|
const disabled =
|
||||||
<Toggle.Label>Logged out</Toggle.Label>
|
isSelfLabel &&
|
||||||
</Toggle.Item>
|
LABELS[labelValue].flags.includes('no-self')
|
||||||
|
return (
|
||||||
|
<Toggle.Item
|
||||||
|
key={labelValue}
|
||||||
|
name={labelValue}
|
||||||
|
label={labelStrings[labelValue].general.name}
|
||||||
|
disabled={disabled}
|
||||||
|
style={disabled ? {opacity: 0.5} : undefined}>
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>{labelValue}</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<Toggle.Item
|
||||||
|
name="x-custom"
|
||||||
|
label="Custom label"
|
||||||
|
disabled={isSelfLabel}
|
||||||
|
style={isSelfLabel ? {opacity: 0.5} : undefined}>
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Custom label</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
|
||||||
|
{label[0] === 'x-custom' && (
|
||||||
|
<CustomLabelForm
|
||||||
|
def={customLabelDef}
|
||||||
|
setDef={setCustomLabelDef}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Toggle.Group
|
||||||
|
label="Toggle"
|
||||||
|
type="checkbox"
|
||||||
|
values={scenarioSwitches}
|
||||||
|
onChange={setScenarioSwitches}>
|
||||||
|
<View style={[a.gap_md, a.flex_row, a.flex_wrap, a.pt_md]}>
|
||||||
|
<Toggle.Item name="targetMe" label="Target is me">
|
||||||
|
<Toggle.Checkbox />
|
||||||
|
<Toggle.Label>Target is me</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="following" label="Following target">
|
||||||
|
<Toggle.Checkbox />
|
||||||
|
<Toggle.Label>Following target</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="selfLabel" label="Self label">
|
||||||
|
<Toggle.Checkbox />
|
||||||
|
<Toggle.Label>Self label</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="noAdult" label="Adult disabled">
|
||||||
|
<Toggle.Checkbox />
|
||||||
|
<Toggle.Label>Adult disabled</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="loggedOut" label="Logged out">
|
||||||
|
<Toggle.Checkbox />
|
||||||
|
<Toggle.Label>Logged out</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={[a.flex_row, a.flex_wrap, a.gap_md]}>
|
||||||
|
<View>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.font_bold,
|
||||||
|
a.text_xs,
|
||||||
|
t.atoms.text,
|
||||||
|
a.pl_md,
|
||||||
|
a.pb_xs,
|
||||||
|
]}>
|
||||||
|
Target
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.border,
|
||||||
|
a.rounded_full,
|
||||||
|
a.px_md,
|
||||||
|
a.py_sm,
|
||||||
|
t.atoms.border_contrast_medium,
|
||||||
|
t.atoms.bg,
|
||||||
|
]}>
|
||||||
|
<Toggle.Group
|
||||||
|
label="Target"
|
||||||
|
type="radio"
|
||||||
|
values={target}
|
||||||
|
onChange={setTarget}>
|
||||||
|
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
|
||||||
|
<Toggle.Item name="account" label="Account">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Account</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="profile" label="Profile">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Profile</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="post" label="Post">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Post</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="embed" label="Embed">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Embed</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Toggle.Group>
|
{LABELS[label[0] as keyof typeof LABELS]?.configurable !==
|
||||||
<View style={{height: 10}} />
|
false && (
|
||||||
|
<View>
|
||||||
<Heading title="" subtitle="Target" />
|
<Text
|
||||||
<ToggleButton.Group
|
style={[
|
||||||
label="Target"
|
a.font_bold,
|
||||||
values={target}
|
a.text_xs,
|
||||||
onChange={setTarget}>
|
t.atoms.text,
|
||||||
<ToggleButton.Button name="account" label="Account">
|
a.pl_md,
|
||||||
Account
|
a.pb_xs,
|
||||||
</ToggleButton.Button>
|
]}>
|
||||||
<ToggleButton.Button name="profile" label="Profile">
|
Preference
|
||||||
Profile
|
</Text>
|
||||||
</ToggleButton.Button>
|
<View
|
||||||
<ToggleButton.Button name="post" label="Post">
|
style={[
|
||||||
Post
|
a.border,
|
||||||
</ToggleButton.Button>
|
a.rounded_full,
|
||||||
<ToggleButton.Button name="embed" label="Embed">
|
a.px_md,
|
||||||
Embed
|
a.py_sm,
|
||||||
</ToggleButton.Button>
|
t.atoms.border_contrast_medium,
|
||||||
</ToggleButton.Group>
|
t.atoms.bg,
|
||||||
|
]}>
|
||||||
<View style={{height: 10}} />
|
<Toggle.Group
|
||||||
|
label="Preference"
|
||||||
<Heading title="" subtitle="Preference" />
|
type="radio"
|
||||||
<ToggleButton.Group
|
values={visibility}
|
||||||
label="Visiblity"
|
onChange={setVisiblity}>
|
||||||
values={visibility}
|
<View
|
||||||
onChange={setVisiblity}>
|
style={[
|
||||||
<ToggleButton.Button name="hide" label="Hide">
|
a.flex_row,
|
||||||
Hide
|
a.gap_md,
|
||||||
</ToggleButton.Button>
|
a.flex_wrap,
|
||||||
<ToggleButton.Button name="warn" label="Warn">
|
a.align_center,
|
||||||
Warn
|
]}>
|
||||||
</ToggleButton.Button>
|
<Toggle.Item name="hide" label="Hide">
|
||||||
<ToggleButton.Button name="ignore" label="Ignore">
|
<Toggle.Radio />
|
||||||
Ignore
|
<Toggle.Label>Hide</Toggle.Label>
|
||||||
</ToggleButton.Button>
|
</Toggle.Item>
|
||||||
</ToggleButton.Group>
|
<Toggle.Item name="warn" label="Warn">
|
||||||
|
<Toggle.Radio />
|
||||||
<View style={{height: 10}} />
|
<Toggle.Label>Warn</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
<Heading title="" subtitle="Label" />
|
<Toggle.Item name="ignore" label="Ignore">
|
||||||
<Toggle.Group
|
<Toggle.Radio />
|
||||||
label="Toggle"
|
<Toggle.Label>Ignore</Toggle.Label>
|
||||||
type="radio"
|
</Toggle.Item>
|
||||||
values={label}
|
</View>
|
||||||
onChange={setLabel}>
|
</Toggle.Group>
|
||||||
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
|
</View>
|
||||||
{LABEL_VALUES.map(labelValue => {
|
</View>
|
||||||
let targetFixed = target[0]
|
)}
|
||||||
if (
|
</View>
|
||||||
targetFixed !== 'account' &&
|
|
||||||
targetFixed !== 'profile'
|
|
||||||
) {
|
|
||||||
targetFixed = 'content'
|
|
||||||
}
|
|
||||||
const disabled =
|
|
||||||
isSelfLabel &&
|
|
||||||
LABELS[labelValue].flags.includes('no-self')
|
|
||||||
return (
|
|
||||||
<Toggle.Item
|
|
||||||
key={labelValue}
|
|
||||||
name={labelValue}
|
|
||||||
label={labelStrings[labelValue].general.name}
|
|
||||||
disabled={disabled}
|
|
||||||
style={disabled ? {opacity: 0.5} : undefined}>
|
|
||||||
<Toggle.Radio />
|
|
||||||
<Toggle.Label>{labelValue}</Toggle.Label>
|
|
||||||
</Toggle.Item>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</Toggle.Group>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Spacer />
|
<Spacer />
|
||||||
|
|
||||||
<Heading title="Post" subtitle="in feed" />
|
<Heading title="" subtitle="Results" />
|
||||||
<MockPostFeedItem post={post} moderation={postModeration} />
|
|
||||||
|
|
||||||
<Spacer />
|
<ToggleButton.Group label="Results" values={view} onChange={setView}>
|
||||||
|
<ToggleButton.Button name="post" label="Post">
|
||||||
|
Post
|
||||||
|
</ToggleButton.Button>
|
||||||
|
<ToggleButton.Button name="notifications" label="Notifications">
|
||||||
|
Notifications
|
||||||
|
</ToggleButton.Button>
|
||||||
|
<ToggleButton.Button name="account" label="Account">
|
||||||
|
Account
|
||||||
|
</ToggleButton.Button>
|
||||||
|
<ToggleButton.Button name="data" label="Data">
|
||||||
|
Data
|
||||||
|
</ToggleButton.Button>
|
||||||
|
</ToggleButton.Group>
|
||||||
|
|
||||||
<Heading title="Post" subtitle="viewed directly" />
|
<View
|
||||||
<MockPostThreadItem post={post} moderation={postModeration} />
|
style={[
|
||||||
|
a.border,
|
||||||
|
a.rounded_sm,
|
||||||
|
a.mt_lg,
|
||||||
|
a.p_md,
|
||||||
|
t.atoms.border_contrast_medium,
|
||||||
|
]}>
|
||||||
|
{view[0] === 'post' && (
|
||||||
|
<>
|
||||||
|
<Heading title="Post" subtitle="in feed" />
|
||||||
|
<MockPostFeedItem post={post} moderation={postModeration} />
|
||||||
|
|
||||||
<Spacer />
|
<Heading title="Post" subtitle="viewed directly" />
|
||||||
|
<MockPostThreadItem post={post} moderation={postModeration} />
|
||||||
|
|
||||||
<Heading title="Post" subtitle="reply in thread" />
|
<Heading title="Post" subtitle="reply in thread" />
|
||||||
<MockPostThreadItem post={post} moderation={postModeration} reply />
|
<MockPostThreadItem
|
||||||
|
post={post}
|
||||||
|
moderation={postModeration}
|
||||||
|
reply
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Spacer />
|
{view[0] === 'notifications' && (
|
||||||
|
<>
|
||||||
|
<Heading title="Notification" subtitle="quote or reply" />
|
||||||
|
<MockNotifItem notif={replyNotif} moderationOpts={modOpts} />
|
||||||
|
|
||||||
<Heading title="Notification" subtitle="quote or reply" />
|
<Spacer />
|
||||||
<MockNotifItem notif={replyNotif} moderationOpts={modOpts} />
|
|
||||||
|
|
||||||
<Spacer />
|
<Heading title="Notification" subtitle="follow or like" />
|
||||||
|
<MockNotifItem notif={followNotif} moderationOpts={modOpts} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{(target[0] === 'account' || target[0] === 'profile') && (
|
{view[0] === 'account' && (
|
||||||
<>
|
<>
|
||||||
<Heading title="Notification" subtitle="follow or like" />
|
<Heading title="Account" subtitle="in listing" />
|
||||||
<MockNotifItem notif={followNotif} moderationOpts={modOpts} />
|
<MockAccountCard
|
||||||
|
profile={profile}
|
||||||
|
moderation={profileModeration}
|
||||||
|
/>
|
||||||
|
|
||||||
<Spacer />
|
<Spacer />
|
||||||
|
|
||||||
<Heading title="Account" subtitle="in listing" />
|
<Heading title="Account" subtitle="viewing directly" />
|
||||||
<MockAccountCard
|
<MockAccountScreen
|
||||||
profile={profile}
|
profile={profile}
|
||||||
moderation={profileModeration}
|
moderation={profileModeration}
|
||||||
/>
|
moderationOpts={modOpts}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Spacer />
|
{view[0] === 'data' && (
|
||||||
|
<>
|
||||||
<Heading title="Account" subtitle="viewing directly" />
|
<ModerationUIView
|
||||||
<MockAccountScreen
|
label="Profile Moderation UI"
|
||||||
profile={profile}
|
mod={profileModeration}
|
||||||
moderation={profileModeration}
|
/>
|
||||||
moderationOpts={modOpts}
|
<ModerationUIView
|
||||||
/>
|
label="Post Moderation UI"
|
||||||
|
mod={postModeration}
|
||||||
<Spacer />
|
/>
|
||||||
</>
|
<DataView
|
||||||
)}
|
label={label[0]}
|
||||||
|
data={LABELS[label[0] as keyof typeof LABELS]}
|
||||||
<ModerationUIView
|
/>
|
||||||
label="Profile Moderation UI"
|
<DataView
|
||||||
mod={profileModeration}
|
label="Profile Moderation Data"
|
||||||
/>
|
data={profileModeration}
|
||||||
<ModerationUIView label="Post Moderation UI" mod={postModeration} />
|
/>
|
||||||
<DataView
|
<DataView label="Post Moderation Data" data={postModeration} />
|
||||||
label={label[0]}
|
</>
|
||||||
data={LABELS[label[0] as keyof typeof LABELS]}
|
)}
|
||||||
/>
|
</View>
|
||||||
<DataView label="Profile Moderation Data" data={profileModeration} />
|
|
||||||
<DataView label="Post Moderation Data" data={postModeration} />
|
|
||||||
|
|
||||||
<View style={{height: 400}} />
|
<View style={{height: 400}} />
|
||||||
</CenteredView>
|
</CenteredView>
|
||||||
@@ -451,6 +585,101 @@ function Heading({title, subtitle}: {title: string; subtitle?: string}) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CustomLabelForm({
|
||||||
|
def,
|
||||||
|
setDef,
|
||||||
|
}: {
|
||||||
|
def: ComAtprotoLabelDefs.LabelValueDefinition
|
||||||
|
setDef: React.Dispatch<
|
||||||
|
React.SetStateAction<ComAtprotoLabelDefs.LabelValueDefinition>
|
||||||
|
>
|
||||||
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.flex_wrap,
|
||||||
|
a.gap_md,
|
||||||
|
t.atoms.bg_contrast_50,
|
||||||
|
a.rounded_md,
|
||||||
|
a.p_md,
|
||||||
|
a.mt_md,
|
||||||
|
]}>
|
||||||
|
<View>
|
||||||
|
<Text style={[a.font_bold, a.text_xs, t.atoms.text, a.pl_md, a.pb_xs]}>
|
||||||
|
Blurs
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.border,
|
||||||
|
a.rounded_full,
|
||||||
|
a.px_md,
|
||||||
|
a.py_sm,
|
||||||
|
t.atoms.border_contrast_medium,
|
||||||
|
t.atoms.bg,
|
||||||
|
]}>
|
||||||
|
<Toggle.Group
|
||||||
|
label="Blurs"
|
||||||
|
type="radio"
|
||||||
|
values={[def.blurs]}
|
||||||
|
onChange={values => setDef(v => ({...v, blurs: values[0]}))}>
|
||||||
|
<View style={[a.flex_row, a.gap_md, a.flex_wrap]}>
|
||||||
|
<Toggle.Item name="content" label="Content">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Content</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="media" label="Media">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Media</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="none" label="None">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>None</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Text style={[a.font_bold, a.text_xs, t.atoms.text, a.pl_md, a.pb_xs]}>
|
||||||
|
Severity
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.border,
|
||||||
|
a.rounded_full,
|
||||||
|
a.px_md,
|
||||||
|
a.py_sm,
|
||||||
|
t.atoms.border_contrast_medium,
|
||||||
|
t.atoms.bg,
|
||||||
|
]}>
|
||||||
|
<Toggle.Group
|
||||||
|
label="Severity"
|
||||||
|
type="radio"
|
||||||
|
values={[def.severity]}
|
||||||
|
onChange={values => setDef(v => ({...v, severity: values[0]}))}>
|
||||||
|
<View style={[a.flex_row, a.gap_md, a.flex_wrap, a.align_center]}>
|
||||||
|
<Toggle.Item name="alert" label="Alert">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Alert</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="inform" label="Inform">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>Inform</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
<Toggle.Item name="none" label="None">
|
||||||
|
<Toggle.Radio />
|
||||||
|
<Toggle.Label>None</Toggle.Label>
|
||||||
|
</Toggle.Item>
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function Toggler({label, children}: React.PropsWithChildren<{label: string}>) {
|
function Toggler({label, children}: React.PropsWithChildren<{label: string}>) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const [show, setShow] = React.useState(false)
|
const [show, setShow] = React.useState(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user