mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix(studio): short-circuit slideshow-island detection with a substring check (review N2)
slideshowIslandRegex scanned the full file content on every editingFile change even for the common non-slideshow case. Gate it behind a plain substring check on SLIDESHOW_ISLAND_TYPE first — cheap, and avoids the full-content RegExp pass for files that plainly have no island. Added a test for the still-open behavior this preserves: a malformed island (invalid JSON) still trips the substring check and the regex, so the tab stays discoverable rather than silently disappearing.
This commit is contained in:
@@ -69,6 +69,13 @@ describe("useSlideshowTabState", () => {
|
|||||||
harness.unmount();
|
harness.unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("still detects a malformed island — presence-only, not full manifest validation", () => {
|
||||||
|
const malformed = `<html><body><script type="application/hyperframes-slideshow+json">{not valid json</script></body></html>`;
|
||||||
|
const harness = renderHook({ editingFileContent: malformed, rightPanelTab: "design" });
|
||||||
|
expect(harness.getState().isSlideshowComposition).toBe(true);
|
||||||
|
harness.unmount();
|
||||||
|
});
|
||||||
|
|
||||||
it("bounces rightPanelTab off 'slideshow' to 'renders' on a non-slideshow composition", () => {
|
it("bounces rightPanelTab off 'slideshow' to 'renders' on a non-slideshow composition", () => {
|
||||||
const harness = renderHook({ editingFileContent: PLAIN_HTML, rightPanelTab: "slideshow" });
|
const harness = renderHook({ editingFileContent: PLAIN_HTML, rightPanelTab: "slideshow" });
|
||||||
expect(harness.setRightPanelTabCalls).toEqual(["renders"]);
|
expect(harness.setRightPanelTabCalls).toEqual(["renders"]);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useMemo, type MutableRefObject } from "react";
|
import { useEffect, useMemo, type MutableRefObject } from "react";
|
||||||
import { slideshowIslandRegex } from "@hyperframes/core/slideshow";
|
import { SLIDESHOW_ISLAND_TYPE, slideshowIslandRegex } from "@hyperframes/core/slideshow";
|
||||||
import type { SceneInfo } from "../components/panels/SlideshowPanel";
|
import type { SceneInfo } from "../components/panels/SlideshowPanel";
|
||||||
import type { IframeWindow } from "../player/lib/playbackTypes";
|
import type { IframeWindow } from "../player/lib/playbackTypes";
|
||||||
import type { RightPanelTab } from "../utils/studioHelpers";
|
import type { RightPanelTab } from "../utils/studioHelpers";
|
||||||
@@ -27,11 +27,13 @@ export function useSlideshowTabState(params: {
|
|||||||
|
|
||||||
// Presence-only (not full manifest validation): a malformed island should
|
// Presence-only (not full manifest validation): a malformed island should
|
||||||
// still surface the Slideshow tab so the user can see/fix it, rather than
|
// still surface the Slideshow tab so the user can see/fix it, rather than
|
||||||
// making the whole panel disappear.
|
// making the whole panel disappear. The plain substring check short-circuits
|
||||||
const isSlideshowComposition = useMemo(
|
// the regex scan on every non-slideshow file (the common case) without
|
||||||
() => Boolean(editingFileContent && slideshowIslandRegex("i").test(editingFileContent)),
|
// paying for a full-content RegExp pass.
|
||||||
[editingFileContent],
|
const isSlideshowComposition = useMemo(() => {
|
||||||
);
|
if (!editingFileContent || !editingFileContent.includes(SLIDESHOW_ISLAND_TYPE)) return false;
|
||||||
|
return slideshowIslandRegex("i").test(editingFileContent);
|
||||||
|
}, [editingFileContent]);
|
||||||
|
|
||||||
// Derive scene list from the live clip manifest in the preview iframe.
|
// Derive scene list from the live clip manifest in the preview iframe.
|
||||||
const slideshowScenes = useMemo<SceneInfo[]>(() => {
|
const slideshowScenes = useMemo<SceneInfo[]>(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user