Skip to content

Commit 9673e9d

Browse files
ralyodioclaude
andcommitted
newtab: show full favorites list (no caps) + live filter box + played ✓; v0.2.8
- removed the 12-item cap on every section; renders all favorites. - added a 'Filter favorites…' search box that live-filters across all sections client-side, with per-section counts. - podcasts show a ✓ when the latest episode is completed (from favorites progress data). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c0bbc1d commit 9673e9d

3 files changed

Lines changed: 46 additions & 11 deletions

File tree

apps/desktop/extensions/ai-sidebar/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "TronBrowser",
4-
"version": "0.2.7",
4+
"version": "0.2.8",
55
"description": "TronBrowser — privacy-first, AI-native. Branded new tab, private search, CoinPay login, and a bring-your-own-keys AI sidebar.",
66
"icons": {
77
"16": "icons/icon-16.png",

apps/desktop/extensions/ai-sidebar/newtab.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ body {
6666
.btr-item .btr-sub { font-size: 10px; text-align: center; line-height: 1.2; color: var(--muted);
6767
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
6868
.btr-item:hover .btr-label { color: var(--cyan); }
69+
.btr-item { position: relative; }
70+
.btr-item .btr-played { position: absolute; top: -4px; right: 8px; width: 18px; height: 18px;
71+
border-radius: 50%; background: #2fd47a; color: #04060c; font-size: 11px; font-weight: 700;
72+
display: grid; place-items: center; }
73+
.btr-filter { width: 100%; max-width: 360px; margin: 10px 0 4px; padding: 8px 12px;
74+
background: var(--panel); color: var(--fg); border: 1px solid var(--line); border-radius: 8px;
75+
font: inherit; }
76+
.btr-filter::placeholder { color: var(--muted); }
77+
#btr-groups { display: flex; flex-direction: column; gap: 14px; margin-top: 8px; }
78+
.btr-group .btr-count { color: var(--muted); font-weight: 400; letter-spacing: 0; }
6979

7080
.tickers { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 8px; }
7181
.tk { background: var(--panel); border: 1px solid var(--line); border-radius: 8px;

apps/desktop/extensions/ai-sidebar/newtab.js

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -253,28 +253,53 @@ async function renderBtr() {
253253
sec.hidden = false;
254254

255255
// Playable tiles carry data-player (open in a modal); the rest link out.
256-
const tile = (player, url, img, ph, label, sub) =>
257-
`<a class="btr-item" ${player ? `href="#" data-player="${escAttr(player)}"` : `href="${escAttr(url)}" target="_blank"`}>` +
256+
// data-label drives the live filter below. ✓ marks already-played items.
257+
const tile = (player, url, img, ph, label, sub, played) =>
258+
`<a class="btr-item" data-label="${escAttr(String(label || '').toLowerCase())}" ${player ? `href="#" data-player="${escAttr(player)}"` : `href="${escAttr(url)}" target="_blank"`}>` +
258259
(img ? `<img src="${escAttr(img)}" alt="" loading="lazy" referrerpolicy="no-referrer" />` : `<span class="btr-ph">${ph}</span>`) +
260+
(played ? '<span class="btr-played" title="Played">✓</span>' : '') +
259261
`<span class="btr-label">${escapeHtml(label)}</span>` +
260262
(sub ? `<span class="btr-sub">${escapeHtml(sub)}</span>` : '') + `</a>`;
261263
const group = (title, items) => items.length
262-
? `<div class="btr-group"><h3>${title}</h3><div class="btr-items">${items.join('')}</div></div>` : '';
264+
? `<div class="btr-group" data-group><h3>${title} <span class="btr-count">${items.length}</span></h3><div class="btr-items">${items.join('')}</div></div>` : '';
263265

264266
if (!tv.length && !radio.length && !pods.length && !movies.length) {
265267
el('btr').innerHTML = '<p class="muted">Connected — add Live TV, radio, podcast or movie favorites on bittorrented.com and they’ll show up here.</p>';
266268
return;
267269
}
270+
const music = movies.filter((m) => m.contentType === 'music');
271+
const books = movies.filter((m) => m.contentType === 'book');
272+
const shows = movies.filter((m) => !['music', 'book'].includes(m.contentType));
273+
// Full list (no caps) + a live client-side filter across every section.
268274
el('btr').innerHTML =
269-
group('Live TV', tv.slice(0, 12).map((c) => tile(c.player, c.url, c.logo, '📺', c.name))) +
270-
group('Podcasts', pods.slice(0, 12).map((p) => {
275+
`<input id="btr-filter" class="btr-filter" type="search" placeholder="Filter favorites…" autocomplete="off" />` +
276+
`<div id="btr-groups">` +
277+
group('Live TV', tv.map((c) => tile(c.player, c.url, c.logo, '📺', c.name))) +
278+
group('Podcasts', pods.map((p) => {
271279
const ep = (p.episodes || [])[0];
272-
return tile(ep?.player, p.url, p.image, '🎙', p.title, ep ? `▶ ${ep.title}` : 'no recent episodes');
280+
const played = !!(ep && ep.progress && ep.progress.completed);
281+
const sub = ep ? (played ? `✓ ${ep.title}` : `▶ ${ep.title}`) : 'no recent episodes';
282+
return tile(ep?.player, p.url, p.image, '🎙', p.title, sub, played);
273283
})) +
274-
group('Radio', radio.slice(0, 12).map((s) => tile(s.player, s.url, s.logo, '📻', s.name))) +
275-
group('Music', movies.filter((m) => m.contentType === 'music').slice(0, 12).map((m) => tile(m.player, m.url, m.poster, '🎵', m.title))) +
276-
group('Books', movies.filter((m) => m.contentType === 'book').slice(0, 12).map((m) => tile(m.player, m.url, m.poster, '📖', m.title))) +
277-
group('Movies & Shows', movies.filter((m) => !['music', 'book'].includes(m.contentType)).slice(0, 12).map((m) => tile(m.player, m.url, m.poster, '🎬', m.title)));
284+
group('Radio', radio.map((s) => tile(s.player, s.url, s.logo, '📻', s.name))) +
285+
group('Music', music.map((m) => tile(m.player, m.url, m.poster, '🎵', m.title))) +
286+
group('Books', books.map((m) => tile(m.player, m.url, m.poster, '📖', m.title))) +
287+
group('Movies & Shows', shows.map((m) => tile(m.player, m.url, m.poster, '🎬', m.title))) +
288+
`</div>`;
289+
290+
const fi = el('btr-filter');
291+
if (fi) fi.addEventListener('input', () => {
292+
const q = fi.value.trim().toLowerCase();
293+
document.querySelectorAll('#btr-groups [data-group]').forEach((g) => {
294+
let any = false;
295+
g.querySelectorAll('.btr-item').forEach((it) => {
296+
const show = !q || (it.getAttribute('data-label') || '').includes(q);
297+
it.style.display = show ? '' : 'none';
298+
if (show) any = true;
299+
});
300+
g.style.display = any ? '' : 'none';
301+
});
302+
});
278303
}
279304

280305
// Open a bittorrented /api/player URL in a themed modal iframe. Append the

0 commit comments

Comments
 (0)