101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
import { Plus, LogOut } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
import { Muted } from "@/components/ui/typography";
|
|
import { Progress } from "@/components/ui/progress";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { useAppStore } from "@/stores/app-store";
|
|
import { useAuthStore } from "@/stores/auth-store";
|
|
import { StreamList } from "@/features/streams/stream-list";
|
|
import { CreateStreamDialog } from "@/features/streams/create-stream-dialog";
|
|
import { WindowControls } from "@/components/window-controls";
|
|
|
|
export function StreamsPage() {
|
|
const networks = useAppStore((s) => s.networks);
|
|
const selectedNetworkId = useAppStore((s) => s.selectedNetworkId);
|
|
const setSelectedNetwork = useAppStore((s) => s.setSelectedNetwork);
|
|
const signOut = useAuthStore((s) => s.signOut);
|
|
const user = useAuthStore((s) => s.user);
|
|
|
|
const selectedNetwork = selectedNetworkId
|
|
? networks.find((n) => n.id === selectedNetworkId)
|
|
: null;
|
|
|
|
return (
|
|
<div className="flex h-screen flex-col">
|
|
{/* Top bar — draggable for frameless window */}
|
|
<div className="drag-region flex items-center gap-3 border-b px-4 py-3">
|
|
<WindowControls />
|
|
|
|
<Select
|
|
value={selectedNetworkId ?? undefined}
|
|
onValueChange={(value) => setSelectedNetwork(value)}
|
|
>
|
|
<SelectTrigger className="no-drag">
|
|
<SelectValue placeholder="Select a network" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{networks.map((network) => (
|
|
<SelectItem key={network.id} value={network.id}>
|
|
{network.name}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
|
|
{selectedNetwork && (
|
|
<div className="flex items-center gap-2">
|
|
<Progress
|
|
value={
|
|
(selectedNetwork.open_stream_count /
|
|
selectedNetwork.open_stream_capacity) *
|
|
100
|
|
}
|
|
className="h-1.5 w-24"
|
|
/>
|
|
<Muted className="text-xs">
|
|
{selectedNetwork.open_stream_count}/
|
|
{selectedNetwork.open_stream_capacity} streams
|
|
</Muted>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex-1" />
|
|
|
|
{selectedNetworkId && (
|
|
<CreateStreamDialog networkId={selectedNetworkId}>
|
|
<Button variant="outline" size="sm" className="no-drag">
|
|
<Plus className="mr-1.5 h-3.5 w-3.5" />
|
|
New Stream
|
|
</Button>
|
|
</CreateStreamDialog>
|
|
)}
|
|
|
|
{user && (
|
|
<Muted className="text-xs">{user.email_prefix}</Muted>
|
|
)}
|
|
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="no-drag text-muted-foreground"
|
|
onClick={signOut}
|
|
>
|
|
<LogOut className="h-3.5 w-3.5" />
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Stream list */}
|
|
<ScrollArea className="flex-1">
|
|
<StreamList />
|
|
</ScrollArea>
|
|
</div>
|
|
);
|
|
}
|