feat: Create 'Websocket' class for client side websockets

This commit is contained in:
April Hall 2025-02-06 17:12:16 -05:00
parent 42d50bf90d
commit 2c523c6940
Signed by: arithefirst
GPG Key ID: 4508A15C4DB91C5B
2 changed files with 65 additions and 42 deletions

View File

@ -0,0 +1,46 @@
import type { TypeMessage, TypeFullMessage } from '$lib';
import type { Socket } from 'socket.io-client';
class Websocket {
private socket: Socket;
public messages: TypeMessage[] = $state([]);
private channel: string = '';
constructor(socket: Socket) {
this.socket = socket;
}
connect() {
this.socket.on('message', (data: TypeFullMessage) => {
console.log('[ws] message received', data);
if (data.channel == this.channel) {
this.loadMessage(data);
}
});
}
// Change the current channel
updateChannel(newChannel: string) {
this.channel = newChannel;
this.messages = [];
}
// Add message to local messages array
loadMessage(newMsg: TypeMessage) {
this.messages = [
{
message: newMsg.message,
imageSrc: newMsg.imageSrc,
user: newMsg.user,
},
...this.messages,
];
}
// Send a message
sendMessage(user: string, msg: string) {
if (this.socket) this.socket.emit('message', { id: user, content: msg, channel: this.channel });
}
}
export default Websocket;

View File

@ -9,52 +9,24 @@
import Send from 'lucide-svelte/icons/send'; import Send from 'lucide-svelte/icons/send';
import Message from '$lib/components/message.svelte'; import Message from '$lib/components/message.svelte';
import { page } from '$app/state'; import { page } from '$app/state';
import Websocket from '$lib/clientWebsocket.svelte';
let { data }: { data: PageData } = $props(); const { data }: { data: PageData } = $props();
let user: string | undefined;
let socket: ReturnType<typeof io> | null = null; let user: string = uuidv4();
let log: TypeMessage[] = $state([]); let socket: Websocket | undefined = $state();
let msg: string = $state(''); let msg: string = $state('');
const channel = $derived(page.params.channel); const channel = $derived(page.params.channel);
function logEvent(newMsg: TypeMessage) { // Connect on page load
log = [
{
message: newMsg.message,
imageSrc: newMsg.imageSrc,
user: newMsg.user,
},
...log,
];
}
function establishSocketIOConnection() {
if (socket) return;
socket = io();
socket.on('message', (data: TypeFullMessage) => {
console.log('[ws] message received', data);
if (data.channel == channel) {
logEvent(data);
}
});
}
function sendMessage() {
if (!socket) return;
socket.emit('message', { id: user, content: msg, channel: channel });
msg = '';
}
// Clear the log whenever the channel changes
$effect(() => {
console.info(`Channel changed to ${channel}`);
log = [];
});
onMount(() => { onMount(() => {
establishSocketIOConnection(); socket = new Websocket(io());
user = uuidv4(); socket.connect();
});
// Update channel on page refresh
$effect(() => {
if (socket) socket.updateChannel(channel);
}); });
</script> </script>
@ -65,10 +37,15 @@
{/snippet} {/snippet}
<div class="flex flex-1 flex-col items-center justify-center rounded-lg shadow-sm gap-1 h-full"> <div class="flex flex-1 flex-col items-center justify-center rounded-lg shadow-sm gap-1 h-full">
<div class="flex-grow flex-col-reverse flex flex-auto overflow-y-scroll overflow-x-hidden rounded-lg border w-full"> <div class="flex-grow flex-col-reverse flex flex-auto overflow-y-scroll overflow-x-hidden rounded-lg border w-full">
{@render message(log)} {@render message(socket?.messages!)}
{@render message(data.messages)} {@render message(data.messages)}
</div> </div>
<form class="flex gap-1 w-full" onsubmit={sendMessage}> <form
class="flex gap-1 w-full"
onsubmit={() => {
socket?.sendMessage(user!, msg);
msg = '';
}}>
<Input type="text" placeholder="Type Here" bind:value={msg} /> <Input type="text" placeholder="Type Here" bind:value={msg} />
<Button class="h-9 w-14"><Send class="size-full" /></Button> <Button class="h-9 w-14"><Send class="size-full" /></Button>
</form> </form>