Hook up data to settings page

This commit is contained in:
Eric Bailey
2024-02-13 12:40:24 -06:00
parent 6f5058d474
commit 02bbc5e0d5
3 changed files with 69 additions and 44 deletions
+22 -1
View File
@@ -1,4 +1,10 @@
import {ModerationCause, ProfileModeration, PostModeration} from '@atproto/api' import {
ModerationCause,
ProfileModeration,
PostModeration,
LABEL_GROUPS,
LabelGroupDefinition,
} from '@atproto/api'
export function getProfileModerationCauses( export function getProfileModerationCauses(
moderation: ProfileModeration, moderation: ProfileModeration,
@@ -70,3 +76,18 @@ export function getModerationCauseKey(cause: ModerationCause): string {
} }
return `${cause.type}:${source}` return `${cause.type}:${source}`
} }
export function getLabelGroupsFromLabels(labels: string[]) {
const groups: LabelGroupDefinition[] = []
for (const label of labels) {
for (const group in LABEL_GROUPS) {
const def = LABEL_GROUPS[group as LabelGroupDefinition['id']]
if (def.labels.find(l => l.id === label)) {
groups.push(def)
}
}
}
return Array.from(groups)
}
+19 -18
View File
@@ -30,9 +30,9 @@ import {Bars3_Stroke2_Corner0_Rounded as Bars} from '#/components/icons/Bars'
import {Divider} from '#/components/Divider' import {Divider} from '#/components/Divider'
export function Header({ export function Header({
info, modservice,
}: { }: {
info: AppBskyModerationDefs.ModServiceViewDetailed modservice: AppBskyModerationDefs.ModServiceViewDetailed
}) { }) {
const t = useTheme() const t = useTheme()
const {gtMobile} = useBreakpoints() const {gtMobile} = useBreakpoints()
@@ -81,7 +81,7 @@ export function Header({
</ButtonText> </ButtonText>
</Button> </Button>
<CommonControls info={info} /> <CommonControls modservice={modservice} />
</View> </View>
</View> </View>
@@ -98,8 +98,8 @@ export function Header({
a.overflow_hidden, a.overflow_hidden,
]}> ]}>
<LinearGradient <LinearGradient
colors={tokens.gradients.bonfire.values.map(c => c[1])} colors={tokens.gradients.midnight.values.map(c => c[1])}
locations={tokens.gradients.bonfire.values.map(c => c[0])} locations={tokens.gradients.midnight.values.map(c => c[0])}
start={{x: 0, y: 0}} start={{x: 0, y: 0}}
end={{x: 1, y: 1}} end={{x: 1, y: 1}}
style={[a.absolute, a.inset_0]} style={[a.absolute, a.inset_0]}
@@ -115,10 +115,11 @@ export function Header({
onPress={emitSoftReset} onPress={emitSoftReset}
style={[a.justify_start]}> style={[a.justify_start]}>
<Text style={[a.text_4xl, a.font_bold, t.atoms.text]}> <Text style={[a.text_4xl, a.font_bold, t.atoms.text]}>
{/* A really long and complex title for a moderation service */} {modservice.displayName
{info.creator.displayName ? sanitizeDisplayName(modservice.displayName)
? sanitizeDisplayName(info.creator.displayName) : modservice.creator.displayName
: sanitizeHandle(info.creator.handle, '@')} ? sanitizeDisplayName(modservice.creator.displayName)
: sanitizeHandle(modservice.creator.handle, '@')}
</Text> </Text>
</Button> </Button>
@@ -139,7 +140,7 @@ export function Header({
</ButtonText> </ButtonText>
</Button> </Button>
<CommonControls info={info} /> <CommonControls modservice={modservice} />
</View> </View>
)} )}
</View> </View>
@@ -148,9 +149,9 @@ export function Header({
} }
function CommonControls({ function CommonControls({
info, modservice,
}: { }: {
info: AppBskyModerationDefs.ModServiceViewDetailed modservice: AppBskyModerationDefs.ModServiceViewDetailed
}) { }) {
const t = useTheme() const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
@@ -158,19 +159,19 @@ function CommonControls({
const {openModal} = useModalControls() const {openModal} = useModalControls()
const onPressShare = React.useCallback(() => { const onPressShare = React.useCallback(() => {
const url = makeProfileLink(info.creator, 'modservice') const url = makeProfileLink(modservice.creator, 'modservice')
shareUrl(url) shareUrl(url)
// track('CustomFeed:Share') TODO // track('CustomFeed:Share') TODO
}, [info /*, track*/]) }, [modservice /*, track*/])
const onPressReport = React.useCallback(() => { const onPressReport = React.useCallback(() => {
if (!info) return if (!modservice) return
openModal({ openModal({
name: 'report', name: 'report',
uri: info.uri, uri: modservice.uri,
cid: info.cid, cid: modservice.cid,
}) })
}, [openModal, info]) }, [openModal, modservice])
const dropdownItems: DropdownItem[] = React.useMemo(() => { const dropdownItems: DropdownItem[] = React.useMemo(() => {
return [ return [
+28 -25
View File
@@ -1,10 +1,9 @@
import React from 'react' import React from 'react'
import {Dimensions, View} from 'react-native' import {Dimensions, View} from 'react-native'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {AppBskyModerationDefs, LabelGroupDefinition} from '@atproto/api' import {AppBskyModerationDefs} from '@atproto/api'
import {Trans, msg} from '@lingui/macro' import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {LABEL_GROUPS} from '@atproto/api'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {CommonNavigatorParams} from '#/lib/routes/types' import {CommonNavigatorParams} from '#/lib/routes/types'
@@ -28,6 +27,8 @@ import {useSession} from '#/state/session'
import {useLikeMutation, useUnlikeMutation} from '#/state/queries/like' import {useLikeMutation, useUnlikeMutation} from '#/state/queries/like'
import {sanitizeHandle} from '#/lib/strings/handles' import {sanitizeHandle} from '#/lib/strings/handles'
import {getLabelGroupsFromLabels} from '#/lib/moderation'
import {useTheme, atoms as a} from '#/alf' import {useTheme, atoms as a} from '#/alf'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
@@ -108,7 +109,7 @@ function ProfileModservicecreenIntermediate({modDid}: {modDid: string}) {
<Loader size="xl" fill={t.atoms.text.color} /> <Loader size="xl" fill={t.atoms.text.color} />
</View> </View>
) : preferences && info ? ( ) : preferences && info ? (
<ProfileModserviceScreenInner preferences={preferences} modInfo={info} /> <ProfileModserviceScreenInner preferences={preferences} modservice={info} />
) : ( ) : (
<ErrorState <ErrorState
error={ error={
@@ -120,10 +121,10 @@ function ProfileModservicecreenIntermediate({modDid}: {modDid: string}) {
export function ProfileModserviceScreenInner({ export function ProfileModserviceScreenInner({
// preferences, // preferences,
modInfo, modservice,
}: { }: {
preferences: UsePreferencesQueryResponse preferences: UsePreferencesQueryResponse
modInfo: AppBskyModerationDefs.ModServiceViewDetailed modservice: AppBskyModerationDefs.ModServiceViewDetailed
}) { }) {
const t = useTheme() const t = useTheme()
const {_} = useLingui() const {_} = useLingui()
@@ -134,13 +135,13 @@ export function ProfileModserviceScreenInner({
const {mutateAsync: unlikeMod, isPending: isUnlikePending} = const {mutateAsync: unlikeMod, isPending: isUnlikePending} =
useUnlikeMutation() useUnlikeMutation()
const [likeUri, setLikeUri] = React.useState<string>( const [likeUri, setLikeUri] = React.useState<string>(
modInfo.viewer?.like || '', modservice.viewer?.like || '',
) )
const groups = React.useMemo< const groups = React.useMemo(() => {
[keyof typeof LABEL_GROUPS, LabelGroupDefinition][] return getLabelGroupsFromLabels(modservice.policies.labelValues).filter(
>(() => { def => def.configurable,
return Object.entries(LABEL_GROUPS).filter(([, def]) => def.configurable) )
}, []) }, [modservice.policies.labelValues])
const isLiked = !!likeUri const isLiked = !!likeUri
// const isSaved = false // TODO // const isSaved = false // TODO
@@ -150,7 +151,7 @@ export function ProfileModserviceScreenInner({
// !unpinnedFeed && // !unpinnedFeed &&
// (!!pinnedFeed || preferences.feeds.pinned.includes(feedInfo.uri)) // (!!pinnedFeed || preferences.feeds.pinned.includes(feedInfo.uri))
useSetTitle(modInfo.creator.displayName || modInfo.creator.handle) useSetTitle(modservice.creator.displayName || modservice.creator.handle)
// event handlers // event handlers
// //
@@ -163,7 +164,7 @@ export function ProfileModserviceScreenInner({
track('CustomFeed:Unlike') track('CustomFeed:Unlike')
setLikeUri('') setLikeUri('')
} else { } else {
const res = await likeMod({uri: modInfo.uri, cid: modInfo.cid}) const res = await likeMod({uri: modservice.uri, cid: modservice.cid})
track('CustomFeed:Like') track('CustomFeed:Like')
setLikeUri(res.uri) setLikeUri(res.uri)
} }
@@ -175,7 +176,7 @@ export function ProfileModserviceScreenInner({
) )
logger.error('Failed up toggle like', {error: err}) logger.error('Failed up toggle like', {error: err})
} }
}, [likeUri, isLiked, modInfo, likeMod, unlikeMod, track, _]) }, [likeUri, isLiked, modservice, likeMod, unlikeMod, track, _])
return ( return (
<ScrollView <ScrollView
@@ -185,14 +186,14 @@ export function ProfileModserviceScreenInner({
borderWidth: 0, borderWidth: 0,
paddingHorizontal: a.px_xl.paddingLeft, paddingHorizontal: a.px_xl.paddingLeft,
}}> }}>
<Header info={modInfo} /> <Header modservice={modservice} />
<View style={[a.gap_md]}> <View style={[a.gap_md]}>
{modInfo.description ? ( {modservice.description ? (
<RichText <RichText
testID="modinfoDescription" testID="modinfoDescription"
resolveFacets resolveFacets
value={modInfo.description} value={modservice.description}
style={[a.text_md, a.leading_normal]} style={[a.text_md, a.leading_normal]}
/> />
) : ( ) : (
@@ -203,7 +204,9 @@ export function ProfileModserviceScreenInner({
t.atoms.text_contrast_medium, t.atoms.text_contrast_medium,
{fontStyle: 'italic'}, {fontStyle: 'italic'},
]}> ]}>
<Trans>No description</Trans> <Trans>
Moderation service managed by @{modservice.creator.handle}
</Trans>
</Text> </Text>
)} )}
@@ -217,8 +220,8 @@ export function ProfileModserviceScreenInner({
<Trans> <Trans>
Operated by{' '} Operated by{' '}
<TextLink <TextLink
href={makeProfileLink(modInfo.creator)} href={makeProfileLink(modservice.creator)}
text={sanitizeHandle(modInfo.creator.handle, '@')} text={sanitizeHandle(modservice.creator.handle, '@')}
style={pal.link} style={pal.link}
/> />
. Handles reports of anti-social behavior, illegal content, unwanted . Handles reports of anti-social behavior, illegal content, unwanted
@@ -243,11 +246,11 @@ export function ProfileModserviceScreenInner({
)} )}
</Button> </Button>
{typeof modInfo.likeCount === 'number' && ( {typeof modservice.likeCount === 'number' && (
<InlineLink to={'#todo'} style={[pal.textLight, s.semiBold]}> <InlineLink to={'#todo'} style={[pal.textLight, s.semiBold]}>
<Trans> <Trans>
Liked by {modInfo.likeCount}{' '} Liked by {modservice.likeCount}{' '}
{pluralize(modInfo.likeCount, 'user')} {pluralize(modservice.likeCount, 'user')}
</Trans> </Trans>
</InlineLink> </InlineLink>
)} )}
@@ -255,11 +258,11 @@ export function ProfileModserviceScreenInner({
</View> </View>
<View style={[a.gap_md, a.mt_xl]}> <View style={[a.gap_md, a.mt_xl]}>
{groups.map(([name, def]) => { {groups.map(def => {
return ( return (
<React.Fragment key={def.id}> <React.Fragment key={def.id}>
<Divider /> <Divider />
<PreferenceRow labelGroup={name} /> <PreferenceRow labelGroup={def.id} />
</React.Fragment> </React.Fragment>
) )
})} })}