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