Alt text for gifs (#3876)
* add alt text dialog * multiline alt text input * add pressable alt text badge * rename `ALT: ` to `Alt text: ` to avoid including old bad ones * reuse alt text reminder * reuse alt text reminder in gallery * add alt text reminder in the dialog itself * autofocus text input * reorder components to fix tab order * fix close btn position
This commit is contained in:
parent
ae7626ce6e
commit
c33c3b7d1e
9 changed files with 344 additions and 47 deletions
|
@ -1,9 +1,10 @@
|
|||
import {AppBskyEmbedImages} from '@atproto/api'
|
||||
import React, {ComponentProps, FC} from 'react'
|
||||
import {StyleSheet, Text, Pressable, View} from 'react-native'
|
||||
import {Pressable, StyleSheet, Text, View} from 'react-native'
|
||||
import {Image} from 'expo-image'
|
||||
import {AppBskyEmbedImages} from '@atproto/api'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {isWeb} from 'platform/detection'
|
||||
|
||||
type EventFunction = (index: number) => void
|
||||
|
|
|
@ -20,9 +20,11 @@ import {Text} from '../text/Text'
|
|||
export const ExternalLinkEmbed = ({
|
||||
link,
|
||||
style,
|
||||
hideAlt,
|
||||
}: {
|
||||
link: AppBskyEmbedExternal.ViewExternal
|
||||
style?: StyleProp<ViewStyle>
|
||||
hideAlt?: boolean
|
||||
}) => {
|
||||
const pal = usePalette('default')
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
|
@ -37,7 +39,7 @@ export const ExternalLinkEmbed = ({
|
|||
}, [link.uri, externalEmbedPrefs])
|
||||
|
||||
if (embedPlayerParams?.source === 'tenor') {
|
||||
return <GifEmbed params={embedPlayerParams} link={link} />
|
||||
return <GifEmbed params={embedPlayerParams} link={link} hideAlt={hideAlt} />
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import React from 'react'
|
||||
import {Pressable, View} from 'react-native'
|
||||
import {Pressable, StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||
import {AppBskyEmbedExternal} from '@atproto/api'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {HITSLOP_10} from '#/lib/constants'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {EmbedPlayerParams} from 'lib/strings/embed-player'
|
||||
import {useAutoplayDisabled} from 'state/preferences'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {GifView} from '../../../../../modules/expo-bluesky-gif-view'
|
||||
import {GifViewStateChangeEvent} from '../../../../../modules/expo-bluesky-gif-view/src/GifView.types'
|
||||
|
||||
|
@ -82,9 +86,11 @@ function PlaybackControls({
|
|||
export function GifEmbed({
|
||||
params,
|
||||
link,
|
||||
hideAlt,
|
||||
}: {
|
||||
params: EmbedPlayerParams
|
||||
link: AppBskyEmbedExternal.ViewExternal
|
||||
hideAlt?: boolean
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const autoplayDisabled = useAutoplayDisabled()
|
||||
|
@ -111,7 +117,8 @@ export function GifEmbed({
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<View style={[a.rounded_sm, a.overflow_hidden, a.mt_sm]}>
|
||||
<View
|
||||
style={[a.rounded_sm, a.overflow_hidden, a.mt_sm, {maxWidth: '100%'}]}>
|
||||
<View
|
||||
style={[
|
||||
a.rounded_sm,
|
||||
|
@ -133,9 +140,69 @@ export function GifEmbed({
|
|||
onPlayerStateChange={onPlayerStateChange}
|
||||
ref={playerRef}
|
||||
accessibilityHint={_(msg`Animated GIF`)}
|
||||
accessibilityLabel={link.description.replace('ALT: ', '')}
|
||||
accessibilityLabel={link.description.replace('Alt text: ', '')}
|
||||
/>
|
||||
|
||||
{!hideAlt && link.description.startsWith('Alt text: ') && (
|
||||
<AltText text={link.description.replace('Alt text: ', '')} />
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
function AltText({text}: {text: string}) {
|
||||
const control = Prompt.usePromptControl()
|
||||
|
||||
const {_} = useLingui()
|
||||
return (
|
||||
<>
|
||||
<TouchableOpacity
|
||||
testID="altTextButton"
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Show alt text`)}
|
||||
accessibilityHint=""
|
||||
hitSlop={HITSLOP_10}
|
||||
onPress={control.open}
|
||||
style={styles.altContainer}>
|
||||
<Text style={styles.alt} accessible={false}>
|
||||
<Trans>ALT</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<Prompt.Outer control={control}>
|
||||
<Prompt.TitleText>
|
||||
<Trans>Alt Text</Trans>
|
||||
</Prompt.TitleText>
|
||||
<Prompt.DescriptionText>{text}</Prompt.DescriptionText>
|
||||
<Prompt.Actions>
|
||||
<Prompt.Action
|
||||
onPress={control.close}
|
||||
cta={_(msg`Close`)}
|
||||
color="secondary"
|
||||
/>
|
||||
</Prompt.Actions>
|
||||
</Prompt.Outer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
altContainer: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
||||
borderRadius: 6,
|
||||
paddingHorizontal: 6,
|
||||
paddingVertical: 3,
|
||||
position: 'absolute',
|
||||
// Related to margin/gap hack. This keeps the alt label in the same position
|
||||
// on all platforms
|
||||
left: isWeb ? 8 : 5,
|
||||
bottom: isWeb ? 8 : 5,
|
||||
zIndex: 2,
|
||||
},
|
||||
alt: {
|
||||
color: 'white',
|
||||
fontSize: 10,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue