diff --git a/packages/studio/src/components/editor/useColorGradingController.test.ts b/packages/studio/src/components/editor/useColorGradingController.test.ts index 40fe3cd90..d16fe5f62 100644 --- a/packages/studio/src/components/editor/useColorGradingController.test.ts +++ b/packages/studio/src/components/editor/useColorGradingController.test.ts @@ -490,15 +490,27 @@ describe("useColorGradingController", () => { vi.useRealTimers(); }); - it("resetGrading returns to the neutral preset", () => { + it("resetGrading resets Grade fields without clearing Effects or Palette", () => { const { root, getState } = renderHook(vi.fn()); + const grading = normalizeHfColorGrading({ + preset: "bright-pop", + lut: { src: "assets/luts/custom.cube", intensity: 0.6 }, + effects: { pixelate: 0.5 }, + palette: ["#112233", "#ffffff"], + }); + if (!grading) throw new Error("expected grading to normalize"); act(() => { - getState().commitColorGrading(brightPopGrading()); + getState().commitColorGrading(grading); }); act(() => { getState().resetGrading(); }); - expect(getState().grading.preset).toBe("neutral"); + expect(getState().grading).toMatchObject({ + preset: "neutral", + lut: null, + effects: { pixelate: 0.5 }, + palette: ["#112233", "#ffffff"], + }); act(() => root.unmount()); }); diff --git a/packages/studio/src/components/editor/useColorGradingController.ts b/packages/studio/src/components/editor/useColorGradingController.ts index 87ab54dfd..e1994401d 100644 --- a/packages/studio/src/components/editor/useColorGradingController.ts +++ b/packages/studio/src/components/editor/useColorGradingController.ts @@ -542,6 +542,13 @@ export function useColorGradingController({ commitCompare, setApplyScope, applyToScope, - resetGrading: () => commitColorGrading(defaultColorGrading()), + resetGrading: () => { + const neutral = defaultColorGrading(); + commitColorGrading({ + ...neutral, + effects: latestGradingRef.current.effects, + palette: latestGradingRef.current.palette, + }); + }, }; } diff --git a/packages/studio/src/hooks/useBlockCatalog.ts b/packages/studio/src/hooks/useBlockCatalog.ts index 74a7eadee..7efaee4d4 100644 --- a/packages/studio/src/hooks/useBlockCatalog.ts +++ b/packages/studio/src/hooks/useBlockCatalog.ts @@ -6,33 +6,51 @@ import { resolveBlockCategory, } from "../utils/blockCategories"; -export type CatalogItem = RegistryItem & { +type CatalogItem = RegistryItem & { category: BlockCategory; }; +let catalogCache: CatalogItem[] | null = null; +let catalogRequest: Promise | null = null; + +function loadCatalog(): Promise { + catalogRequest ??= fetch("/api/registry/blocks") + .then((response) => { + if (!response.ok) throw new Error("Failed to load catalog"); + return response.json() as Promise; + }) + .then((items) => { + catalogCache = items + .map((item) => ({ ...item, category: resolveBlockCategory(item.tags) })) + .sort((a, b) => { + const aIndex = BLOCK_CATEGORIES.findIndex((category) => category.id === a.category); + const bIndex = BLOCK_CATEGORIES.findIndex((category) => category.id === b.category); + return (aIndex === -1 ? 99 : aIndex) - (bIndex === -1 ? 99 : bIndex); + }); + return catalogCache; + }) + .catch((error: unknown) => { + catalogRequest = null; + throw error; + }); + return catalogRequest; +} + export function useBlockCatalog() { - const [blocks, setBlocks] = useState([]); - const [loading, setLoading] = useState(true); + const [blocks, setBlocks] = useState(() => catalogCache ?? []); + const [loading, setLoading] = useState(catalogCache === null); const [error, setError] = useState(null); const [search, setSearch] = useState(""); const [category, setCategory] = useState(null); // fallow-ignore-next-line complexity useEffect(() => { + if (catalogCache) return; let cancelled = false; (async () => { try { - const res = await fetch("/api/registry/blocks"); - if (!res.ok) throw new Error("Failed to load catalog"); - const data = (await res.json()) as RegistryItem[]; + const items = await loadCatalog(); if (cancelled) return; - const items = data - .map((b) => ({ ...b, category: resolveBlockCategory(b.tags) })) - .sort((a, b) => { - const ia = BLOCK_CATEGORIES.findIndex((c) => c.id === a.category); - const ib = BLOCK_CATEGORIES.findIndex((c) => c.id === b.category); - return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib); - }); setBlocks(items); } catch (err) { if (cancelled) return;