feat(playlists): total playtime in header + sticky-header fade fix (E9 S1)
Surface the playlist's total playtime beside the item count in the detail header (12D) — sums every item's duration (formatRuntime "h m", matching the approved mockup), hidden when nothing sums. Data is already client-side; no backend change. Pass fadeTop:false for the playlists page (12B) so the shell's top edge-fade no longer sits over the already-sticky column header (tableHeader.tsx:257), matching the channels/audit pages.
This commit is contained in:
@@ -39,6 +39,7 @@ import { notifyYouTubeActionError } from "../lib/youtubeErrors";
|
||||
import { playlistName } from "../lib/playlistName";
|
||||
import { useUndoable } from "../lib/useUndoable";
|
||||
import { cycleSort, type SortState } from "../lib/columnSort";
|
||||
import { formatRuntime } from "../lib/format";
|
||||
import { applyView, sameOrder } from "../lib/playlistView";
|
||||
const PlayerModal = lazy(() => import("./PlayerModal"));
|
||||
import UndoToolbar from "./UndoToolbar";
|
||||
@@ -259,6 +260,13 @@ export default function Playlists() {
|
||||
return (v: Video) => m.get(v.id) ?? 0;
|
||||
}, [items]);
|
||||
|
||||
// Total playtime of the whole playlist (sums every item, matching the itemCount beside it — not
|
||||
// the filtered `shown` set). Items with an unknown duration count as 0; hidden when nothing sums.
|
||||
const totalSeconds = useMemo(
|
||||
() => items.reduce((acc, v) => acc + (v.duration_seconds ?? 0), 0),
|
||||
[items],
|
||||
);
|
||||
|
||||
const columns = useMemo(
|
||||
() => playlistColumns({ t, indexOf: storedIndex, onPlay, onRemove, canEdit }),
|
||||
[t, storedIndex, onPlay, onRemove, canEdit],
|
||||
@@ -648,6 +656,7 @@ export default function Playlists() {
|
||||
)}
|
||||
<div className="text-xs text-muted mt-0.5">
|
||||
{t("playlists.itemCount", { count: items.length })}
|
||||
{totalSeconds > 0 && ` · ${formatRuntime(totalSeconds)}`}
|
||||
{filterActive && ` · ${t("playlists.filteredCount", { count: shown.length })}`}
|
||||
</div>
|
||||
<div className="flex gap-1.5 mt-3 flex-wrap items-center">
|
||||
|
||||
@@ -94,7 +94,7 @@ export type PageDef = {
|
||||
export const PAGE_CONTENT: Record<Page, PageDef> = {
|
||||
feed: { Component: FeedPage },
|
||||
channels: { Component: Channels, fadeTop: false, maxWidth: "96rem" },
|
||||
playlists: { Component: Playlists, maxWidth: "64rem" },
|
||||
playlists: { Component: Playlists, fadeTop: false, maxWidth: "64rem" },
|
||||
plex: { Component: PlexBrowse, maxWidth: "1600px" },
|
||||
notifications: { Component: NotificationsPanel, maxWidth: "48rem" },
|
||||
messages: { Component: MessagesPage },
|
||||
|
||||
Reference in New Issue
Block a user