桌面壳补齐历史导航菜单

为桌面应用菜单增加后退和前进历史动作

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

更新桌面壳菜单导航文档
This commit is contained in:
2026-06-18 21:14:51 +08:00
parent 106798f505
commit ddfdc409f3
4 changed files with 74 additions and 3 deletions
@@ -1107,8 +1107,16 @@ const requiredRustHostSnippets = [
'tauri_plugin_clipboard_manager::init()',
'register_desktop_app_menu(app)?',
'DESKTOP_APP_MENU_SHOW',
'DESKTOP_APP_MENU_BACK',
'DESKTOP_APP_MENU_FORWARD',
'DESKTOP_APP_MENU_RELOAD',
'DESKTOP_APP_MENU_QUIT',
'DesktopAppMenuAction::GoBack',
'DesktopAppMenuAction::GoForward',
'DESKTOP_HISTORY_BACK_SCRIPT',
'DESKTOP_HISTORY_FORWARD_SCRIPT',
'window.history.back(); true;',
'window.history.forward(); true;',
'resolve_desktop_app_menu_action',
'app.set_menu',
'app.on_menu_event',
+64 -1
View File
@@ -1,13 +1,20 @@
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,
@@ -16,17 +23,41 @@ pub(crate) enum DesktopAppMenuAction {
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);
}
@@ -38,6 +69,14 @@ fn handle_desktop_app_menu_action(app: &tauri::AppHandle, action: DesktopAppMenu
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,
@@ -57,7 +96,14 @@ pub(crate) fn register_desktop_app_menu(app: &tauri::App) -> tauri::Result<()> {
app,
"Genarrative",
true,
&[&show_item, &reload_item, &app_separator, &quit_item],
&[
&show_item,
&back_item,
&forward_item,
&reload_item,
&app_separator,
&quit_item,
],
)?;
let undo_item = PredefinedMenuItem::undo(app, Some("撤销"))?;
@@ -120,6 +166,14 @@ mod tests {
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
@@ -133,4 +187,13 @@ mod tests {
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;"
);
}
}
@@ -2506,7 +2506,7 @@
## 2026-06-18 桌面壳应用菜单
- 背景:桌面壳方案要求 Tauri 承接系统菜单,但当前桌面壳只有系统托盘菜单和 HostBridge 受控能力;可分发桌面包缺少常规应用菜单会让刷新、退出、系统编辑和窗口操作只能依赖 WebView 或托盘。
- 决策:新增 `apps/desktop-shell/src-tauri/src/shell/menu.rs` 注册 Tauri 应用菜单。应用菜单只复用宿主壳级显示主窗口、刷新主窗口和退出应用动作;编辑菜单和窗口菜单使用 Tauri 原生预定义项承接剪切、复制、粘贴、全选、最小化、最大化和关闭窗口。该能力不进入 HostBridge capability,不开放菜单 API、shell API 或任意窗口控制给 H5;菜单注册失败直接阻断启动,避免生产桌面壳缺少系统菜单仍静默运行。
- 决策:新增 `apps/desktop-shell/src-tauri/src/shell/menu.rs` 注册 Tauri 应用菜单。应用菜单只复用宿主壳级显示主窗口、后退、前进、刷新主窗口和退出应用动作;后退 / 前进只执行固定 `window.history.back(); true;``window.history.forward(); true;`,无历史记录时按浏览器 no-op 处理,不新增 HostBridge method,也不接收 H5 payload 或任意脚本;编辑菜单和窗口菜单使用 Tauri 原生预定义项承接剪切、复制、粘贴、全选、最小化、最大化和关闭窗口。该能力不进入 HostBridge capability,不开放菜单 API、shell API 或任意窗口控制给 H5;菜单注册失败直接阻断启动,避免生产桌面壳缺少系统菜单仍静默运行。
- 影响范围:`apps/desktop-shell/src-tauri/src/main.rs``apps/desktop-shell/src-tauri/src/shell/menu.rs``apps/desktop-shell/src-tauri/src/shell/tray.rs``apps/desktop-shell/scripts/check-config.mjs``scripts/check-native-shells.mjs`、Expo / Tauri HostBridge 方案文档。
- 验证方式:`npm run desktop-shell:typecheck``npm run desktop-shell:test``npm run desktop-shell:build -- --no-bundle``npm run check:native-shells``npm run typecheck -- --pretty false``npm run check:encoding``git diff --check`
@@ -356,7 +356,7 @@ GameBridge 禁止:
2026-06-18 追加:桌面壳启用 Tauri 真实系统托盘,并复用品牌图标。托盘菜单只提供宿主壳级动作:显示主窗口、刷新主窗口和退出应用;左键点击托盘图标恢复并聚焦主窗口。该能力不进入 HostBridge capability 清单,不向 H5 暴露托盘 API、菜单 API、shell API 或任意窗口控制;如果当前桌面环境无法注册托盘,壳会继续启动主窗口。托盘注册成功时,用户点击主窗口关闭按钮会隐藏到托盘,必须通过托盘“退出”动作结束应用;托盘注册失败时不拦截关闭,避免窗口消失后没有恢复入口。
2026-06-18 追加:桌面壳启用 Tauri 应用菜单。`shell/menu.rs` 注册应用菜单、编辑菜单和窗口菜单,其中应用菜单只复用宿主壳级动作:显示主窗口、刷新主窗口和退出应用;编辑 / 窗口项使用 Tauri 原生预定义菜单项承接系统剪切、复制、粘贴、全选、最小化、最大化和关闭窗口。该能力不进入 HostBridge capability,不向 H5 暴露菜单 API、shell API 或任意窗口控制;应用菜单注册失败视为桌面壳启动失败,避免可分发桌面包缺少系统菜单仍静默运行。
2026-06-18 追加:桌面壳启用 Tauri 应用菜单。`shell/menu.rs` 注册应用菜单、编辑菜单和窗口菜单,其中应用菜单只复用宿主壳级动作:显示主窗口、后退、前进、刷新主窗口和退出应用;后退 / 前进只执行固定 `window.history.back(); true;``window.history.forward(); true;`,无历史记录时按浏览器 no-op 处理,不新增 HostBridge method,也不接收 H5 payload 或任意脚本;编辑 / 窗口项使用 Tauri 原生预定义菜单项承接系统剪切、复制、粘贴、全选、最小化、最大化和关闭窗口。该能力不进入 HostBridge capability,不向 H5 暴露菜单 API、shell API 或任意窗口控制;应用菜单注册失败视为桌面壳启动失败,避免可分发桌面包缺少系统菜单仍静默运行。
2026-06-18 追加:桌面壳启用 Tauri 单实例。用户重复启动桌面 App 时,新实例会退出并唤醒已有主窗口;该回调只执行显示、取消最小化和聚焦主窗口,不把第二实例的命令行参数或工作目录作为事件透传给 H5。Windows / Linux 上由单实例插件的 `deep-link` feature 把二次实例 URL 交给 deep-link 插件,仍由 `shell/deep_link.rs` 做受控归一。