[GIFs] Restore default alt text (#3893)

* restore default alt text

* factor out gif alt logic + enable require alt text setting

* rm console.log

* don't prefill input + esc handling

* typo

* Nits

* shorten user alt prefix

* Remove unnecessary condition, rename for clarity

* Add comment

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
zio/stable
Samuel Newman 2024-05-07 20:05:40 +01:00 committed by GitHub
parent 77e6c75a2c
commit 7d72dfb1cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 20 deletions

View File

@ -0,0 +1,36 @@
// Kind of a hack. We needed some way to distinguish these.
const USER_ALT_PREFIX = 'Alt: '
const DEFAULT_ALT_PREFIX = 'ALT: '
export function createGIFDescription(
tenorDescription: string,
preferredAlt: string = '',
) {
preferredAlt = preferredAlt.trim()
if (preferredAlt !== '') {
return USER_ALT_PREFIX + preferredAlt
} else {
return DEFAULT_ALT_PREFIX + tenorDescription
}
}
export function parseAltFromGIFDescription(description: string): {
isPreferred: boolean
alt: string
} {
if (description.startsWith(USER_ALT_PREFIX)) {
return {
isPreferred: true,
alt: description.replace(USER_ALT_PREFIX, ''),
}
} else if (description.startsWith(DEFAULT_ALT_PREFIX)) {
return {
isPreferred: false,
alt: description.replace(DEFAULT_ALT_PREFIX, ''),
}
}
return {
isPreferred: false,
alt: description,
}
}

View File

@ -18,6 +18,10 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {
createGIFDescription,
parseAltFromGIFDescription,
} from '#/lib/gif-alt-text'
import {LikelyType} from '#/lib/link-meta/link-meta' import {LikelyType} from '#/lib/link-meta/link-meta'
import {logEvent} from '#/lib/statsig/statsig' import {logEvent} from '#/lib/statsig/statsig'
import {logger} from '#/logger' import {logger} from '#/logger'
@ -211,11 +215,25 @@ export const ComposePost = observer(function ComposePost({
[gallery, track], [gallery, track],
) )
const isAltTextRequiredAndMissing = useMemo(() => {
if (!requireAltTextEnabled) return false
if (gallery.needsAltText) return true
if (extGif) {
if (!extLink?.meta?.description) return true
const parsedAlt = parseAltFromGIFDescription(extLink.meta.description)
if (!parsedAlt.isPreferred) return true
}
return false
}, [gallery.needsAltText, extLink, extGif, requireAltTextEnabled])
const onPressPublish = async () => { const onPressPublish = async () => {
if (isProcessing || graphemeLength > MAX_GRAPHEME_LENGTH) { if (isProcessing || graphemeLength > MAX_GRAPHEME_LENGTH) {
return return
} }
if (requireAltTextEnabled && gallery.needsAltText) {
if (isAltTextRequiredAndMissing) {
return return
} }
@ -298,10 +316,8 @@ export const ComposePost = observer(function ComposePost({
} }
const canPost = useMemo( const canPost = useMemo(
() => () => graphemeLength <= MAX_GRAPHEME_LENGTH && !isAltTextRequiredAndMissing,
graphemeLength <= MAX_GRAPHEME_LENGTH && [graphemeLength, isAltTextRequiredAndMissing],
(!requireAltTextEnabled || !gallery.needsAltText),
[graphemeLength, requireAltTextEnabled, gallery.needsAltText],
) )
const selectTextInputPlaceholder = replyTo const selectTextInputPlaceholder = replyTo
? _(msg`Write your reply`) ? _(msg`Write your reply`)
@ -328,7 +344,7 @@ export const ComposePost = observer(function ComposePost({
image: gif.media_formats.preview.url, image: gif.media_formats.preview.url,
likelyType: LikelyType.HTML, likelyType: LikelyType.HTML,
title: gif.content_description, title: gif.content_description,
description: '', description: createGIFDescription(gif.content_description),
}, },
}) })
setExtGif(gif) setExtGif(gif)
@ -343,11 +359,11 @@ export const ComposePost = observer(function ComposePost({
? { ? {
...ext, ...ext,
meta: { meta: {
...ext?.meta, ...ext.meta,
description: description: createGIFDescription(
altText.trim().length === 0 ext.meta.title ?? '',
? '' altText,
: `Alt text: ${altText.trim()}`, ),
}, },
} }
: ext, : ext,
@ -433,7 +449,7 @@ export const ComposePost = observer(function ComposePost({
</> </>
)} )}
</View> </View>
{requireAltTextEnabled && gallery.needsAltText && ( {isAltTextRequiredAndMissing && (
<View style={[styles.reminderLine, pal.viewLight]}> <View style={[styles.reminderLine, pal.viewLight]}>
<View style={styles.errorIcon}> <View style={styles.errorIcon}>
<FontAwesomeIcon <FontAwesomeIcon

View File

@ -6,6 +6,7 @@ import {useLingui} from '@lingui/react'
import {ExternalEmbedDraft} from '#/lib/api' import {ExternalEmbedDraft} from '#/lib/api'
import {HITSLOP_10, MAX_ALT_TEXT} from '#/lib/constants' import {HITSLOP_10, MAX_ALT_TEXT} from '#/lib/constants'
import {parseAltFromGIFDescription} from '#/lib/gif-alt-text'
import { import {
EmbedPlayerParams, EmbedPlayerParams,
parseEmbedPlayerFromUrl, parseEmbedPlayerFromUrl,
@ -59,6 +60,7 @@ export function GifAltText({
if (!gif || !params) return null if (!gif || !params) return null
const parsedAlt = parseAltFromGIFDescription(link.description)
return ( return (
<> <>
<TouchableOpacity <TouchableOpacity
@ -80,7 +82,7 @@ export function GifAltText({
a.align_center, a.align_center,
{backgroundColor: 'rgba(0, 0, 0, 0.75)'}, {backgroundColor: 'rgba(0, 0, 0, 0.75)'},
]}> ]}>
{link.description ? ( {parsedAlt.isPreferred ? (
<Check size="xs" fill={t.palette.white} style={a.ml_xs} /> <Check size="xs" fill={t.palette.white} style={a.ml_xs} />
) : ( ) : (
<Plus size="sm" fill={t.palette.white} /> <Plus size="sm" fill={t.palette.white} />
@ -102,7 +104,7 @@ export function GifAltText({
onSubmit={onPressSubmit} onSubmit={onPressSubmit}
link={link} link={link}
params={params} params={params}
initalValue={link.description.replace('Alt text: ', '')} initialValue={parsedAlt.isPreferred ? parsedAlt.alt : ''}
key={link.uri} key={link.uri}
/> />
</Dialog.Outer> </Dialog.Outer>
@ -114,15 +116,16 @@ function AltTextInner({
onSubmit, onSubmit,
link, link,
params, params,
initalValue, initialValue: initalValue,
}: { }: {
onSubmit: (text: string) => void onSubmit: (text: string) => void
link: AppBskyEmbedExternal.ViewExternal link: AppBskyEmbedExternal.ViewExternal
params: EmbedPlayerParams params: EmbedPlayerParams
initalValue: string initialValue: string
}) { }) {
const {_} = useLingui() const {_} = useLingui()
const [altText, setAltText] = useState(initalValue) const [altText, setAltText] = useState(initalValue)
const control = Dialog.useDialogContext()
const onPressSubmit = useCallback(() => { const onPressSubmit = useCallback(() => {
onSubmit(altText) onSubmit(altText)
@ -147,6 +150,11 @@ function AltTextInner({
multiline multiline
numberOfLines={3} numberOfLines={3}
autoFocus autoFocus
onKeyPress={({nativeEvent}) => {
if (nativeEvent.key === 'Escape') {
control.close()
}
}}
/> />
</TextField.Root> </TextField.Root>
</View> </View>

View File

@ -6,6 +6,7 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {HITSLOP_10} from '#/lib/constants' import {HITSLOP_10} from '#/lib/constants'
import {parseAltFromGIFDescription} from '#/lib/gif-alt-text'
import {isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
import {EmbedPlayerParams} from 'lib/strings/embed-player' import {EmbedPlayerParams} from 'lib/strings/embed-player'
import {useAutoplayDisabled} from 'state/preferences' import {useAutoplayDisabled} from 'state/preferences'
@ -116,6 +117,11 @@ export function GifEmbed({
playerRef.current?.toggleAsync() playerRef.current?.toggleAsync()
}, []) }, [])
const parsedAlt = React.useMemo(
() => parseAltFromGIFDescription(link.description),
[link],
)
return ( return (
<View <View
style={[a.rounded_sm, a.overflow_hidden, a.mt_sm, {maxWidth: '100%'}]}> style={[a.rounded_sm, a.overflow_hidden, a.mt_sm, {maxWidth: '100%'}]}>
@ -140,12 +146,10 @@ export function GifEmbed({
onPlayerStateChange={onPlayerStateChange} onPlayerStateChange={onPlayerStateChange}
ref={playerRef} ref={playerRef}
accessibilityHint={_(msg`Animated GIF`)} accessibilityHint={_(msg`Animated GIF`)}
accessibilityLabel={link.description.replace('Alt text: ', '')} accessibilityLabel={parsedAlt.alt}
/> />
{!hideAlt && link.description.startsWith('Alt text: ') && ( {!hideAlt && parsedAlt.isPreferred && <AltText text={parsedAlt.alt} />}
<AltText text={link.description.replace('Alt text: ', '')} />
)}
</View> </View>
</View> </View>
) )