UNPKG

@aitianyu.cn/tianyu-store

Version:
210 lines 10 kB
"use strict"; /** @format */ Object.defineProperty(exports, "__esModule", { value: true }); exports.StoreInstanceImpl = void 0; const types_1 = require("@aitianyu.cn/types"); const DiffHelper_1 = require("../../common/DiffHelper"); const Message_1 = require("../../infra/Message"); const Action_1 = require("../../types/Action"); const ExternalRegister_1 = require("../modules/ExternalRegister"); const RedoUndoStackImpl_1 = require("../storage/RedoUndoStackImpl"); const RedoUndoStack_1 = require("../storage/interface/RedoUndoStack"); const StoreState_1 = require("../storage/interface/StoreState"); const InstanceIdImpl_1 = require("./InstanceIdImpl"); const InstanceParentHolder_1 = require("../modules/InstanceParentHolder"); const RedoUndoStack_2 = require("../../types/RedoUndoStack"); const ObjectUtils_1 = require("../../utils/ObjectUtils"); class StoreInstanceImpl { // external object will not be redo/undo // even it is created, only when the whole store instance is destroied or delete it manually, // the external objects are always kept externalObjectMap; parentChildHolder; storeState; instanceId; changeCache; diffCache; constructor(state, instanceId) { this.storeState = state; this.changeCache = {}; this.diffCache = {}; this.instanceId = instanceId; this.externalObjectMap = new Map(); this.parentChildHolder = new InstanceParentHolder_1.InstanceParentHolder(); // to init the root external register const externalRegister = new ExternalRegister_1.ExternalRegister(); if (this.storeState[StoreState_1.STORE_STATE_SYSTEM].config.redoUndo) { externalRegister.add(RedoUndoStack_1.STORE_STATE_EXTERNAL_REDOUNDO_STACK, new RedoUndoStackImpl_1.RedoUndoStackImpl()); } this.externalObjectMap.set(instanceId.toString(), externalRegister); } getRecentChanges() { const redoUndoStack = this.externalObjectMap .get(this.instanceId.toString()) ?.get(RedoUndoStack_1.STORE_STATE_EXTERNAL_REDOUNDO_STACK); return redoUndoStack?.getCurrent() || {}; } getHistories() { const redoUndoStack = this.externalObjectMap .get(this.instanceId.toString()) ?.get(RedoUndoStack_1.STORE_STATE_EXTERNAL_REDOUNDO_STACK); return redoUndoStack?.getHistroies() || /* istanbul ignore next */ { histroy: [], index: -1 }; } addStoreType(storeType) { if (!this.storeState[StoreState_1.STORE_STATE_INSTANCE][storeType]) { this.storeState[StoreState_1.STORE_STATE_INSTANCE][storeType] = {}; } } getRawState() { return types_1.ObjectHelper.clone(this.storeState); } getExternalRegister(instanceId, creating) { const externalObject = this.externalObjectMap.get(instanceId.toString()); if (!externalObject) { throw new Error(Message_1.MessageBundle.getText("STORE_INSTANCE_EXTRERNAL_MANAGER_NOT_FOUND", instanceId.toString())); } return externalObject; } getState(instanceId, creating) { if (InstanceIdImpl_1.InstanceIdImpl.isAncestor(instanceId)) { // if the instance id indicates an entity it self // return whole store state return this.storeState; } const instanceId2String = instanceId.toString(); const storeType = instanceId.storeType; if (!storeType) { throw new Error(Message_1.MessageBundle.getText("INSTANCE_ID_NOT_VALID", instanceId2String)); } const cachedState = this.changeCache[storeType]?.[instanceId2String]; if (cachedState?.type === RedoUndoStack_2.DifferenceChangeType.Delete) { // instance is deleted and it does not be able to be used throw new Error(Message_1.MessageBundle.getText("STORE_INSTANCE_USE_DELETED", storeType, instanceId2String)); } const instances = this.storeState[StoreState_1.STORE_STATE_INSTANCE][storeType]; const ins = cachedState?.state || instances[instanceId2String]; if (!ins && !creating) { throw new Error(Message_1.MessageBundle.getText("STORE_INSTANCE_NOT_EXIST", instanceId2String)); } return ins; } getOriginState(instanceId) { if (InstanceIdImpl_1.InstanceIdImpl.isAncestor(instanceId)) { // if the instance id indicates an entity it self // return whole store state return this.storeState; } const instanceId2String = instanceId.toString(); const storeType = instanceId.storeType; if (!storeType) { throw new Error(Message_1.MessageBundle.getText("INSTANCE_ID_NOT_VALID", instanceId2String)); } const instances = this.storeState[StoreState_1.STORE_STATE_INSTANCE][storeType]; const ins = instances[instanceId2String]; if (!ins) { throw new Error(Message_1.MessageBundle.getText("STORE_INSTANCE_NOT_EXIST", instanceId2String)); } return ins; } applyChanges() { let redoUndoSupport = true; let recordRedoUndo = true; const diff = this.diffCache; this.diffCache = {}; if ((0, ObjectUtils_1.isChangesEmpty)(diff)) { const changes = this.changeCache; this.changeCache = {}; for (const storyType of Object.keys(changes)) { const instances = changes[storyType]; for (const insId of Object.keys(instances)) { const changeItem = instances[insId]; const oldState = this.storeState[StoreState_1.STORE_STATE_INSTANCE][storyType]?.[insId]; if (types_1.ObjectHelper.compareObjects(oldState, changeItem.state) === "different") { // ensure the state is changed if (!diff[storyType]) { diff[storyType] = {}; } diff[storyType][insId] = { new: changeItem.state, old: oldState, type: changeItem.type, }; } if (changeItem.type === RedoUndoStack_2.DifferenceChangeType.Create) { this.parentChildHolder.createInstance(new InstanceIdImpl_1.InstanceIdImpl(insId), this.storeState[StoreState_1.STORE_STATE_SYSTEM].instanceMap); } // this is for state redo/undo checking // when there is a view action // should clean all redo/undo stack due to the state is could not be navigated redoUndoSupport = redoUndoSupport && changeItem.redoUndo; // this is for state redo/undo recording checking // when there is a redo/undo action // should not to record the state change again recordRedoUndo = recordRedoUndo && changeItem.record; } } } else { recordRedoUndo = false; } this.storeState = (0, DiffHelper_1.mergeDiff)(this.storeState, diff); this.parentChildHolder.applyChanges(this.storeState[StoreState_1.STORE_STATE_SYSTEM].instanceMap); const redoUndoStack = this.externalObjectMap .get(this.instanceId.toString()) ?.get(RedoUndoStack_1.STORE_STATE_EXTERNAL_REDOUNDO_STACK); if (redoUndoSupport) { recordRedoUndo && redoUndoStack?.record(diff); } else { redoUndoStack?.resetRedoUndo(); } return diff; } discardChanges() { this.changeCache = {}; this.parentChildHolder.discardChanges(); } pushStateChange(storeType, instanceId, actionType, newState, notRedoUndo) { if (!this.changeCache[storeType]) { this.changeCache[storeType] = {}; } const redoUndo = !notRedoUndo && actionType !== Action_1.ActionType.VIEW_ACTION; const record = actionType !== Action_1.ActionType.REDO && actionType !== Action_1.ActionType.UNDO; this.changeCache[storeType][instanceId] = { state: newState, type: actionType === Action_1.ActionType.CREATE ? RedoUndoStack_2.DifferenceChangeType.Create : actionType === Action_1.ActionType.DESTROY ? RedoUndoStack_2.DifferenceChangeType.Delete : RedoUndoStack_2.DifferenceChangeType.Change, redoUndo, record, }; if (actionType === Action_1.ActionType.CREATE) { // for create new instance, to create a new external object manager this.externalObjectMap.set(instanceId, new ExternalRegister_1.ExternalRegister()); } if (actionType === Action_1.ActionType.DESTROY) { // for destroy instance, to destroy its children const instances = this.parentChildHolder.removeInstance(instanceId, this.storeState[StoreState_1.STORE_STATE_SYSTEM].instanceMap); for (const insId of instances) { const ins = new InstanceIdImpl_1.InstanceIdImpl(insId); const storeType = ins.storeType; this.changeCache[storeType][insId] = { state: undefined, type: RedoUndoStack_2.DifferenceChangeType.Delete, redoUndo, record, }; } } } pushDiffChange(diff) { this.diffCache = diff; } validateActionInstance(action) { // } } exports.StoreInstanceImpl = StoreInstanceImpl; //# sourceMappingURL=StoreInstanceImpl.js.map