Add notification count to dock icon on desktop

This commit is contained in:
Tom Moor
2023-05-20 18:01:55 -04:00
parent 965d85fb6f
commit 7e6831c803
5 changed files with 54 additions and 34 deletions

View File

@@ -0,0 +1,32 @@
import { observer } from "mobx-react";
import { SubscribeIcon } from "outline-icons";
import * as React from "react";
import styled, { useTheme } from "styled-components";
import { s } from "@shared/styles";
import useStores from "~/hooks/useStores";
import Relative from "../Sidebar/components/Relative";
const NotificationIcon = () => {
const { notifications } = useStores();
const theme = useTheme();
const count = notifications.approximateUnreadCount;
return (
<Relative style={{ height: 24 }}>
<SubscribeIcon color={theme.textTertiary} />
{count > 0 && <Badge />}
</Relative>
);
};
const Badge = styled.div`
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background: ${s("accent")};
top: 0;
right: 0;
`;
export default observer(NotificationIcon);

View File

@@ -10,6 +10,7 @@ import { markNotificationsAsRead } from "~/actions/definitions/notifications";
import useActionContext from "~/hooks/useActionContext";
import useStores from "~/hooks/useStores";
import { hover } from "~/styles";
import Desktop from "~/utils/Desktop";
import Empty from "../Empty";
import Flex from "../Flex";
import NudeButton from "../NudeButton";
@@ -36,6 +37,15 @@ function Notifications(
const { t } = useTranslation();
const isEmpty = notifications.orderedData.length === 0;
// Update the notification count in the dock icon, if possible.
React.useEffect(() => {
// Account for old versions of the desktop app that don't have the
// setNotificationCount method on the bridge.
if (Desktop.bridge && "setNotificationCount" in Desktop.bridge) {
Desktop.bridge.setNotificationCount(notifications.approximateUnreadCount);
}
}, [notifications.approximateUnreadCount]);
return (
<Flex style={{ width: "100%" }} column>
<Header justify="space-between">

View File

@@ -7,7 +7,7 @@ import { depths } from "@shared/styles";
import Popover from "~/components/Popover";
import Notifications from "./Notifications";
const NotificationsButton: React.FC = ({ children }) => {
const NotificationsPopover: React.FC = ({ children }) => {
const { t } = useTranslation();
const scrollableRef = React.useRef<HTMLDivElement>(null);
@@ -46,4 +46,4 @@ const StyledPopover = styled(Popover)`
z-index: ${depths.menu};
`;
export default observer(NotificationsButton);
export default observer(NotificationsPopover);

View File

@@ -1,5 +1,4 @@
import { observer } from "mobx-react";
import { SubscribeIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Portal } from "react-portal";
@@ -16,9 +15,9 @@ import { draggableOnDesktop, fadeOnDesktopBackgrounded } from "~/styles";
import { fadeIn } from "~/styles/animations";
import Desktop from "~/utils/Desktop";
import Avatar from "../Avatar";
import NotificationsButton from "../Notifications/NotificationsButton";
import NotificationIcon from "../Notifications/NotificationIcon";
import NotificationsPopover from "../Notifications/NotificationsPopover";
import HeaderButton, { HeaderButtonProps } from "./components/HeaderButton";
import Relative from "./components/Relative";
import ResizeBorder from "./components/ResizeBorder";
import Toggle, { ToggleButton, Positioner } from "./components/Toggle";
@@ -188,14 +187,11 @@ const Sidebar = React.forwardRef<HTMLDivElement, Props>(
/>
}
>
<NotificationsButton>
<NotificationsPopover>
{(rest: HeaderButtonProps) => (
<HeaderButton
{...rest}
image={<BadgedNotificationIcon />}
/>
<HeaderButton {...rest} image={<NotificationIcon />} />
)}
</NotificationsButton>
</NotificationsPopover>
</HeaderButton>
)}
</AccountMenu>
@@ -223,29 +219,6 @@ const Sidebar = React.forwardRef<HTMLDivElement, Props>(
}
);
const BadgedNotificationIcon = observer(() => {
const { notifications } = useStores();
const theme = useTheme();
const count = notifications.approximateUnreadCount;
return (
<Relative style={{ height: 24 }}>
<SubscribeIcon color={theme.textTertiary} />
{count > 0 && <Badge />}
</Relative>
);
});
const Badge = styled.div`
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
background: ${s("accent")};
top: 0;
right: 0;
`;
const StyledAvatar = styled(Avatar)`
margin-left: 4px;
`;

View File

@@ -56,6 +56,11 @@ declare global {
*/
setSpellCheckerLanguages: (languages: string[]) => Promise<void>;
/**
* Set the badge on the app icon.
*/
setNotificationCount: (count: number) => Promise<void>;
/**
* Registers a callback to be called when the window is focused.
*/