mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
perf(studio): a scrub's state messages re-read the preview's compositions at most every 500 ms (#6429)
This commit is contained in:
@@ -23,6 +23,40 @@ describe("preview state messages", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("preview state messages while a scrub posts them", () => {
|
||||
it("re-reads the preview for missing compositions at most every 500 ms", () => {
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
vi.setSystemTime(10_000);
|
||||
const enrich = vi.fn();
|
||||
const handle = createPreviewMessageHandler({
|
||||
iframeRef: { current: null },
|
||||
processTimelineMessageRef: { current: vi.fn() },
|
||||
enrichMissingCompositionsRef: { current: enrich },
|
||||
lastTimelineMessageRef: { current: 0 },
|
||||
getAdapter: () => null,
|
||||
syncTimelineElements: vi.fn(),
|
||||
});
|
||||
const state = () =>
|
||||
handle(
|
||||
new MessageEvent("message", {
|
||||
data: { source: "hf-preview", type: "state", isPlaying: false },
|
||||
}),
|
||||
);
|
||||
state();
|
||||
vi.advanceTimersByTime(100);
|
||||
state();
|
||||
state();
|
||||
expect(enrich).toHaveBeenCalledTimes(1);
|
||||
vi.advanceTimersByTime(500);
|
||||
state();
|
||||
expect(enrich).toHaveBeenCalledTimes(2);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("preview quality messages", () => {
|
||||
function routeMessage(data: unknown, frame?: { postMessage: (message: unknown) => void }) {
|
||||
const iframe = frame ? ({ contentWindow: frame } as unknown as HTMLIFrameElement) : null;
|
||||
|
||||
@@ -69,15 +69,24 @@ function acceptedPreviewMessage(
|
||||
return acceptStudioRuntimeMessage(data) ? data : null;
|
||||
}
|
||||
|
||||
/** Whether enrichment is due: no timeline message and no enrichment of ours for 500 ms. Marks it run. */
|
||||
function enrichDue(lastTimelineMessage: number, enriched: { at: number }): boolean {
|
||||
const now = Date.now();
|
||||
if (now - lastTimelineMessage <= 500 || now - enriched.at <= 500) return false;
|
||||
enriched.at = now;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A `state` tick doubles as a recovery hook: if the store still has no
|
||||
* elements, read the manifest straight off the iframe, and if no `timeline`
|
||||
* message has arrived recently, re-run enrichment.
|
||||
* message has arrived recently, re-run enrichment (at most every 500 ms: it queries the whole document).
|
||||
*/
|
||||
function handleStateMessage(
|
||||
deps: PreviewMessageRouterDeps,
|
||||
iframe: HTMLIFrameElement | null,
|
||||
playingHoldsClipListPosts: boolean,
|
||||
enriched: { at: number },
|
||||
): void {
|
||||
try {
|
||||
if (usePlayerStore.getState().elements.length === 0) {
|
||||
@@ -86,7 +95,7 @@ function handleStateMessage(
|
||||
deps.processTimelineMessageRef.current(manifest);
|
||||
}
|
||||
}
|
||||
if (!playingHoldsClipListPosts && Date.now() - deps.lastTimelineMessageRef.current > 500) {
|
||||
if (!playingHoldsClipListPosts && enrichDue(deps.lastTimelineMessageRef.current, enriched)) {
|
||||
deps.enrichMissingCompositionsRef.current();
|
||||
}
|
||||
} catch {}
|
||||
@@ -135,11 +144,13 @@ function applyStoreReport(data: PreviewMessage): boolean {
|
||||
export function createPreviewMessageHandler(
|
||||
deps: PreviewMessageRouterDeps,
|
||||
): (e: MessageEvent) => void {
|
||||
const enriched = { at: 0 };
|
||||
return (e: MessageEvent) => {
|
||||
const iframe = deps.iframeRef.current;
|
||||
const data = acceptedPreviewMessage(e, iframe);
|
||||
if (!data) return;
|
||||
if (data.type === "state") return handleStateMessage(deps, iframe, data.isPlaying === true);
|
||||
if (data.type === "state")
|
||||
return handleStateMessage(deps, iframe, data.isPlaying === true, enriched);
|
||||
if (applyStoreReport(data)) return;
|
||||
if (data.type === "ready") {
|
||||
const level = usePlayerStore.getState().previewQuality;
|
||||
|
||||
Reference in New Issue
Block a user