feat: Kalender-Ansicht aktualisiert sich live via SSE
Backend: Neuer Event-Typ 'calendar' im Broadcaster. Wird bei Event-CRUD, Serien-Ausnahmen, Freigaben hinzufuegen/entfernen und beim Loeschen ganzer Kalender emittiert. Empfaenger: Eigentuemer + alle User mit CalendarShare auf dem jeweiligen Kalender. Frontend: CalendarView oeffnet beim Mount eine EventSource zu /api/sync/events und reloaded Kalenderliste + Events bei jedem 'calendar'-Event (300ms debounced). Damit sehen beteiligte Nutzer Aenderungen in praktisch Echtzeit - kein F5 mehr noetig. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -260,7 +260,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, reactive, watch } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted, reactive, watch } from 'vue'
|
||||
import { useToast } from 'primevue/usetoast'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import apiClient from '../api/client'
|
||||
@@ -858,9 +858,36 @@ watch(() => eventForm.value.all_day, (allDay) => {
|
||||
eventForm.value.dtend = fix(eventForm.value.dtend)
|
||||
})
|
||||
|
||||
// Live updates via SSE: refresh calendar list + events when anything
|
||||
// relevant changes (own or shared).
|
||||
let eventSource = null
|
||||
let reloadTimer = null
|
||||
|
||||
function scheduleReload() {
|
||||
if (reloadTimer) return
|
||||
reloadTimer = setTimeout(async () => {
|
||||
reloadTimer = null
|
||||
await loadCalendars()
|
||||
refreshEvents()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await loadCalendars()
|
||||
refreshEvents()
|
||||
if (auth.accessToken) {
|
||||
try {
|
||||
eventSource = new EventSource(`/api/sync/events?token=${encodeURIComponent(auth.accessToken)}`)
|
||||
eventSource.addEventListener('calendar', scheduleReload)
|
||||
eventSource.addEventListener('message', scheduleReload)
|
||||
eventSource.onerror = () => { /* auto-reconnects */ }
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (reloadTimer) { clearTimeout(reloadTimer); reloadTimer = null }
|
||||
if (eventSource) { eventSource.close(); eventSource = null }
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user