diff options
author | Eric Bailey <git@esb.lol> | 2024-10-05 05:58:04 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-05 19:58:04 +0900 |
commit | 76d63f9967a9a59193652487d2a10f41eac22268 (patch) | |
tree | e70fcda6005d4501f87309d70fa574d24f51c96c /src/view/com/composer/photos/ImageAltTextDialog.tsx | |
parent | 6dfd57e6218eb32fcf700f1fbbd0339705940679 (diff) | |
download | voidsky-76d63f9967a9a59193652487d2a10f41eac22268.tar.zst |
Add alt text limit to image dialog (#5611)
* Add alt text limit to image dialog * GIF alt text too * Fix * tweaks, save alt on dialog dismiss * simplify close behavior * use state in gif alt * state --------- Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/view/com/composer/photos/ImageAltTextDialog.tsx')
-rw-r--r-- | src/view/com/composer/photos/ImageAltTextDialog.tsx | 127 |
1 files changed, 88 insertions, 39 deletions
diff --git a/src/view/com/composer/photos/ImageAltTextDialog.tsx b/src/view/com/composer/photos/ImageAltTextDialog.tsx index 16ce4351a..e9e8d4222 100644 --- a/src/view/com/composer/photos/ImageAltTextDialog.tsx +++ b/src/view/com/composer/photos/ImageAltTextDialog.tsx @@ -5,12 +5,16 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {MAX_ALT_TEXT} from '#/lib/constants' +import {enforceLen} from '#/lib/strings/helpers' import {isAndroid, isWeb} from '#/platform/detection' import {ComposerImage} from '#/state/gallery' +import {AltTextCounterWrapper} from '#/view/com/composer/AltTextCounterWrapper' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' +import {DialogControlProps} from '#/components/Dialog' import * as TextField from '#/components/forms/TextField' +import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' import {PortalComponent} from '#/components/Portal' import {Text} from '#/components/Typography' @@ -21,32 +25,50 @@ type Props = { Portal: PortalComponent } -export const ImageAltTextDialog = (props: Props): React.ReactNode => { +export const ImageAltTextDialog = ({ + control, + image, + onChange, + Portal, +}: Props): React.ReactNode => { + const [altText, setAltText] = React.useState(image.alt) + return ( - <Dialog.Outer control={props.control} Portal={props.Portal}> + <Dialog.Outer + control={control} + onClose={() => { + onChange({ + ...image, + alt: enforceLen(altText, MAX_ALT_TEXT, true), + }) + }} + Portal={Portal}> <Dialog.Handle /> - <ImageAltTextInner {...props} /> + <ImageAltTextInner + control={control} + image={image} + altText={altText} + setAltText={setAltText} + /> </Dialog.Outer> ) } const ImageAltTextInner = ({ + altText, + setAltText, control, image, - onChange, -}: Props): React.ReactNode => { - const {_} = useLingui() +}: { + altText: string + setAltText: (text: string) => void + control: DialogControlProps + image: Props['image'] +}): React.ReactNode => { + const {_, i18n} = useLingui() const t = useTheme() - const windim = useWindowDimensions() - const [altText, setAltText] = React.useState(image.alt) - - const onPressSubmit = React.useCallback(() => { - control.close() - onChange({...image, alt: altText.trim()}) - }, [control, image, altText, onChange]) - const imageStyle = React.useMemo<ImageStyle>(() => { const maxWidth = isWeb ? 450 : windim.width const source = image.transformed ?? image.source @@ -90,32 +112,59 @@ const ImageAltTextInner = ({ </View> <View style={[a.mt_md, a.gap_md]}> - <View> - <TextField.LabelText> - <Trans>Descriptive alt text</Trans> - </TextField.LabelText> - <TextField.Root> - <Dialog.Input - label={_(msg`Alt text`)} - onChangeText={text => setAltText(text)} - value={altText} - multiline - numberOfLines={3} - autoFocus - /> - </TextField.Root> + <View style={[a.gap_sm]}> + <View style={[a.relative, {width: '100%'}]}> + <TextField.LabelText> + <Trans>Descriptive alt text</Trans> + </TextField.LabelText> + <TextField.Root> + <Dialog.Input + label={_(msg`Alt text`)} + onChangeText={text => { + setAltText(text) + }} + defaultValue={altText} + multiline + numberOfLines={3} + autoFocus + /> + </TextField.Root> + </View> + + {altText.length > MAX_ALT_TEXT && ( + <View style={[a.pb_sm, a.flex_row, a.gap_xs]}> + <CircleInfo fill={t.palette.negative_500} /> + <Text + style={[ + a.italic, + a.leading_snug, + t.atoms.text_contrast_medium, + ]}> + <Trans> + Alt text will be truncated. Limit: {i18n.number(MAX_ALT_TEXT)}{' '} + characters. + </Trans> + </Text> + </View> + )} </View> - <Button - label={_(msg`Save`)} - disabled={altText.length > MAX_ALT_TEXT || altText === image.alt} - size="large" - color="primary" - variant="solid" - onPress={onPressSubmit}> - <ButtonText> - <Trans>Save</Trans> - </ButtonText> - </Button> + + <AltTextCounterWrapper altText={altText}> + <Button + label={_(msg`Save`)} + disabled={altText === image.alt} + size="large" + color="primary" + variant="solid" + onPress={() => { + control.close() + }} + style={[a.flex_grow]}> + <ButtonText> + <Trans>Save</Trans> + </ButtonText> + </Button> + </AltTextCounterWrapper> </View> {/* Maybe fix this later -h */} {isAndroid ? <View style={{height: 300}} /> : null} |