Skip to content

Commit

Permalink
Merge pull request #17823 from calixteman/bug1886959
Browse files Browse the repository at this point in the history
[Editor] Fix undoing an editor deletion (bug 1886959)
  • Loading branch information
calixteman authored Mar 25, 2024
2 parents b0f54b2 + d5a0e55 commit 3fbd6b5
Show file tree
Hide file tree
Showing 10 changed files with 574 additions and 11 deletions.
5 changes: 2 additions & 3 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -441,9 +441,6 @@ class AnnotationEditorLayer {
* @param {AnnotationEditor} editor
*/
remove(editor) {
// Since we can undo a removal we need to keep the
// parent property as it is, so don't null it!

this.detach(editor);
this.#uiManager.removeEditor(editor);
editor.div.remove();
Expand Down Expand Up @@ -546,6 +543,7 @@ class AnnotationEditorLayer {
if (editor.needsToBeRebuilt()) {
editor.parent ||= this;
editor.rebuild();
editor.show();
} else {
this.add(editor);
}
Expand Down Expand Up @@ -842,6 +840,7 @@ class AnnotationEditorLayer {
setLayerDimensions(this.div, viewport);
for (const editor of this.#uiManager.getEditors(this.pageIndex)) {
this.add(editor);
editor.rebuild();
}
// We're maybe rendering a layer which was invisible when we started to edit
// so we must set the different callbacks for it.
Expand Down
6 changes: 3 additions & 3 deletions src/display/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -1270,7 +1270,6 @@ class AnnotationEditor {
rebuild() {
this.div?.addEventListener("focusin", this.#boundFocusin);
this.div?.addEventListener("focusout", this.#boundFocusout);
this.show(this._isVisible);
}

/**
Expand Down Expand Up @@ -1354,6 +1353,7 @@ class AnnotationEditor {
}
this.#telemetryTimeouts = null;
}
this.parent = null;
}

/**
Expand Down Expand Up @@ -1676,9 +1676,9 @@ class AnnotationEditor {

/**
* Show or hide this editor.
* @param {boolean} visible
* @param {boolean|undefined} visible
*/
show(visible) {
show(visible = this._isVisible) {
this.div.classList.toggle("hidden", !visible);
this._isVisible = visible;
}
Expand Down
11 changes: 9 additions & 2 deletions src/display/editor/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,11 +418,11 @@ class HighlightEditor extends AnnotationEditor {

/** @inheritdoc */
remove() {
super.remove();
this.#cleanDrawLayer();
this._reportTelemetry({
action: "deleted",
});
super.remove();
}

/** @inheritdoc */
Expand Down Expand Up @@ -628,13 +628,19 @@ class HighlightEditor extends AnnotationEditor {
/** @inheritdoc */
select() {
super.select();
if (!this.#outlineId) {
return;
}
this.parent?.drawLayer.removeClass(this.#outlineId, "hovered");
this.parent?.drawLayer.addClass(this.#outlineId, "selected");
}

/** @inheritdoc */
unselect() {
super.unselect();
if (!this.#outlineId) {
return;
}
this.parent?.drawLayer.removeClass(this.#outlineId, "selected");
if (!this.#isFreeHighlight) {
this.#setCaret(/* start = */ false);
Expand All @@ -646,7 +652,8 @@ class HighlightEditor extends AnnotationEditor {
return !this.#isFreeHighlight;
}

show(visible) {
/** @inheritdoc */
show(visible = this._isVisible) {
super.show(visible);
if (this.parent) {
this.parent.drawLayer.show(this.#id, visible);
Expand Down
2 changes: 1 addition & 1 deletion src/display/editor/ink.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ class InkEditor extends AnnotationEditor {
this.allRawPaths.push(currentPath);
this.paths.push(bezier);
this.bezierPath2D.push(path2D);
this.rebuild();
this._uiManager.rebuild(this);
};

const undo = () => {
Expand Down
5 changes: 3 additions & 2 deletions src/display/editor/stamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class StampEditor extends AnnotationEditor {
return;
}

if (this.#bitmapId) {
if (this.#bitmapId && this.#canvas === null) {
this.#getBitmap();
}

Expand All @@ -241,7 +241,8 @@ class StampEditor extends AnnotationEditor {
this.#bitmapPromise ||
this.#bitmap ||
this.#bitmapUrl ||
this.#bitmapFile
this.#bitmapFile ||
this.#bitmapId
);
}

Expand Down
1 change: 1 addition & 0 deletions src/display/editor/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,7 @@ class AnnotationEditorUIManager {
layer.addOrRebuild(editor);
} else {
this.addEditor(editor);
this.addToAnnotationStorage(editor);
}
}

Expand Down
115 changes: 115 additions & 0 deletions test/integration/freetext_editor_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3431,4 +3431,119 @@ describe("FreeText Editor", () => {
);
});
});

describe("Delete a freetext and undo it on another page", () => {
let pages;

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

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

it("must check that a freetext can be undone", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await switchToFreeText(page);

const rect = await page.$eval(".annotationEditorLayer", el => {
const { x, y } = el.getBoundingClientRect();
return { x, y };
});

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);

const twoToFourteen = Array.from(new Array(13).keys(), n => n + 2);
for (const pageNumber of twoToFourteen) {
const pageSelector = `.page[data-page-number = "${pageNumber}"]`;
await scrollIntoView(page, pageSelector);
}

await kbUndo(page);
await waitForSerialized(page, 1);

const thirteenToOne = Array.from(new Array(13).keys(), n => 13 - n);
for (const pageNumber of thirteenToOne) {
const pageSelector = `.page[data-page-number = "${pageNumber}"]`;
await scrollIntoView(page, pageSelector);
}

await page.waitForSelector(getEditorSelector(0));
})
);
});
});

describe("Delete a freetext, scroll and undo it", () => {
let pages;

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

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

it("must check that a freetext can be undone", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await switchToFreeText(page);

const rect = await page.$eval(".annotationEditorLayer", el => {
const { x, y } = el.getBoundingClientRect();
return { x, y };
});

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);

const twoToOne = Array.from(new Array(13).keys(), n => n + 2).concat(
Array.from(new Array(13).keys(), n => 13 - n)
);
for (const pageNumber of twoToOne) {
const pageSelector = `.page[data-page-number = "${pageNumber}"]`;
await scrollIntoView(page, pageSelector);
}

await kbUndo(page);
await waitForSerialized(page, 1);
await page.waitForSelector(getEditorSelector(0));
})
);
});
});
});
Loading

0 comments on commit 3fbd6b5

Please sign in to comment.