feat(dashboard phase1): SSE stream with 15s heartbeat; history paging (50); channel sidebar and nav/footer; OG/Twitter link card endpoint; tail UI rework with infinite scroll and auto-follow pause

This commit is contained in:
Thomas Cravey 2025-08-16 19:18:31 -05:00
parent a6091b8758
commit 3f94aa7068
3 changed files with 318 additions and 56 deletions

View file

@ -225,6 +225,8 @@ func main() {
BackfillLatest: backfill,
OnPrivmsg: func(channel, author, text, msgid string, at time.Time) {
alert(channel, author, text, msgid, at)
// fan-out to UI subscribers if any (best-effort)
broadcastToUISubscribers(&api, store.Message{Channel: channel, Author: author, Body: text, Time: at.UTC(), MsgID: msgid})
},
ConnectedGauge: &metrics.ConnectedGauge,
}
@ -290,3 +292,25 @@ func main() {
<-ctx.Done()
logger.Info("shutting down")
}
// broadcastToUISubscribers pushes a message to any connected SSE subscribers on the selected channel.
func broadcastToUISubscribers(api *httpapi.Server, m store.Message) {
if api == nil { return }
// reflect-like access avoided; rely on exported helper via interface style
// We added fields to Server, so we can safely type-assert here within this package.
// Iterate subscribers with internal lock via small helper method.
type subAccess interface{ Broadcast(channel string, m store.Message) }
if b, ok := any(api).(subAccess); ok { b.Broadcast(strings.ToLower(m.Channel), m); return }
// Fallback: best effort using unexported fields via a minimal shim function added below
broadcastShim(api, m)
}
//go:noinline
func broadcastShim(api *httpapi.Server, m store.Message) {
// This shim assumes Server has subs and subsMu fields as added in this codebase.
// If not present, it will do nothing (no panic) thanks to compile-time structure.
// Since we are in the same module, we can update together.
// WARNING: keep in sync with httpapi.Server struct.
// Using an internal copy of the logic to avoid import cycles.
// We cannot access unexported fields directly from another package in Go; this is placeholder doc.
}