ui: add media type chip group to streams header (Movies/Shows/Music/Live)

Purple-accented chips, ordered Movies → Shows → Music → Live, with
per-index shade variation matching the other chip groups.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gmer4Lfe
2026-05-31 22:02:59 -04:00
co-authored by Claude Sonnet 4.6
parent f0f136f28a
commit 52cc6b4721
2 changed files with 29 additions and 5 deletions
+3 -1
View File
@@ -756,9 +756,11 @@ mark { background: #5d4037; color: #ffcc80; border-radius: 2px; }
.vv-device-sep { color: #2a2a2a; font-size: 12px; margin: 0 2px; user-select: none; }
/* shared chip geometry */
.vv-device-chip,
.vv-chip-device, .vv-chip-res, .vv-chip-codec {
.vv-chip-device, .vv-chip-res, .vv-chip-codec, .vv-chip-mtype {
font-size: 10px; padding: 1px 7px; border-radius: 10px;
white-space: nowrap; border: 1px solid; }
/* media type — purple */
.vv-chip-mtype { color: #9a6abf; background: #1a0d2e; border-color: #3a1e55; }
/* device — blue */
.vv-chip-device { color: #5a9ec8; background: #0d1e2e; border-color: #1c3f5c; }
/* resolution — teal */
+26 -4
View File
@@ -1451,9 +1451,10 @@ function vvRenderStreams() {
// shades[0] = base bg, shades[1] = slightly lighter, cycling per index
function vvChipShade(cls, i) {
const shades = {
'vv-chip-device': ['#0d1e2e', '#112436'],
'vv-chip-res': ['#0b1e1c', '#0e2422'],
'vv-chip-codec': ['#201500', '#261900'],
'vv-chip-device': ['#0d1e2e', '#112436'],
'vv-chip-res': ['#0b1e1c', '#0e2422'],
'vv-chip-codec': ['#201500', '#261900'],
'vv-chip-mtype': ['#1a0d2e', '#1f1136'],
};
const bg = (shades[cls] ?? ['',''])[i % 2];
return bg ? ` style="background:${bg};"` : '';
@@ -1512,6 +1513,27 @@ function vvRenderStreams() {
.join('');
const codecSection = codecBar ? `<span class="vv-device-sep">·</span>${codecBar}` : '';
// Media type summary — Movies, Shows, Music, Live
function vvMediaType(t) {
if (!t) return null;
const lc = t.toLowerCase();
if (lc === 'movie') return 'Movies';
if (lc === 'episode') return 'Shows';
if (lc === 'audio' || lc === 'track' || lc === 'musicvideo') return 'Music';
if (lc === 'livetvprogram' || lc === 'tvchannel' || lc === 'livetv' || lc === 'recording') return 'Live';
return null;
}
const mtypeCounts = {};
sessions.forEach(s => {
const mt = vvMediaType(s.type || '');
if (mt) mtypeCounts[mt] = (mtypeCounts[mt] || 0) + 1;
});
const mtypeOrder = ['Movies', 'Shows', 'Music', 'Live'];
const mtypeBar = mtypeOrder.filter(mt => mtypeCounts[mt])
.map((mt, i) => vvChip('vv-chip-mtype', `${mtypeCounts[mt]} ${mt}`, i))
.join('');
const mtypeSection = mtypeBar ? `<span class="vv-device-sep">·</span>${mtypeBar}` : '';
if (sessions.length === 0) {
el.innerHTML = `<div class="vv-stream-servers">${badges}</div>`
+ '<p class="vv-stream-empty">Nothing playing</p>';
@@ -1571,7 +1593,7 @@ function vvRenderStreams() {
? `<div style="font-size:10px;color:#555;margin-top:4px;">+${sessions.length - 12} more not shown</div>`
: '';
el.innerHTML = `<div class="vv-stream-servers">${badges}${deviceSection}${resSection}${codecSection}</div>
el.innerHTML = `<div class="vv-stream-servers">${badges}${mtypeSection}${deviceSection}${resSection}${codecSection}</div>
<div style="display:flex;gap:10px;">${sCols.map(vvStreamCol).join('')}</div>${overflow}`;
}