feat(app): 支持设置 .md 默认打开方式(docs/32)

三条链路:①tauri.conf bundle.fileAssociations 注册 md/markdown,
新版安装包重装后出现在「打开方式」候选;②文件菜单「设为 .md
默认打开方式…」:Rust 命令经 reg.exe 写 HKCU 的 ProgID
NewMarkdown.md/OpenWithProgids/SupportedTypes(免管理员、指向
当前 exe),再打开系统默认应用设置让用户确认一次(Windows 不许
程序直接抢默认);③双击打开:单实例插件转发第二实例参数到待
打开队列+聚焦主窗口,冷启动读 env args,共用 md_files_from_args
过滤;前端 take_pending_open_files 取走逐个打开,只由 main 窗口
消费防子窗口抢文件。命令数 31→33 对账,参数过滤纯函数已抽 crate
实测,vitest 154+2、构建通过;Windows 构建与双击全流程待真机验。
This commit is contained in:
Muse
2026-11-15 13:57:31 +08:00
parent 492051cef0
commit c300b4c8db
10 changed files with 710 additions and 4 deletions

48
docs/32-md文件关联.md Normal file
View File

@@ -0,0 +1,48 @@
# docs/32 .md 文件关联(默认打开方式)
2026-11-15 用户要求:「支持设置 md 格式的打开方式」。目标:在资源
管理器双击 .md 能用本程序打开,且程序内能发起设置。三条链路:
## 1. 安装器注册(tauri.conf.json)
`bundle.fileAssociations` 增加 md/markdown(name=NewMarkdown,
role=Editor)。NSIS/MSI 安装时写入关联注册信息,本程序出现在
「打开方式」候选里,用户在打开方式对话框勾「始终」或在系统设置
里选一次即设为默认。注意:需用新版安装包**重装一次**才生效。
## 2. 程序内发起设置(文件菜单)
「文件 → 设为 .md 默认打开方式…」(仅桌面模式):Rust 命令
`register_file_association` 用 reg.exe 写当前用户注册表(免管理员):
ProgID `NewMarkdown.md`(类型名、打开命令 `"<exe>" "%1"`、图标)、
.md/.markdown 的 OpenWithProgids、Applications 的 SupportedTypes 与
打开命令——便携版/未走安装器的场景也能注册,且指向当前 exe 路径。
写完后打开 `ms-settings:defaultapps` 并弹窗说明:**Windows 不允许
程序直接抢占默认**(UserChoice 带哈希校验),最后一步必须由用户
在设置里把 .md 选为 new-markdown,只需一次。
## 3. 双击真正打开文件
- 单实例插件(tauri-plugin-single-instance,须最先注册):程序已
运行时双击第二个文件不再起新进程,第二实例的参数经回调转入
待打开队列并发 `pending-open-files` 事件,同时聚焦主窗口。
- 冷启动:setup 里读 `std::env::args`,与第二实例共用纯函数
`md_files_from_args` 过滤(跳过开关项、只收存在的 .md/.markdown),
存入 `PendingOpen` 队列。
- 前端:新命令 `take_pending_open_files` 取走队列并逐个 openPath。
主窗口在启动流程末尾拉一次(冷启动),并监听事件随时拉(热转
发)。**只由 label=main 的窗口消费**:子窗口(?file= 打开的)跑
同一套 App,不拦会把文件抢到子窗口里。
命令总数 31 → 33。
## 验证
- 参数过滤纯函数抽入独立 crate 实测:开关项/.txt/不存在的文件被
排除,.md 与 .markdown 存在文件入选。
- rustfmt 语法解析通过;命令数对账 33=33;tsc 0;vitest 全过
(InfoModal 新增 1 例);生产构建通过。
- 沙箱验不了(待真机):Windows 完整构建(含单实例插件与
cfg(windows) 的 reg.exe 分支)、安装包关联注册实效、双击冷启动
打开、已运行双击第二个文件转发到主窗口、菜单项注册后在系统
设置里选默认全流程。