Handle edited state

This commit is contained in:
Eric Bailey
2025-02-05 17:06:30 -06:00
parent 7f8aee3583
commit b5406347a5
4 changed files with 50 additions and 31 deletions
+1
View File
@@ -148,6 +148,7 @@
"expo-updates": "~0.26.10", "expo-updates": "~0.26.10",
"expo-video": "^2.0.5", "expo-video": "^2.0.5",
"expo-web-browser": "~14.0.1", "expo-web-browser": "~14.0.1",
"fast-deep-equal": "^3.1.3",
"fast-text-encoding": "^1.0.6", "fast-text-encoding": "^1.0.6",
"history": "^5.3.0", "history": "^5.3.0",
"hls.js": "^1.5.11", "hls.js": "^1.5.11",
@@ -30,16 +30,19 @@ import {
import {useAgent, useSession} from '#/state/session' import {useAgent, useSession} from '#/state/session'
import * as Toast from '#/view/com/util/Toast' import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {Divider} from '#/components/Divider' import {Divider} from '#/components/Divider'
import * as Toggle from '#/components/forms/Toggle' import * as Toggle from '#/components/forms/Toggle'
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {InlineLinkText} from '#/components/Link'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
export type PostInteractionSettingsFormProps = { export type PostInteractionSettingsFormProps = {
canSave?: boolean
onSave: () => void onSave: () => void
isSaving?: boolean isSaving?: boolean
@@ -59,6 +62,7 @@ export function PostInteractionSettingsControlledDialog({
control: Dialog.DialogControlProps control: Dialog.DialogControlProps
}) { }) {
const {_} = useLingui() const {_} = useLingui()
return ( return (
<Dialog.Outer control={control}> <Dialog.Outer control={control}>
<Dialog.Handle /> <Dialog.Handle />
@@ -68,6 +72,16 @@ export function PostInteractionSettingsControlledDialog({
<View style={[a.gap_md]}> <View style={[a.gap_md]}>
<Header /> <Header />
<PostInteractionSettingsForm {...rest} /> <PostInteractionSettingsForm {...rest} />
<Admonition type="tip" style={[a.mt_sm]}>
<Trans>
You can configure defaults for these settings from within your{' '}
<InlineLinkText
label={_(msg`Configure default interaction settings`)}
to="/moderation/interaction-settings">
moderation settings screen.
</InlineLinkText>
</Trans>
</Admonition>
</View> </View>
<Dialog.Close /> <Dialog.Close />
</Dialog.ScrollableInner> </Dialog.ScrollableInner>
@@ -244,6 +258,7 @@ export function PostInteractionSettingsDialogControlledInner(
} }
export function PostInteractionSettingsForm({ export function PostInteractionSettingsForm({
canSave = true,
onSave, onSave,
isSaving, isSaving,
postgate, postgate,
@@ -446,6 +461,7 @@ export function PostInteractionSettingsForm({
</View> </View>
<Button <Button
disabled={!canSave || isSaving}
label={_(msg`Save`)} label={_(msg`Save`)}
onPress={onSave} onPress={onSave}
color="primary" color="primary"
@@ -2,6 +2,7 @@ import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import deepEqual from 'fast-deep-equal'
import {logger} from '#/logger' import {logger} from '#/logger'
import {usePostInteractionSettingsMutation} from '#/state/queries/post-interaction-settings' import {usePostInteractionSettingsMutation} from '#/state/queries/post-interaction-settings'
@@ -11,7 +12,6 @@ import {
UsePreferencesQueryResponse, UsePreferencesQueryResponse,
} from '#/state/queries/preferences' } from '#/state/queries/preferences'
import { import {
ThreadgateAllowUISetting,
threadgateAllowUISettingToAllowRecordValue, threadgateAllowUISettingToAllowRecordValue,
threadgateRecordToAllowUISetting, threadgateRecordToAllowUISetting,
} from '#/state/queries/threadgate' } from '#/state/queries/threadgate'
@@ -40,8 +40,8 @@ export function Screen() {
<View style={[gutters, a.gap_xl]}> <View style={[gutters, a.gap_xl]}>
<Admonition type="tip"> <Admonition type="tip">
<Trans> <Trans>
The following settings will be applied automatically to all new The following settings will be used as your defaults when creating
posts you create. new posts. They can be edited from the composer before you post.
</Trans> </Trans>
</Admonition> </Admonition>
{preferences ? ( {preferences ? (
@@ -63,23 +63,31 @@ function Inner({preferences}: {preferences: UsePreferencesQueryResponse}) {
usePostInteractionSettingsMutation() usePostInteractionSettingsMutation()
const [error, setError] = React.useState<string | undefined>(undefined) const [error, setError] = React.useState<string | undefined>(undefined)
const [postgate, setPostgate] = React.useState(() => { const allowUI = React.useMemo(() => {
return createPostgateRecord({
post: '',
embeddingRules:
preferences.postInteractionSettings.postgateEmbeddingRules,
})
})
const [allowUISettings, setAllowUISettings] = React.useState<
ThreadgateAllowUISetting[]
>(() => {
return threadgateRecordToAllowUISetting({ return threadgateRecordToAllowUISetting({
$type: 'app.bsky.feed.threadgate', $type: 'app.bsky.feed.threadgate',
post: '', post: '',
createdAt: new Date().toString(), createdAt: new Date().toString(),
allow: preferences.postInteractionSettings.threadgateAllowRules, allow: preferences.postInteractionSettings.threadgateAllowRules,
}) })
}) }, [preferences.postInteractionSettings.threadgateAllowRules])
const postgate = React.useMemo(() => {
return createPostgateRecord({
post: '',
embeddingRules:
preferences.postInteractionSettings.postgateEmbeddingRules,
})
}, [preferences.postInteractionSettings.postgateEmbeddingRules])
const [maybeEditedAllowUI, setAllowUI] = React.useState(allowUI)
const [maybeEditedPostgate, setEditedPostgate] = React.useState(postgate)
const wasEdited = React.useMemo(() => {
return (
!deepEqual(allowUI, maybeEditedAllowUI) ||
!deepEqual(postgate.embeddingRules, maybeEditedPostgate.embeddingRules)
)
}, [postgate, allowUI, maybeEditedAllowUI, maybeEditedPostgate])
const onSave = React.useCallback(async () => { const onSave = React.useCallback(async () => {
setError('') setError('')
@@ -87,8 +95,8 @@ function Inner({preferences}: {preferences: UsePreferencesQueryResponse}) {
try { try {
await setPostInteractionSettings({ await setPostInteractionSettings({
threadgateAllowRules: threadgateAllowRules:
threadgateAllowUISettingToAllowRecordValue(allowUISettings), threadgateAllowUISettingToAllowRecordValue(maybeEditedAllowUI),
postgateEmbeddingRules: postgate.embeddingRules ?? [], postgateEmbeddingRules: maybeEditedPostgate.embeddingRules ?? [],
}) })
Toast.show(_(msg`Settings saved`)) Toast.show(_(msg`Settings saved`))
} catch (e: any) { } catch (e: any) {
@@ -98,17 +106,18 @@ function Inner({preferences}: {preferences: UsePreferencesQueryResponse}) {
}) })
setError(_(msg`Failed to save settings. Please try again.`)) setError(_(msg`Failed to save settings. Please try again.`))
} }
}, [_, postgate, allowUISettings, setPostInteractionSettings]) }, [_, maybeEditedPostgate, maybeEditedAllowUI, setPostInteractionSettings])
return ( return (
<> <>
<PostInteractionSettingsForm <PostInteractionSettingsForm
canSave={wasEdited}
isSaving={isPending} isSaving={isPending}
onSave={onSave} onSave={onSave}
postgate={postgate} postgate={maybeEditedPostgate}
onChangePostgate={setPostgate} onChangePostgate={setEditedPostgate}
threadgateAllowUISettings={allowUISettings} threadgateAllowUISettings={maybeEditedAllowUI}
onChangeThreadgateAllowUISettings={setAllowUISettings} onChangeThreadgateAllowUISettings={setAllowUI}
/> />
{error && <Admonition type="error">{error}</Admonition>} {error && <Admonition type="error">{error}</Admonition>}
+3 -10
View File
@@ -83,10 +83,7 @@ import {
useLanguagePrefs, useLanguagePrefs,
useLanguagePrefsApi, useLanguagePrefsApi,
} from '#/state/preferences/languages' } from '#/state/preferences/languages'
import { import {usePreferencesQuery} from '#/state/queries/preferences'
preferencesQueryKey,
UsePreferencesQueryResponse,
} from '#/state/queries/preferences'
import {useProfileQuery} from '#/state/queries/profile' import {useProfileQuery} from '#/state/queries/profile'
import {Gif} from '#/state/queries/tenor' import {Gif} from '#/state/queries/tenor'
import {useAgent, useSession} from '#/state/session' import {useAgent, useSession} from '#/state/session'
@@ -173,11 +170,7 @@ export const ComposePost = ({
const discardPromptControl = Prompt.usePromptControl() const discardPromptControl = Prompt.usePromptControl()
const {closeAllDialogs} = useDialogStateControlContext() const {closeAllDialogs} = useDialogStateControlContext()
const {closeAllModals} = useModalControls() const {closeAllModals} = useModalControls()
const initInteractionSettings = useMemo(() => { const {data: preferences} = usePreferencesQuery()
const prefs =
queryClient.getQueryData<UsePreferencesQueryResponse>(preferencesQueryKey)
return prefs?.postInteractionSettings
}, [queryClient])
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true}) const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
const [isPublishing, setIsPublishing] = useState(false) const [isPublishing, setIsPublishing] = useState(false)
@@ -191,7 +184,7 @@ export const ComposePost = ({
initQuoteUri: initQuote?.uri, initQuoteUri: initQuote?.uri,
initText, initText,
initMention, initMention,
initInteractionSettings, initInteractionSettings: preferences?.postInteractionSettings,
}, },
createComposerState, createComposerState,
) )