Files
siftlode/frontend/src/features/video/liveWithoutLength.ts
T
peter 5b846136ad fix(catalog): a 24/7 stream archive's years-long length is unknown, not summed or sorted by
YouTube reports a 24/7 stream's archive with the years it has run (prod: 122,962,914 s), and one
such video made the Watch later total read 44,073 hours. A length past a day is now no length
(`Video.length_seconds`, LENGTH_MAX_S): the API sends none, the playlist and channel totals
leave it out and count it as `live_without_length` ("+N live" beside the sum), and the duration
filter, sort and Home budget never match it. Migration 0117 moves the duration sort indexes onto
the length expression. An AST test holds who may still read the raw column.

The migration 0110 test now ends its read before the way down: 0117 builds an index
CONCURRENTLY there, which waited for that open transaction forever.
2026-11-07 02:20:03 +01:00

19 lines
1.1 KiB
TypeScript

// A total of video lengths and the live videos it cannot hold. The server decides what a length is
// (a YouTube "length" past a day is a 24/7 stream's archive reporting the years it has run, and the
// API sends none for it: `catalog.models.LENGTH_MAX_S`), so this side keeps no copy of that limit. It
// only names what a sum left out: a live video — on air, upcoming, a premiere or an archive — with no
// length, as the server's `Video.live_without_length` counts it for the totals it sums itself.
import type { TFunction } from "i18next";
import type { Video } from "../../lib/api/feed";
export function isLiveWithoutLength(v: Pick<Video, "duration_seconds" | "live_status">): boolean {
return v.duration_seconds == null && v.live_status !== "none";
}
/** "12 hr 5 min +2 live": `total` is the formatted sum ("" when nothing summed), `live` the count
* it left out. Empty when both are. */
export function withLiveCount(total: string, live: number, t: TFunction): string {
const suffix = live > 0 ? t("card.liveWithoutLength", { count: live }) : "";
return [total, suffix].filter(Boolean).join(" ");
}