bep40 commited on
Commit
7a0c951
Β·
verified Β·
1 Parent(s): b597c9f

Add: VTV sticky/fixed mode when scrolling + compact toggle

Browse files
Files changed (1) hide show
  1. static/yt_live.js +83 -6
static/yt_live.js CHANGED
@@ -1,6 +1,7 @@
1
  // === VNEWS β€” VTV1-VTV10 + VTVPrime LIVE CHANNELS ===
2
  // Default channel: VTV6
3
  // Features: PiP button, floating mini-player when reading articles/videos
 
4
 
5
  (function(){
6
  if(window._ytLiveLoaded) return;
@@ -30,11 +31,28 @@
30
  let _streamsLoaded = false;
31
  let _pipActive = false;
32
  let _miniActive = false;
 
33
 
34
  // ===== STYLES =====
35
  const style = document.createElement('style');
36
  style.textContent = `
37
- .vtv-wrap{margin:6px 4px;background:#111;border:1px solid #0066cc;border-radius:10px;overflow:hidden}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  .vtv-head{display:flex;align-items:center;gap:8px;padding:8px 10px;background:linear-gradient(90deg,#003366,#1a1a1a)}
39
  .vtv-title{font-size:13px;font-weight:800;color:#00ccff}
40
  .vtv-badge{font-size:10px;font-weight:800;color:#00ccff;animation:vtvp 1.3s infinite}
@@ -93,6 +111,68 @@
93
  `;
94
  document.head.appendChild(style);
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  // ===== MINI PLAYER =====
97
  function createMiniPlayer(){
98
  if(document.getElementById('vtv-mini')) return;
@@ -133,7 +213,6 @@
133
  }
134
 
135
  function expandFromMini(){
136
- // Close mini player and go home β€” user wants to see full player
137
  closeMiniPlayer();
138
  if(typeof switchCat === 'function') switchCat('home');
139
  }
@@ -299,6 +378,8 @@
299
  if(!h||document.getElementById('vtv-block')) return;
300
  h.insertBefore(buildBlock(), h.firstChild);
301
  _blockInserted = true;
 
 
302
  if(!_streamsLoaded){
303
  loadAllStreams().then(()=>{
304
  setTimeout(()=>window._vtvPlay(DEFAULT_CHANNEL), 300);
@@ -374,7 +455,6 @@
374
  }
375
 
376
  // ===== NAVIGATION HOOKS =====
377
- // Close mini player when returning to home
378
  const _origShowView = window.showView;
379
  window.showView = function(id){
380
  if(id==='view-home' && _miniActive){
@@ -385,7 +465,6 @@
385
  return _origShowView.apply(this, arguments);
386
  };
387
 
388
- // Override readArticle β€” activate mini when leaving home
389
  const _origReadArticle = window.readArticle;
390
  if(_origReadArticle){
391
  window.readArticle = function(url){
@@ -394,12 +473,10 @@
394
  };
395
  }
396
 
397
- // Override switchCat β€” close mini when going to home, activate when leaving
398
  const _origSwitchCat = window.switchCat;
399
  if(_origSwitchCat){
400
  window.switchCat = function(id){
401
  if(id==='home'){
402
- // Returning to home β€” close mini player
403
  if(_miniActive) closeMiniPlayer();
404
  } else if(_currentCh && STREAMS[_currentCh] && STREAMS[_currentCh].length>0 && !_miniActive){
405
  activateMiniPlayer();
 
1
  // === VNEWS β€” VTV1-VTV10 + VTVPrime LIVE CHANNELS ===
2
  // Default channel: VTV6
3
  // Features: PiP button, floating mini-player when reading articles/videos
4
+ // Fixed sticky: VTV stays visible at top when scrolling down
5
 
6
  (function(){
7
  if(window._ytLiveLoaded) return;
 
31
  let _streamsLoaded = false;
32
  let _pipActive = false;
33
  let _miniActive = false;
34
+ let _vtvSticky = false;
35
 
36
  // ===== STYLES =====
37
  const style = document.createElement('style');
38
  style.textContent = `
39
+ /* ===== VTV STICKY / FIXED MODE ===== */
40
+ .vtv-wrap.vtv-sticky{position:sticky;top:0;z-index:48;transition:all .25s ease;box-shadow:0 4px 24px rgba(0,102,204,.35)}
41
+ .vtv-wrap.vtv-sticky .vtv-epg{display:none}
42
+ .vtv-wrap.vtv-sticky .vtv-controls{display:none}
43
+ .vtv-wrap.vtv-sticky .vtv-tabs{padding:3px 8px}
44
+ .vtv-wrap.vtv-sticky .vtv-tab{padding:3px 7px;font-size:8px}
45
+ .vtv-wrap.vtv-sticky .vtv-frame{max-height:140px;min-height:100px}
46
+ .vtv-wrap.vtv-sticky .vtv-frame video{max-height:140px}
47
+ .vtv-wrap.vtv-sticky .vtv-load{height:100px}
48
+ .vtv-wrap.vtv-sticky .vtv-err{height:100px}
49
+ .vtv-wrap.vtv-sticky .vtv-head{padding:5px 10px}
50
+ .vtv-wrap.vtv-sticky .vtv-title{font-size:11px}
51
+ .vtv-wrap.vtv-sticky .vtv-badge{font-size:8px}
52
+ .vtv-sticky-toggle{position:absolute;top:6px;right:8px;z-index:5;background:rgba(0,0,0,.5);border:1px solid #2a3a4a;color:#8ab4d8;font-size:9px;padding:2px 6px;border-radius:4px;cursor:pointer;font-weight:700}
53
+ .vtv-sticky-toggle:hover{background:#0b4a7a;color:#fff}
54
+ .vtv-wrap.vtv-sticky .vtv-sticky-toggle{top:4px;right:6px}
55
+ .vtv-wrap{position:relative;margin:6px 4px;background:#111;border:1px solid #0066cc;border-radius:10px;overflow:hidden}
56
  .vtv-head{display:flex;align-items:center;gap:8px;padding:8px 10px;background:linear-gradient(90deg,#003366,#1a1a1a)}
57
  .vtv-title{font-size:13px;font-weight:800;color:#00ccff}
58
  .vtv-badge{font-size:10px;font-weight:800;color:#00ccff;animation:vtvp 1.3s infinite}
 
111
  `;
112
  document.head.appendChild(style);
113
 
114
+ // ===== STICKY SCROLL DETECTION =====
115
+ function enableStickyVTV(){
116
+ const block = document.getElementById('vtv-block');
117
+ if(!block) return;
118
+ const header = block.querySelector('.vtv-head');
119
+ if(!header) return;
120
+
121
+ // Add sticky toggle button to header
122
+ if(!document.getElementById('vtv-sticky-btn')){
123
+ const btn = document.createElement('button');
124
+ btn.id = 'vtv-sticky-btn';
125
+ btn.className = 'vtv-sticky-toggle';
126
+ btn.textContent = 'πŸ“Œ';
127
+ btn.title = 'Giα»― VTV cα»‘ Δ‘α»‹nh khi cuα»™n';
128
+ btn.onclick = function(e){
129
+ e.stopPropagation();
130
+ _vtvSticky = !_vtvSticky;
131
+ if(_vtvSticky){
132
+ block.classList.add('vtv-sticky');
133
+ btn.textContent = 'πŸ“Œ';
134
+ btn.style.color = '#00ccff';
135
+ btn.style.borderColor = '#00ccff';
136
+ } else {
137
+ block.classList.remove('vtv-sticky');
138
+ btn.textContent = 'πŸ“Œ';
139
+ btn.style.color = '#8ab4d8';
140
+ btn.style.borderColor = '#2a3a4a';
141
+ }
142
+ };
143
+ header.style.position = 'relative';
144
+ header.appendChild(btn);
145
+ }
146
+
147
+ // Auto-sticky: when VTV block scrolls out of view, make it sticky
148
+ let lastScrollY = 0;
149
+ let autoStickyOn = false;
150
+
151
+ window.addEventListener('scroll', function(){
152
+ const scrollY = window.scrollY || window.pageYOffset;
153
+ const blockRect = block.getBoundingClientRect();
154
+ const blockBottom = blockRect.bottom;
155
+
156
+ // If user manually toggled sticky, respect that
157
+ if(_vtvSticky) return;
158
+
159
+ // Auto-detect: if block bottom is above viewport top (scrolled past)
160
+ if(blockBottom < 0 && !autoStickyOn){
161
+ autoStickyOn = true;
162
+ block.classList.add('vtv-sticky');
163
+ const btn = document.getElementById('vtv-sticky-btn');
164
+ if(btn){btn.textContent='πŸ“Œ';btn.style.color='#00ccff';btn.style.borderColor='#00ccff';}
165
+ } else if(blockRect.top >= 0 && autoStickyOn && scrollY < lastScrollY){
166
+ // Scrolled back up to VTV β€” release sticky
167
+ autoStickyOn = false;
168
+ block.classList.remove('vtv-sticky');
169
+ const btn = document.getElementById('vtv-sticky-btn');
170
+ if(btn){btn.textContent='πŸ“Œ';btn.style.color='#8ab4d8';btn.style.borderColor='#2a3a4a';}
171
+ }
172
+ lastScrollY = scrollY;
173
+ }, {passive: true});
174
+ }
175
+
176
  // ===== MINI PLAYER =====
177
  function createMiniPlayer(){
178
  if(document.getElementById('vtv-mini')) return;
 
213
  }
214
 
215
  function expandFromMini(){
 
216
  closeMiniPlayer();
217
  if(typeof switchCat === 'function') switchCat('home');
218
  }
 
378
  if(!h||document.getElementById('vtv-block')) return;
379
  h.insertBefore(buildBlock(), h.firstChild);
380
  _blockInserted = true;
381
+ // Enable sticky behavior after block is inserted
382
+ setTimeout(()=>enableStickyVTV(), 500);
383
  if(!_streamsLoaded){
384
  loadAllStreams().then(()=>{
385
  setTimeout(()=>window._vtvPlay(DEFAULT_CHANNEL), 300);
 
455
  }
456
 
457
  // ===== NAVIGATION HOOKS =====
 
458
  const _origShowView = window.showView;
459
  window.showView = function(id){
460
  if(id==='view-home' && _miniActive){
 
465
  return _origShowView.apply(this, arguments);
466
  };
467
 
 
468
  const _origReadArticle = window.readArticle;
469
  if(_origReadArticle){
470
  window.readArticle = function(url){
 
473
  };
474
  }
475
 
 
476
  const _origSwitchCat = window.switchCat;
477
  if(_origSwitchCat){
478
  window.switchCat = function(id){
479
  if(id==='home'){
 
480
  if(_miniActive) closeMiniPlayer();
481
  } else if(_currentCh && STREAMS[_currentCh] && STREAMS[_currentCh].length>0 && !_miniActive){
482
  activateMiniPlayer();