From 7e6831c803e863107a28768c5b6bb6cac7657cfa Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 20 May 2023 18:01:55 -0400 Subject: [PATCH] Add notification count to dock icon on desktop --- .../Notifications/NotificationIcon.tsx | 32 ++++++++++++++++ .../Notifications/Notifications.tsx | 10 +++++ ...onsButton.tsx => NotificationsPopover.tsx} | 4 +- app/components/Sidebar/Sidebar.tsx | 37 +++---------------- app/typings/window.d.ts | 5 +++ 5 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 app/components/Notifications/NotificationIcon.tsx rename app/components/Notifications/{NotificationsButton.tsx => NotificationsPopover.tsx} (92%) diff --git a/app/components/Notifications/NotificationIcon.tsx b/app/components/Notifications/NotificationIcon.tsx new file mode 100644 index 000000000..22ae3ce3e --- /dev/null +++ b/app/components/Notifications/NotificationIcon.tsx @@ -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 ( + + + {count > 0 && } + + ); +}; + +const Badge = styled.div` + position: absolute; + width: 8px; + height: 8px; + border-radius: 50%; + background: ${s("accent")}; + top: 0; + right: 0; +`; + +export default observer(NotificationIcon); diff --git a/app/components/Notifications/Notifications.tsx b/app/components/Notifications/Notifications.tsx index 3ba408f03..e234b0376 100644 --- a/app/components/Notifications/Notifications.tsx +++ b/app/components/Notifications/Notifications.tsx @@ -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 (
diff --git a/app/components/Notifications/NotificationsButton.tsx b/app/components/Notifications/NotificationsPopover.tsx similarity index 92% rename from app/components/Notifications/NotificationsButton.tsx rename to app/components/Notifications/NotificationsPopover.tsx index 0c3df2cb8..b1efd1078 100644 --- a/app/components/Notifications/NotificationsButton.tsx +++ b/app/components/Notifications/NotificationsPopover.tsx @@ -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(null); @@ -46,4 +46,4 @@ const StyledPopover = styled(Popover)` z-index: ${depths.menu}; `; -export default observer(NotificationsButton); +export default observer(NotificationsPopover); diff --git a/app/components/Sidebar/Sidebar.tsx b/app/components/Sidebar/Sidebar.tsx index 30ee71d58..aa72341b7 100644 --- a/app/components/Sidebar/Sidebar.tsx +++ b/app/components/Sidebar/Sidebar.tsx @@ -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( /> } > - + {(rest: HeaderButtonProps) => ( - } - /> + } /> )} - + )} @@ -223,29 +219,6 @@ const Sidebar = React.forwardRef( } ); -const BadgedNotificationIcon = observer(() => { - const { notifications } = useStores(); - const theme = useTheme(); - const count = notifications.approximateUnreadCount; - - return ( - - - {count > 0 && } - - ); -}); - -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; `; diff --git a/app/typings/window.d.ts b/app/typings/window.d.ts index 4fc66d294..f2b68bf46 100644 --- a/app/typings/window.d.ts +++ b/app/typings/window.d.ts @@ -56,6 +56,11 @@ declare global { */ setSpellCheckerLanguages: (languages: string[]) => Promise; + /** + * Set the badge on the app icon. + */ + setNotificationCount: (count: number) => Promise; + /** * Registers a callback to be called when the window is focused. */