feat(chat): added desktop notifications
Build and Push Docker image / build-and-push (push) Failing after 4m10s
Details
Build and Push Docker image / build-and-push (push) Failing after 4m10s
Details
This commit is contained in:
parent
390edb38bd
commit
d6df0b1d43
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -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"}
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue