mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at switch-session-failure 265 lines 7.2 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import {AppBskyLabelerDefs} from '@atproto/api' 4import {msg, Trans} from '@lingui/macro' 5import {useLingui} from '@lingui/react' 6 7import {getLabelingServiceTitle} from '#/lib/moderation' 8import {ReportOption} from '#/lib/moderation/useReportOptions' 9import {useAgent} from '#/state/session' 10import {CharProgress} from '#/view/com/composer/char-progress/CharProgress' 11import * as Toast from '#/view/com/util/Toast' 12import {atoms as a, native, useTheme} from '#/alf' 13import {Button, ButtonIcon, ButtonText} from '#/components/Button' 14import * as Dialog from '#/components/Dialog' 15import * as Toggle from '#/components/forms/Toggle' 16import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' 17import {ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft} from '#/components/icons/Chevron' 18import {Loader} from '#/components/Loader' 19import {Text} from '#/components/Typography' 20import {ReportDialogProps} from './types' 21 22export function SubmitView({ 23 params, 24 labelers, 25 selectedLabeler, 26 selectedReportOption, 27 goBack, 28 onSubmitComplete, 29}: ReportDialogProps & { 30 labelers: AppBskyLabelerDefs.LabelerViewDetailed[] 31 selectedLabeler: string 32 selectedReportOption: ReportOption 33 goBack: () => void 34 onSubmitComplete: () => void 35}) { 36 const t = useTheme() 37 const {_} = useLingui() 38 const {getAgent} = useAgent() 39 const [details, setDetails] = React.useState<string>('') 40 const [submitting, setSubmitting] = React.useState<boolean>(false) 41 const [selectedServices, setSelectedServices] = React.useState<string[]>([ 42 selectedLabeler, 43 ]) 44 const [error, setError] = React.useState('') 45 46 const submit = React.useCallback(async () => { 47 setSubmitting(true) 48 setError('') 49 50 const $type = 51 params.type === 'account' 52 ? 'com.atproto.admin.defs#repoRef' 53 : 'com.atproto.repo.strongRef' 54 const report = { 55 reasonType: selectedReportOption.reason, 56 subject: { 57 $type, 58 ...params, 59 }, 60 reason: details, 61 } 62 const results = await Promise.all( 63 selectedServices.map(did => 64 getAgent() 65 .withProxy('atproto_labeler', did) 66 .createModerationReport(report) 67 .then( 68 _ => true, 69 _ => false, 70 ), 71 ), 72 ) 73 74 setSubmitting(false) 75 76 if (results.includes(true)) { 77 Toast.show(_(msg`Thank you. Your report has been sent.`)) 78 onSubmitComplete() 79 } else { 80 setError( 81 _( 82 msg`There was an issue sending your report. Please check your internet connection.`, 83 ), 84 ) 85 } 86 }, [ 87 _, 88 params, 89 details, 90 selectedReportOption, 91 selectedServices, 92 onSubmitComplete, 93 setError, 94 getAgent, 95 ]) 96 97 return ( 98 <View style={[a.gap_2xl]}> 99 <Button 100 size="small" 101 variant="solid" 102 color="secondary" 103 shape="round" 104 label={_(msg`Go back to previous step`)} 105 onPress={goBack}> 106 <ButtonIcon icon={ChevronLeft} /> 107 </Button> 108 109 <View 110 style={[ 111 a.w_full, 112 a.flex_row, 113 a.align_center, 114 a.justify_between, 115 a.gap_lg, 116 a.p_md, 117 a.rounded_md, 118 a.border, 119 t.atoms.border_contrast_low, 120 ]}> 121 <View style={[a.flex_1, a.gap_xs]}> 122 <Text style={[a.text_md, a.font_bold]}> 123 {selectedReportOption.title} 124 </Text> 125 <Text style={[a.leading_tight, {maxWidth: 400}]}> 126 {selectedReportOption.description} 127 </Text> 128 </View> 129 130 <Check size="md" style={[a.pr_sm, t.atoms.text_contrast_low]} /> 131 </View> 132 133 <View style={[a.gap_md]}> 134 <Text style={[t.atoms.text_contrast_medium]}> 135 <Trans>Select the moderation service(s) to report to</Trans> 136 </Text> 137 138 <Toggle.Group 139 label="Select mod services" 140 values={selectedServices} 141 onChange={setSelectedServices}> 142 <View style={[a.flex_row, a.gap_md, a.flex_wrap]}> 143 {labelers.map(labeler => { 144 const title = getLabelingServiceTitle({ 145 displayName: labeler.creator.displayName, 146 handle: labeler.creator.handle, 147 }) 148 return ( 149 <Toggle.Item 150 key={labeler.creator.did} 151 name={labeler.creator.did} 152 label={title}> 153 <LabelerToggle title={title} /> 154 </Toggle.Item> 155 ) 156 })} 157 </View> 158 </Toggle.Group> 159 </View> 160 <View style={[a.gap_md]}> 161 <Text style={[t.atoms.text_contrast_medium]}> 162 <Trans>Optionally provide additional information below:</Trans> 163 </Text> 164 165 <View style={[a.relative, a.w_full]}> 166 <Dialog.Input 167 multiline 168 value={details} 169 onChangeText={setDetails} 170 label="Text field" 171 style={{paddingRight: 60}} 172 numberOfLines={6} 173 /> 174 175 <View 176 style={[ 177 a.absolute, 178 a.flex_row, 179 a.align_center, 180 a.pr_md, 181 a.pb_sm, 182 { 183 bottom: 0, 184 right: 0, 185 }, 186 ]}> 187 <CharProgress count={details?.length || 0} /> 188 </View> 189 </View> 190 </View> 191 192 <View style={[a.flex_row, a.align_center, a.justify_end, a.gap_lg]}> 193 {!selectedServices.length || 194 (error && ( 195 <Text 196 style={[ 197 a.flex_1, 198 a.italic, 199 a.leading_snug, 200 t.atoms.text_contrast_medium, 201 ]}> 202 {error ? ( 203 error 204 ) : ( 205 <Trans>You must select at least one labeler for a report</Trans> 206 )} 207 </Text> 208 ))} 209 210 <Button 211 testID="sendReportBtn" 212 size="large" 213 variant="solid" 214 color="negative" 215 label={_(msg`Send report`)} 216 onPress={submit} 217 disabled={!selectedServices.length}> 218 <ButtonText> 219 <Trans>Send report</Trans> 220 </ButtonText> 221 {submitting && <ButtonIcon icon={Loader} />} 222 </Button> 223 </View> 224 </View> 225 ) 226} 227 228function LabelerToggle({title}: {title: string}) { 229 const t = useTheme() 230 const ctx = Toggle.useItemContext() 231 232 return ( 233 <View 234 style={[ 235 a.flex_row, 236 a.align_center, 237 a.gap_md, 238 a.p_md, 239 a.pr_lg, 240 a.rounded_sm, 241 a.overflow_hidden, 242 t.atoms.bg_contrast_25, 243 ctx.selected && [t.atoms.bg_contrast_50], 244 ]}> 245 <Toggle.Checkbox /> 246 <View 247 style={[ 248 a.flex_row, 249 a.align_center, 250 a.justify_between, 251 a.gap_lg, 252 a.z_10, 253 ]}> 254 <Text 255 style={[ 256 native({marginTop: 2}), 257 t.atoms.text_contrast_medium, 258 ctx.selected && t.atoms.text, 259 ]}> 260 {title} 261 </Text> 262 </View> 263 </View> 264 ) 265}