forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useCallback, useMemo, useState} from 'react'
2import {View} from 'react-native'
3import {msg} from '@lingui/core/macro'
4import {useLingui} from '@lingui/react'
5import {Trans} from '@lingui/react/macro'
6import deepEqual from 'fast-deep-equal'
7
8import {logger} from '#/logger'
9import {usePostInteractionSettingsMutation} from '#/state/queries/post-interaction-settings'
10import {createPostgateRecord} from '#/state/queries/postgate/util'
11import {
12 usePreferencesQuery,
13 type UsePreferencesQueryResponse,
14} from '#/state/queries/preferences'
15import {
16 threadgateAllowUISettingToAllowRecordValue,
17 threadgateRecordToAllowUISetting,
18} from '#/state/queries/threadgate'
19import {atoms as a, useGutters} from '#/alf'
20import {Admonition} from '#/components/Admonition'
21import {PostInteractionSettingsForm} from '#/components/dialogs/PostInteractionSettingsDialog'
22import * as Layout from '#/components/Layout'
23import {Loader} from '#/components/Loader'
24import * as Toast from '#/components/Toast'
25
26export function Screen() {
27 const gutters = useGutters(['base'])
28 const {data: preferences} = usePreferencesQuery()
29 return (
30 <Layout.Screen testID="ModerationInteractionSettingsScreen">
31 <Layout.Header.Outer>
32 <Layout.Header.BackButton />
33 <Layout.Header.Content>
34 <Layout.Header.TitleText>
35 <Trans>Post Interaction Settings</Trans>
36 </Layout.Header.TitleText>
37 </Layout.Header.Content>
38 <Layout.Header.Slot />
39 </Layout.Header.Outer>
40 <Layout.Content>
41 <View style={[gutters, a.gap_xl]}>
42 <Admonition type="tip">
43 <Trans>
44 The following settings will be used as your defaults when creating
45 new posts. You can edit these for a specific post from the
46 composer.
47 </Trans>
48 </Admonition>
49 {preferences ? (
50 <Inner preferences={preferences} />
51 ) : (
52 <View style={[gutters, a.justify_center, a.align_center]}>
53 <Loader size="xl" />
54 </View>
55 )}
56 </View>
57 </Layout.Content>
58 </Layout.Screen>
59 )
60}
61
62function Inner({preferences}: {preferences: UsePreferencesQueryResponse}) {
63 const {_} = useLingui()
64 const {mutateAsync: setPostInteractionSettings, isPending} =
65 usePostInteractionSettingsMutation()
66 const [error, setError] = useState<string | undefined>(undefined)
67
68 const allowUI = useMemo(() => {
69 return threadgateRecordToAllowUISetting({
70 $type: 'app.bsky.feed.threadgate',
71 post: '',
72 createdAt: new Date().toString(),
73 allow: preferences.postInteractionSettings.threadgateAllowRules,
74 })
75 }, [preferences.postInteractionSettings.threadgateAllowRules])
76 const postgate = useMemo(() => {
77 return createPostgateRecord({
78 post: '',
79 embeddingRules:
80 preferences.postInteractionSettings.postgateEmbeddingRules,
81 })
82 }, [preferences.postInteractionSettings.postgateEmbeddingRules])
83
84 const [maybeEditedAllowUI, setAllowUI] = useState(allowUI)
85 const [maybeEditedPostgate, setEditedPostgate] = useState(postgate)
86
87 const wasEdited = useMemo(() => {
88 return (
89 !deepEqual(allowUI, maybeEditedAllowUI) ||
90 !deepEqual(postgate.embeddingRules, maybeEditedPostgate.embeddingRules)
91 )
92 }, [postgate, allowUI, maybeEditedAllowUI, maybeEditedPostgate])
93
94 const onSave = useCallback(async () => {
95 setError('')
96
97 try {
98 await setPostInteractionSettings({
99 threadgateAllowRules:
100 threadgateAllowUISettingToAllowRecordValue(maybeEditedAllowUI),
101 postgateEmbeddingRules: maybeEditedPostgate.embeddingRules ?? [],
102 })
103 Toast.show(_(msg({message: 'Settings saved', context: 'toast'})))
104 } catch (e: any) {
105 logger.error(`Failed to save post interaction settings`, {
106 source: 'ModerationInteractionSettingsScreen',
107 safeMessage: e.message,
108 })
109 setError(_(msg`Failed to save settings. Please try again.`))
110 }
111 }, [_, maybeEditedPostgate, maybeEditedAllowUI, setPostInteractionSettings])
112
113 return (
114 <>
115 <PostInteractionSettingsForm
116 canSave={wasEdited}
117 isSaving={isPending}
118 onSave={onSave}
119 postgate={maybeEditedPostgate}
120 onChangePostgate={setEditedPostgate}
121 threadgateAllowUISettings={maybeEditedAllowUI}
122 onChangeThreadgateAllowUISettings={setAllowUI}
123 />
124
125 {error && <Admonition type="error">{error}</Admonition>}
126 </>
127 )
128}