Sidebar
This commit is contained in:
@@ -73,6 +73,8 @@ export default class Enclave {
|
|||||||
getHTTPUrl(hostname, isSecure, "/meta"),
|
getHTTPUrl(hostname, isSecure, "/meta"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.server.meta = metaResponse.data as any;
|
||||||
|
|
||||||
this.serverList[hostname] = {
|
this.serverList[hostname] = {
|
||||||
meta: metaResponse.data as any,
|
meta: metaResponse.data as any,
|
||||||
isSecure,
|
isSecure,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export interface ClientMeta {}
|
|||||||
export interface ServerMeta {
|
export interface ServerMeta {
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
channels: Channel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ClientMethod =
|
export type ClientMethod =
|
||||||
@@ -33,3 +34,8 @@ export type ServerMethod =
|
|||||||
method: "Error";
|
method: "Error";
|
||||||
error: string;
|
error: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Channel = { id: string; name: string } & ChannelKind;
|
||||||
|
|
||||||
|
export type ChannelKind =
|
||||||
|
{ kind: "text" } | { kind: "category"; channels: Channel[] };
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as ed from "@noble/ed25519";
|
|||||||
import EnclaveWebSocket from "./ws";
|
import EnclaveWebSocket from "./ws";
|
||||||
import { sha512 } from "@noble/hashes/sha2.js";
|
import { sha512 } from "@noble/hashes/sha2.js";
|
||||||
import { getWSUrl } from "@/lib/serverList";
|
import { getWSUrl } from "@/lib/serverList";
|
||||||
|
import { ServerMeta } from "./protocol";
|
||||||
|
|
||||||
ed.hashes.sha512 = sha512;
|
ed.hashes.sha512 = sha512;
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ export default class EnclaveServer {
|
|||||||
public hostname: string;
|
public hostname: string;
|
||||||
public isSecure: boolean;
|
public isSecure: boolean;
|
||||||
public websocket?: EnclaveWebSocket;
|
public websocket?: EnclaveWebSocket;
|
||||||
|
public meta?: ServerMeta;
|
||||||
|
|
||||||
public constructor(hostname: string, isSecure: boolean) {
|
public constructor(hostname: string, isSecure: boolean) {
|
||||||
this.hostname = hostname;
|
this.hostname = hostname;
|
||||||
|
|||||||
@@ -1,9 +1,52 @@
|
|||||||
import Enclave from "@/app/app";
|
import Enclave from "@/app/app";
|
||||||
|
import { Channel, ChannelKind } from "@/app/protocol";
|
||||||
|
import { HashIcon } from "lucide-react";
|
||||||
|
|
||||||
|
export function ChannelIcon({ kind }: { kind: ChannelKind["kind"] }) {
|
||||||
|
switch (kind) {
|
||||||
|
case "text":
|
||||||
|
return <HashIcon className="p-0.5" />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RenderChannels({ channels }: { channels: Channel[] }) {
|
||||||
|
return channels.map((channel) =>
|
||||||
|
channel.kind === "category" ? (
|
||||||
|
<div>
|
||||||
|
<div className="w-full px-0.5 py-1 rounded-md select-none cursor-default text-sm text-foreground/70">
|
||||||
|
{channel.name}
|
||||||
|
</div>
|
||||||
|
<div className="pl-2 pr-1.5 pt-0.5 w-full flex flex-col gap-1">
|
||||||
|
<RenderChannels channels={channel.channels} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="w-full hover:bg-accent px-2.5 py-1.5 rounded-md flex gap-2.5 items-center select-none cursor-default text-sm text-foreground/70">
|
||||||
|
<ChannelIcon kind={channel.kind} />
|
||||||
|
{channel.name}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function Sidebar({
|
export default function Sidebar({
|
||||||
appRef,
|
appRef,
|
||||||
}: {
|
}: {
|
||||||
appRef: React.RefObject<Enclave | null>;
|
appRef: React.RefObject<Enclave | null>;
|
||||||
}) {
|
}) {
|
||||||
return <div className="h-screen"></div>;
|
return (
|
||||||
|
appRef.current?.server?.meta && (
|
||||||
|
<div className="h-screen">
|
||||||
|
<header className="px-3 pt-2.5 pb-2.5 text-lg font-semibold border-b border-b-border">
|
||||||
|
<h1>{appRef.current.server.meta.name}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section className="px-1.5 pt-3.5 w-full flex flex-col gap-1">
|
||||||
|
<RenderChannels channels={appRef.current.server.meta.channels} />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-35
@@ -49,41 +49,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: oklch(1 0 0);
|
|
||||||
--foreground: oklch(0.145 0 0);
|
|
||||||
--card: oklch(1 0 0);
|
|
||||||
--card-foreground: oklch(0.145 0 0);
|
|
||||||
--popover: oklch(1 0 0);
|
|
||||||
--popover-foreground: oklch(0.145 0 0);
|
|
||||||
--primary: oklch(0.205 0 0);
|
|
||||||
--primary-foreground: oklch(0.985 0 0);
|
|
||||||
--secondary: oklch(0.97 0 0);
|
|
||||||
--secondary-foreground: oklch(0.205 0 0);
|
|
||||||
--muted: oklch(0.97 0 0);
|
|
||||||
--muted-foreground: oklch(0.556 0 0);
|
|
||||||
--accent: oklch(0.97 0 0);
|
|
||||||
--accent-foreground: oklch(0.205 0 0);
|
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
|
||||||
--border: oklch(0.922 0 0);
|
|
||||||
--input: oklch(0.922 0 0);
|
|
||||||
--ring: oklch(0.708 0 0);
|
|
||||||
--chart-1: oklch(0.87 0 0);
|
|
||||||
--chart-2: oklch(0.556 0 0);
|
|
||||||
--chart-3: oklch(0.439 0 0);
|
|
||||||
--chart-4: oklch(0.371 0 0);
|
|
||||||
--chart-5: oklch(0.269 0 0);
|
|
||||||
--radius: 0.625rem;
|
|
||||||
--sidebar: oklch(0.985 0 0);
|
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
|
||||||
--sidebar-primary: oklch(0.205 0 0);
|
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
||||||
--sidebar-accent: oklch(0.97 0 0);
|
|
||||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
||||||
--sidebar-border: oklch(0.922 0 0);
|
|
||||||
--sidebar-ring: oklch(0.708 0 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--background: oklch(0.145 0 0);
|
--background: oklch(0.145 0 0);
|
||||||
--foreground: oklch(0.985 0 0);
|
--foreground: oklch(0.985 0 0);
|
||||||
--card: oklch(0.205 0 0);
|
--card: oklch(0.205 0 0);
|
||||||
@@ -115,6 +80,42 @@
|
|||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-border: oklch(1 0 0 / 10%);
|
--sidebar-border: oklch(1 0 0 / 10%);
|
||||||
--sidebar-ring: oklch(0.556 0 0);
|
--sidebar-ring: oklch(0.556 0 0);
|
||||||
|
|
||||||
|
--radius: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: oklch(1 0 0);
|
||||||
|
--foreground: oklch(0.145 0 0);
|
||||||
|
--card: oklch(1 0 0);
|
||||||
|
--card-foreground: oklch(0.145 0 0);
|
||||||
|
--popover: oklch(1 0 0);
|
||||||
|
--popover-foreground: oklch(0.145 0 0);
|
||||||
|
--primary: oklch(0.205 0 0);
|
||||||
|
--primary-foreground: oklch(0.985 0 0);
|
||||||
|
--secondary: oklch(0.97 0 0);
|
||||||
|
--secondary-foreground: oklch(0.205 0 0);
|
||||||
|
--muted: oklch(0.97 0 0);
|
||||||
|
--muted-foreground: oklch(0.556 0 0);
|
||||||
|
--accent: oklch(0.97 0 0);
|
||||||
|
--accent-foreground: oklch(0.205 0 0);
|
||||||
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
|
--border: oklch(0.922 0 0);
|
||||||
|
--input: oklch(0.922 0 0);
|
||||||
|
--ring: oklch(0.708 0 0);
|
||||||
|
--chart-1: oklch(0.87 0 0);
|
||||||
|
--chart-2: oklch(0.556 0 0);
|
||||||
|
--chart-3: oklch(0.439 0 0);
|
||||||
|
--chart-4: oklch(0.371 0 0);
|
||||||
|
--chart-5: oklch(0.269 0 0);
|
||||||
|
--sidebar: oklch(0.985 0 0);
|
||||||
|
--sidebar-foreground: oklch(0.145 0 0);
|
||||||
|
--sidebar-primary: oklch(0.205 0 0);
|
||||||
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||||
|
--sidebar-accent: oklch(0.97 0 0);
|
||||||
|
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||||
|
--sidebar-border: oklch(0.922 0 0);
|
||||||
|
--sidebar-ring: oklch(0.708 0 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
|
|||||||
Reference in New Issue
Block a user