import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { applyMiddleware, compose, createStore, GenericStoreEnhancer, Middleware, Store, } from 'redux'; import { Provider, } from 'react-redux'; import { ConnectedRouter, routerMiddleware, } from 'react-router-redux'; import createSagaMiddleware, { SagaMiddleware, SagaIterator, } from 'redux-saga'; import { fork, } from 'redux-saga/effects'; import { createHashHistory, History, } from 'history'; import { AppContainer, } from 'react-hot-loader'; import * as injectTapEventPlugin from 'react-tap-event-plugin'; import Application from '@loafer/application/Application'; import ApplicationStater from '@loafer/application/ApplicationStater'; import Platform from '@overflow/commons/platform'; import App from '@loafer/context/decorator/App'; import Inject from '@loafer/pouches/decorator/Inject'; import AppContext from '@loafer/context/AppContext'; import * as AppContextLifecycleActions from '@loafer/context/redux/action/lifecycle'; import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC'; import ReducerContext from '@overflow/commons/redux/ReducerContext'; import { SagaWatcher } from '@overflow/commons/constant'; import appConfig, { Config, ReduxState } from './config'; import * as AppView from './views/App'; declare global { interface Window { devToolsExtension: () => any; } const process: any; const module: any; } injectTapEventPlugin(); @App() class OFApplication implements ApplicationStater { private static isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false; private static useReduxDevTools:boolean = window.devToolsExtension && !OFApplication.isProduction ? true : false; private config: Config; private container: HTMLElement; @Inject() private context: AppContext; private rpcClient: WebSocketRPC; private store: Store; private sagaMiddleware: SagaMiddleware; private history: History; public constructor() { this.config = appConfig; this.history = createHashHistory(); } public static main(): void { Application.run(OFApplication.prototype); } public async start(): Promise { try { this.container = await Platform.getAppContainer(this.config.container.placeholderID); this.displayLoading(); this.rpcClient = await this.initRpcClient(); // this.context.PouchFactory.registerPouch(this.rpcClient); await this.initRedux(); this.store.dispatch(AppContextLifecycleActions.initialized()); this.displayApp(); } catch (e) { console.error(e); this.displayError(e); } } private initRpcClient(): Promise { const rpcClient = new Promise((resolve, reject) => { let client = new WebSocketRPC(this.config.rpc.url); // client.initialize() // .then(() => { // resolve(client); // }) // .catch((err: any) => { // reject(err); // }); resolve(client); }); return rpcClient; } private initRedux(): Promise { const init = new Promise(resolve => { // state tree // reducer for (let reducerMap of this.config.redux.reducerMaps) { ReducerContext.putReducers(reducerMap); } // middleware let middlewares: Middleware[] = new Array(); this.sagaMiddleware = createSagaMiddleware(); middlewares.push(this.sagaMiddleware); let routerReduxMiddleware = routerMiddleware(this.history); middlewares.push(routerReduxMiddleware); // store let middleware: GenericStoreEnhancer = applyMiddleware(...middlewares); this.store = createStore( ReducerContext.reducer, this.config.redux.state, OFApplication.useReduxDevTools ? compose(middleware, window.devToolsExtension()) : middleware, ); // saga this.sagaMiddleware.run(this.initReduxSagaWarchers, this.config.redux.sagaWarchers); resolve(); }); return init; } private * initReduxSagaWarchers(sagaWarchers: SagaWatcher[]): SagaIterator { for (let sagaWarcher of sagaWarchers) { yield fork(sagaWarcher); } } private displayLoading(): void { ReactDOM.render(

Loading......

, this.container, ); } private displayError(e: Error): void { ReactDOM.render(

{e.message}

, this.container, ); } private displayApp(): void { OFApplication.isProduction ? this.displayProductionApp() : this.displayDebugApp(); } private displayProductionApp(): void { ReactDOM.render( , this.container, ); } private displayDebugApp(): void { if (module.hot) { module.hot.accept('./views/App', async () => { const NextApp = (await import('./views/App')).default; ReactDOM.render( , this.container, ); }); } ReactDOM.render( , this.container, ); } } OFApplication.main();