mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-06-26 01:55:48 +02:00
Bug 1999154 - Add the ability to undo comment deletion
This commit is contained in:
parent
6a4a3b060d
commit
d9f67bd8ee
@ -561,6 +561,7 @@ pdfjs-editor-undo-bar-message-freetext = Text removed
|
|||||||
pdfjs-editor-undo-bar-message-ink = Drawing removed
|
pdfjs-editor-undo-bar-message-ink = Drawing removed
|
||||||
pdfjs-editor-undo-bar-message-stamp = Image removed
|
pdfjs-editor-undo-bar-message-stamp = Image removed
|
||||||
pdfjs-editor-undo-bar-message-signature = Signature removed
|
pdfjs-editor-undo-bar-message-signature = Signature removed
|
||||||
|
pdfjs-editor-undo-bar-message-comment = Comment removed
|
||||||
# Variables:
|
# Variables:
|
||||||
# $count (Number) - the number of removed annotations.
|
# $count (Number) - the number of removed annotations.
|
||||||
pdfjs-editor-undo-bar-message-multiple =
|
pdfjs-editor-undo-bar-message-multiple =
|
||||||
|
|||||||
@ -1177,6 +1177,22 @@ class AnnotationEditorUIManager {
|
|||||||
this.#commentManager?.removeComments([editor.uid]);
|
this.#commentManager?.removeComments([editor.uid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a comment from an editor with undo support.
|
||||||
|
* @param {AnnotationEditor} editor - The editor whose comment to delete.
|
||||||
|
* @param {string} savedComment - The comment text to save for undo.
|
||||||
|
*/
|
||||||
|
deleteComment(editor, savedComment) {
|
||||||
|
const undo = () => {
|
||||||
|
editor.comment = savedComment;
|
||||||
|
};
|
||||||
|
const cmd = () => {
|
||||||
|
this._editorUndoBar?.show(undo, "comment");
|
||||||
|
editor.comment = null;
|
||||||
|
};
|
||||||
|
this.addCommands({ cmd, undo, mustExec: true });
|
||||||
|
}
|
||||||
|
|
||||||
toggleComment(editor, isSelected, visibility = undefined) {
|
toggleComment(editor, isSelected, visibility = undefined) {
|
||||||
this.#commentManager?.toggleCommentPopup(editor, isSelected, visibility);
|
this.#commentManager?.toggleCommentPopup(editor, isSelected, visibility);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -965,4 +965,159 @@ describe("Comment", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Undo deletion popup for comments (bug 1999154)", () => {
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
pages = await loadAndWait(
|
||||||
|
"tracemonkey.pdf",
|
||||||
|
".annotationEditorLayer",
|
||||||
|
"page-fit",
|
||||||
|
null,
|
||||||
|
{ enableComment: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must check that deleting a comment can be undone using the undo button", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await switchToHighlight(page);
|
||||||
|
await highlightSpan(page, 1, "Abstract");
|
||||||
|
const editorSelector = getEditorSelector(0);
|
||||||
|
const comment = "Test comment for undo";
|
||||||
|
await editComment(page, editorSelector, comment);
|
||||||
|
|
||||||
|
// Stay in highlight mode - don't disable it
|
||||||
|
await waitAndClick(
|
||||||
|
page,
|
||||||
|
`${editorSelector} .annotationCommentButton`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.waitForSelector("#commentPopup", { visible: true });
|
||||||
|
await waitAndClick(page, "button.commentPopupDelete");
|
||||||
|
|
||||||
|
await page.waitForSelector("#editorUndoBar", { visible: true });
|
||||||
|
await page.waitForSelector("#editorUndoBarUndoButton", {
|
||||||
|
visible: true,
|
||||||
|
});
|
||||||
|
await page.click("#editorUndoBarUndoButton");
|
||||||
|
|
||||||
|
// Check that the comment is restored by hovering to show the popup
|
||||||
|
await page.hover(`${editorSelector} .annotationCommentButton`);
|
||||||
|
await page.waitForSelector("#commentPopup", { visible: true });
|
||||||
|
const popupText = await page.evaluate(
|
||||||
|
() =>
|
||||||
|
document.querySelector("#commentPopup .commentPopupText")
|
||||||
|
?.textContent
|
||||||
|
);
|
||||||
|
expect(popupText).withContext(`In ${browserName}`).toEqual(comment);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must check that the undo deletion popup displays 'Comment removed' message", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await switchToHighlight(page);
|
||||||
|
await highlightSpan(page, 1, "Abstract");
|
||||||
|
const editorSelector = getEditorSelector(0);
|
||||||
|
await editComment(page, editorSelector, "Test comment");
|
||||||
|
|
||||||
|
// Stay in highlight mode - don't disable it
|
||||||
|
await waitAndClick(
|
||||||
|
page,
|
||||||
|
`${editorSelector} .annotationCommentButton`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.waitForSelector("#commentPopup", { visible: true });
|
||||||
|
await waitAndClick(page, "button.commentPopupDelete");
|
||||||
|
|
||||||
|
await page.waitForFunction(() => {
|
||||||
|
const messageElement = document.querySelector(
|
||||||
|
"#editorUndoBarMessage"
|
||||||
|
);
|
||||||
|
return messageElement && messageElement.textContent.trim() !== "";
|
||||||
|
});
|
||||||
|
const message = await page.waitForSelector("#editorUndoBarMessage");
|
||||||
|
const messageText = await page.evaluate(
|
||||||
|
el => el.textContent,
|
||||||
|
message
|
||||||
|
);
|
||||||
|
expect(messageText)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toContain("Comment removed");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must check that the undo bar closes when clicking the close button", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await switchToHighlight(page);
|
||||||
|
await highlightSpan(page, 1, "Abstract");
|
||||||
|
const editorSelector = getEditorSelector(0);
|
||||||
|
await editComment(page, editorSelector, "Test comment");
|
||||||
|
|
||||||
|
// Stay in highlight mode - don't disable it
|
||||||
|
await waitAndClick(
|
||||||
|
page,
|
||||||
|
`${editorSelector} .annotationCommentButton`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.waitForSelector("#commentPopup", { visible: true });
|
||||||
|
await waitAndClick(page, "button.commentPopupDelete");
|
||||||
|
|
||||||
|
await page.waitForSelector("#editorUndoBar", { visible: true });
|
||||||
|
await waitAndClick(page, "#editorUndoBarCloseButton");
|
||||||
|
await page.waitForSelector("#editorUndoBar", { hidden: true });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must check that deleting a comment can be undone using Ctrl+Z", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await switchToHighlight(page);
|
||||||
|
await highlightSpan(page, 1, "Abstract");
|
||||||
|
const editorSelector = getEditorSelector(0);
|
||||||
|
const comment = "Test comment for Ctrl+Z undo";
|
||||||
|
await editComment(page, editorSelector, comment);
|
||||||
|
|
||||||
|
// Stay in highlight mode - don't disable it
|
||||||
|
await waitAndClick(
|
||||||
|
page,
|
||||||
|
`${editorSelector} .annotationCommentButton`
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.waitForSelector("#commentPopup", { visible: true });
|
||||||
|
await waitAndClick(page, "button.commentPopupDelete");
|
||||||
|
|
||||||
|
await page.waitForSelector("#editorUndoBar", { visible: true });
|
||||||
|
|
||||||
|
// Use Ctrl+Z to undo
|
||||||
|
await kbModifierDown(page);
|
||||||
|
await page.keyboard.press("z");
|
||||||
|
await kbModifierUp(page);
|
||||||
|
|
||||||
|
// The undo bar should be hidden after undo
|
||||||
|
await page.waitForSelector("#editorUndoBar", { hidden: true });
|
||||||
|
|
||||||
|
// Check that the comment is restored by hovering to show the popup
|
||||||
|
await page.hover(`${editorSelector} .annotationCommentButton`);
|
||||||
|
await page.waitForSelector("#commentPopup", { visible: true });
|
||||||
|
const popupText = await page.evaluate(
|
||||||
|
() =>
|
||||||
|
document.querySelector("#commentPopup .commentPopupText")
|
||||||
|
?.textContent
|
||||||
|
);
|
||||||
|
expect(popupText).withContext(`In ${browserName}`).toEqual(comment);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -982,9 +982,15 @@ class CommentPopup {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.#editor.comment = null;
|
const savedComment = this.#editor.comment?.text;
|
||||||
this.#editor.focus();
|
const editor = this.#editor;
|
||||||
this.destroy();
|
this.destroy();
|
||||||
|
if (savedComment) {
|
||||||
|
editor._uiManager.deleteComment(editor, savedComment);
|
||||||
|
} else {
|
||||||
|
editor.comment = null;
|
||||||
|
}
|
||||||
|
editor.focus();
|
||||||
});
|
});
|
||||||
del.addEventListener("contextmenu", noContextMenu);
|
del.addEventListener("contextmenu", noContextMenu);
|
||||||
buttons.append(edit, del);
|
buttons.append(edit, del);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ class EditorUndoBar {
|
|||||||
stamp: "pdfjs-editor-undo-bar-message-stamp",
|
stamp: "pdfjs-editor-undo-bar-message-stamp",
|
||||||
ink: "pdfjs-editor-undo-bar-message-ink",
|
ink: "pdfjs-editor-undo-bar-message-ink",
|
||||||
signature: "pdfjs-editor-undo-bar-message-signature",
|
signature: "pdfjs-editor-undo-bar-message-signature",
|
||||||
|
comment: "pdfjs-editor-undo-bar-message-comment",
|
||||||
_multiple: "pdfjs-editor-undo-bar-message-multiple",
|
_multiple: "pdfjs-editor-undo-bar-message-multiple",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user