Feature: Undo Redo options multi tool #2297 (#2348)

* Implement Command class for Command Pattern

Created a base `Command` class to implement the **Command Pattern**. This class provides a skeletal implementation for `execute`, `undo`, and `redo` methods.

**Note:** This class is intended to be subclassed and not instantiated directly.

* Add undo/redo stacks and operations

* Use rotate element command to perform execute/undo/redo operations

* Handle commands executed through events
- Add "command-execution" event listener to execute commands that are not invoked from the same class while adding the command to the undo stack and clearing the redo stack.

* Add and use rotate all command to rotate/redo/undo all elements

* Use command pattern to delete pages

* Use command pattern for page selection

* Use command pattern to move pages up and down

* Use command pattern to remove selected pages

* Use command pattern to perform the splitting operation

* Add undo/redo functionality with filename input exclusion

- Implement undo (Ctrl+Z) and redo (Ctrl+Y) functionality.
- Prevent undo/redo actions when the filename input field is focused.
- Ensures proper handling of undo/redo actions without interfering with text editing.

* Introduce UndoManager for managing undo/redo operations

 - Encapsulate undo/redo stacks and operations within UndoManager.
- Simplify handling of undo/redo functionality through a dedicated manager.

* Call execute on splitAllCommand

- Fix a bug that caused split all functionality to not work as execute() wasn't called on splitAllCommand

* Add undo/redo buttons to multi tool

- Add undo/redo buttons to multi tool
- Dispatch an event upon state change (such as changes in the undo/redo stacks) to update the UI accordingly.

* Add undo/redo to translations

* Replace hard-coded "Undo"/"Redo" with translation keys in multi tool

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
This commit is contained in:
Omar Ahmed Hassan
2024-11-28 16:25:13 +02:00
committed by GitHub
parent de9c21b3de
commit 61e750646c
48 changed files with 848 additions and 124 deletions

View File

@@ -0,0 +1,74 @@
import { Command } from "./command.js";
export class DeletePageCommand extends Command {
constructor(element, pagesContainer) {
super();
this.element = element;
this.pagesContainer = pagesContainer;
this.filenameInputValue = document.getElementById("filename-input").value;
const filenameParagraph = document.getElementById("filename");
this.filenameParagraphText = filenameParagraph ? filenameParagraph.innerText : "";
}
execute() {
this.nextSibling = this.element.nextSibling;
this.pagesContainer.removeChild(this.element);
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;
}
}
undo() {
let node = this.nextSibling;
if (node) this.pagesContainer.insertBefore(this.element, node);
else this.pagesContainer.appendChild(this.element);
const pageNumberElement = this.element.querySelector(".page-number");
if (pageNumberElement) {
this.element.removeChild(pageNumberElement);
}
const filenameInput = document.getElementById("filename-input");
const filenameParagraph = document.getElementById("filename");
const downloadBtn = document.getElementById("export-button");
filenameInput.disabled = false;
filenameInput.value = this.filenameInputValue;
if (this.filenameParagraph)
filenameParagraph.innerText = this.filenameParagraphText;
downloadBtn.disabled = false;
}
redo() {
const pageNumberElement = this.element.querySelector(".page-number");
if (pageNumberElement) {
this.element.removeChild(pageNumberElement);
}
this.pagesContainer.removeChild(this.element);
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;
}
}
}