Files
Genarrative/apps/desktop-shell/src-tauri/src/shell/menu.rs
T
kdletters ddfdc409f3 桌面壳补齐历史导航菜单
为桌面应用菜单增加后退和前进历史动作

补充桌面菜单测试与配置门禁

更新桌面壳菜单导航文档
2026-06-18 21:14:51 +08:00

200 lines
6.3 KiB
Rust

use crate::shell::tray::{reload_main_window, show_main_window};
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem, Submenu};
use tauri::Manager;
pub(crate) const DESKTOP_APP_MENU_SHOW: &str = "app-menu-show-main-window";
pub(crate) const DESKTOP_APP_MENU_BACK: &str = "app-menu-history-back";
pub(crate) const DESKTOP_APP_MENU_FORWARD: &str = "app-menu-history-forward";
pub(crate) const DESKTOP_APP_MENU_RELOAD: &str = "app-menu-reload-main-window";
pub(crate) const DESKTOP_APP_MENU_QUIT: &str = "app-menu-quit-desktop-shell";
pub(crate) const DESKTOP_HISTORY_BACK_SCRIPT: &str = "window.history.back(); true;";
pub(crate) const DESKTOP_HISTORY_FORWARD_SCRIPT: &str = "window.history.forward(); true;";
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum DesktopAppMenuAction {
ShowMainWindow,
GoBack,
GoForward,
ReloadMainWindow,
QuitApp,
Ignore,
}
pub(crate) fn resolve_desktop_app_menu_action(menu_id: &str) -> DesktopAppMenuAction {
match menu_id {
DESKTOP_APP_MENU_SHOW => DesktopAppMenuAction::ShowMainWindow,
DESKTOP_APP_MENU_BACK => DesktopAppMenuAction::GoBack,
DESKTOP_APP_MENU_FORWARD => DesktopAppMenuAction::GoForward,
DESKTOP_APP_MENU_RELOAD => DesktopAppMenuAction::ReloadMainWindow,
DESKTOP_APP_MENU_QUIT => DesktopAppMenuAction::QuitApp,
_ => DesktopAppMenuAction::Ignore,
}
}
fn eval_main_window_history_back(app: &tauri::AppHandle) -> tauri::Result<()> {
if let Some(window) = app.get_webview_window("main") {
window.eval(DESKTOP_HISTORY_BACK_SCRIPT)?;
}
Ok(())
}
fn eval_main_window_history_forward(app: &tauri::AppHandle) -> tauri::Result<()> {
if let Some(window) = app.get_webview_window("main") {
window.eval(DESKTOP_HISTORY_FORWARD_SCRIPT)?;
}
Ok(())
}
fn handle_desktop_app_menu_action(app: &tauri::AppHandle, action: DesktopAppMenuAction) {
match action {
DesktopAppMenuAction::ShowMainWindow => {
let _ = show_main_window(app);
}
DesktopAppMenuAction::GoBack => {
let _ = eval_main_window_history_back(app);
}
DesktopAppMenuAction::GoForward => {
let _ = eval_main_window_history_forward(app);
}
DesktopAppMenuAction::ReloadMainWindow => {
let _ = reload_main_window(app);
}
DesktopAppMenuAction::QuitApp => app.exit(0),
DesktopAppMenuAction::Ignore => {}
}
}
pub(crate) fn register_desktop_app_menu(app: &tauri::App) -> tauri::Result<()> {
let show_item =
MenuItem::with_id(app, DESKTOP_APP_MENU_SHOW, "显示主窗口", true, None::<&str>)?;
let back_item = MenuItem::with_id(app, DESKTOP_APP_MENU_BACK, "后退", true, Some("Alt+Left"))?;
let forward_item = MenuItem::with_id(
app,
DESKTOP_APP_MENU_FORWARD,
"前进",
true,
Some("Alt+Right"),
)?;
let reload_item = MenuItem::with_id(
app,
DESKTOP_APP_MENU_RELOAD,
"刷新",
true,
Some("CmdOrCtrl+R"),
)?;
let quit_item = MenuItem::with_id(
app,
DESKTOP_APP_MENU_QUIT,
"退出",
true,
Some("CmdOrCtrl+Q"),
)?;
let app_separator = PredefinedMenuItem::separator(app)?;
let app_menu = Submenu::with_items(
app,
"Genarrative",
true,
&[
&show_item,
&back_item,
&forward_item,
&reload_item,
&app_separator,
&quit_item,
],
)?;
let undo_item = PredefinedMenuItem::undo(app, Some("撤销"))?;
let redo_item = PredefinedMenuItem::redo(app, Some("重做"))?;
let edit_separator = PredefinedMenuItem::separator(app)?;
let cut_item = PredefinedMenuItem::cut(app, Some("剪切"))?;
let copy_item = PredefinedMenuItem::copy(app, Some("复制"))?;
let paste_item = PredefinedMenuItem::paste(app, Some("粘贴"))?;
let select_all_item = PredefinedMenuItem::select_all(app, Some("全选"))?;
let edit_menu = Submenu::with_items(
app,
"编辑",
true,
&[
&undo_item,
&redo_item,
&edit_separator,
&cut_item,
&copy_item,
&paste_item,
&select_all_item,
],
)?;
let minimize_item = PredefinedMenuItem::minimize(app, Some("最小化"))?;
let maximize_item = PredefinedMenuItem::maximize(app, Some("最大化"))?;
let window_separator = PredefinedMenuItem::separator(app)?;
let close_item = PredefinedMenuItem::close_window(app, Some("关闭窗口"))?;
let window_menu = Submenu::with_items(
app,
"窗口",
true,
&[
&minimize_item,
&maximize_item,
&window_separator,
&close_item,
],
)?;
app.set_menu(Menu::with_items(
app,
&[&app_menu, &edit_menu, &window_menu],
)?)?;
app.on_menu_event(|app, event| {
let menu_id = event.id().0.as_str();
handle_desktop_app_menu_action(app, resolve_desktop_app_menu_action(menu_id));
});
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn desktop_app_menu_ids_map_to_window_actions() {
assert_eq!(
resolve_desktop_app_menu_action(DESKTOP_APP_MENU_SHOW),
DesktopAppMenuAction::ShowMainWindow
);
assert_eq!(
resolve_desktop_app_menu_action(DESKTOP_APP_MENU_BACK),
DesktopAppMenuAction::GoBack
);
assert_eq!(
resolve_desktop_app_menu_action(DESKTOP_APP_MENU_FORWARD),
DesktopAppMenuAction::GoForward
);
assert_eq!(
resolve_desktop_app_menu_action(DESKTOP_APP_MENU_RELOAD),
DesktopAppMenuAction::ReloadMainWindow
);
assert_eq!(
resolve_desktop_app_menu_action(DESKTOP_APP_MENU_QUIT),
DesktopAppMenuAction::QuitApp
);
assert_eq!(
resolve_desktop_app_menu_action("unknown"),
DesktopAppMenuAction::Ignore
);
}
#[test]
fn desktop_app_menu_history_scripts_are_fixed_browser_history_calls() {
assert_eq!(DESKTOP_HISTORY_BACK_SCRIPT, "window.history.back(); true;");
assert_eq!(
DESKTOP_HISTORY_FORWARD_SCRIPT,
"window.history.forward(); true;"
);
}
}