diff --git a/web/static/js/index.js b/web/static/js/index.js index f247e93..c08b1ed 100644 --- a/web/static/js/index.js +++ b/web/static/js/index.js @@ -1,42 +1,105 @@ -(function(){ +(function () { const list = document.getElementById('list'); const filter = document.getElementById('filter'); - function render(data){ - const q = (filter.value||'').toLowerCase(); + // --- wie in stream.js: mögliche Manifest-Dateien ausprobieren --- + async function chooseManifest(name) { + const enc = encodeURIComponent(name); + const candidates = [ + `/hls/${enc}/index.m3u8`, + `/hls/${enc}/main_stream.m3u8`, + ]; + for (const url of candidates) { + try { + const r = await fetch(url, { cache: 'no-store' }); + if (r.ok) return url; + } catch (_) {} + } + return null; + } + + // Kleinster gemeinsamer Nenner: API-Live ODER Manifest erreichbar + const probeCache = new Map(); // vermeidet Doppel-Requests pro Render + + async function probeLive(name) { + if (probeCache.has(name)) return probeCache.get(name); + const p = (async () => { + const url = await chooseManifest(name); + return !!url; + })(); + probeCache.set(name, p); + return p; + } + + function render(data) { + const q = (filter.value || '').toLowerCase(); list.innerHTML = ''; data.items - .filter(it => !q || it.name.toLowerCase().includes(q)) - .forEach(it => { + .filter((it) => !q || it.name.toLowerCase().includes(q)) + .forEach((it) => { const a = document.createElement('a'); a.href = '/' + encodeURIComponent(it.name); a.className = 'card'; + a.dataset.stream = it.name; + + // Grundzustand: was die API sagt + const apiLive = !!it.live; + const pillClass = apiLive ? 'live' : 'off'; + const pillText = apiLive ? 'LIVE' : 'Offline'; + a.innerHTML = `