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
124
125
|
import React, {useState} from 'react'
import {
ActivityIndicator,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native'
import {ComAtprotoModerationDefs} from '@atproto/api'
import LinearGradient from 'react-native-linear-gradient'
import {useStores} from 'state/index'
import {s, colors, gradients} from 'lib/styles'
import {RadioGroup, RadioGroupItem} from '../util/forms/RadioGroup'
import {Text} from '../util/text/Text'
import * as Toast from '../util/Toast'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {cleanError} from 'lib/strings/errors'
import {usePalette} from 'lib/hooks/usePalette'
const ITEMS: RadioGroupItem[] = [
{key: 'spam', label: 'Spam or excessive repeat posts'},
{key: 'abuse', label: 'Abusive, rude, or hateful'},
{key: 'illegal', label: 'Posts illegal content'},
]
export const snapPoints = ['50%']
export function Component({did}: {did: string}) {
const store = useStores()
const pal = usePalette('default')
const [isProcessing, setIsProcessing] = useState<boolean>(false)
const [error, setError] = useState<string>('')
const [issue, setIssue] = useState<string>('')
const onSelectIssue = (v: string) => setIssue(v)
const onPress = async () => {
setError('')
if (!issue) {
return
}
setIsProcessing(true)
try {
// NOTE: we should update the lexicon of reasontype to include more options -prf
let reasonType = ComAtprotoModerationDefs.REASONOTHER
if (issue === 'spam') {
reasonType = ComAtprotoModerationDefs.REASONSPAM
}
const reason = ITEMS.find(item => item.key === issue)?.label || ''
await store.agent.com.atproto.moderation.createReport({
reasonType,
reason,
subject: {
$type: 'com.atproto.admin.defs#repoRef',
did,
},
})
Toast.show("Thank you for your report! We'll look into it promptly.")
store.shell.closeModal()
return
} catch (e: any) {
setError(cleanError(e))
setIsProcessing(false)
}
}
return (
<View
testID="reportAccountModal"
style={[s.flex1, s.pl10, s.pr10, pal.view]}>
<Text style={[pal.text, styles.title]}>Report account</Text>
<Text style={[pal.textLight, styles.description]}>
What is the issue with this account?
</Text>
<RadioGroup
testID="reportAccountRadios"
items={ITEMS}
onSelect={onSelectIssue}
/>
{error ? (
<View style={s.mt10}>
<ErrorMessage message={error} />
</View>
) : undefined}
{isProcessing ? (
<View style={[styles.btn, s.mt10]}>
<ActivityIndicator />
</View>
) : issue ? (
<TouchableOpacity
testID="sendReportBtn"
style={s.mt10}
onPress={onPress}>
<LinearGradient
colors={[gradients.blueLight.start, gradients.blueLight.end]}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}
style={[styles.btn]}>
<Text style={[s.white, s.bold, s.f18]}>Send Report</Text>
</LinearGradient>
</TouchableOpacity>
) : undefined}
</View>
)
}
const styles = StyleSheet.create({
title: {
textAlign: 'center',
fontWeight: 'bold',
fontSize: 24,
marginBottom: 12,
},
description: {
textAlign: 'center',
fontSize: 17,
paddingHorizontal: 22,
marginBottom: 10,
},
btn: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
borderRadius: 32,
padding: 14,
backgroundColor: colors.gray1,
},
})
|