Spaces:
Running
Running
Upload static/auto_update.js
Browse files- static/auto_update.js +85 -0
static/auto_update.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// VNEWS Auto-update Frontend - SSE listener for real-time homepage updates
|
| 2 |
+
(function(){
|
| 3 |
+
let evtSource = null;
|
| 4 |
+
|
| 5 |
+
// Connect to SSE endpoint
|
| 6 |
+
function connectSSE() {
|
| 7 |
+
try {
|
| 8 |
+
evtSource = new EventSource('/api/events');
|
| 9 |
+
evtSource.onmessage = function(e) {
|
| 10 |
+
try {
|
| 11 |
+
const data = JSON.parse(e.data);
|
| 12 |
+
if (data.type === 'new_post' || data.type === 'new_short') {
|
| 13 |
+
console.log('[SSE] Received update:', data.type);
|
| 14 |
+
// Reload wall and re-render short AI
|
| 15 |
+
fetch('/api/ai_wall').then(r => r.json()).then(j => {
|
| 16 |
+
_wallPosts = j.posts || [];
|
| 17 |
+
if (typeof renderShortAISlide === 'function') {
|
| 18 |
+
renderShortAISlide();
|
| 19 |
+
}
|
| 20 |
+
// Update wall on homepage
|
| 21 |
+
const track = document.getElementById('ai-wall-track');
|
| 22 |
+
if (track && _wallPosts.length) {
|
| 23 |
+
track.innerHTML = _wallPosts.slice(0,20).map((p,i) => makeWallItem(p,i)).join('');
|
| 24 |
+
}
|
| 25 |
+
}).catch(() => {});
|
| 26 |
+
}
|
| 27 |
+
} catch(err) {}
|
| 28 |
+
};
|
| 29 |
+
evtSource.onerror = function() {
|
| 30 |
+
evtSource.close();
|
| 31 |
+
setTimeout(connectSSE, 5000); // Reconnect after 5s
|
| 32 |
+
};
|
| 33 |
+
} catch(err) {
|
| 34 |
+
console.log('[SSE] Not supported or error');
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
// Fallback polling (30s) - detects changes even without SSE
|
| 39 |
+
let _lastWallLen = 0;
|
| 40 |
+
function startPolling() {
|
| 41 |
+
setInterval(function(){
|
| 42 |
+
if (typeof _wallPosts === 'undefined') return;
|
| 43 |
+
fetch('/api/ai_wall').then(r => r.json()).then(j => {
|
| 44 |
+
const wall = j.posts || [];
|
| 45 |
+
if (wall.length !== _lastWallLen) {
|
| 46 |
+
console.log('[POLL] Wall changed:', _lastWallLen, '->', wall.length);
|
| 47 |
+
_lastWallLen = wall.length;
|
| 48 |
+
_wallPosts = wall;
|
| 49 |
+
const track = document.getElementById('ai-wall-track');
|
| 50 |
+
if (track && wall.length) {
|
| 51 |
+
track.innerHTML = wall.slice(0,20).map((p,i) => makeWallItem(p,i)).join('');
|
| 52 |
+
}
|
| 53 |
+
if (typeof renderShortAISlide === 'function') {
|
| 54 |
+
renderShortAISlide();
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
}).catch(() => {});
|
| 58 |
+
}, 30000);
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// Start when DOM ready
|
| 62 |
+
if (document.readyState === 'loading') {
|
| 63 |
+
document.addEventListener('DOMContentLoaded', function(){
|
| 64 |
+
connectSSE();
|
| 65 |
+
startPolling();
|
| 66 |
+
});
|
| 67 |
+
} else {
|
| 68 |
+
connectSSE();
|
| 69 |
+
startPolling();
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
// Export for manual trigger
|
| 73 |
+
window.triggerHomepageRefresh = function() {
|
| 74 |
+
fetch('/api/ai_wall').then(r => r.json()).then(j => {
|
| 75 |
+
_wallPosts = j.posts || [];
|
| 76 |
+
if (typeof _renderWallIn === 'function') {
|
| 77 |
+
const afterEl = document.getElementById('home-after-wc');
|
| 78 |
+
if (afterEl) _renderWallIn(afterEl);
|
| 79 |
+
}
|
| 80 |
+
if (typeof renderShortAISlide === 'function') {
|
| 81 |
+
renderShortAISlide();
|
| 82 |
+
}
|
| 83 |
+
});
|
| 84 |
+
};
|
| 85 |
+
})();
|