diff --git a/web/public/static/langs/zh_Hans.json b/web/public/static/langs/zh_Hans.json
index 098a72f6..60542465 100644
--- a/web/public/static/langs/zh_Hans.json
+++ b/web/public/static/langs/zh_Hans.json
@@ -352,5 +352,12 @@
"account_upgrade_dialog_tier_price_billed_monthly": "{{price}} 每年。按月计费。",
"account_upgrade_dialog_tier_price_billed_yearly": "{{价格}} 按年计费。节省 {{save}}。",
"account_upgrade_dialog_billing_contact_email": "有关账单问题,请直接联系我们 。",
- "account_upgrade_dialog_billing_contact_website": "有关账单问题,请参考我们的网站 。"
+ "account_upgrade_dialog_billing_contact_website": "有关账单问题,请参考我们的网站 。",
+ "publish_dialog_call_item": "拨打电话 {{number}}",
+ "publish_dialog_call_label": "拨号",
+ "publish_dialog_chip_call_label": "拨号",
+ "publish_dialog_chip_call_no_verified_numbers_tooltip": "未验证的手机号",
+ "account_basics_phone_numbers_title": "电话号码",
+ "account_basics_phone_numbers_description": "电话通知",
+ "account_basics_phone_numbers_dialog_description": "要使用来电通知功能,您需要添加并验证至少一个电话号码。可以通过短信或电话进行验证。"
}
diff --git a/web/src/components/ActionBar.jsx b/web/src/components/ActionBar.jsx
index 6a36cdb6..1f41aac0 100644
--- a/web/src/components/ActionBar.jsx
+++ b/web/src/components/ActionBar.jsx
@@ -19,11 +19,14 @@ import Navigation from "./Navigation";
import accountApi from "../app/AccountApi";
import PopupMenu from "./PopupMenu";
import { SubscriptionPopup } from "./SubscriptionPopup";
+import { useIsLaunchedPWA } from "./hooks";
const ActionBar = (props) => {
const theme = useTheme();
const { t } = useTranslation();
const location = useLocation();
+ const isLaunchedPWA = useIsLaunchedPWA();
+
let title = "ntfy";
if (props.selected) {
title = topicDisplayName(props.selected);
@@ -32,6 +35,22 @@ const ActionBar = (props) => {
} else if (location.pathname === routes.account) {
title = t("action_bar_account");
}
+
+ const getActionBarBackground = () => {
+ if (isLaunchedPWA) {
+ return "#317f6f";
+ }
+
+ switch (theme.palette.mode) {
+ case "dark":
+ return "linear-gradient(150deg, #203631 0%, #2a6e60 100%)";
+
+ case "light":
+ default:
+ return "linear-gradient(150deg, #338574 0%, #56bda8 100%)";
+ }
+ };
+
return (
{
{
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const themePreference = useLiveQuery(() => prefs.theme());
const theme = React.useMemo(
- () =>
- createTheme({
- ...themeOptions,
- palette: {
- ...(darkModeEnabled(prefersDarkMode, themePreference) ? darkPalette : lightPalette),
- },
- }),
+ () => createTheme(darkModeEnabled(prefersDarkMode, themePreference) ? darkTheme : lightTheme),
[prefersDarkMode, themePreference]
);
diff --git a/web/src/components/Navigation.jsx b/web/src/components/Navigation.jsx
index ad671d99..9025222e 100644
--- a/web/src/components/Navigation.jsx
+++ b/web/src/components/Navigation.jsx
@@ -18,6 +18,7 @@ import {
Box,
IconButton,
Button,
+ useTheme,
} from "@mui/material";
import * as React from "react";
import { useContext, useState } from "react";
@@ -83,6 +84,7 @@ const Navigation = (props) => {
Navigation.width = navWidth;
const NavList = (props) => {
+ const theme = useTheme();
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
@@ -126,7 +128,7 @@ const NavList = (props) => {
return (
<>
-
+
{showNotificationPermissionRequired && }
{showNotificationPermissionDenied && }
{showNotificationBrowserNotSupportedBox && }
@@ -186,7 +188,11 @@ const NavList = (props) => {
- {showUpgradeBanner && }
+ {showUpgradeBanner && (
+ // The text background gradient didn't seem to do well with switching between light/dark mode,
+ // So adding a `key` forces React to replace the entire component when the theme changes
+
+ )}
{
);
};
-const UpgradeBanner = () => {
+const UpgradeBanner = ({ mode }) => {
const { t } = useTranslation();
const [dialogKey, setDialogKey] = useState(0);
const [dialogOpen, setDialogOpen] = useState(false);
@@ -216,13 +222,16 @@ const UpgradeBanner = () => {
width: `${Navigation.width - 1}px`,
bottom: 0,
mt: "auto",
- background: "linear-gradient(150deg, rgba(196, 228, 221, 0.46) 0%, rgb(255, 255, 255) 100%)",
+ background:
+ mode === "light"
+ ? "linear-gradient(150deg, rgba(196, 228, 221, 0.46) 0%, rgb(255, 255, 255) 100%)"
+ : "linear-gradient(150deg, #203631 0%, #2a6e60 100%)",
}}
>
-
+
{
style: {
fontWeight: 500,
fontSize: "1.1rem",
- background: "-webkit-linear-gradient(45deg, #09009f, #00ff95 80%)",
+ background:
+ mode === "light"
+ ? "-webkit-linear-gradient(45deg, #09009f, #00ff95 80%)"
+ : "-webkit-linear-gradient(45deg,rgb(255, 255, 255), #00ff95 80%)",
WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent",
},
diff --git a/web/src/components/theme.js b/web/src/components/theme.js
index f789a0c5..64217eee 100644
--- a/web/src/components/theme.js
+++ b/web/src/components/theme.js
@@ -1,5 +1,5 @@
/** @type {import("@mui/material").ThemeOptions} */
-const themeOptions = {
+const baseThemeOptions = {
components: {
MuiListItemIcon: {
styleOverrides: {
@@ -22,37 +22,53 @@ const themeOptions = {
// https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/values/colors.xml
-/** @type {import("@mui/material").ThemeOptions['palette']} */
-export const lightPalette = {
- mode: "light",
- primary: {
- main: "#338574",
+/** @type {import("@mui/material").ThemeOptions} */
+export const lightTheme = {
+ ...baseThemeOptions,
+ components: {
+ ...baseThemeOptions.components,
},
- secondary: {
- main: "#6cead0",
+ palette: {
+ mode: "light",
+ primary: {
+ main: "#338574",
+ },
+ secondary: {
+ main: "#6cead0",
+ },
+ error: {
+ main: "#c30000",
+ },
},
- error: {
- main: "#c30000",
- },
- actionBarBackground: "linear-gradient(150deg, #338574 0%, #56bda8 100%)",
};
-/** @type {import("@mui/material").ThemeOptions['palette']} */
-export const darkPalette = {
- mode: "dark",
- background: {
- paper: "#1b2124",
+/** @type {import("@mui/material").ThemeOptions} */
+export const darkTheme = {
+ ...baseThemeOptions,
+ components: {
+ ...baseThemeOptions.components,
+ MuiSnackbarContent: {
+ styleOverrides: {
+ root: {
+ color: "#000",
+ backgroundColor: "#aeaeae",
+ },
+ },
+ },
},
- primary: {
- main: "#65b5a3",
+ palette: {
+ mode: "dark",
+ background: {
+ paper: "#1b2124",
+ },
+ primary: {
+ main: "#65b5a3",
+ },
+ secondary: {
+ main: "#6cead0",
+ },
+ error: {
+ main: "#fe4d2e",
+ },
},
- secondary: {
- main: "#6cead0",
- },
- error: {
- main: "#fe4d2e",
- },
- actionBarBackground: "linear-gradient(150deg, #203631 0%, #2a6e60 100%)",
};
-
-export default themeOptions;