mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01: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…
	
		Reference in New Issue
	
	Block a user