aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/containers/Page/DynoWaiter.tsx64
-rw-r--r--src/containers/Page/Page.tsx30
-rw-r--r--src/containers/Page/Router.tsx27
3 files changed, 100 insertions, 21 deletions
diff --git a/src/containers/Page/DynoWaiter.tsx b/src/containers/Page/DynoWaiter.tsx
new file mode 100644
index 0000000..d8460bf
--- /dev/null
+++ b/src/containers/Page/DynoWaiter.tsx
@@ -0,0 +1,64 @@
+import React, { useEffect, useState, useCallback, useMemo } from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import { get } from '../../requests';
+import Loading from '../../components/Loading/Loading';
+
+const DYNO_WAKEUP_TIME = 30;
+
+const messages = [
+ '',
+ 'It looks like our server is sleeping.',
+ `We need about ${DYNO_WAKEUP_TIME} seconds to wake it up.`,
+ 'Please, stay with us.',
+ 'You are doing good.',
+ 'Almost done.'
+];
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ textAlign: 'center'
+ },
+ hidden: {
+ visibility: 'hidden',
+ position: 'absolute'
+ }
+}));
+
+const DynoWaiter: React.FC = ({ children }) => {
+ const classes = useStyles();
+ const [isReady, setIsReady] = useState<boolean>(false);
+ const [time, setTime] = useState<number>(0);
+
+ const tick = useCallback((): void => setTime(value => value + 1), [setTime]);
+
+ useEffect(() => {
+ const interval = setInterval(tick, 1000);
+ get('/ping').then(() => {
+ setIsReady(true);
+ clearInterval(interval);
+ });
+ return () => clearInterval(interval);
+ }, [setIsReady, tick]);
+
+ const message = useMemo(() => {
+ const interval = DYNO_WAKEUP_TIME / messages.length;
+ const index = Math.floor(time / interval);
+ const lastIndex = messages.length - 1;
+ return messages[index > lastIndex ? lastIndex : index];
+ }, [time]);
+
+ const tagline = useMemo(() => time > 3 ? 'Waiting for the server' : '', [time]);
+
+ return (
+ <>
+ {!isReady && <Loading tagline={tagline} message={message} />}
+ <div className={isReady ? '' : classes.hidden}>
+ {children}
+ </div>
+ </>
+ );
+};
+
+
+export default DynoWaiter;
+
diff --git a/src/containers/Page/Page.tsx b/src/containers/Page/Page.tsx
index 023d86e..475f76d 100644
--- a/src/containers/Page/Page.tsx
+++ b/src/containers/Page/Page.tsx
@@ -2,30 +2,24 @@ import React, { Suspense, useEffect } from 'react';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import { useMediaQuery } from '@material-ui/core';
import { SnackbarProvider } from 'notistack';
-import { Switch, Route, useHistory } from 'react-router-dom';
-import Loading from '../../components/Loading/Loading';
+import { useHistory } from 'react-router-dom';
-const Profile = React.lazy(() => import('../Profile/Profile'));
-const Feed = React.lazy(() => import('../Feed/Feed'));
-const Login = React.lazy(() => import('../Login/Login'));
-const Registration = React.lazy(() => import('../Registration/Registration'));
-const Home = React.lazy(() => import('../Home/Home'));
-const Notifications = React.lazy(() => import('../Notifications/Notifications'));
-const PollCreation = React.lazy(() => import('../PollCreation/PollCreation'));
+import Router from './Router';
+import DynoWaiter from './DynoWaiter';
+import Loading from '../../components/Loading/Loading';
const useStyles = makeStyles(theme => ({
root: {
[theme.breakpoints.down('sm')]: {
- margin: theme.spacing(10, 0, 12, 0)
+ padding: theme.spacing(10, 0, 12, 0)
},
[theme.breakpoints.up('md')]: {
- margin: theme.spacing(15, 5, 8, 5)
+ padding: theme.spacing(15, 5, 8, 5)
}
}
}));
-
const Page: React.FC = () => {
const classes = useStyles();
const theme = useTheme();
@@ -49,15 +43,9 @@ const Page: React.FC = () => {
>
<div className={classes.root}>
<Suspense fallback={<Loading />}>
- <Switch>
- <Route exact path="/" component={Home} />
- <Route exact path="/login" component={Login} />
- <Route exact path="/registration" component={Registration} />
- <Route exact path="/feed" component={Feed} />
- <Route exact path="/notifications" component={Notifications} />
- <Route exact path="/new" component={PollCreation} />
- <Route path="/profile/:username" component={Profile} />
- </Switch>
+ <DynoWaiter>
+ <Router />
+ </DynoWaiter>
</Suspense>
</div>
</SnackbarProvider>
diff --git a/src/containers/Page/Router.tsx b/src/containers/Page/Router.tsx
new file mode 100644
index 0000000..7067eea
--- /dev/null
+++ b/src/containers/Page/Router.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import { Switch, Route } from 'react-router-dom';
+
+const Profile = React.lazy(() => import('../Profile/Profile'));
+const Feed = React.lazy(() => import('../Feed/Feed'));
+const Login = React.lazy(() => import('../Login/Login'));
+const Registration = React.lazy(() => import('../Registration/Registration'));
+const Home = React.lazy(() => import('../Home/Home'));
+const Notifications = React.lazy(() => import('../Notifications/Notifications'));
+const PollCreation = React.lazy(() => import('../PollCreation/PollCreation'));
+
+
+const Router: React.FC = React.memo(() => (
+ <Switch>
+ <Route exact path="/" component={Home} />
+ <Route exact path="/login" component={Login} />
+ <Route exact path="/registration" component={Registration} />
+ <Route exact path="/feed" component={Feed} />
+ <Route exact path="/notifications" component={Notifications} />
+ <Route exact path="/new" component={PollCreation} />
+ <Route path="/profile/:username" component={Profile} />
+ </Switch>
+));
+
+
+export default Router;
+