Files
hyperframes/packages/studio/src/hooks/useCompositionContentLoader.ts
T

41 lines
1.5 KiB
TypeScript

import { useCallback } from "react";
/**
* Loads a composition file's content for the source editor when a composition
* is selected. Content stays null until the fetch resolves — the source editor
* must not mount on a null-content file, or its autosave would overwrite the
* real file with an empty document. Load failures surface as an error toast
* instead of silently rendering an empty (and autosave-armed) editor.
*/
export function useCompositionContentLoader({
projectId,
setEditingFile,
setActiveCompPath,
showToast,
}: {
projectId: string | null;
setEditingFile: (file: { path: string; content: string | null }) => void;
setActiveCompPath: (path: string | null) => void;
showToast: (message: string, tone?: "error" | "info") => void;
}) {
return useCallback(
(comp: string) => {
setActiveCompPath(comp.endsWith(".html") ? comp : null);
setEditingFile({ path: comp, content: null });
fetch(`/api/projects/${projectId}/files/${comp}`)
.then(async (r) => {
if (!r.ok) throw new Error(`Failed to load ${comp} (${r.status})`);
return r.json();
})
.then((data: { content?: string }) => {
if (typeof data.content !== "string") throw new Error(`No content returned for ${comp}`);
setEditingFile({ path: comp, content: data.content });
})
.catch((err) => {
showToast(err instanceof Error ? err.message : `Failed to load ${comp}`, "error");
});
},
[projectId, setEditingFile, setActiveCompPath, showToast],
);
}