about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2024-03-18 16:15:57 -0700
committerGitHub <noreply@github.com>2024-03-18 16:15:57 -0700
commit959121f394cd92a5931d618d1cadf6315663c59c (patch)
tree14b2affadf6ac3cc780d4e9339e4e0c42adfb95e
parent1b10c7bc08cf517d2b3a943d8f8949ccc012028b (diff)
downloadvoidsky-959121f394cd92a5931d618d1cadf6315663c59c.tar.zst
Update the reporting flow to first select a recipient if the user has multiple labelers (#3258)
-rw-r--r--src/components/ReportDialog/SelectLabelerView.tsx115
-rw-r--r--src/components/ReportDialog/SelectReportOptionView.tsx18
-rw-r--r--src/components/ReportDialog/SubmitView.tsx8
-rw-r--r--src/components/ReportDialog/index.tsx54
4 files changed, 175 insertions, 20 deletions
diff --git a/src/components/ReportDialog/SelectLabelerView.tsx b/src/components/ReportDialog/SelectLabelerView.tsx
new file mode 100644
index 000000000..300114fc4
--- /dev/null
+++ b/src/components/ReportDialog/SelectLabelerView.tsx
@@ -0,0 +1,115 @@
+import React from 'react'
+import {View} from 'react-native'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {AppBskyLabelerDefs} from '@atproto/api'
+
+export {useDialogControl as useReportDialogControl} from '#/components/Dialog'
+
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
+import {Button, useButtonContext} from '#/components/Button'
+import {Divider} from '#/components/Divider'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+
+import {ReportDialogProps} from './types'
+
+export function SelectLabelerView({
+  ...props
+}: ReportDialogProps & {
+  labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
+  onSelectLabeler: (v: string) => void
+}) {
+  const t = useTheme()
+  const {_} = useLingui()
+
+  return (
+    <View style={[a.gap_lg]}>
+      <View style={[a.justify_center, a.gap_sm]}>
+        <Text style={[a.text_2xl, a.font_bold]}>
+          <Trans>Select moderation service</Trans>
+        </Text>
+        <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
+          <Trans>Who do you want to send this report to?</Trans>
+        </Text>
+      </View>
+
+      <Divider />
+
+      <View style={[a.gap_sm, {marginHorizontal: a.p_md.padding * -1}]}>
+        {props.labelers.map(labeler => {
+          return (
+            <Button
+              key={labeler.creator.did}
+              label={_(msg`Send report to ${labeler.creator.displayName}`)}
+              onPress={() => props.onSelectLabeler(labeler.creator.did)}>
+              <LabelerButton
+                title={labeler.creator.displayName || labeler.creator.handle}
+                description={labeler.creator.description || ''}
+              />
+            </Button>
+          )
+        })}
+      </View>
+    </View>
+  )
+}
+
+function LabelerButton({
+  title,
+  description,
+}: {
+  title: string
+  description: string
+}) {
+  const t = useTheme()
+  const {hovered, pressed} = useButtonContext()
+  const interacted = hovered || pressed
+
+  const styles = React.useMemo(() => {
+    return {
+      interacted: {
+        backgroundColor: t.palette.contrast_50,
+      },
+    }
+  }, [t])
+
+  return (
+    <View
+      style={[
+        a.w_full,
+        a.flex_row,
+        a.align_center,
+        a.justify_between,
+        a.p_md,
+        a.rounded_md,
+        {paddingRight: 70},
+        interacted && styles.interacted,
+      ]}>
+      <View style={[a.flex_1, a.gap_xs]}>
+        <Text style={[a.text_md, a.font_bold, t.atoms.text_contrast_medium]}>
+          {title}
+        </Text>
+        <Text style={[a.leading_tight, {maxWidth: 400}]} numberOfLines={3}>
+          {description}
+        </Text>
+      </View>
+
+      <View
+        style={[
+          a.absolute,
+          a.inset_0,
+          a.justify_center,
+          a.pr_md,
+          {left: 'auto'},
+        ]}>
+        <ChevronRight
+          size="md"
+          fill={
+            hovered ? t.palette.primary_500 : t.atoms.text_contrast_low.color
+          }
+        />
+      </View>
+    </View>
+  )
+}
diff --git a/src/components/ReportDialog/SelectReportOptionView.tsx b/src/components/ReportDialog/SelectReportOptionView.tsx
index 8ae0b52ec..037a62fce 100644
--- a/src/components/ReportDialog/SelectReportOptionView.tsx
+++ b/src/components/ReportDialog/SelectReportOptionView.tsx
@@ -18,7 +18,10 @@ import {
   useButtonContext,
 } from '#/components/Button'
 import {Divider} from '#/components/Divider'
-import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {
+  ChevronRight_Stroke2_Corner0_Rounded as ChevronRight,
+  ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft,
+} from '#/components/icons/Chevron'
 import {SquareArrowTopRight_Stroke2_Corner0_Rounded as SquareArrowTopRight} from '#/components/icons/SquareArrowTopRight'
 
 import {ReportDialogProps} from './types'
@@ -28,6 +31,7 @@ export function SelectReportOptionView({
 }: ReportDialogProps & {
   labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
   onSelectReportOption: (reportOption: ReportOption) => void
+  goBack: () => void
 }) {
   const t = useTheme()
   const {_} = useLingui()
@@ -60,6 +64,18 @@ export function SelectReportOptionView({
 
   return (
     <View style={[a.gap_lg]}>
+      {props.labelers?.length > 1 ? (
+        <Button
+          size="small"
+          variant="solid"
+          color="secondary"
+          shape="round"
+          label={_(msg`Go back to previous step`)}
+          onPress={props.goBack}>
+          <ButtonIcon icon={ChevronLeft} />
+        </Button>
+      ) : null}
+
       <View style={[a.justify_center, a.gap_sm]}>
         <Text style={[a.text_2xl, a.font_bold]}>{i18n.title}</Text>
         <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
diff --git a/src/components/ReportDialog/SubmitView.tsx b/src/components/ReportDialog/SubmitView.tsx
index 99af64a2a..d47211c81 100644
--- a/src/components/ReportDialog/SubmitView.tsx
+++ b/src/components/ReportDialog/SubmitView.tsx
@@ -24,11 +24,13 @@ import {getAgent} from '#/state/session'
 export function SubmitView({
   params,
   labelers,
+  selectedLabeler,
   selectedReportOption,
   goBack,
   onSubmitComplete,
 }: ReportDialogProps & {
   labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
+  selectedLabeler: string
   selectedReportOption: ReportOption
   goBack: () => void
   onSubmitComplete: () => void
@@ -37,9 +39,9 @@ export function SubmitView({
   const {_} = useLingui()
   const [details, setDetails] = React.useState<string>('')
   const [submitting, setSubmitting] = React.useState<boolean>(false)
-  const [selectedServices, setSelectedServices] = React.useState<string[]>(
-    labelers?.map(labeler => labeler.creator.did) || [],
-  )
+  const [selectedServices, setSelectedServices] = React.useState<string[]>([
+    selectedLabeler,
+  ])
   const [error, setError] = React.useState('')
 
   const submit = React.useCallback(async () => {
diff --git a/src/components/ReportDialog/index.tsx b/src/components/ReportDialog/index.tsx
index b35727c7d..f01ff3f3b 100644
--- a/src/components/ReportDialog/index.tsx
+++ b/src/components/ReportDialog/index.tsx
@@ -12,9 +12,11 @@ import * as Dialog from '#/components/Dialog'
 import {Text} from '#/components/Typography'
 
 import {ReportDialogProps} from './types'
+import {SelectLabelerView} from './SelectLabelerView'
 import {SelectReportOptionView} from './SelectReportOptionView'
 import {SubmitView} from './SubmitView'
 import {useDelayedLoading} from '#/components/hooks/useDelayedLoading'
+import {AppBskyLabelerDefs} from '@atproto/api'
 
 export function ReportDialog(props: ReportDialogProps) {
   return (
@@ -33,9 +35,6 @@ function ReportDialogInner(props: ReportDialogProps) {
     error,
   } = useMyLabelersQuery()
   const isLoading = useDelayedLoading(500, isLabelerLoading)
-  const [selectedReportOption, setSelectedReportOption] = React.useState<
-    ReportOption | undefined
-  >()
 
   return (
     <Dialog.ScrollableInner label="Report Dialog">
@@ -51,23 +50,46 @@ function ReportDialogInner(props: ReportDialogProps) {
             <Trans>Something went wrong, please try again.</Trans>
           </Text>
         </View>
-      ) : selectedReportOption ? (
-        <SubmitView
-          {...props}
-          labelers={labelers}
-          selectedReportOption={selectedReportOption}
-          goBack={() => setSelectedReportOption(undefined)}
-          onSubmitComplete={() => props.control.close()}
-        />
       ) : (
-        <SelectReportOptionView
-          {...props}
-          labelers={labelers}
-          onSelectReportOption={setSelectedReportOption}
-        />
+        <ReportDialogLoaded labelers={labelers} {...props} />
       )}
 
       <Dialog.Close />
     </Dialog.ScrollableInner>
   )
 }
+
+function ReportDialogLoaded(
+  props: ReportDialogProps & {
+    labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
+  },
+) {
+  const [selectedLabeler, setSelectedLabeler] = React.useState<
+    string | undefined
+  >(props.labelers.length === 1 ? props.labelers[0].creator.did : undefined)
+  const [selectedReportOption, setSelectedReportOption] = React.useState<
+    ReportOption | undefined
+  >()
+
+  if (selectedReportOption && selectedLabeler) {
+    return (
+      <SubmitView
+        {...props}
+        selectedLabeler={selectedLabeler}
+        selectedReportOption={selectedReportOption}
+        goBack={() => setSelectedReportOption(undefined)}
+        onSubmitComplete={() => props.control.close()}
+      />
+    )
+  }
+  if (selectedLabeler) {
+    return (
+      <SelectReportOptionView
+        {...props}
+        goBack={() => setSelectedLabeler(undefined)}
+        onSelectReportOption={setSelectedReportOption}
+      />
+    )
+  }
+  return <SelectLabelerView {...props} onSelectLabeler={setSelectedLabeler} />
+}