Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotation deletion popup (bug 1899731) #18900

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
17 changes: 17 additions & 0 deletions l10n/en-US/viewer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,20 @@ pdfjs-editor-alt-text-settings-editor-title = Alt text editor
pdfjs-editor-alt-text-settings-show-dialog-button-label = Show alt text editor right away when adding an image
pdfjs-editor-alt-text-settings-show-dialog-description = Helps you make sure all your images have alt text.
pdfjs-editor-alt-text-settings-close-button = Close

## "Annotations removed" bar

pdfjs-editor-undo-bar-message-highlight = Highlight removed
pdfjs-editor-undo-bar-message-freetext = Text removed
pdfjs-editor-undo-bar-message-ink = Drawing removed
pdfjs-editor-undo-bar-message-stamp = Image removed
# Variables:
# $count (Number) - the number of removed annotations.
pdfjs-editor-undo-bar-message-multiple = { $count } annotations removed

pdfjs-editor-undo-bar-undo-button =
.title = Undo
pdfjs-editor-undo-bar-undo-button-label = Undo
pdfjs-editor-undo-bar-close-button =
.title = Close
pdfjs-editor-undo-bar-close-button-label = Close
3 changes: 3 additions & 0 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,9 @@ class AnnotationEditorLayer {
// Do nothing on right click.
return;
}

this.#uiManager._editorUndoBar?.hide();

this.#uiManager.showAllEditors(
"highlight",
true,
Expand Down
2 changes: 2 additions & 0 deletions src/display/editor/freetext.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@ class FreeTextEditor extends AnnotationEditor {
return this.div;
}

this._uiManager._editorUndoBar?.hide();

let baseX, baseY;
if (this.width) {
baseX = this.x;
Expand Down
2 changes: 2 additions & 0 deletions src/display/editor/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,8 @@ class HighlightEditor extends AnnotationEditor {
return this.div;
}

this._uiManager._editorUndoBar?.hide();

const div = super.render();
if (this.#text) {
div.setAttribute("aria-label", this.#text);
Expand Down
1 change: 1 addition & 0 deletions src/display/editor/ink.js
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ class InkEditor extends AnnotationEditor {
});
}

this._uiManager._editorUndoBar?.hide();
this.#startDrawing(event.offsetX, event.offsetY);
}

Expand Down
2 changes: 2 additions & 0 deletions src/display/editor/stamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ class StampEditor extends AnnotationEditor {
return this.div;
}

this._uiManager._editorUndoBar?.hide();

let baseX, baseY;
if (this.width) {
baseX = this.x;
Expand Down
10 changes: 9 additions & 1 deletion src/display/editor/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ class AnnotationEditorUIManager {

#editorsToRescale = new Set();

_editorUndoBar = null;

#enableHighlightFloatingButton = false;

#enableUpdatedAddImage = false;
Expand Down Expand Up @@ -814,7 +816,8 @@ class AnnotationEditorUIManager {
enableHighlightFloatingButton,
enableUpdatedAddImage,
enableNewAltTextWhenAddingImage,
mlManager
mlManager,
editorUndoBar
) {
const signal = (this._signal = this.#abortController.signal);
this.#container = container;
Expand Down Expand Up @@ -849,6 +852,7 @@ class AnnotationEditorUIManager {
rotation: 0,
};
this.isShiftKeyDown = false;
this._editorUndoBar = editorUndoBar;

if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
Object.defineProperty(this, "reset", {
Expand Down Expand Up @@ -2069,6 +2073,10 @@ class AnnotationEditorUIManager {

const editors = [...this.#selectedEditors];
const cmd = () => {
this._editorUndoBar?.show(
undo,
editors.length === 1 ? editors[0].editorType : editors.length
);
for (const editor of editors) {
editor.remove();
}
Expand Down
126 changes: 126 additions & 0 deletions test/integration/freetext_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3688,4 +3688,130 @@ describe("FreeText Editor", () => {
);
});
});

describe("Undo deletion popup has the expected behaviour", () => {
let pages;

beforeEach(async () => {
pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer");
});

afterEach(async () => {
await closePages(pages);
});

it("must check that deleting a FreeText editor can be undone using the undo button", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await switchToFreeText(page);

const rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100);
await page.waitForSelector(getEditorSelector(0), {
visible: true,
});
await page.type(`${getEditorSelector(0)} .internal`, data);

// Commit.
await page.keyboard.press("Escape");
await page.waitForSelector(
`${getEditorSelector(0)} .overlay.enabled`
);
await waitForSerialized(page, 1);

await page.waitForSelector(`${getEditorSelector(0)} button.delete`);
await page.click(`${getEditorSelector(0)} button.delete`);
await waitForSerialized(page, 0);

await page.waitForSelector("#editorUndoBar:not([hidden])");
await page.click("#editorUndoBarUndoButton");
await waitForSerialized(page, 1);
await page.waitForSelector(getEditorSelector(0));
})
);
});

it("must check that the undo deletion popup displays the correct message", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await switchToFreeText(page);

const rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100);
await page.waitForSelector(getEditorSelector(0), {
visible: true,
});
await page.type(`${getEditorSelector(0)} .internal`, data);

// Commit.
await page.keyboard.press("Escape");
await page.waitForSelector(
`${getEditorSelector(0)} .overlay.enabled`
);
await waitForSerialized(page, 1);

await page.waitForSelector(`${getEditorSelector(0)} button.delete`);
await page.click(`${getEditorSelector(0)} button.delete`);
await waitForSerialized(page, 0);

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).toContain("Text removed");
})
);
});

it("must check that the popup disappears when a new textbox is created", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await switchToFreeText(page);

let rect = await getRect(page, ".annotationEditorLayer");
const data = "Hello PDF.js World !!";
await page.mouse.click(rect.x + 100, rect.y + 100);
await page.waitForSelector(getEditorSelector(0), {
visible: true,
});
await page.type(`${getEditorSelector(0)} .internal`, data);

await page.keyboard.press("Escape");
await page.waitForSelector(
`${getEditorSelector(0)} .overlay.enabled`
);
await waitForSerialized(page, 1);

await page.waitForSelector(`${getEditorSelector(0)} button.delete`);
await page.click(`${getEditorSelector(0)} button.delete`);
await waitForSerialized(page, 0);

await page.waitForSelector("#editorUndoBar:not([hidden])");
rect = await getRect(page, ".annotationEditorLayer");
const newData = "This is a new text box!";
await page.mouse.click(rect.x + 150, rect.y + 150);
await page.waitForSelector(getEditorSelector(1), {
visible: true,
});
await page.type(`${getEditorSelector(1)} .internal`, newData);

await page.keyboard.press("Escape");
await page.waitForSelector(
`${getEditorSelector(1)} .overlay.enabled`
);
await waitForSerialized(page, 1);
await page.waitForSelector("#editorUndoBar", { hidden: true });
})
);
});
});
});
Loading