fix(desktop): redirect menu bar events to window (#5200)

This commit is contained in:
Shreyas 2025-06-26 13:33:15 +05:30 committed by GitHub
parent b1d4ad2bf8
commit 224525be66
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 110 additions and 142 deletions

View file

@ -2,10 +2,8 @@ pub mod logger;
pub mod server;
pub mod updater;
use std::ops::Not;
use std::sync::OnceLock;
use tauri::menu::{MenuBuilder, MenuItemBuilder, SubmenuBuilder};
use tauri::{Emitter, Manager};
use tauri_plugin_appload::VendorConfigBuilder;
use tauri_plugin_deep_link::DeepLinkExt;
@ -23,144 +21,6 @@ fn hopp_auth_port() -> u16 {
pub fn run() {
tauri::Builder::default()
.setup(|app| {
let new_tab = MenuItemBuilder::with_id("new_tab", "New Tab")
.accelerator("CmdOrCtrl+T")
.build(app)
.expect("Failed to build new tab menu item");
let close_tab = MenuItemBuilder::with_id("close_tab", "Close Tab")
.accelerator("CmdOrCtrl+W")
.build(app)
.expect("Failed to build close tab menu item");
let reopen_tab = MenuItemBuilder::with_id("reopen_tab", "Reopen Closed Tab")
.accelerator("CmdOrCtrl+Shift+T")
.build(app)
.expect("Failed to build reopen tab menu item");
let file_menu = SubmenuBuilder::new(app, "File")
.item(&new_tab)
.item(&close_tab)
.item(&reopen_tab)
.build()
.expect("Failed to build file menu");
let focus_url = MenuItemBuilder::with_id("focus_url", "Focus Address Bar")
.accelerator("CmdOrCtrl+L")
.build(app)
.expect("Failed to build focus URL menu item");
let view_menu = SubmenuBuilder::new(app, "View")
.item(&focus_url)
.build()
.expect("Failed to build view menu");
let next_tab = MenuItemBuilder::with_id("next_tab", "Next Tab")
.accelerator("CmdOrCtrl+Alt+Right")
.build(app)
.expect("Failed to build next tab menu item");
let prev_tab = MenuItemBuilder::with_id("prev_tab", "Previous Tab")
.accelerator("CmdOrCtrl+Alt+Left")
.build(app)
.expect("Failed to build previous tab menu item");
let tab_first = MenuItemBuilder::with_id("tab_first", "Switch to First Tab")
.accelerator("CmdOrCtrl+Alt+9")
.build(app)
.expect("Failed to build first tab menu item");
let tab_last = MenuItemBuilder::with_id("tab_last", "Switch to Last Tab")
.accelerator("CmdOrCtrl+Alt+0")
.build(app)
.expect("Failed to build last tab menu item");
let tabs_menu = SubmenuBuilder::new(app, "Tabs")
.item(&next_tab)
.item(&prev_tab)
.separator()
.item(&tab_first)
.item(&tab_last)
.build()
.expect("Failed to build tabs menu");
let menu = MenuBuilder::new(app)
.item(&file_menu)
.item(&view_menu)
.item(&tabs_menu)
.build()
.expect("Failed to build menu");
app.set_menu(menu).expect("Failed to set menu");
let handle = app.handle().clone();
app.on_menu_event(move |app, event| {
let event_id = event.id().as_ref();
let webview_windows = app.webview_windows();
let perhaps_window = webview_windows
.iter()
// Any window that's not `main` since there can
// only be one window open at the moment.
//
// NOTE: Generally this should use `get_focused_window`
// but that requires `unstable` flag currently
// and causes arrow keys to insert escape sequences on MacOS
// see: https://github.com/hoppscotch/hoppscotch/pull/5108
.filter(|kv| kv.0.eq_ignore_ascii_case("main").not())
.last()
.map(|lw| lw.1);
if let Some(window) = perhaps_window {
let shortcut_event = match event_id {
"new_tab" => {
tracing::info!("New Tab menu item triggered (CMD+T/Ctrl+T)");
Some("ctrl-t")
}
"close_tab" => {
tracing::info!("Close Tab menu item triggered (CMD+W/Ctrl+W)");
Some("ctrl-w")
}
"reopen_tab" => {
tracing::info!(
"Reopen Tab menu item triggered (CMD+Shift+T/Ctrl+Shift+T)"
);
Some("ctrl-shift-t")
}
"next_tab" => {
tracing::info!("Next Tab menu item triggered (CMD+Alt+Right/Ctrl+Alt+Right)");
Some("ctrl-alt-right")
}
"prev_tab" => {
tracing::info!(
"Previous Tab menu item triggered (CMD+Alt+Left/Ctrl+Alt+Left)"
);
Some("ctrl-alt-left")
}
"tab_first" => {
tracing::info!("Switch to First Tab menu item triggered (CMD+Alt+9/Ctrl+Alt+9)");
Some("ctrl-alt-9")
}
"tab_last" => {
tracing::info!("Switch to Last Tab menu item triggered (CMD+Alt+0/Ctrl+Alt+0)");
Some("ctrl-alt-0")
}
_ => None,
};
if let Some(shortcut) = shortcut_event {
window
.emit("hoppscotch_desktop_shortcut", shortcut)
.unwrap_or_else(|e| {
tracing::error!(
error.message = %e,
shortcut = shortcut,
"Failed to emit shortcut event from menu"
);
});
}
}
});
let server_port = portpicker::pick_unused_port().expect("Cannot find unused port");
tracing::info!("Selected server port: {}", server_port);
SERVER_PORT
@ -168,10 +28,11 @@ pub fn run() {
.expect("Failed to set server port");
let port = *SERVER_PORT.get().expect("Server port not initialized");
tracing::info!(port = port, "Initializing server with pre-selected port");
let port = server::init(port, handle.clone());
let port = server::init(port, app.handle().clone());
tracing::info!(port = port, "Server initialization complete");
tracing::info!(app_name = %app.package_info().name, "Configuring deep link handler");
let handle = app.handle().clone();
app.deep_link().on_open_url(move |event| {
let urls = event.urls();
tracing::info!(

View file

@ -1,5 +1,6 @@
import { ref } from "vue"
import { listen } from "@tauri-apps/api/event"
import { listen, emit } from "@tauri-apps/api/event"
import { createHoppApp } from "@hoppscotch/common"
import { def as webAuth } from "@platform/auth/web"
@ -209,8 +210,114 @@ async function initApp() {
window.addEventListener(
"keydown",
function (e) {
// Prevent backspace navigation
// NOTE: Only for "non-text" inputs
if (e.key === "Backspace" && !isTextInput(e.target)) {
e.preventDefault()
return
}
const isCtrlOrCmd = e.ctrlKey || e.metaKey
let shortcutEvent: string | null = null
if (
isCtrlOrCmd &&
!e.shiftKey &&
!e.altKey &&
e.key.toLowerCase() === "t"
) {
// Ctrl/Cmd + T - New Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-t"
} else if (
isCtrlOrCmd &&
!e.shiftKey &&
!e.altKey &&
e.key.toLowerCase() === "w"
) {
// Ctrl/Cmd + W - Close Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-w"
} else if (
isCtrlOrCmd &&
e.shiftKey &&
!e.altKey &&
e.key.toLowerCase() === "t"
) {
// Ctrl/Cmd + Shift + T - Reopen Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-shift-t"
} else if (
isCtrlOrCmd &&
!e.shiftKey &&
e.altKey &&
e.key === "ArrowRight"
) {
// Ctrl/Cmd + Alt + Right - Next Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-alt-right"
} else if (
isCtrlOrCmd &&
!e.shiftKey &&
e.altKey &&
e.key === "ArrowLeft"
) {
// Ctrl/Cmd + Alt + Left - Previous Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-alt-left"
} else if (
isCtrlOrCmd &&
!e.shiftKey &&
e.altKey &&
(e.key === "9" || e.code === "Digit9")
) {
// Ctrl/Cmd + Alt + 9 - First Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-alt-9"
} else if (
isCtrlOrCmd &&
!e.shiftKey &&
e.altKey &&
(e.key === "0" || e.code === "Digit0")
) {
// Ctrl/Cmd + Alt + 0 - Last Tab
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "ctrl-alt-0"
} else if (
isCtrlOrCmd &&
!e.shiftKey &&
!e.altKey &&
e.key.toLowerCase() === "l"
) {
// Ctrl/Cmd + L - Focus Address Bar
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()
shortcutEvent = "focus-url"
}
if (shortcutEvent) {
setTimeout(() => {
emit("hoppscotch_desktop_shortcut", shortcutEvent).catch(
(error) => {
console.error("Failed to emit shortcut event:", error)
}
)
}, 0)
}
},
true