Adds data saving / loading to local storage
This commit is contained in:
parent
b45cef260a
commit
520553fb2f
7 changed files with 99 additions and 6 deletions
|
@ -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 (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -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
8
hooks/useLoadOnMount.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { useEffect } from "react"
|
||||||
|
import state from "state"
|
||||||
|
|
||||||
|
export default function useLoadOnMount() {
|
||||||
|
useEffect(() => {
|
||||||
|
state.send("MOUNTED")
|
||||||
|
}, [])
|
||||||
|
}
|
|
@ -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 (
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue