Spaces:
Running
Running
v6.8: Fix page hang — remove VTV loadHome override (double-load), add cachedFetch to all API calls, debounce loadLivescore, global _homeLoaded guard
Browse files- static/vnews_all.js +36 -37
static/vnews_all.js
CHANGED
|
@@ -26,10 +26,10 @@ function clearApiCache() { _apiCache.clear(); }
|
|
| 26 |
// Updated: Voice selector + speed control + image gallery + auto voice detect
|
| 27 |
|
| 28 |
// === LOAD HOME ===
|
| 29 |
-
|
| 30 |
let _homeLoading = false;
|
| 31 |
async function loadHome(){
|
| 32 |
-
if(_homeLoaded) return; // Already loaded, skip
|
| 33 |
if(_homeLoading) return; // Currently loading, skip
|
| 34 |
_homeLoading = true;
|
| 35 |
// Load critical content first (featured + livescore HTML)
|
|
@@ -70,6 +70,9 @@ async function loadHome(){
|
|
| 70 |
if(ai&&ai.length){h+='<div class="slider-wrap"><div class="slider-header"><span class="slider-label">🤖 Ứng dụng AI</span></div><div class="slider-track">';ai.slice(0,12).forEach(a=>{h+=`<div class="slider-item" onclick="readArticle('${esc(a.link)}')"><div class="slider-thumb">${a.img?`<img src="${a.img}">`:''}</div><div class="slider-title">${esc(a.title)}</div></div>`});h+='</div></div>';}
|
| 71 |
document.getElementById('view-home').innerHTML=h;
|
| 72 |
loadLivescore('today');loadHotTopics();
|
|
|
|
|
|
|
|
|
|
| 73 |
if(_wc2026Data)switchWCTab('news');
|
| 74 |
}
|
| 75 |
|
|
@@ -223,12 +226,18 @@ function renderSecondarySections(){
|
|
| 223 |
|
| 224 |
function interleaveShorts(shorts){const dt=shorts.filter(s=>s.channel==='baodantri7941');const sk=shorts.filter(s=>s.channel==='baosuckhoedoisongboyte');const result=[];let i=0,j=0;while(i<dt.length||j<sk.length){if(i<dt.length)result.push(dt[i++]);if(j<sk.length)result.push(sk[j++]);}return result;}
|
| 225 |
let _htPage=0,_htTopic='';
|
| 226 |
-
async function loadHotTopics(){const j=await
|
| 227 |
function searchTopic(topic){if(!topic){topic=document.getElementById('topic-input')?.value.trim();if(!topic){alert('Nhập chủ đề');return;}}document.getElementById('topic-input').value='';_htTopic=topic;_htPage=0;showHashtagSources(topic,0);}
|
| 228 |
-
async function showHashtagSources(topic,page){const box=document.getElementById('hashtag-box');if(!box)return;if(page===0)box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div class="hashtag-loading"><div class="hashtag-spinner"></div>Đang tìm...</div></div>`;try{const
|
| 229 |
function loadMoreHashtag(){_htPage++;const btn=document.getElementById('ht-more');if(btn){btn.disabled=true;btn.textContent='Đang tải...';}showHashtagSources(_htTopic,_htPage);}
|
| 230 |
async function rewriteHashtag(topic){const btn=event?.target;if(btn){btn.disabled=true;btn.textContent='Đang tổng hợp...';}try{const r=await fetch('/api/topic_post',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({topic})});const j=await r.json();if(!r.ok||j.error)throw new Error(j.error||'Lỗi');toast('✅ Đã đăng Tường AI!');if(btn)btn.textContent='✅ Đăng thành công!';if(j.post)prependWallPost(j.post);}catch(e){toast('❌ '+e.message);if(btn){btn.disabled=false;btn.textContent='🤖 Rewrite AI';}}}
|
| 231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
function bindMatchClicks(el){
|
| 233 |
if(!el) return;
|
| 234 |
// Handle direct <a> clicks inside match-detail (highest priority)
|
|
@@ -522,7 +531,7 @@ fetch('/api/storage_status').then(r=>r.json()).then(j=>{if(!j.persistent){const
|
|
| 522 |
|
| 523 |
function updateMiniEpg(){
|
| 524 |
if(!_currentCh) return;
|
| 525 |
-
|
| 526 |
const progs = d.programs||[];
|
| 527 |
const now = progs.find(p=>p.now);
|
| 528 |
document.getElementById('vtv-mini-epg').textContent = now ? now.time+' '+now.title : (progs[0] ? progs[0].time+' '+progs[0].title : '');
|
|
@@ -864,26 +873,16 @@ fetch('/api/storage_status').then(r=>r.json()).then(j=>{if(!j.persistent){const
|
|
| 864 |
});
|
| 865 |
};
|
| 866 |
|
| 867 |
-
//
|
| 868 |
-
|
| 869 |
-
|
| 870 |
-
window.loadHome
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
| 876 |
-
|
| 877 |
-
try{
|
| 878 |
-
pinBlock();
|
| 879 |
-
// Inject MyTV section after VTV block
|
| 880 |
-
setTimeout(()=>{ try{ injectMyTVBlock(); }catch(e){ console.warn('MyTV inject error:', e); } }, 500);
|
| 881 |
-
setTimeout(()=>{ try{ injectMyTVBlock(); }catch(e){} }, 2000);
|
| 882 |
-
}catch(e){ console.warn('VTV pinBlock error:', e); }
|
| 883 |
-
return r;
|
| 884 |
-
};
|
| 885 |
-
window.loadHome.__vtvWrapped = true;
|
| 886 |
-
}
|
| 887 |
})();
|
| 888 |
|
| 889 |
// ===== static/hot_multi.js =====
|
|
@@ -891,7 +890,7 @@ fetch('/api/storage_status').then(r=>r.json()).then(j=>{if(!j.persistent){const
|
|
| 891 |
// This file loaded AFTER app_v2.js, overrides the function
|
| 892 |
|
| 893 |
async function loadHotTopics(){
|
| 894 |
-
const j=await
|
| 895 |
const el=document.getElementById('hot-topics');if(!el)return;
|
| 896 |
const topics=j.topics||[];
|
| 897 |
el.innerHTML=topics.slice(0,18).map(t=>{
|
|
@@ -911,7 +910,7 @@ async function loadMultiHashtag(topicList){
|
|
| 911 |
box.innerHTML=`<div class="hashtag-sources"><h3>🔥 Tin HOT tổng hợp</h3><div class="hashtag-loading"><div class="hashtag-spinner"></div>Tổng hợp từ ${topicList.length} chủ đề nóng nhất...</div></div>`;
|
| 912 |
try{
|
| 913 |
const results=await Promise.all(topicList.map(topic=>
|
| 914 |
-
|
| 915 |
));
|
| 916 |
// Interleave from all topics
|
| 917 |
const all=[];const seen=new Set();
|
|
@@ -932,7 +931,7 @@ async function loadMultiHashtag(topicList){
|
|
| 932 |
h+=`</div></div>`;
|
| 933 |
box.innerHTML=h;
|
| 934 |
// Lazy load images
|
| 935 |
-
all.slice(0,12).forEach((s,i)=>{if(!s.url)return;
|
| 936 |
_htTopic=topicList[0];
|
| 937 |
}catch(e){box.innerHTML=`<div class="hashtag-sources"><h3>🔥 Tin HOT</h3><div style="color:#e74c3c;padding:8px">Lỗi tải tin</div></div>`;}
|
| 938 |
}
|
|
@@ -981,9 +980,9 @@ function startHomepageLive() {
|
|
| 981 |
if (!document.getElementById('view-home')?.classList.contains('active')) return;
|
| 982 |
_liveTick++;
|
| 983 |
const lsTab = document.querySelector('.ls-tab.active');
|
| 984 |
-
|
| 985 |
try {
|
| 986 |
-
const f = await
|
| 987 |
if (f && f.home) {
|
| 988 |
const el = document.querySelector('.featured-match');
|
| 989 |
if (el) {
|
|
@@ -1020,7 +1019,7 @@ function refreshHashtag() {
|
|
| 1020 |
if (typeof _htTopic !== 'undefined' && _htTopic) {
|
| 1021 |
const box = document.getElementById('hashtag-box');
|
| 1022 |
if (box && box.innerHTML.length > 50) {
|
| 1023 |
-
|
| 1024 |
.then(r => r.json())
|
| 1025 |
.then(j => {
|
| 1026 |
const sources = j.sources || [];
|
|
@@ -1034,7 +1033,7 @@ function refreshHashtag() {
|
|
| 1034 |
list.innerHTML = h;
|
| 1035 |
sources.forEach((s, i) => {
|
| 1036 |
if (!s.url) return;
|
| 1037 |
-
|
| 1038 |
if (d && (d.og_image || d.img)) {
|
| 1039 |
const el = document.getElementById('ht-img-' + i);
|
| 1040 |
if (el) el.innerHTML = `<img src="${esc(d.og_image || d.img)}" onerror="this.style.display='none'">`;
|
|
@@ -1104,7 +1103,7 @@ function renderWCNews(el){
|
|
| 1104 |
h+=`<div class="wc-news-item" onclick="readArticle('${esc(a.link)}')"><div class="wc-news-img" id="wcimg-${i}">${a.img?`<img src="${esc(a.img)}" onerror="this.parentElement.innerHTML=''">`:''}</div><div class="wc-news-text">${badge}<div class="wc-news-title">${esc(a.title)}</div><div class="wc-news-via">${esc(a.source||'')}</div></div></div>`;
|
| 1105 |
});
|
| 1106 |
h+='</div>';el.innerHTML=h;
|
| 1107 |
-
combined.slice(0,20).forEach((a,i)=>{if(a.img)return;
|
| 1108 |
}
|
| 1109 |
|
| 1110 |
// === FIXTURES ===
|
|
@@ -1165,8 +1164,8 @@ async function renderWCHighlights(el){
|
|
| 1165 |
try{
|
| 1166 |
// Load both WC and Friendly highlights
|
| 1167 |
const[wc,fr]=await Promise.all([
|
| 1168 |
-
|
| 1169 |
-
|
| 1170 |
]);
|
| 1171 |
// Keep per-league index so the clicked card maps to the correct video in its own league array
|
| 1172 |
const all=[...(wc||[]).map((v,j)=>({...v,_league:'WC',_li:j})),...(fr||[]).map((v,j)=>({...v,_league:'Friendly',_li:j}))];
|
|
@@ -1190,7 +1189,7 @@ function startWCLiveRefresh(){
|
|
| 1190 |
_wcRefreshInterval=setInterval(async()=>{
|
| 1191 |
if(!document.getElementById('view-home')?.classList.contains('active'))return;
|
| 1192 |
try{
|
| 1193 |
-
const data=await
|
| 1194 |
if(data){_wc2026Data=data;const wcEl=document.getElementById('wc-content');if(wcEl){const tab=document.querySelector('.wc-tab.active');if(tab){const t=tab.textContent;if(t.includes('Tin'))renderWCNews(wcEl);else if(t.includes('Lịch'))renderWCFixtures(wcEl);else if(t.includes('BXH'))renderWCStandings(wcEl);else if(t.includes('Thống'))renderWCStats(wcEl);}}}
|
| 1195 |
}catch(e){}
|
| 1196 |
},90000);
|
|
|
|
| 26 |
// Updated: Voice selector + speed control + image gallery + auto voice detect
|
| 27 |
|
| 28 |
// === LOAD HOME ===
|
| 29 |
+
window._homeLoaded = window._homeLoaded || false;
|
| 30 |
let _homeLoading = false;
|
| 31 |
async function loadHome(){
|
| 32 |
+
if(window._homeLoaded) return; // Already loaded, skip
|
| 33 |
if(_homeLoading) return; // Currently loading, skip
|
| 34 |
_homeLoading = true;
|
| 35 |
// Load critical content first (featured + livescore HTML)
|
|
|
|
| 70 |
if(ai&&ai.length){h+='<div class="slider-wrap"><div class="slider-header"><span class="slider-label">🤖 Ứng dụng AI</span></div><div class="slider-track">';ai.slice(0,12).forEach(a=>{h+=`<div class="slider-item" onclick="readArticle('${esc(a.link)}')"><div class="slider-thumb">${a.img?`<img src="${a.img}">`:''}</div><div class="slider-title">${esc(a.title)}</div></div>`});h+='</div></div>';}
|
| 71 |
document.getElementById('view-home').innerHTML=h;
|
| 72 |
loadLivescore('today');loadHotTopics();
|
| 73 |
+
window._homeLoaded = true;
|
| 74 |
+
// Inject VTV block after home loaded
|
| 75 |
+
if(window._vtvInject) window._vtvInject();
|
| 76 |
if(_wc2026Data)switchWCTab('news');
|
| 77 |
}
|
| 78 |
|
|
|
|
| 226 |
|
| 227 |
function interleaveShorts(shorts){const dt=shorts.filter(s=>s.channel==='baodantri7941');const sk=shorts.filter(s=>s.channel==='baosuckhoedoisongboyte');const result=[];let i=0,j=0;while(i<dt.length||j<sk.length){if(i<dt.length)result.push(dt[i++]);if(j<sk.length)result.push(sk[j++]);}return result;}
|
| 228 |
let _htPage=0,_htTopic='';
|
| 229 |
+
async function loadHotTopics(){const j=await cachedFetch('/api/hot_topics', 60000).catch(()=>({topics:[]}));const el=document.getElementById('hot-topics');if(!el)return;el.innerHTML=(j.topics||[]).slice(0,18).map(t=>{const topicText=t.topic||t.label.replace(/^#/,'');return`<button class="hot-chip" onclick="searchTopic('${topicText.replace(/'/g,"\\'")}')">${esc(t.label)}</button>`;}).join('');if(j.topics&&j.topics[0]){const firstTopic=j.topics[0].topic||j.topics[0].label.replace(/^#/,'');setTimeout(()=>searchTopic(firstTopic),800);}}
|
| 230 |
function searchTopic(topic){if(!topic){topic=document.getElementById('topic-input')?.value.trim();if(!topic){alert('Nhập chủ đề');return;}}document.getElementById('topic-input').value='';_htTopic=topic;_htPage=0;showHashtagSources(topic,0);}
|
| 231 |
+
async function showHashtagSources(topic,page){const box=document.getElementById('hashtag-box');if(!box)return;if(page===0)box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div class="hashtag-loading"><div class="hashtag-spinner"></div>Đang tìm...</div></div>`;try{const j=await cachedFetch(`/api/hashtag/sources?topic=${encodeURIComponent(topic)}&page=${page}`, 60000);const sources=j.sources||[];if(!sources.length&&page===0){box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div style="color:#888;padding:8px">Không tìm được bài viết liên quan</div></div>`;return;}let h='';if(page===0)h=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)} <span style="font-size:10px;color:#888">(${j.total} bài từ 8 nguồn)</span></h3><div id="ht-list">`;sources.forEach((s,i)=>{const idx=page*8+i;h+=`<div class="hashtag-src-item" onclick="readArticle('${esc(s.url)}')"><div class="hashtag-src-img" id="ht-img-${idx}"></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>`;});if(page===0){h+=`</div><button class="hashtag-rewrite-btn" onclick="rewriteHashtag('${esc(topic).replace(/'/g,"\\'")}')">🤖 Rewrite AI tổng hợp & đăng tường</button>`;if(j.has_more)h+=`<button class="hashtag-load-more" id="ht-more" onclick="loadMoreHashtag()">Tải thêm ▼</button>`;h+=`</div>`;box.innerHTML=h;}else{document.getElementById('ht-list')?.insertAdjacentHTML('beforeend',h);const btn=document.getElementById('ht-more');if(btn){if(!j.has_more)btn.remove();else{btn.disabled=false;btn.textContent='Tải thêm ▼';}}}sources.forEach((s,i)=>{const idx=page*8+i;if(!s.url)return;cachedFetch('/api/article?url='+encodeURIComponent(s.url), 120000).then(d=>{if(d&&(d.og_image||d.img)){const el=document.getElementById('ht-img-'+idx);if(el)el.innerHTML=`<img src="${esc(d.og_image||d.img)}" onerror="this.style.display='none'">`;}}).catch(()=>{});});}catch(e){box.innerHTML=`<div class="hashtag-sources"><h3>🔍 ${esc(topic)}</h3><div style="color:#e74c3c;padding:8px">Lỗi: ${esc(e.message)}</div></div>`;}}
|
| 232 |
function loadMoreHashtag(){_htPage++;const btn=document.getElementById('ht-more');if(btn){btn.disabled=true;btn.textContent='Đang tải...';}showHashtagSources(_htTopic,_htPage);}
|
| 233 |
async function rewriteHashtag(topic){const btn=event?.target;if(btn){btn.disabled=true;btn.textContent='Đang tổng hợp...';}try{const r=await fetch('/api/topic_post',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({topic})});const j=await r.json();if(!r.ok||j.error)throw new Error(j.error||'Lỗi');toast('✅ Đã đăng Tường AI!');if(btn)btn.textContent='✅ Đăng thành công!';if(j.post)prependWallPost(j.post);}catch(e){toast('❌ '+e.message);if(btn){btn.disabled=false;btn.textContent='🤖 Rewrite AI';}}}
|
| 234 |
+
// Debounce livescore calls
|
| 235 |
+
let _lsLoading = false;
|
| 236 |
+
async function loadLivescore(tab){
|
| 237 |
+
if(_lsLoading) return; // Skip if already loading
|
| 238 |
+
_lsLoading = true;
|
| 239 |
+
setTimeout(()=>{_lsLoading=false;}, 500);
|
| 240 |
+
document.querySelectorAll('.ls-tab').forEach(t=>t.classList.remove('active'));document.querySelector(`.ls-tab[data-tab="${tab}"]`)?.classList.add('active');const el=document.getElementById('ls-content');if(!el)return;el.innerHTML='<div class="loading">Đang tải...</div>';let ep='/api/livescore/'+tab;if(tab.startsWith('bxh_'))ep='/api/livescore/standings/'+tab.replace('bxh_','');try{const d=await cachedFetch(ep, 30000);el.innerHTML=d.html&&d.html.length>50?d.html:'<div class="loading">Không có dữ liệu</div>';bindMatchClicks(el);}catch(e){el.innerHTML='<div class="loading">Lỗi</div>';}}
|
| 241 |
function bindMatchClicks(el){
|
| 242 |
if(!el) return;
|
| 243 |
// Handle direct <a> clicks inside match-detail (highest priority)
|
|
|
|
| 531 |
|
| 532 |
function updateMiniEpg(){
|
| 533 |
if(!_currentCh) return;
|
| 534 |
+
cachedFetch('/api/vtv/epg/'+_currentCh, 60000).then(d=>{
|
| 535 |
const progs = d.programs||[];
|
| 536 |
const now = progs.find(p=>p.now);
|
| 537 |
document.getElementById('vtv-mini-epg').textContent = now ? now.time+' '+now.title : (progs[0] ? progs[0].time+' '+progs[0].title : '');
|
|
|
|
| 873 |
});
|
| 874 |
};
|
| 875 |
|
| 876 |
+
// Inject VTV block AFTER loadHome completes (no override to avoid double-load)
|
| 877 |
+
// Use a one-time listener pattern
|
| 878 |
+
window._vtvInject = function(){
|
| 879 |
+
if(!window._homeLoaded) return; // loadHome not done yet
|
| 880 |
+
pinBlock();
|
| 881 |
+
// Inject MyTV section after VTV block (once)
|
| 882 |
+
if(!_mytvInserted){
|
| 883 |
+
setTimeout(()=>{ try{ injectMyTVBlock(); }catch(e){} }, 500);
|
| 884 |
+
}
|
| 885 |
+
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 886 |
})();
|
| 887 |
|
| 888 |
// ===== static/hot_multi.js =====
|
|
|
|
| 890 |
// This file loaded AFTER app_v2.js, overrides the function
|
| 891 |
|
| 892 |
async function loadHotTopics(){
|
| 893 |
+
const j=await cachedFetch('/api/hot_topics', 60000).catch(()=>({topics:[]}));
|
| 894 |
const el=document.getElementById('hot-topics');if(!el)return;
|
| 895 |
const topics=j.topics||[];
|
| 896 |
el.innerHTML=topics.slice(0,18).map(t=>{
|
|
|
|
| 910 |
box.innerHTML=`<div class="hashtag-sources"><h3>🔥 Tin HOT tổng hợp</h3><div class="hashtag-loading"><div class="hashtag-spinner"></div>Tổng hợp từ ${topicList.length} chủ đề nóng nhất...</div></div>`;
|
| 911 |
try{
|
| 912 |
const results=await Promise.all(topicList.map(topic=>
|
| 913 |
+
cachedFetch(`/api/hashtag/sources?topic=${encodeURIComponent(topic)}&page=0`, 60000).catch(()=>({sources:[]}))
|
| 914 |
));
|
| 915 |
// Interleave from all topics
|
| 916 |
const all=[];const seen=new Set();
|
|
|
|
| 931 |
h+=`</div></div>`;
|
| 932 |
box.innerHTML=h;
|
| 933 |
// Lazy load images
|
| 934 |
+
all.slice(0,12).forEach((s,i)=>{if(!s.url)return;cachedFetch('/api/article?url='+encodeURIComponent(s.url), 120000).then(d=>{if(d&&(d.og_image||d.img)){const el=document.getElementById('ht-img-'+i);if(el)el.innerHTML=`<img src="${esc(d.og_image||d.img)}" onerror="this.style.display='none'">`;}}).catch(()=>{});});
|
| 935 |
_htTopic=topicList[0];
|
| 936 |
}catch(e){box.innerHTML=`<div class="hashtag-sources"><h3>🔥 Tin HOT</h3><div style="color:#e74c3c;padding:8px">Lỗi tải tin</div></div>`;}
|
| 937 |
}
|
|
|
|
| 980 |
if (!document.getElementById('view-home')?.classList.contains('active')) return;
|
| 981 |
_liveTick++;
|
| 982 |
const lsTab = document.querySelector('.ls-tab.active');
|
| 983 |
+
// loadLivescore already called in loadHome, skip to avoid duplicate
|
| 984 |
try {
|
| 985 |
+
const f = await cachedFetch('/api/livescore/featured', 30000).catch(() => null);
|
| 986 |
if (f && f.home) {
|
| 987 |
const el = document.querySelector('.featured-match');
|
| 988 |
if (el) {
|
|
|
|
| 1019 |
if (typeof _htTopic !== 'undefined' && _htTopic) {
|
| 1020 |
const box = document.getElementById('hashtag-box');
|
| 1021 |
if (box && box.innerHTML.length > 50) {
|
| 1022 |
+
cachedFetch(`/api/hashtag/sources?topic=${encodeURIComponent(_htTopic)}&page=0`, 60000)
|
| 1023 |
.then(r => r.json())
|
| 1024 |
.then(j => {
|
| 1025 |
const sources = j.sources || [];
|
|
|
|
| 1033 |
list.innerHTML = h;
|
| 1034 |
sources.forEach((s, i) => {
|
| 1035 |
if (!s.url) return;
|
| 1036 |
+
cachedFetch('/api/article?url=' + encodeURIComponent(s.url), 120000).then(d => {
|
| 1037 |
if (d && (d.og_image || d.img)) {
|
| 1038 |
const el = document.getElementById('ht-img-' + i);
|
| 1039 |
if (el) el.innerHTML = `<img src="${esc(d.og_image || d.img)}" onerror="this.style.display='none'">`;
|
|
|
|
| 1103 |
h+=`<div class="wc-news-item" onclick="readArticle('${esc(a.link)}')"><div class="wc-news-img" id="wcimg-${i}">${a.img?`<img src="${esc(a.img)}" onerror="this.parentElement.innerHTML=''">`:''}</div><div class="wc-news-text">${badge}<div class="wc-news-title">${esc(a.title)}</div><div class="wc-news-via">${esc(a.source||'')}</div></div></div>`;
|
| 1104 |
});
|
| 1105 |
h+='</div>';el.innerHTML=h;
|
| 1106 |
+
combined.slice(0,20).forEach((a,i)=>{if(a.img)return;cachedFetch('/api/article?url='+encodeURIComponent(a.link), 120000).then(d=>{a.img=d.image;return d;}).then(r=>r.json()).then(d=>{if(d&&(d.og_image||d.img)){const x=document.getElementById('wcimg-'+i);if(x)x.innerHTML=`<img src="${esc(d.og_image||d.img)}" onerror="this.parentElement.innerHTML=''">`;}}).catch(()=>{});});
|
| 1107 |
}
|
| 1108 |
|
| 1109 |
// === FIXTURES ===
|
|
|
|
| 1164 |
try{
|
| 1165 |
// Load both WC and Friendly highlights
|
| 1166 |
const[wc,fr]=await Promise.all([
|
| 1167 |
+
cachedFetch('/api/highlights/world-cup', 120000).catch(()=>[]),
|
| 1168 |
+
cachedFetch('/api/highlights/friendly', 120000).catch(()=>[])
|
| 1169 |
]);
|
| 1170 |
// Keep per-league index so the clicked card maps to the correct video in its own league array
|
| 1171 |
const all=[...(wc||[]).map((v,j)=>({...v,_league:'WC',_li:j})),...(fr||[]).map((v,j)=>({...v,_league:'Friendly',_li:j}))];
|
|
|
|
| 1189 |
_wcRefreshInterval=setInterval(async()=>{
|
| 1190 |
if(!document.getElementById('view-home')?.classList.contains('active'))return;
|
| 1191 |
try{
|
| 1192 |
+
const data=await cachedFetch('/api/wc2026', 300000).catch(()=>null);
|
| 1193 |
if(data){_wc2026Data=data;const wcEl=document.getElementById('wc-content');if(wcEl){const tab=document.querySelector('.wc-tab.active');if(tab){const t=tab.textContent;if(t.includes('Tin'))renderWCNews(wcEl);else if(t.includes('Lịch'))renderWCFixtures(wcEl);else if(t.includes('BXH'))renderWCStandings(wcEl);else if(t.includes('Thống'))renderWCStats(wcEl);}}}
|
| 1194 |
}catch(e){}
|
| 1195 |
},90000);
|