import { LivestreamProvider } from "@/components/stream/livestream-provider"; import { Button } from "@/components/ui/button"; import { useFullscreen } from "@/contexts/fullscreen-context"; import { useSession } from "@/lib/session"; import { useStore } from "@/lib/store"; import { Link, Outlet, useMatchRoute } from "@tanstack/react-router"; import { ArrowLeft, ArrowUpFromLine, Key, LayoutGrid, ListVideo, Radio, Share2, Video, Webhook, } from "lucide-react"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarInset, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarProvider, SidebarTrigger, } from "../ui/sidebar"; import { DashboardMetricsProvider } from "./dashboard-metrics"; import { DashboardStoreContext } from "./dashboard-store-context"; interface NavLink { to: string; icon: React.ComponentType<{ className?: string }>; labelKey: string; } /** Main nav; appears above the Settings group. */ const MAIN_NAV: NavLink[] = [ { to: "/dashboard", icon: LayoutGrid, labelKey: "control-panel" }, { to: "/dashboard/upload", icon: ArrowUpFromLine, labelKey: "upload-videos", }, { to: "/dashboard/videos", icon: Video, labelKey: "my-videos", }, ]; /** Settings group; appears under a "Settings" header. */ const SETTINGS_NAV: NavLink[] = [ { to: "/dashboard/stream", icon: Radio, labelKey: "stream-settings" }, { to: "/dashboard/keys", icon: Key, labelKey: "key-manager" }, { to: "/dashboard/multistream", icon: Share2, labelKey: "multistream" }, { to: "/dashboard/recommendations", icon: ListVideo, labelKey: "recommendations-to-others", }, { to: "/dashboard/webhooks", icon: Webhook, labelKey: "webhooks" }, ]; const DASHBOARD_NAV_OPEN_KEY = "streamplace:dashboard-nav-open"; export default function DashboardChrome() { const { t } = useTranslation("settings"); const { state } = useSession(); const { theatre } = useFullscreen(); const [open, setOpen] = useState(() => { if (typeof localStorage === "undefined") return true; return localStorage.getItem(DASHBOARD_NAV_OPEN_KEY) !== "false"; }); if (state.status !== "authenticated") { // "loading" means the OAuth client is restoring the session; don't // flash the "please log in" prompt on refresh for an already-logged-in // user. if (state.status === "loading") { return (
); } return (

{t("login-required", { defaultValue: "Please log in to access the dashboard.", })}

); } const user = state.session.did; // are we in /dashboard/? if so hide the header const isDashboardRoot = window.location.pathname === "/dashboard"; return ( {(store) => ( { setOpen(o); if (typeof localStorage !== "undefined") { localStorage.setItem(DASHBOARD_NAV_OPEN_KEY, String(o)); } }} > {!theatre && } {!theatre && !isDashboardRoot && (

{t("nav-dashboard", { defaultValue: "Creator Dashboard", })}

)}
)}
); } function DashboardSidebar() { const { t } = useTranslation("settings"); const { state } = useSession(); const matchRoute = useMatchRoute(); if (state.status !== "authenticated") { return null; } const user = state.session.did; // The control panel (/dashboard) is the parent of every dashboard // page, so it matches exactly; the rest are leaf routes. const isNavActive = (to: string) => matchRoute({ to, fuzzy: to !== "/dashboard" }) !== false; return ( {/* Back to Streamplace */} Back to Streamplace {/* Main nav: Control Panel + Stream Settings */} {MAIN_NAV.map((item) => { const Icon = item.icon; return ( {t(item.labelKey)} ); })} {/* Settings group: stream keys, multistream, recommendations, webhooks */} {t("settings-group", { defaultValue: "Settings" })} {SETTINGS_NAV.map((item) => { const Icon = item.icon; return ( {t(item.labelKey)} ); })} ); }