mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-04-19 19:21:18 +00:00
2926 bug undo feature of multitool delete your upload file (#3101)
# Description of Changes Please provide a summary of the changes, including: - What was changed Added support for single page and multi page undo/redo drag and drop in multitool removed selecting pages from undo/redo stack - Why the change was made Drag and drop was not supported fully with undo/redo functionality Closes #(2926) --- ## [Checklist] ### General - [X] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [X] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [X] I have performed a self-review of my code - [X] My changes generate no new warnings ### Documentation ### UI Changes I Will start a demo in PR so people can try the new functionality [numberedpages.pdf](https://github.com/user-attachments/files/19043978/numberedpages.pdf) Please feel free to use this PDF to aid with trying out the new functionality ### Testing (if applicable) - [X] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
parent
58edc777c0
commit
e6abffe1a1
@ -39,7 +39,7 @@ class DragDropManager {
|
||||
// Multi-page drag logic
|
||||
this.selectedPageElements = window.selectedPages
|
||||
.map((index) => {
|
||||
const pageEl = document.getElementById(`page-container-${index}`);
|
||||
const pageEl = Array.from(this.wrapper.childNodes)[index];
|
||||
if (pageEl) {
|
||||
pageEl.initialTransform = pageEl.style.transform || 'translate(0px, 0px)';
|
||||
pageEl.classList.add('drag-manager_dragging');
|
||||
@ -114,13 +114,15 @@ class DragDropManager {
|
||||
} else {
|
||||
this.selectedPageElements.forEach((pageEl) => {
|
||||
pageEl.classList.remove('drag-manager_dragging');
|
||||
});
|
||||
|
||||
if (this.hoveredEl === this.endInsertionElement) {
|
||||
this.movePageTo(pageEl);
|
||||
} else {
|
||||
this.movePageTo(pageEl, this.hoveredEl);
|
||||
}
|
||||
this.movePageTo(
|
||||
this.selectedPageElements,
|
||||
this.hoveredEl === this.endInsertionElement
|
||||
? null
|
||||
: this.hoveredEl);
|
||||
|
||||
this.selectedPageElements.forEach((pageEl) => {
|
||||
// Handle timeout for the current element
|
||||
this.handleTimeoutForElement(pageEl);
|
||||
});
|
||||
|
@ -35,8 +35,7 @@ class PdfActionsManager {
|
||||
|
||||
const sibling = imgContainer.previousSibling;
|
||||
if (sibling) {
|
||||
let movePageCommand = this.movePageTo(imgContainer, sibling, true, true);
|
||||
this._pushUndoClearRedo(movePageCommand);
|
||||
this.movePageTo(imgContainer, sibling, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,12 +43,11 @@ class PdfActionsManager {
|
||||
var imgContainer = this.getPageContainer(e.target);
|
||||
const sibling = imgContainer.nextSibling;
|
||||
if (sibling) {
|
||||
let movePageCommand = this.movePageTo(
|
||||
this.movePageTo(
|
||||
imgContainer,
|
||||
sibling.nextSibling,
|
||||
true
|
||||
);
|
||||
this._pushUndoClearRedo(movePageCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +183,6 @@ class PdfActionsManager {
|
||||
const pageNumber = Array.from(div.parentNode.children).indexOf(div) + 1;
|
||||
let selectPageCommand = new SelectPageCommand(pageNumber, selectCheckbox);
|
||||
selectPageCommand.execute();
|
||||
|
||||
this._pushUndoClearRedo(selectPageCommand);
|
||||
};
|
||||
|
||||
const insertFileButtonContainer = document.createElement("div");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MovePageUpCommand, MovePageDownCommand } from './commands/move-page.js';
|
||||
import { MovePageCommand } from './commands/move-page.js';
|
||||
import { RemoveSelectedCommand } from './commands/remove.js';
|
||||
import { RotateAllCommand, RotateElementCommand } from './commands/rotate.js';
|
||||
import { SplitAllCommand } from './commands/split.js';
|
||||
@ -6,6 +6,7 @@ import { UndoManager } from './UndoManager.js';
|
||||
import { PageBreakCommand } from './commands/page-break.js';
|
||||
import { AddFilesCommand } from './commands/add-page.js';
|
||||
import { DecryptFile } from '../DecryptFiles.js';
|
||||
import { CommandSequence } from './commands/commands-sequence.js';
|
||||
|
||||
class PdfContainer {
|
||||
fileName;
|
||||
@ -109,27 +110,41 @@ class PdfContainer {
|
||||
downloadBtn.disabled = true;
|
||||
}
|
||||
|
||||
movePageTo(startElement, endElement, scrollTo = false, moveUp = false) {
|
||||
let movePageCommand;
|
||||
if (moveUp) {
|
||||
movePageCommand = new MovePageUpCommand(
|
||||
startElement,
|
||||
movePagesTo(startElements, endElement, scrollTo = false) {
|
||||
let commands = [];
|
||||
startElements.forEach((page) => {
|
||||
let command = new MovePageCommand(
|
||||
page,
|
||||
endElement,
|
||||
this.pagesContainer,
|
||||
this.pagesContainerWrapper,
|
||||
scrollTo
|
||||
);
|
||||
} else {
|
||||
movePageCommand = new MovePageDownCommand(
|
||||
startElement,
|
||||
endElement,
|
||||
this.pagesContainer,
|
||||
this.pagesContainerWrapper,
|
||||
scrollTo
|
||||
);
|
||||
)
|
||||
command.execute();
|
||||
commands.push(command);
|
||||
})
|
||||
|
||||
let commandSequence = new CommandSequence(commands);
|
||||
this.undoManager.pushUndoClearRedo(commandSequence);
|
||||
return commandSequence;
|
||||
}
|
||||
|
||||
movePageTo(startElements, endElement, scrollTo = false) {
|
||||
|
||||
if (Array.isArray(startElements)){
|
||||
return this.movePagesTo(startElements, endElement, scrollTo = false);
|
||||
}
|
||||
|
||||
let movePageCommand = new MovePageCommand(
|
||||
startElements,
|
||||
endElement,
|
||||
this.pagesContainer,
|
||||
this.pagesContainerWrapper,
|
||||
scrollTo
|
||||
);
|
||||
|
||||
movePageCommand.execute();
|
||||
this.undoManager.pushUndoClearRedo(movePageCommand);
|
||||
return movePageCommand;
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,10 @@ export class AddFilesCommand extends Command {
|
||||
|
||||
if (this.pagesContainer.childElementCount === 0) {
|
||||
const filenameInput = document.getElementById('filename-input');
|
||||
const filenameParagraph = document.getElementById('filename');
|
||||
const downloadBtn = document.getElementById('export-button');
|
||||
|
||||
filenameInput.disabled = true;
|
||||
filenameInput.value = '';
|
||||
filenameParagraph.innerText = '';
|
||||
downloadBtn.disabled = true;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
import {Command} from './command.js';
|
||||
|
||||
export class CommandSequence extends Command {
|
||||
constructor(commands) {
|
||||
super();
|
||||
this.commands = commands;
|
||||
|
||||
}
|
||||
execute() {
|
||||
this.commands.forEach((command) => command.execute())
|
||||
}
|
||||
|
||||
undo() {
|
||||
this.commands.slice().reverse().forEach((command) => command.undo())
|
||||
}
|
||||
|
||||
redo() {
|
||||
this.execute();
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import {Command} from './command.js';
|
||||
|
||||
export class AbstractMovePageCommand extends Command {
|
||||
export class MovePageCommand extends Command {
|
||||
constructor(startElement, endElement, pagesContainer, pagesContainerWrapper, scrollTo = false) {
|
||||
super();
|
||||
|
||||
@ -16,7 +16,6 @@ export class AbstractMovePageCommand extends Command {
|
||||
this.scrollTo = scrollTo;
|
||||
this.pagesContainerWrapper = pagesContainerWrapper;
|
||||
}
|
||||
|
||||
execute() {
|
||||
// Check & remove page number elements here too if they exist because Firefox doesn't fire the relevant event on page move.
|
||||
const pageNumberElement = this.startElement.querySelector('.page-number');
|
||||
@ -42,51 +41,11 @@ export class AbstractMovePageCommand extends Command {
|
||||
}
|
||||
|
||||
undo() {
|
||||
// Requires overriding in child classes
|
||||
}
|
||||
|
||||
redo() {
|
||||
this.execute();
|
||||
}
|
||||
}
|
||||
|
||||
export class MovePageUpCommand extends AbstractMovePageCommand {
|
||||
constructor(startElement, endElement, pagesContainer, pagesContainerWrapper, scrollTo = false) {
|
||||
super(startElement, endElement, pagesContainer, pagesContainerWrapper, scrollTo);
|
||||
}
|
||||
|
||||
undo() {
|
||||
if (this.endElement) {
|
||||
this.pagesContainer.removeChild(this.endElement);
|
||||
this.startElement.insertAdjacentElement('beforebegin', this.endElement);
|
||||
}
|
||||
|
||||
if (this.scrollTo) {
|
||||
const {width} = this.startElement.getBoundingClientRect();
|
||||
const vector = this.endIndex === -1 || this.startIndex <= this.endIndex ? 0 - width : width;
|
||||
|
||||
this.pagesContainerWrapper.scroll({
|
||||
left: this.pagesContainerWrapper.scrollLeft - vector,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
redo() {
|
||||
this.execute();
|
||||
}
|
||||
}
|
||||
|
||||
export class MovePageDownCommand extends AbstractMovePageCommand {
|
||||
constructor(startElement, endElement, pagesContainer, pagesContainerWrapper, scrollTo = false) {
|
||||
super(startElement, endElement, pagesContainer, pagesContainerWrapper, scrollTo);
|
||||
}
|
||||
|
||||
undo() {
|
||||
let previousElement = this.startElement.previousSibling;
|
||||
|
||||
if (this.startElement) {
|
||||
this.pagesContainer.removeChild(this.startElement);
|
||||
previousElement.insertAdjacentElement('beforebegin', this.startElement);
|
||||
let previousNeighbour = Array.from(this.pagesContainer.childNodes)[this.startIndex];
|
||||
previousNeighbour?.insertAdjacentElement('beforebegin', this.startElement)
|
||||
?? this.pagesContainer.append(this.startElement);
|
||||
}
|
||||
|
||||
if (this.scrollTo) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user