From 1caac024ab504c2fc82a3efbf1182493007ee2a5 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 14 Nov 2025 20:29:49 +0200 Subject: [PATCH] Fix video letterboxing issue (#9339) * give video a black background on web * Video crop on web tweaks (#9371) * Remove video embed crop option to reduce confusion * Improve default thumb and border on web --------- Co-authored-by: Eric Bailey --- .../VideoEmbedInner/VideoEmbedInnerWeb.tsx | 2 - .../Post/Embed/VideoEmbed/index.tsx | 38 ++++----------- .../Post/Embed/VideoEmbed/index.web.tsx | 48 ++++++------------- src/components/Post/Embed/index.tsx | 2 +- src/view/com/util/images/AutoSizedImage.tsx | 12 ++--- 5 files changed, 30 insertions(+), 72 deletions(-) diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx index 52449698c2..add2a7afb4 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx @@ -7,7 +7,6 @@ import type * as HlsTypes from 'hls.js' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' import {atoms as a} from '#/alf' -import {MediaInsetBorder} from '#/components/MediaInsetBorder' import * as BandwidthEstimate from './bandwidth-estimate' import {Controls} from './web-controls/VideoControls' @@ -102,7 +101,6 @@ export function VideoEmbedInnerWeb({ hasSubtitleTrack={hasSubtitleTrack} /> - ) } diff --git a/src/components/Post/Embed/VideoEmbed/index.tsx b/src/components/Post/Embed/VideoEmbed/index.tsx index 2212be83d3..9de292b4ad 100644 --- a/src/components/Post/Embed/VideoEmbed/index.tsx +++ b/src/components/Post/Embed/VideoEmbed/index.tsx @@ -7,7 +7,7 @@ import {useLingui} from '@lingui/react' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {ConstrainedImage} from '#/view/com/util/images/AutoSizedImage' -import {atoms as a, useTheme} from '#/alf' +import {atoms as a} from '#/alf' import {Button} from '#/components/Button' import {useThrottledValue} from '#/components/hooks/useThrottledValue' import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' @@ -16,11 +16,9 @@ import * as VideoFallback from './VideoEmbedInner/VideoFallback' interface Props { embed: AppBskyEmbedVideo.View - crop?: 'none' | 'square' | 'constrained' } -export function VideoEmbed({embed, crop}: Props) { - const t = useTheme() +export function VideoEmbed({embed}: Props) { const [key, setKey] = useState(0) const renderError = useCallback( @@ -40,13 +38,10 @@ export function VideoEmbed({embed, crop}: Props) { } let constrained: number | undefined - let max: number | undefined if (aspectRatio !== undefined) { const ratio = 1 / 2 // max of 1:2 ratio in feeds constrained = Math.max(aspectRatio, ratio) - max = Math.max(aspectRatio, 0.25) // max of 1:4 in thread } - const cropDisabled = crop === 'none' const contents = ( @@ -56,28 +51,13 @@ export function VideoEmbed({embed, crop}: Props) { return ( - {cropDisabled ? ( - - {contents} - - ) : ( - - {contents} - - )} + + {contents} + ) } diff --git a/src/components/Post/Embed/VideoEmbed/index.web.tsx b/src/components/Post/Embed/VideoEmbed/index.web.tsx index 8965e8b90e..3de5a99687 100644 --- a/src/components/Post/Embed/VideoEmbed/index.web.tsx +++ b/src/components/Post/Embed/VideoEmbed/index.web.tsx @@ -17,6 +17,7 @@ import {ConstrainedImage} from '#/view/com/util/images/AutoSizedImage' import {atoms as a, useTheme} from '#/alf' import {useIsWithinMessage} from '#/components/dms/MessageContext' import {useFullscreen} from '#/components/hooks/useFullscreen' +import {MediaInsetBorder} from '#/components/MediaInsetBorder' import { HLSUnsupportedError, VideoEmbedInnerWeb, @@ -25,13 +26,7 @@ import { import {useActiveVideoWeb} from './ActiveVideoWebContext' import * as VideoFallback from './VideoEmbedInner/VideoFallback' -export function VideoEmbed({ - embed, - crop, -}: { - embed: AppBskyEmbedVideo.View - crop?: 'none' | 'square' | 'constrained' -}) { +export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { const t = useTheme() const ref = useRef(null) const {active, setActive, sendPosition, currentActiveView} = @@ -76,13 +71,10 @@ export function VideoEmbed({ } let constrained: number | undefined - let max: number | undefined if (aspectRatio !== undefined) { const ratio = 1 / 2 // max of 1:2 ratio in feeds constrained = Math.max(aspectRatio, ratio) - max = Math.max(aspectRatio, 0.25) // max of 1:4 in thread } - const cropDisabled = crop === 'none' const contents = (
evt.stopPropagation()}> @@ -114,28 +109,15 @@ export function VideoEmbed({ - {cropDisabled ? ( - - {contents} - - ) : ( - - {contents} - - )} + + {contents} + + ) diff --git a/src/components/Post/Embed/index.tsx b/src/components/Post/Embed/index.tsx index 1462ef542f..6382412b56 100644 --- a/src/components/Post/Embed/index.tsx +++ b/src/components/Post/Embed/index.tsx @@ -112,7 +112,7 @@ function MediaEmbed({ - + ) } diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx index e248ea5414..92210e55e7 100644 --- a/src/view/com/util/images/AutoSizedImage.tsx +++ b/src/view/com/util/images/AutoSizedImage.tsx @@ -13,7 +13,7 @@ import {useLingui} from '@lingui/react' import {type Dimensions} from '#/lib/media/types' import {isNative} from '#/platform/detection' import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' -import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {atoms as a, useTheme} from '#/alf' import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/components/icons/ArrowsDiagonal' import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {Text} from '#/components/Typography' @@ -30,18 +30,16 @@ export function ConstrainedImage({ children: React.ReactNode }) { const t = useTheme() - const {gtMobile} = useBreakpoints() /** * Computed as a % value to apply as `paddingTop`, this basically controls * the height of the image. */ const outerAspectRatio = React.useMemo(() => { - const ratio = - isNative || !gtMobile - ? Math.min(1 / aspectRatio, minMobileAspectRatio ?? 16 / 9) // 9:16 bounding box - : Math.min(1 / aspectRatio, 1) // 1:1 bounding box + const ratio = isNative + ? Math.min(1 / aspectRatio, minMobileAspectRatio ?? 16 / 9) // 9:16 bounding box + : Math.min(1 / aspectRatio, 1) // 1:1 bounding box return `${ratio * 100}%` - }, [aspectRatio, gtMobile, minMobileAspectRatio]) + }, [aspectRatio, minMobileAspectRatio]) return (