From 27aea732a2a733201939e3969c095b93203b48a2 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 3 Mar 2026 19:55:46 +0100 Subject: [PATCH] Fix the paste button position and add a button before the first thumbnail --- test/integration/reorganize_pages_spec.mjs | 42 ++++++++++++++++++++++ web/pdf_thumbnail_view.js | 15 ++++++++ web/pdf_thumbnail_viewer.js | 3 ++ web/views_manager.css | 4 ++- 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/test/integration/reorganize_pages_spec.mjs b/test/integration/reorganize_pages_spec.mjs index 8d7572e77..be9d7169a 100644 --- a/test/integration/reorganize_pages_spec.mjs +++ b/test/integration/reorganize_pages_spec.mjs @@ -802,6 +802,48 @@ describe("Reorganize Pages View", () => { await closePages(pages); }); + it("should check that a page can be copied and pasted before the first thumbnail", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await waitForThumbnailVisible(page, 1); + await page.waitForSelector("#viewsManagerStatusActionButton", { + visible: true, + }); + await waitAndClick( + page, + `.thumbnail:has(${getThumbnailSelector(2)}) input` + ); + + let handlePagesEdited = await waitForPagesEdited(page); + await waitAndClick(page, "#viewsManagerStatusActionButton"); + await waitAndClick(page, "#viewsManagerStatusActionCopy"); + + let pageIndices = await awaitPromise(handlePagesEdited); + let expected = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + ]; + expect(pageIndices) + .withContext(`In ${browserName}`) + .toEqual(expected); + await waitForHavingContents(page, expected); + + handlePagesEdited = await waitForPagesEdited(page); + await waitAndClick( + page, + `button.thumbnailPasteButton:has(+ ${getThumbnailSelector(1)})` + ); + pageIndices = await awaitPromise(handlePagesEdited); + expected = [ + 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + ]; + expect(pageIndices) + .withContext(`In ${browserName}`) + .toEqual(expected); + await waitForHavingContents(page, expected); + }) + ); + }); + it("should check that the pages has been copied and pasted correctly", async () => { await Promise.all( pages.map(async ([browserName, page]) => { diff --git a/web/pdf_thumbnail_view.js b/web/pdf_thumbnail_view.js index d01d89b2d..e393f35f9 100644 --- a/web/pdf_thumbnail_view.js +++ b/web/pdf_thumbnail_view.js @@ -188,10 +188,25 @@ class PDFThumbnailView extends RenderableView { pasteButton.addEventListener("click", () => { pasteCallback(this.id); }); + if (this.id === 1) { + const prevPasteButton = (this.prevPasteButton = + pasteButton.cloneNode(true)); + prevPasteButton.addEventListener("click", () => { + pasteCallback(0); + }); + this.imageContainer.before(prevPasteButton); + } this.imageContainer.after(pasteButton); } + removePasteButton() { + this.pasteButton?.remove(); + this.pasteButton = null; + this.prevPasteButton?.remove(); + this.prevPasteButton = null; + } + toggleSelected(isSelected) { if (this.checkbox) { this.checkbox.checked = isSelected; diff --git a/web/pdf_thumbnail_viewer.js b/web/pdf_thumbnail_viewer.js index 621065d45..2f5be74d5 100644 --- a/web/pdf_thumbnail_viewer.js +++ b/web/pdf_thumbnail_viewer.js @@ -651,6 +651,9 @@ class PDFThumbnailViewer { #pastePages(index) { this.container.classList.remove("pasteMode"); + for (const thumbnail of this._thumbnails) { + thumbnail.removePasteButton(); + } this.#toggleMenuEntries(true); const pagesMapper = this.#pagesMapper; diff --git a/web/views_manager.css b/web/views_manager.css index 6a80b4f35..81d08fba8 100644 --- a/web/views_manager.css +++ b/web/views_manager.css @@ -543,6 +543,7 @@ #thumbnailsView { --thumbnail-width: 126px; + --gap-between-input-and-thumbnail: 16px; display: flex; flex-flow: row wrap; @@ -581,6 +582,8 @@ } &.pasteMode { + gap: var(--gap-between-input-and-thumbnail); + > .thumbnail { flex-direction: column; @@ -611,7 +614,6 @@ > .thumbnail { --input-dim: 16px; - --gap-between-input-and-thumbnail: 16px; &:not(&:has(input)) { --input-dim: 0px;