diff --git a/src/components/moderation/GlobalModerationLabelPref.tsx b/src/components/moderation/GlobalModerationLabelPref.tsx
deleted file mode 100644
index 7633cb9f21..0000000000
--- a/src/components/moderation/GlobalModerationLabelPref.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import React from 'react'
-import {View} from 'react-native'
-import {InterpretedLabelValueDefinition, LabelPreference} from '@atproto/api'
-import {useLingui} from '@lingui/react'
-import {msg} from '@lingui/macro'
-
-import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings'
-import {
- usePreferencesQuery,
- usePreferencesSetContentLabelMutation,
-} from '#/state/queries/preferences'
-
-import {useTheme, atoms as a} from '#/alf'
-import {Text} from '#/components/Typography'
-import * as ToggleButton from '#/components/forms/ToggleButton'
-
-export function GlobalModerationLabelPref({
- labelValueDefinition,
- disabled,
-}: {
- labelValueDefinition: InterpretedLabelValueDefinition
- disabled?: boolean
-}) {
- const {_} = useLingui()
- const t = useTheme()
-
- const {identifier} = labelValueDefinition
- const {data: preferences} = usePreferencesQuery()
- const {mutate, variables} = usePreferencesSetContentLabelMutation()
- const savedPref = preferences?.moderationPrefs.labels[identifier]
- const pref = variables?.visibility ?? savedPref ?? 'warn'
-
- const allLabelStrings = useGlobalLabelStrings()
- const labelStrings =
- labelValueDefinition.identifier in allLabelStrings
- ? allLabelStrings[labelValueDefinition.identifier]
- : {
- name: labelValueDefinition.identifier,
- description: `Labeled "${labelValueDefinition.identifier}"`,
- }
-
- const labelOptions = {
- hide: _(msg`Hide`),
- warn: _(msg`Warn`),
- ignore: _(msg`Show`),
- }
-
- return (
-
-
- {labelStrings.name}
-
- {labelStrings.description}
-
-
-
- {!disabled && (
-
- mutate({
- label: identifier,
- visibility: newPref[0] as LabelPreference,
- labelerDid: undefined,
- })
- }>
-
- {labelOptions.ignore}
-
-
- {labelOptions.warn}
-
-
- {labelOptions.hide}
-
-
- )}
-
-
- )
-}
diff --git a/src/components/moderation/LabelPreference.tsx b/src/components/moderation/LabelPreference.tsx
new file mode 100644
index 0000000000..7d4bd9c321
--- /dev/null
+++ b/src/components/moderation/LabelPreference.tsx
@@ -0,0 +1,294 @@
+import React from 'react'
+import {View} from 'react-native'
+import {InterpretedLabelValueDefinition, LabelPreference} from '@atproto/api'
+import {useLingui} from '@lingui/react'
+import {msg, Trans} from '@lingui/macro'
+
+import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings'
+import {
+ usePreferencesQuery,
+ usePreferencesSetContentLabelMutation,
+} from '#/state/queries/preferences'
+import {useLabelBehaviorDescription} from '#/lib/moderation/useLabelBehaviorDescription'
+import {getLabelStrings} from '#/lib/moderation/useLabelInfo'
+
+import {useTheme, atoms as a, useBreakpoints} from '#/alf'
+import {Text} from '#/components/Typography'
+import {InlineLink} from '#/components/Link'
+import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '../icons/CircleInfo'
+import * as ToggleButton from '#/components/forms/ToggleButton'
+
+export function Outer({children}: React.PropsWithChildren<{}>) {
+ return (
+
+ {children}
+
+ )
+}
+
+export function Content({
+ children,
+ name,
+ description,
+}: React.PropsWithChildren<{
+ name: string
+ description: string
+}>) {
+ const t = useTheme()
+ const {gtPhone} = useBreakpoints()
+
+ return (
+
+ {name}
+
+ {description}
+
+
+ {children}
+
+ )
+}
+
+export function Buttons({
+ name,
+ values,
+ onChange,
+ ignoreLabel,
+ warnLabel,
+ hideLabel,
+}: {
+ name: string
+ values: ToggleButton.GroupProps['values']
+ onChange: ToggleButton.GroupProps['onChange']
+ ignoreLabel?: string
+ warnLabel?: string
+ hideLabel?: string
+}) {
+ const {_} = useLingui()
+ const {gtPhone} = useBreakpoints()
+
+ return (
+
+
+ {ignoreLabel && (
+
+ {ignoreLabel}
+
+ )}
+ {warnLabel && (
+
+ {warnLabel}
+
+ )}
+ {hideLabel && (
+
+ {hideLabel}
+
+ )}
+
+
+ )
+}
+
+/**
+ * For use on the global Moderation screen to set prefs for a "global" label,
+ * not scoped to a single labeler.
+ */
+export function GlobalLabelPreference({
+ labelDefinition,
+ disabled,
+}: {
+ labelDefinition: InterpretedLabelValueDefinition
+ disabled?: boolean
+}) {
+ const {_} = useLingui()
+
+ const {identifier} = labelDefinition
+ const {data: preferences} = usePreferencesQuery()
+ const {mutate, variables} = usePreferencesSetContentLabelMutation()
+ const savedPref = preferences?.moderationPrefs.labels[identifier]
+ const pref = variables?.visibility ?? savedPref ?? 'warn'
+
+ const allLabelStrings = useGlobalLabelStrings()
+ const labelStrings =
+ labelDefinition.identifier in allLabelStrings
+ ? allLabelStrings[labelDefinition.identifier]
+ : {
+ name: labelDefinition.identifier,
+ description: `Labeled "${labelDefinition.identifier}"`,
+ }
+
+ const labelOptions = {
+ hide: _(msg`Hide`),
+ warn: _(msg`Warn`),
+ ignore: _(msg`Show`),
+ }
+
+ return (
+
+
+ {!disabled && (
+ {
+ mutate({
+ label: identifier,
+ visibility: values[0] as LabelPreference,
+ labelerDid: undefined,
+ })
+ }}
+ ignoreLabel={labelOptions.ignore}
+ warnLabel={labelOptions.warn}
+ hideLabel={labelOptions.hide}
+ />
+ )}
+
+ )
+}
+
+/**
+ * For use on individual labeler pages
+ */
+export function LabelerLabelPreference({
+ labelDefinition,
+ disabled,
+ labelerDid,
+}: {
+ labelDefinition: InterpretedLabelValueDefinition
+ disabled?: boolean
+ labelerDid?: string
+}) {
+ const {i18n} = useLingui()
+ const t = useTheme()
+ const {gtPhone} = useBreakpoints()
+
+ const isGlobalLabel = !labelDefinition.definedBy
+ const {identifier} = labelDefinition
+ const {data: preferences} = usePreferencesQuery()
+ const {mutate, variables} = usePreferencesSetContentLabelMutation()
+ const savedPref =
+ labelerDid && !isGlobalLabel
+ ? preferences?.moderationPrefs.labelers.find(l => l.did === labelerDid)
+ ?.labels[identifier]
+ : preferences?.moderationPrefs.labels[identifier]
+ const pref =
+ variables?.visibility ??
+ savedPref ??
+ labelDefinition.defaultSetting ??
+ 'warn'
+
+ // does the 'warn' setting make sense for this label?
+ const canWarn = !(
+ labelDefinition.blurs === 'none' && labelDefinition.severity === 'none'
+ )
+ // is this label adult only?
+ const adultOnly = labelDefinition.flags.includes('adult')
+ // is this label disabled because it's adult only?
+ const adultDisabled =
+ adultOnly && !preferences?.moderationPrefs.adultContentEnabled
+ // are there any reasons we cant configure this label here?
+ const cantConfigure = isGlobalLabel || adultDisabled
+ const showConfig = !disabled && (gtPhone || !cantConfigure)
+
+ // adjust the pref based on whether warn is available
+ let prefAdjusted = pref
+ if (adultDisabled) {
+ prefAdjusted = 'hide'
+ } else if (!canWarn && pref === 'warn') {
+ prefAdjusted = 'ignore'
+ }
+
+ // grab localized descriptions of the label and its settings
+ const currentPrefLabel = useLabelBehaviorDescription(
+ labelDefinition,
+ prefAdjusted,
+ )
+ const hideLabel = useLabelBehaviorDescription(labelDefinition, 'hide')
+ const warnLabel = useLabelBehaviorDescription(labelDefinition, 'warn')
+ const ignoreLabel = useLabelBehaviorDescription(labelDefinition, 'ignore')
+ const globalLabelStrings = useGlobalLabelStrings()
+ const labelStrings = getLabelStrings(
+ i18n.locale,
+ globalLabelStrings,
+ labelDefinition,
+ )
+
+ return (
+
+
+ {cantConfigure && (
+
+
+
+
+ {adultDisabled ? (
+ Adult content is disabled.
+ ) : isGlobalLabel ? (
+
+ Configured in{' '}
+
+ moderation settings
+
+ .
+
+ ) : null}
+
+
+ )}
+
+
+ {showConfig && (
+
+ {cantConfigure ? (
+
+
+ {currentPrefLabel}
+
+
+ ) : (
+ {
+ mutate({
+ label: identifier,
+ visibility: values[0] as LabelPreference,
+ labelerDid,
+ })
+ }}
+ ignoreLabel={ignoreLabel}
+ warnLabel={canWarn ? warnLabel : undefined}
+ hideLabel={hideLabel}
+ />
+ )}
+
+ )}
+
+ )
+}
diff --git a/src/components/moderation/ModerationLabelPref.tsx b/src/components/moderation/ModerationLabelPref.tsx
deleted file mode 100644
index b16c248592..0000000000
--- a/src/components/moderation/ModerationLabelPref.tsx
+++ /dev/null
@@ -1,177 +0,0 @@
-import React from 'react'
-import {View} from 'react-native'
-import {InterpretedLabelValueDefinition, LabelPreference} from '@atproto/api'
-import {useLingui} from '@lingui/react'
-import {msg, Trans} from '@lingui/macro'
-
-import {useGlobalLabelStrings} from '#/lib/moderation/useGlobalLabelStrings'
-import {useLabelBehaviorDescription} from '#/lib/moderation/useLabelBehaviorDescription'
-import {
- usePreferencesQuery,
- usePreferencesSetContentLabelMutation,
-} from '#/state/queries/preferences'
-import {getLabelStrings} from '#/lib/moderation/useLabelInfo'
-
-import {useTheme, atoms as a, useBreakpoints} from '#/alf'
-import {Text} from '#/components/Typography'
-import {InlineLink} from '#/components/Link'
-import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '../icons/CircleInfo'
-import * as ToggleButton from '#/components/forms/ToggleButton'
-
-export function ModerationLabelPref({
- labelValueDefinition,
- labelerDid,
- disabled,
-}: {
- labelValueDefinition: InterpretedLabelValueDefinition
- labelerDid: string | undefined
- disabled?: boolean
-}) {
- const {_, i18n} = useLingui()
- const t = useTheme()
- const {gtPhone} = useBreakpoints()
-
- const isGlobalLabel = !labelValueDefinition.definedBy
- const {identifier} = labelValueDefinition
- const {data: preferences} = usePreferencesQuery()
- const {mutate, variables} = usePreferencesSetContentLabelMutation()
- const savedPref =
- labelerDid && !isGlobalLabel
- ? preferences?.moderationPrefs.labelers.find(l => l.did === labelerDid)
- ?.labels[identifier]
- : preferences?.moderationPrefs.labels[identifier]
- const pref =
- variables?.visibility ??
- savedPref ??
- labelValueDefinition.defaultSetting ??
- 'warn'
-
- // does the 'warn' setting make sense for this label?
- const canWarn = !(
- labelValueDefinition.blurs === 'none' &&
- labelValueDefinition.severity === 'none'
- )
- // is this label adult only?
- const adultOnly = labelValueDefinition.flags.includes('adult')
- // is this label disabled because it's adult only?
- const adultDisabled =
- adultOnly && !preferences?.moderationPrefs.adultContentEnabled
- // are there any reasons we cant configure this label here?
- const cantConfigure = isGlobalLabel || adultDisabled
- const showConfig = !disabled && (gtPhone || !cantConfigure)
-
- // adjust the pref based on whether warn is available
- let prefAdjusted = pref
- if (adultDisabled) {
- prefAdjusted = 'hide'
- } else if (!canWarn && pref === 'warn') {
- prefAdjusted = 'ignore'
- }
-
- // grab localized descriptions of the label and its settings
- const currentPrefLabel = useLabelBehaviorDescription(
- labelValueDefinition,
- prefAdjusted,
- )
- const hideLabel = useLabelBehaviorDescription(labelValueDefinition, 'hide')
- const warnLabel = useLabelBehaviorDescription(labelValueDefinition, 'warn')
- const ignoreLabel = useLabelBehaviorDescription(
- labelValueDefinition,
- 'ignore',
- )
- const globalLabelStrings = useGlobalLabelStrings()
- const labelStrings = getLabelStrings(
- i18n.locale,
- globalLabelStrings,
- labelValueDefinition,
- )
-
- return (
-
-
-
- {labelStrings.name}
-
-
- {labelStrings.description}
-
-
- {cantConfigure && (
-
-
-
-
- {adultDisabled ? (
- Adult content is disabled.
- ) : isGlobalLabel ? (
-
- Configured in{' '}
-
- moderation settings
-
- .
-
- ) : null}
-
-
- )}
-
-
- {showConfig && (
-
- {cantConfigure ? (
-
-
- {currentPrefLabel}
-
-
- ) : (
-
-
- mutate({
- label: identifier,
- visibility: newPref[0] as LabelPreference,
- labelerDid,
- })
- }>
-
- {ignoreLabel}
-
- {canWarn && (
-
- {warnLabel}
-
- )}
-
- {hideLabel}
-
-
-
- )}
-
- )}
-
- )
-}
diff --git a/src/screens/Moderation/index.tsx b/src/screens/Moderation/index.tsx
index d73823fadf..7d991cc711 100644
--- a/src/screens/Moderation/index.tsx
+++ b/src/screens/Moderation/index.tsx
@@ -41,7 +41,7 @@ import {InlineLink, Link} from '#/components/Link'
import {Button, ButtonText} from '#/components/Button'
import {Loader} from '#/components/Loader'
import * as LabelingService from '#/components/LabelingServiceCard'
-import {GlobalModerationLabelPref} from '#/components/moderation/GlobalModerationLabelPref'
+import {GlobalLabelPreference} from '#/components/moderation/LabelPreference'
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
import {Props as SVGIconProps} from '#/components/icons/common'
import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings'
@@ -352,17 +352,17 @@ export function ModerationScreenInner({
)}
{!isUnderage && adultContentEnabled && (
<>
-
+
-
+
-
>
)}
-
+
diff --git a/src/screens/Profile/Sections/Labels.tsx b/src/screens/Profile/Sections/Labels.tsx
index 08db4a861d..2b2b995940 100644
--- a/src/screens/Profile/Sections/Labels.tsx
+++ b/src/screens/Profile/Sections/Labels.tsx
@@ -23,7 +23,7 @@ import {Loader} from '#/components/Loader'
import {Divider} from '#/components/Divider'
import {CenteredView, ScrollView} from '#/view/com/util/Views'
import {ErrorState} from '../ErrorState'
-import {ModerationLabelPref} from '#/components/moderation/ModerationLabelPref'
+import {LabelerLabelPreference} from '#/components/moderation/LabelPreference'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
interface LabelsSectionProps {
@@ -197,9 +197,9 @@ export function ProfileLabelsSectionInner({
return (
{i !== 0 && }
-