[APP-2170] Render GIFs through ConstrainedImage (#10453)
Co-authored-by: vineyardbovines <spencer@thepope.dev>
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
import {useRef, useState} from 'react'
|
import {useRef, useState} from 'react'
|
||||||
import {type StyleProp, View, type ViewStyle} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {clamp} from '#/lib/numbers'
|
|
||||||
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
||||||
import {useAutoplayDisabled} from '#/state/preferences'
|
import {useAutoplayDisabled} from '#/state/preferences'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Fill} from '#/components/Fill'
|
import {Fill} from '#/components/Fill'
|
||||||
|
import {ConstrainedImage} from '#/components/images/AutoSizedImage'
|
||||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||||
import {GifView} from '../../../../../modules/expo-bluesky-gif-view'
|
import {GifView} from '../../../../../modules/expo-bluesky-gif-view'
|
||||||
import {type GifViewStateChangeEvent} from '../../../../../modules/expo-bluesky-gif-view/src/GifView.types'
|
import {type GifViewStateChangeEvent} from '../../../../../modules/expo-bluesky-gif-view/src/GifView.types'
|
||||||
@@ -19,14 +19,12 @@ export function GifEmbed({
|
|||||||
altText,
|
altText,
|
||||||
isPreferredAltText,
|
isPreferredAltText,
|
||||||
hideAlt,
|
hideAlt,
|
||||||
style = {width: '100%'},
|
|
||||||
}: {
|
}: {
|
||||||
params: EmbedPlayerParams
|
params: EmbedPlayerParams
|
||||||
thumb: string | undefined
|
thumb: string | undefined
|
||||||
altText: string
|
altText: string
|
||||||
isPreferredAltText: boolean
|
isPreferredAltText: boolean
|
||||||
hideAlt?: boolean
|
hideAlt?: boolean
|
||||||
style?: StyleProp<ViewStyle>
|
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -53,60 +51,64 @@ export function GifEmbed({
|
|||||||
let aspectRatio = 1
|
let aspectRatio = 1
|
||||||
if (params.dimensions) {
|
if (params.dimensions) {
|
||||||
const ratio = params.dimensions.width / params.dimensions.height
|
const ratio = params.dimensions.width / params.dimensions.height
|
||||||
aspectRatio = clamp(ratio, 0.75, 4)
|
if (!Number.isNaN(ratio)) {
|
||||||
|
aspectRatio = ratio
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
const constrained = Math.max(aspectRatio, 1 / 2)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<ConstrainedImage aspectRatio={constrained} minMobileAspectRatio={14 / 9}>
|
||||||
style={[
|
|
||||||
a.rounded_md,
|
|
||||||
a.overflow_hidden,
|
|
||||||
{backgroundColor: t.palette.black},
|
|
||||||
{aspectRatio},
|
|
||||||
style,
|
|
||||||
]}>
|
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.flex_1,
|
||||||
/*
|
a.rounded_md,
|
||||||
* Aspect ratio was being clipped weirdly on web -esb
|
a.overflow_hidden,
|
||||||
*/
|
{backgroundColor: t.palette.black},
|
||||||
{
|
|
||||||
top: -2,
|
|
||||||
bottom: -2,
|
|
||||||
left: -2,
|
|
||||||
right: -2,
|
|
||||||
},
|
|
||||||
]}>
|
]}>
|
||||||
<MediaInsetBorder />
|
<View
|
||||||
<GifPresentationControls
|
style={[
|
||||||
onPress={onPress}
|
a.absolute,
|
||||||
isPlaying={playerState.isPlaying}
|
/*
|
||||||
isLoading={!playerState.isLoaded}
|
* Aspect ratio was being clipped weirdly on web -esb
|
||||||
altText={!hideAlt && isPreferredAltText ? altText : undefined}
|
*/
|
||||||
/>
|
{
|
||||||
<GifView
|
top: -2,
|
||||||
source={params.playerUri}
|
bottom: -2,
|
||||||
sources={params.playerSources}
|
left: -2,
|
||||||
placeholderSource={thumb}
|
right: -2,
|
||||||
style={[a.flex_1]}
|
},
|
||||||
autoplay={!autoplayDisabled}
|
]}>
|
||||||
onPlayerStateChange={onPlayerStateChange}
|
<MediaInsetBorder />
|
||||||
ref={playerRef}
|
<GifPresentationControls
|
||||||
accessibilityHint={_(msg`Animated GIF`)}
|
onPress={onPress}
|
||||||
accessibilityLabel={altText}
|
isPlaying={playerState.isPlaying}
|
||||||
/>
|
isLoading={!playerState.isLoaded}
|
||||||
{!playerState.isPlaying && (
|
altText={!hideAlt && isPreferredAltText ? altText : undefined}
|
||||||
<Fill
|
|
||||||
style={[
|
|
||||||
t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg,
|
|
||||||
{
|
|
||||||
opacity: 0.3,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
)}
|
<GifView
|
||||||
|
source={params.playerUri}
|
||||||
|
sources={params.playerSources}
|
||||||
|
placeholderSource={thumb}
|
||||||
|
style={[a.flex_1]}
|
||||||
|
autoplay={!autoplayDisabled}
|
||||||
|
onPlayerStateChange={onPlayerStateChange}
|
||||||
|
ref={playerRef}
|
||||||
|
accessibilityHint={_(msg`Animated GIF`)}
|
||||||
|
accessibilityLabel={altText}
|
||||||
|
/>
|
||||||
|
{!playerState.isPlaying && (
|
||||||
|
<Fill
|
||||||
|
style={[
|
||||||
|
t.name === 'light' ? t.atoms.bg_contrast_975 : t.atoms.bg,
|
||||||
|
{
|
||||||
|
opacity: 0.3,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</ConstrainedImage>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,16 +216,13 @@ function AltTextInner({
|
|||||||
style={[a.text_2xl, a.font_semi_bold, a.leading_tight, a.pb_sm]}>
|
style={[a.text_2xl, a.font_semi_bold, a.leading_tight, a.pb_sm]}>
|
||||||
<Trans>Add alt text</Trans>
|
<Trans>Add alt text</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
<View style={[a.align_center]}>
|
<GifEmbed
|
||||||
<GifEmbed
|
thumb={thumb}
|
||||||
thumb={thumb}
|
altText={altText}
|
||||||
altText={altText}
|
isPreferredAltText={true}
|
||||||
isPreferredAltText={true}
|
params={params}
|
||||||
params={params}
|
hideAlt
|
||||||
hideAlt
|
/>
|
||||||
style={[{height: 225}]}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
|
|||||||
Reference in New Issue
Block a user