diff options
-rw-r--r-- | modern/src/App.js | 4 | ||||
-rw-r--r-- | modern/src/Navigation.js | 2 | ||||
-rw-r--r-- | modern/src/index.js | 4 | ||||
-rw-r--r-- | modern/src/login/LoginPage.js | 22 | ||||
-rw-r--r-- | modern/src/other/ChangeServerPage.js | 66 |
5 files changed, 88 insertions, 10 deletions
diff --git a/modern/src/App.js b/modern/src/App.js index f6197d0a..aac6979e 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -5,6 +5,8 @@ import { LinearProgress, useMediaQuery } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import theme from './common/theme'; import BottomMenu from './common/components/BottomMenu'; +import SocketController from './SocketController'; +import CachingController from './CachingController'; const useStyles = makeStyles(() => ({ page: { @@ -28,6 +30,8 @@ const App = () => { } return ( <> + <SocketController /> + <CachingController /> <div className={classes.page}> <Outlet /> </div> diff --git a/modern/src/Navigation.js b/modern/src/Navigation.js index e7366d2b..d37ca72c 100644 --- a/modern/src/Navigation.js +++ b/modern/src/Navigation.js @@ -44,6 +44,7 @@ import PreferencesPage from './settings/PreferencesPage'; import AccumulatorsPage from './settings/AccumulatorsPage'; import CommandSendPage from './settings/CommandSendPage'; import App from './App'; +import ChangeServerPage from './other/ChangeServerPage'; const Navigation = () => { const navigate = useNavigate(); @@ -86,6 +87,7 @@ const Navigation = () => { <Route path="/login" element={<LoginPage />} /> <Route path="/register" element={<RegisterPage />} /> <Route path="/reset-password" element={<ResetPasswordPage />} /> + <Route path="/change-server" element={<ChangeServerPage />} /> <Route path="/" element={<App />}> <Route index element={<MainPage />} /> diff --git a/modern/src/index.js b/modern/src/index.js index dbcd4c07..6af059cf 100644 --- a/modern/src/index.js +++ b/modern/src/index.js @@ -7,8 +7,6 @@ import { CssBaseline, ThemeProvider, StyledEngineProvider } from '@mui/material' import store from './store'; import { LocalizationProvider } from './common/components/LocalizationProvider'; import ErrorHandler from './common/components/ErrorHandler'; -import CachingController from './CachingController'; -import SocketController from './SocketController'; import theme from './common/theme'; import Navigation from './Navigation'; import preloadImages from './map/core/preloadImages'; @@ -29,8 +27,6 @@ ReactDOM.render( <CssBaseline /> <ServerProvider> <BrowserRouter basename={base}> - <SocketController /> - <CachingController /> <Navigation /> </BrowserRouter> </ServerProvider> diff --git a/modern/src/login/LoginPage.js b/modern/src/login/LoginPage.js index 34d0e7d8..88a25d9d 100644 --- a/modern/src/login/LoginPage.js +++ b/modern/src/login/LoginPage.js @@ -5,6 +5,7 @@ import { import makeStyles from '@mui/styles/makeStyles'; import CloseIcon from '@mui/icons-material/Close'; import CachedIcon from '@mui/icons-material/Cached'; +import LockOpenIcon from '@mui/icons-material/LockOpen'; import { useTheme } from '@mui/material/styles'; import { useDispatch, useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; @@ -16,7 +17,7 @@ import logoSvg from '../resources/images/logo.svg'; import { nativePostMessage } from '../common/components/NativeInterface'; const useStyles = makeStyles((theme) => ({ - legacy: { + options: { position: 'fixed', top: theme.spacing(1), right: theme.spacing(1), @@ -93,11 +94,20 @@ const LoginPage = () => { return ( <LoginLayout> - <Tooltip title="Switch to Legacy App" className={classes.legacy}> - <IconButton onClick={() => window.localStorage.setItem('legacyApp', true) || window.location.replace('/')}> - <CachedIcon /> - </IconButton> - </Tooltip> + <div className={classes.options}> + <Tooltip title="Switch to Legacy App"> + <IconButton onClick={() => window.localStorage.setItem('legacyApp', true) || window.location.replace('/')}> + <CachedIcon /> + </IconButton> + </Tooltip> + {(window.appInterface || (window.webkit && window.webkit.messageHandlers.appInterface)) && ( + <Tooltip title={t('settingsServer')}> + <IconButton onClick={() => navigate('/change-server')}> + <LockOpenIcon /> + </IconButton> + </Tooltip> + )} + </div> <div className={classes.container}> {useMediaQuery(theme.breakpoints.down('lg')) && ( <div className={classes.logoContainer}> diff --git a/modern/src/other/ChangeServerPage.js b/modern/src/other/ChangeServerPage.js new file mode 100644 index 00000000..1862ecbd --- /dev/null +++ b/modern/src/other/ChangeServerPage.js @@ -0,0 +1,66 @@ +import React, { useState } from 'react'; +import ElectricalServicesIcon from '@mui/icons-material/ElectricalServices'; +import { makeStyles } from '@mui/styles'; +import { Autocomplete, Button, Container, TextField } from '@mui/material'; +import { useTranslation } from '../common/components/LocalizationProvider'; + +const currentServer = `${window.location.protocol}//${window.location.host}`; + +const officialServers = [ + currentServer, + 'https://demo.traccar.org', + 'https://demo2.traccar.org', + 'https://demo3.traccar.org', + 'https://demo4.traccar.org', + 'https://server.traccar.org', + 'http://localhost:8082', +]; + +const useStyles = makeStyles((theme) => ({ + icon: { + textAlign: 'center', + fontSize: '128px', + color: theme.palette.colors.neutral, + }, + container: { + textAlign: 'center', + padding: theme.spacing(5, 3), + }, + field: { + margin: theme.spacing(3, 0), + }, +})); + +const ChangeServerPage = () => { + const classes = useStyles(); + const t = useTranslation(); + + const [url, setUrl] = useState(currentServer); + + const handleSubmit = () => { + if (window.webkit && window.webkit.messageHandlers.appInterface) { + window.webkit.messageHandlers.appInterface.postMessage(`server|${url}`); + } else if (window.appInterface) { + window.appInterface.postMessage(`server|${url}`); + } else { + window.location.replace(url); + } + }; + + return ( + <Container maxWidth="xs" className={classes.container}> + <ElectricalServicesIcon className={classes.icon} /> + <Autocomplete + freeSolo + className={classes.field} + options={officialServers} + renderInput={(params) => <TextField {...params} label={t('settingsServer')} />} + value={url} + onChange={(_, value) => setUrl(value)} + /> + <Button variant="outlined" color="secondary" onClick={handleSubmit}>{t('sharedSave')}</Button> + </Container> + ); +}; + +export default ChangeServerPage; |