morz-infoboard/server/backend/internal/httpapi/screenshot_store.go
Jesko Anschütz b73da77835 feat(screens): Screen-Übersicht mit On-Demand-Screenshots für Multi-Screen-User
- GET /manage: neue Übersichtsseite mit Bulma-Karten für screen_user mit ≥2 Screens
- handleScreenUserRedirect leitet bei ≥2 Screens auf /manage statt auf ersten Screen
- On-Demand-Screenshot-Flow via MQTT:
  - Backend publiziert signage/screen/{slug}/screenshot-request beim Seitenaufruf
  - Player-Agent empfängt Topic, ruft TakeAndSendOnce() auf
  - Player POST /api/v1/player/screenshot → Backend speichert in ScreenshotStore (RAM)
  - GET /api/v1/screens/{screenId}/screenshot liefert gespeichertes Bild (authOnly)
- ScreenshotStore: In-Memory, thread-safe, kein Persistenz-Overhead
- JS-Retry nach 4s in Templates (Screenshot braucht 1-3s für MQTT-Roundtrip)
- manageTmpl zeigt Screenshot-Thumbnail beim Einzelscreen-Aufruf
- Doku: neue Endpoints, MQTT-Topics, Screenshot-Flow in SERVER-KONZEPT.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 14:27:10 +01:00

33 lines
714 B
Go

package httpapi
import "sync"
type screenshotRecord struct {
Data []byte
MimeType string
}
type ScreenshotStore struct {
mu sync.RWMutex
records map[string]screenshotRecord
}
func NewScreenshotStore() *ScreenshotStore {
return &ScreenshotStore{records: make(map[string]screenshotRecord)}
}
func (s *ScreenshotStore) Save(screenID string, data []byte, mimeType string) {
s.mu.Lock()
defer s.mu.Unlock()
s.records[screenID] = screenshotRecord{Data: data, MimeType: mimeType}
}
func (s *ScreenshotStore) Get(screenID string) ([]byte, string, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
rec, ok := s.records[screenID]
if !ok {
return nil, "", false
}
return rec.Data, rec.MimeType, true
}