Add notification count to dock icon on desktop
This commit is contained in:
32
app/components/Notifications/NotificationIcon.tsx
Normal file
32
app/components/Notifications/NotificationIcon.tsx
Normal 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);
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
`;
|
||||
|
||||
5
app/typings/window.d.ts
vendored
5
app/typings/window.d.ts
vendored
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user