forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useCallback, useState} from 'react'
2import {View} from 'react-native'
3import {type AppBskyActorDefs, 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 {logger} from '#/logger'
10import {useAgent} from '#/state/session'
11import {atoms as a, web} from '#/alf'
12import {Button, ButtonIcon, ButtonText} from '#/components/Button'
13import * as Dialog from '#/components/Dialog'
14import {Loader} from '#/components/Loader'
15import * as Toast from '#/components/Toast'
16import {Text} from '#/components/Typography'
17
18export function GoLiveDisabledDialog({
19 control,
20 status,
21}: {
22 control: Dialog.DialogControlProps
23 status: AppBskyActorDefs.StatusView
24}) {
25 return (
26 <Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
27 <Dialog.Handle />
28 <DialogInner control={control} status={status} />
29 </Dialog.Outer>
30 )
31}
32
33export function DialogInner({
34 control,
35 status,
36}: {
37 control: Dialog.DialogControlProps
38 status: AppBskyActorDefs.StatusView
39}) {
40 const {_} = useLingui()
41 const agent = useAgent()
42 const [details, setDetails] = useState('')
43
44 const {mutate, isPending} = useMutation({
45 mutationFn: async () => {
46 if (!agent.session?.did) {
47 throw new Error('Not logged in')
48 }
49 if (!status.uri || !status.cid) {
50 throw new Error('Status is missing uri or cid')
51 }
52
53 if (__DEV__) {
54 logger.info('Submitting go live appeal', {
55 details,
56 })
57 } else {
58 await agent.createModerationReport(
59 {
60 reasonType: ToolsOzoneReportDefs.REASONAPPEAL,
61 subject: {
62 $type: 'com.atproto.repo.strongRef',
63 uri: status.uri,
64 cid: status.cid,
65 },
66 reason: details,
67 },
68 {
69 encoding: 'application/json',
70 headers: BLUESKY_MOD_SERVICE_HEADERS,
71 },
72 )
73 }
74 },
75 onError: () => {
76 Toast.show(_(msg`Failed to submit appeal, please try again.`), {
77 type: 'error',
78 })
79 },
80 onSuccess: () => {
81 control.close()
82 Toast.show(_(msg({message: 'Appeal submitted', context: 'toast'})), {
83 type: 'success',
84 })
85 },
86 })
87
88 const onSubmit = useCallback(() => mutate(), [mutate])
89
90 return (
91 <Dialog.ScrollableInner
92 label={_(msg`Appeal livestream suspension`)}
93 style={[web({maxWidth: 400})]}>
94 <View style={[a.gap_lg]}>
95 <View style={[a.gap_md]}>
96 <Text
97 style={[
98 a.flex_1,
99 a.text_2xl,
100 a.font_semi_bold,
101 a.leading_snug,
102 a.pr_4xl,
103 ]}>
104 <Trans>Going live is currently disabled for your account</Trans>
105 </Text>
106 <Text style={[a.text_md, a.leading_snug]}>
107 <Trans>
108 You are currently blocked from using the Go Live feature. To
109 appeal this moderation decision, please submit the form below.
110 </Trans>
111 </Text>
112 <Text style={[a.text_md, a.leading_snug]}>
113 <Trans>
114 This appeal will be sent to Bluesky's moderation service.
115 </Trans>
116 </Text>
117 </View>
118
119 <View style={[a.gap_md]}>
120 <Dialog.Input
121 label={_(msg`Text input field`)}
122 placeholder={_(
123 msg`Please explain why you think your Go Live access was incorrectly disabled.`,
124 )}
125 value={details}
126 onChangeText={setDetails}
127 autoFocus={true}
128 numberOfLines={3}
129 multiline
130 maxLength={300}
131 />
132 <Button
133 testID="submitBtn"
134 variant="solid"
135 color="primary"
136 size="large"
137 onPress={onSubmit}
138 label={_(msg`Submit`)}>
139 <ButtonText>{_(msg`Submit`)}</ButtonText>
140 {isPending && <ButtonIcon icon={Loader} />}
141 </Button>
142 </View>
143 </View>
144 <Dialog.Close />
145 </Dialog.ScrollableInner>
146 )
147}