UNPKG

@infinite-canvas-tutorial/webcomponents

Version:
112 lines 4.38 kB
"use strict"; /** * Borrow from https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/store.ts */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Store = exports.CaptureUpdateAction = exports.StoreIncrementEvent = void 0; const eventemitter3_1 = require("eventemitter3"); const AppStateChange_1 = require("./AppStateChange"); const ElementsChange_1 = require("./ElementsChange"); const Snapshot_1 = require("./Snapshot"); exports.StoreIncrementEvent = 'storeIncrement'; exports.CaptureUpdateAction = { /** * Immediately undoable. * * Use for updates which should be captured. * Should be used for most of the local updates. * * These updates will _immediately_ make it to the local undo / redo stacks. */ IMMEDIATELY: 'IMMEDIATELY', /** * Never undoable. * * Use for updates which should never be recorded, such as remote updates * or scene initialization. * * These updates will _never_ make it to the local undo / redo stacks. */ NEVER: 'NEVER', /** * Eventually undoable. * * Use for updates which should not be captured immediately - likely * exceptions which are part of some async multi-step process. Otherwise, all * such updates would end up being captured with the next * `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene` * or internally by the editor. * * These updates will _eventually_ make it to the local undo / redo stacks. */ EVENTUALLY: 'EVENTUALLY', }; class Store { constructor() { this._snapshot = Snapshot_1.Snapshot.empty(); this.scheduledActions = new Set(); this.onStoreIncrementEmitter = new eventemitter3_1.EventEmitter(); } get snapshot() { return this._snapshot; } set snapshot(snapshot) { this._snapshot = snapshot; } scheduleAction(action) { this.scheduledActions.add(action); } shouldCaptureIncrement() { this.scheduleAction(exports.CaptureUpdateAction.IMMEDIATELY); } shouldUpdateSnapshot() { this.scheduleAction(exports.CaptureUpdateAction.NEVER); } commit(elements, appState) { try { // Capture has precedence since it also performs update if (this.scheduledActions.has(exports.CaptureUpdateAction.IMMEDIATELY)) { this.captureIncrement(elements, appState); } else if (this.scheduledActions.has(exports.CaptureUpdateAction.NEVER)) { this.updateSnapshot(elements, appState); } } finally { // Defensively reset all scheduled actions, potentially cleans up other runtime garbage this.scheduledActions = new Set(); } } captureIncrement(elements, appState) { const prevSnapshot = this.snapshot; const nextSnapshot = this.snapshot.maybeClone(elements, appState); // Optimisation, don't continue if nothing has changed if (prevSnapshot !== nextSnapshot) { // Calculate and record the changes based on the previous and next snapshot const elementsChange = nextSnapshot.meta.didElementsChange ? ElementsChange_1.ElementsChange.calculate(prevSnapshot.elements, nextSnapshot.elements) : ElementsChange_1.ElementsChange.empty(); const appStateChange = nextSnapshot.meta.didAppStateChange ? AppStateChange_1.AppStateChange.calculate(prevSnapshot.appState, nextSnapshot.appState) : AppStateChange_1.AppStateChange.empty(); if (!elementsChange.isEmpty() || !appStateChange.isEmpty()) { // Notify listeners with the increment this.onStoreIncrementEmitter.emit(exports.StoreIncrementEvent, { elementsChange, appStateChange, }); } // Update snapshot this.snapshot = nextSnapshot; } } updateSnapshot(elements, appState) { const nextSnapshot = this.snapshot.maybeClone(elements, appState); if (this.snapshot !== nextSnapshot) { // Update snapshot this.snapshot = nextSnapshot; } } } exports.Store = Store; //# sourceMappingURL=Store.js.map