diff --git a/assets/icons/squareArrowTopRight_stroke2_corner0_rounded.svg b/assets/icons/squareArrowTopRight_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..1407a1d6fe
--- /dev/null
+++ b/assets/icons/squareArrowTopRight_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/src/components/dialogs/ReportDialog/const.ts b/src/components/dialogs/ReportDialog/const.ts
new file mode 100644
index 0000000000..30c9aff88d
--- /dev/null
+++ b/src/components/dialogs/ReportDialog/const.ts
@@ -0,0 +1 @@
+export const DMCA_LINK = 'https://bsky.social/about/support/copyright'
diff --git a/src/components/dialogs/ReportDialog/index.tsx b/src/components/dialogs/ReportDialog/index.tsx
index 4868d552d6..69385b303b 100644
--- a/src/components/dialogs/ReportDialog/index.tsx
+++ b/src/components/dialogs/ReportDialog/index.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {View, Dimensions} from 'react-native'
+import {View, Dimensions, Linking} from 'react-native'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {AppBskyModerationDefs, LabelGroupDefinition} from '@atproto/api'
@@ -35,7 +35,11 @@ import {
getModerationServiceTitle,
useConfigurableLabelGroups,
} from '#/lib/moderation'
+import {DMCA_LINK} from '#/components/dialogs/ReportDialog/const'
+import {Link} from '#/components/Link'
+import {SquareArrowTopRight_Stroke2_Corner0_Rounded as SquareArrowTopRight} from '#/components/icons/SquareArrowTopRight'
+export type ReportDialogLabelIds = LabelGroupDefinition['id'] | 'other'
export type ReportDialogProps =
| {
type: 'post'
@@ -48,14 +52,14 @@ export type ReportDialogProps =
}
function LabelGroupButton({
- labelGroup,
+ name,
+ description,
}: {
- labelGroup: LabelGroupDefinition['id']
+ name: string
+ description: string
}) {
const t = useTheme()
const {hovered, focused, pressed} = useButtonContext()
- const labelGroupStrings = useLabelGroupStrings()
- const groupInfoStrings = labelGroupStrings[labelGroup]
const interacted = hovered || focused || pressed
const styles = React.useMemo(() => {
@@ -80,11 +84,9 @@ function LabelGroupButton({
]}>
- {groupInfoStrings.name}
-
-
- {groupInfoStrings.description}
+ {name}
+ {description}
- > = {}
+ > = {
+ // report `other` to all labelers
+ other: modservices,
+ }
for (const modservice of modservices) {
const labelGroups = getLabelGroupsFromLabels(
@@ -219,12 +224,12 @@ function SubmitView({
onSubmitComplete,
labelGroupToModServiceMap,
}: {
- selectedLabelGroup: LabelGroupDefinition['id']
+ selectedLabelGroup: ReportDialogLabelIds
goBack: () => void
onSubmitComplete: () => void
labelers: AppBskyModerationDefs.ModServiceViewDetailed[]
labelGroupToModServiceMap: Record<
- LabelGroupDefinition['id'],
+ ReportDialogLabelIds,
AppBskyModerationDefs.ModServiceViewDetailed[]
>
}) {
@@ -364,25 +369,22 @@ function SubmitView({
)
}
-/**
- * TODO copyright link out to DMCA
- * TODO add "other" option
- */
export function ReportDialog({
params,
cleanup,
}: GlobalDialogProps) {
+ // REQUIRED CLEANUP
+ const onClose = React.useCallback(() => cleanup(), [cleanup])
+
const t = useTheme()
const {_} = useLingui()
const insets = useSafeAreaInsets()
const control = Dialog.useDialogControl()
const [selectedLabelGroup, setSelectedLabelGroup] = React.useState<
- LabelGroupDefinition['id'] | undefined
+ ReportDialogLabelIds | undefined
>()
const labelGroupStrings = useLabelGroupStrings()
-
- // REQUIRED CLEANUP
- const onClose = React.useCallback(() => cleanup(), [cleanup])
+ const groups = useConfigurableLabelGroups()
const i18n = React.useMemo(() => {
let title = _(msg`Report this post`)
@@ -399,7 +401,16 @@ export function ReportDialog({
}
}, [_, params.type])
- const groups = useConfigurableLabelGroups()
+ const next = React.useCallback(
+ (group: ReportDialogLabelIds | 'copyright') => {
+ if (group === 'copyright') {
+ Linking.openURL(DMCA_LINK)
+ } else {
+ setSelectedLabelGroup(group)
+ }
+ },
+ [setSelectedLabelGroup],
+ )
return (
{groups.map(def => {
- const groupStrings = labelGroupStrings[def.id]
+ const strings = labelGroupStrings[def.id]
return (
)
})}
+
+
+
+
+
+
+ Need to report a copyright violation?
+
+
+ View details
+
+
+
+
)}
diff --git a/src/components/icons/SquareArrowTopRight.tsx b/src/components/icons/SquareArrowTopRight.tsx
new file mode 100644
index 0000000000..7701e26e56
--- /dev/null
+++ b/src/components/icons/SquareArrowTopRight.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const SquareArrowTopRight_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M14 5a1 1 0 1 1 0-2h6a1 1 0 0 1 1 1v6a1 1 0 1 1-2 0V6.414l-7.293 7.293a1 1 0 0 1-1.414-1.414L17.586 5H14ZM3 6a1 1 0 0 1 1-1h5a1 1 0 0 1 0 2H5v12h12v-4a1 1 0 1 1 2 0v5a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V6Z',
+})
diff --git a/src/lib/moderation/useLabelGroupStrings.ts b/src/lib/moderation/useLabelGroupStrings.ts
index ebd33fc0c7..152c8010f3 100644
--- a/src/lib/moderation/useLabelGroupStrings.ts
+++ b/src/lib/moderation/useLabelGroupStrings.ts
@@ -4,7 +4,7 @@ import {useLingui} from '@lingui/react'
import {useMemo} from 'react'
export type LabelGroupStrings = Record<
- keyof typeof LABEL_GROUPS,
+ keyof typeof LABEL_GROUPS | 'other',
{name: string; description: string}
>
@@ -116,6 +116,10 @@ export function useLabelGroupStrings(): LabelGroupStrings {
msg`Helpful annotations to explain intent, such as satire or parody.`,
),
},
+ other: {
+ name: _(msg`Other`),
+ description: _(msg`Other content not covered by the other categories.`),
+ },
}),
[_],
)