Add event bus for live UI updates
Introduces a system for broadcasting real-time events to the web UI. This enables features like automatic page reloads when case data changes in the background, improving the user experience by keeping the UI synchronized with the backend. Key components: - `events` module: Contains the `CaseEventKind` enum, `CaseEvent` struct, and `EventSender` type for managing the broadcast channel. - SSE endpoint (`/web/events`): Streams events to connected browsers. - Client-side JavaScript: Listens for events and triggers debounced page reloads. - Integration points: Workers and route handlers now emit events when relevant state changes occur.
This commit is contained in:
@@ -245,6 +245,42 @@ try {
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
// Live-update bus with audio-playback protection: only events for THIS
|
||||
// case trigger a reload, and if any audio is currently playing, show a
|
||||
// dismissible "Updates verfügbar"-banner instead of interrupting playback.
|
||||
// The `.play.is-pause` class is set by the player script above while audio
|
||||
// plays, so we can probe it via DOM selector without extra wiring.
|
||||
(() => {
|
||||
const MY_CASE_ID = "{{ case_id }}";
|
||||
let timer = null;
|
||||
const anyAudioPlaying = () => !!document.querySelector('.player .play.is-pause');
|
||||
const showBanner = () => {
|
||||
if (document.getElementById('update-banner')) return;
|
||||
const b = document.createElement('button');
|
||||
b.id = 'update-banner';
|
||||
b.type = 'button';
|
||||
b.textContent = '\u21bb Aktualisierungen verf\u00fcgbar \u2014 neu laden';
|
||||
b.style.cssText = 'position:fixed;bottom:1em;right:1em;z-index:9999;'
|
||||
+ 'padding:0.6em 1em;background:#fff3cd;border:1px solid #d39e00;'
|
||||
+ 'border-radius:4px;cursor:pointer;font-family:inherit;';
|
||||
b.addEventListener('click', () => location.reload());
|
||||
document.body.appendChild(b);
|
||||
};
|
||||
const scheduleReload = () => {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
if (anyAudioPlaying()) showBanner();
|
||||
else location.reload();
|
||||
}, 300);
|
||||
};
|
||||
const es = new EventSource('/web/events');
|
||||
es.addEventListener('case', (msg) => {
|
||||
let evt;
|
||||
try { evt = JSON.parse(msg.data); } catch (_) { return; }
|
||||
if (evt.case_id === MY_CASE_ID) scheduleReload();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user