Spaces:
Running
Running
Update index.html
Browse files- index.html +36 -10
index.html
CHANGED
|
@@ -2859,32 +2859,44 @@ const LN_CAT_LABELS = {
|
|
| 2859 |
sec:'π¨ SEC ACTION', battle:'βοΈ BATTLE', swarm:'π SWARM ALERT',
|
| 2860 |
hot_post:'π₯ TRENDING', evolution:'𧬠EVOLUTION', editorial:'ποΈ EDITORIAL', market_wrap:'π MARKET',
|
| 2861 |
};
|
| 2862 |
-
let lnData = null, lnFilter = 'all', lnStudioIdx = 0, lnStudioTimer = null, lnAutoRefresh = null;
|
| 2863 |
|
| 2864 |
async function loadLiveNews(){
|
| 2865 |
const feedEl = document.getElementById('lnFeed');
|
| 2866 |
const titleEl = document.getElementById('lnFeedTitle');
|
| 2867 |
-
//
|
|
|
|
|
|
|
|
|
|
| 2868 |
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β Fetching...';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2869 |
let r;
|
| 2870 |
try{
|
| 2871 |
-
const resp = await fetch('/api/live-news?hours=24');
|
|
|
|
| 2872 |
if(!resp.ok){
|
| 2873 |
-
// API returned error status
|
| 2874 |
const errText = await resp.text().catch(()=>'');
|
| 2875 |
console.error('Live news API status:', resp.status, errText);
|
| 2876 |
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β API Error ('+resp.status+')';
|
| 2877 |
-
if(feedEl) feedEl.innerHTML = `<div class="ln-no-stories"><div class="big">β οΈ</div><div style="font-size:14px;font-weight:600;color:var(--red)">API Error ${resp.status}</div><div style="font-size:11px;margin-top:6px;color:var(--muted);max-width:400px;word-break:break-all">${esc(errText.substring(0,300))}</div><div style="margin-top:12px"><button class="btn btn-primary" onclick="loadLiveNews()" style="padding:8px 20px;font-size:12px">π Retry</button></div></div>`;
|
| 2878 |
-
|
| 2879 |
return;
|
| 2880 |
}
|
| 2881 |
r = await resp.json();
|
| 2882 |
console.log('Live news loaded:', r.total_stories||0, 'stories', r.error||'');
|
|
|
|
| 2883 |
}catch(e){
|
| 2884 |
-
|
| 2885 |
-
|
| 2886 |
-
|
| 2887 |
-
|
|
|
|
|
|
|
|
|
|
| 2888 |
return;
|
| 2889 |
}
|
| 2890 |
if(!r){renderLiveCounters({});return;}
|
|
@@ -2899,6 +2911,20 @@ async function loadLiveNews(){
|
|
| 2899 |
lnAutoRefresh = setInterval(()=>{if(cTab==='livenews')loadLiveNews();},60000);
|
| 2900 |
}
|
| 2901 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2902 |
function renderLiveBreaking(items){
|
| 2903 |
const bar = document.getElementById('lnBreaking');
|
| 2904 |
const track = document.getElementById('lnBreakTrack');
|
|
|
|
| 2859 |
sec:'π¨ SEC ACTION', battle:'βοΈ BATTLE', swarm:'π SWARM ALERT',
|
| 2860 |
hot_post:'π₯ TRENDING', evolution:'𧬠EVOLUTION', editorial:'ποΈ EDITORIAL', market_wrap:'π MARKET',
|
| 2861 |
};
|
| 2862 |
+
let lnData = null, lnFilter = 'all', lnStudioIdx = 0, lnStudioTimer = null, lnAutoRefresh = null, lnRetryCount = 0;
|
| 2863 |
|
| 2864 |
async function loadLiveNews(){
|
| 2865 |
const feedEl = document.getElementById('lnFeed');
|
| 2866 |
const titleEl = document.getElementById('lnFeedTitle');
|
| 2867 |
+
// Show loading spinner (only on first load or empty state)
|
| 2868 |
+
if(!lnData && feedEl){
|
| 2869 |
+
feedEl.innerHTML = `<div class="ln-no-stories"><div class="big" style="animation:pulse 1.5s infinite">π‘</div><div style="font-size:16px;font-weight:700;margin-bottom:6px">Loading P&D LIVE...</div><div style="font-size:12px;color:var(--muted)">Fetching ${lnRetryCount>0?'(retry '+lnRetryCount+')':''}...</div></div>`;
|
| 2870 |
+
}
|
| 2871 |
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β Fetching...';
|
| 2872 |
+
|
| 2873 |
+
// AbortController with 12s timeout
|
| 2874 |
+
const controller = new AbortController();
|
| 2875 |
+
const timeoutId = setTimeout(()=> controller.abort(), 12000);
|
| 2876 |
+
|
| 2877 |
let r;
|
| 2878 |
try{
|
| 2879 |
+
const resp = await fetch('/api/live-news?hours=24', {signal: controller.signal});
|
| 2880 |
+
clearTimeout(timeoutId);
|
| 2881 |
if(!resp.ok){
|
|
|
|
| 2882 |
const errText = await resp.text().catch(()=>'');
|
| 2883 |
console.error('Live news API status:', resp.status, errText);
|
| 2884 |
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β API Error ('+resp.status+')';
|
| 2885 |
+
if(feedEl && !lnData) feedEl.innerHTML = `<div class="ln-no-stories"><div class="big">β οΈ</div><div style="font-size:14px;font-weight:600;color:var(--red)">API Error ${resp.status}</div><div style="font-size:11px;margin-top:6px;color:var(--muted);max-width:400px;word-break:break-all">${esc(errText.substring(0,300))}</div><div style="margin-top:12px"><button class="btn btn-primary" onclick="loadLiveNews()" style="padding:8px 20px;font-size:12px">π Retry</button></div></div>`;
|
| 2886 |
+
_scheduleLiveRetry();
|
| 2887 |
return;
|
| 2888 |
}
|
| 2889 |
r = await resp.json();
|
| 2890 |
console.log('Live news loaded:', r.total_stories||0, 'stories', r.error||'');
|
| 2891 |
+
lnRetryCount = 0; // Reset on success
|
| 2892 |
}catch(e){
|
| 2893 |
+
clearTimeout(timeoutId);
|
| 2894 |
+
const isTimeout = e.name === 'AbortError';
|
| 2895 |
+
console.error('Live news fetch error:', isTimeout ? 'TIMEOUT (12s)' : e);
|
| 2896 |
+
if(titleEl) titleEl.textContent = isTimeout ? 'π‘ LIVE FEED β Timeout (retrying...)' : 'π‘ LIVE FEED β Connection Error';
|
| 2897 |
+
// Only overwrite feed if we have NO prior data
|
| 2898 |
+
if(feedEl && !lnData) feedEl.innerHTML = `<div class="ln-no-stories"><div class="big">${isTimeout?'β±οΈ':'π‘'}</div><div style="font-size:14px;font-weight:600;color:var(--red)">${isTimeout?'Server is busy β retrying automatically':'Connection failed'}</div><div style="font-size:11px;margin-top:6px;color:var(--muted)">${isTimeout?'The live feed has many queries. Retrying in a few seconds...':esc(String(e))}</div><div style="margin-top:12px"><button class="btn btn-primary" onclick="lnRetryCount=0;loadLiveNews()" style="padding:8px 20px;font-size:12px">π Retry Now</button></div></div>`;
|
| 2899 |
+
_scheduleLiveRetry();
|
| 2900 |
return;
|
| 2901 |
}
|
| 2902 |
if(!r){renderLiveCounters({});return;}
|
|
|
|
| 2911 |
lnAutoRefresh = setInterval(()=>{if(cTab==='livenews')loadLiveNews();},60000);
|
| 2912 |
}
|
| 2913 |
|
| 2914 |
+
function _scheduleLiveRetry(){
|
| 2915 |
+
lnRetryCount++;
|
| 2916 |
+
if(lnRetryCount > 5) {
|
| 2917 |
+
lnRetryCount = 0; // Reset but stop aggressive retry
|
| 2918 |
+
if(lnAutoRefresh) clearInterval(lnAutoRefresh);
|
| 2919 |
+
lnAutoRefresh = setInterval(()=>{if(cTab==='livenews')loadLiveNews();},60000);
|
| 2920 |
+
return;
|
| 2921 |
+
}
|
| 2922 |
+
// Exponential backoff: 3s, 6s, 12s, 20s, 30s
|
| 2923 |
+
const delay = Math.min(3000 * Math.pow(1.8, lnRetryCount - 1), 30000);
|
| 2924 |
+
console.log(`Live news retry #${lnRetryCount} in ${Math.round(delay/1000)}s`);
|
| 2925 |
+
setTimeout(()=>{if(cTab==='livenews')loadLiveNews();}, delay);
|
| 2926 |
+
}
|
| 2927 |
+
|
| 2928 |
function renderLiveBreaking(items){
|
| 2929 |
const bar = document.getElementById('lnBreaking');
|
| 2930 |
const track = document.getElementById('lnBreakTrack');
|