aboutsummaryrefslogtreecommitdiff
path: root/modern
diff options
context:
space:
mode:
Diffstat (limited to 'modern')
-rw-r--r--modern/src/App.js4
-rw-r--r--modern/src/Navigation.js2
-rw-r--r--modern/src/index.js4
-rw-r--r--modern/src/login/LoginPage.js22
-rw-r--r--modern/src/other/ChangeServerPage.js66
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;