Bluesky app fork with some witchin' additions 💫 forked from jollywhoppers.com/witchsky.app
Something went wrong. Try again.
7.6 kB · 274 lines
TSX
at commit 8ce9bdb2
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275import React from 'react'import {View} from 'react-native'import {AppBskyLabelerDefs} from '@atproto/api'import {msg, Trans} from '@lingui/macro'import {useLingui} from '@lingui/react'
import {getLabelingServiceTitle} from '#/lib/moderation'import {ReportOption} from '#/lib/moderation/useReportOptions'import {isAndroid} from '#/platform/detection'import {useAgent} from '#/state/session'import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'import * as Toast from '#/view/com/util/Toast'import {atoms as a, native, useTheme} from '#/alf'import {Button, ButtonIcon, ButtonText} from '#/components/Button'import * as Dialog from '#/components/Dialog'import * as Toggle from '#/components/forms/Toggle'import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'import {ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft} from '#/components/icons/Chevron'import {PaperPlane_Stroke2_Corner0_Rounded as SendIcon} from '#/components/icons/PaperPlane'import {Loader} from '#/components/Loader'import {Text} from '#/components/Typography'import {ReportDialogProps} from './types'
export function SubmitView({ params, labelers, selectedLabeler, selectedReportOption, goBack, onSubmitComplete,}: ReportDialogProps & { labelers: AppBskyLabelerDefs.LabelerViewDetailed[] selectedLabeler: string selectedReportOption: ReportOption goBack: () => void onSubmitComplete: () => void}) { const t = useTheme() const {_} = useLingui() const agent = useAgent() const [details, setDetails] = React.useState<string>('') const [submitting, setSubmitting] = React.useState<boolean>(false) const [selectedServices, setSelectedServices] = React.useState<string[]>([ selectedLabeler, ]) const [error, setError] = React.useState('')
const submit = React.useCallback(async () => { setSubmitting(true) setError('')
const $type = params.type === 'account' ? 'com.atproto.admin.defs#repoRef' : 'com.atproto.repo.strongRef' const report = { reasonType: selectedReportOption.reason, subject: { $type, ...params, }, reason: details, } const results = await Promise.all( selectedServices.map(did => { return agent .createModerationReport(report, { encoding: 'application/json', headers: { 'atproto-proxy': `${did}#atproto_labeler`, }, }) .then( _ => true, _ => false, ) }), )
setSubmitting(false)
if (results.includes(true)) { Toast.show(_(msg`Thank you. Your report has been sent.`)) onSubmitComplete() } else { setError( _( msg`There was an issue sending your report. Please check your internet connection.`, ), ) } }, [ _, params, details, selectedReportOption, selectedServices, onSubmitComplete, setError, agent, ])
return ( <View style={[a.gap_2xl]}> <Button size="small" variant="solid" color="secondary" shape="round" label={_(msg`Go back to previous step`)} onPress={goBack}> <ButtonIcon icon={ChevronLeft} /> </Button>
<View style={[ a.w_full, a.flex_row, a.align_center, a.justify_between, a.gap_lg, a.p_md, a.rounded_md, a.border, t.atoms.border_contrast_low, ]}> <View style={[a.flex_1, a.gap_xs]}> <Text style={[a.text_md, a.font_bold]}> {selectedReportOption.title} </Text> <Text style={[a.leading_tight, {maxWidth: 400}]}> {selectedReportOption.description} </Text> </View>
<Check size="md" style={[a.pr_sm, t.atoms.text_contrast_low]} /> </View>
<View style={[a.gap_md]}> <Text style={[t.atoms.text_contrast_medium]}> <Trans>Select the moderation service(s) to report to</Trans> </Text>
<Toggle.Group label="Select mod services" values={selectedServices} onChange={setSelectedServices}> <View style={[a.flex_row, a.gap_md, a.flex_wrap]}> {labelers.map(labeler => { const title = getLabelingServiceTitle({ displayName: labeler.creator.displayName, handle: labeler.creator.handle, }) return ( <Toggle.Item key={labeler.creator.did} name={labeler.creator.did} label={title}> <LabelerToggle title={title} /> </Toggle.Item> ) })} </View> </Toggle.Group> </View> <View style={[a.gap_md]}> <Text style={[t.atoms.text_contrast_medium]}> <Trans>Optionally provide additional information below:</Trans> </Text>
<View style={[a.relative, a.w_full]}> <Dialog.Input multiline value={details} onChangeText={setDetails} label="Text field" style={{paddingRight: 60}} numberOfLines={6} />
<View style={[ a.absolute, a.flex_row, a.align_center, a.pr_md, a.pb_sm, { bottom: 0, right: 0, }, ]}> <CharProgress count={details?.length || 0} /> </View> </View> </View>
<View style={[a.flex_row, a.align_center, a.justify_end, a.gap_lg]}> {!selectedServices.length || (error && ( <Text style={[ a.flex_1, a.italic, a.leading_snug, t.atoms.text_contrast_medium, ]}> {error ? ( error ) : ( <Trans>You must select at least one labeler for a report</Trans> )} </Text> ))}
<Button testID="sendReportBtn" size="large" variant="solid" color="negative" label={_(msg`Send report`)} onPress={submit} disabled={!selectedServices.length}> <ButtonText> <Trans>Send report</Trans> </ButtonText> <ButtonIcon icon={submitting ? Loader : SendIcon} /> </Button> </View> {/* Maybe fix this later -h */} {isAndroid ? <View style={{height: 300}} /> : null} </View> )}
function LabelerToggle({title}: {title: string}) { const t = useTheme() const ctx = Toggle.useItemContext()
return ( <View style={[ a.flex_row, a.align_center, a.gap_md, a.p_md, a.pr_lg, a.rounded_sm, a.overflow_hidden, t.atoms.bg_contrast_25, ctx.selected && [t.atoms.bg_contrast_50], ]}> <Toggle.Checkbox /> <View style={[ a.flex_row, a.align_center, a.justify_between, a.gap_lg, a.z_10, ]}> <Text emoji style={[ native({marginTop: 2}), t.atoms.text_contrast_medium, ctx.selected && t.atoms.text, ]}> {title} </Text> </View> </View> )}