diff --git a/bun.lockb b/bun.lockb index fe07be3..8fbc20a 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 623ede0..8859855 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@tauri-apps/plugin-upload": "~2", "react": "^18.3.1", "react-dom": "^18.3.1", + "sonner": "^2.0.7", "tailwindcss": "^4.0.2", "tauri-plugin-macos-permissions-api": "^2.0.4", "zod": "^3.24.4" diff --git a/src/App.tsx b/src/App.tsx index e3c80e6..fbd1a45 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import Footer from "./components/footer"; import HandyTextLogo from "./components/icons/HandyTextLogo"; import Onboarding from "./components/onboarding"; import { Settings } from "./components/settings/Settings"; +import { Toaster } from "sonner"; function App() { const [showOnboarding, setShowOnboarding] = useState(null); @@ -43,6 +44,7 @@ function App() { return (
+
diff --git a/src/components/settings/HandyShortcut.tsx b/src/components/settings/HandyShortcut.tsx index b4ebd96..2501ab0 100644 --- a/src/components/settings/HandyShortcut.tsx +++ b/src/components/settings/HandyShortcut.tsx @@ -11,6 +11,7 @@ import ResetIcon from "../icons/ResetIcon"; import { SettingContainer } from "../ui/SettingContainer"; import { useSettings } from "../../hooks/useSettings"; import { invoke } from "@tauri-apps/api/core"; +import { toast } from "sonner"; interface HandyShortcutProps { descriptionMode?: "inline" | "tooltip"; @@ -38,7 +39,7 @@ export const HandyShortcut: React.FC = ({ useEffect(() => { const detectOsType = async () => { try { - const detectedType = await type(); + const detectedType = type(); let normalizedType: OSType; switch (detectedType) { @@ -75,8 +76,18 @@ export const HandyShortcut: React.FC = ({ const handleKeyDown = async (e: KeyboardEvent) => { if (e.repeat) return; // ignore auto-repeat if (e.key === "Escape") { - // Cancel recording - if (editingShortcutId) { + // Cancel recording and restore original binding + if (editingShortcutId && originalBinding) { + try { + await updateBinding(editingShortcutId, originalBinding); + await invoke("resume_binding", { id: editingShortcutId }).catch( + console.error, + ); + } catch (error) { + console.error("Failed to restore original binding:", error); + toast.error("Failed to restore original shortcut"); + } + } else if (editingShortcutId) { await invoke("resume_binding", { id: editingShortcutId }).catch( console.error, ); @@ -129,6 +140,20 @@ export const HandyShortcut: React.FC = ({ ); } catch (error) { console.error("Failed to change binding:", error); + toast.error(`Failed to set shortcut: ${error}`); + + // Reset to original binding on error + if (originalBinding) { + try { + await updateBinding(editingShortcutId, originalBinding); + await invoke("resume_binding", { id: editingShortcutId }).catch( + console.error, + ); + } catch (resetError) { + console.error("Failed to reset binding:", resetError); + toast.error("Failed to reset shortcut to original value"); + } + } } // Exit editing mode and reset states @@ -141,11 +166,21 @@ export const HandyShortcut: React.FC = ({ }; // Add click outside handler - const handleClickOutside = (e: MouseEvent) => { + const handleClickOutside = async (e: MouseEvent) => { const activeElement = shortcutRefs.current.get(editingShortcutId); if (activeElement && !activeElement.contains(e.target as Node)) { - // Cancel shortcut recording - the hook will handle rollback - if (editingShortcutId) { + // Cancel shortcut recording and restore original binding + if (editingShortcutId && originalBinding) { + try { + await updateBinding(editingShortcutId, originalBinding); + await invoke("resume_binding", { id: editingShortcutId }).catch( + console.error, + ); + } catch (error) { + console.error("Failed to restore original binding:", error); + toast.error("Failed to restore original shortcut"); + } + } else if (editingShortcutId) { invoke("resume_binding", { id: editingShortcutId }).catch( console.error, );