Improve Cut and Paste - #17850
Conversation
…at the second time
|
我还没看代码和测试,仅补充一个场景: 打开文档 A → 剪切一个块 → 关闭文档 A → 打开文档 B → 粘贴块到里面 → 打开文档 A → 在文档 A 里撤销 |
|
刚看了一下 你说的这个场景,fable 5 写的代码 确实没有覆盖 |
这个场景思源本身也不支持,关闭 A 后就不支持撤销了。我觉得应该是属于 #4866 的支持范围。 |
|
我可以看看等fable可以用了以后,看看fable有没有什么办法实现#4866 |
|
好,那现在这个应该可以 review 了吧? |
There was a problem hiding this comment.
Pull request overview
This PR refactors cut/copy/paste and undo behavior to better preserve block reference integrity by conditionally keeping original block IDs on paste, supported by a new bulk “block IDs exist” kernel API.
Changes:
- Add kernel API endpoint
/api/block/checkBlocksExistto bulk-check whether block IDs exist. - Update editor paste logic to keep original block IDs when they no longer exist (cut→paste), and regenerate IDs only when they still exist (copy→paste).
- Add an undo-time duplicate-ID resolver to avoid inserting blocks with IDs already present after cross-editor cut/paste.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| kernel/api/router.go | Registers the new bulk block existence API route. |
| kernel/api/block.go | Implements checkBlocksExist handler and validation/filtering of IDs. |
| app/src/protyle/util/paste.ts | Uses bulk existence check to decide whether to keep or regenerate pasted block IDs. |
| app/src/protyle/undo/index.ts | Adds duplicate-ID resolution before replaying insert operations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| idsArg := arg["ids"].([]interface{}) | ||
| var ids []string | ||
| for _, idArg := range idsArg { | ||
| if id, idOk := idArg.(string); idOk && ast.IsNodeIDPattern(id) { | ||
| ids = append(ids, id) | ||
| } | ||
| } | ||
| ret.Data = treenode.ExistBlockTrees(ids) |
| const oldIds: string[] = []; | ||
| pastedBlockElements.forEach((e) => { | ||
| oldIds.push(e.getAttribute("data-node-id")); | ||
| }); | ||
| const existResponse = await fetchSyncPost("/api/block/checkBlocksExist", {ids: oldIds}); | ||
| pastedBlockElements.forEach((e) => { | ||
| if (existResponse.data[e.getAttribute("data-node-id")] !== false) { | ||
| e.setAttribute("data-node-id", Lute.NewNodeID()); | ||
| } | ||
| clearBlockElement(e); | ||
| }); |
| private async render(protyle: IProtyle, state: IOperations, redo: boolean) { | ||
| hideElements(["hint", "gutter"], protyle); | ||
| protyle.wysiwyg.lastHTMLs = {}; | ||
| await this.resolveDuplicateIds(redo ? state.doOperations : state.undoOperations); | ||
| if (!redo) { |
我的想法是这个PR供各位参考,不一定要合并,因为这个代码完全是AI生成的,一般大项目我不敢在没有100%把握的情况下用ai代码。当然如果你们感觉没啥问题的话我也可以跟进一下,或者你们push变更到这个pr也行。 |
|
把草稿状态改成准备合并吧 |
|
改了 |
|
我和 V 先把全局撤销解决掉 #4866 就来处理这个,多谢。 |
|
不急,我今天再测一下 |
|
等跨编辑器撤销搞定了再测 |
|
嗷~ |
|
我们先合并吧,后续修改我这边来搞,多谢。 |
|
嗷~我刚好在合并冲突 |
Signed-off-by: Daniel <845765@qq.com>
Description / 描述
as per discussions in #17679
Type of change / 变更类型
缺陷修复
代码重构
新功能
修改文案或增加新语言
Checklist / 检查清单
我对自己的代码进行了自我审查
我拥有所提交代码的完整权利,并同意其以本项目的 AGPL-3.0 许可证授权
devbranch and has no merge conflictsPR 提交到
dev分支,并且没有合并冲突