91 lines
3.1 KiB
Svelte
91 lines
3.1 KiB
Svelte
<script lang="ts">
|
|
import { page } from '$app/state';
|
|
import EmptyChannel from '$lib/components/emptyChannel.svelte';
|
|
import Message from '$lib/components/message.svelte';
|
|
import MessageLengthDialog from '$lib/components/messageLengthDialog.svelte';
|
|
import { Button } from '$lib/components/ui/button/index';
|
|
import { autoResize } from '$lib/functions/autoresize.svelte';
|
|
import Websocket from '$lib/functions/clientWebsocket.svelte';
|
|
import type { TypeMessage } from '$lib/types';
|
|
import Send from 'lucide-svelte/icons/send';
|
|
import { io } from 'socket.io-client';
|
|
import { onMount } from 'svelte';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
import type { PageData } from './$types';
|
|
|
|
const { data }: { data: PageData } = $props();
|
|
|
|
let user: string = uuidv4();
|
|
let socket: Websocket | undefined = $state();
|
|
let msg: string = $state('');
|
|
let showDialog: boolean = $state(false);
|
|
const channel: string = $derived(page.params.channel);
|
|
let textareaRef: HTMLTextAreaElement | undefined = $state();
|
|
let formref: HTMLFormElement | undefined = $state();
|
|
|
|
function submit() {
|
|
if (msg.length <= 2000) {
|
|
socket?.sendMessage(user!, msg);
|
|
if (textareaRef) textareaRef.style.height = '40px';
|
|
msg = '';
|
|
} else {
|
|
showDialog = true;
|
|
}
|
|
}
|
|
|
|
onMount(() => {
|
|
// Connect on page load
|
|
socket = new Websocket(io());
|
|
socket.connect();
|
|
|
|
// Submit on textarea enter
|
|
textareaRef?.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault();
|
|
formref?.requestSubmit();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Update channel on page refresh
|
|
$effect(() => {
|
|
if (socket) socket.updateChannel(channel);
|
|
});
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>SVChat | #{channel}</title>
|
|
</svelte:head>
|
|
|
|
{#snippet message(messages: TypeMessage[])}
|
|
{#each messages as message}
|
|
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} />
|
|
{/each}
|
|
{/snippet}
|
|
|
|
<MessageLengthDialog messageLength={msg.length} bind:showDialog />
|
|
|
|
<div class="flex h-full flex-1 flex-col items-center justify-center gap-1 rounded-lg shadow-sm">
|
|
<div class="relative size-full flex-grow rounded-lg border">
|
|
{#if data.messages.length != 0 || socket?.messages.length != 0}
|
|
<div class="flex size-full flex-auto flex-col-reverse overflow-x-hidden overflow-y-scroll">
|
|
{@render message(socket?.messages ?? [])}
|
|
{@render message(data.messages)}
|
|
</div>
|
|
{:else}
|
|
<EmptyChannel />
|
|
{/if}
|
|
</div>
|
|
<form bind:this={formref} class="flex w-full gap-1" onsubmit={submit}>
|
|
<textarea
|
|
placeholder="Type Here"
|
|
bind:value={msg}
|
|
bind:this={textareaRef}
|
|
use:autoResize
|
|
class="flex h-10 min-h-10 w-full resize-none rounded-md border border-input bg-transparent px-3 py-2 text-sm
|
|
shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1
|
|
focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"></textarea>
|
|
<Button class="h-full min-h-10 w-14" type="submit"><Send class="size-full" /></Button>
|
|
</form>
|
|
</div>
|