Files
mnote/bugs/05-editor-mainline/done/5-39-block-menu-delete-undo-regression-v1.md
T

60 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 5-39 Block menu 删除后 Ctrl+Z 不恢复目标块
> 创建时间:2026-05-25
> 状态:`done`
> Owner`05-editor-mainline`
## 现象
`node scripts/task489-block-menu-delete-undo-smoke.js` 连续两次失败。块菜单删除 `Beta block` 成功,但随后 `Control+Z` 未恢复目标块,最终等待 `Beta block` 重新出现超时。
失败证据:
- `tmp/task489-block-menu-delete-undo-smoke/result.json`
- `tmp/task489-block-menu-delete-undo-smoke/failure.png`
当前 result 摘要:
```json
{
"ok": false,
"states": [
{ "step": "opened", "text": "Block Undo\n\nAlpha block\n\nBeta block\n\nGamma block" },
{ "step": "deleted", "text": "Block Undo\n\nAlpha block\n\nGamma block" }
],
"error": "page.waitForFunction: Timeout 30000ms exceeded."
}
```
## 初步判断
失败点不是删除动作本身,而是删除后的 undo 历史不可恢复。当前代码已经调用 `editor_runtime::history_safe_commands::delete_top_level_block_with_history(&editor, block_index)`,需要继续核实:
- `delete_range(range)` 是否真的进入 Tiptap history。
- 删除后 `sync_persisted_editor_command(...)` 是否触发了会清空 undo history 或重建 editor state 的路径。
- 失败是否与焦点丢失有关;需要用最小浏览器复现确认点击 editor 后再 `Control+Z` 是否能恢复。
## 根因
块菜单按钮点击后,删除命令先通过 Tiptap history-safe `delete_range` 路径删除目标块,history 本身仍可用;浏览器诊断确认删除后点击 editor 再 `Control+Z` 可以恢复 `Beta block`。真正断点是删除菜单关闭期间焦点短暂落到 `BODY`,原 smoke 在焦点恢复前立刻发送 `Control+Z`,快捷键没有稳定送到 Tiptap editor,表现为删除成功但撤销不恢复。
## 修复
- 删除菜单项 `mousedown` 阶段阻止默认焦点转移,减少按钮卸载后焦点落回 `BODY` 的窗口。
- 在块菜单删除成功、关闭菜单状态后,异步补一次 `editor.focus()`,确保正常用户操作后的键盘撤销进入 ProseMirror。
-`BODY` 短暂持有焦点时,只兜底转发 `Ctrl/Cmd+Z``Ctrl/Cmd+Y``Shift+Ctrl/Cmd+Z` 到当前 editor,覆盖 smoke 中删除后立即按撤销的竞态。
- 同批拆出 `editor_runtime/block_menu_document.rs`,隔离 legacy 顶层块 JSON helper;当前运行路径仍优先使用 history-safe command,不回退到 HTML 整文替换删除。
## 验收
- `cargo fmt --manifest-path rust/Cargo.toml --all --check` 通过。
- `cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml` 通过。
- `cargo build --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml --target wasm32-unknown-unknown --release` 通过,并已执行 `wasm-bindgen` 更新 island wasm。
- `node scripts/task489-block-menu-delete-undo-smoke.js` 通过。
- `node scripts/task488-local-attachment-link-delete-undo-smoke.js` 通过。
- 不得回退到 HTML 整文替换删除路径。
## 未覆盖
- `cargo test --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml block_menu_document -- --test-threads=1` 当前被既有 `STYLE` 测试编译错误阻断,错误为 `cannot find value STYLE in this scope`,未进入本次新增 helper 测试。