import { Inject , Injectable , InjectionToken , Optional } from "@angular/core" ; import { BehaviorSubject } from "rxjs/BehaviorSubject" ; import { Observable } from "rxjs/Observable" ; import { observeOn , withLatestFrom } from "rxjs/operators" ; import { queue } from "rxjs/scheduler/queue" ; import { LibState , ReduxDevTools } from "../common/interfaces" ; import { Dispatcher } from "../store/dispatcher" ; import { Reducer } from "../store/reducer" ; export const STORE_INITIAL_STATE = new InjectionToken ( "ng2-md-datatable-test-initial-state" ) ; export const REDUX_DEVTOOLS_EXTENSION = new InjectionToken ( "redux-devtools" ) ; export function reduxDevToolsExtensionFactory ( ) { const REDUX_DEVTOOLS_KEY = "__REDUX_DEVTOOLS_EXTENSION__" ; return typeof window === "object" && typeof window [ REDUX_DEVTOOLS_KEY ] === "function" ? ( window [ REDUX_DEVTOOLS_KEY ] as ReduxDevTools . IExtension ) : null ; } @ Injectable ( ) export class Store extends Observable < LibState . IStates > { private instanceId = `ng2-md-datatable-store-${ Date . now ( ) }` ; private state$ : BehaviorSubject < LibState . IStates > ; constructor ( private dispatcher$ , @ Inject ( STORE_INITIAL_STATE ) initialState , reducer , @ Inject ( REDUX_DEVTOOLS_EXTENSION ) @ Optional ( ) reduxDevToolsExtension ) { super ( ) ; this . state$ = new BehaviorSubject < LibState . IStates > ( initialState ) ; this . source = this . state$ ; let connection ; if ( reduxDevToolsExtension ) { connection = reduxDevToolsExtension . connect ( { name : this . instanceId , features : { pause : false , lock : false , persist : false , export : true , import : false , jump : false , skip : false , reorder : false , dispatch : false , test : false } } ) ; } this . dispatcher$ . pipe ( observeOn ( queue ) , withLatestFrom ( this . source ) ) . subscribe ( ( [ action , state ] ) => { const newState = reducer . reduce ( state , action ) ; this . state$ . next ( newState ) ; if ( connection ) { connection . send ( action , newState , undefined , this . instanceId ) ; } } ) ; } dispatch ( action ) { this . dispatcher$ . dispatch ( action ) ; } }