Server functionality
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams, useSearchParams } from "next/navigation";
|
||||||
import MessageBox from "@/components/MessageBox";
|
import MessageBox from "@/components/MessageBox";
|
||||||
import AppLayout from "@/components/app/AppLayout";
|
import AppLayout from "@/components/app/AppLayout";
|
||||||
import { Server as ServerType } from "@/types/types";
|
import { Server as ServerType } from "@/types/types";
|
||||||
@@ -12,6 +12,7 @@ import { useEffectOnceWhenReady } from "@/hooks/use-once";
|
|||||||
|
|
||||||
export default function Server() {
|
export default function Server() {
|
||||||
const { ip } = useParams<{ ip: string }>();
|
const { ip } = useParams<{ ip: string }>();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const serverRef = useRef<WebSocket | null>(null);
|
const serverRef = useRef<WebSocket | null>(null);
|
||||||
const [server, setServer] = useState<undefined | ServerType>();
|
const [server, setServer] = useState<undefined | ServerType>();
|
||||||
const app = useApp();
|
const app = useApp();
|
||||||
@@ -31,27 +32,48 @@ export default function Server() {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
[ip, messages],
|
[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 (
|
return (
|
||||||
<AppLayout app={app} server={server}>
|
<AppLayout app={app} server={server}>
|
||||||
<MessageBox
|
{app.currentChannel ? (
|
||||||
app={app}
|
<MessageBox
|
||||||
channelName="General"
|
app={app}
|
||||||
messages={messages[ip]?.filter((m) => m.channel_id === "general") || []}
|
channelName={app.currentChannel.name}
|
||||||
sendMessage={(message) => {
|
messages={
|
||||||
serverRef.current?.send(
|
messages[ip]?.filter(
|
||||||
JSON.stringify({
|
(m) => m.channel_id === app.currentChannel?.id
|
||||||
type: "send_message",
|
) || []
|
||||||
params: {
|
}
|
||||||
channel_id: "general",
|
sendMessage={(message) => {
|
||||||
contents: 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>
|
</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-w-0 flex flex-col bg-sidebar">
|
||||||
<div className="flex-1 min-h-0">
|
<div className="flex-1 min-h-0">
|
||||||
{server ? (
|
{server ? (
|
||||||
<SidebarChannels server={server} />
|
<SidebarChannels server={server} app={app} />
|
||||||
) : (
|
) : (
|
||||||
<SidebarDMs app={app} />
|
<SidebarDMs app={app} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ScrollArea } from "../ui/scroll-area";
|
|||||||
import { Server, Channel } from "@/types/types";
|
import { Server, Channel } from "@/types/types";
|
||||||
import { Card } from "../ui/card";
|
import { Card } from "../ui/card";
|
||||||
import { HashIcon, Volume2Icon } from "lucide-react";
|
import { HashIcon, Volume2Icon } from "lucide-react";
|
||||||
|
import App from "@/types/app";
|
||||||
|
|
||||||
export function ChannelIcon({ kind }: { kind: "text" | "voice" }) {
|
export function ChannelIcon({ kind }: { kind: "text" | "voice" }) {
|
||||||
switch (kind) {
|
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 (
|
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} />
|
<ChannelIcon kind={channel.kind} />
|
||||||
<span className="text-sm font-medium">{channel.name}</span>
|
<span className="text-sm font-medium">{channel.name}</span>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SidebarChannels({ server }: { server: Server }) {
|
export default function SidebarChannels({
|
||||||
|
server,
|
||||||
|
app,
|
||||||
|
}: {
|
||||||
|
server: Server;
|
||||||
|
app: App;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full flex flex-col bg-sidebar">
|
<div className="w-full flex flex-col bg-sidebar">
|
||||||
<div className="p-3 border-b flex items-center gap-2">
|
<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">
|
<ScrollArea className="flex-1">
|
||||||
<div className="p-2 flex flex-col gap-2">
|
<div className="p-2 flex flex-col gap-2">
|
||||||
{server.channels.map((channel: Channel) => (
|
{server.channels.map((channel: Channel) => (
|
||||||
<ChannelItem key={channel.id} channel={channel} />
|
<ChannelItem key={channel.id} channel={channel} app={app} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { StringMap } from "@/types/typeUtils";
|
|||||||
import useUser, { UserProfile } from "./get-user";
|
import useUser, { UserProfile } from "./get-user";
|
||||||
import { useClientSettings } from "./use-settings";
|
import { useClientSettings } from "./use-settings";
|
||||||
import { get, Response } from "@/lib/request";
|
import { get, Response } from "@/lib/request";
|
||||||
import { Server } from "@/types/types";
|
import { Channel, Server } from "@/types/types";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ export default function useApp(): App {
|
|||||||
const [clientSettings, setClientSettings] = useClientSettings();
|
const [clientSettings, setClientSettings] = useClientSettings();
|
||||||
const [dms, setDms] = useState<UserProfile[]>([]);
|
const [dms, setDms] = useState<UserProfile[]>([]);
|
||||||
const [servers, setServers] = useState<StringMap<Server>>({});
|
const [servers, setServers] = useState<StringMap<Server>>({});
|
||||||
|
const [currentChannel, setCurrentChannel] = useState<Channel | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const stored = Cookies.get("servers");
|
const stored = Cookies.get("servers");
|
||||||
@@ -36,6 +37,8 @@ export default function useApp(): App {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
currentChannel,
|
||||||
|
setCurrentChannel,
|
||||||
servers,
|
servers,
|
||||||
setServers,
|
setServers,
|
||||||
dms,
|
dms,
|
||||||
|
|||||||
+4
-1
@@ -1,7 +1,7 @@
|
|||||||
import { Dispatch, RefObject, SetStateAction } from "react";
|
import { Dispatch, RefObject, SetStateAction } from "react";
|
||||||
import { StringMap } from "./typeUtils";
|
import { StringMap } from "./typeUtils";
|
||||||
import { UserProfile } from "@/hooks/get-user";
|
import { UserProfile } from "@/hooks/get-user";
|
||||||
import { Message, Server } from "./types";
|
import { Channel, Message, Server } from "./types";
|
||||||
import { ClientSettings } from "./settings";
|
import { ClientSettings } from "./settings";
|
||||||
|
|
||||||
export type SetState<T> = Dispatch<SetStateAction<T>>;
|
export type SetState<T> = Dispatch<SetStateAction<T>>;
|
||||||
@@ -29,4 +29,7 @@ export default interface App {
|
|||||||
|
|
||||||
dms: UserProfile[];
|
dms: UserProfile[];
|
||||||
setDms: SetState<UserProfile[]>;
|
setDms: SetState<UserProfile[]>;
|
||||||
|
|
||||||
|
currentChannel: Channel | null;
|
||||||
|
setCurrentChannel: SetState<Channel | null>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user