Add gif support to web (#6433)

* add gif support to web

* rm set dimensions

* rm effect from preview

* rm log

* rm use of {cause: error}

* fix lint
This commit is contained in:
Samuel Newman
2024-11-22 17:58:29 +00:00
committed by GitHub
parent 76ca72cf72
commit 3781074921
9 changed files with 183 additions and 114 deletions
@@ -1,4 +1,3 @@
import {useEffect, useRef} from 'react'
import {View} from 'react-native'
import {ImagePickerAsset} from 'expo-image-picker'
import {msg} from '@lingui/macro'
@@ -12,58 +11,22 @@ import * as Toast from '#/view/com/util/Toast'
import {atoms as a} from '#/alf'
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
const MAX_DURATION = 60
export function VideoPreview({
asset,
video,
setDimensions,
clear,
}: {
asset: ImagePickerAsset
video: CompressedVideo
setDimensions: (width: number, height: number) => void
clear: () => void
}) {
const ref = useRef<HTMLVideoElement>(null)
const {_} = useLingui()
// TODO: figure out how to pause a GIF for reduced motion
// it's not possible using an img tag -sfn
const autoplayDisabled = useAutoplayDisabled()
useEffect(() => {
if (!ref.current) return
const abortController = new AbortController()
const {signal} = abortController
ref.current.addEventListener(
'loadedmetadata',
function () {
setDimensions(this.videoWidth, this.videoHeight)
if (!isNaN(this.duration)) {
if (this.duration > MAX_DURATION) {
Toast.show(
_(msg`Videos must be less than 60 seconds long`),
'xmark',
)
clear()
}
}
},
{signal},
)
ref.current.addEventListener(
'error',
() => {
Toast.show(_(msg`Could not process your video`), 'xmark')
clear()
},
{signal},
)
return () => {
abortController.abort()
}
}, [setDimensions, _, clear])
let aspectRatio = asset.width / asset.height
if (isNaN(aspectRatio)) {
@@ -83,19 +46,34 @@ export function VideoPreview({
a.relative,
]}>
<ExternalEmbedRemoveBtn onRemove={clear} />
<video
ref={ref}
src={video.uri}
style={{width: '100%', height: '100%', objectFit: 'cover'}}
autoPlay={!autoplayDisabled}
loop
muted
playsInline
/>
{autoplayDisabled && (
<View style={[a.absolute, a.inset_0, a.justify_center, a.align_center]}>
<PlayButtonIcon />
</View>
{video.mimeType === 'image/gif' ? (
<img
src={video.uri}
style={{width: '100%', height: '100%', objectFit: 'cover'}}
alt="GIF"
/>
) : (
<>
<video
src={video.uri}
style={{width: '100%', height: '100%', objectFit: 'cover'}}
autoPlay={!autoplayDisabled}
loop
muted
playsInline
onError={err => {
console.error('Error loading video', err)
Toast.show(_(msg`Could not process your video`), 'xmark')
clear()
}}
/>
{autoplayDisabled && (
<View
style={[a.absolute, a.inset_0, a.justify_center, a.align_center]}>
<PlayButtonIcon />
</View>
)}
</>
)}
</View>
)