Skip to content

Commit 224525b

Browse files
fix(desktop): redirect menu bar events to window (hoppscotch#5200)
1 parent b1d4ad2 commit 224525b

File tree

2 files changed

+110
-142
lines changed
  • packages
    • hoppscotch-desktop/src-tauri/src
    • hoppscotch-selfhost-web/src

2 files changed

+110
-142
lines changed

packages/hoppscotch-desktop/src-tauri/src/lib.rs

Lines changed: 2 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ pub mod logger;
22
pub mod server;
33
pub mod updater;
44

5-
use std::ops::Not;
65
use std::sync::OnceLock;
76

8-
use tauri::menu::{MenuBuilder, MenuItemBuilder, SubmenuBuilder};
97
use tauri::{Emitter, Manager};
108
use tauri_plugin_appload::VendorConfigBuilder;
119
use tauri_plugin_deep_link::DeepLinkExt;
@@ -23,155 +21,18 @@ fn hopp_auth_port() -> u16 {
2321
pub fn run() {
2422
tauri::Builder::default()
2523
.setup(|app| {
26-
let new_tab = MenuItemBuilder::with_id("new_tab", "New Tab")
27-
.accelerator("CmdOrCtrl+T")
28-
.build(app)
29-
.expect("Failed to build new tab menu item");
30-
31-
let close_tab = MenuItemBuilder::with_id("close_tab", "Close Tab")
32-
.accelerator("CmdOrCtrl+W")
33-
.build(app)
34-
.expect("Failed to build close tab menu item");
35-
36-
let reopen_tab = MenuItemBuilder::with_id("reopen_tab", "Reopen Closed Tab")
37-
.accelerator("CmdOrCtrl+Shift+T")
38-
.build(app)
39-
.expect("Failed to build reopen tab menu item");
40-
41-
let file_menu = SubmenuBuilder::new(app, "File")
42-
.item(&new_tab)
43-
.item(&close_tab)
44-
.item(&reopen_tab)
45-
.build()
46-
.expect("Failed to build file menu");
47-
48-
let focus_url = MenuItemBuilder::with_id("focus_url", "Focus Address Bar")
49-
.accelerator("CmdOrCtrl+L")
50-
.build(app)
51-
.expect("Failed to build focus URL menu item");
52-
53-
let view_menu = SubmenuBuilder::new(app, "View")
54-
.item(&focus_url)
55-
.build()
56-
.expect("Failed to build view menu");
57-
58-
let next_tab = MenuItemBuilder::with_id("next_tab", "Next Tab")
59-
.accelerator("CmdOrCtrl+Alt+Right")
60-
.build(app)
61-
.expect("Failed to build next tab menu item");
62-
63-
let prev_tab = MenuItemBuilder::with_id("prev_tab", "Previous Tab")
64-
.accelerator("CmdOrCtrl+Alt+Left")
65-
.build(app)
66-
.expect("Failed to build previous tab menu item");
67-
68-
let tab_first = MenuItemBuilder::with_id("tab_first", "Switch to First Tab")
69-
.accelerator("CmdOrCtrl+Alt+9")
70-
.build(app)
71-
.expect("Failed to build first tab menu item");
72-
73-
let tab_last = MenuItemBuilder::with_id("tab_last", "Switch to Last Tab")
74-
.accelerator("CmdOrCtrl+Alt+0")
75-
.build(app)
76-
.expect("Failed to build last tab menu item");
77-
78-
let tabs_menu = SubmenuBuilder::new(app, "Tabs")
79-
.item(&next_tab)
80-
.item(&prev_tab)
81-
.separator()
82-
.item(&tab_first)
83-
.item(&tab_last)
84-
.build()
85-
.expect("Failed to build tabs menu");
86-
87-
let menu = MenuBuilder::new(app)
88-
.item(&file_menu)
89-
.item(&view_menu)
90-
.item(&tabs_menu)
91-
.build()
92-
.expect("Failed to build menu");
93-
94-
app.set_menu(menu).expect("Failed to set menu");
95-
96-
let handle = app.handle().clone();
97-
app.on_menu_event(move |app, event| {
98-
let event_id = event.id().as_ref();
99-
let webview_windows = app.webview_windows();
100-
let perhaps_window = webview_windows
101-
.iter()
102-
// Any window that's not `main` since there can
103-
// only be one window open at the moment.
104-
//
105-
// NOTE: Generally this should use `get_focused_window`
106-
// but that requires `unstable` flag currently
107-
// and causes arrow keys to insert escape sequences on MacOS
108-
// see: https://github.com/hoppscotch/hoppscotch/pull/5108
109-
.filter(|kv| kv.0.eq_ignore_ascii_case("main").not())
110-
.last()
111-
.map(|lw| lw.1);
112-
113-
if let Some(window) = perhaps_window {
114-
let shortcut_event = match event_id {
115-
"new_tab" => {
116-
tracing::info!("New Tab menu item triggered (CMD+T/Ctrl+T)");
117-
Some("ctrl-t")
118-
}
119-
"close_tab" => {
120-
tracing::info!("Close Tab menu item triggered (CMD+W/Ctrl+W)");
121-
Some("ctrl-w")
122-
}
123-
"reopen_tab" => {
124-
tracing::info!(
125-
"Reopen Tab menu item triggered (CMD+Shift+T/Ctrl+Shift+T)"
126-
);
127-
Some("ctrl-shift-t")
128-
}
129-
"next_tab" => {
130-
tracing::info!("Next Tab menu item triggered (CMD+Alt+Right/Ctrl+Alt+Right)");
131-
Some("ctrl-alt-right")
132-
}
133-
"prev_tab" => {
134-
tracing::info!(
135-
"Previous Tab menu item triggered (CMD+Alt+Left/Ctrl+Alt+Left)"
136-
);
137-
Some("ctrl-alt-left")
138-
}
139-
"tab_first" => {
140-
tracing::info!("Switch to First Tab menu item triggered (CMD+Alt+9/Ctrl+Alt+9)");
141-
Some("ctrl-alt-9")
142-
}
143-
"tab_last" => {
144-
tracing::info!("Switch to Last Tab menu item triggered (CMD+Alt+0/Ctrl+Alt+0)");
145-
Some("ctrl-alt-0")
146-
}
147-
_ => None,
148-
};
149-
150-
if let Some(shortcut) = shortcut_event {
151-
window
152-
.emit("hoppscotch_desktop_shortcut", shortcut)
153-
.unwrap_or_else(|e| {
154-
tracing::error!(
155-
error.message = %e,
156-
shortcut = shortcut,
157-
"Failed to emit shortcut event from menu"
158-
);
159-
});
160-
}
161-
}
162-
});
163-
16424
let server_port = portpicker::pick_unused_port().expect("Cannot find unused port");
16525
tracing::info!("Selected server port: {}", server_port);
16626
SERVER_PORT
16727
.set(server_port)
16828
.expect("Failed to set server port");
16929
let port = *SERVER_PORT.get().expect("Server port not initialized");
17030
tracing::info!(port = port, "Initializing server with pre-selected port");
171-
let port = server::init(port, handle.clone());
31+
let port = server::init(port, app.handle().clone());
17232
tracing::info!(port = port, "Server initialization complete");
17333

17434
tracing::info!(app_name = %app.package_info().name, "Configuring deep link handler");
35+
let handle = app.handle().clone();
17536
app.deep_link().on_open_url(move |event| {
17637
let urls = event.urls();
17738
tracing::info!(

packages/hoppscotch-selfhost-web/src/main.ts

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ref } from "vue"
2-
import { listen } from "@tauri-apps/api/event"
2+
import { listen, emit } from "@tauri-apps/api/event"
3+
34
import { createHoppApp } from "@hoppscotch/common"
45

56
import { def as webAuth } from "@platform/auth/web"
@@ -209,8 +210,114 @@ async function initApp() {
209210
window.addEventListener(
210211
"keydown",
211212
function (e) {
213+
// Prevent backspace navigation
214+
// NOTE: Only for "non-text" inputs
212215
if (e.key === "Backspace" && !isTextInput(e.target)) {
213216
e.preventDefault()
217+
return
218+
}
219+
220+
const isCtrlOrCmd = e.ctrlKey || e.metaKey
221+
let shortcutEvent: string | null = null
222+
223+
if (
224+
isCtrlOrCmd &&
225+
!e.shiftKey &&
226+
!e.altKey &&
227+
e.key.toLowerCase() === "t"
228+
) {
229+
// Ctrl/Cmd + T - New Tab
230+
e.preventDefault()
231+
e.stopPropagation()
232+
e.stopImmediatePropagation()
233+
shortcutEvent = "ctrl-t"
234+
} else if (
235+
isCtrlOrCmd &&
236+
!e.shiftKey &&
237+
!e.altKey &&
238+
e.key.toLowerCase() === "w"
239+
) {
240+
// Ctrl/Cmd + W - Close Tab
241+
e.preventDefault()
242+
e.stopPropagation()
243+
e.stopImmediatePropagation()
244+
shortcutEvent = "ctrl-w"
245+
} else if (
246+
isCtrlOrCmd &&
247+
e.shiftKey &&
248+
!e.altKey &&
249+
e.key.toLowerCase() === "t"
250+
) {
251+
// Ctrl/Cmd + Shift + T - Reopen Tab
252+
e.preventDefault()
253+
e.stopPropagation()
254+
e.stopImmediatePropagation()
255+
shortcutEvent = "ctrl-shift-t"
256+
} else if (
257+
isCtrlOrCmd &&
258+
!e.shiftKey &&
259+
e.altKey &&
260+
e.key === "ArrowRight"
261+
) {
262+
// Ctrl/Cmd + Alt + Right - Next Tab
263+
e.preventDefault()
264+
e.stopPropagation()
265+
e.stopImmediatePropagation()
266+
shortcutEvent = "ctrl-alt-right"
267+
} else if (
268+
isCtrlOrCmd &&
269+
!e.shiftKey &&
270+
e.altKey &&
271+
e.key === "ArrowLeft"
272+
) {
273+
// Ctrl/Cmd + Alt + Left - Previous Tab
274+
e.preventDefault()
275+
e.stopPropagation()
276+
e.stopImmediatePropagation()
277+
shortcutEvent = "ctrl-alt-left"
278+
} else if (
279+
isCtrlOrCmd &&
280+
!e.shiftKey &&
281+
e.altKey &&
282+
(e.key === "9" || e.code === "Digit9")
283+
) {
284+
// Ctrl/Cmd + Alt + 9 - First Tab
285+
e.preventDefault()
286+
e.stopPropagation()
287+
e.stopImmediatePropagation()
288+
shortcutEvent = "ctrl-alt-9"
289+
} else if (
290+
isCtrlOrCmd &&
291+
!e.shiftKey &&
292+
e.altKey &&
293+
(e.key === "0" || e.code === "Digit0")
294+
) {
295+
// Ctrl/Cmd + Alt + 0 - Last Tab
296+
e.preventDefault()
297+
e.stopPropagation()
298+
e.stopImmediatePropagation()
299+
shortcutEvent = "ctrl-alt-0"
300+
} else if (
301+
isCtrlOrCmd &&
302+
!e.shiftKey &&
303+
!e.altKey &&
304+
e.key.toLowerCase() === "l"
305+
) {
306+
// Ctrl/Cmd + L - Focus Address Bar
307+
e.preventDefault()
308+
e.stopPropagation()
309+
e.stopImmediatePropagation()
310+
shortcutEvent = "focus-url"
311+
}
312+
313+
if (shortcutEvent) {
314+
setTimeout(() => {
315+
emit("hoppscotch_desktop_shortcut", shortcutEvent).catch(
316+
(error) => {
317+
console.error("Failed to emit shortcut event:", error)
318+
}
319+
)
320+
}, 0)
214321
}
215322
},
216323
true

0 commit comments

Comments
 (0)