From 48fb42e5f0d067997aef90410e53dab7362bce71 Mon Sep 17 00:00:00 2001 From: ukimsanov Date: Tue, 16 Jun 2026 13:04:59 -0700 Subject: [PATCH] refactor(runtime): trim color grading helpers --- packages/core/src/runtime/bridge.test.ts | 10 ++---- packages/core/src/runtime/bridge.ts | 33 ++----------------- packages/core/src/runtime/colorGrading.ts | 31 ++++++++--------- .../src/services/videoFrameInjector.test.ts | 9 +++-- .../engine/src/services/videoFrameInjector.ts | 4 +-- 5 files changed, 24 insertions(+), 63 deletions(-) diff --git a/packages/core/src/runtime/bridge.test.ts b/packages/core/src/runtime/bridge.test.ts index 560d7c19d..282baad33 100644 --- a/packages/core/src/runtime/bridge.test.ts +++ b/packages/core/src/runtime/bridge.test.ts @@ -119,10 +119,7 @@ describe("installRuntimeControlBridge", () => { const grading = { preset: "warm-clean", intensity: 0.7 }; const target = { id: "hero-video", selectorIndex: 0 }; handler(makeControlMessage("set-color-grading", { target, grading })); - expect(deps.onSetColorGrading).toHaveBeenCalledWith( - { id: "hero-video", hfId: null, selector: null, selectorIndex: 0 }, - grading, - ); + expect(deps.onSetColorGrading).toHaveBeenCalledWith(target, grading); }); it("dispatches set-color-grading-compare command with target and compare payload", () => { @@ -131,10 +128,7 @@ describe("installRuntimeControlBridge", () => { const compare = { enabled: true, position: 0.42 }; const target = { id: "hero-video", selectorIndex: 0 }; handler(makeControlMessage("set-color-grading-compare", { target, compare })); - expect(deps.onSetColorGradingCompare).toHaveBeenCalledWith( - { id: "hero-video", hfId: null, selector: null, selectorIndex: 0 }, - compare, - ); + expect(deps.onSetColorGradingCompare).toHaveBeenCalledWith(target, compare); }); it("dispatches tick command", () => { diff --git a/packages/core/src/runtime/bridge.ts b/packages/core/src/runtime/bridge.ts index 11b51aa5b..c1c885a75 100644 --- a/packages/core/src/runtime/bridge.ts +++ b/packages/core/src/runtime/bridge.ts @@ -20,30 +20,6 @@ type BridgeDeps = { onDisablePickMode: () => void; }; -function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null && !Array.isArray(value); -} - -function readOptionalString(value: unknown): string | null { - return typeof value === "string" && value.trim() ? value : null; -} - -function readOptionalIndex(value: unknown): number | null { - const parsed = Number(value); - return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : null; -} - -function readColorGradingTarget(value: unknown): HfColorGradingTarget | string | null { - if (typeof value === "string") return value; - if (!isRecord(value)) return null; - return { - id: readOptionalString(value.id), - hfId: readOptionalString(value.hfId), - selector: readOptionalString(value.selector), - selectorIndex: readOptionalIndex(value.selectorIndex), - }; -} - export function postRuntimeMessage(payload: RuntimeOutboundMessage): void { try { window.parent.postMessage(payload, "*"); @@ -91,16 +67,11 @@ export function installRuntimeControlBridge(deps: BridgeDeps): (event: MessageEv return; } if (action === "set-color-grading") { - const payload = isRecord(data) ? data : {}; - deps.onSetColorGrading(readColorGradingTarget(payload.target), payload.grading ?? null); + deps.onSetColorGrading(data.target ?? null, data.grading ?? null); return; } if (action === "set-color-grading-compare") { - const payload = isRecord(data) ? data : {}; - deps.onSetColorGradingCompare( - readColorGradingTarget(payload.target), - payload.compare ?? null, - ); + deps.onSetColorGradingCompare(data.target ?? null, data.compare ?? null); return; } if (action === "enable-pick-mode") { diff --git a/packages/core/src/runtime/colorGrading.ts b/packages/core/src/runtime/colorGrading.ts index 3abcbe8b1..94646323a 100644 --- a/packages/core/src/runtime/colorGrading.ts +++ b/packages/core/src/runtime/colorGrading.ts @@ -121,12 +121,10 @@ export type RuntimeColorGradingStatus = | { state: "active"; message: string } | { state: "unavailable"; message: string }; -interface HfGlobalWithColorGrading { - colorGrading?: RuntimeColorGradingApi; -} - type WindowWithColorGrading = Window & { - __hf?: HfGlobalWithColorGrading; + __hf?: { + colorGrading?: RuntimeColorGradingApi; + }; __hyperframes?: { getVariables?: () => Partial>; }; @@ -161,10 +159,6 @@ const DEFAULT_COMPARE: RuntimeColorGradingCompareState = { lineWidth: 2, }; -function readColorGradingRawAttribute(element: Element): string | null { - return element.getAttribute(HF_COLOR_GRADING_ATTR); -} - function readVariablesForElement(element: Element): HfColorGradingVariableMap { const win = window as WindowWithColorGrading; const scope = element.closest("[data-composition-id]"); @@ -180,7 +174,7 @@ function readVariablesForElement(element: Element): HfColorGradingVariableMap { } function readColorGradingAttribute(element: Element): NormalizedHfColorGrading | null { - const raw = readColorGradingRawAttribute(element); + const raw = element.getAttribute(HF_COLOR_GRADING_ATTR); if (raw == null) return null; return normalizeHfColorGradingWithVariables(raw, readVariablesForElement(element)); } @@ -680,21 +674,24 @@ function parseObjectPosition(value: string): { x: number; y: number } { const tokens = value.trim().split(/\s+/).filter(Boolean); let x = 0.5; let y = 0.5; - for (const token of tokens) { + for (let index = 0; index < tokens.length; index++) { + const token = tokens[index] ?? ""; const xValue = parseObjectPositionPart(token, "x"); const yValue = parseObjectPositionPart(token, "y"); - if (xValue !== null && (token === "left" || token === "right" || token.endsWith("%"))) { + if ( + xValue !== null && + (token === "left" || token === "right" || (token.endsWith("%") && index === 0)) + ) { x = xValue; continue; } - if (yValue !== null && (token === "top" || token === "bottom")) { + if ( + yValue !== null && + (token === "top" || token === "bottom" || (token.endsWith("%") && index > 0)) + ) { y = yValue; continue; } - if (token === "center") { - if (x === 0.5) x = 0.5; - else y = 0.5; - } } return { x, y }; } diff --git a/packages/engine/src/services/videoFrameInjector.test.ts b/packages/engine/src/services/videoFrameInjector.test.ts index 11caff59b..b61ab4901 100644 --- a/packages/engine/src/services/videoFrameInjector.test.ts +++ b/packages/engine/src/services/videoFrameInjector.test.ts @@ -272,11 +272,10 @@ describe("createVideoFrameInjector cache hygiene against page-side skips", () => injectVideoFramesBatchMock.mockResolvedValueOnce(["facet"]); await hook!(page, 1.5); - expect(evaluate).toHaveBeenCalledTimes(1); - // Re-render is requested at the same time as the seek. - expect(evaluate.mock.calls[0]![1]).toBe(1.5); + const reseekCall = evaluate.mock.calls.find((call) => call[1] === 1.5); + expect(reseekCall).toBeDefined(); // The evaluated page function invokes window.__hfReseekGpu(time). - const pageFn = evaluate.mock.calls[0]![0] as (t: number) => void; + const pageFn = reseekCall![0] as (t: number) => void; const reseek = vi.fn(); (globalThis as unknown as { window?: unknown }).window = { __hfReseekGpu: reseek }; pageFn(1.5); @@ -296,6 +295,6 @@ describe("createVideoFrameInjector cache hygiene against page-side skips", () => injectVideoFramesBatchMock.mockResolvedValueOnce([]); await hook!(page, 1.5); - expect(evaluate).not.toHaveBeenCalled(); + expect(evaluate.mock.calls.some((call) => call[1] === 1.5)).toBe(false); }); }); diff --git a/packages/engine/src/services/videoFrameInjector.ts b/packages/engine/src/services/videoFrameInjector.ts index 4fd254808..8ee8318aa 100644 --- a/packages/engine/src/services/videoFrameInjector.ts +++ b/packages/engine/src/services/videoFrameInjector.ts @@ -147,7 +147,7 @@ function createFrameSourceCache( export const __testing = { createFrameSourceCache }; async function redrawRuntimeColorGrading(page: Page): Promise { - await page.evaluate(async () => { + await page.evaluate(() => { const hf = ( window as Window & { __hf?: { @@ -158,7 +158,7 @@ async function redrawRuntimeColorGrading(page: Page): Promise { const redraw = hf?.colorGrading?.redraw; if (typeof redraw !== "function") return; try { - await Promise.resolve(redraw()); + redraw(); } catch { // Optional page-side shader layer. }