Server functionality
This commit is contained in:
@@ -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}>
|
||||
<MessageBox
|
||||
app={app}
|
||||
channelName="General"
|
||||
messages={messages[ip]?.filter((m) => m.channel_id === "general") || []}
|
||||
sendMessage={(message) => {
|
||||
serverRef.current?.send(
|
||||
JSON.stringify({
|
||||
type: "send_message",
|
||||
params: {
|
||||
channel_id: "general",
|
||||
contents: message,
|
||||
},
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{app.currentChannel ? (
|
||||
<MessageBox
|
||||
app={app}
|
||||
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: 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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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} />
|
||||
)}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user