feat: Add support for mutiple channels

This commit is contained in:
April Hall 2025-02-06 13:50:46 -05:00
parent edfd65335c
commit 39bb7418c9
No known key found for this signature in database
GPG Key ID: A49AC35CB186266C
5 changed files with 102 additions and 79 deletions

View File

@ -1,5 +1,10 @@
import cassandra from 'cassandra-driver';
interface Messages {
messages: cassandra.types.Row[] | null;
error: Error | null;
}
class Db {
private client: cassandra.Client;
@ -47,15 +52,21 @@ class Db {
}
// Get messages method
async getMessages(channelName: string, limit: number): Promise<cassandra.types.Row[] | undefined> {
async getMessages(channelName: string, limit: number): Promise<Messages> {
try {
const res = await this.client.execute(
`SELECT * FROM channels.${channelName} WHERE channel_name = '${channelName}' ORDER BY timestamp DESC LIMIT ${limit}`,
);
return res.rows;
return {
messages: res.rows,
error: null,
};
} catch (e) {
console.log(`Error fetching messages: ${(e as Error).message}`);
return;
return {
messages: null,
error: e as Error,
};
}
}
}
@ -85,4 +96,4 @@ try {
const db = new Db(client);
await db.createChannel('general');
export { db };
export { db, type Messages };

View File

@ -1,19 +1,5 @@
import type { TypeMessage } from '$lib';
import { db } from '$lib/server/db';
import { redirect } from '@sveltejs/kit';
export async function load(): Promise<{ messages: TypeMessage[] }> {
const rows = await db.getMessages('general', 50);
const messages: TypeMessage[] = rows
? rows.map((value) => {
return {
message: value.message_content,
user: value.sender.toString(),
imageSrc: `https://api.dicebear.com/9.x/identicon/svg?seed=${value.sender.toString()}`,
};
})
: [];
return {
messages: messages ?? [],
};
export function load(): void {
redirect(308, '/channel/general');
}

View File

@ -1,58 +0,0 @@
<script lang="ts">
import { io } from 'socket.io-client';
import { onMount } from 'svelte';
import { v4 as uuidv4 } from 'uuid';
import { type TypeMessage } from '$lib';
import type { PageData } from './$types';
import { Input } from '$lib/components/ui/input/index';
import { Button } from '$lib/components/ui/button/index';
import Send from 'lucide-svelte/icons/send';
import Message from '$lib/components/message.svelte';
let { data }: { data: PageData } = $props();
let user: string | undefined;
let socket: ReturnType<typeof io> | null = null;
let log: TypeMessage[] = $state([]);
let msg: string = $state('');
function logEvent(newMsg: TypeMessage) {
log = [newMsg, ...log];
}
function establishSocketIOConnection() {
if (socket) return;
socket = io();
socket.on('message', (data: TypeMessage) => {
console.log('[ws] message received', data);
logEvent(data);
});
}
function sendMessage() {
if (!socket) return;
socket.emit('message', { id: user, content: msg });
msg = '';
}
onMount(() => {
establishSocketIOConnection();
user = uuidv4();
});
</script>
{#snippet message(messages: TypeMessage[])}
{#each messages as message}
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} />
{/each}
{/snippet}
<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">
{@render message(log)}
{@render message(data.messages)}
</div>
<form class="flex gap-1 w-full" onsubmit={sendMessage}>
<Input type="text" placeholder="Type Here" bind:value={msg} />
<Button class="h-9 w-14"><Send class="size-full" /></Button>
</form>
</div>

View File

@ -0,0 +1,26 @@
import type { TypeMessage } from '$lib';
import { error } from '@sveltejs/kit';
import { db } from '$lib/server/db';
export async function load({ params }): Promise<{ messages: TypeMessage[] }> {
let messages: TypeMessage[];
const rows = await db.getMessages(params.channel, 50);
if (rows.messages !== null) {
messages = rows
? rows.messages.map((value) => {
return {
message: value.message_content,
user: value.sender.toString(),
imageSrc: `https://api.dicebear.com/9.x/identicon/svg?seed=${value.sender.toString()}`,
};
})
: [];
} else {
return error(404, `Channel '${params.channel}' does not exist`);
}
return {
messages: messages ?? [],
};
}

View File

@ -0,0 +1,58 @@
<script lang="ts">
import { io } from 'socket.io-client';
import { onMount } from 'svelte';
import { v4 as uuidv4 } from 'uuid';
import { type TypeMessage } from '$lib';
import type { PageData } from './$types';
import { Input } from '$lib/components/ui/input/index';
import { Button } from '$lib/components/ui/button/index';
import Send from 'lucide-svelte/icons/send';
import Message from '$lib/components/message.svelte';
let { data }: { data: PageData } = $props();
let user: string | undefined;
let socket: ReturnType<typeof io> | null = null;
let log: TypeMessage[] = $state([]);
let msg: string = $state('');
function logEvent(newMsg: TypeMessage) {
log = [newMsg, ...log];
}
function establishSocketIOConnection() {
if (socket) return;
socket = io();
socket.on('message', (data: TypeMessage) => {
console.log('[ws] message received', data);
logEvent(data);
});
}
function sendMessage() {
if (!socket) return;
socket.emit('message', { id: user, content: msg });
msg = '';
}
onMount(() => {
establishSocketIOConnection();
user = uuidv4();
});
</script>
{#snippet message(messages: TypeMessage[])}
{#each messages as message}
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} />
{/each}
{/snippet}
<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">
{@render message(log)}
{@render message(data.messages)}
</div>
<form class="flex gap-1 w-full" onsubmit={sendMessage}>
<Input type="text" placeholder="Type Here" bind:value={msg} />
<Button class="h-9 w-14"><Send class="size-full" /></Button>
</form>
</div>