about summary refs log tree commit diff
path: root/src/components/moderation
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/moderation')
-rw-r--r--src/components/moderation/GlobalModerationLabelPref.tsx93
-rw-r--r--src/components/moderation/LabelPreference.tsx294
-rw-r--r--src/components/moderation/ModerationLabelPref.tsx177
3 files changed, 294 insertions, 270 deletions
diff --git a/src/components/moderation/GlobalModerationLabelPref.tsx b/src/components/moderation/GlobalModerationLabelPref.tsx
deleted file mode 100644
index 7633cb9f2..000000000
--- 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 (
-    <View
-      style={[
-        a.flex_row,
-        a.justify_between,
-        a.gap_sm,
-        a.py_md,
-        a.pl_lg,
-        a.pr_md,
-        a.align_center,
-      ]}>
-      <View style={[a.gap_xs, a.flex_1]}>
-        <Text style={[a.font_bold]}>{labelStrings.name}</Text>
-        <Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
-          {labelStrings.description}
-        </Text>
-      </View>
-      <View style={[a.justify_center, {minHeight: 35}]}>
-        {!disabled && (
-          <ToggleButton.Group
-            label={_(
-              msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`,
-            )}
-            values={[pref]}
-            onChange={newPref =>
-              mutate({
-                label: identifier,
-                visibility: newPref[0] as LabelPreference,
-                labelerDid: undefined,
-              })
-            }>
-            <ToggleButton.Button name="ignore" label={labelOptions.ignore}>
-              {labelOptions.ignore}
-            </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>
-  )
-}
diff --git a/src/components/moderation/LabelPreference.tsx b/src/components/moderation/LabelPreference.tsx
new file mode 100644
index 000000000..7d4bd9c32
--- /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 (
+    <View
+      style={[
+        a.flex_row,
+        a.gap_md,
+        a.px_lg,
+        a.py_lg,
+        a.justify_between,
+        a.flex_wrap,
+      ]}>
+      {children}
+    </View>
+  )
+}
+
+export function Content({
+  children,
+  name,
+  description,
+}: React.PropsWithChildren<{
+  name: string
+  description: string
+}>) {
+  const t = useTheme()
+  const {gtPhone} = useBreakpoints()
+
+  return (
+    <View style={[a.gap_xs, a.flex_1]}>
+      <Text style={[a.font_bold, gtPhone ? a.text_sm : a.text_md]}>{name}</Text>
+      <Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
+        {description}
+      </Text>
+
+      {children}
+    </View>
+  )
+}
+
+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 (
+    <View style={[{minHeight: 35}, gtPhone ? undefined : a.w_full]}>
+      <ToggleButton.Group
+        label={_(
+          msg`Configure content filtering setting for category: ${name}`,
+        )}
+        values={values}
+        onChange={onChange}>
+        {ignoreLabel && (
+          <ToggleButton.Button name="ignore" label={ignoreLabel}>
+            {ignoreLabel}
+          </ToggleButton.Button>
+        )}
+        {warnLabel && (
+          <ToggleButton.Button name="warn" label={warnLabel}>
+            {warnLabel}
+          </ToggleButton.Button>
+        )}
+        {hideLabel && (
+          <ToggleButton.Button name="hide" label={hideLabel}>
+            {hideLabel}
+          </ToggleButton.Button>
+        )}
+      </ToggleButton.Group>
+    </View>
+  )
+}
+
+/**
+ * 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 (
+    <Outer>
+      <Content
+        name={labelStrings.name}
+        description={labelStrings.description}
+      />
+      {!disabled && (
+        <Buttons
+          name={labelStrings.name.toLowerCase()}
+          values={[pref]}
+          onChange={values => {
+            mutate({
+              label: identifier,
+              visibility: values[0] as LabelPreference,
+              labelerDid: undefined,
+            })
+          }}
+          ignoreLabel={labelOptions.ignore}
+          warnLabel={labelOptions.warn}
+          hideLabel={labelOptions.hide}
+        />
+      )}
+    </Outer>
+  )
+}
+
+/**
+ * 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 (
+    <Outer>
+      <Content name={labelStrings.name} description={labelStrings.description}>
+        {cantConfigure && (
+          <View style={[a.flex_row, a.gap_xs, a.align_center, a.mt_xs]}>
+            <CircleInfo size="sm" fill={t.atoms.text_contrast_high.color} />
+
+            <Text
+              style={[t.atoms.text_contrast_medium, a.font_semibold, a.italic]}>
+              {adultDisabled ? (
+                <Trans>Adult content is disabled.</Trans>
+              ) : isGlobalLabel ? (
+                <Trans>
+                  Configured in{' '}
+                  <InlineLink to="/moderation" style={a.text_sm}>
+                    moderation settings
+                  </InlineLink>
+                  .
+                </Trans>
+              ) : null}
+            </Text>
+          </View>
+        )}
+      </Content>
+
+      {showConfig && (
+        <View style={[gtPhone ? undefined : a.w_full]}>
+          {cantConfigure ? (
+            <View
+              style={[
+                {minHeight: 35},
+                a.px_md,
+                a.py_md,
+                a.rounded_sm,
+                a.border,
+                t.atoms.border_contrast_low,
+              ]}>
+              <Text style={[a.font_bold, t.atoms.text_contrast_low]}>
+                {currentPrefLabel}
+              </Text>
+            </View>
+          ) : (
+            <Buttons
+              name={labelStrings.name.toLowerCase()}
+              values={[pref]}
+              onChange={values => {
+                mutate({
+                  label: identifier,
+                  visibility: values[0] as LabelPreference,
+                  labelerDid,
+                })
+              }}
+              ignoreLabel={ignoreLabel}
+              warnLabel={canWarn ? warnLabel : undefined}
+              hideLabel={hideLabel}
+            />
+          )}
+        </View>
+      )}
+    </Outer>
+  )
+}
diff --git a/src/components/moderation/ModerationLabelPref.tsx b/src/components/moderation/ModerationLabelPref.tsx
deleted file mode 100644
index b16c24859..000000000
--- 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 (
-    <View
-      style={[
-        a.flex_row,
-        a.gap_md,
-        a.px_lg,
-        a.py_lg,
-        a.justify_between,
-        a.flex_wrap,
-      ]}>
-      <View style={[a.gap_xs, a.flex_1]}>
-        <Text style={[a.font_bold, gtPhone ? a.text_sm : a.text_md]}>
-          {labelStrings.name}
-        </Text>
-        <Text style={[t.atoms.text_contrast_medium, a.leading_snug]}>
-          {labelStrings.description}
-        </Text>
-
-        {cantConfigure && (
-          <View style={[a.flex_row, a.gap_xs, a.align_center, a.mt_xs]}>
-            <CircleInfo size="sm" fill={t.atoms.text_contrast_high.color} />
-
-            <Text
-              style={[t.atoms.text_contrast_medium, a.font_semibold, a.italic]}>
-              {adultDisabled ? (
-                <Trans>Adult content is disabled.</Trans>
-              ) : isGlobalLabel ? (
-                <Trans>
-                  Configured in{' '}
-                  <InlineLink to="/moderation" style={a.text_sm}>
-                    moderation settings
-                  </InlineLink>
-                  .
-                </Trans>
-              ) : null}
-            </Text>
-          </View>
-        )}
-      </View>
-
-      {showConfig && (
-        <View style={[gtPhone ? undefined : a.w_full]}>
-          {cantConfigure ? (
-            <View
-              style={[
-                {minHeight: 35},
-                a.px_md,
-                a.py_md,
-                a.rounded_sm,
-                a.border,
-                t.atoms.border_contrast_low,
-              ]}>
-              <Text style={[a.font_bold, t.atoms.text_contrast_low]}>
-                {currentPrefLabel}
-              </Text>
-            </View>
-          ) : (
-            <View style={[{minHeight: 35}]}>
-              <ToggleButton.Group
-                label={_(
-                  msg`Configure content filtering setting for category: ${labelStrings.name.toLowerCase()}`,
-                )}
-                values={[prefAdjusted]}
-                onChange={newPref =>
-                  mutate({
-                    label: identifier,
-                    visibility: newPref[0] as LabelPreference,
-                    labelerDid,
-                  })
-                }>
-                <ToggleButton.Button name="ignore" label={ignoreLabel}>
-                  {ignoreLabel}
-                </ToggleButton.Button>
-                {canWarn && (
-                  <ToggleButton.Button name="warn" label={warnLabel}>
-                    {warnLabel}
-                  </ToggleButton.Button>
-                )}
-                <ToggleButton.Button name="hide" label={hideLabel}>
-                  {hideLabel}
-                </ToggleButton.Button>
-              </ToggleButton.Group>
-            </View>
-          )}
-        </View>
-      )}
-    </View>
-  )
-}