1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
import {View} from 'react-native'
import React, {useMemo} from 'react'
import {AtUri, ComAtprotoModerationDefs} from '@atproto/api'
import {Text} from '../../util/text/Text'
import {UsePaletteValue, usePalette} from 'lib/hooks/usePalette'
import {RadioGroup, RadioGroupItem} from 'view/com/util/forms/RadioGroup'
import {CollectionId} from './types'
type ReasonMap = Record<string, {title: string; description: string}>
const CommonReasons = {
[ComAtprotoModerationDefs.REASONRUDE]: {
title: 'Anti-Social Behavior',
description: 'Harassment, trolling, or intolerance',
},
[ComAtprotoModerationDefs.REASONVIOLATION]: {
title: 'Illegal and Urgent',
description: 'Glaring violations of law or terms of service',
},
[ComAtprotoModerationDefs.REASONOTHER]: {
title: 'Other',
description: 'An issue not included in these options',
},
}
const CollectionToReasonsMap: Record<string, ReasonMap> = {
[CollectionId.Post]: {
[ComAtprotoModerationDefs.REASONSPAM]: {
title: 'Spam',
description: 'Excessive mentions or replies',
},
[ComAtprotoModerationDefs.REASONSEXUAL]: {
title: 'Unwanted Sexual Content',
description: 'Nudity or pornography not labeled as such',
},
__copyright__: {
title: 'Copyright Violation',
description: 'Contains copyrighted material',
},
...CommonReasons,
},
[CollectionId.List]: {
...CommonReasons,
[ComAtprotoModerationDefs.REASONVIOLATION]: {
title: 'Name or Description Violates Community Standards',
description: 'Terms used violate community standards',
},
},
}
const AccountReportReasons = {
[ComAtprotoModerationDefs.REASONMISLEADING]: {
title: 'Misleading Account',
description: 'Impersonation or false claims about identity or affiliation',
},
[ComAtprotoModerationDefs.REASONSPAM]: {
title: 'Frequently Posts Unwanted Content',
description: 'Spam; excessive mentions or replies',
},
[ComAtprotoModerationDefs.REASONVIOLATION]: {
title: 'Name or Description Violates Community Standards',
description: 'Terms used violate community standards',
},
}
const Option = ({
pal,
title,
description,
}: {
pal: UsePaletteValue
description: string
title: string
}) => {
return (
<View>
<Text style={pal.text} type="md-bold">
{title}
</Text>
<Text style={pal.textLight}>{description}</Text>
</View>
)
}
// This is mostly just content copy without almost any logic
// so this may grow over time and it makes sense to split it up into its own file
// to keep it separate from the actual reporting modal logic
const useReportRadioOptions = (pal: UsePaletteValue, atUri: AtUri | null) =>
useMemo(() => {
let items: ReasonMap = {...CommonReasons}
// If no atUri is passed, that means the reporting collection is account
if (!atUri) {
items = {...AccountReportReasons}
}
if (atUri?.collection && CollectionToReasonsMap[atUri.collection]) {
items = {...CollectionToReasonsMap[atUri.collection]}
}
return Object.entries(items).map(([key, {title, description}]) => ({
key,
label: <Option pal={pal} title={title} description={description} />,
}))
}, [pal, atUri])
export const ReportReasonOptions = ({
atUri,
selectedIssue,
onSelectIssue,
}: {
atUri: AtUri | null
selectedIssue?: string
onSelectIssue: (key: string) => void
}) => {
const pal = usePalette('default')
const ITEMS: RadioGroupItem[] = useReportRadioOptions(pal, atUri)
return (
<RadioGroup
items={ITEMS}
onSelect={onSelectIssue}
testID="reportReasonRadios"
initialSelection={selectedIssue}
/>
)
}
|