feat: Add support for mutiple channels
This commit is contained in:
parent
edfd65335c
commit
39bb7418c9
@ -1,5 +1,10 @@
|
|||||||
import cassandra from 'cassandra-driver';
|
import cassandra from 'cassandra-driver';
|
||||||
|
|
||||||
|
interface Messages {
|
||||||
|
messages: cassandra.types.Row[] | null;
|
||||||
|
error: Error | null;
|
||||||
|
}
|
||||||
|
|
||||||
class Db {
|
class Db {
|
||||||
private client: cassandra.Client;
|
private client: cassandra.Client;
|
||||||
|
|
||||||
@ -47,15 +52,21 @@ class Db {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get messages method
|
// Get messages method
|
||||||
async getMessages(channelName: string, limit: number): Promise<cassandra.types.Row[] | undefined> {
|
async getMessages(channelName: string, limit: number): Promise<Messages> {
|
||||||
try {
|
try {
|
||||||
const res = await this.client.execute(
|
const res = await this.client.execute(
|
||||||
`SELECT * FROM channels.${channelName} WHERE channel_name = '${channelName}' ORDER BY timestamp DESC LIMIT ${limit}`,
|
`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) {
|
} catch (e) {
|
||||||
console.log(`Error fetching messages: ${(e as Error).message}`);
|
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);
|
const db = new Db(client);
|
||||||
await db.createChannel('general');
|
await db.createChannel('general');
|
||||||
|
|
||||||
export { db };
|
export { db, type Messages };
|
||||||
|
@ -1,19 +1,5 @@
|
|||||||
import type { TypeMessage } from '$lib';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import { db } from '$lib/server/db';
|
|
||||||
|
|
||||||
export async function load(): Promise<{ messages: TypeMessage[] }> {
|
export function load(): void {
|
||||||
const rows = await db.getMessages('general', 50);
|
redirect(308, '/channel/general');
|
||||||
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 ?? [],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
|
26
src/routes/channel/[channel]/+page.server.ts
Normal file
26
src/routes/channel/[channel]/+page.server.ts
Normal 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 ?? [],
|
||||||
|
};
|
||||||
|
}
|
58
src/routes/channel/[channel]/+page.svelte
Normal file
58
src/routes/channel/[channel]/+page.svelte
Normal 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>
|
Loading…
Reference in New Issue
Block a user