diff --git a/src-tauri/src/shortcut.rs b/src-tauri/src/shortcut.rs
index f983b0b..a827ad8 100644
--- a/src-tauri/src/shortcut.rs
+++ b/src-tauri/src/shortcut.rs
@@ -624,10 +624,13 @@ pub fn change_app_language_setting(app: AppHandle, language: String) -> Result<(
Ok(())
}
-/// Determine whether a shortcut string contains at least one non-modifier key.
-/// We allow single non-modifier keys (e.g. "f5" or "space") but disallow
-/// modifier-only combos (e.g. "ctrl" or "ctrl+shift").
+/// Validate that a shortcut contains at least one non-modifier key.
+/// The tauri-plugin-global-shortcut library requires at least one main key.
fn validate_shortcut_string(raw: &str) -> Result<(), String> {
+ if raw.trim().is_empty() {
+ return Err("Shortcut cannot be empty".into());
+ }
+
let modifiers = [
"ctrl", "control", "shift", "alt", "option", "meta", "command", "cmd", "super", "win",
"windows",
@@ -635,10 +638,11 @@ fn validate_shortcut_string(raw: &str) -> Result<(), String> {
let has_non_modifier = raw
.split('+')
.any(|part| !modifiers.contains(&part.trim().to_lowercase().as_str()));
+
if has_non_modifier {
Ok(())
} else {
- Err("Shortcut must contain at least one non-modifier key".into())
+ Err("Shortcut must include a main key (letter, number, F-key, etc.) in addition to modifiers".into())
}
}
diff --git a/src/App.tsx b/src/App.tsx
index 7b637b6..c85db42 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -75,7 +75,18 @@ function App() {
return (
-
+
{/* Main content area that takes remaining space */}
= ({
if (editingShortcutId && originalBinding) {
try {
await updateBinding(editingShortcutId, originalBinding);
- await commands
- .resumeBinding(editingShortcutId)
- .catch(console.error);
} catch (error) {
console.error("Failed to restore original binding:", error);
toast.error(t("settings.general.shortcut.errors.restore"));
@@ -132,15 +129,32 @@ export const HandyShortcut: React.FC = ({
const updatedKeyPressed = keyPressed.filter((k) => k !== key);
if (updatedKeyPressed.length === 0 && recordedKeys.length > 0) {
// Create the shortcut string from all recorded keys
- const newShortcut = recordedKeys.join("+");
+ // Sort keys so modifiers come first, then the main key
+ const modifiers = [
+ "ctrl",
+ "control",
+ "shift",
+ "alt",
+ "option",
+ "meta",
+ "command",
+ "cmd",
+ "super",
+ "win",
+ "windows",
+ ];
+ const sortedKeys = recordedKeys.sort((a, b) => {
+ const aIsModifier = modifiers.includes(a.toLowerCase());
+ const bIsModifier = modifiers.includes(b.toLowerCase());
+ if (aIsModifier && !bIsModifier) return -1;
+ if (!aIsModifier && bIsModifier) return 1;
+ return 0;
+ });
+ const newShortcut = sortedKeys.join("+");
if (editingShortcutId && bindings[editingShortcutId]) {
try {
await updateBinding(editingShortcutId, newShortcut);
- // Re-register the shortcut now that recording is finished
- await commands
- .resumeBinding(editingShortcutId)
- .catch(console.error);
} catch (error) {
console.error("Failed to change binding:", error);
toast.error(
@@ -153,9 +167,6 @@ export const HandyShortcut: React.FC = ({
if (originalBinding) {
try {
await updateBinding(editingShortcutId, originalBinding);
- await commands
- .resumeBinding(editingShortcutId)
- .catch(console.error);
} catch (resetError) {
console.error("Failed to reset binding:", resetError);
toast.error(t("settings.general.shortcut.errors.reset"));
@@ -181,9 +192,6 @@ export const HandyShortcut: React.FC = ({
if (editingShortcutId && originalBinding) {
try {
await updateBinding(editingShortcutId, originalBinding);
- await commands
- .resumeBinding(editingShortcutId)
- .catch(console.error);
} catch (error) {
console.error("Failed to restore original binding:", error);
toast.error(t("settings.general.shortcut.errors.restore"));
diff --git a/src/stores/settingsStore.ts b/src/stores/settingsStore.ts
index f35a6e9..3a7a231 100644
--- a/src/stores/settingsStore.ts
+++ b/src/stores/settingsStore.ts
@@ -307,7 +307,17 @@ export const useSettingsStore = create()(
: null,
}));
- await commands.changeBinding(id, binding);
+ const result = await commands.changeBinding(id, binding);
+
+ // Check if the command executed successfully
+ if (result.status === "error") {
+ throw new Error(result.error);
+ }
+
+ // Check if the binding change was successful
+ if (!result.data.success) {
+ throw new Error(result.data.error || "Failed to update binding");
+ }
} catch (error) {
console.error(`Failed to update binding ${id}:`, error);
@@ -328,6 +338,9 @@ export const useSettingsStore = create()(
: null,
}));
}
+
+ // Re-throw to let the caller know it failed
+ throw error;
} finally {
setUpdating(updateKey, false);
}