Merge pull request #20697 from calixteman/bug2018139

Add keyboard shortcuts for copying/cutting/deleting the pages (bug 2018139, bug 2010831)
This commit is contained in:
calixteman 2026-02-22 22:42:31 +01:00 committed by GitHub
commit c91de765e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 181 additions and 0 deletions

View File

@ -23,6 +23,9 @@ import {
getAnnotationSelector,
getRect,
getThumbnailSelector,
kbCopy,
kbCut,
kbDelete,
loadAndWait,
scrollIntoView,
waitAndClick,
@ -841,4 +844,144 @@ describe("Reorganize Pages View", () => {
);
});
});
describe("Keyboard shortcuts for cut and copy (bug 2018139)", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait(
"page_with_number.pdf",
"#viewsManagerToggleButton",
"1",
null,
{ enableSplitMerge: true }
);
});
afterEach(async () => {
await closePages(pages);
});
it("should cut pages with Ctrl+X and paste them", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await waitForThumbnailVisible(page, 1);
await waitAndClick(
page,
`.thumbnail:has(${getThumbnailSelector(1)}) input`
);
await waitAndClick(
page,
`.thumbnail:has(${getThumbnailSelector(3)}) input`
);
let handlePagesEdited = await waitForPagesEdited(page, "cut");
await kbCut(page);
let pageIndices = await awaitPromise(handlePagesEdited);
let expected = [2, 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, `${getThumbnailSelector(1)}+button`);
pageIndices = await awaitPromise(handlePagesEdited);
expected = [
2, 1, 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 copy pages with Ctrl+C and paste them", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await waitForThumbnailVisible(page, 1);
await waitAndClick(
page,
`.thumbnail:has(${getThumbnailSelector(1)}) input`
);
await waitAndClick(
page,
`.thumbnail:has(${getThumbnailSelector(3)}) input`
);
let handlePagesEdited = await waitForPagesEdited(page, "copy");
await kbCopy(page);
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, `${getThumbnailSelector(2)}+button`);
pageIndices = await awaitPromise(handlePagesEdited);
expected = [
1, 2, 1, 3, 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);
})
);
});
});
describe("Keyboard shortcuts for delete (bug 2010831)", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait(
"page_with_number.pdf",
"#viewsManagerToggleButton",
"1",
null,
{ enableSplitMerge: true }
);
});
afterEach(async () => {
await closePages(pages);
});
it("should delete pages with the Delete key", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await waitForThumbnailVisible(page, 1);
await waitAndClick(
page,
`.thumbnail:has(${getThumbnailSelector(1)}) input`
);
await waitAndClick(
page,
`.thumbnail:has(${getThumbnailSelector(3)}) input`
);
const handlePagesEdited = await waitForPagesEdited(page);
await kbDelete(page);
const pageIndices = await awaitPromise(handlePagesEdited);
const expected = [
2, 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);
})
);
});
});
});

View File

@ -702,6 +702,14 @@ async function kbCopy(page) {
await page.keyboard.press("c", { commands: ["Copy"] });
await page.keyboard.up(modifier);
}
async function kbCut(page) {
await page.keyboard.down(modifier);
await page.keyboard.press("x", { commands: ["Cut"] });
await page.keyboard.up(modifier);
}
async function kbDelete(page) {
await page.keyboard.press("Delete");
}
async function kbPaste(page) {
await page.keyboard.down(modifier);
await page.keyboard.press("v", { commands: ["Paste"] });
@ -997,6 +1005,9 @@ export {
kbBigMoveLeft,
kbBigMoveRight,
kbBigMoveUp,
kbCopy,
kbCut,
kbDelete,
kbDeleteLastWord,
kbFocusNext,
kbFocusPrevious,

View File

@ -884,6 +884,33 @@ class PDFThumbnailViewer {
}
// For checkboxes, let the default behavior handle toggling
break;
case "c":
if (
this.#enableSplitMerge &&
(e.ctrlKey || e.metaKey) &&
this.#selectedPages?.size
) {
this.#copyPages();
stopEvent(e);
}
break;
case "x":
if (
this.#enableSplitMerge &&
(e.ctrlKey || e.metaKey) &&
this.#selectedPages?.size
) {
this.#cutPages();
stopEvent(e);
}
break;
case "Delete":
case "Backspace":
if (this.#enableSplitMerge && this.#selectedPages?.size) {
this.#deletePages();
stopEvent(e);
}
break;
}
});
this.container.addEventListener("click", e => {