fix: isolate editor undo history by memo

This commit is contained in:
tianma-if committed 2026-08-10 01:16:16 +08:00
1 parent 9123eaa28e
commit e26387b74d
2 files changed
+53 -1

No files matched your search

+6 -1
View File
@@ -1137,7 +1137,12 @@ const RichEditorPane = ({
return true;
},
},
});
}, [
// A ProseMirror undo history belongs to exactly one memo. Reusing the same
// Editor instance across memo switches lets Ctrl/Cmd+Z undo the hydration
// transaction and restore another memo's entire document.
memo?.id,
]);
const insertMemoLink = useCallback((target: MemoSummary) => {
if (!isEditorReady(editor) || effectiveReadOnly || target.id === memo?.id) {
+47
View File
@@ -0,0 +1,47 @@
import { expect, test } from "@playwright/test";
test("keeps undo history isolated when switching between search results", async ({ page }) => {
const marker = `undo-isolation-${Date.now()}`;
const notebooksResponse = await page.request.get("/api/v1/notebooks");
expect(notebooksResponse.ok()).toBe(true);
const notebooks = await notebooksResponse.json() as { notebooks: Array<{ id: string }> };
const notebookId = notebooks.notebooks[0]?.id;
expect(notebookId).toBeTruthy();
const createMemo = async (title: string, contentMarkdown: string) => {
const response = await page.request.post("/api/v1/memos", {
data: { notebookId, title, contentMarkdown },
});
expect(response.status()).toBe(201);
return (await response.json() as { memo: { id: string } }).memo;
};
const first = await createMemo(`${marker} first`, `${marker} FIRST CONTENT`);
const second = await createMemo(`${marker} second`, `${marker} SECOND CONTENT`);
try {
await page.goto("/");
await page.getByRole("button", { name: "全部笔记", exact: true }).click();
await page.getByPlaceholder("搜索笔记").fill(marker);
await page.locator(`[data-memo-id="${first.id}"]`).locator("button").first().click();
const editor = page.locator(".ProseMirror[contenteditable='true']");
await expect(editor).toContainText(`${marker} FIRST CONTENT`);
await page.locator(`[data-memo-id="${second.id}"]`).locator("button").first().click();
await expect(editor).toContainText(`${marker} SECOND CONTENT`);
await editor.click();
await page.keyboard.insertText(" accidental edit");
await page.keyboard.press("ControlOrMeta+z");
await expect(editor).toContainText(`${marker} SECOND CONTENT`);
await expect(editor).not.toContainText("accidental edit");
await expect(editor).not.toContainText(`${marker} FIRST CONTENT`);
} finally {
for (const memo of [first, second]) {
await page.request.delete(`/api/v1/memos/${memo.id}`);
await page.request.delete(`/api/v1/memos/${memo.id}?permanent=1`);
}
}
});