Add preference

pull/790/head
nimbleghost 2023-06-28 17:39:40 +02:00
parent e607944ad1
commit 4828e3a691
4 changed files with 61 additions and 3 deletions

View File

@ -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_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_enabled": "Enabled for {{server}}",
"prefs_notifications_web_push_disabled": "Disabled", "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_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": "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.", "prefs_users_description_no_sync": "Users and passwords are not synchronized to your account.",

View File

@ -1,5 +1,11 @@
import db from "./db"; import db from "./db";
export const UI_MODE = {
DARK: "dark",
LIGHT: "light",
SYSTEM: "system",
};
class Prefs { class Prefs {
constructor(dbImpl) { constructor(dbImpl) {
this.db = dbImpl; this.db = dbImpl;
@ -40,6 +46,15 @@ class Prefs {
async setWebPushEnabled(enabled) { async setWebPushEnabled(enabled) {
await this.db.prefs.put({ key: "webPushEnabled", value: 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()); const prefs = new Prefs(db());

View File

@ -22,24 +22,41 @@ import Login from "./Login";
import Signup from "./Signup"; import Signup from "./Signup";
import Account from "./Account"; import Account from "./Account";
import "../app/i18n"; // Translations! import "../app/i18n"; // Translations!
import prefs, { UI_MODE } from "../app/Prefs";
export const AccountContext = createContext(null); 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 App = () => {
const [account, setAccount] = useState(null); const [account, setAccount] = useState(null);
const accountMemo = useMemo(() => ({ account, setAccount }), [account, setAccount]); const accountMemo = useMemo(() => ({ account, setAccount }), [account, setAccount]);
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)"); const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const uiModePreference = useLiveQuery(() => prefs.uiMode());
const theme = React.useMemo( const theme = React.useMemo(
() => () =>
createTheme({ createTheme({
...themeOptions, ...themeOptions,
palette: { palette: {
...(prefersDarkMode ? darkPalette : lightPalette), ...(darkModeEnabled(prefersDarkMode, uiModePreference) ? darkPalette : lightPalette),
}, },
}), }),
[prefersDarkMode] [prefersDarkMode, uiModePreference]
); );
return ( return (

View File

@ -43,7 +43,7 @@ import accountApi, { Permission, Role } from "../app/AccountApi";
import { Pref, PrefGroup } from "./Pref"; import { Pref, PrefGroup } from "./Pref";
import { AccountContext } from "./App"; import { AccountContext } from "./App";
import { Paragraph } from "./styles"; import { Paragraph } from "./styles";
import prefs from "../app/Prefs"; import prefs, { UI_MODE } from "../app/Prefs";
import { PermissionDenyAll, PermissionRead, PermissionReadWrite, PermissionWrite } from "./ReserveIcons"; import { PermissionDenyAll, PermissionRead, PermissionReadWrite, PermissionWrite } from "./ReserveIcons";
import { ReserveAddDialog, ReserveDeleteDialog, ReserveEditDialog } from "./ReserveDialogs"; import { ReserveAddDialog, ReserveDeleteDialog, ReserveEditDialog } from "./ReserveDialogs";
import { UnauthorizedError } from "../app/errors"; import { UnauthorizedError } from "../app/errors";
@ -86,6 +86,7 @@ const Notifications = () => {
{t("prefs_notifications_title")} {t("prefs_notifications_title")}
</Typography> </Typography>
<PrefGroup> <PrefGroup>
<UIMode />
<Sound /> <Sound />
<MinPriority /> <MinPriority />
<DeleteAfter /> <DeleteAfter />
@ -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 (
<Pref labelId={labelId} title={t("prefs_ui_mode_title")}>
<FormControl fullWidth variant="standard" sx={{ m: 1 }}>
<Select value={enabled ?? false} onChange={handleChange} aria-labelledby={labelId}>
<MenuItem value={UI_MODE.SYSTEM}>{t("prefs_ui_mode_system")}</MenuItem>
<MenuItem value={UI_MODE.DARK}>{t("prefs_ui_mode_dark")}</MenuItem>
<MenuItem value={UI_MODE.LIGHT}>{t("prefs_ui_mode_light")}</MenuItem>
</Select>
</FormControl>
</Pref>
);
};
const WebPushEnabled = () => { const WebPushEnabled = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const labelId = "prefWebPushEnabled"; const labelId = "prefWebPushEnabled";