Improve loading experience

This commit is contained in:
Anton Tananaev 2024-09-13 22:22:39 -07:00
parent 8b6ed6f5cd
commit aa06eaacc5
6 changed files with 35 additions and 9 deletions

View File

@ -10,10 +10,21 @@
<link rel="manifest" href="/manifest.webmanifest" />
<link rel="stylesheet" href="/styles.css">
<title>${title}</title>
<style>
.loader {
position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
width: 120px; height: 20px;
-webkit-mask: radial-gradient(circle closest-side,#000 94%,#0000) left/20% 100%;
background: linear-gradient(#000 0 0) left/0% 100% no-repeat #ddd;
animation: loader 2s infinite steps(6);
}
@keyframes loader { 100% {background-size:120% 100%} }
</style>
</head>
<body>
<noscript>Enable JavaScript to use <a href="https://www.traccar.org/">Traccar GPS Tracking System</a>.</noscript>
<div id="root" class="root"></div>
<script type="module" src="/src/index.jsx"></script>
<div class="loader"></div>
<script type="module" src="/src/index.jsx" onerror="alert('Loading error.')"></script>
</body>
</html>

View File

@ -1,7 +1,7 @@
import React from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { LinearProgress, useMediaQuery, useTheme } from '@mui/material';
import { useMediaQuery, useTheme } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import BottomMenu from './common/components/BottomMenu';
import SocketController from './SocketController';
@ -10,6 +10,7 @@ import { useCatch, useEffectAsync } from './reactHelper';
import { sessionActions } from './store';
import UpdateController from './UpdateController';
import TermsDialog from './common/components/TermsDialog';
import Loader from './common/components/Loader';
const useStyles = makeStyles(() => ({
page: {
@ -61,7 +62,7 @@ const App = () => {
}, [user]);
if (user == null) {
return (<LinearProgress />);
return (<Loader />);
}
if (termsUrl && !user.attributes.termsAccepted) {
return (<TermsDialog open onCancel={() => navigate('/login')} onAccept={() => acceptTerms()} />);

View File

@ -3,7 +3,6 @@ import {
Route, Routes, useLocation, useNavigate,
} from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { LinearProgress } from '@mui/material';
import MainPage from './main/MainPage';
import CombinedReportPage from './reports/CombinedReportPage';
import RouteReportPage from './reports/RouteReportPage';
@ -58,6 +57,7 @@ import LogsPage from './reports/LogsPage';
import SharePage from './settings/SharePage';
import AnnouncementPage from './settings/AnnouncementPage';
import EmulatorPage from './other/EmulatorPage';
import Loader from './common/components/Loader';
const Navigation = () => {
const navigate = useNavigate();
@ -94,7 +94,7 @@ const Navigation = () => {
}, [query]);
if (!redirectsHandled) {
return (<LinearProgress />);
return (<Loader />);
}
return (
<Routes>

View File

@ -1,9 +1,10 @@
import React, { useState } from 'react';
import { Alert, IconButton, LinearProgress } from '@mui/material';
import { Alert, IconButton } from '@mui/material';
import ReplayIcon from '@mui/icons-material/Replay';
import { useDispatch, useSelector } from 'react-redux';
import { useEffectAsync } from './reactHelper';
import { sessionActions } from './store';
import Loader from './common/components/Loader';
const ServerProvider = ({
children,
@ -43,7 +44,7 @@ const ServerProvider = ({
);
}
if (!initialized) {
return (<LinearProgress />);
return (<Loader />);
}
return children;
};

View File

@ -0,0 +1,12 @@
import { useEffect } from 'react';
const Loader = () => {
useEffect(() => {
const loader = document.querySelector('.loader');
loader.style.display = '';
return () => loader.style.display = 'none';
}, []);
return null;
};
export default Loader;

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import dayjs from 'dayjs';
import {
useMediaQuery, Select, MenuItem, FormControl, Button, TextField, Link, Snackbar, IconButton, Tooltip, LinearProgress, Box,
useMediaQuery, Select, MenuItem, FormControl, Button, TextField, Link, Snackbar, IconButton, Tooltip, Box,
} from '@mui/material';
import ReactCountryFlag from 'react-country-flag';
import makeStyles from '@mui/styles/makeStyles';
@ -17,6 +17,7 @@ import usePersistedState from '../common/util/usePersistedState';
import { handleLoginTokenListeners, nativeEnvironment, nativePostMessage } from '../common/components/NativeInterface';
import LogoImage from './LogoImage';
import { useCatch } from '../reactHelper';
import Loader from '../common/components/Loader';
const useStyles = makeStyles((theme) => ({
options: {
@ -143,7 +144,7 @@ const LoginPage = () => {
if (openIdForced) {
handleOpenIdLogin();
return (<LinearProgress />);
return (<Loader />);
}
return (