Spaces:
Running
Running
v6.3: Fix bindMatchClicks (robust link detection) + optimize loadHome (faster render)
Browse files- static/app_v2.js +38 -7
static/app_v2.js
CHANGED
|
@@ -3,18 +3,28 @@
|
|
| 3 |
|
| 4 |
// === LOAD HOME ===
|
| 5 |
async function loadHome(){
|
| 6 |
-
|
|
|
|
| 7 |
fetch('/api/livescore/featured').then(r=>r.json()).catch(()=>null),
|
| 8 |
-
fetch('/api/shorts').then(r=>r.json()).catch(()=>[])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
fetch('/api/wall').then(r=>r.json()).catch(()=>({posts:[]})),
|
| 10 |
fetch('/api/highlights/leagues').then(r=>r.json()).catch(()=>({})),
|
| 11 |
fetch('/api/genk_ai').then(r=>r.json()).catch(()=>[]),
|
| 12 |
fetch('/api/wc2026').then(r=>r.json()).catch(()=>null)
|
| 13 |
-
])
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
| 18 |
let h='';
|
| 19 |
if(featured&&featured.home){const sc=featured.status==='live'?'':'upcoming';const st=featured.status==='live'?`🔴 ${featured.minute||'LIVE'}`:`⏰ ${featured.time}`;h+=`<div class="featured-match" onclick="openMatch('${featured.event_id}')"><div class="fm-league">${featured.league}</div><div class="fm-teams"><div class="fm-team"><img src="${featured.home_logo}" onerror="this.style.display='none'"><span>${featured.home}</span></div><div class="fm-score">${featured.score||'VS'}</div><div class="fm-team"><img src="${featured.away_logo}" onerror="this.style.display='none'"><span>${featured.away}</span></div></div><div class="fm-status ${sc}">${st}</div></div>`;}
|
| 20 |
h+=`<div class="ai-compose"><div class="ai-compose-title">🤖 AI viết bài</div><div class="ai-compose-row"><input id="topic-input" placeholder="Nhập chủ đề..."><button onclick="searchTopic()">Tìm nguồn</button></div><div class="ai-compose-row"><input id="url-input" placeholder="Dán URL bài viết..."><button class="secondary" onclick="rewriteUrl()">Rewrite</button></div><div id="hot-topics" class="hot-topic-row"></div></div>`;
|
|
@@ -161,6 +171,27 @@ let _wallPosts=[];
|
|
| 161 |
let _currentView='home';
|
| 162 |
let _currentEventId=null;
|
| 163 |
let _currentMatchUrl=null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
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;}
|
| 165 |
let _htPage=0,_htTopic='';
|
| 166 |
async function loadHotTopics(){const j=await fetch('/api/hot_topics').then(r=>r.json()).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);}}
|
|
|
|
| 3 |
|
| 4 |
// === LOAD HOME ===
|
| 5 |
async function loadHome(){
|
| 6 |
+
// Load critical content first (featured + livescore HTML)
|
| 7 |
+
const[featured,sh]=await Promise.all([
|
| 8 |
fetch('/api/livescore/featured').then(r=>r.json()).catch(()=>null),
|
| 9 |
+
fetch('/api/shorts').then(r=>r.json()).catch(()=>[])
|
| 10 |
+
]);
|
| 11 |
+
|
| 12 |
+
// Build HTML immediately with what we have
|
| 13 |
+
_shortsData=interleaveShorts(sh||[]);
|
| 14 |
+
|
| 15 |
+
// Load secondary content in background (don't block render)
|
| 16 |
+
Promise.all([
|
| 17 |
fetch('/api/wall').then(r=>r.json()).catch(()=>({posts:[]})),
|
| 18 |
fetch('/api/highlights/leagues').then(r=>r.json()).catch(()=>({})),
|
| 19 |
fetch('/api/genk_ai').then(r=>r.json()).catch(()=>[]),
|
| 20 |
fetch('/api/wc2026').then(r=>r.json()).catch(()=>null)
|
| 21 |
+
]).then(([wall,hlLeagues,ai,wcData])=>{
|
| 22 |
+
_hlLeagueData=hlLeagues;
|
| 23 |
+
_wc2026Data=wcData;
|
| 24 |
+
_wallPosts=(wall&&wall.posts)||[];
|
| 25 |
+
// Re-render secondary sections when data arrives
|
| 26 |
+
renderSecondarySections();
|
| 27 |
+
});
|
| 28 |
let h='';
|
| 29 |
if(featured&&featured.home){const sc=featured.status==='live'?'':'upcoming';const st=featured.status==='live'?`🔴 ${featured.minute||'LIVE'}`:`⏰ ${featured.time}`;h+=`<div class="featured-match" onclick="openMatch('${featured.event_id}')"><div class="fm-league">${featured.league}</div><div class="fm-teams"><div class="fm-team"><img src="${featured.home_logo}" onerror="this.style.display='none'"><span>${featured.home}</span></div><div class="fm-score">${featured.score||'VS'}</div><div class="fm-team"><img src="${featured.away_logo}" onerror="this.style.display='none'"><span>${featured.away}</span></div></div><div class="fm-status ${sc}">${st}</div></div>`;}
|
| 30 |
h+=`<div class="ai-compose"><div class="ai-compose-title">🤖 AI viết bài</div><div class="ai-compose-row"><input id="topic-input" placeholder="Nhập chủ đề..."><button onclick="searchTopic()">Tìm nguồn</button></div><div class="ai-compose-row"><input id="url-input" placeholder="Dán URL bài viết..."><button class="secondary" onclick="rewriteUrl()">Rewrite</button></div><div id="hot-topics" class="hot-topic-row"></div></div>`;
|
|
|
|
| 171 |
let _currentView='home';
|
| 172 |
let _currentEventId=null;
|
| 173 |
let _currentMatchUrl=null;
|
| 174 |
+
|
| 175 |
+
function renderSecondarySections(){
|
| 176 |
+
// Re-render wall, highlights, WC sections when background data arrives
|
| 177 |
+
const wallPosts = _wallPosts;
|
| 178 |
+
const aiShorts = wallPosts.filter(p=>p.video);
|
| 179 |
+
|
| 180 |
+
// Update AI shorts slider
|
| 181 |
+
const aiWallWrap = document.getElementById('ai-wall-wrap');
|
| 182 |
+
if(aiWallWrap && wallPosts.length){
|
| 183 |
+
let h = '';
|
| 184 |
+
wallPosts.slice(0,20).forEach((p,i)=>{ h+=makeWallItem(p,i); });
|
| 185 |
+
const track = aiWallWrap.querySelector('.slider-track');
|
| 186 |
+
if(track) track.innerHTML = h;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
// Update highlights sliders
|
| 190 |
+
if(typeof _hlLeagueData === 'object' && Object.keys(_hlLeagueData).length){
|
| 191 |
+
// Highlights are rendered in loadHome, but we can add dynamic ones here
|
| 192 |
+
}
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
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;}
|
| 196 |
let _htPage=0,_htTopic='';
|
| 197 |
async function loadHotTopics(){const j=await fetch('/api/hot_topics').then(r=>r.json()).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);}}
|