fix uploaded videos don't load on safari (#1593)
* fix uploaded videos don't load on safari * fix safari loading video as image, min-content restored * refinements for ssr and skip load check for images --------- Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com> Co-authored-by: k00b <k00b@stacker.news>
This commit is contained in:
parent
83e72e21cc
commit
c08088bdbe
|
@ -1,5 +1,5 @@
|
|||
import styles from './text.module.css'
|
||||
import { useState, useEffect, useMemo, useCallback, memo } from 'react'
|
||||
import { useState, useEffect, useMemo, useCallback, memo, useRef } from 'react'
|
||||
import { decodeProxyUrl, IMGPROXY_URL_REGEXP, MEDIA_DOMAIN_REGEXP } from '@/lib/url'
|
||||
import { useMe } from './me'
|
||||
import { UNKNOWN_LINK_REL } from '@/lib/constants'
|
||||
|
@ -23,13 +23,31 @@ const Media = memo(function Media ({
|
|||
src, bestResSrc, srcSet, sizes, width,
|
||||
height, onClick, onError, style, className, video
|
||||
}) {
|
||||
const [loaded, setLoaded] = useState(!video)
|
||||
const ref = useRef(null)
|
||||
|
||||
const handleLoadedMedia = () => {
|
||||
setLoaded(true)
|
||||
}
|
||||
|
||||
// events are not fired on elements during hydration
|
||||
// https://github.com/facebook/react/issues/15446
|
||||
useEffect(() => {
|
||||
if (ref.current) {
|
||||
ref.current.src = src
|
||||
}
|
||||
}, [ref.current, src])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(className, styles.mediaContainer)}
|
||||
// will set min-content ONLY after the media is loaded
|
||||
// due to safari video bug
|
||||
className={classNames(className, styles.mediaContainer, { [styles.loaded]: loaded })}
|
||||
style={style}
|
||||
>
|
||||
{video
|
||||
? <video
|
||||
ref={ref}
|
||||
src={src}
|
||||
preload={bestResSrc !== src ? 'metadata' : undefined}
|
||||
controls
|
||||
|
@ -37,8 +55,10 @@ const Media = memo(function Media ({
|
|||
width={width}
|
||||
height={height}
|
||||
onError={onError}
|
||||
onLoadedMetadata={handleLoadedMedia}
|
||||
/>
|
||||
: <img
|
||||
ref={ref}
|
||||
src={src}
|
||||
srcSet={srcSet}
|
||||
sizes={sizes}
|
||||
|
@ -46,6 +66,7 @@ const Media = memo(function Media ({
|
|||
height={height}
|
||||
onClick={onClick}
|
||||
onError={onError}
|
||||
onLoad={handleLoadedMedia}
|
||||
/>}
|
||||
</div>
|
||||
)
|
||||
|
@ -101,21 +122,28 @@ export const useMediaHelper = ({ src, srcSet: srcSetIntital, topLevel, tab }) =>
|
|||
useEffect(() => {
|
||||
// don't load the video at all if user doesn't want these
|
||||
if (!showMedia || isVideo || isImage) return
|
||||
// make sure it's not a false negative by trying to load URL as <img>
|
||||
const img = new window.Image()
|
||||
img.onload = () => setIsImage(true)
|
||||
img.src = src
|
||||
|
||||
// check if it's a video by trying to load it
|
||||
const video = document.createElement('video')
|
||||
video.onloadeddata = () => setIsVideo(true)
|
||||
video.onloadedmetadata = () => {
|
||||
setIsVideo(true)
|
||||
setIsImage(false)
|
||||
}
|
||||
video.onerror = () => {
|
||||
// hack
|
||||
// if it's not a video it will throw an error, so we can assume it's an image
|
||||
const img = new window.Image()
|
||||
img.onload = () => setIsImage(true)
|
||||
img.src = src
|
||||
}
|
||||
video.src = src
|
||||
|
||||
return () => {
|
||||
img.onload = null
|
||||
img.src = ''
|
||||
video.onloadeddata = null
|
||||
video.onloadedmetadata = null
|
||||
video.onerror = null
|
||||
video.src = ''
|
||||
}
|
||||
}, [src, setIsImage, setIsVideo, showMedia, isVideo])
|
||||
}, [src, setIsImage, setIsVideo, showMedia, isImage])
|
||||
|
||||
const srcSet = useMemo(() => {
|
||||
if (Object.keys(srcSetObj).length === 0) return undefined
|
||||
|
|
|
@ -184,10 +184,14 @@
|
|||
.p:has(> .mediaContainer) .mediaContainer
|
||||
{
|
||||
display: flex;
|
||||
width: min-content;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer) .mediaContainer.loaded
|
||||
{
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer) .mediaContainer img,
|
||||
.p:has(> .mediaContainer) .mediaContainer video
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue