aboutsummaryrefslogtreecommitdiff
path: root/modern/src
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2023-08-26 17:40:59 -0700
committerAnton Tananaev <anton@traccar.org>2023-08-26 17:40:59 -0700
commit778d626e5ca58f62b75ef070c5c347afa89a6de4 (patch)
treeafc2821805ddd65bfb24b65cbd60cc4239eee3c9 /modern/src
parente5d05451febf482f1192b2a4ba49b9275e236722 (diff)
downloadtrackermap-web-778d626e5ca58f62b75ef070c5c347afa89a6de4.tar.gz
trackermap-web-778d626e5ca58f62b75ef070c5c347afa89a6de4.tar.bz2
trackermap-web-778d626e5ca58f62b75ef070c5c347afa89a6de4.zip
Dark mode support (fix #1129)
Diffstat (limited to 'modern/src')
-rw-r--r--modern/src/common/attributes/useServerAttributes.js4
-rw-r--r--modern/src/common/components/StatusCard.jsx2
-rw-r--r--modern/src/common/theme/components.js8
-rw-r--r--modern/src/common/theme/palette.js17
-rw-r--r--modern/src/resources/l10n/en.json1
-rw-r--r--modern/src/settings/PreferencesPage.jsx84
6 files changed, 63 insertions, 53 deletions
diff --git a/modern/src/common/attributes/useServerAttributes.js b/modern/src/common/attributes/useServerAttributes.js
index 74749991..5cce479e 100644
--- a/modern/src/common/attributes/useServerAttributes.js
+++ b/modern/src/common/attributes/useServerAttributes.js
@@ -31,6 +31,10 @@ export default (t) => useMemo(() => ({
name: t('serverChangeDisable'),
type: 'boolean',
},
+ darkMode: {
+ name: t('settingsDarkMode'),
+ type: 'boolean',
+ },
'ui.disableLoginLanguage': {
name: t('attributeUiDisableLoginLanguage'),
type: 'boolean',
diff --git a/modern/src/common/components/StatusCard.jsx b/modern/src/common/components/StatusCard.jsx
index 0d32eb0d..c8898b7c 100644
--- a/modern/src/common/components/StatusCard.jsx
+++ b/modern/src/common/components/StatusCard.jsx
@@ -45,7 +45,7 @@ const useStyles = makeStyles((theme) => ({
alignItems: 'flex-start',
},
mediaButton: {
- color: theme.palette.colors.white,
+ color: theme.palette.primary.contrastText,
mixBlendMode: 'difference',
},
header: {
diff --git a/modern/src/common/theme/components.js b/modern/src/common/theme/components.js
index 572f876e..56a2ac75 100644
--- a/modern/src/common/theme/components.js
+++ b/modern/src/common/theme/components.js
@@ -1,5 +1,3 @@
-import { grey } from '@mui/material/colors';
-
export default {
MuiUseMediaQuery: {
defaultProps: {
@@ -8,9 +6,9 @@ export default {
},
MuiOutlinedInput: {
styleOverrides: {
- root: {
- backgroundColor: grey[50],
- },
+ root: ({ theme }) => ({
+ backgroundColor: theme.palette.background.default,
+ }),
},
},
MuiButton: {
diff --git a/modern/src/common/theme/palette.js b/modern/src/common/theme/palette.js
index 51a01c69..99288aee 100644
--- a/modern/src/common/theme/palette.js
+++ b/modern/src/common/theme/palette.js
@@ -1,15 +1,18 @@
+import { useMediaQuery } from '@mui/material';
import {
- amber, grey, green, indigo, red, common,
+ amber, grey, green, indigo, red,
} from '@mui/material/colors';
const validatedColor = (color) => (/^#([0-9A-Fa-f]{3}){1,2}$/.test(color) ? color : null);
export default (server) => {
+ const preferDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
+ const serverDarkMode = server?.attributes?.darkMode;
+ const darkMode = serverDarkMode !== undefined ? serverDarkMode : preferDarkMode;
+
const colors = {
- white: common.white,
- background: grey[50],
- primary: validatedColor(server?.attributes?.colorPrimary) || indigo[900],
- secondary: validatedColor(server?.attributes?.colorSecondary) || green[800],
+ primary: validatedColor(server?.attributes?.colorPrimary) || (darkMode ? indigo[200] : indigo[900]),
+ secondary: validatedColor(server?.attributes?.colorSecondary) || (darkMode ? green[200] : green[800]),
positive: green[500],
medium: amber[700],
negative: red[500],
@@ -18,15 +21,15 @@ export default (server) => {
};
return {
+ mode: darkMode ? 'dark' : 'light',
background: {
- default: colors.background,
+ default: darkMode ? grey[900] : grey[50],
},
primary: {
main: colors.primary,
},
secondary: {
main: colors.secondary,
- contrastText: colors.white,
},
colors,
};
diff --git a/modern/src/resources/l10n/en.json b/modern/src/resources/l10n/en.json
index dcfea816..7933abd8 100644
--- a/modern/src/resources/l10n/en.json
+++ b/modern/src/resources/l10n/en.json
@@ -221,6 +221,7 @@
"settingsServerVersion": "Server Version",
"settingsAppVersion": "App Version",
"settingsConnection": "Connection",
+ "settingsDarkMode": "Dark Mode",
"reportTitle": "Reports",
"reportScheduled": "Scheduled Reports",
"reportDevice": "Device",
diff --git a/modern/src/settings/PreferencesPage.jsx b/modern/src/settings/PreferencesPage.jsx
index b83e7095..15fd762a 100644
--- a/modern/src/settings/PreferencesPage.jsx
+++ b/modern/src/settings/PreferencesPage.jsx
@@ -114,48 +114,9 @@ const PreferencesPage = () => {
return (
<PageLayout menu={<SettingsMenu />} breadcrumbs={['settingsTitle', 'sharedPreferences']}>
<Container maxWidth="xs" className={classes.container}>
- <Accordion defaultExpanded>
- <AccordionSummary expandIcon={<ExpandMoreIcon />}>
- <Typography variant="subtitle1">
- {t('userToken')}
- </Typography>
- </AccordionSummary>
- <AccordionDetails className={classes.details}>
- <TextField
- label={t('userExpirationTime')}
- type="date"
- value={tokenExpiration}
- onChange={(e) => {
- setTokenExpiration(e.target.value);
- setToken(null);
- }}
- />
- <FormControl>
- <OutlinedInput
- multiline
- rows={6}
- readOnly
- type="text"
- value={token || ''}
- endAdornment={(
- <InputAdornment position="end">
- <div className={classes.tokenActions}>
- <IconButton size="small" edge="end" onClick={generateToken} disabled={!!token}>
- <CachedIcon fontSize="small" />
- </IconButton>
- <IconButton size="small" edge="end" onClick={() => navigator.clipboard.writeText(token)} disabled={!token}>
- <ContentCopyIcon fontSize="small" />
- </IconButton>
- </div>
- </InputAdornment>
- )}
- />
- </FormControl>
- </AccordionDetails>
- </Accordion>
{!readonly && (
<>
- <Accordion>
+ <Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">
{t('mapTitle')}
@@ -346,6 +307,49 @@ const PreferencesPage = () => {
/>
</AccordionDetails>
</Accordion>
+ </>
+ )}
+ <Accordion>
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography variant="subtitle1">
+ {t('userToken')}
+ </Typography>
+ </AccordionSummary>
+ <AccordionDetails className={classes.details}>
+ <TextField
+ label={t('userExpirationTime')}
+ type="date"
+ value={tokenExpiration}
+ onChange={(e) => {
+ setTokenExpiration(e.target.value);
+ setToken(null);
+ }}
+ />
+ <FormControl>
+ <OutlinedInput
+ multiline
+ rows={6}
+ readOnly
+ type="text"
+ value={token || ''}
+ endAdornment={(
+ <InputAdornment position="end">
+ <div className={classes.tokenActions}>
+ <IconButton size="small" edge="end" onClick={generateToken} disabled={!!token}>
+ <CachedIcon fontSize="small" />
+ </IconButton>
+ <IconButton size="small" edge="end" onClick={() => navigator.clipboard.writeText(token)} disabled={!token}>
+ <ContentCopyIcon fontSize="small" />
+ </IconButton>
+ </div>
+ </InputAdornment>
+ )}
+ />
+ </FormControl>
+ </AccordionDetails>
+ </Accordion>
+ {!readonly && (
+ <>
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">