Popular button in the sidebar; the popular list counts everyone

- A Popular button beside + Feed opens the popular list directly; the
  Add feed dialog keeps it too.
- The list counts every subscriber, you included. Your own feeds stay on
  it, marked Subscribed, and clicking one opens it. Private feeds and
  feeds inside an OPML are still never listed, for anyone.
- GET /api/popular rows carry `subscribed`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HdTEWQNrzyFULijigkmMn
This commit is contained in:
2026-09-11 14:05:24 +00:00
parent 8b8b48302b
commit c0f4b0bcb2
7 changed files with 54 additions and 16 deletions

View File

@@ -373,6 +373,7 @@ input[type=range]::-moz-range-thumb{width:12px;height:12px;border:0;border-radiu
</div>
<div class="sidetools">
<button id="addFeed">+ Feed</button>
<button id="popularFeeds" title="What everyone on this server subscribes to">Popular</button>
<button id="scanAll">Scan all</button>
</div>
<div class="searchwrap"><input type="search" id="feedFilter" placeholder="Filter feeds…"></div>
@@ -1161,20 +1162,22 @@ $('#addFeed').onclick=()=>{
};
};
// What other people here read, as a place to start. The rows carry an id, never a URL, so a
// key in someone's feed address never reaches this page.
// What everyone here reads, you included, as a place to start. The rows carry an id, never a
// URL, so a key in someone's feed address never reaches this page.
async function showPopular(){
const box=$('#popular');
let rows=[];
try{ rows=await api('/api/popular')||[]; }catch{}
box.innerHTML=rows.length?'':'<p class="hint">Nothing yet. Feeds other people here subscribe to show up here.</p>';
box.innerHTML=rows.length?'':'<p class="hint">Nothing yet. Feeds people here subscribe to show up here.</p>';
for(const p of rows){
const el=document.createElement('div');
el.className='childrow';
el.innerHTML=artHTML(p.image,p.title||p.id)+
`<div class="txt"><b>${esc(p.title||p.id)}</b>`+
`<small class="meta">${p.subscribers} subscriber${p.subscribers===1?'':'s'}</small></div>`+
`<button class="btn" data-a="sub">Subscribe</button>`;
(p.subscribed?'<span class="tag">Subscribed</span>':'<button class="btn" data-a="sub">Subscribe</button>');
// Yours already: the row opens it instead.
if(p.subscribed){ el.onclick=()=>{ closeModal(); selectFeed(p.id); }; box.appendChild(el); continue; }
$('[data-a="sub"]',el).onclick=async()=>{
try{
await api(`/api/popular/${encodeURIComponent(p.id)}`,{method:'POST'});
@@ -1186,6 +1189,15 @@ async function showPopular(){
}
}
$('#popularFeeds').onclick=()=>{
openModal(`<h3>Popular on this server</h3>
<p class="hint" style="margin:-6px 0 12px">What everyone here subscribes to, you included, most
subscribers first. Feeds inside an OPML subscription, and private feeds, are never listed.</p>
<div class="childlist" id="popular"><p class="hint">Loading…</p></div>
<div class="cardacts"><button class="btn" onclick="closeModal()">Close</button></div>`);
showPopular();
};
let expanded = new Set(JSON.parse(localStorage.getItem('ipx.expanded')||'[]'));
function toggleGroup(id){
expanded.has(id) ? expanded.delete(id) : expanded.add(id);