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

Configure Feed

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

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