feat: add tauri-plugin-shortcut with centralized shortcut registry#4056
Open
devin-ai-integration[bot] wants to merge 13 commits intomainfrom
Open
feat: add tauri-plugin-shortcut with centralized shortcut registry#4056devin-ai-integration[bot] wants to merge 13 commits intomainfrom
devin-ai-integration[bot] wants to merge 13 commits intomainfrom
Conversation
- Create plugins/shortcut/ with types, registry, and get_all_shortcuts command - Wire plugin into app (Cargo.toml, lib.rs, capabilities, package.json) - Create useGlobalShortcuts hook centralizing ~13 global shortcuts - Migrate shortcuts from body/index.tsx, chat.ts, settings.ts to hook - Mount useGlobalShortcuts in main layout Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
✅ Deploy Preview for hyprnote canceled.
|
✅ Deploy Preview for hyprnote-storybook canceled.
|
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
… in TS - Create useShortcutRegistry hook with shared query and keysMap lookup - Refactor useGlobalShortcuts to use registry keys via k(id) helper - Update all scoped shortcuts (leftsidebar, search, empty, note-input, settings, ai, transcript search, audio playback, undo-delete) to read keys from the Rust registry - Add enabled guards so shortcuts only activate after registry loads Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Add askama template-based doc generation for the keyboard shortcuts MDX. Running 'cargo test -p tauri-plugin-shortcut' (codegen) now generates both TS bindings and the docs page from the Rust shortcut registry. - Add doc.rs with key-to-kbd formatting and section builder - Add askama template for keyboard-shortcuts.mdx - Add export_docs test that renders template to MDX output - Reorder ShortcutCategory variants to control doc section order - Add display_name() to ShortcutCategory for doc section headers Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: add tauri-plugin-shortcut with centralized shortcut registry
Summary
Creates a new
tauri-plugin-shortcutRust plugin that serves as the single source of truth for all keyboard shortcuts in the app. The Rust side declares all shortcuts; the TS side reads from the registry and registers handlers as needed.Rust side (
plugins/shortcut/):ShortcutIdenum with#[serde(rename_all = "snake_case")]— all 36 shortcut identifiers as type-safe enum variants, exported via specta as a TS string literal unionShortcutDefstruct with typedid: ShortcutId, keys, category, description, scope (Global vs Scoped)registry.rsget_all_shortcutscommand exposed via spectadoc.rsmodule for deterministic keyboard shortcuts documentation generationTS side:
ShortcutIdtype generated by specta — compile-time enforcement that all shortcut references are validuseShortcutRegistryhook — shared React Query fetch withkeysMapfor O(1) lookup byShortcutIduseShortcutKeys(id: ShortcutId)— convenience hook to read a single key binding from the registryuseScopedShortcut(id, handler, options?, deps?)— wrapper hook that combinesuseShortcutKeys+useHotkeysinto a single call, automatically guarding withenabled: !!keysuseGlobalShortcutshook reads all key bindings from the registry viak(id: ShortcutId)helper (no hardcoded key strings)toggle_sidebar,focus_search,open_note_dialog,switch_to_enhanced/raw/transcript,prev/next_panel_tab,transcript_search,play_pause_audio,undo_delete) useuseScopedShortcut— no more manualuseShortcutKeys+useHotkeystwo-step patternuseTabsShortcutsfunction (~225 lines inbody/index.tsx) is removed; its logic now lives inuseGlobalShortcutsDoc generation (
plugins/shortcut/):doc.rswithformat_keys_as_kbd()(converts"mod+shift+n"→<kbd>⌘</kbd> + <kbd>⇧</kbd> + <kbd>N</kbd>),render_table()for markdown table generation, andbuild_sections()to group shortcuts by categoryassets/keyboard-shortcuts.mdx.jinja— uses{%- for %}whitespace trimming and{{ section.table }}(table rendered in Rust) to stay dprint-compatibleexport_docstest inlib.rs— runningcargo test -p tauri-plugin-shortcutgenerates both TS bindings andapps/web/content/docs/faq/6.keyboard-shortcuts.mdxdisplay_name()onShortcutCategoryfor human-readable section headers (e.g.Tabs→ "Notes & Tabs",View→ "Sidebar & Panels")ShortcutCategoryenum variants control doc section order (Navigation → View → Tabs → Search → Editor)CI:
tauri-plugin-shortcutto the Windows CI exclude list indesktop_ci.yamlReview & Testing Checklist for Human
getAllShortcuts()resolving via React Query. Until the query completes, shortcuts are disabled. Open the app and confirm shortcuts activate within ~1s.mod+n,mod+t,mod+w,mod+1-9,mod+alt+left/right,mod+shift+t/c/o/comma/l/f/n,mod+j,mod+,mod+\(sidebar),mod+k(search),mod+o(empty tab),mod+f(transcript),mod+h(find/replace),alt+s/m/t(editor tabs),ctrl+alt+left/right(panel nav in note-input),space(audio playback),mod+z(undo delete)mod+wclose-while-listening behavior — complex branching (listening → confirmation, pinned → unpin, chat_support → CLOSE event, else → close). Logic was moved fromuseTabsShortcutsinbody/index.tsxtouseGlobalShortcutsin a different component context.mod+,splitKey special case — this shortcut usessplitKey: "|"option inuseGlobalShortcuts. Confirm it still works through the registry.Recommended test plan: Open the app, create tabs of different types (empty, note, calendar, session with active listening), and systematically test each shortcut. Pay special attention to shortcuts with complex logic (
mod+w) and scoped shortcuts that should only work in specific contexts.Notes
ShortcutIdenum provides compile-time validation that all shortcut references are valid. Typos in shortcut IDs are now caught at build time rather than silently failing at runtime.useScopedShortcutwrapper: Simplifies scoped shortcut registration by combininguseShortcutKeys+useHotkeysinto one call. Automatically setsenabled: !!keysto prevent invalid handlers.enabled: false) until the registry query completes. This preventsuseHotkeys("")from registering invalid handlers, but means there's a brief window (~1s) on app launch where no shortcuts work.pnpm codegeninplugins/shortcut/(which runscargo test -p tauri-plugin-shortcut) now generates both TS bindings and the keyboard shortcuts MDX doc. The doc is deterministically generated from the registry using askama templates. Table rendering is done in Rust (render_table()) to keep the Jinja template dprint-compatible (no markdown table syntax in the template).mod+\shortcut required special handling — backslash is escaped as\\in MDX output to prevent it from escaping the closing</kbd>tag.useTabsShortcutsfunction was removed frombody/index.tsx; its logic now lives inuseGlobalShortcutsin_layout.tsx.Link to Devin run: https://app.devin.ai/sessions/0fda949a1eda4eed97e4ae4099fdb145
Requested by: @yujonglee