Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 967b3b49d9b0bdbe9c8fd7ea802ecf780b9e1a0c 143 lines 4.2 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import {ToolsOzoneReportDefs} from '@atproto/api' 4import {msg, Trans} from '@lingui/macro' 5import {useLingui} from '@lingui/react' 6import {useMutation} from '@tanstack/react-query' 7 8import {BLUESKY_MOD_SERVICE_HEADERS} from '#/lib/constants' 9import {useAgent, useSession} from '#/state/session' 10import * as Toast from '#/view/com/util/Toast' 11import {atoms as a, useBreakpoints, web} from '#/alf' 12import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' 13import {Button, ButtonIcon, ButtonText} from '#/components/Button' 14import * as Dialog from '#/components/Dialog' 15import {Loader} from '#/components/Loader' 16import {Text} from '#/components/Typography' 17import {logger} from '#/ageAssurance' 18import {useAnalytics} from '#/analytics' 19 20export function AgeAssuranceAppealDialog({ 21 control, 22}: { 23 control: Dialog.DialogControlProps 24}) { 25 const {_} = useLingui() 26 return ( 27 <Dialog.Outer control={control}> 28 <Dialog.Handle /> 29 <Dialog.ScrollableInner 30 label={_(msg`Contact our moderation team`)} 31 style={[web({maxWidth: 400})]}> 32 <Inner control={control} /> 33 <Dialog.Close /> 34 </Dialog.ScrollableInner> 35 </Dialog.Outer> 36 ) 37} 38 39function Inner({control}: {control: Dialog.DialogControlProps}) { 40 const {_} = useLingui() 41 const ax = useAnalytics() 42 const {currentAccount} = useSession() 43 const {gtPhone} = useBreakpoints() 44 const agent = useAgent() 45 46 const [details, setDetails] = React.useState('') 47 const isInvalid = details.length > 1000 48 49 const {mutate, isPending} = useMutation({ 50 mutationFn: async () => { 51 ax.metric('ageAssurance:appealDialogSubmit', {}) 52 53 await agent.createModerationReport( 54 { 55 reasonType: ToolsOzoneReportDefs.REASONAPPEAL, 56 subject: { 57 $type: 'com.atproto.admin.defs#repoRef', 58 did: currentAccount?.did, 59 }, 60 reason: `AGE_ASSURANCE_INQUIRY: ` + details, 61 }, 62 { 63 encoding: 'application/json', 64 headers: BLUESKY_MOD_SERVICE_HEADERS, 65 }, 66 ) 67 }, 68 onError: err => { 69 logger.error('AgeAssuranceAppealDialog failed', {safeMessage: err}) 70 Toast.show( 71 _(msg`Age assurance inquiry failed to send, please try again.`), 72 'xmark', 73 ) 74 }, 75 onSuccess: () => { 76 control.close() 77 Toast.show( 78 _( 79 msg({ 80 message: 'Age assurance inquiry was submitted', 81 context: 'toast', 82 }), 83 ), 84 ) 85 }, 86 }) 87 88 return ( 89 <View> 90 <View style={[a.align_start]}> 91 <AgeAssuranceBadge /> 92 </View> 93 94 <Text style={[a.text_2xl, a.font_bold, a.pt_md, a.leading_tight]}> 95 <Trans>Contact us</Trans> 96 </Text> 97 98 <Text style={[a.text_sm, a.pt_sm, a.leading_snug]}> 99 <Trans> 100 Please provide any additional details you feel moderators may need in 101 order to properly assess your Age Assurance status. 102 </Trans> 103 </Text> 104 105 <View style={[a.pt_md]}> 106 <Dialog.Input 107 multiline 108 isInvalid={isInvalid} 109 value={details} 110 onChangeText={details => { 111 setDetails(details) 112 }} 113 label={_(msg`Additional details (limit 1000 characters)`)} 114 numberOfLines={4} 115 onSubmitEditing={() => mutate()} 116 /> 117 <View style={[a.pt_md, a.gap_sm, gtPhone && [a.flex_row_reverse]]}> 118 <Button 119 label={_(msg`Submit`)} 120 size="small" 121 variant="solid" 122 color="primary" 123 onPress={() => mutate()}> 124 <ButtonText> 125 <Trans>Submit</Trans> 126 </ButtonText> 127 {isPending && <ButtonIcon icon={Loader} position="right" />} 128 </Button> 129 <Button 130 label={_(msg`Cancel`)} 131 size="small" 132 variant="solid" 133 color="secondary" 134 onPress={() => control.close()}> 135 <ButtonText> 136 <Trans>Cancel</Trans> 137 </ButtonText> 138 </Button> 139 </View> 140 </View> 141 </View> 142 ) 143}