A bunch of speculative non-working UI

This commit is contained in:
Paul Frazee
2024-02-22 16:32:22 -08:00
parent acd9532331
commit 047df5939f
8 changed files with 320 additions and 28 deletions
+3
View File
@@ -216,6 +216,9 @@ export const atoms = {
font_normal: {
fontWeight: tokens.fontWeight.normal,
},
font_semibold: {
fontWeight: '500',
},
font_bold: {
fontWeight: tokens.fontWeight.semibold,
},
@@ -78,7 +78,7 @@ export function Content({
) : (
<Text>
<Trans>
Moderation service managed by @{sanitizeHandle(handle, '@')}
Moderation service managed by {sanitizeHandle(handle, '@')}
</Trans>
</Text>
)}
@@ -23,7 +23,7 @@ export function Link({
return (
<InternalLink
to={{
screen: 'ProfileModservice',
screen: 'Profile',
params: {
name: modservice.creator.handle,
},
@@ -116,6 +116,10 @@ export function useLabelGroupStrings(): LabelGroupStrings {
msg`Helpful annotations to explain intent, such as satire or parody.`,
),
},
bot: {
name: _(msg`Bots`),
description: _(msg`Automated accounts which follow the rules.`),
},
other: {
name: _(msg`Other`),
description: _(msg`Other content not covered by the other categories.`),
+285 -13
View File
@@ -1,7 +1,7 @@
import React from 'react'
import {View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {ComAtprotoLabelDefs, LabelPreference} from '@atproto/api'
import {ComAtprotoLabelDefs, LabelPreference, LABELS} from '@atproto/api'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {LabelGroupDefinition, AppBskyModerationDefs} from '@atproto/api'
@@ -24,6 +24,7 @@ import {
UsePreferencesQueryResponse,
usePreferencesQuery,
useSetContentLabelMutation,
usePreferencesSetAdultContentMutation,
} from '#/state/queries/preferences'
import {useModServicesDetailedInfoQuery} from '#/state/queries/modservice'
import {useModServiceLabelGroupEnableMutation} from '#/state/queries/modservice'
@@ -182,6 +183,27 @@ export function ModerationScreenInner({
[modSettingsDialogControl],
)
const {mutateAsync: setAdultContentPref, variables: optimisticAdultContent} =
usePreferencesSetAdultContentMutation()
const adultContentEnabled = !!(
(optimisticAdultContent && optimisticAdultContent.enabled) ||
(!optimisticAdultContent && preferences.moderationOpts.adultContentEnabled)
)
const onToggleAdultContentEnabled = React.useCallback(
async (selected: boolean) => {
try {
await setAdultContentPref({
enabled: selected,
})
} catch (e) {
// TODO
console.error(e)
}
},
[setAdultContentPref],
)
return (
<View>
<Dialog.Outer control={modSettingsDialogControl}>
@@ -275,6 +297,110 @@ export function ModerationScreenInner({
</Link>
</View>
<Text
style={[
a.pt_2xl,
a.pb_md,
a.text_md,
a.font_bold,
t.atoms.text_contrast_high,
]}>
<Trans>Content filters</Trans>
</Text>
<View
style={[
a.w_full,
a.rounded_md,
a.overflow_hidden,
t.atoms.bg_contrast_25,
]}>
<View
style={[a.pt_lg, a.pb_md, a.px_lg, a.flex_row, a.justify_between]}>
<Text
style={[a.text_md, a.font_semibold, t.atoms.text_contrast_high]}>
<Trans>Enable adult content</Trans>
</Text>
<Toggle.Item
label={'Toggle adult content'}
name="adultContent"
value={adultContentEnabled}
onChange={onToggleAdultContentEnabled}>
<View style={[a.flex_row, a.align_center, a.gap_sm]}>
<Text style={[t.atoms.text_contrast_medium]}>
{adultContentEnabled ? (
<Trans>Enabled</Trans>
) : (
<Trans>Disabled</Trans>
)}
</Text>
<Toggle.Switch />
</View>
</Toggle.Item>
</View>
{adultContentEnabled && (
<>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'porn')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'suggestive')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'nudity')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'violence')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
</>
)}
<Divider />
<View
style={[a.pt_lg, a.pb_md, a.px_lg, a.flex_row, a.justify_between]}>
<View style={[a.flex_wrap, a.flex_1]}>
<Text
style={[
a.text_md,
a.font_semibold,
t.atoms.text_contrast_high,
a.pb_xs,
]}>
<Trans>Hide posts by bots</Trans>
</Text>
<Text style={[t.atoms.text_contrast_medium]}>
<Trans>Bots are automated users which follow the rules.</Trans>
</Text>
</View>
<Toggle.Item
label={'Toggle hiding posts by bots'}
name="hideBots"
value={false}
onChange={undefined}>
<View style={[a.flex_row, a.align_center, a.gap_sm]}>
<Text style={[t.atoms.text_contrast_medium]}>
{false ? <Trans>Enabled</Trans> : <Trans>Disabled</Trans>}
</Text>
<Toggle.Switch />
</View>
</Toggle.Item>
</View>
</View>
<Text
style={[
a.text_md,
@@ -283,10 +409,34 @@ export function ModerationScreenInner({
a.pb_md,
t.atoms.text_contrast_high,
]}>
<Trans>Labelers</Trans>
<Trans>Advanced</Trans>
</Text>
<View style={[a.gap_sm, a.rounded_sm, t.atoms.bg_contrast_25]}>
<View style={[a.rounded_sm, t.atoms.bg_contrast_25]}>
<ModerationServiceCard.Link
modservice={{
uri: '',
cid: '',
policies: {},
creator: {
did: '',
handle: 'safety.bsky.app',
displayName: 'Bluesky Safety',
},
indexedAt: new Date().toISOString(),
}}>
<ModerationServiceCard.Card.Outer>
<ModerationServiceCard.Card.Avatar avatar={undefined} />
<ModerationServiceCard.Card.Content
title={getModerationServiceTitle({
displayName: 'Bluesky Safety',
handle: 'safety.bsky.app',
})}
handle={'safety.bsky.app'}
description={'Official moderation team'}
/>
</ModerationServiceCard.Card.Outer>
</ModerationServiceCard.Link>
<Divider />
{modservices.map(mod => {
return (
<ModerationServiceCard.Link
@@ -310,6 +460,125 @@ export function ModerationScreenInner({
})}
</View>
{
undefined /*<Text
style={[
a.text_md,
a.font_bold,
a.pt_2xl,
a.pb_md,
t.atoms.text_contrast_high,
]}>
<Trans>Bluesky Safety</Trans>{' '}
<Text style={[a.text_sm, a.pb_md, t.atoms.text_contrast_medium]}>
@safety.bsky.app
</Text>
</Text>
<View
style={[
a.w_full,
a.rounded_md,
a.overflow_hidden,
t.atoms.bg_contrast_25,
]}>
<LabelGroup
labelGroup={groups.find(g => g.id === 'intolerance')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'misrepresentation')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'security')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
<Divider />
<LabelGroup
labelGroup={groups.find(g => g.id === 'spam')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
</View>
{modservices.map(mod => {
return (
<>
<Text
style={[
a.text_md,
a.font_bold,
a.pt_2xl,
a.pb_md,
t.atoms.text_contrast_high,
]}>
{mod.creator.displayName}{' '}
<Text
style={[a.text_sm, a.pb_md, t.atoms.text_contrast_medium]}>
@{mod.creator.handle}
</Text>
</Text>
<View
style={[
a.w_full,
a.rounded_md,
a.overflow_hidden,
t.atoms.bg_contrast_25,
]}>
{mod.policies.labelValues
.filter(label => !label.startsWith('!'))
.map((label, i) => {
return (
<React.Fragment key={mod.did + '-' + label}>
{i !== 0 && <Divider />}
<LabelGroup
labelGroup={LABELS[label].groupId}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
</React.Fragment>
)
})}
</View>
</>
)
})}
<Text
style={[
a.text_md,
a.font_bold,
a.pt_2xl,
a.pb_md,
t.atoms.text_contrast_high,
]}>
<Trans>Other</Trans>
</Text>
<View
style={[
a.w_full,
a.rounded_md,
a.overflow_hidden,
t.atoms.bg_contrast_25,
]}>
<LabelGroup
labelGroup={groups.find(g => g.id === 'bot')!.id}
labelers={[]}
preferences={preferences}
openModSettingsDialog={openModSettingsDialog}
/>
</View>
<Text
style={[
a.text_md,
@@ -342,7 +611,8 @@ export function ModerationScreenInner({
</React.Fragment>
)
})}
</View>
</View>*/
}
<Text
style={[
@@ -404,11 +674,11 @@ function LabelGroup({
const labelOptions = {
hide: _(msg`Hide`),
warn: _(msg`Warn`),
show: _(msg`Show`),
// show: _(msg`Show`),
}
return (
<View style={[a.px_md, a.pr_md, gtMobile && a.px_lg]}>
<View style={[a.px_lg, a.pr_md, gtMobile && a.px_lg]}>
<View
style={[
a.py_md,
@@ -418,7 +688,7 @@ function LabelGroup({
a.align_center,
]}>
<View style={[a.gap_xs, {width: '50%'}]}>
<Text style={[a.font_bold, t.atoms.text_contrast_medium]}>
<Text style={[a.font_semibold, t.atoms.text_contrast_high]}>
{name}
</Text>
<Text style={[a.leading_tight, {maxWidth: 400}]}>{description}</Text>
@@ -431,15 +701,17 @@ function LabelGroup({
)}
values={[value]}
onChange={onChangeVisibility}>
<ToggleButton.Button name="hide" label={labelOptions.hide}>
{labelOptions.hide}
</ToggleButton.Button>
<ToggleButton.Button name="warn" label={labelOptions.warn}>
{labelOptions.warn}
</ToggleButton.Button>
<ToggleButton.Button name="ignore" label={labelOptions.show}>
{labelOptions.show}
<ToggleButton.Button name="hide" label={labelOptions.hide}>
{labelOptions.hide}
</ToggleButton.Button>
{
undefined /*<ToggleButton.Button name="ignore" label={labelOptions.show}>
{labelOptions.show}
</ToggleButton.Button>*/
}
</ToggleButton.Group>
</View>
</View>
@@ -161,7 +161,7 @@ export function ProfileContentFiltersSectionInner({
borderWidth: 0,
paddingHorizontal: a.px_xl.paddingLeft,
}}>
{isSubscribed ? (
{false /* TODO wanted? isSubscribed*/ ? (
<View style={[a.flex_row, a.pr_lg, a.pt_xl]}>
<View style={[a.gap_sm, a.flex_1]}>
<Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
@@ -185,7 +185,7 @@ export function ProfileContentFiltersSectionInner({
) : (
<View style={[a.gap_sm, a.pt_xl]}>
<Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
This labeler moderates the following types of content.
This service labels the following types of content.
</Text>
</View>
)}
@@ -12,7 +12,7 @@ import {logger} from '#/logger'
import {useTheme, atoms as a} from '#/alf'
import {Text} from '#/components/Typography'
import * as Toggle from '#/components/forms/Toggle'
import * as ToggleButton from '#/components/forms/ToggleButton'
export function PreferenceRow({
labelGroup,
@@ -50,6 +50,12 @@ export function PreferenceRow({
}
}, [mutateAsync, enabled, modservicePreferences, labelGroup])
const labelOptions = {
hide: _(msg`Hide`),
warn: _(msg`Warn`),
show: _(msg`Ignore`),
}
return (
<View
style={[
@@ -67,15 +73,22 @@ export function PreferenceRow({
</View>
<View style={[a.justify_center, {minHeight: 35}]}>
{modservicePreferences && (
<Toggle.Item
disabled={disabled}
name="enable"
value={disabled ? false : enabled}
onChange={onToggleEnabled}
label={_(msg`Enable`)}>
<Toggle.Label>{enabled ? 'Enabled' : 'Disabled'}</Toggle.Label>
<Toggle.Switch />
</Toggle.Item>
<ToggleButton.Group
label={_(
msg`Configure content filtering setting for category: ${groupInfoStrings.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>
</View>
+1 -1
View File
@@ -490,7 +490,7 @@ function ProfileScreenLoadedV2({
const sectionTitles = useMemo<string[]>(() => {
return [
showFiltersTab ? _(msg`Content Filters`) : undefined,
showFiltersTab ? _(msg`Content filters`) : undefined,
showPostsTab ? _(msg`Posts`) : undefined,
showRepliesTab ? _(msg`Replies`) : undefined,
showMediaTab ? _(msg`Media`) : undefined,