Channel features: subscribers, new-videos badges, activity-driven sync

- Store subscriber count from YouTube statistics and show it on channel page
- Sync 50 videos per channel with playlistItems pagination support
- Show per-channel and per-category new-videos counters (2-day window)
- Replace hourly videos sync with activity trigger (2h idle) and
  incremental backfill (hard cap 200 per channel)
- Clicking the sidebar new-videos count filters the category feed to
  recent videos only (new_only)
- Update agent-team docs: deploy after green checks
This commit is contained in:
vrubelroman 2026-09-17 21:07:33 +00:00
parent fde9a439df
commit e10df8dcbd
27 changed files with 1420 additions and 107 deletions

View file

@ -33,7 +33,12 @@
.category-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.category-link { gap: 15px; padding-left: 18px; }
.category-link.active .category-dot { background: var(--accent); }
.sidebar-count { margin-left: auto; font-size: 11px; color: var(--subtle); }
.sidebar-category-row { display: flex; align-items: center; gap: 4px; }
.sidebar-category-row .sidebar-link { flex: 1; min-width: 0; }
.sidebar-badge { margin-left: auto; flex: none; padding: 1px 8px; border-radius: 999px; background: rgba(255,107,104,.13); color: var(--error); font-size: 11px; font-weight: 650; line-height: 1.5; white-space: nowrap; }
.sidebar-badge-link { cursor: pointer; text-decoration: none; transition: background .16s; }
.sidebar-badge-link:hover { background: rgba(255,107,104,.26); }
.sidebar-badge-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sidebar-add { color: var(--accent); font-size: 13px; margin-top: 4px; }
.sidebar-hint { margin: 0; padding: 5px 13px 9px; color: var(--subtle); font-size: 12px; }
.sidebar-bottom { margin-top: auto; padding-bottom: 0; }
@ -46,6 +51,8 @@ h1, h2, h3, p { margin-top: 0; }
h1 { color: var(--text); font-size: clamp(25px, 2.25vw, 34px); line-height: 1.18; letter-spacing: -.035em; font-weight: 700; margin-bottom: 8px; }
h2 { color: var(--text); font-size: 18px; line-height: 1.3; font-weight: 650; }
.page-subtitle { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.5; }
.page-subtitle a { color: var(--accent); text-decoration: none; font-weight: 650; }
.page-subtitle a:hover { text-decoration: underline; }
button, .button-primary, .button-secondary, .button-quiet, .button-danger, .button-link { transition: background .16s, color .16s, border-color .16s; }
.button-primary, .button-secondary, .button-danger, .button-link { min-height: 42px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: 8px; padding: 0 15px; text-decoration: none; font-size: 13px; font-weight: 650; white-space: nowrap; }
.button-primary { border: 1px solid var(--accent); background: var(--accent); color: #081521; }
@ -125,6 +132,7 @@ button, .button-primary, .button-secondary, .button-quiet, .button-danger, .butt
.channel-title { font-size: 15px; font-weight: 650; text-decoration: none; }
.channel-title:hover { color: var(--accent); }
.badge { font-size: 11px; color: var(--subtle); }
.badge-new { padding: 2px 8px; border-radius: 999px; background: rgba(255,107,104,.13); color: var(--error); font-weight: 650; white-space: nowrap; }
.unsubscribe-button { margin-left: auto; min-height: 28px; border: 0; border-radius: 6px; padding: 0 8px; color: var(--subtle); background: transparent; font-size: 11px; }
.unsubscribe-button:hover { color: var(--error); background: rgba(255,107,104,.1); }
.channel-categories { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
@ -271,7 +279,8 @@ button, .button-primary, .button-secondary, .button-quiet, .button-danger, .butt
}
@media (min-width: 621px) and (max-width: 699px) { .video-grid { grid-template-columns: 1fr; } }
@media (pointer: coarse) {
.video-actions .button-link, .video-actions .button-secondary, .download-badge, .category-nav button, .local-filter-nav a, .mobile-category-nav a, .chip, .chip-edit, .category-checkbox, .unsubscribe-button { min-height: 44px; }
.video-actions .button-link, .video-actions .button-secondary, .download-badge, .category-nav button, .local-filter-nav a, .mobile-category-nav a, .chip, .chip-edit, .category-checkbox, .unsubscribe-button, .sidebar-badge { min-height: 44px; }
.sidebar-badge { display: inline-flex; align-items: center; }
.reorder-buttons .icon-button { width: 40px; height: 40px; }
.popover-create input, .popover-create button { height: 44px; }
.popover-create button { width: 44px; }