fix: allow standard text shortcuts in command palette input (#73)
* fix: allow standard text shortcuts in command palette input Two root causes prevented macOS text shortcuts (Cmd+A, Cmd+Backspace, etc.) from working in the command palette input: 1. The Tauri native menu only had a View submenu — no Edit menu. On macOS, app.set_menu() replaces the entire menu bar, so Cmd+A/C/V/X/Z accelerators were removed. Added standard Edit menu with predefined items. 2. useAppKeyboard globally intercepted Cmd+Backspace (mapped to trash note) even when a text input was focused. Added an isTextInputFocused guard so Cmd+Backspace/Delete fall through to native text editing in inputs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: close missing }) in useAppKeyboard.test.ts --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use tauri::{
|
||||
menu::{MenuBuilder, MenuItemBuilder, SubmenuBuilder},
|
||||
menu::{MenuBuilder, MenuItemBuilder, PredefinedMenuItem, SubmenuBuilder},
|
||||
App, Emitter,
|
||||
};
|
||||
|
||||
@@ -10,6 +10,16 @@ const VIEW_ITEMS: [(&str, &str, &str); 3] = [
|
||||
];
|
||||
|
||||
pub fn setup_menu(app: &App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let edit_submenu = SubmenuBuilder::new(app, "Edit")
|
||||
.item(&PredefinedMenuItem::undo(app, Some("Undo"))?)
|
||||
.item(&PredefinedMenuItem::redo(app, Some("Redo"))?)
|
||||
.separator()
|
||||
.item(&PredefinedMenuItem::cut(app, Some("Cut"))?)
|
||||
.item(&PredefinedMenuItem::copy(app, Some("Copy"))?)
|
||||
.item(&PredefinedMenuItem::paste(app, Some("Paste"))?)
|
||||
.item(&PredefinedMenuItem::select_all(app, Some("Select All"))?)
|
||||
.build()?;
|
||||
|
||||
let mut view_menu = SubmenuBuilder::new(app, "View");
|
||||
for (id, label, accel) in &VIEW_ITEMS {
|
||||
let item = MenuItemBuilder::new(*label)
|
||||
@@ -20,7 +30,10 @@ pub fn setup_menu(app: &App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
let view_submenu = view_menu.build()?;
|
||||
|
||||
let menu = MenuBuilder::new(app).item(&view_submenu).build()?;
|
||||
let menu = MenuBuilder::new(app)
|
||||
.item(&edit_submenu)
|
||||
.item(&view_submenu)
|
||||
.build()?;
|
||||
|
||||
app.set_menu(menu)?;
|
||||
|
||||
|
||||
@@ -111,4 +111,36 @@ describe('useAppKeyboard', () => {
|
||||
expect(actions.onQuickOpen).not.toHaveBeenCalled()
|
||||
expect(actions.onCreateNote).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
function withFocusedInput(fn: () => void) {
|
||||
const input = document.createElement('input')
|
||||
document.body.appendChild(input)
|
||||
input.focus()
|
||||
try { fn() } finally { document.body.removeChild(input) }
|
||||
}
|
||||
|
||||
it('Cmd+Backspace does not trash note when text input is focused', () => {
|
||||
const actions = makeActions()
|
||||
renderHook(() => useAppKeyboard(actions))
|
||||
withFocusedInput(() => {
|
||||
fireKey('Backspace', { metaKey: true })
|
||||
expect(actions.onTrashNote).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
it('Cmd+Backspace trashes note when no text input is focused', () => {
|
||||
const actions = makeActions()
|
||||
renderHook(() => useAppKeyboard(actions))
|
||||
fireKey('Backspace', { metaKey: true })
|
||||
expect(actions.onTrashNote).toHaveBeenCalledWith('/vault/test.md')
|
||||
})
|
||||
|
||||
it('Cmd+K still works when text input is focused', () => {
|
||||
const actions = makeActions()
|
||||
renderHook(() => useAppKeyboard(actions))
|
||||
withFocusedInput(() => {
|
||||
fireKey('k', { metaKey: true })
|
||||
expect(actions.onCommandPalette).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -17,6 +17,13 @@ interface KeyboardActions {
|
||||
|
||||
type ShortcutHandler = () => void
|
||||
|
||||
const TEXT_EDITING_KEYS = new Set(['Backspace', 'Delete'])
|
||||
|
||||
function isTextInputFocused(): boolean {
|
||||
const tag = document.activeElement?.tagName
|
||||
return tag === 'INPUT' || tag === 'TEXTAREA'
|
||||
}
|
||||
|
||||
const VIEW_MODE_KEYS: Record<string, ViewMode> = {
|
||||
'1': 'editor-only',
|
||||
'2': 'editor-list',
|
||||
@@ -41,6 +48,7 @@ function handleCmdKey(e: KeyboardEvent, keyMap: Record<string, ShortcutHandler>)
|
||||
if (!mod) return false
|
||||
const handler = keyMap[e.key]
|
||||
if (!handler) return false
|
||||
if (TEXT_EDITING_KEYS.has(e.key) && isTextInputFocused()) return false
|
||||
e.preventDefault()
|
||||
handler()
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user