Implement complete native menu system with keyboard accelerators
This commit establishes a comprehensive native menu system for the Tauri application, bringing it to parity with the Electron implementation and enabling full keyboard shortcut support. ## Key Features Added **Native Menu System:** - Complete menu bar with File, Edit, View, and Window menus - Platform-specific adaptations (macOS app menu, Windows/Linux quit behavior) - Full menu event handling system with proper window management **Keyboard Accelerators:** - CmdOrCtrl+N for New Instance creation - Standard Edit menu shortcuts (Undo, Redo, Cut, Copy, Paste, Select All) - View menu shortcuts (Reload, Force Reload, Toggle DevTools, Fullscreen) - Built-in zoom hotkeys enabled via zoomHotkeysEnabled **Enhanced Capabilities:** - Added core:menu:default permission for menu management - Added core:webview:allow-set-webview-zoom for zoom functionality - Proper event communication between Tauri backend and frontend **Frontend Integration:** - Tauri event listener for menu:newInstance events - Proper cleanup and error handling for event subscriptions - Runtime environment detection for Tauri-specific behavior ## Technical Changes **Backend (Rust):** - Replaced empty menu stub with full SubmenuBuilder implementation - Added comprehensive menu event handling with window operations - Implemented MenuItem::with_id for accelerator support - Added platform-specific menu construction logic **Frontend (TypeScript):** - Added Tauri event listener integration in main App component - Proper lifecycle management with onMount/onCleanup - Runtime environment detection for conditional Tauri behavior **Configuration:** - Enabled zoomHotkeysEnabled in tauri.conf.json for built-in zoom support - Updated capabilities to include necessary menu and webview permissions This implementation provides a native, platform-consistent user experience with full keyboard shortcut support, matching the functionality users expect from desktop applications.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Component, Show, createMemo, createEffect, createSignal } from "solid-js"
|
||||
import { Component, Show, createMemo, createEffect, createSignal, onMount, onCleanup } from "solid-js"
|
||||
import { Dialog } from "@kobalte/core/dialog"
|
||||
import { Toaster } from "solid-toast"
|
||||
import AlertDialog from "./components/alert-dialog"
|
||||
@@ -14,6 +14,7 @@ import { useCommands } from "./lib/hooks/use-commands"
|
||||
import { useAppLifecycle } from "./lib/hooks/use-app-lifecycle"
|
||||
import { getLogger } from "./lib/logger"
|
||||
import { initReleaseNotifications } from "./stores/releases"
|
||||
import { runtimeEnv } from "./lib/runtime-env"
|
||||
import {
|
||||
hasInstances,
|
||||
isSelectingFolder,
|
||||
@@ -247,6 +248,28 @@ const App: Component = () => {
|
||||
getActiveSessionIdForInstance: activeSessionIdForInstance,
|
||||
})
|
||||
|
||||
// Listen for Tauri menu events
|
||||
onMount(() => {
|
||||
if (runtimeEnv.host === "tauri") {
|
||||
const tauriBridge = (window as { __TAURI__?: { event?: { listen: (event: string, handler: (event: { payload: unknown }) => void) => Promise<() => void> } } }).__TAURI__
|
||||
if (tauriBridge?.event) {
|
||||
let unlistenMenu: (() => void) | null = null
|
||||
|
||||
tauriBridge.event.listen("menu:newInstance", () => {
|
||||
handleNewInstanceRequest()
|
||||
}).then((unlisten) => {
|
||||
unlistenMenu = unlisten
|
||||
}).catch((error) => {
|
||||
log.error("Failed to listen for menu:newInstance event", error)
|
||||
})
|
||||
|
||||
onCleanup(() => {
|
||||
unlistenMenu?.()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<InstanceDisconnectedModal
|
||||
|
||||
Reference in New Issue
Block a user