From 83c7926728c05aafe062531f05b19fa7e1d87b96 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 20 Aug 2026 18:12:47 +0200 Subject: [PATCH] Text Channel UI --- src/app/app.ts | 4 +- src/app/server.ts | 2 +- src/components/page/channel/TextChannel.tsx | 82 +++++++++++++++++++-- 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/app/app.ts b/src/app/app.ts index 58a752c..169196e 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -168,11 +168,11 @@ export default class Enclave

{ console.log("msg", msg.messages); Object.entries(msg.messages).forEach(([channelId, messages]) => { if (!server.messages[channelId]) { - server.messages[channelId] = []; + server.messages[channelId] = new Set(); } messages.forEach((message) => { - server.messages[channelId].push(message); + server.messages[channelId].add(message); }); }); diff --git a/src/app/server.ts b/src/app/server.ts index c54efd1..7d23595 100644 --- a/src/app/server.ts +++ b/src/app/server.ts @@ -29,7 +29,7 @@ export default class EnclaveServer { public isSecure: boolean; public websocket?: EnclaveWebSocket; public meta?: ServerMeta; - public messages: Record; + public messages: Record>; public constructor(hostname: string, isSecure: boolean) { this.hostname = hostname; diff --git a/src/components/page/channel/TextChannel.tsx b/src/components/page/channel/TextChannel.tsx index 166b90f..be60580 100644 --- a/src/components/page/channel/TextChannel.tsx +++ b/src/components/page/channel/TextChannel.tsx @@ -1,17 +1,21 @@ import Enclave from "@/app/app"; import { ChannelPageProps } from "@/components/page/PageView"; -import { useEffect } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { StoredMessage } from "@/lib/types"; +import { useEffect, useState } from "react"; export default function TextChannel({ appRef, }: { appRef: React.RefObject | null>; }) { + const [currentMessage, setCurrentMessage] = useState(""); const channel = appRef.current?.page?.channel; - if (!channel) return null; - useEffect(() => { + if (!channel) return; + appRef.current?.server?.websocket?.send({ method: "GetMessages", channel_id: channel.id, @@ -19,9 +23,77 @@ export default function TextChannel({ }); appRef.current?.forceRender(); - }, []); + }, [channel]); + + if (!channel) return null; + + const sendMessage = () => { + appRef.current?.sendMessage(currentMessage, channel.id); + setCurrentMessage(""); + }; return ( -

{JSON.stringify(appRef.current?.server?.messages[channel.id])}
+
+
+

{channel.name}

+
+ +
+ {appRef.current?.server?.messages[channel.id] && + Array.from(appRef.current?.server?.messages[channel.id]).map( + (message) => , + )} +
+ +
+ setCurrentMessage(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + sendMessage(); + } + }} + /> + + {currentMessage.trim() && } +
+
+ ); +} + +export function TextMessage({ + appRef, + message, +}: { + appRef: React.RefObject | null>; + message: StoredMessage; +}) { + const time = new Date(message.timestamp).toLocaleTimeString([], { + hour: "numeric", + minute: "2-digit", + }); + + return ( +
+
+ {message.author.slice(0, 2).toUpperCase()} +
+ +
+
+ + {message.author.slice(0, 8)} + + {time} +
+

+ {message.content} +

+
+
); }