diff --git a/web/src/app/Notifier.js b/web/src/app/Notifier.js index 5db6f487..10bfc50d 100644 --- a/web/src/app/Notifier.js +++ b/web/src/app/Notifier.js @@ -22,7 +22,7 @@ class Notifier { if (notification.click) { n.onclick = (e) => openUrl(notification.click); } else { - n.onclick = onClickFallback; + n.onclick = () => onClickFallback(subscription); } // Play sound @@ -51,6 +51,9 @@ class Notifier { } async shouldNotify(subscription, notification) { + if (subscription.mutedUntil === 1) { + return false; + } const priority = (notification.priority) ? notification.priority : 3; const minPriority = await prefs.minPriority(); if (priority < minPriority) { diff --git a/web/src/app/SubscriptionManager.js b/web/src/app/SubscriptionManager.js index 4b608f41..253acf17 100644 --- a/web/src/app/SubscriptionManager.js +++ b/web/src/app/SubscriptionManager.js @@ -23,6 +23,7 @@ class SubscriptionManager { baseUrl: baseUrl, topic: topic, ephemeral: ephemeral, + mutedUntil: 0, last: null }; await db.subscriptions.put(subscription); @@ -108,6 +109,12 @@ class SubscriptionManager { .modify({new: 0}); } + async setMutedUntil(subscriptionId, mutedUntil) { + await db.subscriptions.update(subscriptionId, { + mutedUntil: mutedUntil + }); + } + async pruneNotifications(thresholdTimestamp) { await db.notifications .where("time").below(thresholdTimestamp) diff --git a/web/src/components/ActionBar.js b/web/src/components/ActionBar.js index a135a238..32b32d98 100644 --- a/web/src/components/ActionBar.js +++ b/web/src/components/ActionBar.js @@ -16,6 +16,8 @@ import Popper from '@mui/material/Popper'; import MenuItem from '@mui/material/MenuItem'; import MenuList from '@mui/material/MenuList'; import MoreVertIcon from "@mui/icons-material/MoreVert"; +import NotificationsIcon from '@mui/icons-material/Notifications'; +import NotificationsOffIcon from '@mui/icons-material/NotificationsOff'; import api from "../app/Api"; import subscriptionManager from "../app/SubscriptionManager"; @@ -50,25 +52,32 @@ const ActionBar = (props) => { {title} - {props.selected && } + {props.selected && + } ); }; // Originally from https://mui.com/components/menus/#MenuListComposition.js -const SettingsIcon = (props) => { +const SettingsIcons = (props) => { const navigate = useNavigate(); const [open, setOpen] = useState(false); const anchorRef = useRef(null); + const subscription = props.subscription; - const handleToggle = () => { + const handleToggleOpen = () => { setOpen((prevOpen) => !prevOpen); }; + const handleToggleMute = async () => { + const mutedUntil = (subscription.mutedUntil) ? 0 : 1; // Make this a timestamp in the future + await subscriptionManager.setMutedUntil(subscription.id, mutedUntil); + } + const handleClose = (event) => { if (anchorRef.current && anchorRef.current.contains(event.target)) { return; @@ -122,14 +131,10 @@ const SettingsIcon = (props) => { return ( <> - + + {subscription.mutedUntil ? : } + + { {({TransitionProps, placement}) => ( diff --git a/web/src/components/Navigation.js b/web/src/components/Navigation.js index c49e533d..0cb1de0b 100644 --- a/web/src/components/Navigation.js +++ b/web/src/components/Navigation.js @@ -18,11 +18,11 @@ import {subscriptionRoute, topicShortUrl, topicUrl} from "../app/utils"; import {ConnectionState} from "../app/Connection"; import {useLocation, useNavigate} from "react-router-dom"; import subscriptionManager from "../app/SubscriptionManager"; -import {ChatBubble} from "@mui/icons-material"; +import {ChatBubble, NotificationsOffOutlined} from "@mui/icons-material"; import Box from "@mui/material/Box"; import notifier from "../app/Notifier"; -const navWidth = 240; +const navWidth = 280; const Navigation = (props) => { const navigationList = ; @@ -159,6 +159,8 @@ const SubscriptionItem = (props) => { {icon} + {subscription.mutedUntil > 0 && + } ); };