From e16f87cc66323e2c4ba6e518a0412ddc88d2460b Mon Sep 17 00:00:00 2001 From: Soxasora Date: Thu, 14 Nov 2024 21:10:25 +0100 Subject: [PATCH 1/3] fix uploaded videos don't load on safari --- components/text.module.css | 1 - 1 file changed, 1 deletion(-) diff --git a/components/text.module.css b/components/text.module.css index ff99b8a90e..9e64c5a933 100644 --- a/components/text.module.css +++ b/components/text.module.css @@ -184,7 +184,6 @@ .p:has(> .mediaContainer) .mediaContainer { display: flex; - width: min-content; max-width: 100%; } From cf18aaa2a976414318ced37149ea485958014c24 Mon Sep 17 00:00:00 2001 From: Soxasora Date: Sat, 16 Nov 2024 11:52:59 +0100 Subject: [PATCH 2/3] fix safari loading video as image, min-content restored --- components/media-or-link.js | 36 ++++++++++++++++++++++++++---------- components/text.module.css | 5 +++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/components/media-or-link.js b/components/media-or-link.js index fa36842fbc..e60573cc12 100644 --- a/components/media-or-link.js +++ b/components/media-or-link.js @@ -23,9 +23,16 @@ const Media = memo(function Media ({ src, bestResSrc, srcSet, sizes, width, height, onClick, onError, style, className, video }) { + const [loaded, setLoaded] = useState(false) + + const handleLoadedMedia = () => { + setLoaded(true) + } + return (
{video @@ -37,6 +44,7 @@ const Media = memo(function Media ({ width={width} height={height} onError={onError} + onLoadedMetadata={handleLoadedMedia} /> : }
) @@ -101,21 +110,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 9e64c5a933..faa1f1e3ae 100644 --- a/components/text.module.css +++ b/components/text.module.css @@ -187,6 +187,11 @@ max-width: 100%; } +.p:has(> .mediaContainer) .mediaContainer.loaded +{ + width: min-content; +} + .p:has(> .mediaContainer) .mediaContainer img, .p:has(> .mediaContainer) .mediaContainer video { From e4a7e7028643ddab5725da39b7f1e67f9774421e Mon Sep 17 00:00:00 2001 From: k00b Date: Sun, 17 Nov 2024 13:36:51 -0600 Subject: [PATCH 3/3] refinements for ssr and skip load check for images --- components/media-or-link.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/components/media-or-link.js b/components/media-or-link.js index e60573cc12..5b42efe826 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,20 +23,31 @@ const Media = memo(function Media ({ src, bestResSrc, srcSet, sizes, width, height, onClick, onError, style, className, video }) { - const [loaded, setLoaded] = useState(false) + 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 ?