d33ca6278a
Cliente web sobre el gateway (REST + SSE). El navegador no habla NATS ni cripto: el peer Go del gateway lo hace. - Pantalla de conexión: gateway URL + identidad (persistidas en localStorage). - Navbar: crear room (con toggle de cifrado E2E), unirse por id, lista de rooms. - Centro: mensajes en vivo por SSE, burbujas con autor y hora, composer. - Lateral: miembros (rol owner), invitar por peer conectado, expulsar (owner). - Mantine v9 (createTheme + MantineProvider), @tabler/icons-react, layout con AppShell/Stack/Group; sin Tailwind ni CSS manual. React 19 (peer dep de v9). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 lines
882 B
TypeScript
30 lines
882 B
TypeScript
import { useState } from "react";
|
|
import { GatewayClient } from "./api";
|
|
import type { Peer } from "./types";
|
|
import { ConnectScreen } from "./components/ConnectScreen";
|
|
import { ChatLayout } from "./components/ChatLayout";
|
|
|
|
// Connection holds the live gateway client plus the identity it connected as.
|
|
interface Connection {
|
|
client: GatewayClient;
|
|
peer: Peer;
|
|
}
|
|
|
|
// App is the root: it shows the connect screen until the user picks a gateway
|
|
// URL and a peer name, then swaps to the full chat layout. Disconnecting drops
|
|
// back to the connect screen.
|
|
export function App() {
|
|
const [conn, setConn] = useState<Connection | null>(null);
|
|
|
|
if (!conn) {
|
|
return <ConnectScreen onConnect={(client, peer) => setConn({ client, peer })} />;
|
|
}
|
|
return (
|
|
<ChatLayout
|
|
client={conn.client}
|
|
peer={conn.peer}
|
|
onDisconnect={() => setConn(null)}
|
|
/>
|
|
);
|
|
}
|