diff --git a/TODO.md b/TODO.md index b6b309b..ffc8397 100644 --- a/TODO.md +++ b/TODO.md @@ -11,7 +11,7 @@ A more complex version of this list is available [here](https://trello.com/b/kJw - [ ] Images/Attatchments support - [x] Installation documentation - [ ] LaTeX support -- [ ] Notifications +- [x] Notifications - [x] Make the damn textbox stop unfocusing on every message submit - [ ] Message context menus - [ ] Message Timestamps diff --git a/src/lib/functions/clientWebsocket.svelte.ts b/src/lib/functions/clientWebsocket.svelte.ts index b24fa2a..e32330e 100644 --- a/src/lib/functions/clientWebsocket.svelte.ts +++ b/src/lib/functions/clientWebsocket.svelte.ts @@ -3,11 +3,13 @@ import type { Socket } from 'socket.io-client'; class Websocket { private socket: Socket; + private me: string; public messages: TypeMessage[] = $state([]); private channel: string = ''; - constructor(socket: Socket) { + constructor(socket: Socket, user: string) { this.socket = socket; + this.me = user; } connect() { @@ -26,7 +28,7 @@ class Websocket { } // Add message to local messages array - loadMessage(newMsg: TypeMessage) { + private loadMessage(newMsg: TypeMessage) { this.messages = [ { message: newMsg.message, @@ -35,6 +37,16 @@ class Websocket { }, ...this.messages, ]; + + // Sends a notif if the window is unfocused and + // the sender is not the current user + if (this.me !== newMsg.user && !document.hasFocus()) { + new Notification(`Message in #${this.channel}`, { + body: `${newMsg.user}: ${newMsg.message}`, + icon: newMsg.imageSrc, + tag: `message-in-channel-${this.channel}`, + }); + } } // Send a message diff --git a/src/routes/(main)/channel/[channel]/+page.server.ts b/src/routes/(main)/channel/[channel]/+page.server.ts index 833a515..dc7a5a7 100644 --- a/src/routes/(main)/channel/[channel]/+page.server.ts +++ b/src/routes/(main)/channel/[channel]/+page.server.ts @@ -4,7 +4,13 @@ import type { TypeMessage } from '$lib/types'; import { error, redirect } from '@sveltejs/kit'; import { auth } from '$lib/server/db/auth'; -export async function load({ params, request }): Promise<{ messages: TypeMessage[]; currentUser: string }> { +interface ChannelLoad { + messages: TypeMessage[]; + currentUserID: string; + currentUserName: string; +} + +export async function load({ params, request }): Promise { const session = await auth.api.getSession({ headers: request.headers, }); @@ -34,6 +40,7 @@ export async function load({ params, request }): Promise<{ messages: TypeMessage return { messages: messages ?? [], - currentUser: session.user.id!, + currentUserID: session.user.id!, + currentUserName: session.user.username!, }; } diff --git a/src/routes/(main)/channel/[channel]/+page.svelte b/src/routes/(main)/channel/[channel]/+page.svelte index b1bf92a..f9b5031 100644 --- a/src/routes/(main)/channel/[channel]/+page.svelte +++ b/src/routes/(main)/channel/[channel]/+page.svelte @@ -21,10 +21,20 @@ let textareaRef: HTMLTextAreaElement | undefined = $state(); let formref: HTMLFormElement | undefined = $state(); + function askNotificationPermission() { + // Check if the browser supports notifications + if (!('Notification' in window)) { + alert('This browser does not support notifications.'); + return; + } + + Notification.requestPermission(); + } + function submit(event: Event) { event.preventDefault(); if (msg.length <= 2000) { - socket?.sendMessage(data.currentUser, msg); + socket?.sendMessage(data.currentUserID, msg); if (textareaRef) textareaRef.style.height = '40px'; msg = ''; } else { @@ -34,9 +44,12 @@ onMount(() => { // Connect on page load - socket = new Websocket(io()); + socket = new Websocket(io(), data.currentUserName); socket.connect(); + // Ask for notification permissions + askNotificationPermission(); + // Submit on textarea enter textareaRef?.addEventListener('keypress', (e) => { if (e.key === 'Enter' && !e.shiftKey) {