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:
+39
-16
@@ -17,7 +17,7 @@
|
||||
--accent:#ff2200;--accent2:#00d4ff;--text:#f0f0ff;--dim:#6668a0;
|
||||
--font-d:'Bebas Neue',Impact,'Arial Black',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}
|
||||
|
||||
@@ -51,6 +51,11 @@ html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);font-famil
|
||||
/* Player */
|
||||
#pw{position:absolute;inset:0;z-index:0;overflow:hidden;background:#000}
|
||||
#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}
|
||||
|
||||
/* 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}
|
||||
|
||||
/* 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-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-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)}
|
||||
.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: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)}
|
||||
@@ -274,6 +281,13 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
||||
<!-- ── APP ── -->
|
||||
<div id="app">
|
||||
<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="gb"></div>
|
||||
<div class="gr"></div>
|
||||
@@ -321,18 +335,22 @@ body.idle .gt,body.idle .gb,body.idle .gr,body.idle .gl{opacity:0;transition:opa
|
||||
</div>
|
||||
|
||||
<div id="bb">
|
||||
<div class="np-lbl"><span class="np-lbl-dot"></span><span>NOW PLAYING</span></div>
|
||||
<div class="np-wrap">
|
||||
<div id="np-ticker">
|
||||
<span class="np-art" id="npa"></span><span id="npt">Select a channel above to begin</span>
|
||||
<div class="bb-top">
|
||||
<div class="np-lbl"><span class="np-lbl-dot"></span><span>NOW PLAYING</span></div>
|
||||
<div class="np-wrap">
|
||||
<div id="np-ticker">
|
||||
<span class="np-art" id="npa"></span><span id="npt">Select a channel above to begin</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ctrls">
|
||||
<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-next" title="Next (→)">⏩</button>
|
||||
<button class="c-btn" id="b-shuf" title="Shuffle (S)">⇌</button>
|
||||
<button class="c-btn" id="b-sb" title="Channels (C)">☰</button>
|
||||
<div class="bb-bot">
|
||||
<div class="ctrls">
|
||||
<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-next" title="Next (→)">⏩</button>
|
||||
<button class="c-btn" id="b-shuf" title="Shuffle (S)">⇌</button>
|
||||
<button class="c-btn" id="b-sb" title="Channels (C)">☰</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -364,7 +382,8 @@ const A = {
|
||||
npTimer:null, pbTimer:null,
|
||||
tickerRaf:null, tickerPos:9999, tcTimer:null, idleTimer:null,
|
||||
tab:'channels',
|
||||
lastActivity:Date.now(), isIdle:false
|
||||
lastActivity:Date.now(), isIdle:false,
|
||||
popoutWin:null
|
||||
};
|
||||
const FD = "'Bebas Neue',Impact,'Arial Black',sans-serif";
|
||||
const DEBUG = false;
|
||||
@@ -525,7 +544,7 @@ function showTitleCard(artist, title){
|
||||
function tickerLoop(){
|
||||
const el=qs('#np-ticker'), wrap=qs('.np-wrap');
|
||||
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;
|
||||
el.style.transform=`translateX(${A.tickerPos}px) translateY(-50%)`;
|
||||
el.style.top='50%';
|
||||
@@ -959,6 +978,7 @@ setInterval(()=>{
|
||||
|
||||
// ── Pop-out transfer ──
|
||||
function popOut(){
|
||||
if(A.popoutWin&&!A.popoutWin.closed){ A.popoutWin.focus(); return; }
|
||||
try{
|
||||
const data=A.player?.getVideoData?.();
|
||||
const time=A.player?.getCurrentTime?.();
|
||||
@@ -967,7 +987,8 @@ function popOut(){
|
||||
A.player.pauseVideo();
|
||||
}
|
||||
}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
|
||||
@@ -991,6 +1012,8 @@ if(!window.opener){
|
||||
const t=JSON.parse(e.newValue||'null');
|
||||
if(t?.videoId&&t?.from==='popout'&&A.ready){
|
||||
localStorage.removeItem('vf_transfer');
|
||||
qs('#po-overlay').style.display='none';
|
||||
A.popoutWin=null;
|
||||
A.player?.loadVideoById?.({videoId:t.videoId,startSeconds:t.startSeconds||0});
|
||||
}
|
||||
}catch(err){}
|
||||
|
||||
Reference in New Issue
Block a user