enhance stream view
This commit is contained in:
@@ -43,7 +43,6 @@ export default function ControlsIndicator({ type, children }: ControlsIndicatorP
|
|||||||
{children ? <div className="flex-1">{children}</div> :
|
{children ? <div className="flex-1">{children}</div> :
|
||||||
<div className="flex-1" />
|
<div className="flex-1" />
|
||||||
}
|
}
|
||||||
{children && <span className="text-muted-foreground">·</span>}
|
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
Hold{" "}
|
Hold{" "}
|
||||||
<kbd
|
<kbd
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ export function PlaybackPageIndicator({
|
|||||||
{/* Dim track */}
|
{/* Dim track */}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
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",
|
"group-hover:h-1.5 group-hover:top-0.5",
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{/* Fill */}
|
{/* Fill */}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
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",
|
"group-hover:h-1.5 group-hover:top-0.5",
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Home, Settings } from "lucide-react";
|
import { Home, Settings } from "lucide-react";
|
||||||
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
|
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
|
||||||
import { WindowControls } from "@/components/window-controls";
|
import { WindowControls } from "@/components/window-controls";
|
||||||
|
import { formatDistanceToNow } from "@/lib/time-utils";
|
||||||
|
|
||||||
function getParticleDisplayName(particle: Particle): string {
|
function getParticleDisplayName(particle: Particle): string {
|
||||||
switch (particle.type) {
|
switch (particle.type) {
|
||||||
@@ -367,58 +368,7 @@ export function StreamView({ path, streamParticle }: StreamViewProps) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="z-10 absolute left-0 right-0 flex flex-row mt-3 px-2 gap-5 items-center">
|
<TopBar networkId={networkId} particle={currentParticle} streamParticle={streamParticle} />
|
||||||
<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>
|
|
||||||
|
|
||||||
{/* Main playback area */}
|
{/* Main playback area */}
|
||||||
<div className="flex-1 overflow-hidden">
|
<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 }) {
|
function NetworkBreadcrumbContent({ networkId }: { networkId: string }) {
|
||||||
const { data: networks } = useNetworks();
|
const { data: networks } = useNetworks();
|
||||||
const network = networks?.find((n) => n.id === networkId);
|
const network = networks?.find((n) => n.id === networkId);
|
||||||
@@ -480,13 +489,14 @@ function ParticleBreadcrumbContent({ particle }: { particle: Particle }) {
|
|||||||
const initials = createdByEmail.slice(0, 2).toUpperCase();
|
const initials = createdByEmail.slice(0, 2).toUpperCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="flex items-center gap-1.5">
|
<span className="flex
|
||||||
|
items-center gap-1.5">
|
||||||
<Avatar size="sm">
|
<Avatar size="sm">
|
||||||
<AvatarFallback>
|
<AvatarFallback>
|
||||||
{initials}
|
{initials}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
{prefix}
|
{prefix} - {formatDistanceToNow(particle.created_at.toISOString())}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user