From bd462b6db3e1cbfe82da3bd114a07f174b9be58e Mon Sep 17 00:00:00 2001 From: Eli Mallon Date: Tue, 2 Jun 2026 11:45:50 -0700 Subject: [PATCH] app: bound mobile VOD video to its real aspect ratio + clear the notch Mobile VOD previously fell back to a full-window {flex:1} box whenever the contentWidth-derived height measured 0 (common on Android's first layout). Anchor the VOD box to an aspect-ratio box instead, sized from the real video dimensions via useSegmentDimensions (so portrait and other shapes render true, not forced 16:9), falling back to 16:9 until the track metadata loads. Also inset the VOD scroll content by the top safe-area so the video clears the notch instead of sitting flush against the top. Co-Authored-By: Claude Opus 4.8 --- js/app/components/mobile/player.tsx | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/js/app/components/mobile/player.tsx b/js/app/components/mobile/player.tsx index 1c141288..264b17bc 100644 --- a/js/app/components/mobile/player.tsx +++ b/js/app/components/mobile/player.tsx @@ -354,6 +354,15 @@ export function PlayerInner( // Calculate aspect ratio and determine if we're in desktop mode const aspectRatio = width > 0 && height > 0 ? width / height : 16 / 9; + // The VOD box is sized to the real video aspect ratio (so portrait and other + // shapes aren't forced into 16:9), falling back to 16:9 until the track + // metadata loads. + const segDims = useSegmentDimensions(); + const vodAspectRatio = + segDims.width > 0 && segDims.height > 0 + ? segDims.width / segDims.height + : 16 / 9; + // on mobile we want to hide the sidebar when going fullscreen useEffect(() => { if (Platform.OS !== "web" && width > height) { @@ -386,12 +395,6 @@ export function PlayerInner( const isPlayerRatioGreater = aspectRatio >= 16 / 9; - const { height: windowHeight } = useWindowDimensions(); - const vodMobileHeight = - props.mode === "vod" - ? Math.min(contentWidth / aspectRatio, windowHeight * 0.7) - : undefined; - // animated style for offline height transition const animatedHeightStyle = useAnimatedStyle(() => { return { @@ -415,7 +418,7 @@ export function PlayerInner( minHeight: "100%", // Ensures minimum height } : props.mode === "vod" - ? { flexGrow: 1 } + ? { flexGrow: 1, paddingTop: safeAreaInsets.top } : { flex: 1, } @@ -430,10 +433,15 @@ export function PlayerInner( ? { width: calculatedWidth, } - : props.mode === "vod" && vodMobileHeight + : props.mode === "vod" ? { + // Bound the video to its real aspect ratio so it occupies a + // fixed height with the metadata/comments below — never the + // whole window. (A pixel height derived from contentWidth + // collapsed to full-window on Android when contentWidth + // measured 0.) width: "100%" as any, - height: vodMobileHeight, + aspectRatio: vodAspectRatio, } : { flex: 1, -- 2.51.2