From 8f5e2749ff2c446572f6d04f1d4886a093cea965 Mon Sep 17 00:00:00 2001 From: rays Date: Thu, 10 Sep 2026 18:42:42 +0000 Subject: [PATCH] Sum a subscription's counts from the feeds it holds An OPML folder has no entries of its own, so its row always showed zero unread however much was waiting inside. Summed from every feed it holds -- not just the ones a filter left showing, so the count doesn't move as you type -- with the badge capped at 999+ so a four-digit number doesn't eat the title beside it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AdXho5tTkjFLeUXKbEjKBh --- PROGRESS.md | 9 +++++++++ web/index.html | 13 ++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 75418e7..ae6cc80 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -56,6 +56,15 @@ and until now nothing set them. --- +## 2026-09-10 — A folder counts what it holds + +An OPML subscription has no entries of its own, so its row always read `0 unread` no matter how much +was waiting inside it. Unread and saved are now summed from the feeds it holds -- from all of them, +not just the ones a search filter left showing, so the number doesn't move as you type. The badge +caps at `999+` (the real figure is in its tooltip); a four-digit count ate the title beside it. + +--- + ## 2026-09-10 — Sidebar alignment The feed list had four different left edges: a row with no children skipped the chevron entirely, so diff --git a/web/index.html b/web/index.html index e852574..e5310aa 100644 --- a/web/index.html +++ b/web/index.html @@ -457,6 +457,13 @@ function renderFeeds(){ } for(const [f,depth] of order){ const kids=shown.filter(c=>c.group===f.id).length; + // A subscription holds no entries itself, so its counts are the sum of what is inside -- + // taken from every feed it holds, not just the ones a filter left showing. + const mine=S.feeds.filter(c=>c.group===f.id); + const sum=k=>mine.reduce((n,c)=>n+(c[k]||0),0); + const [unread,eps,saved]=mine.length + ? [sum('unread'),sum('entries'),sum('downloaded')] + : [f.unread,f.entries,f.downloaded]; const el=document.createElement('div'); el.className='feed'+(S.feed===f.id?' sel':'')+(depth?' child':'')+(kids?' group':''); const open = kids && (expanded.has(f.id) || q); @@ -464,11 +471,11 @@ function renderFeeds(){ `${kids?'▶':''}`+ artHTML(f.image,f.title||f.id)+ `
${esc(f.title||f.id)}`+ - (kids?`${kids} feed${kids===1?'':'s'}${f.unread?` · ${f.unread} unread`:''}` - :`${f.entries} eps · ${f.downloaded} saved`)+ + (mine.length?`${mine.length} feed${mine.length===1?'':'s'} · ${saved} saved` + :`${eps} eps · ${saved} saved`)+ `
`+ (f.orphaned?'gone':'')+ - `${f.unread}`; + `${unread>999?'999+':unread}`; el.onclick=()=>{ selectFeed(f.id); $('#sidebar').classList.remove('open'); }; if(kids) $('.chev',el).onclick=ev=>{ ev.stopPropagation(); toggleGroup(f.id); }; list.appendChild(el);