diff options
author | Eric Bailey <git@esb.lol> | 2024-02-29 19:30:30 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-29 19:30:30 -0600 |
commit | cecb6e4e69eaccedf56f503589a59044fd7c6d19 (patch) | |
tree | 90dd52ea6a797f4f251a13ccc675c7ef6cbe851f /src/components/dialogs/MutedWords.tsx | |
parent | 21bdddcfbe6ae85c15a4544fe5fd751b7e94d960 (diff) | |
download | voidsky-cecb6e4e69eaccedf56f503589a59044fd7c6d19.tar.zst |
Bump API SDK, add validation to MutedWords (#3055)
* Bump API SDK, add validation to MutedWords * Tweaks to error state * Comment * Early return
Diffstat (limited to 'src/components/dialogs/MutedWords.tsx')
-rw-r--r-- | src/components/dialogs/MutedWords.tsx | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/src/components/dialogs/MutedWords.tsx b/src/components/dialogs/MutedWords.tsx index 7c0d4fbca..453b13513 100644 --- a/src/components/dialogs/MutedWords.tsx +++ b/src/components/dialogs/MutedWords.tsx @@ -2,7 +2,7 @@ import React from 'react' import {View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {AppBskyActorDefs} from '@atproto/api' +import {AppBskyActorDefs, sanitizeMutedWordValue} from '@atproto/api' import { usePreferencesQuery, @@ -10,7 +10,14 @@ import { useRemoveMutedWordMutation, } from '#/state/queries/preferences' import {isNative} from '#/platform/detection' -import {atoms as a, useTheme, useBreakpoints, ViewStyleProp, web} from '#/alf' +import { + atoms as a, + useTheme, + useBreakpoints, + ViewStyleProp, + web, + native, +} from '#/alf' import {Text} from '#/components/Typography' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' @@ -48,24 +55,29 @@ function MutedWordsInner({}: {control: Dialog.DialogOuterProps['control']}) { const {isPending, mutateAsync: addMutedWord} = useUpsertMutedWordsMutation() const [field, setField] = React.useState('') const [options, setOptions] = React.useState(['content']) - const [_error, setError] = React.useState('') + const [error, setError] = React.useState('') const submit = React.useCallback(async () => { - const value = field.trim() + const sanitizedValue = sanitizeMutedWordValue(field) const targets = ['tag', options.includes('content') && 'content'].filter( Boolean, ) as AppBskyActorDefs.MutedWord['targets'] - if (!value || !targets.length) return + if (!sanitizedValue || !targets.length) { + setField('') + setError(_(msg`Please enter a valid word, tag, or phrase to mute`)) + return + } try { - await addMutedWord([{value, targets}]) + // send raw value and rely on SDK as sanitization source of truth + await addMutedWord([{value: field, targets}]) setField('') } catch (e: any) { logger.error(`Failed to save muted word`, {message: e.message}) setError(e.message) } - }, [field, options, addMutedWord, setField]) + }, [_, field, options, addMutedWord, setField]) return ( <Dialog.ScrollableInner label={_(msg`Manage your muted words and tags`)}> @@ -87,7 +99,12 @@ function MutedWordsInner({}: {control: Dialog.DialogOuterProps['control']}) { label={_(msg`Enter a word or tag`)} placeholder={_(msg`Enter a word or tag`)} value={field} - onChangeText={setField} + onChangeText={value => { + if (error) { + setError('') + } + setField(value) + }} onSubmitEditing={submit} /> @@ -99,7 +116,7 @@ function MutedWordsInner({}: {control: Dialog.DialogOuterProps['control']}) { <View style={[ a.pt_sm, - a.pb_md, + a.py_sm, a.flex_row, a.align_center, a.gap_sm, @@ -151,8 +168,33 @@ function MutedWordsInner({}: {control: Dialog.DialogOuterProps['control']}) { </View> </Toggle.Group> + {error && ( + <View + style={[ + a.mb_lg, + a.flex_row, + a.rounded_sm, + a.p_md, + a.mb_xs, + t.atoms.bg_contrast_25, + { + backgroundColor: t.palette.negative_400, + }, + ]}> + <Text + style={[ + a.italic, + {color: t.palette.white}, + native({marginTop: 2}), + ]}> + {error} + </Text> + </View> + )} + <Text style={[ + a.pt_xs, a.text_sm, a.italic, a.leading_snug, |