Spaces:
Running
Running
Remove unused rewrite_fix_v2.js (not loaded in index_v2.html)
Browse files- static/rewrite_fix_v2.js +0 -167
static/rewrite_fix_v2.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* VNEWS Rewrite Fix v2 — OVERRIDES loadHome() with fast non-blocking rendering
|
| 3 |
-
*
|
| 4 |
-
* FIXES:
|
| 5 |
-
* 1. News grid loads FIRST (homepage API returns in ~100ms)
|
| 6 |
-
* 2. All other API calls are non-blocking — render what's available immediately
|
| 7 |
-
* 3. WC2026 (14s) / highlights (5s) / livescore (2s) load in background
|
| 8 |
-
* 4. rewriteUrl() → rewriteSlide() (auto create slides + Short AI)
|
| 9 |
-
* 5. No page reload needed after Short AI creation
|
| 10 |
-
* 6. Share link now includes post_id for slides/video content inline on /s
|
| 11 |
-
*/
|
| 12 |
-
|
| 13 |
-
// ===== OVERRIDE: fast non-blocking loadHome =====
|
| 14 |
-
async function loadHome(){
|
| 15 |
-
const homeEl = document.getElementById('view-home');
|
| 16 |
-
if(!homeEl) return;
|
| 17 |
-
|
| 18 |
-
// Render structure immediately
|
| 19 |
-
homeEl.innerHTML =
|
| 20 |
-
'<div id="home-featured-area"></div>'
|
| 21 |
-
+'<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>'
|
| 22 |
-
+'<div id="hashtag-box"></div>'
|
| 23 |
-
+'<div class="ls-section"><div class="ls-header"><h3>⚽ Livescore</h3></div><div class="ls-tabs"><span class="ls-tab active" data-tab="today" onclick="loadLivescore(\'today\')">📅 Hôm nay</span><span class="ls-tab" data-tab="live" onclick="loadLivescore(\'live\')">🔴 Live</span><span class="ls-tab" data-tab="incoming" onclick="loadLivescore(\'incoming\')">⏰ Sắp tới</span><span class="ls-tab" data-tab="results" onclick="loadLivescore(\'results\')">✅ Kết quả</span><span class="ls-tab" data-tab="bxh_nha" onclick="loadLivescore(\'bxh_nha\')">🏆 NHA</span><span class="ls-tab" data-tab="bxh_laliga" onclick="loadLivescore(\'bxh_laliga\')">🏆 La Liga</span></div><div class="ls-content" id="ls-content"><div class="loading">Đang tải...</div></div></div>'
|
| 24 |
-
// News grid on homepage!
|
| 25 |
-
+'<div id="home-news-grid"><div class="loading" style="padding:8px;font-size:11px">📰 Đang tải tin tức...</div></div>'
|
| 26 |
-
+'<div id="wc2026-live-section" class="wc2026-section" style="display:none"><div class="wc-header"><h2>🏆 World Cup 2026</h2><span class="wc-live-badge">● LIVE</span></div><div class="wc-tabs"><span class="wc-tab active" onclick="switchWCTab(\'news\')">📰 Tin tức</span><span class="wc-tab" onclick="switchWCTab(\'fixtures\')">📅 Lịch thi đấu</span><span class="wc-tab" onclick="switchWCTab(\'standings\')">🏆 BXH</span><span class="wc-tab" onclick="switchWCTab(\'highlights\')">🎬 Highlight</span><span class="wc-tab" onclick="switchWCTab(\'stats\')">📊 Thống kê</span></div><div class="wc-content" id="wc-content"><div class="loading">Đang tải World Cup 2026...</div></div></div>'
|
| 27 |
-
+'<div id="home-after-wc"></div>';
|
| 28 |
-
|
| 29 |
-
const afterEl = homeEl.querySelector('#home-after-wc');
|
| 30 |
-
const newsEl = homeEl.querySelector('#home-news-grid');
|
| 31 |
-
|
| 32 |
-
// 1. FAST: load livescore + hot topics (both < 1s)
|
| 33 |
-
loadLivescore('today');
|
| 34 |
-
loadHotTopics();
|
| 35 |
-
|
| 36 |
-
// 2. FAST: load news grid (homepage API ~108ms) — renders immediately
|
| 37 |
-
(async ()=>{
|
| 38 |
-
try{
|
| 39 |
-
const r = await fetch('/api/homepage');
|
| 40 |
-
const articles = await r.json();
|
| 41 |
-
if(articles && articles.length){
|
| 42 |
-
let h = '<div class="section-title">📰 Tin tức mới nhất</div><div class="grid">';
|
| 43 |
-
articles.slice(0, 20).forEach(a=>{
|
| 44 |
-
const src = a.source||'vne';
|
| 45 |
-
const badge = a.group||a.source||'';
|
| 46 |
-
h+=`<div class="card" onclick="readArticle('${esc(a.link)}')"><div class="card-img">${a.img?`<img src="${_proxyImg(a.img)}" loading="lazy" onerror="this.style.display=\'none\'">`:''}</div><div class="card-body"><span class="badge badge-${src}">${esc(badge)}</span><div class="card-title">${esc(a.title)}</div></div></div>`;
|
| 47 |
-
});
|
| 48 |
-
h+='</div>';
|
| 49 |
-
if(newsEl) newsEl.innerHTML = h;
|
| 50 |
-
} else if(newsEl) newsEl.style.display='none';
|
| 51 |
-
} catch(e){
|
| 52 |
-
if(newsEl) newsEl.innerHTML = '<div style="padding:12px;color:#888;font-size:11px">📰 Nhấn "📰 Tin tức" để xem tin mới</div>';
|
| 53 |
-
}
|
| 54 |
-
})();
|
| 55 |
-
|
| 56 |
-
// 3. BACKGROUND: featured match, wall, highlights, WC2026
|
| 57 |
-
Promise.allSettled([
|
| 58 |
-
_fetchWithTimeout('/api/livescore/featured', 5000),
|
| 59 |
-
_fetchWithTimeout('/api/wall', 5000),
|
| 60 |
-
_fetchWithTimeout('/api/highlights/leagues', 10000),
|
| 61 |
-
_fetchWithTimeout('/api/wc2026', 8000),
|
| 62 |
-
]).then(results => {
|
| 63 |
-
const resultsArr = results.map(r => r.status === 'fulfilled' ? r.value : null);
|
| 64 |
-
const [featuredData, wallData, hlLeagues, wcData] = resultsArr;
|
| 65 |
-
|
| 66 |
-
// Featured match
|
| 67 |
-
if(featuredData && featuredData.home){
|
| 68 |
-
const sc=featuredData.status==='live'?'':'upcoming';
|
| 69 |
-
const st=featuredData.status==='live'?`🔴 ${featuredData.minute||'LIVE'}`:`⏰ ${featuredData.time}`;
|
| 70 |
-
const area=document.getElementById('home-featured-area');
|
| 71 |
-
if(area) area.innerHTML=`<div class="featured-match" onclick="openMatch('${featuredData.event_id}')"><div class="fm-league">${featuredData.league}</div><div class="fm-teams"><div class="fm-team"><img src="${_proxyImg(featuredData.home_logo)}" onerror="this.style.display='none'"><span>${featuredData.home}</span></div><div class="fm-score">${featuredData.score||'VS'}</div><div class="fm-team"><img src="${_proxyImg(featuredData.away_logo)}" onerror="this.style.display='none'"><span>${featuredData.away}</span></div></div><div class="fm-status ${sc}">${st}</div></div>`;
|
| 72 |
-
}
|
| 73 |
-
|
| 74 |
-
_wallPosts = (wallData && wallData.posts) || [];
|
| 75 |
-
_hlLeagueData = hlLeagues || {};
|
| 76 |
-
_wc2026Data = wcData;
|
| 77 |
-
|
| 78 |
-
// Show WC2026 section
|
| 79 |
-
const wcSection = document.getElementById('wc2026-live-section');
|
| 80 |
-
if(wcSection) wcSection.style.display = '';
|
| 81 |
-
if(wcData) switchWCTab('news');
|
| 82 |
-
|
| 83 |
-
_renderWallIn(afterEl);
|
| 84 |
-
_renderHLIn(afterEl);
|
| 85 |
-
});
|
| 86 |
-
}
|
| 87 |
-
|
| 88 |
-
// ===== OVERRIDE rewriteUrl() =====
|
| 89 |
-
async function rewriteUrl(){
|
| 90 |
-
const url = document.getElementById('url-input')?.value.trim();
|
| 91 |
-
if(!url){ alert('Nhập URL bài viết'); return; }
|
| 92 |
-
rewriteSlide(url);
|
| 93 |
-
}
|
| 94 |
-
|
| 95 |
-
// ===== AUTO Short AI + show slides (replaces app_v2.js rewriteSlide) =====
|
| 96 |
-
async function rewriteSlide(url){
|
| 97 |
-
if(!url) return;
|
| 98 |
-
const btn = document.querySelector('.article-actions .primary') || event?.target;
|
| 99 |
-
if(btn){ btn.disabled=true; btn.textContent='⏳ Đang tạo slides...'; }
|
| 100 |
-
toast('⏳ Đang tạo slide rewrite...');
|
| 101 |
-
try{
|
| 102 |
-
const r = await fetch('/api/rewrite_slide',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url})});
|
| 103 |
-
const j = await r.json();
|
| 104 |
-
if(!r.ok||j.error) throw new Error(j.error||'Lỗi');
|
| 105 |
-
toast('✅ Đã tạo slide! Đang tự động tạo Short AI...');
|
| 106 |
-
if(btn) btn.textContent='✅ Đang tạo Short AI...';
|
| 107 |
-
|
| 108 |
-
// Show slides immediately
|
| 109 |
-
if(j.post && j.post.slides && j.post.slides.length){
|
| 110 |
-
showView('view-article');
|
| 111 |
-
const el = document.getElementById('view-article');
|
| 112 |
-
let h = `<button class="back-btn" onclick="switchCat('home')">← Tường AI</button><div class="slide-viewer" style="padding:12px;max-width:600px;margin:0 auto">`;
|
| 113 |
-
j.post.slides.forEach(s=>{
|
| 114 |
-
h += `<div class="slide-card" style="background:#1a1a1a;border:1px solid #2a2a2a;border-radius:12px;padding:16px;margin-bottom:12px"><div class="slide-num" style="color:#5cb87a;font-size:12px;font-weight:700;margin-bottom:6px">Slide ${s.index}/${j.post.slides.length}</div>${
|
| 115 |
-
s.image ? `<img src="${s.image.startsWith('/api/')?s.image:'/api/proxy/img?url='+encodeURIComponent(s.image)}" style="width:100%;max-height:300px;object-fit:cover;border-radius:8px;margin-bottom:8px" loading="lazy" onerror="this.style.display=\'none\'">` : ''}<p style="color:#ddd;font-size:14px;line-height:1.6;margin:0">${esc(s.text)}</p></div>`;
|
| 116 |
-
});
|
| 117 |
-
h += `</div><div style="text-align:center;padding:12px"><div id="short-ai-status" style="color:#888;font-size:12px">⏳ Đang tạo video Short AI...</div></div>`;
|
| 118 |
-
el.innerHTML = h;
|
| 119 |
-
}
|
| 120 |
-
|
| 121 |
-
// Add to wall
|
| 122 |
-
if(j.post) prependWallPost(j.post);
|
| 123 |
-
|
| 124 |
-
// Auto-create Short AI
|
| 125 |
-
const postId = j.post && j.post.id;
|
| 126 |
-
if(postId){
|
| 127 |
-
// Map old voice format to new format
|
| 128 |
-
const voiceMap = {'hoaimy': 'vi-VN-HoaiMyNeural', 'namminh': 'vi-VN-NamMinhNeural', 'andrew': 'en-US-AndrewMultilingualNeural'};
|
| 129 |
-
const voice = voiceMap[j.post.voice] || j.post.voice || 'vi-VN-HoaiMyNeural';
|
| 130 |
-
const emotion = j.post.emotion || 'neutral';
|
| 131 |
-
try{
|
| 132 |
-
const sr = await fetch('/api/ai/short/'+encodeURIComponent(postId),{
|
| 133 |
-
method:'POST',
|
| 134 |
-
headers:{'Content-Type':'application/json'},
|
| 135 |
-
body:JSON.stringify({voice,emotion,speed:1.2})
|
| 136 |
-
});
|
| 137 |
-
const sj = await sr.json();
|
| 138 |
-
if(!sr.ok||sj.error) throw new Error(sj.error||'Lỗi tạo Short AI');
|
| 139 |
-
toast('✅ Short AI đã tạo xong! Xem trong Tường AI.');
|
| 140 |
-
const statusEl = document.getElementById('short-ai-status');
|
| 141 |
-
if(statusEl) statusEl.innerHTML = '✅ Short AI đã sẵn sàng! <button class="primary" onclick="openShortAIFeed(0)" style="background:#2d8659;border:0;color:#fff;padding:6px 12px;border-radius:10px;font-size:11px;cursor:pointer;margin-left:8px">▶ Xem ngay</button>';
|
| 142 |
-
// Update wall card
|
| 143 |
-
if(sj.video && typeof _wallPosts!=='undefined'){
|
| 144 |
-
const p = _wallPosts.find(x => String(x.id) === String(postId));
|
| 145 |
-
if(p){
|
| 146 |
-
p.video = sj.video;
|
| 147 |
-
const itemId = 'wall-item-'+postId;
|
| 148 |
-
const el2 = document.getElementById(itemId);
|
| 149 |
-
if(el2){
|
| 150 |
-
const idx = _wallPosts.indexOf(p);
|
| 151 |
-
el2.insertAdjacentHTML('afterend', makeWallItem(p, idx));
|
| 152 |
-
el2.remove();
|
| 153 |
-
}
|
| 154 |
-
}
|
| 155 |
-
}
|
| 156 |
-
} catch(e2){
|
| 157 |
-
console.log('Auto Short AI failed:', e2.message);
|
| 158 |
-
const statusEl = document.getElementById('short-ai-status');
|
| 159 |
-
if(statusEl) statusEl.innerHTML = '❌ '+e2.message;
|
| 160 |
-
}
|
| 161 |
-
}
|
| 162 |
-
if(btn) btn.textContent='✅ Hoàn tất';
|
| 163 |
-
} catch(e){
|
| 164 |
-
toast('❌ '+e.message);
|
| 165 |
-
if(btn){ btn.disabled=false; btn.textContent='🤖 Slide Rewrite AI'; }
|
| 166 |
-
}
|
| 167 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|