feat(chat): added desktop notifications
Build and Push Docker image / build-and-push (push) Failing after 4m10s Details

This commit is contained in:
Valentin Kolb 2024-06-12 00:13:03 +02:00
parent 390edb38bd
commit d6df0b1d43
2 changed files with 56 additions and 17 deletions

BIN
public/stuve-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -2,37 +2,76 @@ import {ActionIcon, Indicator} from "@mantine/core";
import {Link, useMatch} from "react-router-dom";
import {IconMessageCircle} from "@tabler/icons-react";
import {usePB} from "@/lib/pocketbase.tsx";
import {useState} from "react";
import {useEffect, useState} from "react";
import {useTimeout} from "@mantine/hooks";
import {MessagesModel} from "@/models/MessageTypes.ts";
import {APP_NAME, APP_URL} from "../../../../config.ts";
/**
* Parse HTML string and return text content
* @param html - HTML string
*/
const parseHtmlString = (html: string): string => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
return doc.body.textContent || '';
}
const sendDesktopNotification = (body: string, url: string) => {
if ("Notification" in window && Notification.permission === 'granted') {
const notification = new Notification(APP_NAME, {
body: body,
icon: `${APP_URL}/stuve-logo.svg`,
vibrate: [200, 100, 200],
data: {url: url}
})
notification.onclick = () => {
window.focus()
window.open(notification.data.url);
}
}
}
export default function ChatNavIcon() {
const [newMessage, setNewMessage] = useState<string | null>(null);
const {start} = useTimeout(() => setNewMessage(null), 5000);
const [notificationUrl, setNotificationUrl] = useState<string | null>(null);
const {start} = useTimeout(() => setNotificationUrl(null), 5000);
const {user, useSubscription} = usePB()
const match = useMatch("/chat/:listId")
useEffect(() => {
// Request notification permission on component mount
if ("Notification" in window && Notification.permission !== 'granted') {
Notification.requestPermission().then(() => {
sendDesktopNotification(
"Willkommen bei StuVe! Du kannst jetzt Desktop Benachrichtigungen erhalten.",
`${APP_URL}/chat`
)
})
}
}, [])
useSubscription<MessagesModel>({
idOrName: "messages",
topic: "*",
callback: (event) => {
if (event.action == "create") {
if (event.record.isAnnouncement) {
start()
setNewMessage("announcements")
} else if (
event.record.eventList
&&
match?.params.listId !== event.record.eventList // check if chat page is not already open
&&
event.record.sender !== user?.id // check if sender is not the user
) {
start()
setNewMessage(event.record.eventList)
// check if chat page is not already open and if sender is not the user
if (match?.params.listId === event.record.eventList && event.record.sender === user?.id) {
return
}
const notificationUrl = `/chat/${event.record.isAnnouncement ? "announcements" : event.record.eventList}`
setNotificationUrl(notificationUrl)
start()
sendDesktopNotification(
parseHtmlString(event.record.content),
`${APP_URL}${notificationUrl}`
)
}
}
})
@ -42,12 +81,12 @@ export default function ChatNavIcon() {
}
return <>
<Indicator inline processing disabled={newMessage === null} classNames={{
<Indicator inline processing disabled={notificationUrl === null} classNames={{
root: "stack"
}}>
<ActionIcon
component={Link}
to={`/chat${newMessage ? `/${newMessage}` : ""}`}
to={notificationUrl ?? "/chat"}
variant={"transparent"}
color={"gray"}
>