diff --git a/components/media-or-link.js b/components/media-or-link.js index fa36842f..5b42efe8 100644 --- a/components/media-or-link.js +++ b/components/media-or-link.js @@ -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 (
{video ?
) @@ -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 - 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 diff --git a/components/text.module.css b/components/text.module.css index ff99b8a9..faa1f1e3 100644 --- a/components/text.module.css +++ b/components/text.module.css @@ -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 {