enhance stream view

This commit is contained in:
talksik
2026-03-21 11:39:43 -07:00
parent 2262bf4f3b
commit cba24c5d95
3 changed files with 66 additions and 57 deletions
@@ -43,7 +43,6 @@ export default function ControlsIndicator({ type, children }: ControlsIndicatorP
{children ? <div className="flex-1">{children}</div> :
<div className="flex-1" />
}
{children && <span className="text-muted-foreground">·</span>}
<div className="text-muted-foreground">
Hold{" "}
<kbd
@@ -29,14 +29,14 @@ export function PlaybackPageIndicator({
{/* Dim track */}
<div
className={cn(
"absolute inset-x-0 top-1 h-1 rounded-full bg-white/30",
"absolute inset-x-0 top-0 h-1 bg-white/30 transition-all",
"group-hover:h-1.5 group-hover:top-0.5",
)}
/>
{/* Fill */}
<div
className={cn(
"absolute left-0 top-1 h-1 rounded-full bg-white/90",
"absolute left-0 top-0 h-1 bg-white/90 transition-all",
"group-hover:h-1.5 group-hover:top-0.5",
)}
style={{
+64 -54
View File
@@ -18,6 +18,7 @@ import { Button } from "@/components/ui/button";
import { Home, Settings } from "lucide-react";
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
import { WindowControls } from "@/components/window-controls";
import { formatDistanceToNow } from "@/lib/time-utils";
function getParticleDisplayName(particle: Particle): string {
switch (particle.type) {
@@ -367,58 +368,7 @@ export function StreamView({ path, streamParticle }: StreamViewProps) {
/>
</div>
<div className="z-10 absolute left-0 right-0 flex flex-row mt-3 px-2 gap-5 items-center">
<WindowControls />
<Breadcrumb className="no-drag rounded-full bg-black/30 backdrop-blur-sm px-3 py-1 mx-auto">
<BreadcrumbList>
<BreadcrumbItem className="text-xs">
<BreadcrumbLink
className="flex cursor-pointer items-center gap-1"
onClick={() => navigate("/")}
>
<Home className="size-3.5" />
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem className="text-xs">
<BreadcrumbLink
className="cursor-pointer"
onClick={() => navigate(`/${networkId}`)}
>
<NetworkBreadcrumbContent networkId={networkId} />
</BreadcrumbLink>
</BreadcrumbItem>
{streamParticle && (
<span key={path} className="contents">
<BreadcrumbSeparator />
<BreadcrumbItem className="text-xs">
<BreadcrumbPage>{getParticleDisplayName(streamParticle)}</BreadcrumbPage>
</BreadcrumbItem>
</span>
)}
{currentParticle && (
<>
<BreadcrumbSeparator />
<BreadcrumbItem className="text-xs">
<BreadcrumbPage><ParticleBreadcrumbContent particle={currentParticle} /></BreadcrumbPage>
</BreadcrumbItem>
</>
)}
</BreadcrumbList>
</Breadcrumb>
<Button
variant="ghost"
size="sm"
className="no-drag text-muted-foreground"
onClick={() => navigate("/settings")}
>
<Settings className="size-3.5" />
</Button>
</div>
<TopBar networkId={networkId} particle={currentParticle} streamParticle={streamParticle} />
{/* Main playback area */}
<div className="flex-1 overflow-hidden">
@@ -456,6 +406,65 @@ export function StreamView({ path, streamParticle }: StreamViewProps) {
);
}
function TopBar({ networkId, particle, streamParticle }: { networkId: string; particle: Particle; streamParticle: Particle & { type: "stream" } }) {
const navigate = useNavigate();
return (
<div className="drag-region z-10 absolute left-0 right-0 flex flex-row mt-3 px-4 gap-5 items-center opacity-0 hover:opacity-100 transition-all">
<WindowControls />
<Breadcrumb className="no-drag rounded-full bg-black/30 backdrop-blur-sm px-3 py-1 mx-auto">
<BreadcrumbList>
<BreadcrumbItem className="text-xs">
<BreadcrumbLink
className="flex cursor-pointer items-center gap-1"
onClick={() => navigate("/")}
>
<Home className="size-3.5" />
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem className="text-xs">
<BreadcrumbLink
className="cursor-pointer"
onClick={() => navigate(`/${networkId}`)}
>
<NetworkBreadcrumbContent networkId={networkId} />
</BreadcrumbLink>
</BreadcrumbItem>
{streamParticle && (
<>
<BreadcrumbSeparator />
<BreadcrumbItem className="text-xs">
<BreadcrumbPage>{getParticleDisplayName(streamParticle)}</BreadcrumbPage>
</BreadcrumbItem>
</>
)}
{particle && (
<>
<BreadcrumbSeparator />
<BreadcrumbItem className="text-xs">
<BreadcrumbPage><ParticleBreadcrumbContent particle={particle} /></BreadcrumbPage>
</BreadcrumbItem>
</>
)}
</BreadcrumbList>
</Breadcrumb>
<Button
variant="ghost"
size="sm"
className="no-drag text-muted-foreground"
onClick={() => navigate("/settings")}
>
<Settings className="size-3.5" />
</Button>
</div>
);
}
function NetworkBreadcrumbContent({ networkId }: { networkId: string }) {
const { data: networks } = useNetworks();
const network = networks?.find((n) => n.id === networkId);
@@ -480,13 +489,14 @@ function ParticleBreadcrumbContent({ particle }: { particle: Particle }) {
const initials = createdByEmail.slice(0, 2).toUpperCase();
return (
<span className="flex items-center gap-1.5">
<span className="flex
items-center gap-1.5">
<Avatar size="sm">
<AvatarFallback>
{initials}
</AvatarFallback>
</Avatar>
{prefix}
{prefix} - {formatDistanceToNow(particle.created_at.toISOString())}
</span>
)
}