Update report modal to use new groupings (close [APP-567]) (#533)

zio/stable
Paul Frazee 2023-04-25 21:04:50 -05:00 committed by GitHub
parent 9b86cb5c36
commit fc19ffba38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 142 additions and 51 deletions

View File

@ -1,4 +1,4 @@
import React, {useState} from 'react' import React, {useState, useMemo} from 'react'
import { import {
ActivityIndicator, ActivityIndicator,
StyleSheet, StyleSheet,
@ -15,12 +15,7 @@ import * as Toast from '../util/Toast'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
import {cleanError} from 'lib/strings/errors' import {cleanError} from 'lib/strings/errors'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {isDesktopWeb} from 'platform/detection'
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 const snapPoints = ['50%']
@ -31,6 +26,39 @@ export function Component({did}: {did: string}) {
const [error, setError] = useState<string>('') const [error, setError] = useState<string>('')
const [issue, setIssue] = useState<string>('') const [issue, setIssue] = useState<string>('')
const onSelectIssue = (v: string) => setIssue(v) const onSelectIssue = (v: string) => setIssue(v)
const ITEMS: RadioGroupItem[] = useMemo(
() => [
{
key: ComAtprotoModerationDefs.REASONMISLEADING,
label: (
<View>
<Text style={pal.text} type="md-bold">
Misleading Account
</Text>
<Text style={pal.textLight}>
Impersonation or false claims about identity or affiliation
</Text>
</View>
),
},
{
key: ComAtprotoModerationDefs.REASONSPAM,
label: (
<View>
<Text style={pal.text} type="md-bold">
Frequently Posts Unwanted Content
</Text>
<Text style={pal.textLight}>
Spam; excessive mentions or replies
</Text>
</View>
),
},
],
[pal],
)
const onPress = async () => { const onPress = async () => {
setError('') setError('')
if (!issue) { if (!issue) {
@ -38,15 +66,8 @@ export function Component({did}: {did: string}) {
} }
setIsProcessing(true) setIsProcessing(true)
try { 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({ await store.agent.com.atproto.moderation.createReport({
reasonType, reasonType: issue,
reason,
subject: { subject: {
$type: 'com.atproto.admin.defs#repoRef', $type: 'com.atproto.admin.defs#repoRef',
did, did,
@ -61,11 +82,11 @@ export function Component({did}: {did: string}) {
} }
} }
return ( return (
<View <View testID="reportAccountModal" style={[styles.container, pal.view]}>
testID="reportAccountModal" <Text type="title-xl" style={[pal.text, styles.title]}>
style={[s.flex1, s.pl10, s.pr10, pal.view]}> Report account
<Text style={[pal.text, styles.title]}>Report account</Text> </Text>
<Text style={[pal.textLight, styles.description]}> <Text type="xl" style={[pal.text, styles.description]}>
What is the issue with this account? What is the issue with this account?
</Text> </Text>
<RadioGroup <RadioGroup
@ -73,6 +94,9 @@ export function Component({did}: {did: string}) {
items={ITEMS} items={ITEMS}
onSelect={onSelectIssue} onSelect={onSelectIssue}
/> />
<Text type="sm" style={[pal.text, styles.description, s.pt10]}>
For other issues, please report specific posts.
</Text>
{error ? ( {error ? (
<View style={s.mt10}> <View style={s.mt10}>
<ErrorMessage message={error} /> <ErrorMessage message={error} />
@ -101,15 +125,17 @@ export function Component({did}: {did: string}) {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: isDesktopWeb ? 0 : 10,
},
title: { title: {
textAlign: 'center', textAlign: 'center',
fontWeight: 'bold', fontWeight: 'bold',
fontSize: 24,
marginBottom: 12, marginBottom: 12,
}, },
description: { description: {
textAlign: 'center', textAlign: 'center',
fontSize: 17,
paddingHorizontal: 22, paddingHorizontal: 22,
marginBottom: 10, marginBottom: 10,
}, },

View File

@ -1,6 +1,7 @@
import React, {useState} from 'react' import React, {useState, useMemo} from 'react'
import { import {
ActivityIndicator, ActivityIndicator,
Linking,
StyleSheet, StyleSheet,
TouchableOpacity, TouchableOpacity,
View, View,
@ -16,14 +17,9 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
import {cleanError} from 'lib/strings/errors' import {cleanError} from 'lib/strings/errors'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
const ITEMS: RadioGroupItem[] = [ const DMCA_LINK = 'https://bsky.app/support/copyright'
{key: 'spam', label: 'Spam or excessive repeat posts'},
{key: 'abuse', label: 'Abusive, rude, or hateful'},
{key: 'copyright', label: 'Contains copyrighted material'},
{key: 'illegal', label: 'Contains illegal content'},
]
export const snapPoints = ['50%'] export const snapPoints = [500]
export function Component({ export function Component({
postUri, postUri,
@ -38,6 +34,74 @@ export function Component({
const [error, setError] = useState<string>('') const [error, setError] = useState<string>('')
const [issue, setIssue] = useState<string>('') const [issue, setIssue] = useState<string>('')
const onSelectIssue = (v: string) => setIssue(v) const onSelectIssue = (v: string) => setIssue(v)
const ITEMS: RadioGroupItem[] = useMemo(
() => [
{
key: ComAtprotoModerationDefs.REASONSPAM,
label: (
<View>
<Text style={pal.text} type="md-bold">
Spam
</Text>
<Text style={pal.textLight}>Excessive mentions or replies</Text>
</View>
),
},
{
key: ComAtprotoModerationDefs.REASONSEXUAL,
label: (
<View>
<Text style={pal.text} type="md-bold">
Unwanted Sexual Content
</Text>
<Text style={pal.textLight}>
Nudity or pornography not labeled as such
</Text>
</View>
),
},
{
key: '__copyright__',
label: (
<View>
<Text style={pal.text} type="md-bold">
Copyright Violation
</Text>
<Text style={pal.textLight}>Contains copyrighted material</Text>
</View>
),
},
{
key: ComAtprotoModerationDefs.REASONVIOLATION,
label: (
<View>
<Text style={pal.text} type="md-bold">
Illegal and Urgent
</Text>
<Text style={pal.textLight}>
Glaring violations of law or terms of service
</Text>
</View>
),
},
{
key: ComAtprotoModerationDefs.REASONOTHER,
label: (
<View>
<Text style={pal.text} type="md-bold">
Other
</Text>
<Text style={pal.textLight}>
An issue not included in these options
</Text>
</View>
),
},
],
[pal],
)
const onPress = async () => { const onPress = async () => {
setError('') setError('')
if (!issue) { if (!issue) {
@ -45,22 +109,19 @@ export function Component({
} }
setIsProcessing(true) setIsProcessing(true)
try { try {
// NOTE: we should update the lexicon of reasontype to include more options -prf if (issue === '__copyright__') {
let reasonType = ComAtprotoModerationDefs.REASONOTHER Linking.openURL(DMCA_LINK)
if (issue === 'spam') { } else {
reasonType = ComAtprotoModerationDefs.REASONSPAM await store.agent.createModerationReport({
reasonType: issue,
subject: {
$type: 'com.atproto.repo.strongRef',
uri: postUri,
cid: postCid,
},
})
Toast.show("Thank you for your report! We'll look into it promptly.")
} }
const reason = ITEMS.find(item => item.key === issue)?.label || ''
await store.agent.createModerationReport({
reasonType,
reason,
subject: {
$type: 'com.atproto.repo.strongRef',
uri: postUri,
cid: postCid,
},
})
Toast.show("Thank you for your report! We'll look into it promptly.")
store.shell.closeModal() store.shell.closeModal()
return return
} catch (e: any) { } catch (e: any) {

View File

@ -15,7 +15,7 @@ export function RadioButton({
}: { }: {
testID?: string testID?: string
type?: ButtonType type?: ButtonType
label: string label: string | JSX.Element
isSelected: boolean isSelected: boolean
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
onPress: () => void onPress: () => void
@ -47,7 +47,7 @@ export function RadioButton({
borderColor: theme.palette.default.border, borderColor: theme.palette.default.border,
}, },
'default-light': { 'default-light': {
borderColor: theme.palette.default.border, borderColor: theme.palette.default.borderDark,
}, },
}) })
const circleFillStyle = choose<TextStyle, Record<ButtonType, TextStyle>>( const circleFillStyle = choose<TextStyle, Record<ButtonType, TextStyle>>(
@ -128,9 +128,13 @@ export function RadioButton({
<View style={[circleFillStyle, styles.circleFill]} /> <View style={[circleFillStyle, styles.circleFill]} />
) : undefined} ) : undefined}
</View> </View>
<Text type="button" style={[labelStyle, styles.label]}> {typeof label === 'string' ? (
{label} <Text type="button" style={[labelStyle, styles.label]}>
</Text> {label}
</Text>
) : (
<View style={styles.label}>{label}</View>
)}
</View> </View>
</Button> </Button>
) )

View File

@ -5,7 +5,7 @@ import {ButtonType} from './Button'
import {s} from 'lib/styles' import {s} from 'lib/styles'
export interface RadioGroupItem { export interface RadioGroupItem {
label: string label: string | JSX.Element
key: string key: string
} }