import { types , resolvePath , getEnv , onSnapshot , getSnapshot , applySnapshot , IDisposer } from "mobx-state-tree" ; import { IObservableArray } from "mobx" ; const TimeTraveller = types . model ( "TimeTraveller" , { history : types . array ( types . frozen ( ) ) , undoIdx : - 1 , targetPath : "" } ) . views ( ( self ) => ( { get canUndo ( ) { return self . undoIdx > 0 ; } , get canRedo ( ) { return self . undoIdx < self . history . length - 1 ; } } ) ) . actions ( ( self ) => { let targetStore ; let snapshotDisposer ; let skipNextUndoState = false ; return { addUndoState ( todos ) { if ( skipNextUndoState ) { skipNextUndoState = false ; return ; } self . history . splice ( self . undoIdx + 1 ) ; self . history . push ( todos ) ; self . undoIdx = self . history . length - 1 ; } , afterCreate ( ) { targetStore = self . targetPath ? resolvePath ( self , self . targetPath ) : getEnv ( self ) . targetStore ; if ( ! targetStore ) throw new Error ( "Failed to find target store for TimeTraveller. Please provide `targetPath` property, or a `targetStore` in the environment" ) ; snapshotDisposer = onSnapshot ( targetStore , ( snapshot ) => this . addUndoState ( snapshot ) ) ; if ( self . history . length === 0 ) { this . addUndoState ( getSnapshot ( targetStore ) ) ; } } , beforeDestroy ( ) { snapshotDisposer ( ) ; } , undo ( ) { self . undoIdx -- ; skipNextUndoState = true ; applySnapshot ( targetStore , self . history [ self . undoIdx ] ) ; } , redo ( ) { self . undoIdx ++ ; skipNextUndoState = true ; applySnapshot ( targetStore , self . history [ self . undoIdx ] ) ; } } ; } ) ; export default TimeTraveller ;