Run 2: layout restructure and pop-out overlay
- Bottom bar: two-row layout — ticker above centered controls - Ticker speed halved (0.5px/frame) and longer bottom bar (76px) - Pop-out overlay: shows "PLAYING IN MINI PLAYER" when popup is open - Pop-out re-press: focuses existing popup window instead of opening a new one - Clear overlay and popoutWin ref when video returns from popup Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
+29
-6
@@ -17,7 +17,7 @@
|
|||||||
--accent:#ff2200;--accent2:#00d4ff;--text:#f0f0ff;--dim:#6668a0;
|
--accent:#ff2200;--accent2:#00d4ff;--text:#f0f0ff;--dim:#6668a0;
|
||||||
--font-d:'Bebas Neue',Impact,'Arial Black',sans-serif;
|
--font-d:'Bebas Neue',Impact,'Arial Black',sans-serif;
|
||||||
--font-b:'Rajdhani',sans-serif;
|
--font-b:'Rajdhani',sans-serif;
|
||||||
--top-h:52px;--bot-h:58px;
|
--top-h:52px;--bot-h:76px;
|
||||||
}
|
}
|
||||||
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-family:var(--font-b);color:var(--text);user-select:none;-webkit-tap-highlight-color:transparent}
|
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-family:var(--font-b);color:var(--text);user-select:none;-webkit-tap-highlight-color:transparent}
|
||||||
|
|
||||||
@@ -51,6 +51,11 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil
|
|||||||
/* Player */
|
/* Player */
|
||||||
#pw{position:absolute;inset:0;z-index:0;overflow:hidden;background:#000}
|
#pw{position:absolute;inset:0;z-index:0;overflow:hidden;background:#000}
|
||||||
#pw-cover{position:absolute;inset:0;z-index:1;background:transparent}
|
#pw-cover{position:absolute;inset:0;z-index:1;background:transparent}
|
||||||
|
#po-overlay{position:absolute;inset:0;z-index:3;display:none;align-items:center;justify-content:center;background:rgba(6,6,15,.88)}
|
||||||
|
.po-msg{text-align:center}
|
||||||
|
.po-icon{font-size:52px;margin-bottom:12px;opacity:.7}
|
||||||
|
.po-title{font-family:var(--font-d);font-size:28px;letter-spacing:4px;margin-bottom:8px}
|
||||||
|
.po-sub{font-size:12px;color:var(--dim);letter-spacing:1px}
|
||||||
#pw iframe{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border:none;pointer-events:none}
|
#pw iframe{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);border:none;pointer-events:none}
|
||||||
|
|
||||||
/* Overlays */
|
/* Overlays */
|
||||||
@@ -112,13 +117,15 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil
|
|||||||
#pb-thumb{position:absolute;right:-5px;top:-3px;width:10px;height:10px;background:#fff;border-radius:50%;opacity:0;transition:opacity .15s;pointer-events:none}
|
#pb-thumb{position:absolute;right:-5px;top:-3px;width:10px;height:10px;background:#fff;border-radius:50%;opacity:0;transition:opacity .15s;pointer-events:none}
|
||||||
|
|
||||||
/* Bottom bar */
|
/* Bottom bar */
|
||||||
#bb{position:absolute;bottom:0;left:0;right:0;height:var(--bot-h);z-index:5;display:flex;align-items:center;padding:0 14px;gap:12px}
|
#bb{position:absolute;bottom:0;left:0;right:0;height:var(--bot-h);z-index:5;display:flex;flex-direction:column;justify-content:center;align-items:stretch;padding:5px 14px;gap:2px}
|
||||||
|
.bb-top{display:flex;align-items:center;gap:8px;overflow:hidden}
|
||||||
|
.bb-bot{display:flex;justify-content:center;align-items:center}
|
||||||
.np-lbl{font-family:var(--font-d);font-size:12px;letter-spacing:2.5px;color:var(--accent);flex-shrink:0;display:flex;align-items:center;gap:5px;white-space:nowrap}
|
.np-lbl{font-family:var(--font-d);font-size:12px;letter-spacing:2.5px;color:var(--accent);flex-shrink:0;display:flex;align-items:center;gap:5px;white-space:nowrap}
|
||||||
.np-lbl-dot{width:5px;height:5px;background:var(--accent);border-radius:50%;animation:dot-p 1s ease-in-out infinite}
|
.np-lbl-dot{width:5px;height:5px;background:var(--accent);border-radius:50%;animation:dot-p 1s ease-in-out infinite}
|
||||||
.np-wrap{flex:1;overflow:hidden;height:100%;display:flex;align-items:center;position:relative}
|
.np-wrap{flex:1;overflow:hidden;height:100%;display:flex;align-items:center;position:relative}
|
||||||
#np-ticker{white-space:nowrap;font-size:15px;font-weight:600;letter-spacing:.4px;will-change:transform;position:absolute;left:0;top:50%;transform-origin:left center;margin-top:-10px}
|
#np-ticker{white-space:nowrap;font-size:15px;font-weight:600;letter-spacing:.4px;will-change:transform;position:absolute;left:0;top:50%;transform-origin:left center;margin-top:-10px}
|
||||||
.np-art{color:var(--accent2)}
|
.np-art{color:var(--accent2)}
|
||||||
.ctrls{display:flex;align-items:center;gap:3px;flex-shrink:0}
|
.ctrls{display:flex;align-items:center;gap:3px}
|
||||||
.c-btn{background:rgba(255,255,255,.06);border:1px solid var(--border);color:var(--dim);cursor:pointer;width:34px;height:34px;display:flex;align-items:center;justify-content:center;font-size:15px;transition:.15s}
|
.c-btn{background:rgba(255,255,255,.06);border:1px solid var(--border);color:var(--dim);cursor:pointer;width:34px;height:34px;display:flex;align-items:center;justify-content:center;font-size:15px;transition:.15s}
|
||||||
.c-btn:hover{background:rgba(255,255,255,.12);color:var(--text)}
|
.c-btn:hover{background:rgba(255,255,255,.12);color:var(--text)}
|
||||||
.c-btn.act{background:rgba(0,212,255,.13);border-color:var(--accent2);color:var(--accent2)}
|
.c-btn.act{background:rgba(0,212,255,.13);border-color:var(--accent2);color:var(--accent2)}
|
||||||
@@ -274,6 +281,13 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
|||||||
<!-- ── APP ── -->
|
<!-- ── APP ── -->
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div id="pw"><div id="yt-player"></div><div id="pw-cover"></div></div>
|
<div id="pw"><div id="yt-player"></div><div id="pw-cover"></div></div>
|
||||||
|
<div id="po-overlay">
|
||||||
|
<div class="po-msg">
|
||||||
|
<div class="po-icon">⧉</div>
|
||||||
|
<div class="po-title">PLAYING IN MINI PLAYER</div>
|
||||||
|
<div class="po-sub">Press P to bring it back into focus</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="gt"></div>
|
<div class="gt"></div>
|
||||||
<div class="gb"></div>
|
<div class="gb"></div>
|
||||||
<div class="gr"></div>
|
<div class="gr"></div>
|
||||||
@@ -321,12 +335,15 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="bb">
|
<div id="bb">
|
||||||
|
<div class="bb-top">
|
||||||
<div class="np-lbl"><span class="np-lbl-dot"></span><span>NOW PLAYING</span></div>
|
<div class="np-lbl"><span class="np-lbl-dot"></span><span>NOW PLAYING</span></div>
|
||||||
<div class="np-wrap">
|
<div class="np-wrap">
|
||||||
<div id="np-ticker">
|
<div id="np-ticker">
|
||||||
<span class="np-art" id="npa"></span><span id="npt">Select a channel above to begin</span>
|
<span class="np-art" id="npa"></span><span id="npt">Select a channel above to begin</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bb-bot">
|
||||||
<div class="ctrls">
|
<div class="ctrls">
|
||||||
<button class="c-btn" id="b-prev" title="Previous (←)">⏪</button>
|
<button class="c-btn" id="b-prev" title="Previous (←)">⏪</button>
|
||||||
<button class="c-btn" id="b-play" title="Play / Pause (Space)">▶</button>
|
<button class="c-btn" id="b-play" title="Play / Pause (Space)">▶</button>
|
||||||
@@ -335,6 +352,7 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
|||||||
<button class="c-btn" id="b-sb" title="Channels (C)">☰</button>
|
<button class="c-btn" id="b-sb" title="Channels (C)">☰</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="lo"><div class="ldr"><div class="lb"></div><div class="lb"></div><div class="lb"></div><div class="lb"></div></div></div>
|
<div id="lo"><div class="ldr"><div class="lb"></div><div class="lb"></div><div class="lb"></div><div class="lb"></div></div></div>
|
||||||
<div id="toast"></div>
|
<div id="toast"></div>
|
||||||
@@ -364,7 +382,8 @@ const A = {
|
|||||||
npTimer:null, pbTimer:null,
|
npTimer:null, pbTimer:null,
|
||||||
tickerRaf:null, tickerPos:9999, tcTimer:null, idleTimer:null,
|
tickerRaf:null, tickerPos:9999, tcTimer:null, idleTimer:null,
|
||||||
tab:'channels',
|
tab:'channels',
|
||||||
lastActivity:Date.now(), isIdle:false
|
lastActivity:Date.now(), isIdle:false,
|
||||||
|
popoutWin:null
|
||||||
};
|
};
|
||||||
const FD = "'Bebas Neue',Impact,'Arial Black',sans-serif";
|
const FD = "'Bebas Neue',Impact,'Arial Black',sans-serif";
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
@@ -525,7 +544,7 @@ function showTitleCard(artist, title){
|
|||||||
function tickerLoop(){
|
function tickerLoop(){
|
||||||
const el=qs('#np-ticker'), wrap=qs('.np-wrap');
|
const el=qs('#np-ticker'), wrap=qs('.np-wrap');
|
||||||
if(!el||!wrap){ A.tickerRaf=requestAnimationFrame(tickerLoop); return; }
|
if(!el||!wrap){ A.tickerRaf=requestAnimationFrame(tickerLoop); return; }
|
||||||
A.tickerPos -= 1.0;
|
A.tickerPos -= 0.5;
|
||||||
if(A.tickerPos < -(el.offsetWidth+20)) A.tickerPos = wrap.offsetWidth+20;
|
if(A.tickerPos < -(el.offsetWidth+20)) A.tickerPos = wrap.offsetWidth+20;
|
||||||
el.style.transform=`translateX(${A.tickerPos}px) translateY(-50%)`;
|
el.style.transform=`translateX(${A.tickerPos}px) translateY(-50%)`;
|
||||||
el.style.top='50%';
|
el.style.top='50%';
|
||||||
@@ -959,6 +978,7 @@ setInterval(()=>{
|
|||||||
|
|
||||||
// ── Pop-out transfer ──
|
// ── Pop-out transfer ──
|
||||||
function popOut(){
|
function popOut(){
|
||||||
|
if(A.popoutWin&&!A.popoutWin.closed){ A.popoutWin.focus(); return; }
|
||||||
try{
|
try{
|
||||||
const data=A.player?.getVideoData?.();
|
const data=A.player?.getVideoData?.();
|
||||||
const time=A.player?.getCurrentTime?.();
|
const time=A.player?.getCurrentTime?.();
|
||||||
@@ -967,7 +987,8 @@ function popOut(){
|
|||||||
A.player.pauseVideo();
|
A.player.pauseVideo();
|
||||||
}
|
}
|
||||||
}catch(e){}
|
}catch(e){}
|
||||||
window.open(location.href,'vidflow-mini','popup,width=480,height=270');
|
A.popoutWin=window.open(location.href,'vidflow-mini','popup,width=480,height=270');
|
||||||
|
qs('#po-overlay').style.display='flex';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Popup → on close, write current position back so main window can resume
|
// Popup → on close, write current position back so main window can resume
|
||||||
@@ -991,6 +1012,8 @@ if(!window.opener){
|
|||||||
const t=JSON.parse(e.newValue||'null');
|
const t=JSON.parse(e.newValue||'null');
|
||||||
if(t?.videoId&&t?.from==='popout'&&A.ready){
|
if(t?.videoId&&t?.from==='popout'&&A.ready){
|
||||||
localStorage.removeItem('vf_transfer');
|
localStorage.removeItem('vf_transfer');
|
||||||
|
qs('#po-overlay').style.display='none';
|
||||||
|
A.popoutWin=null;
|
||||||
A.player?.loadVideoById?.({videoId:t.videoId,startSeconds:t.startSeconds||0});
|
A.player?.loadVideoById?.({videoId:t.videoId,startSeconds:t.startSeconds||0});
|
||||||
}
|
}
|
||||||
}catch(err){}
|
}catch(err){}
|
||||||
|
|||||||
Reference in New Issue
Block a user