Merge branch 'main' into fix-permission-handling

pull/795/head
binwiederhier 2023-06-28 20:05:26 -04:00
commit 3f42e0e945
5 changed files with 92 additions and 44 deletions

View File

@ -352,5 +352,12 @@
"account_upgrade_dialog_tier_price_billed_monthly": "{{price}} 每年。按月计费。", "account_upgrade_dialog_tier_price_billed_monthly": "{{price}} 每年。按月计费。",
"account_upgrade_dialog_tier_price_billed_yearly": "{{价格}} 按年计费。节省 {{save}}。", "account_upgrade_dialog_tier_price_billed_yearly": "{{价格}} 按年计费。节省 {{save}}。",
"account_upgrade_dialog_billing_contact_email": "有关账单问题,请直接<Link>联系我们 </Link>。", "account_upgrade_dialog_billing_contact_email": "有关账单问题,请直接<Link>联系我们 </Link>。",
"account_upgrade_dialog_billing_contact_website": "有关账单问题,请参考我们的<Link>网站 </Link>。" "account_upgrade_dialog_billing_contact_website": "有关账单问题,请参考我们的<Link>网站 </Link>。",
"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": "要使用来电通知功能,您需要添加并验证至少一个电话号码。可以通过短信或电话进行验证。"
} }

View File

@ -19,11 +19,14 @@ import Navigation from "./Navigation";
import accountApi from "../app/AccountApi"; import accountApi from "../app/AccountApi";
import PopupMenu from "./PopupMenu"; import PopupMenu from "./PopupMenu";
import { SubscriptionPopup } from "./SubscriptionPopup"; import { SubscriptionPopup } from "./SubscriptionPopup";
import { useIsLaunchedPWA } from "./hooks";
const ActionBar = (props) => { const ActionBar = (props) => {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(); const { t } = useTranslation();
const location = useLocation(); const location = useLocation();
const isLaunchedPWA = useIsLaunchedPWA();
let title = "ntfy"; let title = "ntfy";
if (props.selected) { if (props.selected) {
title = topicDisplayName(props.selected); title = topicDisplayName(props.selected);
@ -32,6 +35,22 @@ const ActionBar = (props) => {
} else if (location.pathname === routes.account) { } else if (location.pathname === routes.account) {
title = t("action_bar_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 ( return (
<AppBar <AppBar
position="fixed" position="fixed"
@ -44,7 +63,7 @@ const ActionBar = (props) => {
<Toolbar <Toolbar
sx={{ sx={{
pr: "24px", pr: "24px",
background: theme.palette.actionBarBackground, background: getActionBarBackground(),
}} }}
> >
<IconButton <IconButton

View File

@ -5,7 +5,7 @@ import { ThemeProvider, createTheme } from "@mui/material/styles";
import { useLiveQuery } from "dexie-react-hooks"; import { useLiveQuery } from "dexie-react-hooks";
import { BrowserRouter, Outlet, Route, Routes, useParams } from "react-router-dom"; import { BrowserRouter, Outlet, Route, Routes, useParams } from "react-router-dom";
import { AllSubscriptions, SingleSubscription } from "./Notifications"; import { AllSubscriptions, SingleSubscription } from "./Notifications";
import themeOptions, { darkPalette, lightPalette } from "./theme"; import { darkTheme, lightTheme } from "./theme";
import Navigation from "./Navigation"; import Navigation from "./Navigation";
import ActionBar from "./ActionBar"; import ActionBar from "./ActionBar";
import Preferences from "./Preferences"; import Preferences from "./Preferences";
@ -45,13 +45,7 @@ const App = () => {
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)"); const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const themePreference = useLiveQuery(() => prefs.theme()); const themePreference = useLiveQuery(() => prefs.theme());
const theme = React.useMemo( const theme = React.useMemo(
() => () => createTheme(darkModeEnabled(prefersDarkMode, themePreference) ? darkTheme : lightTheme),
createTheme({
...themeOptions,
palette: {
...(darkModeEnabled(prefersDarkMode, themePreference) ? darkPalette : lightPalette),
},
}),
[prefersDarkMode, themePreference] [prefersDarkMode, themePreference]
); );

View File

@ -18,6 +18,7 @@ import {
Box, Box,
IconButton, IconButton,
Button, Button,
useTheme,
} from "@mui/material"; } from "@mui/material";
import * as React from "react"; import * as React from "react";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
@ -83,6 +84,7 @@ const Navigation = (props) => {
Navigation.width = navWidth; Navigation.width = navWidth;
const NavList = (props) => { const NavList = (props) => {
const theme = useTheme();
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
@ -126,7 +128,7 @@ const NavList = (props) => {
return ( return (
<> <>
<Toolbar sx={{ display: { xs: "none", sm: "block" } }} /> <Toolbar sx={{ display: { xs: "none", sm: "block" } }} />
<List component="nav" sx={{ paddingTop: alertVisible ? "0" : "" }}> <List component="nav" sx={{ paddingTop: { xs: 0, sm: alertVisible ? 0 : "" } }}>
{showNotificationPermissionRequired && <NotificationPermissionRequired />} {showNotificationPermissionRequired && <NotificationPermissionRequired />}
{showNotificationPermissionDenied && <NotificationPermissionDeniedAlert />} {showNotificationPermissionDenied && <NotificationPermissionDeniedAlert />}
{showNotificationBrowserNotSupportedBox && <NotificationBrowserNotSupportedAlert />} {showNotificationBrowserNotSupportedBox && <NotificationBrowserNotSupportedAlert />}
@ -186,7 +188,11 @@ const NavList = (props) => {
</ListItemIcon> </ListItemIcon>
<ListItemText primary={t("nav_button_subscribe")} /> <ListItemText primary={t("nav_button_subscribe")} />
</ListItemButton> </ListItemButton>
{showUpgradeBanner && <UpgradeBanner />} {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
<UpgradeBanner key={`upgrade-banner-${theme.palette.mode}`} mode={theme.palette.mode} />
)}
</List> </List>
<SubscribeDialog <SubscribeDialog
key={`subscribeDialog${subscribeDialogKey}`} // Resets dialog when canceled/closed key={`subscribeDialog${subscribeDialogKey}`} // Resets dialog when canceled/closed
@ -199,7 +205,7 @@ const NavList = (props) => {
); );
}; };
const UpgradeBanner = () => { const UpgradeBanner = ({ mode }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [dialogKey, setDialogKey] = useState(0); const [dialogKey, setDialogKey] = useState(0);
const [dialogOpen, setDialogOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false);
@ -216,13 +222,16 @@ const UpgradeBanner = () => {
width: `${Navigation.width - 1}px`, width: `${Navigation.width - 1}px`,
bottom: 0, bottom: 0,
mt: "auto", 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%)",
}} }}
> >
<Divider /> <Divider />
<ListItemButton onClick={handleClick} sx={{ pt: 2, pb: 2 }}> <ListItemButton onClick={handleClick} sx={{ pt: 2, pb: 2 }}>
<ListItemIcon> <ListItemIcon>
<CelebrationIcon sx={{ color: "#55b86e" }} fontSize="large" /> <CelebrationIcon sx={{ color: mode === "light" ? "#55b86e" : "#00ff95" }} fontSize="large" />
</ListItemIcon> </ListItemIcon>
<ListItemText <ListItemText
sx={{ ml: 1 }} sx={{ ml: 1 }}
@ -232,7 +241,10 @@ const UpgradeBanner = () => {
style: { style: {
fontWeight: 500, fontWeight: 500,
fontSize: "1.1rem", 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", WebkitBackgroundClip: "text",
WebkitTextFillColor: "transparent", WebkitTextFillColor: "transparent",
}, },

View File

@ -1,5 +1,5 @@
/** @type {import("@mui/material").ThemeOptions} */ /** @type {import("@mui/material").ThemeOptions} */
const themeOptions = { const baseThemeOptions = {
components: { components: {
MuiListItemIcon: { MuiListItemIcon: {
styleOverrides: { styleOverrides: {
@ -22,8 +22,13 @@ const themeOptions = {
// https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/values/colors.xml // https://github.com/binwiederhier/ntfy-android/blob/main/app/src/main/res/values/colors.xml
/** @type {import("@mui/material").ThemeOptions['palette']} */ /** @type {import("@mui/material").ThemeOptions} */
export const lightPalette = { export const lightTheme = {
...baseThemeOptions,
components: {
...baseThemeOptions.components,
},
palette: {
mode: "light", mode: "light",
primary: { primary: {
main: "#338574", main: "#338574",
@ -34,11 +39,24 @@ export const lightPalette = {
error: { error: {
main: "#c30000", main: "#c30000",
}, },
actionBarBackground: "linear-gradient(150deg, #338574 0%, #56bda8 100%)", },
}; };
/** @type {import("@mui/material").ThemeOptions['palette']} */ /** @type {import("@mui/material").ThemeOptions} */
export const darkPalette = { export const darkTheme = {
...baseThemeOptions,
components: {
...baseThemeOptions.components,
MuiSnackbarContent: {
styleOverrides: {
root: {
color: "#000",
backgroundColor: "#aeaeae",
},
},
},
},
palette: {
mode: "dark", mode: "dark",
background: { background: {
paper: "#1b2124", paper: "#1b2124",
@ -52,7 +70,5 @@ export const darkPalette = {
error: { error: {
main: "#fe4d2e", main: "#fe4d2e",
}, },
actionBarBackground: "linear-gradient(150deg, #203631 0%, #2a6e60 100%)", },
}; };
export default themeOptions;