Skip to content

Commit d9f67bd

Browse files
committed
Bug 1999154 - Add the ability to undo comment deletion
1 parent 6a4a3b0 commit d9f67bd

5 files changed

Lines changed: 181 additions & 2 deletions

File tree

l10n/en-US/viewer.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ pdfjs-editor-undo-bar-message-freetext = Text removed
561561
pdfjs-editor-undo-bar-message-ink = Drawing removed
562562
pdfjs-editor-undo-bar-message-stamp = Image removed
563563
pdfjs-editor-undo-bar-message-signature = Signature removed
564+
pdfjs-editor-undo-bar-message-comment = Comment removed
564565
# Variables:
565566
# $count (Number) - the number of removed annotations.
566567
pdfjs-editor-undo-bar-message-multiple =

src/display/editor/tools.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,22 @@ class AnnotationEditorUIManager {
11771177
this.#commentManager?.removeComments([editor.uid]);
11781178
}
11791179

1180+
/**
1181+
* Delete a comment from an editor with undo support.
1182+
* @param {AnnotationEditor} editor - The editor whose comment to delete.
1183+
* @param {string} savedComment - The comment text to save for undo.
1184+
*/
1185+
deleteComment(editor, savedComment) {
1186+
const undo = () => {
1187+
editor.comment = savedComment;
1188+
};
1189+
const cmd = () => {
1190+
this._editorUndoBar?.show(undo, "comment");
1191+
editor.comment = null;
1192+
};
1193+
this.addCommands({ cmd, undo, mustExec: true });
1194+
}
1195+
11801196
toggleComment(editor, isSelected, visibility = undefined) {
11811197
this.#commentManager?.toggleCommentPopup(editor, isSelected, visibility);
11821198
}

test/integration/comment_spec.mjs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,4 +965,159 @@ describe("Comment", () => {
965965
);
966966
});
967967
});
968+
969+
describe("Undo deletion popup for comments (bug 1999154)", () => {
970+
let pages;
971+
972+
beforeEach(async () => {
973+
pages = await loadAndWait(
974+
"tracemonkey.pdf",
975+
".annotationEditorLayer",
976+
"page-fit",
977+
null,
978+
{ enableComment: true }
979+
);
980+
});
981+
982+
afterEach(async () => {
983+
await closePages(pages);
984+
});
985+
986+
it("must check that deleting a comment can be undone using the undo button", async () => {
987+
await Promise.all(
988+
pages.map(async ([browserName, page]) => {
989+
await switchToHighlight(page);
990+
await highlightSpan(page, 1, "Abstract");
991+
const editorSelector = getEditorSelector(0);
992+
const comment = "Test comment for undo";
993+
await editComment(page, editorSelector, comment);
994+
995+
// Stay in highlight mode - don't disable it
996+
await waitAndClick(
997+
page,
998+
`${editorSelector} .annotationCommentButton`
999+
);
1000+
1001+
await page.waitForSelector("#commentPopup", { visible: true });
1002+
await waitAndClick(page, "button.commentPopupDelete");
1003+
1004+
await page.waitForSelector("#editorUndoBar", { visible: true });
1005+
await page.waitForSelector("#editorUndoBarUndoButton", {
1006+
visible: true,
1007+
});
1008+
await page.click("#editorUndoBarUndoButton");
1009+
1010+
// Check that the comment is restored by hovering to show the popup
1011+
await page.hover(`${editorSelector} .annotationCommentButton`);
1012+
await page.waitForSelector("#commentPopup", { visible: true });
1013+
const popupText = await page.evaluate(
1014+
() =>
1015+
document.querySelector("#commentPopup .commentPopupText")
1016+
?.textContent
1017+
);
1018+
expect(popupText).withContext(`In ${browserName}`).toEqual(comment);
1019+
})
1020+
);
1021+
});
1022+
1023+
it("must check that the undo deletion popup displays 'Comment removed' message", async () => {
1024+
await Promise.all(
1025+
pages.map(async ([browserName, page]) => {
1026+
await switchToHighlight(page);
1027+
await highlightSpan(page, 1, "Abstract");
1028+
const editorSelector = getEditorSelector(0);
1029+
await editComment(page, editorSelector, "Test comment");
1030+
1031+
// Stay in highlight mode - don't disable it
1032+
await waitAndClick(
1033+
page,
1034+
`${editorSelector} .annotationCommentButton`
1035+
);
1036+
1037+
await page.waitForSelector("#commentPopup", { visible: true });
1038+
await waitAndClick(page, "button.commentPopupDelete");
1039+
1040+
await page.waitForFunction(() => {
1041+
const messageElement = document.querySelector(
1042+
"#editorUndoBarMessage"
1043+
);
1044+
return messageElement && messageElement.textContent.trim() !== "";
1045+
});
1046+
const message = await page.waitForSelector("#editorUndoBarMessage");
1047+
const messageText = await page.evaluate(
1048+
el => el.textContent,
1049+
message
1050+
);
1051+
expect(messageText)
1052+
.withContext(`In ${browserName}`)
1053+
.toContain("Comment removed");
1054+
})
1055+
);
1056+
});
1057+
1058+
it("must check that the undo bar closes when clicking the close button", async () => {
1059+
await Promise.all(
1060+
pages.map(async ([browserName, page]) => {
1061+
await switchToHighlight(page);
1062+
await highlightSpan(page, 1, "Abstract");
1063+
const editorSelector = getEditorSelector(0);
1064+
await editComment(page, editorSelector, "Test comment");
1065+
1066+
// Stay in highlight mode - don't disable it
1067+
await waitAndClick(
1068+
page,
1069+
`${editorSelector} .annotationCommentButton`
1070+
);
1071+
1072+
await page.waitForSelector("#commentPopup", { visible: true });
1073+
await waitAndClick(page, "button.commentPopupDelete");
1074+
1075+
await page.waitForSelector("#editorUndoBar", { visible: true });
1076+
await waitAndClick(page, "#editorUndoBarCloseButton");
1077+
await page.waitForSelector("#editorUndoBar", { hidden: true });
1078+
})
1079+
);
1080+
});
1081+
1082+
it("must check that deleting a comment can be undone using Ctrl+Z", async () => {
1083+
await Promise.all(
1084+
pages.map(async ([browserName, page]) => {
1085+
await switchToHighlight(page);
1086+
await highlightSpan(page, 1, "Abstract");
1087+
const editorSelector = getEditorSelector(0);
1088+
const comment = "Test comment for Ctrl+Z undo";
1089+
await editComment(page, editorSelector, comment);
1090+
1091+
// Stay in highlight mode - don't disable it
1092+
await waitAndClick(
1093+
page,
1094+
`${editorSelector} .annotationCommentButton`
1095+
);
1096+
1097+
await page.waitForSelector("#commentPopup", { visible: true });
1098+
await waitAndClick(page, "button.commentPopupDelete");
1099+
1100+
await page.waitForSelector("#editorUndoBar", { visible: true });
1101+
1102+
// Use Ctrl+Z to undo
1103+
await kbModifierDown(page);
1104+
await page.keyboard.press("z");
1105+
await kbModifierUp(page);
1106+
1107+
// The undo bar should be hidden after undo
1108+
await page.waitForSelector("#editorUndoBar", { hidden: true });
1109+
1110+
// Check that the comment is restored by hovering to show the popup
1111+
await page.hover(`${editorSelector} .annotationCommentButton`);
1112+
await page.waitForSelector("#commentPopup", { visible: true });
1113+
const popupText = await page.evaluate(
1114+
() =>
1115+
document.querySelector("#commentPopup .commentPopupText")
1116+
?.textContent
1117+
);
1118+
expect(popupText).withContext(`In ${browserName}`).toEqual(comment);
1119+
})
1120+
);
1121+
});
1122+
});
9681123
});

web/comment_manager.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -982,9 +982,15 @@ class CommentPopup {
982982
},
983983
},
984984
});
985-
this.#editor.comment = null;
986-
this.#editor.focus();
985+
const savedComment = this.#editor.comment?.text;
986+
const editor = this.#editor;
987987
this.destroy();
988+
if (savedComment) {
989+
editor._uiManager.deleteComment(editor, savedComment);
990+
} else {
991+
editor.comment = null;
992+
}
993+
editor.focus();
988994
});
989995
del.addEventListener("contextmenu", noContextMenu);
990996
buttons.append(edit, del);

web/editor_undo_bar.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class EditorUndoBar {
4040
stamp: "pdfjs-editor-undo-bar-message-stamp",
4141
ink: "pdfjs-editor-undo-bar-message-ink",
4242
signature: "pdfjs-editor-undo-bar-message-signature",
43+
comment: "pdfjs-editor-undo-bar-message-comment",
4344
_multiple: "pdfjs-editor-undo-bar-message-multiple",
4445
});
4546

0 commit comments

Comments
 (0)