Merge pull request #18800 from calixteman/popup_deletion
[Editor] When deleting an annotation with popup, then delete the popup too
This commit is contained in:
commit
c46ac3f73f
@ -284,6 +284,12 @@ class Page {
|
|||||||
}
|
}
|
||||||
if (annotation.deleted) {
|
if (annotation.deleted) {
|
||||||
deletedAnnotations.put(ref, ref);
|
deletedAnnotations.put(ref, ref);
|
||||||
|
if (annotation.popupRef) {
|
||||||
|
const popupRef = Ref.fromString(annotation.popupRef);
|
||||||
|
if (popupRef) {
|
||||||
|
deletedAnnotations.put(popupRef, popupRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
existingAnnotations?.put(ref);
|
existingAnnotations?.put(ref);
|
||||||
|
|||||||
@ -80,6 +80,8 @@ class AnnotationEditor {
|
|||||||
|
|
||||||
_initialOptions = Object.create(null);
|
_initialOptions = Object.create(null);
|
||||||
|
|
||||||
|
_initialData = null;
|
||||||
|
|
||||||
_isVisible = true;
|
_isVisible = true;
|
||||||
|
|
||||||
_uiManager = null;
|
_uiManager = null;
|
||||||
@ -1335,6 +1337,19 @@ class AnnotationEditor {
|
|||||||
*/
|
*/
|
||||||
rotate(_angle) {}
|
rotate(_angle) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the editor when it has been deleted.
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
serializeDeleted() {
|
||||||
|
return {
|
||||||
|
id: this.annotationElementId,
|
||||||
|
deleted: true,
|
||||||
|
pageIndex: this.pageIndex,
|
||||||
|
popupRef: this._initialData?.popupRef || "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the editor.
|
* Serialize the editor.
|
||||||
* The result of the serialization will be used to construct a
|
* The result of the serialization will be used to construct a
|
||||||
@ -1809,11 +1824,7 @@ class FakeEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serialize() {
|
serialize() {
|
||||||
return {
|
return this.serializeDeleted();
|
||||||
id: this.annotationElementId,
|
|
||||||
deleted: true,
|
|
||||||
pageIndex: this.pageIndex,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,6 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
|
|
||||||
#fontSize;
|
#fontSize;
|
||||||
|
|
||||||
#initialData = null;
|
|
||||||
|
|
||||||
static _freeTextDefaultContent = "";
|
static _freeTextDefaultContent = "";
|
||||||
|
|
||||||
static _internalPadding = 0;
|
static _internalPadding = 0;
|
||||||
@ -598,7 +596,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
|
|
||||||
// position is the position of the first glyph in the annotation
|
// position is the position of the first glyph in the annotation
|
||||||
// and it's relative to its container.
|
// and it's relative to its container.
|
||||||
const { position } = this.#initialData;
|
const { position } = this._initialData;
|
||||||
let [tx, ty] = this.getInitialTranslation();
|
let [tx, ty] = this.getInitialTranslation();
|
||||||
[tx, ty] = this.pageTranslationToScreen(tx, ty);
|
[tx, ty] = this.pageTranslationToScreen(tx, ty);
|
||||||
const [pageWidth, pageHeight] = this.pageDimensions;
|
const [pageWidth, pageHeight] = this.pageDimensions;
|
||||||
@ -781,6 +779,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
rect,
|
rect,
|
||||||
rotation,
|
rotation,
|
||||||
id,
|
id,
|
||||||
|
popupRef,
|
||||||
},
|
},
|
||||||
textContent,
|
textContent,
|
||||||
textPosition,
|
textPosition,
|
||||||
@ -805,6 +804,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
rotation,
|
rotation,
|
||||||
id,
|
id,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
popupRef,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const editor = super.deserialize(data, parent, uiManager);
|
const editor = super.deserialize(data, parent, uiManager);
|
||||||
@ -812,7 +812,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
editor.#color = Util.makeHexColor(...data.color);
|
editor.#color = Util.makeHexColor(...data.color);
|
||||||
editor.#content = FreeTextEditor.#deserializeContent(data.value);
|
editor.#content = FreeTextEditor.#deserializeContent(data.value);
|
||||||
editor.annotationElementId = data.id || null;
|
editor.annotationElementId = data.id || null;
|
||||||
editor.#initialData = initialData;
|
editor._initialData = initialData;
|
||||||
|
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
@ -824,11 +824,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.deleted) {
|
if (this.deleted) {
|
||||||
return {
|
return this.serializeDeleted();
|
||||||
pageIndex: this.pageIndex,
|
|
||||||
id: this.annotationElementId,
|
|
||||||
deleted: true,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const padding = FreeTextEditor._internalPadding * this.parentScale;
|
const padding = FreeTextEditor._internalPadding * this.parentScale;
|
||||||
@ -866,7 +862,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#hasElementChanged(serialized) {
|
#hasElementChanged(serialized) {
|
||||||
const { value, fontSize, color, pageIndex } = this.#initialData;
|
const { value, fontSize, color, pageIndex } = this._initialData;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this._hasBeenMoved ||
|
this._hasBeenMoved ||
|
||||||
|
|||||||
@ -55,8 +55,6 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
|
|
||||||
#id = null;
|
#id = null;
|
||||||
|
|
||||||
#initialData = null;
|
|
||||||
|
|
||||||
#isFreeHighlight = false;
|
#isFreeHighlight = false;
|
||||||
|
|
||||||
#lastPoint = null;
|
#lastPoint = null;
|
||||||
@ -785,7 +783,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
let initialData = null;
|
let initialData = null;
|
||||||
if (data instanceof HighlightAnnotationElement) {
|
if (data instanceof HighlightAnnotationElement) {
|
||||||
const {
|
const {
|
||||||
data: { quadPoints, rect, rotation, id, color, opacity },
|
data: { quadPoints, rect, rotation, id, color, opacity, popupRef },
|
||||||
parent: {
|
parent: {
|
||||||
page: { pageNumber },
|
page: { pageNumber },
|
||||||
},
|
},
|
||||||
@ -801,6 +799,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
rotation,
|
rotation,
|
||||||
id,
|
id,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
popupRef,
|
||||||
};
|
};
|
||||||
} else if (data instanceof InkAnnotationElement) {
|
} else if (data instanceof InkAnnotationElement) {
|
||||||
const {
|
const {
|
||||||
@ -811,6 +810,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
id,
|
id,
|
||||||
color,
|
color,
|
||||||
borderStyle: { rawWidth: thickness },
|
borderStyle: { rawWidth: thickness },
|
||||||
|
popupRef,
|
||||||
},
|
},
|
||||||
parent: {
|
parent: {
|
||||||
page: { pageNumber },
|
page: { pageNumber },
|
||||||
@ -827,6 +827,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
rotation,
|
rotation,
|
||||||
id,
|
id,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
popupRef,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -839,7 +840,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
editor.#thickness = data.thickness;
|
editor.#thickness = data.thickness;
|
||||||
}
|
}
|
||||||
editor.annotationElementId = data.id || null;
|
editor.annotationElementId = data.id || null;
|
||||||
editor.#initialData = initialData;
|
editor._initialData = initialData;
|
||||||
|
|
||||||
const [pageWidth, pageHeight] = editor.pageDimensions;
|
const [pageWidth, pageHeight] = editor.pageDimensions;
|
||||||
const [pageX, pageY] = editor.pageTranslation;
|
const [pageX, pageY] = editor.pageTranslation;
|
||||||
@ -902,11 +903,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.deleted) {
|
if (this.deleted) {
|
||||||
return {
|
return this.serializeDeleted();
|
||||||
pageIndex: this.pageIndex,
|
|
||||||
id: this.annotationElementId,
|
|
||||||
deleted: true,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rect = this.getRect(0, 0);
|
const rect = this.getRect(0, 0);
|
||||||
@ -934,7 +931,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#hasElementChanged(serialized) {
|
#hasElementChanged(serialized) {
|
||||||
const { color } = this.#initialData;
|
const { color } = this._initialData;
|
||||||
return serialized.color.some((c, i) => c !== color[i]);
|
return serialized.color.some((c, i) => c !== color[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1237,6 +1237,7 @@ describe("FreeText Editor", () => {
|
|||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
id: "51R",
|
id: "51R",
|
||||||
deleted: true,
|
deleted: true,
|
||||||
|
popupRef: "",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@ -1972,6 +1972,50 @@ describe("Highlight Editor", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Highlight (delete an existing annotation)", () => {
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
pages = await loadAndWait(
|
||||||
|
"highlight_popup.pdf",
|
||||||
|
".annotationEditorLayer"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must delete an existing annotation and its popup", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
const modeChangedHandle = await waitForAnnotationModeChanged(page);
|
||||||
|
await waitAndClick(page, "[data-annotation-id='24R']", { count: 2 });
|
||||||
|
await awaitPromise(modeChangedHandle);
|
||||||
|
await page.waitForSelector("#highlightParamsToolbarContainer");
|
||||||
|
|
||||||
|
const editorSelector = getEditorSelector(0);
|
||||||
|
await page.waitForSelector(editorSelector);
|
||||||
|
await page.waitForSelector(`${editorSelector} button.delete`);
|
||||||
|
await page.click(`${editorSelector} button.delete`);
|
||||||
|
await waitForSerialized(page, 1);
|
||||||
|
|
||||||
|
const serialized = await getSerialized(page);
|
||||||
|
expect(serialized)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual([
|
||||||
|
{
|
||||||
|
pageIndex: 0,
|
||||||
|
id: "24R",
|
||||||
|
deleted: true,
|
||||||
|
popupRef: "25R",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("Free Highlight (edit existing in double clicking on it)", () => {
|
describe("Free Highlight (edit existing in double clicking on it)", () => {
|
||||||
let pages;
|
let pages;
|
||||||
|
|
||||||
|
|||||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -670,3 +670,4 @@
|
|||||||
!bug1918115.pdf
|
!bug1918115.pdf
|
||||||
!bug1919513.pdf
|
!bug1919513.pdf
|
||||||
!issue16038.pdf
|
!issue16038.pdf
|
||||||
|
!highlight_popup.pdf
|
||||||
|
|||||||
BIN
test/pdfs/highlight_popup.pdf
Executable file
BIN
test/pdfs/highlight_popup.pdf
Executable file
Binary file not shown.
@ -2926,6 +2926,29 @@ describe("api", function () {
|
|||||||
await loadingTask.destroy();
|
await loadingTask.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("write an highlight annotation and delete its popup", async function () {
|
||||||
|
let loadingTask = getDocument(
|
||||||
|
buildGetDocumentParams("highlight_popup.pdf")
|
||||||
|
);
|
||||||
|
let pdfDoc = await loadingTask.promise;
|
||||||
|
pdfDoc.annotationStorage.setValue("pdfjs_internal_editor_0", {
|
||||||
|
deleted: true,
|
||||||
|
id: "24R",
|
||||||
|
pageIndex: 0,
|
||||||
|
popupRef: "25R",
|
||||||
|
});
|
||||||
|
const data = await pdfDoc.saveDocument();
|
||||||
|
await loadingTask.destroy();
|
||||||
|
|
||||||
|
loadingTask = getDocument(data);
|
||||||
|
pdfDoc = await loadingTask.promise;
|
||||||
|
const page = await pdfDoc.getPage(1);
|
||||||
|
const annotations = await page.getAnnotations();
|
||||||
|
|
||||||
|
expect(annotations).toEqual([]);
|
||||||
|
await loadingTask.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
it("read content from multiline textfield containing an empty line", async function () {
|
it("read content from multiline textfield containing an empty line", async function () {
|
||||||
const loadingTask = getDocument(buildGetDocumentParams("issue17492.pdf"));
|
const loadingTask = getDocument(buildGetDocumentParams("issue17492.pdf"));
|
||||||
const pdfDoc = await loadingTask.promise;
|
const pdfDoc = await loadingTask.promise;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user