Skip to content

Commit 44f3dd7

Browse files
authored
feat: add warning before losing editor progress (magic-peach#1117)
1 parent e78f7ee commit 44f3dd7

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

src/components/VideoEditor.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,19 @@ export default function VideoEditor() {
225225

226226
const [copied, setCopied] = useState(false);
227227
const [shareCopied, setShareCopied] = useState(false);
228+
useEffect(() => {
229+
if (!file) return;
230+
231+
localStorage.setItem(
232+
"editorState",
233+
JSON.stringify({
234+
recipe,
235+
overlayPosition,
236+
overlaySize,
237+
overlayOpacity,
238+
})
239+
);
240+
}, [recipe, overlayPosition, overlaySize, overlayOpacity, file]);
228241
const [selectedTextId, setSelectedTextId] = useState<string | null>(null);
229242
const [openSections, setOpenSections] = useState({
230243
resize: true,
@@ -234,6 +247,33 @@ export default function VideoEditor() {
234247
audio: false,
235248
export: false,
236249
});
250+
useEffect(() => {
251+
const saved = localStorage.getItem("editorState");
252+
253+
if (!saved) return;
254+
255+
try {
256+
const parsed = JSON.parse(saved);
257+
258+
if (parsed.recipe) {
259+
updateRecipe(parsed.recipe);
260+
}
261+
262+
if (parsed.overlayPosition) {
263+
setOverlayPosition(parsed.overlayPosition);
264+
}
265+
266+
if (parsed.overlaySize) {
267+
setOverlaySize(parsed.overlaySize);
268+
}
269+
270+
if (parsed.overlayOpacity) {
271+
setOverlayOpacity(parsed.overlayOpacity);
272+
}
273+
} catch (err) {
274+
console.error("Failed to restore editor state", err);
275+
}
276+
}, []);
237277

238278
const toggleSection = (key: keyof typeof openSections) =>
239279
setOpenSections((prev) => ({ ...prev, [key]: !prev[key] }));
@@ -263,13 +303,28 @@ export default function VideoEditor() {
263303

264304
useEffect(() => {
265305
if (status === "done" && downloadRef.current) {
306+
266307
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
267308
downloadRef.current.scrollIntoView({
268309
behavior: prefersReducedMotion ? "instant" : "smooth",
269310
block: "center",
270311
});
271312
}
272313
}, [status]);
314+
useEffect(() => {
315+
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
316+
if (file) {
317+
e.preventDefault();
318+
e.returnValue = "";
319+
}
320+
};
321+
322+
window.addEventListener("beforeunload", handleBeforeUnload);
323+
324+
return () => {
325+
window.removeEventListener("beforeunload", handleBeforeUnload);
326+
};
327+
}, [file]);
273328

274329
const isProcessing = status === "loading-engine" || status === "exporting";
275330
const isMac = typeof navigator !== "undefined" && /Mac/i.test(navigator.platform);

0 commit comments

Comments
 (0)