diff --git a/test/integration/reorganize_pages_spec.mjs b/test/integration/reorganize_pages_spec.mjs index 2ee980053..f6497ca5c 100644 --- a/test/integration/reorganize_pages_spec.mjs +++ b/test/integration/reorganize_pages_spec.mjs @@ -1267,6 +1267,68 @@ describe("Reorganize Pages View", () => { }) ); }); + + it("should focus the newly pasted page after copy and paste (bug 2022516)", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await waitForThumbnailVisible(page, 1); + await page.waitForSelector("#viewsManagerStatusActionButton", { + visible: true, + }); + + // Select page 1 and copy it. + await waitAndClick( + page, + `.thumbnail:has(${getThumbnailSelector(1)}) input` + ); + let handlePagesEdited = await waitForPagesEdited(page, "copy"); + await waitAndClick(page, "#viewsManagerStatusActionButton"); + await waitAndClick(page, "#viewsManagerStatusActionCopy"); + await awaitPromise(handlePagesEdited); + + // Paste after page 3: the pasted page lands at position 4. + handlePagesEdited = await waitForPagesEdited(page); + await waitAndClick(page, `${getThumbnailSelector(3)}+button`); + await awaitPromise(handlePagesEdited); + + // Focus must be on the newly pasted page (position 4), not page 1. + await page.waitForSelector(`${getThumbnailSelector(4)}:focus`, { + visible: true, + }); + }) + ); + }); + + it("should focus the newly pasted page after cut and paste (bug 2022516)", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await waitForThumbnailVisible(page, 1); + await page.waitForSelector("#viewsManagerStatusActionButton", { + visible: true, + }); + + // Select page 3 and cut it. + await waitAndClick( + page, + `.thumbnail:has(${getThumbnailSelector(3)}) input` + ); + let handlePagesEdited = await waitForPagesEdited(page, "cut"); + await waitAndClick(page, "#viewsManagerStatusActionButton"); + await waitAndClick(page, "#viewsManagerStatusActionCut"); + await awaitPromise(handlePagesEdited); + + // Paste after page 1: the pasted page lands at position 2. + handlePagesEdited = await waitForPagesEdited(page); + await waitAndClick(page, `${getThumbnailSelector(1)}+button`); + await awaitPromise(handlePagesEdited); + + // Focus must be on the newly pasted page (position 2), not page 1. + await page.waitForSelector(`${getThumbnailSelector(2)}:focus`, { + visible: true, + }); + }) + ); + }); }); describe("Status label reflects number of checked thumbnails (bug 2010832)", () => { diff --git a/web/pdf_thumbnail_viewer.js b/web/pdf_thumbnail_viewer.js index 77b57049c..287990e8d 100644 --- a/web/pdf_thumbnail_viewer.js +++ b/web/pdf_thumbnail_viewer.js @@ -729,13 +729,13 @@ class PDFThumbnailViewer { this.#selectedPages.clear(); } - #updateCurrentPage(currentPageNumber) { + #updateCurrentPage(currentPageNumber, forceFocus = false) { setTimeout(() => { this.forceRendering(); const newPageNumber = currentPageNumber || 1; this.linkService.goToPage(newPageNumber); const thumbnailView = this._thumbnails[newPageNumber - 1]; - if (!this.container.contains(document.activeElement)) { + if (forceFocus || !this.container.contains(document.activeElement)) { thumbnailView.imageContainer.focus(); } }, 0); @@ -883,7 +883,8 @@ class PDFThumbnailViewer { : this._currentPageNumber; pagesMapper.pastePages(index); - this.#updateCurrentPage(this.#updateThumbnails(currentPageNumber)); + this.#updateThumbnails(currentPageNumber); + this.#updateCurrentPage(index + 1, /* forceFocus = */ true); this.#computeThumbnailsPosition(); this.eventBus.dispatch("pagesedited", {