2017-11-29 05:24:35 +01:00
|
|
|
const { Component } = require('react')
|
2017-12-04 09:06:09 +01:00
|
|
|
const PropTypes = require('prop-types')
|
2018-03-29 17:00:44 +02:00
|
|
|
const connect = require('react-redux').connect
|
2018-05-14 23:34:10 +02:00
|
|
|
const { Route, Switch, withRouter } = require('react-router-dom')
|
2017-11-29 05:24:35 +01:00
|
|
|
const { compose } = require('recompose')
|
2016-04-14 00:28:44 +02:00
|
|
|
const h = require('react-hyperscript')
|
|
|
|
const actions = require('./actions')
|
2018-01-10 01:45:39 +01:00
|
|
|
const classnames = require('classnames')
|
2018-04-12 23:06:59 +02:00
|
|
|
const log = require('loglevel')
|
2018-01-10 01:45:39 +01:00
|
|
|
|
2018-03-28 22:21:53 +02:00
|
|
|
// init
|
|
|
|
const InitializeScreen = require('../../mascara/src/app/first-time').default
|
2016-04-14 00:28:44 +02:00
|
|
|
// accounts
|
2018-06-20 17:48:23 +02:00
|
|
|
const SendTransactionScreen = require('./components/send/send.container')
|
2018-06-23 08:52:45 +02:00
|
|
|
const ConfirmTransaction = require('./components/pages/confirm-transaction')
|
2017-08-02 23:17:58 +02:00
|
|
|
|
|
|
|
// slideout menu
|
2018-08-23 04:27:35 +02:00
|
|
|
const Sidebar = require('./components/sidebars').default
|
2017-08-02 23:17:58 +02:00
|
|
|
|
2016-04-14 00:28:44 +02:00
|
|
|
// other views
|
2018-07-24 20:40:05 +02:00
|
|
|
import Home from './components/pages/home'
|
2018-09-12 02:32:37 +02:00
|
|
|
import Settings from './components/pages/settings'
|
2017-11-29 05:24:35 +01:00
|
|
|
const Authenticated = require('./components/pages/authenticated')
|
2017-12-04 21:13:02 +01:00
|
|
|
const Initialized = require('./components/pages/initialized')
|
2018-07-05 19:09:55 +02:00
|
|
|
const RestoreVaultPage = require('./components/pages/keychains/restore-vault').default
|
2018-05-14 15:30:50 +02:00
|
|
|
const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed')
|
2017-11-29 05:24:35 +01:00
|
|
|
const AddTokenPage = require('./components/pages/add-token')
|
2018-05-20 08:04:19 +02:00
|
|
|
const ConfirmAddTokenPage = require('./components/pages/confirm-add-token')
|
2018-08-07 02:03:49 +02:00
|
|
|
const ConfirmAddSuggestedTokenPage = require('./components/pages/confirm-add-suggested-token')
|
2018-02-01 03:08:49 +01:00
|
|
|
const CreateAccountPage = require('./components/pages/create-account')
|
2017-11-29 05:24:35 +01:00
|
|
|
const NoticeScreen = require('./components/pages/notice')
|
|
|
|
|
2018-05-14 15:30:50 +02:00
|
|
|
const Loading = require('./components/loading-screen')
|
2017-08-13 22:15:21 +02:00
|
|
|
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
|
2017-10-13 08:10:58 +02:00
|
|
|
const AccountMenu = require('./components/account-menu')
|
2017-08-13 19:24:51 +02:00
|
|
|
|
|
|
|
// Global Modals
|
2017-08-21 03:32:58 +02:00
|
|
|
const Modal = require('./components/modals/index').Modal
|
2018-07-19 08:31:02 +02:00
|
|
|
// Global Alert
|
|
|
|
const Alert = require('./components/alert')
|
2016-10-31 19:35:09 +01:00
|
|
|
|
2018-08-19 03:41:19 +02:00
|
|
|
import AppHeader from './components/app-header'
|
2018-07-10 23:56:12 +02:00
|
|
|
import UnlockPage from './components/pages/unlock-page'
|
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
// Routes
|
|
|
|
const {
|
|
|
|
DEFAULT_ROUTE,
|
|
|
|
UNLOCK_ROUTE,
|
|
|
|
SETTINGS_ROUTE,
|
|
|
|
REVEAL_SEED_ROUTE,
|
|
|
|
RESTORE_VAULT_ROUTE,
|
|
|
|
ADD_TOKEN_ROUTE,
|
2018-05-20 08:04:19 +02:00
|
|
|
CONFIRM_ADD_TOKEN_ROUTE,
|
2018-08-07 02:03:49 +02:00
|
|
|
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
|
2018-02-01 03:08:49 +01:00
|
|
|
NEW_ACCOUNT_ROUTE,
|
2017-11-29 05:24:35 +01:00
|
|
|
SEND_ROUTE,
|
|
|
|
CONFIRM_TRANSACTION_ROUTE,
|
2017-12-04 07:24:30 +01:00
|
|
|
INITIALIZE_ROUTE,
|
2017-11-29 05:24:35 +01:00
|
|
|
NOTICE_ROUTE,
|
|
|
|
} = require('./routes')
|
|
|
|
|
|
|
|
class App extends Component {
|
|
|
|
componentWillMount () {
|
2018-05-14 15:30:50 +02:00
|
|
|
const { currentCurrency, setCurrentCurrencyToUSD } = this.props
|
2017-11-29 05:24:35 +01:00
|
|
|
|
|
|
|
if (!currentCurrency) {
|
|
|
|
setCurrentCurrencyToUSD()
|
|
|
|
}
|
2017-08-07 04:03:38 +02:00
|
|
|
}
|
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
renderRoutes () {
|
|
|
|
const exact = true
|
|
|
|
|
|
|
|
return (
|
|
|
|
h(Switch, [
|
2018-04-02 11:59:49 +02:00
|
|
|
h(Route, { path: INITIALIZE_ROUTE, component: InitializeScreen }),
|
2017-12-04 21:13:02 +01:00
|
|
|
h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }),
|
|
|
|
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
|
2018-05-14 15:30:50 +02:00
|
|
|
h(Authenticated, { path: REVEAL_SEED_ROUTE, exact, component: RevealSeedConfirmation }),
|
|
|
|
h(Authenticated, { path: SETTINGS_ROUTE, component: Settings }),
|
|
|
|
h(Authenticated, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
|
2018-06-23 08:52:45 +02:00
|
|
|
h(Authenticated, {
|
|
|
|
path: `${CONFIRM_TRANSACTION_ROUTE}/:id?`,
|
|
|
|
component: ConfirmTransaction,
|
|
|
|
}),
|
2018-04-27 21:03:00 +02:00
|
|
|
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen }),
|
2017-11-29 05:24:35 +01:00
|
|
|
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
|
2018-05-20 08:04:19 +02:00
|
|
|
h(Authenticated, { path: CONFIRM_ADD_TOKEN_ROUTE, exact, component: ConfirmAddTokenPage }),
|
2018-08-07 02:03:49 +02:00
|
|
|
h(Authenticated, { path: CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE, exact, component: ConfirmAddSuggestedTokenPage }),
|
2018-02-01 03:08:49 +01:00
|
|
|
h(Authenticated, { path: NEW_ACCOUNT_ROUTE, component: CreateAccountPage }),
|
2018-03-30 23:51:11 +02:00
|
|
|
h(Authenticated, { path: DEFAULT_ROUTE, exact, component: Home }),
|
2017-11-29 05:24:35 +01:00
|
|
|
])
|
|
|
|
)
|
2017-10-19 04:09:26 +02:00
|
|
|
}
|
2017-09-29 01:13:53 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
render () {
|
2017-12-04 09:06:09 +01:00
|
|
|
const {
|
|
|
|
isLoading,
|
2018-07-19 08:31:02 +02:00
|
|
|
alertMessage,
|
2017-12-04 09:06:09 +01:00
|
|
|
loadingMessage,
|
|
|
|
network,
|
2018-03-27 09:20:35 +02:00
|
|
|
isMouseUser,
|
2017-12-04 09:06:09 +01:00
|
|
|
provider,
|
|
|
|
frequentRpcList,
|
|
|
|
currentView,
|
2018-03-27 09:20:35 +02:00
|
|
|
setMouseUserState,
|
2018-08-23 04:27:35 +02:00
|
|
|
sidebar,
|
2017-12-04 09:06:09 +01:00
|
|
|
} = this.props
|
|
|
|
const isLoadingNetwork = network === 'loading' && currentView.name !== 'config'
|
2017-11-29 05:24:35 +01:00
|
|
|
const loadMessage = loadingMessage || isLoadingNetwork ?
|
2018-05-30 21:13:45 +02:00
|
|
|
this.getConnectingLabel(loadingMessage) : null
|
2017-11-29 05:24:35 +01:00
|
|
|
log.debug('Main ui render function')
|
2016-04-14 00:28:44 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
return (
|
|
|
|
h('.flex-column.full-height', {
|
2018-03-27 09:20:35 +02:00
|
|
|
className: classnames({ 'mouse-user-styles': isMouseUser }),
|
2017-11-29 05:24:35 +01:00
|
|
|
style: {
|
|
|
|
overflowX: 'hidden',
|
|
|
|
position: 'relative',
|
|
|
|
alignItems: 'center',
|
|
|
|
},
|
2018-03-27 09:20:35 +02:00
|
|
|
tabIndex: '0',
|
|
|
|
onClick: () => setMouseUserState(true),
|
|
|
|
onKeyDown: (e) => {
|
|
|
|
if (e.keyCode === 9) {
|
|
|
|
setMouseUserState(false)
|
|
|
|
}
|
|
|
|
},
|
2017-11-29 05:24:35 +01:00
|
|
|
}, [
|
2017-08-08 22:37:41 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
// global modal
|
|
|
|
h(Modal, {}, []),
|
2017-08-02 23:17:58 +02:00
|
|
|
|
2018-07-19 08:31:02 +02:00
|
|
|
// global alert
|
|
|
|
h(Alert, {visible: this.props.alertOpen, msg: alertMessage}),
|
|
|
|
|
2018-05-14 23:34:10 +02:00
|
|
|
h(AppHeader),
|
2017-08-02 23:17:58 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
// sidebar
|
2018-08-23 04:27:35 +02:00
|
|
|
h(Sidebar, {
|
|
|
|
sidebarOpen: sidebar.isOpen,
|
|
|
|
hideSidebar: this.props.hideSidebar,
|
|
|
|
transitionName: sidebar.transitionName,
|
|
|
|
type: sidebar.type,
|
|
|
|
}),
|
2016-04-14 00:28:44 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
// network dropdown
|
|
|
|
h(NetworkDropdown, {
|
2017-12-04 09:06:09 +01:00
|
|
|
provider,
|
|
|
|
frequentRpcList,
|
2017-11-29 05:24:35 +01:00
|
|
|
}, []),
|
2017-10-13 08:10:58 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
h(AccountMenu),
|
2017-11-02 13:15:59 +01:00
|
|
|
|
2018-09-19 21:13:58 +02:00
|
|
|
h('div.main-container-wrapper', [
|
2018-09-19 20:22:39 +02:00
|
|
|
(isLoading || isLoadingNetwork) && h(Loading, {
|
|
|
|
loadingMessage: loadMessage,
|
|
|
|
}),
|
|
|
|
|
|
|
|
// content
|
|
|
|
this.renderRoutes(),
|
|
|
|
]),
|
2017-11-29 05:24:35 +01:00
|
|
|
])
|
|
|
|
)
|
|
|
|
}
|
2017-08-08 22:37:41 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
toggleMetamaskActive () {
|
|
|
|
if (!this.props.isUnlocked) {
|
|
|
|
// currently inactive: redirect to password box
|
|
|
|
var passwordBox = document.querySelector('input[type=password]')
|
|
|
|
if (!passwordBox) return
|
|
|
|
passwordBox.focus()
|
|
|
|
} else {
|
|
|
|
// currently active: deactivate
|
|
|
|
this.props.dispatch(actions.lockMetamask(false))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-30 21:13:45 +02:00
|
|
|
getConnectingLabel = function (loadingMessage) {
|
|
|
|
if (loadingMessage) {
|
|
|
|
return loadingMessage
|
|
|
|
}
|
2018-03-27 09:20:35 +02:00
|
|
|
const { provider } = this.props
|
|
|
|
const providerName = provider.type
|
|
|
|
|
|
|
|
let name
|
|
|
|
|
|
|
|
if (providerName === 'mainnet') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('connectingToMainnet')
|
2018-03-27 09:20:35 +02:00
|
|
|
} else if (providerName === 'ropsten') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('connectingToRopsten')
|
2018-03-27 09:20:35 +02:00
|
|
|
} else if (providerName === 'kovan') {
|
2018-09-06 16:50:55 +02:00
|
|
|
name = this.context.t('connectingToKovan')
|
2018-03-27 09:20:35 +02:00
|
|
|
} else if (providerName === 'rinkeby') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('connectingToRinkeby')
|
2018-03-27 09:20:35 +02:00
|
|
|
} else {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('connectingToUnknown')
|
2018-03-27 09:20:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return name
|
2018-03-19 19:28:02 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
getNetworkName () {
|
|
|
|
const { provider } = this.props
|
|
|
|
const providerName = provider.type
|
|
|
|
|
|
|
|
let name
|
|
|
|
|
|
|
|
if (providerName === 'mainnet') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('mainnet')
|
2017-11-29 05:24:35 +01:00
|
|
|
} else if (providerName === 'ropsten') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('ropsten')
|
2017-11-29 05:24:35 +01:00
|
|
|
} else if (providerName === 'kovan') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('kovan')
|
2017-11-29 05:24:35 +01:00
|
|
|
} else if (providerName === 'rinkeby') {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('rinkeby')
|
2017-11-29 05:24:35 +01:00
|
|
|
} else {
|
2018-03-31 01:18:48 +02:00
|
|
|
name = this.context.t('unknownNetwork')
|
2017-11-29 05:24:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return name
|
2016-05-14 03:07:47 +02:00
|
|
|
}
|
|
|
|
}
|
2016-06-29 02:57:53 +02:00
|
|
|
|
2017-12-04 09:06:09 +01:00
|
|
|
App.propTypes = {
|
|
|
|
currentCurrency: PropTypes.string,
|
|
|
|
setCurrentCurrencyToUSD: PropTypes.func,
|
|
|
|
isLoading: PropTypes.bool,
|
|
|
|
loadingMessage: PropTypes.string,
|
2018-07-19 08:31:02 +02:00
|
|
|
alertMessage: PropTypes.string,
|
2017-12-04 09:06:09 +01:00
|
|
|
network: PropTypes.string,
|
|
|
|
provider: PropTypes.object,
|
|
|
|
frequentRpcList: PropTypes.array,
|
|
|
|
currentView: PropTypes.object,
|
2018-08-23 04:27:35 +02:00
|
|
|
sidebar: PropTypes.object,
|
2018-07-19 08:31:02 +02:00
|
|
|
alertOpen: PropTypes.bool,
|
2017-12-04 09:06:09 +01:00
|
|
|
hideSidebar: PropTypes.func,
|
|
|
|
isMascara: PropTypes.bool,
|
|
|
|
isOnboarding: PropTypes.bool,
|
|
|
|
isUnlocked: PropTypes.bool,
|
|
|
|
networkDropdownOpen: PropTypes.bool,
|
|
|
|
showNetworkDropdown: PropTypes.func,
|
|
|
|
hideNetworkDropdown: PropTypes.func,
|
|
|
|
history: PropTypes.object,
|
2018-04-03 10:03:31 +02:00
|
|
|
location: PropTypes.object,
|
2017-12-04 09:06:09 +01:00
|
|
|
dispatch: PropTypes.func,
|
|
|
|
toggleAccountMenu: PropTypes.func,
|
|
|
|
selectedAddress: PropTypes.string,
|
|
|
|
noActiveNotices: PropTypes.bool,
|
|
|
|
lostAccounts: PropTypes.array,
|
|
|
|
isInitialized: PropTypes.bool,
|
|
|
|
forgottenPassword: PropTypes.bool,
|
|
|
|
activeAddress: PropTypes.string,
|
|
|
|
unapprovedTxs: PropTypes.object,
|
|
|
|
seedWords: PropTypes.string,
|
2017-12-05 04:27:42 +01:00
|
|
|
unapprovedMsgCount: PropTypes.number,
|
|
|
|
unapprovedPersonalMsgCount: PropTypes.number,
|
|
|
|
unapprovedTypedMessagesCount: PropTypes.number,
|
2018-03-27 09:20:35 +02:00
|
|
|
welcomeScreenSeen: PropTypes.bool,
|
|
|
|
isPopup: PropTypes.bool,
|
|
|
|
betaUI: PropTypes.bool,
|
|
|
|
isMouseUser: PropTypes.bool,
|
|
|
|
setMouseUserState: PropTypes.func,
|
2018-03-30 23:51:11 +02:00
|
|
|
t: PropTypes.func,
|
2017-12-04 09:06:09 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
function mapStateToProps (state) {
|
|
|
|
const { appState, metamask } = state
|
|
|
|
const {
|
|
|
|
networkDropdownOpen,
|
2018-08-23 04:27:35 +02:00
|
|
|
sidebar,
|
2018-07-19 08:31:02 +02:00
|
|
|
alertOpen,
|
|
|
|
alertMessage,
|
2017-11-29 05:24:35 +01:00
|
|
|
isLoading,
|
|
|
|
loadingMessage,
|
|
|
|
} = appState
|
|
|
|
|
|
|
|
const {
|
|
|
|
identities,
|
|
|
|
accounts,
|
|
|
|
address,
|
|
|
|
keyrings,
|
|
|
|
isInitialized,
|
|
|
|
noActiveNotices,
|
|
|
|
seedWords,
|
|
|
|
unapprovedTxs,
|
2018-06-14 08:30:31 +02:00
|
|
|
nextUnreadNotice,
|
2017-11-29 05:24:35 +01:00
|
|
|
lostAccounts,
|
2017-12-05 04:27:42 +01:00
|
|
|
unapprovedMsgCount,
|
|
|
|
unapprovedPersonalMsgCount,
|
|
|
|
unapprovedTypedMessagesCount,
|
2017-11-29 05:24:35 +01:00
|
|
|
} = metamask
|
|
|
|
const selected = address || Object.keys(accounts)[0]
|
|
|
|
|
|
|
|
return {
|
|
|
|
// state from plugin
|
|
|
|
networkDropdownOpen,
|
2018-08-23 04:27:35 +02:00
|
|
|
sidebar,
|
2018-07-19 08:31:02 +02:00
|
|
|
alertOpen,
|
|
|
|
alertMessage,
|
2017-11-29 05:24:35 +01:00
|
|
|
isLoading,
|
|
|
|
loadingMessage,
|
|
|
|
noActiveNotices,
|
|
|
|
isInitialized,
|
|
|
|
isUnlocked: state.metamask.isUnlocked,
|
|
|
|
selectedAddress: state.metamask.selectedAddress,
|
|
|
|
currentView: state.appState.currentView,
|
|
|
|
activeAddress: state.appState.activeAddress,
|
|
|
|
transForward: state.appState.transForward,
|
|
|
|
isMascara: state.metamask.isMascara,
|
|
|
|
isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized),
|
2018-03-27 09:20:35 +02:00
|
|
|
isPopup: state.metamask.isPopup,
|
2017-11-29 05:24:35 +01:00
|
|
|
seedWords: state.metamask.seedWords,
|
|
|
|
unapprovedTxs,
|
2018-03-27 09:20:35 +02:00
|
|
|
unapprovedMsgs: state.metamask.unapprovedMsgs,
|
2017-12-05 04:27:42 +01:00
|
|
|
unapprovedMsgCount,
|
|
|
|
unapprovedPersonalMsgCount,
|
|
|
|
unapprovedTypedMessagesCount,
|
2017-11-29 05:24:35 +01:00
|
|
|
menuOpen: state.appState.menuOpen,
|
|
|
|
network: state.metamask.network,
|
|
|
|
provider: state.metamask.provider,
|
|
|
|
forgottenPassword: state.appState.forgottenPassword,
|
2018-06-14 08:30:31 +02:00
|
|
|
nextUnreadNotice,
|
2017-11-29 05:24:35 +01:00
|
|
|
lostAccounts,
|
|
|
|
frequentRpcList: state.metamask.frequentRpcList || [],
|
|
|
|
currentCurrency: state.metamask.currentCurrency,
|
2018-03-27 09:20:35 +02:00
|
|
|
isMouseUser: state.appState.isMouseUser,
|
|
|
|
betaUI: state.metamask.featureFlags.betaUI,
|
|
|
|
isRevealingSeedWords: state.metamask.isRevealingSeedWords,
|
|
|
|
Qr: state.appState.Qr,
|
|
|
|
welcomeScreenSeen: state.metamask.welcomeScreenSeen,
|
2017-11-29 05:24:35 +01:00
|
|
|
|
|
|
|
// state needed to get account dropdown temporarily rendering from app bar
|
|
|
|
identities,
|
|
|
|
selected,
|
|
|
|
keyrings,
|
2017-07-04 00:12:24 +02:00
|
|
|
}
|
2017-11-29 05:24:35 +01:00
|
|
|
}
|
2017-07-04 00:12:24 +02:00
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
function mapDispatchToProps (dispatch, ownProps) {
|
|
|
|
return {
|
|
|
|
dispatch,
|
|
|
|
hideSidebar: () => dispatch(actions.hideSidebar()),
|
|
|
|
showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()),
|
|
|
|
hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()),
|
|
|
|
setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')),
|
|
|
|
toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
|
2018-03-27 09:20:35 +02:00
|
|
|
setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)),
|
2017-11-29 05:24:35 +01:00
|
|
|
}
|
2017-07-04 00:12:24 +02:00
|
|
|
}
|
2017-11-29 05:24:35 +01:00
|
|
|
|
2018-03-31 02:37:24 +02:00
|
|
|
App.contextTypes = {
|
|
|
|
t: PropTypes.func,
|
|
|
|
}
|
|
|
|
|
2017-11-29 05:24:35 +01:00
|
|
|
module.exports = compose(
|
|
|
|
withRouter,
|
|
|
|
connect(mapStateToProps, mapDispatchToProps)
|
|
|
|
)(App)
|