From 0fdda4da956754b48a7904d7ffe8dae308954b4c Mon Sep 17 00:00:00 2001 From: maxime Date: Mon, 18 Mar 2024 17:11:04 +0100 Subject: [PATCH] add simple undo/redo --- src/editor/ContentVersions.ts | 22 ++++++++++++++ src/pages/Editor.tsx | 55 +++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/editor/ContentVersions.ts diff --git a/src/editor/ContentVersions.ts b/src/editor/ContentVersions.ts new file mode 100644 index 0000000..26cf6f1 --- /dev/null +++ b/src/editor/ContentVersions.ts @@ -0,0 +1,22 @@ +import { StepContent } from "../model/tactic/Tactic.ts" + +export class ContentVersions { + private index = 0 + private contents: StepContent[] = [] + + public insertAndCut(content: StepContent) { + this.contents.splice(this.index + 1) + this.contents.push(content) + this.index = this.contents.length - 1 + } + + public previous(): StepContent | null { + if (this.index == 0) return null + return this.contents[--this.index] + } + + public next(): StepContent | null { + if (this.index == this.contents.length - 1) return null + return this.contents[++this.index] + } +} diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx index a0b6708..5ed73b4 100644 --- a/src/pages/Editor.tsx +++ b/src/pages/Editor.tsx @@ -92,6 +92,7 @@ import { ServiceError, TacticService } from "../service/TacticService.ts" import { LocalStorageTacticService } from "../service/LocalStorageTacticService.ts" import { APITacticService } from "../service/APITacticService.ts" import { useParams } from "react-router-dom" +import { ContentVersions } from "../editor/ContentVersions.ts" const ERROR_STYLE: CSSProperties = { borderColor: "red", @@ -146,6 +147,11 @@ function EditorPageWrapper({ service }: { service: TacticService }) { const courtRef = useRef(null) + const stepsVersions = useMemo>( + () => new Map(), + [], + ) + const saveContent = useCallback( async (content: StepContent) => { const result = await service.saveContent(stepId!, content) @@ -168,6 +174,15 @@ function EditorPageWrapper({ service }: { service: TacticService }) { courtBounds, content, ) + + let versions = stepsVersions.get(stepId!) + if (versions == undefined) { + versions = new ContentVersions() + stepsVersions.set(stepId!, versions) + } + + versions.insertAndCut(content) + return { content, relativePositions, @@ -181,7 +196,7 @@ function EditorPageWrapper({ service }: { service: TacticService }) { ) return SaveStates.Ok }, - [service, stepId, stepsTree], + [stepsVersions, service, stepId, stepsTree], ) const [stepContent, setStepContent, saveState] = @@ -193,6 +208,34 @@ function EditorPageWrapper({ service }: { service: TacticService }) { const isNotInit = !tacticName || !stepId || !stepsTree || !courtType + useEffect(() => { + const handleGlobalControls = (e: KeyboardEvent) => { + if (!e.ctrlKey) return + if (e.key == "z" || e.key == "y") { + console.log(e.key, stepsVersions) + + let versions = stepsVersions.get(stepId!) + if (versions == undefined) { + versions = new ContentVersions() + stepsVersions.set(stepId!, versions) + } + + console.log(versions) + + const previous = + e.key == "z" ? versions.previous() : versions.next() + if (previous) { + setStepContent(previous, false) + } + } + } + + document.addEventListener("keydown", handleGlobalControls) + + return () => + document.removeEventListener("keydown", handleGlobalControls) + }, [stepsVersions, setStepContent, stepId]) + useEffect(() => { async function init() { const contextResult = await service.getContext() @@ -218,11 +261,16 @@ function EditorPageWrapper({ service }: { service: TacticService }) { ) return } + + const versions = new ContentVersions() + stepsVersions.set(stepId, versions) + versions.insertAndCut(contentResult) + setStepContent(contentResult, false) } if (isNotInit) init() - }, [isNotInit, service, setStepContent]) + }, [isNotInit, service, setStepContent, stepsVersions]) const editorService: EditorService = useMemo( () => ({ @@ -239,6 +287,7 @@ function EditorPageWrapper({ service }: { service: TacticService }) { const result = await service.removeStep(step) if (typeof result !== "string") setStepsTree(removeStepNode(stepsTree!, step)) + stepsVersions.delete(step) return result }, @@ -260,7 +309,7 @@ function EditorPageWrapper({ service }: { service: TacticService }) { setStepContent(result, false) }, }), - [service, setStepContent, stepsTree], + [stepsVersions, service, setStepContent, stepsTree], ) if (panicMessage) {