From 64ac111d55383c4d73adcf8cd2a52e2d5e4df625 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Wed, 28 Jun 2023 13:30:51 -0400 Subject: [PATCH] Rename UI_MODE to THEME --- docs/releases.md | 15 +++++++++++---- web/public/static/langs/en.json | 8 ++++---- web/src/app/Prefs.js | 12 ++++++------ web/src/components/App.jsx | 21 +++++++++------------ web/src/components/Preferences.jsx | 20 ++++++++++---------- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index cd7e37da..475b03fd 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -7,15 +7,22 @@ Released June 28, 2023 With this release, the ntfy web app now contains a **[progressive web app](https://docs.ntfy.sh/subscribe/pwa/) (PWA) with Web Push support**, which means you'll be able to **install the ntfy web app on your desktop or phone** similar -to a native app (__even on iOS!__ 🥳), and get basic push notification support (without any battery drain). +to a native app (__even on iOS!__ 🥳). Installing the PWA gives ntfy web its own launcher, a standalone window, +push notifications, and an app badge with the unread notification count. -Installing the PWA gives ntfy web its own launcher (e.g. shortcut on Windows, app on macOS, launcher shortcut on Linux, -home screen icon on iOS, and launcher icon on Android), a standalone window, push notifications, and an app badge with -the unread notification count. +On top of that, this release also brings **dark mode** 🧛🌙 to the web app. + +🙏 A huge thanks for this release goes to [@nimbleghost](https://github.com/nimbleghost), for basically implementing the +Web Push / PWA and dark mode feature by himself. I'm really grateful for your contributions. + +❤️ If you like ntfy, **please consider sponsoring us** via [GitHub Sponsors](https://github.com/sponsors/binwiederhier) +and [Liberapay](https://en.liberapay.com/ntfy/), or buying a [paid plan via the web app](https://ntfy.sh/app) (20% off +if you use promo code `MYTOPIC`). ntfy will always remain open source. **Features:** * The web app now supports Web Push, and is installable as a [progressive web app (PWA)](https://docs.ntfy.sh/subscribe/pwa/) on Chrome, Edge, Android, and iOS ([#751](https://github.com/binwiederhier/ntfy/pull/751), thanks to [@nimbleghost](https://github.com/nimbleghost)) +* Support for dark mode in the web app ([#206](https://github.com/binwiederhier/ntfy/issues/206), thanks to [@nimbleghost](https://github.com/nimbleghost)) **Bug fixes:** diff --git a/web/public/static/langs/en.json b/web/public/static/langs/en.json index fa0a3b0f..0b74c6e2 100644 --- a/web/public/static/langs/en.json +++ b/web/public/static/langs/en.json @@ -338,10 +338,6 @@ "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.", @@ -359,6 +355,10 @@ "prefs_users_dialog_password_label": "Password", "prefs_appearance_title": "Appearance", "prefs_appearance_language_title": "Language", + "prefs_appearance_theme_title": "Theme", + "prefs_appearance_theme_system": "System (default)", + "prefs_appearance_theme_dark": "Dark mode", + "prefs_appearance_theme_light": "Light mode", "prefs_reservations_title": "Reserved topics", "prefs_reservations_description": "You can reserve topic names for personal use here. Reserving a topic gives you ownership over the topic, and allows you to define access permissions for other users over the topic.", "prefs_reservations_limit_reached": "You reached your reserved topics limit.", diff --git a/web/src/app/Prefs.js b/web/src/app/Prefs.js index 006e8bf5..4f28f87e 100644 --- a/web/src/app/Prefs.js +++ b/web/src/app/Prefs.js @@ -1,6 +1,6 @@ import db from "./db"; -export const UI_MODE = { +export const THEME = { DARK: "dark", LIGHT: "light", SYSTEM: "system", @@ -47,13 +47,13 @@ class Prefs { 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 theme() { + const theme = await this.db.prefs.get("theme"); + return theme?.value ?? THEME.SYSTEM; } - async setUIMode(mode) { - await this.db.prefs.put({ key: "uiMode", value: mode }); + async setTheme(mode) { + await this.db.prefs.put({ key: "theme", value: mode }); } } diff --git a/web/src/components/App.jsx b/web/src/components/App.jsx index 38343785..6c4761f1 100644 --- a/web/src/components/App.jsx +++ b/web/src/components/App.jsx @@ -22,19 +22,19 @@ import Login from "./Login"; import Signup from "./Signup"; import Account from "./Account"; import "../app/i18n"; // Translations! -import prefs, { UI_MODE } from "../app/Prefs"; +import prefs, { THEME } from "../app/Prefs"; export const AccountContext = createContext(null); -const darkModeEnabled = (prefersDarkMode, uiModePreference) => { - switch (uiModePreference) { - case UI_MODE.DARK: +const darkModeEnabled = (prefersDarkMode, themePreference) => { + switch (themePreference) { + case THEME.DARK: return true; - case UI_MODE.LIGHT: + case THEME.LIGHT: return false; - case UI_MODE.SYSTEM: + case THEME.SYSTEM: default: return prefersDarkMode; } @@ -43,20 +43,17 @@ const darkModeEnabled = (prefersDarkMode, uiModePreference) => { 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 themePreference = useLiveQuery(() => prefs.theme()); const theme = React.useMemo( () => createTheme({ ...themeOptions, palette: { - ...(darkModeEnabled(prefersDarkMode, uiModePreference) ? darkPalette : lightPalette), + ...(darkModeEnabled(prefersDarkMode, themePreference) ? darkPalette : lightPalette), }, }), - [prefersDarkMode, uiModePreference] + [prefersDarkMode, themePreference] ); return ( diff --git a/web/src/components/Preferences.jsx b/web/src/components/Preferences.jsx index 42b04b4d..add9b8c0 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, { UI_MODE } from "../app/Prefs"; +import prefs, { THEME } from "../app/Prefs"; import { PermissionDenyAll, PermissionRead, PermissionReadWrite, PermissionWrite } from "./ReserveIcons"; import { ReserveAddDialog, ReserveDeleteDialog, ReserveEditDialog } from "./ReserveDialogs"; import { UnauthorizedError } from "../app/errors"; @@ -86,7 +86,6 @@ const Notifications = () => { {t("prefs_notifications_title")} - @@ -238,21 +237,21 @@ const DeleteAfter = () => { ); }; -const UIMode = () => { +const Theme = () => { const { t } = useTranslation(); - const labelId = "prefUIMode"; - const enabled = useLiveQuery(async () => prefs.uiMode()); + const labelId = "prefTheme"; + const enabled = useLiveQuery(async () => prefs.theme()); const handleChange = async (ev) => { - await prefs.setUIMode(ev.target.value); + await prefs.setTheme(ev.target.value); }; return ( - + @@ -511,6 +510,7 @@ const Appearance = () => { {t("prefs_appearance_title")} +