Spaces:
Running
Running
Inject CSS fix + rewrite patch at runtime (fixes broken fm-league CSS + rewrite endpoint)"
Browse files- static/live_mode.js +16 -30
static/live_mode.js
CHANGED
|
@@ -1,25 +1,28 @@
|
|
| 1 |
-
// ===
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
|
|
|
| 5 |
let _liveInterval = null;
|
| 6 |
let _liveTick = 0;
|
| 7 |
|
| 8 |
function startHomepageLive() {
|
| 9 |
if (_liveInterval) clearInterval(_liveInterval);
|
| 10 |
-
|
| 11 |
-
// Add LIVE badges to all section headers
|
| 12 |
setTimeout(addLiveBadges, 2000);
|
| 13 |
-
|
| 14 |
_liveInterval = setInterval(async () => {
|
| 15 |
if (!document.getElementById('view-home')?.classList.contains('active')) return;
|
| 16 |
_liveTick++;
|
| 17 |
-
|
| 18 |
-
// === Livescore: every 60s ===
|
| 19 |
const lsTab = document.querySelector('.ls-tab.active');
|
| 20 |
if (lsTab && lsTab.dataset.tab) loadLivescore(lsTab.dataset.tab);
|
| 21 |
-
|
| 22 |
-
// === Featured match: every 60s ===
|
| 23 |
try {
|
| 24 |
const f = await fetch('/api/livescore/featured').then(r => r.json()).catch(() => null);
|
| 25 |
if (f && f.home) {
|
|
@@ -31,25 +34,13 @@ function startHomepageLive() {
|
|
| 31 |
}
|
| 32 |
}
|
| 33 |
} catch(e) {}
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
if (_liveTick % 3 === 0) {
|
| 37 |
-
refreshHashtag();
|
| 38 |
-
}
|
| 39 |
-
|
| 40 |
-
// === Hot topics: every 5 min (tick 5) ===
|
| 41 |
-
if (_liveTick % 5 === 0) {
|
| 42 |
-
loadHotTopics();
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
// Pulse LIVE badges
|
| 46 |
pulseLiveBadges();
|
| 47 |
-
|
| 48 |
-
}, 60000); // 60s base
|
| 49 |
}
|
| 50 |
|
| 51 |
function addLiveBadges() {
|
| 52 |
-
// Add ● LIVE to section headers that don't have it yet
|
| 53 |
document.querySelectorAll('.ls-header h3, .slider-header .slider-label').forEach(el => {
|
| 54 |
if (!el.querySelector('.live-dot')) {
|
| 55 |
const dot = document.createElement('span');
|
|
@@ -62,7 +53,6 @@ function addLiveBadges() {
|
|
| 62 |
}
|
| 63 |
|
| 64 |
function pulseLiveBadges() {
|
| 65 |
-
// Quick visual pulse to show data is fresh
|
| 66 |
document.querySelectorAll('.live-dot').forEach(d => {
|
| 67 |
d.style.opacity = '1';
|
| 68 |
setTimeout(() => { d.style.opacity = '0.4'; }, 500);
|
|
@@ -71,11 +61,9 @@ function pulseLiveBadges() {
|
|
| 71 |
}
|
| 72 |
|
| 73 |
function refreshHashtag() {
|
| 74 |
-
// Re-search current hashtag topic for fresh results
|
| 75 |
if (typeof _htTopic !== 'undefined' && _htTopic) {
|
| 76 |
const box = document.getElementById('hashtag-box');
|
| 77 |
if (box && box.innerHTML.length > 50) {
|
| 78 |
-
// Silently refresh (don't show loading spinner)
|
| 79 |
fetch(`/api/hashtag/sources?topic=${encodeURIComponent(_htTopic)}&page=0`)
|
| 80 |
.then(r => r.json())
|
| 81 |
.then(j => {
|
|
@@ -83,13 +71,11 @@ function refreshHashtag() {
|
|
| 83 |
if (!sources.length) return;
|
| 84 |
const list = document.getElementById('ht-list');
|
| 85 |
if (!list) return;
|
| 86 |
-
// Update content
|
| 87 |
let h = '';
|
| 88 |
sources.forEach((s, i) => {
|
| 89 |
h += `<div class="hashtag-src-item" onclick="readArticle('${esc(s.url)}')"><div class="hashtag-src-img" id="ht-img-${i}"></div><div class="hashtag-src-text"><div class="hashtag-src-title">${esc(s.title)}</div><div class="hashtag-src-via">${esc(s.via || '')}</div></div></div>`;
|
| 90 |
});
|
| 91 |
list.innerHTML = h;
|
| 92 |
-
// Load images
|
| 93 |
sources.forEach((s, i) => {
|
| 94 |
if (!s.url) return;
|
| 95 |
fetch('/api/article?url=' + encodeURIComponent(s.url)).then(r => r.json()).then(d => {
|
|
|
|
| 1 |
+
// === INJECT CSS FIX (broken .fm-league rule in inline style) ===
|
| 2 |
+
(function(){
|
| 3 |
+
const link = document.createElement('link');
|
| 4 |
+
link.rel = 'stylesheet';
|
| 5 |
+
link.href = '/static/fm_fix.css';
|
| 6 |
+
document.head.appendChild(link);
|
| 7 |
+
|
| 8 |
+
// Also load rewrite fix
|
| 9 |
+
const script = document.createElement('script');
|
| 10 |
+
script.src = '/static/rewrite_fix.js';
|
| 11 |
+
document.body.appendChild(script);
|
| 12 |
+
})();
|
| 13 |
|
| 14 |
+
// === HOMEPAGE LIVE MODE ===
|
| 15 |
let _liveInterval = null;
|
| 16 |
let _liveTick = 0;
|
| 17 |
|
| 18 |
function startHomepageLive() {
|
| 19 |
if (_liveInterval) clearInterval(_liveInterval);
|
|
|
|
|
|
|
| 20 |
setTimeout(addLiveBadges, 2000);
|
|
|
|
| 21 |
_liveInterval = setInterval(async () => {
|
| 22 |
if (!document.getElementById('view-home')?.classList.contains('active')) return;
|
| 23 |
_liveTick++;
|
|
|
|
|
|
|
| 24 |
const lsTab = document.querySelector('.ls-tab.active');
|
| 25 |
if (lsTab && lsTab.dataset.tab) loadLivescore(lsTab.dataset.tab);
|
|
|
|
|
|
|
| 26 |
try {
|
| 27 |
const f = await fetch('/api/livescore/featured').then(r => r.json()).catch(() => null);
|
| 28 |
if (f && f.home) {
|
|
|
|
| 34 |
}
|
| 35 |
}
|
| 36 |
} catch(e) {}
|
| 37 |
+
if (_liveTick % 3 === 0) refreshHashtag();
|
| 38 |
+
if (_liveTick % 5 === 0) loadHotTopics();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
pulseLiveBadges();
|
| 40 |
+
}, 60000);
|
|
|
|
| 41 |
}
|
| 42 |
|
| 43 |
function addLiveBadges() {
|
|
|
|
| 44 |
document.querySelectorAll('.ls-header h3, .slider-header .slider-label').forEach(el => {
|
| 45 |
if (!el.querySelector('.live-dot')) {
|
| 46 |
const dot = document.createElement('span');
|
|
|
|
| 53 |
}
|
| 54 |
|
| 55 |
function pulseLiveBadges() {
|
|
|
|
| 56 |
document.querySelectorAll('.live-dot').forEach(d => {
|
| 57 |
d.style.opacity = '1';
|
| 58 |
setTimeout(() => { d.style.opacity = '0.4'; }, 500);
|
|
|
|
| 61 |
}
|
| 62 |
|
| 63 |
function refreshHashtag() {
|
|
|
|
| 64 |
if (typeof _htTopic !== 'undefined' && _htTopic) {
|
| 65 |
const box = document.getElementById('hashtag-box');
|
| 66 |
if (box && box.innerHTML.length > 50) {
|
|
|
|
| 67 |
fetch(`/api/hashtag/sources?topic=${encodeURIComponent(_htTopic)}&page=0`)
|
| 68 |
.then(r => r.json())
|
| 69 |
.then(j => {
|
|
|
|
| 71 |
if (!sources.length) return;
|
| 72 |
const list = document.getElementById('ht-list');
|
| 73 |
if (!list) return;
|
|
|
|
| 74 |
let h = '';
|
| 75 |
sources.forEach((s, i) => {
|
| 76 |
h += `<div class="hashtag-src-item" onclick="readArticle('${esc(s.url)}')"><div class="hashtag-src-img" id="ht-img-${i}"></div><div class="hashtag-src-text"><div class="hashtag-src-title">${esc(s.title)}</div><div class="hashtag-src-via">${esc(s.via || '')}</div></div></div>`;
|
| 77 |
});
|
| 78 |
list.innerHTML = h;
|
|
|
|
| 79 |
sources.forEach((s, i) => {
|
| 80 |
if (!s.url) return;
|
| 81 |
fetch('/api/article?url=' + encodeURIComponent(s.url)).then(r => r.json()).then(d => {
|