fix local office resource editing
- add local-folder OnlyOffice sign/callback writeback and edit-tab handling - align main resource tabs, attachment edit menu, slash isolation, and filetree context behavior - record Sidex/Hermes gap reviews and Reasonix task checklists
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
# Checklist: Local Folder Page Trash And Empty Workspace
|
||||
|
||||
## 目标
|
||||
|
||||
- 修复删除页面后进入资源垃圾箱的问题。
|
||||
- 停止自动生成“初始化的新页面”。
|
||||
- 空白本地工作区保持空白,不创建占位页面。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/local_folder_source.rs`
|
||||
- 必要时 `rust/crates/mnote-web/src/routes/gateway.rs` 中 trash 渲染分类逻辑
|
||||
- 相关 Rust 单测与 smoke
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不删除用户真实文件。
|
||||
- 不回滚 ACP/Hermes 相关改动。
|
||||
- 不改旧 React 回收区。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] 移除默认工作区创建“初始化的新页面”的运行时行为。
|
||||
- [x] 更新旧断言:默认 workspace 只创建 `.mnote` 元数据,不创建默认页面目录。
|
||||
- [x] 对页面 bundle 目录删除进行页面生命周期识别:若目录内存在同名 `.md`,删除应走 `trash_local_markdown_page`。
|
||||
- [x] trash index 中页面记录应可被页面垃圾箱识别,不再作为 `local_directory` 资源统计。
|
||||
- [x] 空 page tree / file tree 不渲染“初始化的新页面”。
|
||||
- [x] 补充或更新 targeted tests。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 代码:`local_folder_source.rs` 移除默认首页创建,并让 `local-dir:*` 页面 bundle 删除转入 `markdown_bundle` 页面垃圾箱。
|
||||
- 新增测试:`local_tree_command_delete_page_bundle_directory_uses_page_trash`。
|
||||
- 浏览器验证:`tmp/bug-20260521-workbench-browser-verify/result-trash.json`,截图 `06-page-bundle-trash-classification.png`。
|
||||
- 说明:`task432-filetree-trash-page-dual-browser-no-refresh-smoke` 当前失败在 convex-source 双浏览器实时 delta 未插入新建子页,不是本地页面 bundle 垃圾箱分类失败;后续应按实时同步历史 smoke 单独处理或退役。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web local_tree_command_manages_loose_markdown_like_regular_file -- --test-threads=1
|
||||
cargo test -p mnote-web local_tree_command_delete_folder_moves_directory_to_trash -- --test-threads=1
|
||||
cargo test -p mnote-web create_default_local_workspace_for_actor_at_base_creates_manifest_and_root_only -- --test-threads=1
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
# Tab / Office / Upload Browser Bugs Review V1
|
||||
|
||||
日期:2026-05-21
|
||||
|
||||
## 范围
|
||||
|
||||
本轮覆盖用户继续反馈的 4 类缺陷:
|
||||
|
||||
1. 主 resource tab 激活后,点击左侧主 Markdown 文件或新建页面,不能切回主 Markdown page tab。
|
||||
2. 左侧新建页面后,文件树焦点/选中没有落到新建页面。
|
||||
3. 真实中文名 docx 上传后仍打不开:`/home/lix/Downloads/重庆发展特殊化妆品可行性报告_政府汇报版.docx`。
|
||||
4. 上传文件偶发浏览器卡死,刷新无效但文件实际已上传;怀疑中文文件名、中文符号、Office 打开链路或上传后插入编辑器引发卡住。
|
||||
|
||||
## 当前初步判断
|
||||
|
||||
- `navigateToDocument` 在当前文档 ID 相同的路径上只更新树行状态,不会调用 resource tab runtime 切回 page tab。因此当前 page 已经是同一 Markdown 时,点击左侧文件树会停留在 resource tab。
|
||||
- `openPrimaryDocument` 替换 primary pane 后未显式调用 `activateMainEditorTab('')`,从 resource tab 导航到其他 Markdown 页面时也可能仍显示 resource host。
|
||||
- `createPage` 创建成功后直接 `navigateToDocument`,没有等待 local folder projection 刷新,也没有把 filetree selection state 的 `selectedRowIds/focusedRowId` 指向新页面。
|
||||
- 上传 Office 附件后 `insertUploadedAssetIntoEditor` 会同步构造 OnlyOffice 链接并拉取 `whoami`,若 DocumentServer 或 iframe 链路异常,当前需要确认是否只是打开失败,还是上传后插入/刷新/资源行追加链路导致页面失去响应。
|
||||
- 之前浏览器测试只验证到 `/onlyoffice` iframe URL 和 resource tab 状态,未完整验证 DocumentServer 内部是否报 `errorCode=-18`;本轮需要抓 iframe/console/network 证据。
|
||||
|
||||
## 修改策略
|
||||
|
||||
- Tab 切回:
|
||||
- 在 document pane runtime 暴露 `activatePageTab()`。
|
||||
- `openPrimaryDocument` 成功后强制切回 page tab。
|
||||
- `navigateToDocument` 的 same-document fast path 也调用 `activatePageTab()`,解决“点击当前主 md 不能从 resource tab 切回”。
|
||||
- 新建页焦点:
|
||||
- 增加 filetree 选择 helper,按 documentId 选中并聚焦 `doc:{documentId}` 行。
|
||||
- `createPage` 在 local_folder 下先刷新 sidebar projection,再选中新页面,再导航。
|
||||
- document pane primary 切换后派发 `mnote:primary-document-activated`,由 sidebar runtime 同步 selection state。
|
||||
- Office / 上传:
|
||||
- 用真实中文 docx 做浏览器测试,记录上传 API、resource tab、iframe src、OnlyOffice 页面错误。
|
||||
- 若出现卡死,优先让上传链路避免等待非关键插入/打开操作;上传完成后 UI 不应被 OnlyOffice whoami/iframe 初始化阻塞。
|
||||
- 需要区分“DocumentServer 内部连接失败”和“MNote 浏览器卡死”两类问题,不混为同一个修复。
|
||||
- Reasonix 测试流程:
|
||||
- 新增 `/home/lix/.codex/skills/reasonix-browser-tester/SKILL.md`。
|
||||
- 本轮派发 Reasonix 独立浏览器测试任务,Codex 只复核其 `result.json` 和截图。
|
||||
|
||||
## 不做事项
|
||||
|
||||
- 不回滚现有 ACP/Hermes 改动。
|
||||
- 不把 Office 改成下载兜底作为唯一行为。
|
||||
- 不把 Reasonix 测试结论当成事实源;必须复核截图和结构化日志。
|
||||
- 不清理用户已有上传文件或真实工作区文件。
|
||||
|
||||
## 验收
|
||||
|
||||
- 点击 page tab / 左侧当前 Markdown / 左侧其他 Markdown,都能从 resource tab 回到主 Markdown page tab。
|
||||
- 左侧新建页面后,URL、page tab 标题、filetree `data-selected`、`data-focused` 指向新页面。
|
||||
- 上传指定中文 docx 后浏览器不应卡死;resource tab 有明确打开状态或错误状态;刷新后不应要求重新登录才能恢复。
|
||||
- Reasonix 输出独立浏览器测试证据,Codex 与本地验证对照。
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
# Workbench Filetree / Office / Slash Bug Review V1
|
||||
|
||||
日期:2026-05-21
|
||||
|
||||
## 范围
|
||||
|
||||
本轮覆盖用户截图 23-26 中的 6 个 P0/P1 缺陷:
|
||||
|
||||
1. 文件树删除页面后,页面进入资源垃圾箱,页面垃圾箱没有使用。
|
||||
2. 主编辑区 tab 标题与实际打开页面标题不一致。
|
||||
3. 上传 docx 后页面卡死,docx 打不开。
|
||||
4. 不应自动出现“初始化的新页面”;空白工作区应保持空白。
|
||||
5. 文件树右键菜单大量动作不可用,需对照 Sidex / VSCode 文件资源管理器收敛到可用动作。
|
||||
6. 主栏打开 slash 菜单时,侧栏也出现 slash 菜单。
|
||||
|
||||
## 当前证据
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/local_folder_source.rs`
|
||||
- `ensure_default_workspace_home_page` 会创建 `初始化的新页面/初始化的新页面.md`。
|
||||
- `create_default_local_workspace_for_actor_at_base_creates_manifest_and_root_only` 仍断言该默认页面存在。
|
||||
- `trash_local_entry` 先解析 `local-dir:*`,再解析 `local-file:*`,最后才走 `trash_local_markdown_page`。
|
||||
- 文件树中页面 bundle 目录在 `scan_directory` 中是 `rowKind=folder`,因此删除会走 `trash_local_directory`,`resourceKind=local_directory`。
|
||||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||||
- `replacePaneDocument` / `updatePaneChrome` 会更新正文、面包屑、`document.title`,但没有同步 `[data-mnote-main-tab="page"] .mnote-main-tab-title`。
|
||||
- `openUnsupportedSideTarget` 会替换 secondary root 为不支持占位;`positionSlashMenuForRoot` 仍允许 fallback 到 `document.querySelector('[data-testid="mnote-leptos-tiptap-slash-menu"]')`,存在跨 pane 定位/展示风险。
|
||||
- `openResourceAsSideTarget` 对 markdown/text/code/office 全部进入 unsupported,占位会污染侧栏;这与用户期望“不可用动作不要误打开侧栏”冲突。
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- 文件树右键菜单直接展示 `open-right / new-file / new-folder / paste / refresh / collapse / reveal / duplicate / rename / delete`,其中部分 disabled 或仅 dispatch event,无真实实现。
|
||||
- `openConvexAssetFromFileTree` 对 local office 可走主 tab 的 iframe,但 Convex office 仍直接 `window.open(buildOnlyOfficeOpenUrl(...))`。
|
||||
- 附件上传 `insertUploadedAssetIntoEditor` 和 `enhanceEditorAttachmentLink` 已尝试统一附件 UI;docx 卡死需要先确认是上传阶段阻塞、OnlyOffice iframe 回源失败,还是 active-tab iframe 加载导致主页面阻塞。
|
||||
- Sidex / VSCode 参考:
|
||||
- Sidex 保留 VSCode 的 `MenuId.ExplorerContext` 菜单体系,文件树动作来源在 `reference-code/sidex-main/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts`。
|
||||
- 可对照的基础动作是 Open to the Side、New File、New Folder、Reveal、Copy Path、Rename、Delete;动作是否显示/启用由 context key 决定,不是把所有潜在动作硬塞进菜单。
|
||||
- Sidex workspace 层有 `FileClipboard`、`InlineInputKind::{Rename, NewFile, NewFolder}` 等状态,说明新建/重命名应走内联输入或明确命令,而不是菜单项只发事件。
|
||||
|
||||
## 修改策略
|
||||
|
||||
- Bug1 / Bug4 属于本地文件夹 tree/source 口径问题,优先修 Rust kernel-facing 路径:
|
||||
- 默认工作区不再创建“初始化的新页面”。
|
||||
- bundle 页面删除必须以 Markdown 页面生命周期入 trash,页面垃圾箱可识别,不应按 `local_directory` 资源归类。
|
||||
- 空 root page tree 可返回空列表;UI 不渲染占位页面。
|
||||
- Bug2 属于主编辑区 tab chrome 同步:
|
||||
- `updatePaneChrome(primary)` 同步 page tab 标题、`data-document-id` 和 active 状态。
|
||||
- 页面标题保存事件也应更新 page tab。
|
||||
- Bug3 属于 Office 打开链路:
|
||||
- 上传本地 docx 后,主 tab 打开应使用 `/onlyoffice?...fileUrl=/api/local-folder/files/open...`,并避免在主线程同步读取/解析大文件。
|
||||
- 如果 OnlyOffice DocumentServer 不可连,应显示非阻塞错误,不应卡死整个页面。
|
||||
- Bug5 属于菜单可用性:
|
||||
- 菜单只显示/启用已有真实实现。
|
||||
- “在右侧边栏打开”只对已支持侧栏打开的页面显示;资源侧栏未支持时不要打开 unsupported placeholder。
|
||||
- `Copy Path` 对 local folder 应复制真实 relative path,不是复制标题。
|
||||
- New Folder 在 local_folder 下应接入 `create_folder`,否则隐藏。
|
||||
- Bug6 属于 editor host 隔离:
|
||||
- Slash 菜单定位只能操作当前 root 内的菜单,不能 fallback 到别的 pane 的菜单。
|
||||
- 不支持侧栏资源时应清理 secondary editor/slash overlay,或完全不打开侧栏。
|
||||
|
||||
## 不做事项
|
||||
|
||||
- 不回滚当前工作区已有 ACP/Hermes 改动。
|
||||
- 不把资源 tab、side pane、OnlyOffice 做成全新架构;只修当前 P0 可见缺陷。
|
||||
- 不复活旧 React / BlockNote 运行时。
|
||||
- 不把 Sidex 菜单实现照搬成通用命令注册系统;本轮只借鉴“按可用能力显示动作”的原则。
|
||||
|
||||
## 验收
|
||||
|
||||
- Rust targeted tests 至少覆盖:
|
||||
- local workspace 默认初始化不创建“初始化的新页面”。
|
||||
- 删除页面 bundle 进入 page/document trash,而不是 `local_directory` resource trash。
|
||||
- 主 page tab 随 active primary document 标题更新。
|
||||
- local docx onlyoffice URL / content-type / proxy 回源可达。
|
||||
- 文件树菜单不可用动作隐藏或禁用,已显示动作有真实 handler。
|
||||
- slash menu 不跨 primary/secondary/resource pane 显示。
|
||||
- UI 类最终必须做真实浏览器或 smoke 验证,并保留截图/输出。
|
||||
|
||||
## 本轮执行结果
|
||||
|
||||
- 已完成并移动到 `done/`:
|
||||
- `bugs/04-tree-domain/done/4-45-local-folder-page-trash-and-empty-workspace-v1.md`
|
||||
- `bugs/05-editor-mainline/done/5-28-main-page-tab-title-active-sync-v1.md`
|
||||
- `bugs/05-editor-mainline/done/5-29-onlyoffice-docx-upload-open-freeze-v1.md`
|
||||
- `bugs/05-editor-mainline/done/5-30-filetree-context-menu-sidex-alignment-v1.md`
|
||||
- `bugs/05-editor-mainline/done/5-31-side-pane-slash-overlay-isolation-v1.md`
|
||||
- Rust 验证:
|
||||
- `cargo test -p mnote-web -- --test-threads=1`:481 passed。
|
||||
- 新增 `local_tree_command_delete_page_bundle_directory_uses_page_trash`,锁定 `local-dir:*` 页面 bundle 删除进入 `markdown_bundle` 页面垃圾箱。
|
||||
- Smoke / 浏览器验证:
|
||||
- `node scripts/task463-onlyoffice-resolver-smoke.js`:通过。
|
||||
- `node scripts/task462-resource-tab-error-placeholder-smoke.js`:通过。
|
||||
- `node scripts/task455-local-folder-mindmap-clean-smoke.js`:通过。
|
||||
- `node scripts/task458-local-create-page-no-conflict-smoke.js`:通过。
|
||||
- `node scripts/task464-local-folder-resource-trash-ui-smoke.js`:通过。
|
||||
- `node scripts/task472-side-target-secondary-pane-smoke.js`:通过。
|
||||
- 真实浏览器证据:
|
||||
- `tmp/bug-20260521-workbench-browser-verify/result-title-docx-menu.json`
|
||||
- `tmp/bug-20260521-workbench-browser-verify/result-slash.json`
|
||||
- `tmp/bug-20260521-workbench-browser-verify/result-trash.json`
|
||||
- 截图覆盖:主 tab 标题同步、真实 docx resource tab、资源右键菜单、primary/secondary slash 隔离、页面 bundle 垃圾箱分类。
|
||||
- 历史 smoke 注意:
|
||||
- `node scripts/task432-filetree-trash-page-dual-browser-no-refresh-smoke.js` 当前失败在 convex-source 双浏览器 live delta 未插入新建子页;失败点早于本轮页面删除/垃圾箱断言,不代表本地页面 bundle 垃圾箱修复失败。后续应按实时同步历史 smoke 单独修复或退役。
|
||||
@@ -0,0 +1,38 @@
|
||||
# Checklist: Main Page Tab Title Active Sync
|
||||
|
||||
## 目标
|
||||
|
||||
主编辑区 page tab 标题必须随当前 primary document 切换和标题保存同步更新。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- `rust/crates/mnote-web/src/ssr/pages/document.rs`
|
||||
- 相关测试 / smoke
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不改资源 tab 整体架构。
|
||||
- 不移除资源 tab close guard。
|
||||
- 不回滚现有 `layout.rs` 用户改动。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] 在 `updatePaneChrome(primary)` 中同步 `[data-mnote-main-tab="page"]` 的 title、document id、workspace id。
|
||||
- [x] 标题保存控制器 `updateVisibleTitle` 同步当前 page tab 标题。
|
||||
- [x] 切换回 page tab 时确保 tab 标题与当前 primary document 一致。
|
||||
- [x] 增加 Rust 字符串测试或 browser smoke 覆盖。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 代码:`web_shell.rs` 在标题更新与 primary pane 切换时同步主 page tab。
|
||||
- 浏览器验证:`tmp/bug-20260521-workbench-browser-verify/result-title-docx-menu.json` 中 `tabState.tabTitle=Beta`,截图 `01-beta-page-tab-title.png`。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web page_layout_renders_main_editor_tab_strip -- --test-threads=1
|
||||
cargo test -p mnote-web document_shell_runtime_renders_resource_tab_runtime -- --test-threads=1
|
||||
```
|
||||
@@ -0,0 +1,42 @@
|
||||
# Checklist: OnlyOffice Docx Upload Open Freeze
|
||||
|
||||
## 目标
|
||||
|
||||
上传 docx 后点击打开不应卡死;本地 docx 应能在主编辑器 resource tab 中打开 OnlyOffice,失败时显示非阻塞错误。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`
|
||||
- `rust/crates/mnote-web/src/routes/local_folder_source.rs`
|
||||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- OnlyOffice / local upload 相关测试
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不绕开 local-first rootUri 授权。
|
||||
- 不把 docx 改成浏览器下载兜底作为唯一行为。
|
||||
- 不引入新外部服务。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] 复现并定位上传后卡死发生在上传、插入附件 UI、resource tab iframe、OnlyOffice DocumentServer 回源哪一层。
|
||||
- [x] 确保 local docx 打开 URL 走 `/api/local-folder/files/open` 且 content-type 正确。
|
||||
- [x] 主 tab iframe 打开 OnlyOffice 时设置清晰 loading/error 状态,超时不阻塞主页面。
|
||||
- [x] Convex / local office 行为尽量统一到 resource tab;新窗口只作为“在新窗口打开”动作。
|
||||
- [x] 补充 docx 上传/打开 targeted smoke 或 Rust 字符串测试。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 代码:`onlyoffice.rs` 为 API 加载和初始化增加超时错误;`layout.rs` 让 office 资源优先进入主 resource tab。
|
||||
- 浏览器验证:使用真实文件 `/mnt/Data1T/research/DHA_cosmetics/progress/DHA美黑化妆品监管综述_2026-05-16.docx` 上传并打开,结果在 `tmp/bug-20260521-workbench-browser-verify/result-title-docx-menu.json`,截图 `02-real-docx-resource-tab.png`。
|
||||
- Smoke:`node scripts/task463-onlyoffice-resolver-smoke.js` 已通过。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web local_file_open_sets_pdf_and_office_content_type -- --test-threads=1
|
||||
cargo test -p mnote-web onlyoffice_page_exposes_documentserver_fetch_base_for_local_files -- --test-threads=1
|
||||
cargo test -p mnote-web sidebar_tree_runtime_opens_office_assets_through_resource_shell -- --test-threads=1
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
# Checklist: Filetree Context Menu Sidex Alignment
|
||||
|
||||
## 目标
|
||||
|
||||
对照 Sidex / VSCode Explorer Context,收敛 MNote 文件树右键菜单:只展示可用动作,已展示动作必须有真实效果。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- `rust/crates/mnote-web/src/tree_shell/filetree_runtime.rs`
|
||||
- `rust/crates/mnote-web/src/routes/local_folder_source.rs` 中已有 tree command 入口的小范围扩展
|
||||
- 相关测试
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不照搬 Sidex 菜单注册框架。
|
||||
- 不保留点击后只 dispatch 但用户不可见无效果的菜单项。
|
||||
- 不让资源“在右侧边栏打开”生成 unsupported placeholder。
|
||||
|
||||
## Sidex 对照结论
|
||||
|
||||
- Sidex / VSCode 的 Explorer 菜单来自 `MenuId.ExplorerContext`,动作在 `fileActions.contribution.ts` 注册。
|
||||
- 基础动作包括 Open to the Side、New File、New Folder、Reveal、Copy Path、Rename、Delete。
|
||||
- 动作显示/启用依赖 context key;不可用动作不应常驻为“假按钮”。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] local_folder 下 `New File` 继续创建页面;`New Folder` 接入 `create_folder` 或在非 local_folder 隐藏。
|
||||
- [x] `Copy Path` 对 local folder 复制 `relativePath` / asset path,不复制标题。
|
||||
- [x] `Reveal` 只做滚动/聚焦即可,但需记录状态。
|
||||
- [x] `Duplicate` 若未实现 copy,则隐藏或禁用并说明;不要只 dispatch。
|
||||
- [x] `Open Right` 对页面可打开 secondary document;对资源若不支持侧栏则隐藏,避免 unsupported placeholder。
|
||||
- [x] 更新菜单字符串测试。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 代码:`layout.rs` 收口文件树右键菜单,移除资源侧栏打开和未实现 duplicate,接入 local folder `create_folder` 与真实 `Copy Path`。
|
||||
- 浏览器验证:`tmp/bug-20260521-workbench-browser-verify/result-title-docx-menu.json` 中资源菜单为“在新窗口打开 / 重命名 / 复制资源 ID / 删除 / Copy Path / Refresh / Reveal”,截图 `03-asset-context-menu.png`。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web sidebar_tree_runtime_renders_context_menu_and_scoped_title_updates -- --test-threads=1
|
||||
cargo test -p mnote-web sidebar_tree_runtime_handles_navigation_drag_and_filetree_actions -- --test-threads=1
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
# Checklist: Side Pane Slash Overlay Isolation
|
||||
|
||||
## 目标
|
||||
|
||||
主编辑器 slash 菜单不得在侧栏/secondary pane 中出现;不支持侧栏打开资源时不得留下会响应 slash 的侧栏 editor host。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||||
- 必要时 `rust/spikes/leptos-tiptap-spike/src/lib.rs`
|
||||
- 相关测试 / smoke
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不禁用主编辑器 slash 菜单。
|
||||
- 不删除侧栏页面编辑能力。
|
||||
- 不用全局 CSS 隐藏全部 slash menu 作为表面修复。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] `positionSlashMenuForRoot` 只查当前 root 内菜单;不能 fallback 到全局第一个 slash menu。
|
||||
- [x] `activeEditorRootForSlashMenu` 优先选择含有 selection/focus 的可见 root;secondary hidden/unsupported root 不参与。
|
||||
- [x] 打开 unsupported side target 时彻底卸载 secondary view 并清理遗留 slash overlay。
|
||||
- [x] 为 primary + secondary 同时存在时的 slash 隔离补测试。
|
||||
- [x] 若 leptos runtime 自身生成全局 overlay,需要给 overlay 绑定 `data-pane-role` 或 editor host id。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 代码:`web_shell.rs` 增加 `setSlashMenuInactive` / `hideSlashMenusOutsideRoot`,非当前 selection/focus root 的 slash menu 会被标记 `data-mnote-slash-inactive` 并隐藏。
|
||||
- 浏览器验证:`tmp/bug-20260521-workbench-browser-verify/result-slash.json`,`primaryMenus=1`、`secondaryMenus=0`、`inactiveSecondary=1`,截图 `05-slash-primary-secondary-isolation.png`。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web document_shell_runtime_renders_resource_tab_runtime -- --test-threads=1
|
||||
cargo test -p mnote-web document_shell_runtime_positions_slash_menu_per_editor_host -- --test-threads=1
|
||||
```
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
# Checklist: Main Resource Tab Page Switch And Filetree Focus
|
||||
|
||||
## 目标
|
||||
|
||||
- resource tab 激活时,点击主 Markdown 或其他 Markdown 页面能切回主 page tab。
|
||||
- 新建页面后,主编辑区显示新页面,filetree 选中和焦点落在新页面。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- 相关 Rust 字符串测试与浏览器 smoke
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不改资源 tab 整体架构。
|
||||
- 不删除 resource tab MRU / close guard。
|
||||
- 不回滚 ACP/Hermes 相关改动。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] document pane runtime 暴露 `activatePageTab()`。
|
||||
- [x] `openPrimaryDocument` 成功后切回 page tab。
|
||||
- [x] `navigateToDocument` same-document fast path 也能从 resource tab 切回 page tab。
|
||||
- [x] 页面树整行点击也能触发打开,避免只点内部按钮才生效。
|
||||
- [x] filetree 增加按 documentId 选中/聚焦 helper。
|
||||
- [x] `createPage` 在 local folder projection 刷新后选中新页面。
|
||||
- [x] primary document 激活后同步 filetree selection state。
|
||||
- [x] 补浏览器验证覆盖 resource tab -> md page 切换、新建页面焦点。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web -- --test-threads=1
|
||||
```
|
||||
|
||||
## 验证记录
|
||||
|
||||
- `cargo test -p mnote-web -- --test-threads=1`:482 passed。
|
||||
- Playwright 复测:resource tab 激活后点击左侧 `Beta` 页面,URL 切到 `/documents/local-md:Beta.md`,active tab 为 `page`,resource host 隐藏,页面树 active 行为 `Beta`。
|
||||
- 截图:`/mnt/Data1T/mnote/tmp/bug-20260521-tab-office-upload-after-row-click.png`。
|
||||
@@ -0,0 +1,49 @@
|
||||
# Checklist: Office Chinese Docx Upload Open Freeze
|
||||
|
||||
## 目标
|
||||
|
||||
上传并打开中文文件名 docx 时,浏览器不应卡死;Office 打开失败时必须是可见、非阻塞错误。
|
||||
|
||||
指定测试文件:
|
||||
|
||||
`/home/lix/Downloads/重庆发展特殊化妆品可行性报告_政府汇报版.docx`
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/local_folder_source.rs`
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- 相关 browser smoke
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不引入新外部服务。
|
||||
- 不把 docx 只做下载兜底。
|
||||
- 不清理用户真实下载文件。
|
||||
|
||||
## 待办
|
||||
|
||||
- [x] 用真实中文 docx 复现上传、插入附件、点击打开、OnlyOffice iframe 内错误。
|
||||
- [x] 记录 console/network/iframe src/页面响应性。
|
||||
- [x] 区分 DocumentServer `errorCode=-18` 与浏览器主页面卡死。
|
||||
- [x] 上传完成后不得等待非关键 Office 初始化;上传链路必须释放 UI。
|
||||
- [x] 对中文文件名/URL 编码和 OnlyOffice document key 安全化补测试。
|
||||
- [x] 增加 Reasonix clean browser 测试流程,并用截图交叉验证。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
cd /mnt/Data1T/mnote/rust
|
||||
cargo test -p mnote-web -- --test-threads=1
|
||||
node scripts/task463-onlyoffice-resolver-smoke.js
|
||||
```
|
||||
|
||||
## 验证记录
|
||||
|
||||
- `cargo test -p mnote-web onlyoffice -- --test-threads=1`:12 passed。
|
||||
- `cargo test -p mnote-web -- --test-threads=1`:482 passed。
|
||||
- Reasonix clean browser 测试输出:`/mnt/Data1T/mnote/tmp/reasonix-office-upload-open-clean-2026-05-21/result.json`,结论 `pass`。
|
||||
- Reasonix 最终截图:`/mnt/Data1T/mnote/tmp/reasonix-office-upload-open-clean-2026-05-21/04-final-state.png`,可见 OnlyOffice 文档正文。
|
||||
- Codex 自测输出:`/mnt/Data1T/mnote/tmp/codex-office-upload-open-clean-2026-05-21/result.json`。
|
||||
- Codex 最终截图:`/mnt/Data1T/mnote/tmp/codex-office-upload-open-clean-2026-05-21/codex-office-final.png`,可见 OnlyOffice 文档正文。
|
||||
- 已确认 WebSocket URL 使用安全 doc key,例如 `mnote_1258170954_1240121036`,不含 `/`、`:` 或中文字符;未出现 `errorCode=-18`。
|
||||
@@ -0,0 +1,107 @@
|
||||
# Office local-first 预览、编辑与插件噪音缺口审查 v1
|
||||
|
||||
## 背景
|
||||
|
||||
本轮只审查 OnlyOffice 与 MNote local-first 工作区之间的三个接口缺口:
|
||||
|
||||
1. `/api/media/sign` 对 local-folder asset 返回 404。
|
||||
2. Office 附件默认只读,但需要三点菜单提供“使用编辑模式打开”。
|
||||
3. OnlyOffice 自定义 annotation 插件存在 404 / pageerror 噪音。
|
||||
|
||||
上一轮浏览器验证已经确认:中文 docx 上传后可在 resource tab 中只读打开,`errorCode=-18` 的 WebSocket 连接问题已通过 doc key 安全化和 `/onlyoffice-server` 反代修复。因此本轮不把“只读预览可见”重新定义为失败。
|
||||
|
||||
## 官方依据
|
||||
|
||||
Context7 查询 `/onlyoffice/api.onlyoffice.com` 得到的关键口径:
|
||||
|
||||
- `editorConfig.mode` 支持 `"view"` / `"edit"`,只是初始化编辑器模式。
|
||||
- 保存必须配置 `editorConfig.callbackUrl`,后端在 callback `status === 2` 或 `status === 6` 时下载 `body.url` 并写回文件,成功返回 `{ "error": 0 }`。
|
||||
- `onRequestEditRights` 是 view 模式切 edit 的官方事件;触发后集成方必须以 edit mode 重新初始化编辑器。
|
||||
- 插件通过 `editorConfig.plugins.autostart` 和 `editorConfig.plugins.pluginsData` 连接;annotation / custom assistant 类插件 404 属于可选插件加载链路,不等于主文档渲染失败。
|
||||
|
||||
## 代码现状
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/media.rs` 的 `/api/media/sign` 当前只服务 Convex media asset,内部查询 `mediaAssets:getById` / `mediaAssets:refreshUrl`。local-folder asset 形如 `local:asset:<path>`,不在 Convex media 表中,所以返回 404 是现状契约不匹配。
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs` 的 `/onlyoffice` 页面在 `resolveAssetUrlAndKey()` 中只要有 `assetId` 就请求 `/api/media/sign`;失败后静默保留传入的 `fileUrl`。这就是“当前 view 模式不阻断打开”的原因。
|
||||
- local-folder Office 预览已经可以直接使用 `/api/local-folder/files/open?rootUri=...&path=...` 作为 `fileUrl`,不需要经过 `/api/media/sign`。
|
||||
- `/api/onlyoffice/callback` 当前仍代理 legacy Next writeback。对 local-folder 的 `status 2/6 -> 下载 body.url -> 原文件覆盖写回 -> watcher 同步` 没有完整闭环。
|
||||
- `layout.rs` 中正文附件菜单已有 `new-window`,但没有“使用编辑模式打开”。部分路径当前会默认生成 `mode=edit`,这与“默认只读、显式编辑”的产品口径不一致。
|
||||
- annotation 插件 404 / pageerror 暂未证明会影响文档渲染;当前更像是 OnlyOffice 静态插件包或自定义插件配置缺失导致的 console 噪音。
|
||||
|
||||
## 根因判断
|
||||
|
||||
### 1. `/api/media/sign` local-folder 404
|
||||
|
||||
根因不是权限失效,而是端点 ownership 错位:`/api/media/sign` 是历史 Convex media asset 签名端点,local-folder 文件已经有 local open route,二者不应混用。
|
||||
|
||||
P0 目标不是让 `/api/media/sign` 接管所有本地文件,而是让 OnlyOffice local 路径不再无意义请求该端点,避免误导日志和后续测试。
|
||||
|
||||
### 2. 编辑模式入口
|
||||
|
||||
OnlyOffice `mode=edit` 并不等于 MNote 已支持保存。没有 callback 写回闭环时,直接默认编辑会制造“看似能改、实际不能保存”的假功能。
|
||||
|
||||
P0 目标:
|
||||
|
||||
- 默认打开仍为 `view`。
|
||||
- 菜单提供“使用编辑模式打开”入口。
|
||||
- 编辑入口必须带 guard:清楚标记为实验能力,或在 local-folder writeback 未闭环时阻止/提示。
|
||||
|
||||
P1 目标才是实现 local-folder callback 写回。
|
||||
|
||||
### 3. annotation 插件 404 / pageerror
|
||||
|
||||
插件链路属于可选增强。若配置了 autostart / pluginsData 但静态资源不存在,会产生 404 或 pageerror。只要正文渲染和 OnlyOffice 主 WebSocket 正常,这不是打开失败。
|
||||
|
||||
P0 目标:
|
||||
|
||||
- 不把可选插件 404 当成 Office 打开失败。
|
||||
- 不让缺失插件反复污染测试结论。
|
||||
- 若当前 MNote 并未真正依赖 annotation 插件,则应禁用 autostart 或明确过滤为 non-critical。
|
||||
|
||||
## Checklist 拆分
|
||||
|
||||
- `5-34-local-folder-media-sign-office-url-contract-v1.md`
|
||||
- P0:OnlyOffice local-folder 打开不再请求 `/api/media/sign`。
|
||||
- P1:补回归测试,确认 local asset 仍可只读打开。
|
||||
|
||||
- `5-35-office-edit-mode-menu-and-guard-v1.md`
|
||||
- P0:正文附件与文件树资源菜单增加“使用编辑模式打开”。
|
||||
- P0:默认打开保持只读。
|
||||
- P0:若保存闭环未完成,编辑入口必须有 guard / 实验标记。
|
||||
|
||||
- `5-36-onlyoffice-local-edit-save-callback-contract-v1.md`
|
||||
- P1:设计或实现 local-folder callback 写回。
|
||||
- P1:覆盖 status 2/6、下载 URL rewrite、路径权限、冲突保护。
|
||||
|
||||
- `5-37-onlyoffice-annotation-plugin-noise-policy-v1.md`
|
||||
- P0:定位 annotation 404 来源。
|
||||
- P0:禁用无效 autostart / pluginsData 或把该类错误降级为 non-critical 测试噪音。
|
||||
|
||||
## 不做事项
|
||||
|
||||
- 不默认以 edit 模式打开 Office。
|
||||
- 不在没有保存闭环时承诺“Office 可编辑保存”。
|
||||
- 不把 local-folder 文件任意暴露给 `/api/media/sign`,除非经过 rootUri / workspace / allowed roots 校验。
|
||||
- 不把 annotation 插件 404 等同于主文档渲染失败。
|
||||
|
||||
## 验收要求
|
||||
|
||||
- `cargo test -p mnote-web -- --test-threads=1`
|
||||
- `codegraph sync .` 后确认索引健康。
|
||||
- Reasonix clean browser 测试:全新 browser context,登录测试账号,上传 `/home/lix/Downloads/重庆发展特殊化妆品可行性报告_政府汇报版.docx`,打开默认只读,截图确认内容可见;打开三点菜单确认编辑入口;点击编辑入口后截图和日志证明行为符合 guard / edit URL 预期。
|
||||
- Codex 必须复核 Reasonix 的 `result.json` 和截图,再自行做一次浏览器截图核查。
|
||||
|
||||
## 当前执行结论
|
||||
|
||||
- P0 已处理:
|
||||
- local-folder Office 打开跳过 `/api/media/sign`,继续使用 `/api/local-folder/files/open`。
|
||||
- Office 默认打开为 `mode=view`。
|
||||
- 菜单提供“使用编辑模式打开”,进入前有实验 guard。
|
||||
- 已存在 Office resource tab 从 view 切 edit 会刷新同一 iframe URL,不再只激活旧 tab。
|
||||
- annotation/custom assistant 插件 404 已归类为 non-critical noise,不作为主文档打开失败。
|
||||
- P1 仍保留:
|
||||
- local-folder Office edit/save callback 写回闭环未实现,编辑模式仍不能承诺保存到原文件。
|
||||
- `onRequestEditRights` 事件重新初始化 edit URL 未实现。
|
||||
- 浏览器证据:
|
||||
- Reasonix:`tmp/reasonix-office-view-edit-plugin-2026-05-21/result.json` 与截图。
|
||||
- Codex:`tmp/codex-office-view-edit-plugin-2026-05-21/result.json`、`01-office-view-mode.png`、`02-office-edit-mode.png`。
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# 5-34 local-folder media/sign 与 Office URL 契约
|
||||
|
||||
## 目标
|
||||
|
||||
OnlyOffice 打开 local-folder asset 时不再向 `/api/media/sign` 发起无意义请求;local 文件继续通过 local-folder open route 进入 OnlyOffice 只读预览。
|
||||
|
||||
## 原因
|
||||
|
||||
`/api/media/sign` 当前只签 Convex media asset。local-folder asset 已有 `rootUri + path` 的本地文件打开链路,不应混入 Convex 签名端点。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- 相关 `mnote-web` 单测
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不开放任意本地路径签名。
|
||||
- 不把 `/api/media/sign` 扩成绕过 allowed roots 的本地文件下载端点。
|
||||
- 不改变非 local Convex media asset 的签名行为。
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] `/onlyoffice` 页面识别 local asset / local fileUrl,跳过 `/api/media/sign`。
|
||||
- [x] local asset 的 doc key 仍稳定、安全,不包含 `/`、`:`、中文等危险字符。
|
||||
- [x] 非 local asset 仍可走 `/api/media/sign` 解析 signedUrl。
|
||||
- [x] 补单测覆盖 local asset 不依赖 media sign 的页面脚本契约。
|
||||
|
||||
## 验收
|
||||
|
||||
- `cargo test -p mnote-web onlyoffice -- --test-threads=1`
|
||||
- `cargo test -p mnote-web -- --test-threads=1`
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 2026-05-21:Reasonix worker A 执行完成。
|
||||
- 在 `page()` 模板 JS 中添加 `isLocalFolderAsset()` 守卫函数。
|
||||
- `resolveAssetUrlAndKey()` 中 local-folder asset 跳过 `/api/media/sign`。
|
||||
- 守卫条件:`assetId` 前缀为 `local:` 或 `local-file:`,或 `fileUrl` 路径含 `/api/local-folder/files/open`。
|
||||
- 新增 `onlyoffice_page_skips_media_sign_for_local_folder_asset` 单测。
|
||||
- `cargo test -p mnote-web onlyoffice -- --test-threads=1` 全部 13 项通过。
|
||||
- 2026-05-21:Codex 复核补充。
|
||||
- 干净浏览器上下文上传并打开 `/home/lix/Downloads/重庆发展特殊化妆品可行性报告_政府汇报版.docx`。
|
||||
- local-folder iframe `fileUrl` 指向 `/api/local-folder/files/open?...`,未出现 `/api/media/sign` local 404。
|
||||
- 证据:`tmp/codex-office-view-edit-plugin-2026-05-21/result.json`,截图 `01-office-view-mode.png` / `02-office-edit-mode.png`。
|
||||
@@ -0,0 +1,62 @@
|
||||
# 5-35 Office 编辑模式菜单与保护
|
||||
|
||||
## 目标
|
||||
|
||||
Office 文件默认只读打开;在正文附件三点菜单和文件树资源右键菜单中增加“使用编辑模式打开”入口。保存闭环未完成前,编辑入口必须有 guard 或明确实验标记。
|
||||
|
||||
## 原因
|
||||
|
||||
ONLYOFFICE `mode=edit` 只是编辑器初始化模式。若 MNote 没有完成 callback 写回,默认 edit 会让用户误以为修改已经保存到本地文件。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs` 中与 view/edit 初始化事件相关的最小补充
|
||||
- 相关 `mnote-web` 单测
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不默认 edit。
|
||||
- 不声称 edit/save 已完整支持。
|
||||
- 不改动 ACP / Hermes 无关代码。
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] `buildOnlyOfficeAssetOpenUrl` / local Office 默认输出 `mode=view`。
|
||||
- [x] 正文附件菜单增加“使用编辑模式打开”。
|
||||
- [x] 文件树 Office asset 菜单增加“使用编辑模式打开”。
|
||||
- [x] 编辑模式入口明确使用 `mode=edit` 打开到主 resource tab 或新窗口,行为与现有打开目标一致。
|
||||
- [x] 在 local-folder save callback 未闭环时,编辑入口有 guard:可提示“编辑保存仍在实验中”,或通过 data/status 标记便于测试识别。
|
||||
- [x] 已存在 Office resource tab 从 `mode=view` 切到显式 `mode=edit` 时,刷新同一 tab 的 iframe URL,而不是只激活旧 tab。
|
||||
- [ ] 若启用 `onRequestEditRights`,必须重新初始化为 edit URL,不只 reload 当前 view。(P1,未实现)
|
||||
|
||||
## 验收
|
||||
|
||||
- `cargo test -p mnote-web sidebar_tree_js -- --test-threads=1`
|
||||
- `cargo test -p mnote-web onlyoffice -- --test-threads=1`
|
||||
- 浏览器截图:默认打开是只读;菜单中存在编辑入口;点击编辑入口后的页面 URL / debug state 包含 `mode=edit` 或 guard 提示。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 2026-05-21:Reasonix worker B 卡在计划阶段后由 Codex 终止;本条实现来自其它 Reasonix 结果与 Codex 复核修正。
|
||||
- `buildOnlyOfficeOpenUrl` 默认 mode 从 `'edit'` 改为 `'view'`。
|
||||
- `buildOnlyOfficeOpenPath` 默认 mode 从 `'edit'` 改为 `'view'`。
|
||||
- `buildLocalOnlyOfficeOpenUrl` 默认 mode 从 `'edit'` 改为 `'view'`。
|
||||
- `normalizeOnlyOfficeAttachmentHref` 默认 mode 从 `'edit'` 改为 `'view'`。
|
||||
- `detailFromEditorAttachmentLink` 默认 mode 从 `'edit'` 改为 `'view'`。
|
||||
- `enhanceEditorAttachmentLink` 默认 mode 从 `'edit'` 改为 `'view'`。
|
||||
- 正文附件菜单(`openTreeContextMenu` `isAttachment` 分支)增加菜单项 `{ action: 'open-edit-mode', icon: 'edit_note', label: '使用编辑模式打开' }`,放置于"在新窗口打开"之前。
|
||||
- 文件树 asset 菜单(`isAsset` 分支)增加相同的 `open-edit-mode` 菜单项。
|
||||
- 新增 `withOfficeEditModeGuard()` 守卫函数:
|
||||
- 设置 `data-mnote-last-office-edit-mode-requested="true"` 和 `data-mnote-last-office-edit-mode-guard="shown"` 以支持浏览器测试识别。
|
||||
- 弹出 `window.confirm('编辑保存仍在实验中,建议先备份文件。是否继续?')` 对话框,用户确认后才继续。
|
||||
- `handleTreeContextMenuAction` 中 attachment 和 isAsset 分支分别处理 `open-edit-mode` 动作,调用 guard 后再以 `mode=edit` 打开。
|
||||
- Codex 修正:普通“在新窗口打开”保持 `mode=view`;只有“使用编辑模式打开”才传入 `mode=edit`。
|
||||
- Codex 补充 `sidebar_tree_runtime_opens_office_assets_through_resource_shell` 契约测试,覆盖默认 view、显式 edit、guard 标记和 edit URL 重写。
|
||||
- `cargo test -p mnote-web sidebar_tree_runtime_opens_office_assets_through_resource_shell -- --test-threads=1` 通过。
|
||||
- `cargo test -p mnote-web onlyoffice -- --test-threads=1` 通过。
|
||||
- 2026-05-21:Codex 浏览器复核发现并修复“已有 Office tab 切 edit 不刷新”。
|
||||
- 根因:`openResourceInActiveTab()` 遇到已存在 `objectIdentity` 时只调用 `activateMainEditorTab(objectIdentity)`,没有更新旧 iframe 的 `officeUrl`。
|
||||
- 修复:`web_shell.rs` 新增 `refreshExistingOfficeResourceTab()`,仅对 `entry.kind === 'office'` 且新旧 `href/officeUrl` 不一致时重建 passive iframe。
|
||||
- 回归:`scripts/task463-onlyoffice-resolver-smoke.js` 新增 Test 1b,断言同一 docx tab 从 `mode=view` 刷新到 `mode=edit`,且不会创建第二个 Office tab。
|
||||
- Codex clean browser 自测通过:中文 docx 默认 view;同 tab edit 后 iframe URL `mode=edit`;证据见 `tmp/codex-office-view-edit-plugin-2026-05-21/result.json`。
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
# 5-36 OnlyOffice local-folder 编辑保存 callback 契约
|
||||
|
||||
## 目标
|
||||
|
||||
为 local-folder Office 编辑保存建立 callback 写回契约。P1 可以先落设计和测试骨架;若实现,必须覆盖 status 2/6 的下载写回和路径安全。
|
||||
|
||||
## 原因
|
||||
|
||||
ONLYOFFICE 官方保存链路要求 callback `status === 2` 或 `status === 6` 时,集成后端下载 `body.url` 并写回原文件。当前 `mnote-web` callback 仍代理 legacy Next,local-folder 写回未闭环。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`
|
||||
- `rust/crates/adapter-onlyoffice/src/lib.rs`
|
||||
- 相关单测
|
||||
- 如需记录设计,可补充本 checklist
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不绕过 allowed roots 写任意路径。
|
||||
- 不在没有冲突保护时覆盖用户无关文件。
|
||||
- 不强行删除 legacy callback 代理。
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] 明确 local asset callback 定位:从 `assetId` / `fileUrl` / session 推导 rootUri 与 path。
|
||||
- [ ] status 非 2/6 时返回 `{ "error": 0 }`,不写文件。
|
||||
- [ ] status 2/6 时下载 rewritten `body.url`。
|
||||
- [ ] 写回前校验目标路径属于当前 local root allowed roots。
|
||||
- [ ] 写回后触发 watcher / projection 刷新或说明现有 watcher 如何感知。
|
||||
- [ ] 若本轮不实现完整写回,必须在编辑入口保留 guard,不让用户以为保存已支持。
|
||||
|
||||
## 验收
|
||||
|
||||
- `cargo test -p mnote-web onlyoffice_callback -- --test-threads=1`
|
||||
- `cargo test -p mnote-web -- --test-threads=1`
|
||||
- 后续浏览器编辑保存验收需单独设计,不纳入 P0。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 2026-05-21:Reasonix worker C 分析完成。
|
||||
**结论:本轮不应实现完整写回。**
|
||||
|
||||
**阻塞输入缺口:**
|
||||
|
||||
1. callback URL 当前只携带 `assetId` 和 `userId`,缺少 `rootUri` 和 `path`。
|
||||
- `buildCallbackUrl()` 在 `onlyoffice.rs` 页脚 JS 中硬编码只传两个参数。
|
||||
- 对于 local-folder asset(assetId `local:asset:path/to/file.docx`),无法从 assetId 推导 rootUri。
|
||||
- 没有 rootUri 就无法 `resolve_onlyoffice_local_file_path` → 无法安全写回。
|
||||
2. `adapter-onlyoffice` 的 `prepare_callback` 不感知 local-folder 路径。
|
||||
- `OnlyOfficeCallbackPreparationInput` 没有 rootUri / path 字段。
|
||||
- `prepare_callback` 只做下载 URL rewrite 和 session 定位,不含路径校验。
|
||||
3. callback Rust handler 的 `proxy_legacy_onlyoffice_json` 目前代理 legacy Next;local-folder 无 legacy 时返回 NOT_IMPLEMENTED。
|
||||
|
||||
**实现写回所需的最小增量(下轮实现):**
|
||||
|
||||
- `page()` 页脚的 `buildCallbackUrl()`:检测 local asset,追加 `rootUri` 和 `path` query 参数。
|
||||
- `OnlyOfficeCallbackQuery` struct:增加 `root_uri: Option<String>` 和 `path: Option<String>`。
|
||||
- `callback()` handler:检测到 local asset 时(assetId 含 `local:` / `local-file:` 前缀),从 query 提取 rootUri 和 path,调用 `resolve_onlyoffice_local_file_path` 校验路径在 allowed roots 内。
|
||||
- `adapter-onlyoffice`:在 `OnlyOfficeCallbackPreparationInput` 和 `prepare_callback` 增加 local path 字段。
|
||||
- status 2/6:下载 rewritten body.url,写回校验过的本地路径。
|
||||
- status 非 2/6:返回 `{"error": 0}`,不写文件。
|
||||
|
||||
**当前 guard 状态:**
|
||||
- Worker B 已在 `layout.rs` 中实现 `withOfficeEditModeGuard`:confirm 对话框 + `data-mnote-last-office-edit-mode-requested` / `data-mnote-last-office-edit-mode-guard` 数据属性。
|
||||
- 编辑入口在 local-folder writeback 未闭环时带 guard 提示,符合安全策略。
|
||||
@@ -0,0 +1,51 @@
|
||||
# 5-37 OnlyOffice annotation 插件噪音策略
|
||||
|
||||
## 目标
|
||||
|
||||
定位 OnlyOffice annotation / custom assistant 插件 404 或 pageerror 来源,并把它从主打开失败中剥离:能禁用则禁用,不能禁用则在测试和日志中明确为 non-critical。
|
||||
|
||||
## 原因
|
||||
|
||||
ONLYOFFICE 插件通过 `editorConfig.plugins.autostart` 和 `pluginsData` 注入。缺失插件资源会产生 404/pageerror,但不应影响主文档渲染、WebSocket 或只读预览。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`
|
||||
- `src/components/onlyoffice/` 下与自定义插件配置直接相关的文件
|
||||
- 相关测试和 smoke 断言
|
||||
|
||||
## 禁止事项
|
||||
|
||||
- 不删除 OnlyOffice 主静态资源。
|
||||
- 不把所有 console error 都静默吞掉。
|
||||
- 不把主文档渲染失败降级为插件噪音。
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] 找到 annotation/custom assistant 插件配置或请求来源。
|
||||
- [x] 若 MNote 当前不依赖该插件,禁用无效 autostart / pluginsData。(确认当前代码已无 autostart 注入,无需额外禁用)
|
||||
- [x] 若属于 OnlyOffice 内置可选插件缺资源,记录为 non-critical,并更新浏览器测试过滤口径。
|
||||
- [ ] 补测试或文档,确保 `errorCode=-18` / WebSocket 失败仍被视为失败,不被插件噪音掩盖。(P1,后续补充)
|
||||
|
||||
## 验收
|
||||
|
||||
- `cargo test -p mnote-web onlyoffice -- --test-threads=1`
|
||||
- Reasonix clean browser 测试的 console/network 摘要能区分插件 404 与主打开失败。
|
||||
|
||||
## 本轮执行记录
|
||||
|
||||
- 2026-05-21:Reasonix worker D 分析完成。
|
||||
- **来源确认**:MNote 后端代码(`onlyoffice.rs`)**没有**在 `editorConfig` 中设置 `plugins.autostart` 或 `plugins.pluginsData`。`MNOTE_AGENT_PLUGIN_GUID` 常量虽定义但未被任何配置引用。
|
||||
- 旧的 `recycle/wolai-frontend/` 中存在设置 `autostart: [MNOTE_AGENT_PLUGIN_GUID]` 和 `pluginsData: [pluginConfigUrl]` 的代码,但那是已废弃的前端实现。
|
||||
- 当前 `onlyoffice.rs` 的 `page()` 函数生成的 JS 中 `editorConfig` 无 `plugins` 字段。
|
||||
- `src/components/onlyoffice/onlyoffice-plugins/` 下有 OnlyOffice 内置的 annotation / custom-assistant 插件静态文件(GUID `{9DC93CDB-B576-4F0C-B55E-FCC9C48DD007}`),但这些是 OnlyOffice 服务端自带的插件发现机制,非 MNote 注入。
|
||||
- **处理策略**:
|
||||
1. 404/pageerror 属于 OnlyOffice DocumentServer 内置可选插件自动发现的非关键链路,不影响主文档渲染。
|
||||
2. 不需要禁用代码层面的 `autostart`——因为当前代码已不注入任何插件。
|
||||
3. 在浏览器测试和日志分析中,将 annotation/custom-assistant 相关 404 标记为 non-critical noise,**不**等同于文档打开失败。
|
||||
4. 保持 `errorCode=-18`(WebSocket 连接失败)和主 iframe 空白仍视为真正失败。
|
||||
- 未修改代码文件。
|
||||
- 2026-05-21:Reasonix 与 Codex 浏览器复核一致。
|
||||
- Reasonix 结果:`tmp/reasonix-office-view-edit-plugin-2026-05-21/result.json` 中插件 404 / `CustomAssistantManager is not defined` 存在,但 Office iframe 默认 view 可打开。
|
||||
- Codex 结果:`tmp/codex-office-view-edit-plugin-2026-05-21/result.json` 中同样捕获 `/sdkjs-plugins/{9DC93CDB-B576-4F0C-B55E-FCC9C48DD007}/...` 404;默认 view 与显式 edit 的主 iframe 均可建立。
|
||||
- 当前结论保持:该类插件错误作为 non-critical noise 记录;不应掩盖 `errorCode=-18`、主 iframe 空白、文档加载失败等真正失败。
|
||||
Reference in New Issue
Block a user