Skip to content

feat(tray): 关闭按钮询问「最小化到托盘 / 退出应用」,并修复 Windows 重复启动 - #228

Merged
feigeCode merged 4 commits into
mainfrom
dev
Sep 18, 2026
Merged

feigeCode merged 4 commits into
mainfrom
dev

Conversation

@feigeCode

Copy link
Copy Markdown
Owner

概要

devmain,含 2 个提交:

提交 内容
bd34cc464 feat(tray): 关闭按钮询问「最小化到托盘 / 退出应用」,并修复 Windows 重复启动
ec34181bc test(extensions): 扩展守卫覆盖 rocketmq 新页与相邻仓清单 schema

关闭行为:从「托盘可用就隐藏」改成先看用户偏好

  1. 新增 AppSettings.close_button_behaviorask / minimize_to_tray / quit,默认 ask,未知值回退 ask)。
    main_window_close_action(tray_ready, behavior) 纯策略三态:托盘不可用一律 RequestQuit,不与偏好互动 —— 宁可退出,也不能制造用户找不到、也没法恢复的隐藏窗口。
  2. AskUser 弹窗的两条出路各自渲染按钮(tray-close-minimize / tray-close-quit),带「记住我的选择」,勾选后落盘。
    刻意不用默认 ok/cancel footer:默认 footer 只有两个固定按钮,「取消」兼职退出会让 Esc 和点遮罩也走成退出应用;而 button_props 跟在 confirm 之后设置还会把 show_cancel 重置、吞掉第二个按钮(前一版就是这么丢的)。
  3. 「记住」勾选框放在独立 entity:弹窗 body 由 Root 渲染,NavopApp::notify 重绘不到它。close_choice_prompt_open 防连点叠窗,关窗复位。
  4. 设置页「通用 → 关闭窗口行为」新增下拉,与弹窗写同一份偏好;托盘不可用时该设置不生效。

Windows 单实例修复

interprocess 的命名管道带 FILE_FLAG_FIRST_PIPE_INSTANCE,名字已存在时返回 ERROR_ACCESS_DENIED(5) 而非 AddrInUse,且错误原样透传、无 error kind 归一化,旧判定永不命中 ⇒ 第二个实例把自己当主实例、起出完整进程。
改为 instance_name_taken()AddrInUseraw_os_error ∈ {5, 231},其余错误(如 PermissionDenied)不误判为「已占用」。

验证

  • cargo test -p one-core --lib settings — 112 passed
  • cargo test -p main — 634 passed
  • cargo check -p main --all-targets
  • cargo clippy -p main --all-targets — 改动文件零告警
  • rustfmt --edition 2024 <改动文件> 已跑

待人工确认

  • Windows 真机:重复双击只保留一个实例,第二个进程把启动请求转发给已有实例。
  • 弹窗交互(两条出路按钮、记住勾选、Esc / 点遮罩不触发退出)与设置页下拉需跑一次真实 UI。

feigeCode and others added 4 commits September 18, 2026 12:54
`extension_pages_render_tests` 原本只覆盖 mqtt/docker/dev-tools 的六个页。本次:

1. `MIGRATED_PAGES` 补上 rocketmq 的三张 shell 页(`overview` / `messages` /
   `send-message`),并把 `send-message` 的期望从只有 `Input` 扩到
   `Input` + `Select` + `Textarea`。
2. 新增 `PLACEHOLDER_TEXT`(`undefined` / `NaN` / `[object Object]`)断言:渲染树里
   出现这些字样就是模板漏了字段兜底。这类 bug **不会**让 `build_error` 报出来,
   节点名断言也照过 —— 加这条之前,rocketmq 消息页表头一直印的是"共 undefined 条"
   (`run()` 写 `this.returned`、表头读 `this.total`)而守卫全绿。
3. 新增 `extension_manifests_load_against_this_host`:用宿主自己的
   `extension_runtime::extension::manifest::load_from_dir` 解析相邻仓
   docker/mqtt/rocketmq/elasticsearch 的 `extension.json`。这是唯一挡得住
   `deny_unknown_fields` 解析期失败的闸门 —— 相邻仓的 `tests/scripts.test.mjs` 只读
   `ui/*.js`,`scripts/verify-composite-package.sh` 的校验清单里根本没有
   `contributes.resourceWorkbenches`。清单字段名写错的表现是"整个扩展消失"而不是报错,
   所以在宿主侧过一遍 schema 值这个价。

两条守卫都做了变异验证(不是只看绿):
- 把消息页表头改回 `共 ${this.total} 条` ⇒ 精确报出
  `rocketmq/ui/messages.js: 渲染树里出现了 \`undefined\``,FAILED。
- 把清单的 `schemaVersion` 改名成 `schemaVersions` ⇒ 精确报出
  `unknown field \`schemaVersions\`, expected one of \`schemaVersion\`, \`id\`, ...`,FAILED。

运行:`cargo test -p universal-plugins --features shell-plugins -- extension_`(25 passed)。
关闭行为从「托盘可用就隐藏」改成先看用户偏好:

1. 新增 `AppSettings.close_button_behavior`(`ask` / `minimize_to_tray` / `quit`,
   默认 `ask`,未知值回退 `ask`),`main_window_close_action(tray_ready, behavior)`
   纯策略三态:托盘不可用一律 `RequestQuit`,不与偏好互动 —— 宁可退出也不能
   制造用户找不到、也没法恢复的隐藏窗口。
2. `AskUser` 弹窗的两条出路各自渲染按钮(`tray-close-minimize` / `tray-close-quit`),
   带「记住我的选择」,勾选后落盘。刻意不用默认 ok/cancel footer:默认 footer
   只有两个固定按钮,「取消」兼职退出会让 Esc 和点遮罩也走成退出应用;而
   `button_props` 跟在 `confirm` 之后设置还会把 `show_cancel` 重置、吞掉第二个
   按钮(前一版就是这么丢的)。
3. 「记住」勾选框放在独立 entity:弹窗 body 由 `Root` 渲染,`NavopApp::notify`
   重绘不到它。`close_choice_prompt_open` 防连点叠窗,关窗复位。
4. 设置页通用页新增「关闭窗口行为」下拉,与弹窗写同一份偏好;托盘不可用时
   该设置不生效。

Windows 单实例:interprocess 的命名管道带 `FILE_FLAG_FIRST_PIPE_INSTANCE`,名字
已存在时返回 `ERROR_ACCESS_DENIED(5)` 而非 `AddrInUse`,且错误原样透传、无 error
kind 归一化,旧判定永不命中 ⇒ 第二个实例把自己当主实例、起出完整进程。改为
`instance_name_taken()` 认 `AddrInUse` 或 `raw_os_error` ∈ {5, 231},其余错误不
误判为「已占用」。

运行:`cargo test -p one-core --lib settings`(112 passed)、`cargo test -p main`
(634 passed);`cargo check -p main --all-targets`、`cargo clippy -p main
--all-targets`(改动文件零告警)通过。Windows 重复启动与弹窗交互仍需真机冒烟。
带上 gpui_linux 的 XIM 握手 guard 修复(navop#223):握手完成前不再
发送 im_id=0 的 CreateIc/SetIcValues,避免 fcitx5 回零 body Error 帧
导致 XIM 被永久禁用。

zed@fec06ca3b3 → gpui-pre fork-0.3.109 @ 94b529e385
@feigeCode
feigeCode merged commit 9c572fa into main Sep 18, 2026
5 checks passed
feigeCode added a commit to paofu-cium/navop that referenced this pull request Sep 19, 2026
解决与 PR feigeCode#228(feat(tray): 关闭按钮询问「最小化到托盘 / 退出应用」,并修复
Windows 重复启动)的冲突,让本 PR 重新可合。

- main/src/windows_single_instance.rs:采用 PR 侧重写(SingleInstanceError 枚举、
  worker + 决策通道、Claim/ForwardAttempt、create_pipe_instance)。main 侧
  bd34cc4 新增的 instance_name_taken 语义已由 PR 的 is_name_in_use(Windows 专用,
  认 ERROR_ACCESS_DENIED=5)与 is_connect_retryable(认 2/231/5)覆盖;其被自动合并
  保留在非冲突区的定义一并删除,否则留下 3 个 dead_code 警告
- Cargo.lock:按合并后的 Cargo.toml 由 cargo 同步(保留 main 侧新增依赖,
  去掉 PR 已移除的 interprocess)
- main/src/main.rs、main/Cargo.toml:自动合并无冲突

验证:cargo check -p main --all-targets(0 警告)、cargo test -p main --bin navop
(634 passed, 0 failed)。Windows 侧属 CI 覆盖范围(本机无 MSVC 工具链,跨编译
在 libz-sys 处止步)。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant