Adds data saving / loading to local storage

This commit is contained in:
Steve Ruiz 2021-05-16 08:09:46 +01:00
parent b45cef260a
commit 520553fb2f
7 changed files with 99 additions and 6 deletions

View file

@ -1,4 +1,5 @@
import useKeyboardEvents from "hooks/useKeyboardEvents" import useKeyboardEvents from "hooks/useKeyboardEvents"
import useLoadOnMount from "hooks/useLoadOnMount"
import Canvas from "./canvas/canvas" import Canvas from "./canvas/canvas"
import StatusBar from "./status-bar" import StatusBar from "./status-bar"
import Toolbar from "./toolbar" import Toolbar from "./toolbar"
@ -6,6 +7,7 @@ import CodePanel from "./code-panel/code-panel"
export default function Editor() { export default function Editor() {
useKeyboardEvents() useKeyboardEvents()
useLoadOnMount()
return ( return (
<> <>

View file

@ -21,6 +21,8 @@ export default function useCamera(ref: React.MutableRefObject<SVGGElement>) {
"transform", "transform",
`scale(${zoom}) translate(${point[0]} ${point[1]})` `scale(${zoom}) translate(${point[0]} ${point[1]})`
) )
localStorage.setItem("code_slate_camera", JSON.stringify(data.camera))
} }
camera = data.camera camera = data.camera

8
hooks/useLoadOnMount.ts Normal file
View file

@ -0,0 +1,8 @@
import { useEffect } from "react"
import state from "state"
export default function useLoadOnMount() {
useEffect(() => {
state.send("MOUNTED")
}, [])
}

View file

@ -1,4 +1,6 @@
import Editor from "components/editor" // import Editor from "components/editor"
import dynamic from "next/dynamic"
const Editor = dynamic(() => import("components/editor"), { ssr: false })
export default function Home() { export default function Home() {
return ( return (

View file

@ -1,9 +1,10 @@
import { Data } from "types" import { Data } from "types"
import { BaseCommand } from "./commands/command" import { BaseCommand } from "./commands/command"
import state from "./state"
// A singleton to manage history changes. // A singleton to manage history changes.
class History<T> { class BaseHistory<T> {
private stack: BaseCommand<T>[] = [] private stack: BaseCommand<T>[] = []
private pointer = -1 private pointer = -1
private maxLength = 100 private maxLength = 100
@ -42,11 +43,22 @@ class History<T> {
this.save(data) this.save(data)
} }
save = (data: T) => { load(data: T, id = "code_slate_0.0.1") {
if (typeof window === "undefined") return if (typeof window === "undefined") return
if (typeof localStorage === "undefined") return if (typeof localStorage === "undefined") return
localStorage.setItem("code_slate_0.0.1", JSON.stringify(data)) const savedData = localStorage.getItem(id)
if (savedData !== null) {
Object.assign(data, this.restoreSavedData(JSON.parse(savedData)))
}
}
save = (data: T, id = "code_slate_0.0.1") => {
if (typeof window === "undefined") return
if (typeof localStorage === "undefined") return
localStorage.setItem(id, JSON.stringify(this.prepareDataForSave(data)))
} }
disable = () => { disable = () => {
@ -57,9 +69,54 @@ class History<T> {
this._enabled = true this._enabled = true
} }
prepareDataForSave(data: T): any {
return { ...data }
}
restoreSavedData(data: any): T {
return { ...data }
}
get disabled() { get disabled() {
return !this._enabled return !this._enabled
} }
} }
export default new History<Data>() // App-specific
class History extends BaseHistory<Data> {
constructor() {
super()
}
prepareDataForSave(data: Data): any {
const dataToSave: any = { ...data }
dataToSave.selectedIds = Array.from(data.selectedIds.values())
return dataToSave
}
restoreSavedData(data: any): Data {
const restoredData = { ...data }
restoredData.selectedIds = new Set(restoredData.selectedIds)
// Also restore camera position, which is saved separately in this app
const cameraInfo = localStorage.getItem("code_slate_camera")
if (cameraInfo !== null) {
Object.assign(data.camera, JSON.parse(cameraInfo))
// And update the CSS property
document.documentElement.style.setProperty(
"--camera-zoom",
data.camera.zoom.toString()
)
}
return restoredData
}
}
export default new History()

View file

@ -56,6 +56,15 @@ export default class TransformSession extends BaseSession {
} = this } = this
// Edge Transform // Edge Transform
/*
Edge transform
Corners a and b are the original top-left and bottom-right corners of the
bounding box. Depending on what the user is dragging, change one or both
points. To keep things smooth, calculate based by adding the delta (the
vector between the current point and its original point) to the original
bounding box values.
*/
switch (transformType) { switch (transformType) {
case TransformEdge.Top: { case TransformEdge.Top: {

View file

@ -52,8 +52,16 @@ const state = createState({
SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" }, SELECTED_POLYLINE_TOOL: { unless: "isReadOnly", to: "polyline" },
SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" }, SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
}, },
initial: "selecting", initial: "loading",
states: { states: {
loading: {
on: {
MOUNTED: {
do: "restoreSavedData",
to: "selecting",
},
},
},
selecting: { selecting: {
on: { on: {
UNDO: { do: "undo" }, UNDO: { do: "undo" },
@ -492,6 +500,11 @@ const state = createState({
decreaseCodeFontSize(data) { decreaseCodeFontSize(data) {
data.settings.fontSize-- data.settings.fontSize--
}, },
// Data
restoreSavedData(data) {
history.load(data)
},
}, },
values: { values: {
selectedIds(data) { selectedIds(data) {