import Link from "next/link"; import { Progress } from "yt-dlp-transcript-common/components/ui/progress"; import type { FlowStation as Station, StationOperation, } from "yt-dlp-transcript-common/views/pipeline/channelFlow"; // THE SPLIT MATTERS HERE. This is a SERVER component, and StateBand.tsx is // `"use client"` — a plain function exported from a client module cannot be // CALLED from the server ("attempted to call bandSentence() from the server"), // only rendered as a component. So the readings come from band.ts, which // carries no directive, and only the component itself comes from StateBand. import { bandHeadline, bandSentence, } from "yt-dlp-transcript-common/views/pipeline/band"; import { StateBand } from "../../../../components/pipelines/StateBand"; import { formatCount, formatCoverage, STATION_DOT } from "yt-dlp-transcript-common/views/pipeline/tone"; // One station on the line, emitted as THREE siblings so the parent grid can put // every dot on the same horizontal rule regardless of how tall the labels above // them are. See ChannelLine for the row contract. export function StationHead({ station, slug, }: { station: Station; slug: string; }) { return ( {/* The house eyebrow, tightened one step. */} {station.label} {/* The only large numeral the page is allowed. ~3:1 against the 10px eyebrow is what makes the line scannable from across the room. */} {formatCount(station.through)} ); } export function StationRail({ station }: { station: Station }) { return (
); } export function StationFoot({ station }: { station: Station }) { return (

{station.denominator == null && station.coverage == null ? // Not "0%". A third of the snapshots on disk predate the denominator // this would divide by, and inventing one is how a fully digested // channel comes to read as empty. "—" : `${formatCoverage(station.coverage)} of ${formatCount(station.denominator)}`}

{station.operations.length > 0 ? ( // ONE BAND PER OPERATION, never one bar for the station. // // The station used to draw a single meter over a number that summed // three unrelated pipelines. Its members are three different // populations with two different cost bases, and the only honest picture is // three bands — the same instrument, at the smallest of its three // scales, so a reader coming from /channels or /operations already // knows what the fills mean. station.operations.map((op) => ( 1} /> )) ) : station.coverage != null ? ( // The one station that is not a registry operation — playlist — keeps // the plain meter. // // aria-hidden, and no label: the

above states the same ratio in // words, so the bar is decorative. Naming it " coverage meter" // both announces the number twice AND makes getByLabel(" // coverage") ambiguous, since that matching is by substring.

); } // One pipeline under a station: its name, its band, and the one population that // dominates what is left. // // The name is only drawn when the station holds MORE THAN ONE — under Digest it // would just repeat the station eyebrow a line above. Under Speakers it is the // whole point: three operations were hiding behind one word, and this is where // they are finally listed. function StationPipeline({ operation, named, }: { operation: StationOperation; named: boolean; }) { const sentence = bandSentence(operation.band); return (
{operation.label}: {sentence}. {operation.costBasis}.
); }