From e038cc93c6c805519634c1d628dbadc99b931d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Wed, 15 Jul 2026 12:02:36 -0400 Subject: [PATCH] fix(studio): mute composition hover previews (#2478) * fix(studio): mute composition hover previews * fix(studio): route hover muting through bridge --- .../sidebar/CompositionsTab.test.ts | 30 +++++++++++++++++-- .../components/sidebar/CompositionsTab.tsx | 4 ++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/studio/src/components/sidebar/CompositionsTab.test.ts b/packages/studio/src/components/sidebar/CompositionsTab.test.ts index 22de6c129..5e89ecc49 100644 --- a/packages/studio/src/components/sidebar/CompositionsTab.test.ts +++ b/packages/studio/src/components/sidebar/CompositionsTab.test.ts @@ -1,5 +1,9 @@ -import { describe, expect, it } from "vitest"; -import { resolveCompositionPreviewScale, resolveThumbnailSeekTime } from "./CompositionsTab"; +import { describe, expect, it, vi } from "vitest"; +import { + resolveCompositionPreviewScale, + resolveThumbnailSeekTime, + syncIframePlayback, +} from "./CompositionsTab"; describe("resolveCompositionPreviewScale", () => { it("scales a 16:9 stage to fit the composition card", () => { @@ -50,3 +54,25 @@ describe("resolveThumbnailSeekTime", () => { expect(resolveThumbnailSeekTime(Number.NaN)).toBe(3); }); }); + +describe("syncIframePlayback", () => { + it("mutes a composition-card preview before playing it", () => { + const calls: string[] = []; + const postMessage = vi.fn(() => calls.push("mute")); + const player = { + play: vi.fn(() => calls.push("play")), + }; + const iframe = { + contentWindow: { __player: player, postMessage }, + getRootNode: () => ({}), + } as unknown as HTMLIFrameElement; + + expect(syncIframePlayback(iframe, true)).toBe(true); + expect(postMessage).toHaveBeenCalledWith( + expect.objectContaining({ action: "set-muted", muted: true }), + "*", + ); + expect(calls).toEqual(["mute", "play"]); + expect(player.play).toHaveBeenCalledOnce(); + }); +}); diff --git a/packages/studio/src/components/sidebar/CompositionsTab.tsx b/packages/studio/src/components/sidebar/CompositionsTab.tsx index a38696798..5ba36a43d 100644 --- a/packages/studio/src/components/sidebar/CompositionsTab.tsx +++ b/packages/studio/src/components/sidebar/CompositionsTab.tsx @@ -1,4 +1,5 @@ import { memo, useCallback, useEffect, useRef, useState } from "react"; +import { setPreviewMediaMuted } from "../../player/lib/timelineIframeHelpers"; interface CompositionsTabProps { projectId: string; @@ -87,12 +88,13 @@ function resolveIframeDuration(iframe: HTMLIFrameElement | null): number | null } } -function syncIframePlayback(iframe: HTMLIFrameElement | null, shouldPlay: boolean): boolean { +export function syncIframePlayback(iframe: HTMLIFrameElement | null, shouldPlay: boolean): boolean { try { const player = (iframe?.contentWindow as PreviewWindow | null)?.__player; if (!player) return false; if (shouldPlay) { + setPreviewMediaMuted(iframe, true); player.play?.(); return true; }