From 07f9cd310e68521c291f2a441338dfa2cd3fc51a Mon Sep 17 00:00:00 2001 From: 44r0n7 <44r0n7+gitea@pm.me> Date: Thu, 28 May 2026 16:39:33 -0400 Subject: [PATCH] Add channel number flash overlay and prefetch-based bad-video skip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CH n flash overlay (#ch-flash) fades in/holds/fades out on channel switch - Prefetch state (prefetchNext/prefetchOk) skips known-bad videos at ENDED - Reduce onPErr skip delay 1.2s → 0.4s now that prefetch catches most cases --- vidflow.html | 60 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/vidflow.html b/vidflow.html index 0631a04..d6fb8d9 100644 --- a/vidflow.html +++ b/vidflow.html @@ -72,6 +72,10 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil .gl{position:absolute;top:0;left:0;bottom:0;width:180px;background:linear-gradient(90deg,rgba(6,6,15,.85) 0%,rgba(6,6,15,.4) 50%,transparent 100%);z-index:2;pointer-events:none} #scanlines{position:absolute;inset:0;z-index:3;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 3px,rgba(0,0,0,.055) 3px,rgba(0,0,0,.055) 4px);opacity:.5} #sc{position:absolute;inset:0;z-index:11;display:none} +#ch-flash{position:absolute;inset:0;z-index:12;display:flex;align-items:center;justify-content:center;pointer-events:none;opacity:0} +#ch-flash.active{animation:ch-show 2s ease forwards} +#chf-num{font-family:var(--font-d);font-size:min(13vw,96px);color:var(--accent);letter-spacing:4px;text-shadow:0 0 60px rgba(255,34,0,.6),0 2px 12px rgba(0,0,0,.9)} +@keyframes ch-show{0%{opacity:0}10%{opacity:1}80%{opacity:1}100%{opacity:0}} /* No channel */ #nco{position:absolute;inset:0;z-index:6;display:flex;align-items:center;justify-content:center;background:var(--bg);background-image:radial-gradient(ellipse 70% 50% at 50% 50%,rgba(255,34,0,.07) 0%,transparent 70%)} @@ -353,6 +357,8 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
+ +
@@ -450,7 +456,9 @@ const A = { tickerRaf:null, tickerPos:9999, tcTimer:null, idleTimer:null, tab:'channels', lastActivity:Date.now(), isIdle:false, - popoutWin:null + popoutWin:null, + prefetchNext:null, // video ID last checked by checkNextVid + prefetchOk:true // whether that video is playable (optimistic default) }; const FD = "'Bebas Neue',Impact,'Arial Black',sans-serif"; const DEBUG = false; @@ -534,13 +542,21 @@ function onPState(e){ pb.textContent='⏸'; A.playing=true; updateNP(); startPB(); hideTap(); hideNCO(); try{ window.focus(); }catch(err){} + setTimeout(checkNextVid, 2000); // preflight the next video after player settles } else if(e.data===S.PAUSED){ pb.textContent='▶'; A.playing=false; } else if(e.data===S.CUED||e.data===-1){ // browser blocked autoplay — prompt user to tap pb.textContent='▶'; A.playing=false; showTap(); } else if(e.data===S.ENDED){ - try{ A.player.nextVideo(); }catch(e){} + if(A.prefetchOk === false){ + // Next video known-bad — advance twice to skip over it, then reset + try{ A.player.nextVideo(); A.player.nextVideo(); }catch(e){} + A.prefetchOk = true; + } else { + try{ A.player.nextVideo(); }catch(e){} + } + // Fallback: if player stalls at ENDED (e.g. single-video playlist), restart from beginning setTimeout(()=>{ try{ if(A.player?.getPlayerState?.()===YT.PlayerState.ENDED) A.player.playVideoAt(0); @@ -549,13 +565,15 @@ function onPState(e){ } } -// Player error (private video, geo-blocked, etc.) — wait 1.2s then skip -function onPErr(e){ dbg('onPErr',e?.data); hideLoad(); setTimeout(()=>A.player?.nextVideo?.(),1200); } +// Player error (private video, geo-blocked, deleted, etc.) — skip quickly now that prefetch catches most cases +function onPErr(e){ dbg('onPErr',e?.data); hideLoad(); setTimeout(()=>A.player?.nextVideo?.(),400); } // ── Channel flip static effect ── // Renders a TV-static transition on #sc canvas before switching channels — chNum is 0-indexed channel index function flip(chNum, cb){ const cv=qs('#sc'); + // Show channel number overlay: CSS animation handles fade-in, hold, fade-out (~2s) + const fl=qs('#ch-flash'),fn=qs('#chf-num'); if(fl&&fn){ fn.textContent='CH '+(chNum+1); fl.classList.remove('active'); void fl.offsetWidth; fl.classList.add('active'); } cv.width=window.innerWidth; cv.height=window.innerHeight; cv.style.display='block'; const ctx=cv.getContext('2d'); @@ -569,14 +587,6 @@ function flip(chNum, cb){ d[i]=v;d[i+1]=v;d[i+2]=v;d[i+3]=fade; } ctx.putImageData(img,0,0); - // Briefly flash the channel number in the middle of the static burst - if(f>=4&&f<=15){ - const alpha=1-Math.abs(f-9.5)/9; - ctx.fillStyle=`rgba(255,34,0,${alpha*.92})`; - ctx.font=`bold ${Math.min(cv.width*.13,96)}px ${FD}`; - ctx.textAlign='center'; ctx.textBaseline='middle'; - ctx.fillText('CH '+(chNum+1), cv.width/2, cv.height/2); - } f++; if(f