diff --git a/src/components/Loader.tsx b/src/components/Loader.tsx
index bbe4e2f75c..031af03775 100644
--- a/src/components/Loader.tsx
+++ b/src/components/Loader.tsx
@@ -7,11 +7,12 @@ import Animated, {
withTiming,
} from 'react-native-reanimated'
-import {atoms as a} from '#/alf'
+import {atoms as a, useTheme} from '#/alf'
import {Props, useCommonSVGProps} from '#/components/icons/common'
import {Loader_Stroke2_Corner0_Rounded as Icon} from '#/components/icons/Loader'
export function Loader(props: Props) {
+ const t = useTheme()
const common = useCommonSVGProps(props)
const rotation = useSharedValue(0)
@@ -35,7 +36,10 @@ export function Loader(props: Props) {
{width: common.size, height: common.size},
animatedStyles,
]}>
-
+
)
}
diff --git a/src/screens/Moderation/index.tsx b/src/screens/Moderation/index.tsx
index 32b7cfb174..620133f1ad 100644
--- a/src/screens/Moderation/index.tsx
+++ b/src/screens/Moderation/index.tsx
@@ -5,6 +5,7 @@ import {ComAtprotoLabelDefs, LabelPreference} from '@atproto/api'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {LabelGroupDefinition, AppBskyModerationDefs} from '@atproto/api'
+import {useSafeAreaFrame} from 'react-native-safe-area-context'
import {NativeStackScreenProps, CommonNavigatorParams} from '#/lib/routes/types'
import {CenteredView} from '#/view/com/util/Views'
@@ -39,9 +40,9 @@ import {useLabelGroupStrings} from '#/lib/moderation/useLabelGroupStrings'
import * as Dialog from '#/components/Dialog'
import {Button} from '#/components/Button'
import {
- getLabelGroupsFromLabels,
getModerationServiceTitle,
useConfigurableLabelGroups,
+ getLabelGroupToLabelerMap,
} from '#/lib/moderation'
import {
@@ -49,51 +50,91 @@ import {
SettingsDialogProps,
} from '#/screens/Moderation/SettingsDialog'
+function ErrorState({error}: {error: string}) {
+ const t = useTheme()
+ return (
+
+
+
+ Hmmmm, it seems we're having trouble loading this data. See below for
+ more details. If this issue persists, please contact us.
+
+
+
+ {error}
+
+
+ )
+}
+
export function ModerationScreen(
_props: NativeStackScreenProps,
) {
const t = useTheme()
+ const {_} = useLingui()
const {
isLoading: isPreferencesLoading,
- // error: preferencesError,
+ error: preferencesError,
data: preferences,
} = usePreferencesQuery()
-
- return isPreferencesLoading ? (
-
-
-
- ) : preferences ? (
-
- ) : // TODO
- null
-}
-
-function ModerationScreenIntermediate({
- preferences,
-}: {
- preferences: UsePreferencesQueryResponse
-}) {
- const t = useTheme()
const {
isLoading: isModServicesLoading,
data: modservices,
- // error: modservicesError,
+ error: modservicesError,
} = useModServicesDetailedInfoQuery({
- dids: preferences.moderationOpts.mods.map(m => m.did),
+ dids: preferences ? preferences.moderationOpts.mods.map(m => m.did) : [],
})
+ const {gtMobile} = useBreakpoints()
+ const {height} = useSafeAreaFrame()
- return isModServicesLoading ? (
-
-
-
- ) : modservices ? (
-
- ) : // TODO
- null
+ const isLoading = isPreferencesLoading || isModServicesLoading
+ const error = preferencesError || modservicesError
+
+ return (
+
+
+
+ {isLoading ? (
+
+
+
+ ) : error || !(preferences && modservices) ? (
+
+ ) : (
+
+ )}
+
+ )
}
export function ModerationScreenInner({
@@ -104,19 +145,20 @@ export function ModerationScreenInner({
modservices: AppBskyModerationDefs.ModServiceViewDetailed[]
}) {
const t = useTheme()
- const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
const {screen} = useAnalytics()
- const {gtMobile, gtTablet} = useBreakpoints()
- const labelGroupStrings = useLabelGroupStrings()
+ const {gtTablet} = useBreakpoints()
const modSettingsDialogControl = Dialog.useDialogControl()
-
const [settingsDialogProps, setSettingsDialogProps] =
React.useState({
- // @ts-ignore
- labelGroup: '',
+ // prefill with valid value to appease TS
+ labelGroup: 'intolerance',
modservices: [],
})
+ const groups = useConfigurableLabelGroups()
+ const labelGroupToLabelerMap = React.useMemo(() => {
+ return getLabelGroupToLabelerMap(modservices)
+ }, [modservices])
useFocusEffect(
React.useCallback(() => {
@@ -125,34 +167,6 @@ export function ModerationScreenInner({
}, [screen, setMinimalShellMode]),
)
- const groups = useConfigurableLabelGroups()
-
- const didToModServiceMap = React.useMemo<
- Record
- >(() => {
- return modservices.reduce((acc, modservice) => {
- return {
- ...acc,
- [modservice.creator.did]: modservice,
- }
- }, {})
- }, [modservices])
- const labelGroupToModServiceMap = React.useMemo(() => {
- const groups: Partial> = {}
-
- for (const modservice of modservices) {
- const labelGroups = getLabelGroupsFromLabels(
- modservice.policies.labelValues,
- )
- for (const group of labelGroups) {
- const g = (groups[group.id] = groups[group.id] || [])
- g.push(modservice.creator.did)
- }
- }
-
- return groups
- }, [modservices])
-
const openModSettingsDialog = React.useCallback(
({labelGroup, modservices}: Omit) => {
setSettingsDialogProps({
@@ -165,21 +179,12 @@ export function ModerationScreenInner({
)
return (
-
+
-
-
{!gtTablet && }
@@ -252,19 +257,15 @@ export function ModerationScreenInner({
{groups.map((def, i) => {
- const groupStrings = labelGroupStrings[def.id]
- const modDids = labelGroupToModServiceMap[def.id] || []
- const mods = modDids.map(did => didToModServiceMap[did])
+ const labelers = labelGroupToLabelerMap[def.id] || []
return (
{i !== 0 && }
)
@@ -280,27 +281,24 @@ export function ModerationScreenInner({
-
+
)
}
function LabelGroup({
labelGroup,
- name,
- description,
labelers: mods,
preferences,
openModSettingsDialog,
}: {
labelGroup: LabelGroupDefinition['id']
- name: string
- description: string
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
preferences: UsePreferencesQueryResponse
openModSettingsDialog: (props: SettingsDialogProps) => void
}) {
const t = useTheme()
const {_} = useLingui()
+ const labelGroupStrings = useLabelGroupStrings()
const {mutateAsync: setContentLabelPref, variables: optimisticContentLabel} =
useSetContentLabelMutation()
@@ -312,16 +310,17 @@ function LabelGroup({
visibility: values[0] as LabelPreference,
})
} catch (e) {
+ // TODO
console.error(e)
}
},
[labelGroup, setContentLabelPref],
)
+ const {name, description} = labelGroupStrings[labelGroup]
const value =
optimisticContentLabel?.visibility ??
preferences.moderationOpts.labelGroups[labelGroup]
-
const labelOptions = {
hide: _(msg`Hide`),
warn: _(msg`Warn`),
diff --git a/src/screens/ProfileModerationService/index.tsx b/src/screens/ProfileModerationService/index.tsx
index 854990b33f..938fe9c476 100644
--- a/src/screens/ProfileModerationService/index.tsx
+++ b/src/screens/ProfileModerationService/index.tsx
@@ -1,9 +1,10 @@
import React from 'react'
-import {Dimensions, View} from 'react-native'
+import {View} from 'react-native'
import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {AppBskyModerationDefs} from '@atproto/api'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
+import {useSafeAreaFrame} from 'react-native-safe-area-context'
import {usePalette} from '#/lib/hooks/usePalette'
import {CommonNavigatorParams} from '#/lib/routes/types'
@@ -45,17 +46,32 @@ import {ErrorState} from '#/screens/ProfileModerationService/ErrorState'
import {Header} from '#/screens/ProfileModerationService/Header'
import {PreferenceRow} from '#/screens/ProfileModerationService/PreferenceRow'
-// TODO
-const MIN_HEIGHT = Dimensions.get('window').height * 1.5
-// TODO loader default color
-
export function ProfileModserviceScreen(
props: NativeStackScreenProps,
) {
const t = useTheme()
const {_} = useLingui()
+ const {height: minHeight} = useSafeAreaFrame()
const {name: handleOrDid} = props.route.params
- const {isLoading, error, data: resolvedDid} = useResolveDidQuery(handleOrDid)
+ const {
+ isLoading: isDidResolutionLoading,
+ error: didResolutionError,
+ data: did,
+ } = useResolveDidQuery(handleOrDid)
+ const {
+ isLoading: isPreferencesLoading,
+ error: preferencesError,
+ data: preferences,
+ } = usePreferencesQuery()
+ const {
+ isLoading: isModServiceLoading,
+ error: modServiceError,
+ data: modservice,
+ } = useModServiceInfoQuery({did})
+
+ const isLoading =
+ isDidResolutionLoading || isPreferencesLoading || isModServiceLoading
+ const error = didResolutionError || preferencesError || modServiceError
return (
@@ -65,60 +81,31 @@ export function ProfileModserviceScreen(
a.border_r,
t.atoms.border_contrast_low,
{
- minHeight: MIN_HEIGHT,
+ minHeight,
},
]}>
{isLoading ? (
-
+
- ) : resolvedDid ? (
-
- ) : (
+ ) : error || !(did && preferences && modservice) ? (
+ ) : (
+
)}
)
}
-function ProfileModservicecreenIntermediate({modDid}: {modDid: string}) {
- const t = useTheme()
- const {_} = useLingui()
- const {
- isLoading: isPreferencesLoading,
- error: preferencesError,
- data: preferences,
- } = usePreferencesQuery()
- const {
- isLoading: isModServiceLoading,
- error: modServiceError,
- data: info,
- } = useModServiceInfoQuery({did: modDid})
-
- const isLoading = isPreferencesLoading || isModServiceLoading
- const error = preferencesError || modServiceError
-
- return isLoading ? (
-
-
-
- ) : preferences && info ? (
-
- ) : (
-
- )
-}
-
export function ProfileModserviceScreenInner({
preferences,
modservice,
@@ -128,6 +115,7 @@ export function ProfileModserviceScreenInner({
}) {
const t = useTheme()
const {_} = useLingui()
+ const {height: minHeight} = useSafeAreaFrame()
const pal = usePalette('default')
const {hasSession} = useSession()
const {track} = useAnalytics()
@@ -178,7 +166,7 @@ export function ProfileModserviceScreenInner({
diff --git a/src/state/queries/modservice.ts b/src/state/queries/modservice.ts
index d79110a421..4a4ebf674e 100644
--- a/src/state/queries/modservice.ts
+++ b/src/state/queries/modservice.ts
@@ -15,11 +15,14 @@ export const modServicesDetailedInfoQueryKey = (dids: string[]) => [
dids,
]
-export function useModServiceInfoQuery({did}: {did: string}) {
+export function useModServiceInfoQuery({did}: {did?: string}) {
return useQuery({
- queryKey: modServiceInfoQueryKey(did),
+ enabled: !!did,
+ queryKey: modServiceInfoQueryKey(did as string),
queryFn: async () => {
- const res = await getAgent().app.bsky.moderation.getService({did})
+ const res = await getAgent().app.bsky.moderation.getService({
+ did: did as string,
+ })
return res.data
},
})
@@ -38,6 +41,7 @@ export function useModServicesInfoQuery({dids}: {dids: string[]}) {
export function useModServicesDetailedInfoQuery({dids}: {dids: string[]}) {
return useQuery({
+ enabled: !!dids.length,
queryKey: modServicesDetailedInfoQueryKey(dids),
queryFn: async () => {
const views: AppBskyModerationDefs.ModServiceViewDetailed[] = []