import * as React from 'react'; import { interpret, Interpreter } from 'xstate'; import { EditContext, EditSchema, EditEvent } from './StateMachine/index.data'; import { IColDimensions, IRowDimensions, IStoreState } from './index.data'; import { Store } from 'unistore'; import getMachine from './StateMachine'; import * as R from 'rambda'; import FormulaManager from './formula-manager/FormulaManager'; import { CommandManager } from 'valor-unistore-undo'; import { getCommands, getQueries } from './SpreadSheetProvider/helper'; import { Props } from './SpreadSheetProvider/index.data'; import { objSubtractDeep } from 'valor-app-utils'; export class SpreadSheetRuntime { store: Store; fsmService: Interpreter; formulaManager: FormulaManager; commands: ReturnType; queries: ReturnType; checkableConfig: Props['checkableConfig']; rowNoTemplates: string[]; // 设置后, 批量操作完成后统一重算 batchMode: boolean; // 设置后将禁用自动重算 disableAutoCalculate: boolean; // 重新根据当前dom数据, patch state里的rowDimensions/colDimensions public setSheetDimensions: () => void = (() => { throw new Error('Runtime尚未设置setDimension, 不能调用'); }) as any; public patchState(patch: Partial) { console.log('patch', patch); this.store.setState(patch as any); } subs: any; constructor( store: Store, formulaManager: FormulaManager, checkableConfig: Props['checkableConfig'], rowNoTemplates: string[], batchMode: boolean, disableAutoCalculate: boolean, ) { this.store = store; this.formulaManager = formulaManager; const commandManager = new CommandManager(this.store, this); this.commands = getCommands(commandManager); this.queries = getQueries(this); this.checkableConfig = checkableConfig; this.rowNoTemplates = rowNoTemplates; this.batchMode = batchMode; this.disableAutoCalculate = disableAutoCalculate; const usage = store.getState().usage; const machine = getMachine(usage); this.fsmService = interpret(machine); this.subs = this.fsmService.subscribe(state => { if (!state.changed) return; const { selectionType, selectedRowRange, selectedColumnRange, selectedCellRange, isActiving, } = state.context; const newMachineState = { selectionType, selectedRowRange, selectedCellRange, selectedColumnRange, isActiving, mode: state.value, }; const oldMachineState = R.pick(Object.keys(newMachineState), store.getState()); if (!R.equals(newMachineState, oldMachineState)) { // console.log('状态机有变动: new:', newMachineState, 'old:', oldMachineState); console.log( '状态机变动 , 差异为:', JSON.stringify(objSubtractDeep(newMachineState, oldMachineState)), ); store.setState(newMachineState); } }); this.sendFsmEvent = this.sendFsmEvent.bind(this); this.fsmService.start(); console.log('状态机已启动'); } dispose() { this.subs.unsubscribe(); this.fsmService.stop(); console.log('状态机已终止'); } sendFsmEvent(event: EditEvent) { const state = this.store.getState(); this.fsmService.send({ ...event, state }); } } const RuntimeContext = React.createContext(null); export default RuntimeContext;