You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

154 lines
4.3 KiB

import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Redirect, Route, Switch } from 'react-router-dom'
import { ConnectedRouter } from 'connected-react-router'
import { ThemeProvider } from 'styled-components'
import { clearError, errorSelectors } from 'reducers/error'
import { loadingSelectors, setLoading, setMounted } from 'reducers/loading'
import { initCurrency, initLocale } from 'reducers/locale'
import { initTheme, themeSelectors } from 'reducers/theme'
import { fetchTicker, tickerSelectors } from 'reducers/ticker'
import { fetchSuggestedNodes } from 'reducers/channels'
import { Page, Titlebar, GlobalStyle } from 'components/UI'
import GlobalError from 'components/GlobalError'
import withLoading from 'components/withLoading'
import Onboarding from './Onboarding'
import Syncing from './Syncing'
import App from './App'
// Wrap the apge with our isLoading HOC so that the app displays the loading graphic whhen it first mounts.
const PageWithLoading = withLoading(Page)
// The minimum amount of time that we will show the loading component when the app mounts.
const SPLASH_SCREEN_TIME = 1500
/**
* Root component that deals with mounting the app and managing top level routing.
*/
class Root extends React.Component {
static propTypes = {
clearError: PropTypes.func.isRequired,
currentTicker: PropTypes.object,
theme: PropTypes.object,
error: PropTypes.string,
fetchSuggestedNodes: PropTypes.func.isRequired,
fetchTicker: PropTypes.func.isRequired,
history: PropTypes.object.isRequired,
initLocale: PropTypes.func.isRequired,
initCurrency: PropTypes.func.isRequired,
initTheme: PropTypes.func.isRequired,
isLoading: PropTypes.bool.isRequired,
isMounted: PropTypes.bool.isRequired,
setLoading: PropTypes.func.isRequired,
setMounted: PropTypes.func.isRequired
}
/**
* Initialise component state props.
*/
constructor(props) {
super(props)
this.state = {
timer: null
}
}
/**
* // Show the loading bold briefly before showing the user the app.
*/
componentDidMount() {
const {
currentTicker,
fetchSuggestedNodes,
fetchTicker,
initLocale,
initCurrency,
initTheme,
isLoading,
isMounted,
setLoading,
setMounted,
theme
} = this.props
// If this is the first time the app has mounted, initialise things.
if (!isMounted) {
setMounted(true)
initTheme()
initLocale()
initCurrency()
fetchTicker()
fetchSuggestedNodes()
}
// Hide the loading screen after a set time.
if (isLoading || !currentTicker || !theme) {
const timer = setTimeout(() => setLoading(false), SPLASH_SCREEN_TIME)
this.setState({ timer })
}
}
/**
* Remove the timer when the component unmounts.
*/
componentWillUnmount() {
const { timer } = this.state
clearTimeout(timer)
}
render() {
const { clearError, theme, error, history, isLoading } = this.props
// Wait until we have loaded essential data before displaying anything..
if (!theme) {
return null
}
return (
<ConnectedRouter history={history}>
<ThemeProvider theme={theme}>
<React.Fragment>
<GlobalStyle />
<Titlebar />
<GlobalError error={error} clearError={clearError} />
<PageWithLoading isLoading={isLoading}>
<Switch>
<Route exact path="/" render={() => <Redirect to="/onboarding" />} />
<Route exact path="/onboarding" component={Onboarding} />
<Route exact path="/syncing" component={Syncing} />
<Route exact path="/app" component={App} />
</Switch>
</PageWithLoading>
</React.Fragment>
</ThemeProvider>
</ConnectedRouter>
)
}
}
const mapStateToProps = state => ({
currentTicker: tickerSelectors.currentTicker(state),
theme: themeSelectors.currentThemeSettings(state),
error: errorSelectors.getErrorState(state),
isLoading: loadingSelectors.isLoading(state),
isMounted: loadingSelectors.isMounted(state)
})
const mapDispatchToProps = {
clearError,
fetchSuggestedNodes,
fetchTicker,
initCurrency,
initLocale,
initTheme,
setLoading,
setMounted
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Root)