From 4828e3a6910d254b351d21038a0851dcebcf973b Mon Sep 17 00:00:00 2001 From: nimbleghost <132819643+nimbleghost@users.noreply.github.com> Date: Wed, 28 Jun 2023 17:39:40 +0200 Subject: [PATCH] Add preference --- web/public/static/langs/en.json | 4 ++++ web/src/app/Prefs.js | 15 +++++++++++++++ web/src/components/App.jsx | 21 +++++++++++++++++++-- web/src/components/Preferences.jsx | 24 +++++++++++++++++++++++- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/web/public/static/langs/en.json b/web/public/static/langs/en.json index 330d4dd1..fa0a3b0f 100644 --- a/web/public/static/langs/en.json +++ b/web/public/static/langs/en.json @@ -338,6 +338,10 @@ "prefs_notifications_web_push_disabled_description": "Notification are received when the web app is running (via WebSocket)", "prefs_notifications_web_push_enabled": "Enabled for {{server}}", "prefs_notifications_web_push_disabled": "Disabled", + "prefs_ui_mode_title": "UI Mode", + "prefs_ui_mode_system": "System (default)", + "prefs_ui_mode_dark": "Dark", + "prefs_ui_mode_light": "Light", "prefs_users_title": "Manage users", "prefs_users_description": "Add/remove users for your protected topics here. Please note that username and password are stored in the browser's local storage.", "prefs_users_description_no_sync": "Users and passwords are not synchronized to your account.", diff --git a/web/src/app/Prefs.js b/web/src/app/Prefs.js index a9510dd2..006e8bf5 100644 --- a/web/src/app/Prefs.js +++ b/web/src/app/Prefs.js @@ -1,5 +1,11 @@ import db from "./db"; +export const UI_MODE = { + DARK: "dark", + LIGHT: "light", + SYSTEM: "system", +}; + class Prefs { constructor(dbImpl) { this.db = dbImpl; @@ -40,6 +46,15 @@ class Prefs { async setWebPushEnabled(enabled) { await this.db.prefs.put({ key: "webPushEnabled", value: enabled }); } + + async uiMode() { + const uiMode = await this.db.prefs.get("uiMode"); + return uiMode?.value ?? UI_MODE.SYSTEM; + } + + async setUIMode(mode) { + await this.db.prefs.put({ key: "uiMode", value: mode }); + } } const prefs = new Prefs(db()); diff --git a/web/src/components/App.jsx b/web/src/components/App.jsx index 9c5e8f79..38343785 100644 --- a/web/src/components/App.jsx +++ b/web/src/components/App.jsx @@ -22,24 +22,41 @@ import Login from "./Login"; import Signup from "./Signup"; import Account from "./Account"; import "../app/i18n"; // Translations! +import prefs, { UI_MODE } from "../app/Prefs"; export const AccountContext = createContext(null); +const darkModeEnabled = (prefersDarkMode, uiModePreference) => { + switch (uiModePreference) { + case UI_MODE.DARK: + return true; + + case UI_MODE.LIGHT: + return false; + + case UI_MODE.SYSTEM: + default: + return prefersDarkMode; + } +}; + const App = () => { const [account, setAccount] = useState(null); const accountMemo = useMemo(() => ({ account, setAccount }), [account, setAccount]); const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)"); + const uiModePreference = useLiveQuery(() => prefs.uiMode()); + const theme = React.useMemo( () => createTheme({ ...themeOptions, palette: { - ...(prefersDarkMode ? darkPalette : lightPalette), + ...(darkModeEnabled(prefersDarkMode, uiModePreference) ? darkPalette : lightPalette), }, }), - [prefersDarkMode] + [prefersDarkMode, uiModePreference] ); return ( diff --git a/web/src/components/Preferences.jsx b/web/src/components/Preferences.jsx index 0911d69e..42b04b4d 100644 --- a/web/src/components/Preferences.jsx +++ b/web/src/components/Preferences.jsx @@ -43,7 +43,7 @@ import accountApi, { Permission, Role } from "../app/AccountApi"; import { Pref, PrefGroup } from "./Pref"; import { AccountContext } from "./App"; import { Paragraph } from "./styles"; -import prefs from "../app/Prefs"; +import prefs, { UI_MODE } from "../app/Prefs"; import { PermissionDenyAll, PermissionRead, PermissionReadWrite, PermissionWrite } from "./ReserveIcons"; import { ReserveAddDialog, ReserveDeleteDialog, ReserveEditDialog } from "./ReserveDialogs"; import { UnauthorizedError } from "../app/errors"; @@ -86,6 +86,7 @@ const Notifications = () => { {t("prefs_notifications_title")} + @@ -237,6 +238,27 @@ const DeleteAfter = () => { ); }; +const UIMode = () => { + const { t } = useTranslation(); + const labelId = "prefUIMode"; + const enabled = useLiveQuery(async () => prefs.uiMode()); + const handleChange = async (ev) => { + await prefs.setUIMode(ev.target.value); + }; + + return ( + + + + + + ); +}; + const WebPushEnabled = () => { const { t } = useTranslation(); const labelId = "prefWebPushEnabled";