fix(web): size uploaded videos from their own frame

Uploaded videos carry no dimensions, so a vertical clip sat letterboxed in
a 16:9 frame. The player now takes the frame size from the file's metadata
when the block has none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
This commit is contained in:
Claude 2026-10-03 14:26:11 +00:00
parent d67a6275a4
commit 17d285f87e
No known key found for this signature in database
2 changed files with 24 additions and 1 deletions

View File

@ -66,6 +66,21 @@ describe("MediaPlayer", () => {
expect(video.hasAttribute("controls")).toBe(true);
});
it("sizes the frame from the file when the block has no dimensions", async () => {
await act(async () =>
root.render(<MediaPlayer artifactId="art-4" kind="video" name="up.mp4" />),
);
const frame = container.querySelector<HTMLDivElement>('[data-testid="media-video"]')!;
expect(frame.style.width).toBe("420px");
const video = container.querySelector("video")!;
Object.defineProperty(video, "videoWidth", { value: 1080 });
Object.defineProperty(video, "videoHeight", { value: 1920 });
await act(async () => {
video.dispatchEvent(new Event("loadedmetadata"));
});
expect(frame.style.width).toBe("270px");
});
it("falls back to a download link when the browser cannot play the file", async () => {
await act(async () =>
root.render(<MediaPlayer artifactId="art-3" kind="audio" name="memo.ogg" />),

View File

@ -28,6 +28,7 @@ export function MediaPlayer({
const container = useRef<HTMLDivElement>(null);
const near = useNearViewport(container);
const [failed, setFailed] = useState(false);
const [frame, setFrame] = useState<{ width: number; height: number } | null>(null);
const src = near ? artifactUrl(artifactId) : undefined;
if (failed) return <MediaFallback artifactId={artifactId} name={name} />;
@ -48,7 +49,8 @@ export function MediaPlayer({
);
}
const box = videoBox(width, height);
// Uploads carry no dimensions; size the frame from the file once its metadata loads.
const box = videoBox(width ?? frame?.width, height ?? frame?.height);
return (
<div
ref={container}
@ -66,6 +68,12 @@ export function MediaPlayer({
aria-label={name}
className="block size-full object-contain"
onError={() => setFailed(true)}
onLoadedMetadata={(event) => {
const { videoWidth, videoHeight } = event.currentTarget;
if (videoWidth > 0 && videoHeight > 0) {
setFrame({ width: videoWidth, height: videoHeight });
}
}}
/>
</div>
);