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, ©_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;" ); } }