feat(header): clarify video counts and hide idle pause button

Show 'N yours / M total' in the header (your subscriptions vs. the whole shared
catalog) with a tooltip, backed by a new total_videos field on /sync/my-status.
The admin pause button now only appears when there's sync work to pause; Resume
still shows whenever sync is paused.
This commit is contained in:
npeter83 2026-06-14 18:42:55 +02:00
parent 0b37862618
commit f36799ed69
3 changed files with 18 additions and 3 deletions

View file

@ -152,6 +152,9 @@ def my_status(
), ),
) )
) )
# Whole-catalog total (every video any user's subscriptions have pulled in), so the
# header can show "yours" against the shared library size.
total_videos = db.scalar(select(func.count(Video.id)))
return { return {
"channels_total": total, "channels_total": total,
"channels_details_synced": details_synced, "channels_details_synced": details_synced,
@ -163,6 +166,7 @@ def my_status(
"deep_pending_count": deep_eta["channels_pending"], "deep_pending_count": deep_eta["channels_pending"],
"deep_eta_seconds": deep_eta["eta_seconds"], "deep_eta_seconds": deep_eta["eta_seconds"],
"my_videos": my_videos or 0, "my_videos": my_videos or 0,
"total_videos": total_videos or 0,
"quota_used_today": quota.units_used_today(db), "quota_used_today": quota.units_used_today(db),
"quota_remaining_today": quota.remaining_today(db), "quota_remaining_today": quota.remaining_today(db),
"paused": state.is_sync_paused(db), "paused": state.is_sync_paused(db),

View file

@ -34,8 +34,16 @@ export default function SyncStatus({
return ( return (
<div className="hidden lg:flex items-center gap-2 text-xs text-muted"> <div className="hidden lg:flex items-center gap-2 text-xs text-muted">
<Tooltip hint="Videos from your subscriptions, against the total in the shared catalog that every user's subscriptions have pulled in.">
<span className="flex items-center gap-1.5 cursor-default">
<Database className="w-3.5 h-3.5" /> <Database className="w-3.5 h-3.5" />
<span>{formatViews(data.my_videos)} videos</span> <span>
<span className="text-fg font-medium">{formatViews(data.my_videos)}</span> yours
</span>
<span className="opacity-40">/</span>
<span>{formatViews(data.total_videos)} total</span>
</span>
</Tooltip>
<span className="opacity-40">·</span> <span className="opacity-40">·</span>
{data.paused ? ( {data.paused ? (
<span className="text-accent font-medium">paused</span> <span className="text-accent font-medium">paused</span>
@ -61,7 +69,9 @@ export default function SyncStatus({
</Tooltip> </Tooltip>
</> </>
)} )}
{isAdmin && ( {/* Pause only makes sense when there's work to pause; Resume must always show
while paused so it can be lifted. Hidden entirely when idle and not paused. */}
{isAdmin && (data.paused || syncing > 0) && (
<button <button
onClick={() => toggle.mutate()} onClick={() => toggle.mutate()}
disabled={toggle.isPending} disabled={toggle.isPending}

View file

@ -173,6 +173,7 @@ export interface MyStatus {
deep_pending_count: number; deep_pending_count: number;
deep_eta_seconds: number; deep_eta_seconds: number;
my_videos: number; my_videos: number;
total_videos: number;
quota_used_today: number; quota_used_today: number;
quota_remaining_today: number; quota_remaining_today: number;
paused: boolean; paused: boolean;