talas-group/talas-wiki/internal/wiki/ws.go
senke 66471934af Initial commit: Talas Group project management & documentation
Knowledge base of ~80+ markdown files across 14 domains (00-13),
Logseq graph, hardware design files (KiCAD), infrastructure configs,
and talas-wiki static site.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 20:10:41 +02:00

109 lines
2.1 KiB
Go

package wiki
import (
"net/http"
"sync"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
type WSHub struct {
mu sync.RWMutex
clients map[*websocket.Conn]string // conn → page path being viewed
}
func NewWSHub() *WSHub {
return &WSHub{clients: make(map[*websocket.Conn]string)}
}
func (h *WSHub) HandleWS(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
pagePath := r.URL.Query().Get("page")
h.mu.Lock()
h.clients[conn] = pagePath
h.mu.Unlock()
// Read loop (keeps connection alive, handles page changes)
defer func() {
h.mu.Lock()
delete(h.clients, conn)
h.mu.Unlock()
conn.Close()
}()
for {
_, msg, err := conn.ReadMessage()
if err != nil {
break
}
// Client can update which page they're viewing
h.mu.Lock()
h.clients[conn] = string(msg)
h.mu.Unlock()
}
}
// NotifyPageChange sends a reload message to all clients viewing the given page
func (h *WSHub) NotifyPageChange(pagePath string) {
h.mu.RLock()
defer h.mu.RUnlock()
for conn, viewing := range h.clients {
if viewing == pagePath || viewing == "" {
conn.WriteJSON(map[string]string{
"type": "reload",
"page": pagePath,
})
}
}
}
// NotifyAll sends a message to all connected clients
func (h *WSHub) NotifyAll(msgType string, data string) {
h.mu.RLock()
defer h.mu.RUnlock()
for conn := range h.clients {
conn.WriteJSON(map[string]string{
"type": msgType,
"data": data,
})
}
}
// GetPresence returns a map of page paths to viewer counts
func (h *WSHub) GetPresence() map[string]int {
h.mu.RLock()
defer h.mu.RUnlock()
presence := make(map[string]int)
for _, page := range h.clients {
if page != "" {
presence[page]++
}
}
return presence
}
// GetViewerCount returns how many users are viewing a specific page
func (h *WSHub) GetViewerCount(pagePath string) int {
h.mu.RLock()
defer h.mu.RUnlock()
count := 0
for _, page := range h.clients {
if page == pagePath {
count++
}
}
return count
}