fix: wire export shortcut, text tool canvas integration, and undo rendering

1. Export dialog (Ctrl+Shift+S): replaced react-hotkeys-hook handler with
   a capture-phase keydown listener on window so the browser's native
   "Save Page As" dialog is intercepted before it can fire.

2. Text tool: created useTextTool hook that spawns an inline textarea
   overlay on canvas click, commits the text as a Konva Text object on
   blur/Enter, and wired it into the useActiveToolHandlers dispatcher.

3. Undo (Ctrl+Z): removed the 500ms debounce from zundo's handleSet.
   The debounce caused a race where calling undo before the timer fired
   would discard the future-states stack, making undo appear to do
   nothing.  The equality function (keyed on _historyVersion) already
   prevents intermediate states from being recorded, so the debounce
   was redundant.
This commit is contained in:
SnapOtter
2026-05-07 20:21:46 +08:00
parent 79897fcdb0
commit a633eff788
4 changed files with 209 additions and 17 deletions
+17 -8
View File
@@ -357,14 +357,23 @@ export function useEditorShortcuts(callbacks?: { onSave?: () => void; onExport?:
);
// Ctrl+Shift+S / Cmd+Shift+S - Export image
useHotkeys(
"mod+shift+s",
(e) => {
e.preventDefault();
callbacks?.onExport?.();
},
{ preventDefault: true },
);
// Use a raw keydown listener at capture phase to reliably prevent the
// browser's "Save Page As" dialog, which fires before react-hotkeys-hook
// can intercept.
const onExportRef = useRef(callbacks?.onExport);
onExportRef.current = callbacks?.onExport;
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "s") {
e.preventDefault();
e.stopPropagation();
onExportRef.current?.();
}
};
window.addEventListener("keydown", handler, { capture: true });
return () => window.removeEventListener("keydown", handler, { capture: true });
}, []);
// Ctrl+A / Cmd+A - Select all
useHotkeys(