[Editor] Update the color and the position of the comment button in reading mode they've been modified
This commit is contained in:
parent
ae3c23e28a
commit
0b40bf1743
@ -202,7 +202,19 @@ class AnnotationElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get hasPopupData() {
|
get hasPopupData() {
|
||||||
return AnnotationElement._hasPopupData(this.data);
|
return (
|
||||||
|
AnnotationElement._hasPopupData(this.data) ||
|
||||||
|
(this.enableComment && !!this.commentText)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get commentData() {
|
||||||
|
const { data } = this;
|
||||||
|
const editor = this.annotationStorage?.getEditor(data.id);
|
||||||
|
if (editor) {
|
||||||
|
return editor.getData();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasCommentButton() {
|
get hasCommentButton() {
|
||||||
@ -210,7 +222,11 @@ class AnnotationElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get commentButtonPosition() {
|
get commentButtonPosition() {
|
||||||
const { quadPoints, rect } = this.data;
|
const editor = this.annotationStorage?.getEditor(this.data.id);
|
||||||
|
if (editor) {
|
||||||
|
return editor.commentButtonPositionInPage;
|
||||||
|
}
|
||||||
|
const { quadPoints, inkLists, rect } = this.data;
|
||||||
let maxX = -Infinity;
|
let maxX = -Infinity;
|
||||||
let maxY = -Infinity;
|
let maxY = -Infinity;
|
||||||
if (quadPoints?.length >= 8) {
|
if (quadPoints?.length >= 8) {
|
||||||
@ -224,6 +240,21 @@ class AnnotationElement {
|
|||||||
}
|
}
|
||||||
return [maxX, maxY];
|
return [maxX, maxY];
|
||||||
}
|
}
|
||||||
|
if (inkLists?.length >= 1) {
|
||||||
|
for (const inkList of inkLists) {
|
||||||
|
for (let i = 0, ii = inkList.length; i < ii; i += 2) {
|
||||||
|
if (inkList[i + 1] > maxY) {
|
||||||
|
maxY = inkList[i + 1];
|
||||||
|
maxX = inkList[i];
|
||||||
|
} else if (inkList[i + 1] === maxY) {
|
||||||
|
maxX = Math.max(maxX, inkList[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxX !== Infinity) {
|
||||||
|
return [maxX, maxY];
|
||||||
|
}
|
||||||
|
}
|
||||||
if (rect) {
|
if (rect) {
|
||||||
return [rect[2], rect[3]];
|
return [rect[2], rect[3]];
|
||||||
}
|
}
|
||||||
@ -2380,7 +2411,6 @@ class PopupElement {
|
|||||||
this.#dateObj = PDFDateString.toDateObject(modificationDate);
|
this.#dateObj = PDFDateString.toDateObject(modificationDate);
|
||||||
|
|
||||||
if (commentManager) {
|
if (commentManager) {
|
||||||
this.#popupAbortController = new AbortController();
|
|
||||||
this.#renderCommentButton();
|
this.#renderCommentButton();
|
||||||
} else {
|
} else {
|
||||||
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
|
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
|
||||||
@ -2457,7 +2487,7 @@ class PopupElement {
|
|||||||
button.ariaHasPopup = "dialog";
|
button.ariaHasPopup = "dialog";
|
||||||
button.ariaControls = "commentPopup";
|
button.ariaControls = "commentPopup";
|
||||||
|
|
||||||
const { signal } = this.#popupAbortController;
|
const { signal } = (this.#popupAbortController = new AbortController());
|
||||||
button.addEventListener("keydown", this.#boundKeyDown, { signal });
|
button.addEventListener("keydown", this.#boundKeyDown, { signal });
|
||||||
button.addEventListener(
|
button.addEventListener(
|
||||||
"click",
|
"click",
|
||||||
@ -2488,19 +2518,26 @@ class PopupElement {
|
|||||||
},
|
},
|
||||||
{ signal }
|
{ signal }
|
||||||
);
|
);
|
||||||
const { style } = button;
|
this.#updateColor();
|
||||||
style.left = `calc(${this.#commentButtonPosition[0]}%)`;
|
this.#updateCommentButtonPosition();
|
||||||
style.top = `calc(${this.#commentButtonPosition[1]}% - var(--comment-button-dim))`;
|
|
||||||
if (this.commentButtonColor) {
|
|
||||||
style.backgroundColor = this.commentButtonColor;
|
|
||||||
}
|
|
||||||
parentContainer.after(button);
|
parentContainer.after(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#updateCommentButtonPosition() {
|
||||||
|
this.#renderCommentButton();
|
||||||
|
const [x, y] = this.#commentButtonPosition;
|
||||||
|
const { style } = this.#commentButton;
|
||||||
|
style.left = `calc(${x}%)`;
|
||||||
|
style.top = `calc(${y}% - var(--comment-button-dim))`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateColor() {
|
||||||
|
this.#renderCommentButton();
|
||||||
|
this.#commentButton.style.backgroundColor = this.commentButtonColor || "";
|
||||||
|
}
|
||||||
|
|
||||||
get commentButtonColor() {
|
get commentButtonColor() {
|
||||||
const {
|
const { color, opacity } = this.#firstElement.commentData;
|
||||||
data: { color, opacity },
|
|
||||||
} = this.#firstElement;
|
|
||||||
if (!color) {
|
if (!color) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -2509,7 +2546,7 @@ class PopupElement {
|
|||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
const { richText, color, opacity, creationDate, modificationDate } =
|
const { richText, color, opacity, creationDate, modificationDate } =
|
||||||
this.#firstElement.data;
|
this.#firstElement.commentData;
|
||||||
return {
|
return {
|
||||||
contentsObj: { str: this.comment },
|
contentsObj: { str: this.comment },
|
||||||
richText,
|
richText,
|
||||||
@ -2743,7 +2780,22 @@ class PopupElement {
|
|||||||
|
|
||||||
updateEdited({ rect, popup, deleted }) {
|
updateEdited({ rect, popup, deleted }) {
|
||||||
if (this.#commentManager) {
|
if (this.#commentManager) {
|
||||||
this.#commentText = deleted ? null : popup.text;
|
if (deleted) {
|
||||||
|
this.remove();
|
||||||
|
this.#commentText = null;
|
||||||
|
} else if (popup) {
|
||||||
|
if (popup.deleted) {
|
||||||
|
this.remove();
|
||||||
|
} else {
|
||||||
|
this.#updateColor();
|
||||||
|
this.#commentText = popup.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rect) {
|
||||||
|
this.#commentButtonPosition = null;
|
||||||
|
this.#setCommentButtonPosition();
|
||||||
|
this.#updateCommentButtonPosition();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (deleted || popup?.deleted) {
|
if (deleted || popup?.deleted) {
|
||||||
@ -2758,7 +2810,7 @@ class PopupElement {
|
|||||||
if (rect) {
|
if (rect) {
|
||||||
this.#position = null;
|
this.#position = null;
|
||||||
}
|
}
|
||||||
if (popup) {
|
if (popup && popup.text) {
|
||||||
this.#richText = this.#makePopupContent(popup.text);
|
this.#richText = this.#makePopupContent(popup.text);
|
||||||
this.#dateObj = PDFDateString.toDateObject(popup.date);
|
this.#dateObj = PDFDateString.toDateObject(popup.date);
|
||||||
this.#contentsObj = null;
|
this.#contentsObj = null;
|
||||||
@ -3346,31 +3398,6 @@ class InkAnnotationElement extends AnnotationElement {
|
|||||||
addHighlightArea() {
|
addHighlightArea() {
|
||||||
this.container.classList.add("highlightArea");
|
this.container.classList.add("highlightArea");
|
||||||
}
|
}
|
||||||
|
|
||||||
get commentButtonPosition() {
|
|
||||||
const { inkLists, rect } = this.data;
|
|
||||||
if (inkLists?.length >= 1) {
|
|
||||||
let maxX = -Infinity;
|
|
||||||
let maxY = -Infinity;
|
|
||||||
for (const inkList of inkLists) {
|
|
||||||
for (let i = 0, ii = inkList.length; i < ii; i += 2) {
|
|
||||||
if (inkList[i + 1] > maxY) {
|
|
||||||
maxY = inkList[i + 1];
|
|
||||||
maxX = inkList[i];
|
|
||||||
} else if (inkList[i + 1] === maxY) {
|
|
||||||
maxX = Math.max(maxX, inkList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxX !== Infinity) {
|
|
||||||
return [maxX, maxY];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rect) {
|
|
||||||
return [rect[2], rect[3]];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HighlightAnnotationElement extends AnnotationElement {
|
class HighlightAnnotationElement extends AnnotationElement {
|
||||||
|
|||||||
@ -268,6 +268,10 @@ class AnnotationStorage {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEditor(annotationId) {
|
||||||
|
return this.#editorsMap?.get(annotationId) || null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {{ids: Set<string>, hash: string}}
|
* @returns {{ids: Set<string>, hash: string}}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1930,6 +1930,17 @@ class AnnotationEditor {
|
|||||||
return this._uiManager.direction === "ltr" ? [1, 0] : [0, 0];
|
return this._uiManager.direction === "ltr" ? [1, 0] : [0, 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get commentButtonPositionInPage() {
|
||||||
|
const {
|
||||||
|
commentButtonPosition: [posX, posY],
|
||||||
|
} = this;
|
||||||
|
const [blX, blY, trX, trY] = this.getPDFRect();
|
||||||
|
return [
|
||||||
|
AnnotationEditor._round(blX + (trX - blX) * posX),
|
||||||
|
AnnotationEditor._round(blY + (trY - blY) * (1 - posY)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
get commentButtonColor() {
|
get commentButtonColor() {
|
||||||
return this._uiManager.makeCommentColor(
|
return this._uiManager.makeCommentColor(
|
||||||
this.getNonHCMColor(),
|
this.getNonHCMColor(),
|
||||||
|
|||||||
@ -904,13 +904,13 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
content.append(div);
|
content.append(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = {
|
annotation.updateEdited({
|
||||||
rect: this.getPDFRect(),
|
rect: this.getPDFRect(),
|
||||||
};
|
popup:
|
||||||
params.popup = this.hasEditedComment
|
this._uiManager.hasCommentManager() || this.hasEditedComment
|
||||||
? this.comment
|
? this.comment
|
||||||
: { text: this.#content };
|
: { text: this.#content },
|
||||||
annotation.updateEdited(params);
|
});
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -172,12 +172,13 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
);
|
);
|
||||||
this.#focusOutlines = outlinerForOutline.getOutlines();
|
this.#focusOutlines = outlinerForOutline.getOutlines();
|
||||||
|
|
||||||
// The last point is in the pages coordinate system.
|
const { firstPoint } = this.#highlightOutlines;
|
||||||
const { firstPoint, lastPoint } = this.#focusOutlines;
|
|
||||||
this.#firstPoint = [
|
this.#firstPoint = [
|
||||||
(firstPoint[0] - this.x) / this.width,
|
(firstPoint[0] - this.x) / this.width,
|
||||||
(firstPoint[1] - this.y) / this.height,
|
(firstPoint[1] - this.y) / this.height,
|
||||||
];
|
];
|
||||||
|
// The last point is in the pages coordinate system.
|
||||||
|
const { lastPoint } = this.#focusOutlines;
|
||||||
this.#lastPoint = [
|
this.#lastPoint = [
|
||||||
(lastPoint[0] - this.x) / this.width,
|
(lastPoint[0] - this.x) / this.width,
|
||||||
(lastPoint[1] - this.y) / this.height,
|
(lastPoint[1] - this.y) / this.height,
|
||||||
@ -268,11 +269,12 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { firstPoint, lastPoint } = this.#focusOutlines;
|
const { firstPoint } = highlightOutlines;
|
||||||
this.#firstPoint = [
|
this.#firstPoint = [
|
||||||
(firstPoint[0] - x) / width,
|
(firstPoint[0] - x) / width,
|
||||||
(firstPoint[1] - y) / height,
|
(firstPoint[1] - y) / height,
|
||||||
];
|
];
|
||||||
|
const { lastPoint } = this.#focusOutlines;
|
||||||
this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height];
|
this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,13 +1084,10 @@ class HighlightEditor extends AnnotationEditor {
|
|||||||
annotation.hide();
|
annotation.hide();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const params = {
|
annotation.updateEdited({
|
||||||
rect: this.getPDFRect(),
|
rect: this.getPDFRect(),
|
||||||
};
|
popup: this.comment,
|
||||||
if (this.hasEditedComment) {
|
});
|
||||||
params.popup = this.comment;
|
|
||||||
}
|
|
||||||
annotation.updateEdited(params);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -305,15 +305,12 @@ class InkEditor extends DrawingEditor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { points, rect } = this.serializeDraw(/* isForCopying = */ false);
|
const { points, rect } = this.serializeDraw(/* isForCopying = */ false);
|
||||||
const params = {
|
annotation.updateEdited({
|
||||||
rect,
|
rect,
|
||||||
thickness: this._drawingOptions["stroke-width"],
|
thickness: this._drawingOptions["stroke-width"],
|
||||||
points,
|
points,
|
||||||
};
|
popup: this.comment,
|
||||||
if (this.hasEditedComment) {
|
});
|
||||||
params.popup = this.comment;
|
|
||||||
}
|
|
||||||
annotation.updateEdited(params);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -942,13 +942,10 @@ class StampEditor extends AnnotationEditor {
|
|||||||
annotation.hide();
|
annotation.hide();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const params = {
|
annotation.updateEdited({
|
||||||
rect: this.getPDFRect(),
|
rect: this.getPDFRect(),
|
||||||
};
|
popup: this.comment,
|
||||||
if (this.hasEditedComment) {
|
});
|
||||||
params.popup = this.comment;
|
|
||||||
}
|
|
||||||
annotation.updateEdited(params);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,16 +15,20 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
closePages,
|
closePages,
|
||||||
|
dragAndDrop,
|
||||||
getEditorSelector,
|
getEditorSelector,
|
||||||
getRect,
|
getRect,
|
||||||
getSpanRectFromText,
|
getSpanRectFromText,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
scrollIntoView,
|
scrollIntoView,
|
||||||
|
selectEditor,
|
||||||
switchToEditor,
|
switchToEditor,
|
||||||
waitAndClick,
|
waitAndClick,
|
||||||
|
waitForSerialized,
|
||||||
} from "./test_utils.mjs";
|
} from "./test_utils.mjs";
|
||||||
|
|
||||||
const switchToHighlight = switchToEditor.bind(null, "Highlight");
|
const switchToHighlight = switchToEditor.bind(null, "Highlight");
|
||||||
|
const switchToStamp = switchToEditor.bind(null, "Stamp");
|
||||||
|
|
||||||
describe("Comment", () => {
|
describe("Comment", () => {
|
||||||
describe("Comment edit dialog must be visible in ltr", () => {
|
describe("Comment edit dialog must be visible in ltr", () => {
|
||||||
@ -131,4 +135,105 @@ describe("Comment", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Update comment position and color in reading mode", () => {
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
pages = await loadAndWait(
|
||||||
|
"comments.pdf",
|
||||||
|
".annotationEditorLayer",
|
||||||
|
"page-fit",
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
enableComment: true,
|
||||||
|
highlightEditorColors:
|
||||||
|
"yellow=#FFFF00,green=#00FF00,blue=#0000FF,pink=#FF00FF,red=#FF0000",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must set the comment button at the right place", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await switchToStamp(page);
|
||||||
|
|
||||||
|
const stampSelector = getEditorSelector(8);
|
||||||
|
await selectEditor(page, stampSelector);
|
||||||
|
await dragAndDrop(page, stampSelector, [[100, 100]]);
|
||||||
|
await waitForSerialized(page, 1);
|
||||||
|
const rectCommentButton = await getRect(
|
||||||
|
page,
|
||||||
|
`${stampSelector} .annotationCommentButton`
|
||||||
|
);
|
||||||
|
|
||||||
|
await switchToStamp(page, /* disable = */ true);
|
||||||
|
const rectCommentButtonAfter = await getRect(
|
||||||
|
page,
|
||||||
|
`#pdfjs_internal_id_713R + .annotationCommentButton`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(Math.abs(rectCommentButtonAfter.x - rectCommentButton.x))
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toBeLessThanOrEqual(1);
|
||||||
|
expect(Math.abs(rectCommentButtonAfter.y - rectCommentButton.y))
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toBeLessThanOrEqual(1);
|
||||||
|
expect(
|
||||||
|
Math.abs(rectCommentButtonAfter.width - rectCommentButton.width)
|
||||||
|
)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toBeLessThanOrEqual(1);
|
||||||
|
expect(
|
||||||
|
Math.abs(rectCommentButtonAfter.height - rectCommentButton.height)
|
||||||
|
)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toBeLessThanOrEqual(1);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must set the right color to the comment button", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await switchToHighlight(page);
|
||||||
|
|
||||||
|
const highlightSelector = getEditorSelector(0);
|
||||||
|
await selectEditor(page, highlightSelector);
|
||||||
|
const colorButtonSelector = `${highlightSelector} .editToolbar button`;
|
||||||
|
await page.waitForSelector(`${colorButtonSelector}.colorPicker`);
|
||||||
|
await page.click(`${colorButtonSelector}.colorPicker`);
|
||||||
|
await page.waitForSelector(`${colorButtonSelector}[title = "Red"]`);
|
||||||
|
await page.click(`${colorButtonSelector}[title = "Red"]`);
|
||||||
|
await page.waitForSelector(
|
||||||
|
`.page[data-page-number = "1"] svg.highlight[fill = "#FF0000"]`
|
||||||
|
);
|
||||||
|
|
||||||
|
const commentButtonColor = await page.evaluate(selector => {
|
||||||
|
const button = document.querySelector(
|
||||||
|
`${selector} .annotationCommentButton`
|
||||||
|
);
|
||||||
|
return window.getComputedStyle(button).backgroundColor;
|
||||||
|
}, highlightSelector);
|
||||||
|
|
||||||
|
await switchToHighlight(page, /* disable = */ true);
|
||||||
|
|
||||||
|
const commentButtonColorAfter = await page.evaluate(() => {
|
||||||
|
const button = document.querySelector(
|
||||||
|
"section[data-annotation-id='612R'] + .annotationCommentButton"
|
||||||
|
);
|
||||||
|
return window.getComputedStyle(button).backgroundColor;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(commentButtonColorAfter)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual(commentButtonColor);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -745,3 +745,4 @@
|
|||||||
!tracemonkey_annotation_on_page_8.pdf
|
!tracemonkey_annotation_on_page_8.pdf
|
||||||
!issue20232.pdf
|
!issue20232.pdf
|
||||||
!bug1989304.pdf
|
!bug1989304.pdf
|
||||||
|
!comments.pdf
|
||||||
|
|||||||
BIN
test/pdfs/comments.pdf
Normal file
BIN
test/pdfs/comments.pdf
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user