From 65f695c7aa899e5fa3afea36b9825c4d4fbe9d90 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 18 Sep 2024 13:40:34 +0200 Subject: [PATCH] Simple notifications on message --- src/App.tsx | 2 ++ src/components/Notifications.tsx | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/components/Notifications.tsx diff --git a/src/App.tsx b/src/App.tsx index 48a806f4..49d24745 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,7 @@ import { useAppStore } from "@core/stores/appStore.js"; import { useDeviceStore } from "@core/stores/deviceStore.js"; import { Dashboard } from "@pages/Dashboard/index.js"; import { MapProvider } from "react-map-gl"; +import { Notifications } from "./components/Notifications"; export const App = (): JSX.Element => { const { getDevice } = useDeviceStore(); @@ -39,6 +40,7 @@ export const App = (): JSX.Element => { + ) : ( <> diff --git a/src/components/Notifications.tsx b/src/components/Notifications.tsx new file mode 100644 index 00000000..0f7bfe24 --- /dev/null +++ b/src/components/Notifications.tsx @@ -0,0 +1,40 @@ +import { useDevice } from "@app/core/stores/deviceStore"; +import type { Types } from "@meshtastic/js"; +import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; +import { useCallback, useEffect } from "react"; + +export const Notifications = (): JSX.Element | null => { + const { nodes, connection, channels } = useDevice(); + let notificationPermission = Notification.permission; + + useEffect(() => { + if (!("Notification" in window)) { + console.log("This browser does not support notifications."); + notificationPermission = "denied"; + return; + } + Notification.requestPermission().then(() => notificationPermission); + connection?.events.onMessagePacket.subscribe(messageHandler); + return () => connection?.events.onMessagePacket.unsubscribe(messageHandler); + }, [notificationPermission, connection]); + + const messageHandler = useCallback( + (packet: Types.PacketMetadata) => { + if (notificationPermission !== "granted") return; + + const notificationBody = packet.data; + let notificationTitle = `New Message from ${nodes.get(packet.from)?.user?.longName ?? `!${numberToHexUnpadded(packet.from)}`}`; + + if (packet.type === "broadcast") { + notificationTitle = `New Message in ${channels.get(packet.channel)?.settings?.name ?? "Broadcast"}, from ${nodes.get(packet.from)?.user?.longName ?? `!${numberToHexUnpadded(packet.from)}`}`; + } + + new Notification(notificationTitle, { + body: notificationBody, + icon: "/favicon.ico", + }); + }, + [notificationPermission, nodes, channels], + ); + return null; +};