Skip to content

Commit

Permalink
refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddenist committed Dec 30, 2023
1 parent c9c5e93 commit 8444dde
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 33 deletions.
64 changes: 43 additions & 21 deletions libs/drawing-engine/src/engine/CanvasHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ import { LineDrawInfo } from "../tools/LineTool"
import { DrawingEngine, EventType } from "./DrawingEngine"
import { Database } from "./Database"

type ToolInfo = LineDrawInfo
type ClearInfo = { tool: "clear" }

export interface HistoryState {
toolInfo: ToolInfo
imageData: Blob | null
}
export type ToolInfo = LineDrawInfo | ClearInfo

interface HistoryEntry {
imageData: Blob | null
Expand Down Expand Up @@ -61,7 +58,14 @@ export class CanvasHistory {
protected readonly engine: DrawingEngine,
protected options: HistoryOptions,
protected db: HistoryDatabase,
) {}
) {
this.engine.addListener(EventType.commit, (toolInfo) => {
this.add(toolInfo)
})
this.engine.addListener(EventType.clear, () => {
this.add({ tool: "clear" })
})
}

static async create(engine: DrawingEngine, options: Partial<HistoryOptions> = {}) {
const db = await HistoryDatabase.create()
Expand Down Expand Up @@ -98,7 +102,8 @@ export class CanvasHistory {

private async save(toolInfo: ToolInfo) {
const canvas = this.engine.htmlCanvas
const tool = this.engine.tools[toolInfo.tool]
const toolName = toolInfo.tool
const tool = toolName === "clear" ? { updatesImageData: false } : this.engine.tools[toolName]

const current = await this.getIncompleteEntry()
current.entry.actions.push(toolInfo)
Expand Down Expand Up @@ -192,33 +197,48 @@ export class CanvasHistory {
}

protected async appendHistoryKey(key: IDBValidKey) {
const db = this.db
this.history.unshift(key)
if (this.history.length >= this.options.maxHistory) {
this.hasTruncated = true
const first = this.history.pop()
if (first) {
db.history.delete(first)
}
}
this.truncateHistory()
}

protected async drawHistoryEntry(entry: Readonly<HistoryEntry> | null) {
if (!entry) {
if (!this.hasTruncated) this.engine.clearCanvas()
return Promise.resolve(null)
protected truncateHistory() {
if (this.history.length <= this.options.maxHistory) {
return
}

const first = this.history.pop()
if (first) {
this.db.history.delete(first)
}
}

protected async drawHistoryEntry(entry: Readonly<HistoryEntry>) {
const { actions, imageData } = entry

if (!imageData) {
this.engine._clear()
return Promise.resolve(null)
}

await this.drawBlob(imageData)
await this.drawActions(actions)
await this.drawActions(CanvasHistory.getActionsSinceClear(entry.actions))

return actions[actions.length - 1]
}

protected async drawActions(actions: Array<ToolInfo>) {
protected static getActionsSinceClear(actions: Array<ToolInfo>): Array<Exclude<ToolInfo, ClearInfo>> {
const result: Array<Exclude<ToolInfo, ClearInfo>> = []
for (const action of actions) {
if (action.tool === "clear") {
result.splice(0)
} else {
result.push(action)
}
}
return result
}

protected async drawActions(actions: Array<Exclude<ToolInfo, ClearInfo>>) {
for (const action of actions) {
const tool = this.engine.tools[action.tool]
if (!tool) {
Expand All @@ -231,6 +251,7 @@ export class CanvasHistory {
protected drawBlob(blob: Blob): Promise<HTMLImageElement> {
const image = new Image()
image.src = URL.createObjectURL(blob)

return new Promise<HTMLImageElement>((resolve, reject) => {
image.onload = () => {
this.engine._clear()
Expand All @@ -249,6 +270,7 @@ export class CanvasHistory {

public canUndo() {
const minStates = this.hasTruncated ? 1 : 0

return this.history.length > minStates
}

Expand Down
18 changes: 7 additions & 11 deletions libs/drawing-engine/src/engine/DrawingEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { Color } from "@libs/shared"
import { Layer, LayerSettings } from "./Layer"
import { SourceImage } from "../utils/image/SourceImage"
import { ToolName, ToolNames } from "../exports"
import { LineDrawInfo, LineTool } from "../tools/LineTool"
import { LineTool } from "../tools/LineTool"
import { InputPoint } from "../tools/InputPoint"
import { EyeDropperTool } from "../tools/EyeDropperTool"
import { CanvasHistory, HistoryState } from "./CanvasHistory"
import { CanvasHistory, ToolInfo } from "./CanvasHistory"

interface DrawingEngineState {
color: Color
Expand All @@ -27,11 +27,10 @@ export interface DrawingEngineOptions {
pixelDensity?: number
}

type ToolInfo = LineDrawInfo

export enum EventType {
engineLoaded = "engineLoaded",
draw = "draw",
commit = "commit",
undo = "undo",
redo = "redo",
pickColor = "pickColor",
Expand All @@ -45,9 +44,11 @@ export enum EventType {
}

export interface DrawingEngineEventMap {
[EventType.engineLoaded]: undefined
[EventType.draw]: ToolInfo
[EventType.undo]: { toolInfo: HistoryState["toolInfo"] | null; canUndo: boolean }
[EventType.redo]: { toolInfo: HistoryState["toolInfo"] | null; canRedo: boolean }
[EventType.commit]: ToolInfo
[EventType.undo]: { toolInfo: ToolInfo | null; canUndo: boolean }
[EventType.redo]: { toolInfo: ToolInfo | null; canRedo: boolean }
[EventType.pickColor]: { color: Color }
[EventType.previewColor]: { color: Color | null }
[EventType.clear]: undefined
Expand All @@ -56,7 +57,6 @@ export interface DrawingEngineEventMap {
[EventType.move]: { positions: ReadonlyArray<InputPoint>; isPressed: boolean }
[EventType.release]: { position: Readonly<InputPoint> }
[EventType.cancel]: undefined
[EventType.engineLoaded]: undefined
}
export type DrawingEngineEvent<T extends EventType> = {
eventName: T
Expand Down Expand Up @@ -316,10 +316,6 @@ export class DrawingEngine {
this.render("draw")
}

public addHistory(toolInfo: ToolInfo) {
this.history?.add(toolInfo)
}

public undo() {
return this.history?.undo()
}
Expand Down
2 changes: 1 addition & 1 deletion libs/drawing-engine/src/tools/LineTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class LineTool {
return
}
this.engine.commitToSavedLayer()
this.engine.addHistory(this.getToolInfo())
this.engine.callListeners(EventType.commit, this.getToolInfo())
this.currentPath = []
}

Expand Down

0 comments on commit 8444dde

Please sign in to comment.