[Editor] Make sure the comment dialog is visible on the screen (bug 1989304)
This commit is contained in:
parent
d85fd12437
commit
623d422ddb
@ -193,11 +193,16 @@ class AnnotationEditorLayer {
|
||||
|
||||
this.toggleAnnotationLayerPointerEvents(false);
|
||||
const { classList } = this.div;
|
||||
for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
|
||||
classList.toggle(
|
||||
`${editorType._type}Editing`,
|
||||
mode === editorType._editorType
|
||||
);
|
||||
if (mode === AnnotationEditorType.POPUP) {
|
||||
classList.toggle("commentEditing", true);
|
||||
} else {
|
||||
classList.toggle("commentEditing", false);
|
||||
for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
|
||||
classList.toggle(
|
||||
`${editorType._type}Editing`,
|
||||
mode === editorType._editorType
|
||||
);
|
||||
}
|
||||
}
|
||||
this.div.hidden = false;
|
||||
}
|
||||
|
||||
134
test/integration/comment_spec.mjs
Normal file
134
test/integration/comment_spec.mjs
Normal file
@ -0,0 +1,134 @@
|
||||
/* Copyright 2025 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
closePages,
|
||||
getEditorSelector,
|
||||
getRect,
|
||||
getSpanRectFromText,
|
||||
loadAndWait,
|
||||
scrollIntoView,
|
||||
switchToEditor,
|
||||
waitAndClick,
|
||||
} from "./test_utils.mjs";
|
||||
|
||||
const switchToHighlight = switchToEditor.bind(null, "Highlight");
|
||||
|
||||
describe("Comment", () => {
|
||||
describe("Comment edit dialog must be visible in ltr", () => {
|
||||
let pages;
|
||||
|
||||
beforeEach(async () => {
|
||||
pages = await loadAndWait(
|
||||
"bug1989304.pdf",
|
||||
".annotationEditorLayer",
|
||||
"page-width",
|
||||
null,
|
||||
{ enableComment: true }
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must set the comment dialog in the viewport (LTR)", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await switchToHighlight(page);
|
||||
|
||||
await scrollIntoView(page, ".textLayer span:last-of-type");
|
||||
const rect = await getSpanRectFromText(page, 1, "...");
|
||||
const x = rect.x + rect.width / 2;
|
||||
const y = rect.y + rect.height / 2;
|
||||
// Here and elsewhere, we add a small delay between press and release
|
||||
// to make sure that a pointerup event is triggered after
|
||||
// selectionchange.
|
||||
// It works with a value of 1ms, but we use 100ms to be sure.
|
||||
await page.mouse.click(x, y, { count: 2, delay: 100 });
|
||||
await page.waitForSelector(getEditorSelector(0));
|
||||
|
||||
const commentButtonSelector = `${getEditorSelector(0)} button.comment`;
|
||||
await waitAndClick(page, commentButtonSelector);
|
||||
|
||||
await page.waitForSelector("#commentManagerDialog", {
|
||||
visible: true,
|
||||
});
|
||||
const dialogRect = await getRect(page, "#commentManagerDialog");
|
||||
const viewport = await page.evaluate(() => ({
|
||||
width: document.documentElement.clientWidth,
|
||||
height: document.documentElement.clientHeight,
|
||||
}));
|
||||
expect(dialogRect.x + dialogRect.width)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toBeLessThanOrEqual(viewport.width);
|
||||
expect(dialogRect.y + dialogRect.height)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toBeLessThanOrEqual(viewport.height);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Comment edit dialog must be visible in rtl", () => {
|
||||
let pages;
|
||||
|
||||
beforeEach(async () => {
|
||||
pages = await loadAndWait(
|
||||
"bug1989304.pdf",
|
||||
".annotationEditorLayer",
|
||||
"page-width",
|
||||
null,
|
||||
{ enableComment: true, localeProperties: "ar" }
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must set the comment dialog in the viewport (RTL)", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await switchToHighlight(page);
|
||||
|
||||
await scrollIntoView(page, ".textLayer span:nth-of-type(4)");
|
||||
const rect = await getSpanRectFromText(page, 1, "World");
|
||||
const x = rect.x + rect.width / 2;
|
||||
const y = rect.y + rect.height / 2;
|
||||
await page.mouse.click(x, y, { count: 2, delay: 100 });
|
||||
await page.waitForSelector(getEditorSelector(0));
|
||||
|
||||
const commentButtonSelector = `${getEditorSelector(0)} button.comment`;
|
||||
await waitAndClick(page, commentButtonSelector);
|
||||
|
||||
await page.waitForSelector("#commentManagerDialog", {
|
||||
visible: true,
|
||||
});
|
||||
const dialogRect = await getRect(page, "#commentManagerDialog");
|
||||
const viewport = await page.evaluate(() => ({
|
||||
height: document.documentElement.clientHeight,
|
||||
}));
|
||||
expect(dialogRect.x + dialogRect.width)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toBeGreaterThanOrEqual(0);
|
||||
expect(dialogRect.y + dialogRect.height)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toBeLessThanOrEqual(viewport.height);
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -30,6 +30,7 @@ async function runTests(results) {
|
||||
"annotation_spec.mjs",
|
||||
"autolinker_spec.mjs",
|
||||
"caret_browsing_spec.mjs",
|
||||
"comment_spec.mjs",
|
||||
"copy_paste_spec.mjs",
|
||||
"document_properties_spec.mjs",
|
||||
"find_spec.mjs",
|
||||
|
||||
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -744,3 +744,4 @@
|
||||
!bug1980958.pdf
|
||||
!tracemonkey_annotation_on_page_8.pdf
|
||||
!issue20232.pdf
|
||||
!bug1989304.pdf
|
||||
|
||||
BIN
test/pdfs/bug1989304.pdf
Executable file
BIN
test/pdfs/bug1989304.pdf
Executable file
Binary file not shown.
@ -368,6 +368,7 @@ const PDFViewerApplication = {
|
||||
docBaseUrl: x => x,
|
||||
enableAltText: x => x === "true",
|
||||
enableAutoLinking: x => x === "true",
|
||||
enableComment: x => x === "true",
|
||||
enableFakeMLManager: x => x === "true",
|
||||
enableGuessAltText: x => x === "true",
|
||||
enablePermissions: x => x === "true",
|
||||
@ -380,6 +381,7 @@ const PDFViewerApplication = {
|
||||
forcePageColors: x => x === "true",
|
||||
pageColorsBackground: x => x,
|
||||
pageColorsForeground: x => x,
|
||||
localeProperties: x => ({ lang: x }),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,8 @@
|
||||
min-width: 200px;
|
||||
position: absolute;
|
||||
padding: 8px 16px 16px;
|
||||
margin: 0;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
border-radius: 8px;
|
||||
|
||||
@ -46,7 +46,7 @@ class CommentManager {
|
||||
dateStyle: "long",
|
||||
});
|
||||
this.dialogElement = commentDialog.dialog;
|
||||
this.#dialog = new CommentDialog(commentDialog, overlayManager);
|
||||
this.#dialog = new CommentDialog(commentDialog, overlayManager, ltr);
|
||||
this.#popup = new CommentPopup(dateFormat, ltr, this.dialogElement);
|
||||
this.#sidebar = new CommentSidebar(
|
||||
sidebar,
|
||||
@ -572,15 +572,19 @@ class CommentDialog {
|
||||
|
||||
#dialogY = 0;
|
||||
|
||||
#isLTR;
|
||||
|
||||
constructor(
|
||||
{ dialog, toolbar, title, textInput, cancelButton, saveButton },
|
||||
overlayManager
|
||||
overlayManager,
|
||||
ltr
|
||||
) {
|
||||
this.#dialog = dialog;
|
||||
this.#textInput = textInput;
|
||||
this.#overlayManager = overlayManager;
|
||||
this.#saveButton = saveButton;
|
||||
this.#title = title;
|
||||
this.#isLTR = ltr;
|
||||
|
||||
const finishBound = this.#finish.bind(this);
|
||||
dialog.addEventListener("close", finishBound);
|
||||
@ -682,7 +686,38 @@ class CommentDialog {
|
||||
}
|
||||
this.#uiManager?.removeEditListeners();
|
||||
this.#saveButton.disabled = true;
|
||||
|
||||
const parentDimensions = options?.parentDimensions;
|
||||
if (editor.hasDefaultPopupPosition()) {
|
||||
const { dialogWidth, dialogHeight } = this._dialogDimensions;
|
||||
if (parentDimensions) {
|
||||
if (
|
||||
this.#isLTR &&
|
||||
posX + dialogWidth >
|
||||
Math.min(
|
||||
parentDimensions.x + parentDimensions.width,
|
||||
window.innerWidth
|
||||
)
|
||||
) {
|
||||
const buttonWidth = this.#editor.commentButtonWidth;
|
||||
posX -= dialogWidth - buttonWidth * parentDimensions.width;
|
||||
} else if (!this.#isLTR) {
|
||||
const buttonWidth =
|
||||
this.#editor.commentButtonWidth * parentDimensions.width;
|
||||
if (posX - dialogWidth < Math.max(0, parentDimensions.x)) {
|
||||
posX = Math.max(0, posX);
|
||||
} else {
|
||||
posX -= dialogWidth - buttonWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
const height = Math.max(dialogHeight, options?.height || 0);
|
||||
if (posY + height > window.innerHeight) {
|
||||
posY = window.innerHeight - height;
|
||||
}
|
||||
if (posY < 0) {
|
||||
posY = 0;
|
||||
}
|
||||
}
|
||||
this.#setPosition(posX, posY);
|
||||
|
||||
await this.#overlayManager.open(this.#dialog);
|
||||
@ -694,14 +729,17 @@ class CommentDialog {
|
||||
this.#finish();
|
||||
}
|
||||
|
||||
get _dialogWidth() {
|
||||
get _dialogDimensions() {
|
||||
const dialog = this.#dialog;
|
||||
const { style } = dialog;
|
||||
style.opacity = "0";
|
||||
style.display = "block";
|
||||
const width = dialog.getBoundingClientRect().width;
|
||||
const { width, height } = dialog.getBoundingClientRect();
|
||||
style.opacity = style.display = "";
|
||||
return shadow(this, "_dialogWidth", width);
|
||||
return shadow(this, "_dialogDimensions", {
|
||||
dialogWidth: width,
|
||||
dialogHeight: height,
|
||||
});
|
||||
}
|
||||
|
||||
#setPosition(x, y) {
|
||||
@ -1021,7 +1059,7 @@ class CommentPopup {
|
||||
}
|
||||
}
|
||||
|
||||
#setPosition(x, y, correctPosition = true) {
|
||||
#setPosition(x, y, correctPosition) {
|
||||
if (!correctPosition) {
|
||||
this.#editor.commentPopupPosition = [x, y];
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user