Server functionality

This commit is contained in:
2025-10-31 15:22:14 +01:00
parent bee5b91fef
commit f123adb15f
5 changed files with 67 additions and 26 deletions
+28 -6
View File
@@ -1,7 +1,7 @@
"use client";
import { useRef, useState } from "react";
import { useParams } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { useParams, useSearchParams } from "next/navigation";
import MessageBox from "@/components/MessageBox";
import AppLayout from "@/components/app/AppLayout";
import { Server as ServerType } from "@/types/types";
@@ -12,6 +12,7 @@ import { useEffectOnceWhenReady } from "@/hooks/use-once";
export default function Server() {
const { ip } = useParams<{ ip: string }>();
const searchParams = useSearchParams();
const serverRef = useRef<WebSocket | null>(null);
const [server, setServer] = useState<undefined | ServerType>();
const app = useApp();
@@ -31,27 +32,48 @@ export default function Server() {
);
},
[ip, messages],
[undefined, (v) => v[ip]]
[undefined, (v) => v]
);
useEffect(() => {
const channelId = searchParams.get("ch");
if (channelId) {
app.setCurrentChannel(
server?.channels.find((v) => v.id === channelId) ||
server?.channels[0] ||
null
);
} else {
app.setCurrentChannel(server?.channels[0] || null);
}
}, [server]);
return (
<AppLayout app={app} server={server}>
{app.currentChannel ? (
<MessageBox
app={app}
channelName="General"
messages={messages[ip]?.filter((m) => m.channel_id === "general") || []}
channelName={app.currentChannel.name}
messages={
messages[ip]?.filter(
(m) => m.channel_id === app.currentChannel?.id
) || []
}
sendMessage={(message) => {
serverRef.current?.send(
JSON.stringify({
type: "send_message",
params: {
channel_id: "general",
channel_id: app.currentChannel?.id,
contents: message,
},
})
);
}}
/>
) : (
<div className="h-svh w-full max-h-svh flex flex-col pb-5 pl-5 gap-5"></div>
)}
</AppLayout>
);
}
+1 -1
View File
@@ -78,7 +78,7 @@ export default function AppLayout({
<div className="flex-1 min-w-0 flex flex-col bg-sidebar">
<div className="flex-1 min-h-0">
{server ? (
<SidebarChannels server={server} />
<SidebarChannels server={server} app={app} />
) : (
<SidebarDMs app={app} />
)}
+17 -4
View File
@@ -3,6 +3,7 @@ import { ScrollArea } from "../ui/scroll-area";
import { Server, Channel } from "@/types/types";
import { Card } from "../ui/card";
import { HashIcon, Volume2Icon } from "lucide-react";
import App from "@/types/app";
export function ChannelIcon({ kind }: { kind: "text" | "voice" }) {
switch (kind) {
@@ -15,16 +16,28 @@ export function ChannelIcon({ kind }: { kind: "text" | "voice" }) {
}
}
export function ChannelItem({ channel }: { channel: Channel }) {
export function ChannelItem({ channel, app }: { channel: Channel; app: App }) {
return (
<Card className="p-2 flex items-center gap-2 cursor-pointer hover:bg-accent">
<Card
className="p-2 flex flex-row px-3 items-center gap-2 cursor-pointer hover:bg-accent"
onClick={() => {
app.setCurrentChannel(channel);
app.setSidebarOpen(false);
}}
>
<ChannelIcon kind={channel.kind} />
<span className="text-sm font-medium">{channel.name}</span>
</Card>
);
}
export default function SidebarChannels({ server }: { server: Server }) {
export default function SidebarChannels({
server,
app,
}: {
server: Server;
app: App;
}) {
return (
<div className="w-full flex flex-col bg-sidebar">
<div className="p-3 border-b flex items-center gap-2">
@@ -33,7 +46,7 @@ export default function SidebarChannels({ server }: { server: Server }) {
<ScrollArea className="flex-1">
<div className="p-2 flex flex-col gap-2">
{server.channels.map((channel: Channel) => (
<ChannelItem key={channel.id} channel={channel} />
<ChannelItem key={channel.id} channel={channel} app={app} />
))}
</div>
</ScrollArea>
+4 -1
View File
@@ -5,7 +5,7 @@ import { StringMap } from "@/types/typeUtils";
import useUser, { UserProfile } from "./get-user";
import { useClientSettings } from "./use-settings";
import { get, Response } from "@/lib/request";
import { Server } from "@/types/types";
import { Channel, Server } from "@/types/types";
import Cookies from "js-cookie";
import { toast } from "sonner";
@@ -18,6 +18,7 @@ export default function useApp(): App {
const [clientSettings, setClientSettings] = useClientSettings();
const [dms, setDms] = useState<UserProfile[]>([]);
const [servers, setServers] = useState<StringMap<Server>>({});
const [currentChannel, setCurrentChannel] = useState<Channel | null>(null);
useEffect(() => {
const stored = Cookies.get("servers");
@@ -36,6 +37,8 @@ export default function useApp(): App {
}, []);
return {
currentChannel,
setCurrentChannel,
servers,
setServers,
dms,
+4 -1
View File
@@ -1,7 +1,7 @@
import { Dispatch, RefObject, SetStateAction } from "react";
import { StringMap } from "./typeUtils";
import { UserProfile } from "@/hooks/get-user";
import { Message, Server } from "./types";
import { Channel, Message, Server } from "./types";
import { ClientSettings } from "./settings";
export type SetState<T> = Dispatch<SetStateAction<T>>;
@@ -29,4 +29,7 @@ export default interface App {
dms: UserProfile[];
setDms: SetState<UserProfile[]>;
currentChannel: Channel | null;
setCurrentChannel: SetState<Channel | null>;
}