Merge pull request 'add simple undo/redo' (#116) from undo-redo into master
continuous-integration/drone/push Build is passing Details

Reviewed-on: #116
pull/117/head
Maxime BATISTA 1 year ago
commit 4ea531c08c

@ -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]
}
}

@ -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<HTMLDivElement>(null)
const stepsVersions = useMemo<Map<number, ContentVersions>>(
() => new Map(),
[],
)
const saveContent = useCallback(
async (content: StepContent) => {
const result = await service.saveContent(stepId!, content)
@ -168,6 +174,17 @@ function EditorPageWrapper({ service }: { service: TacticService }) {
courtBounds,
content,
)
if (id === stepId) {
let versions = stepsVersions.get(stepId!)
if (versions == undefined) {
versions = new ContentVersions()
stepsVersions.set(stepId!, versions)
}
} else {
stepsVersions.delete(id)
}
return {
content,
relativePositions,
@ -181,7 +198,7 @@ function EditorPageWrapper({ service }: { service: TacticService }) {
)
return SaveStates.Ok
},
[service, stepId, stepsTree],
[stepsVersions, service, stepId, stepsTree],
)
const [stepContent, setStepContent, saveState] =
@ -193,6 +210,30 @@ 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") {
let versions = stepsVersions.get(stepId!)
if (versions == undefined) {
versions = new ContentVersions()
stepsVersions.set(stepId!, 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 +259,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 +285,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 +307,7 @@ function EditorPageWrapper({ service }: { service: TacticService }) {
setStepContent(result, false)
},
}),
[service, setStepContent, stepsTree],
[stepsVersions, service, setStepContent, stepsTree],
)
if (panicMessage) {

Loading…
Cancel
Save