package web import ( "encoding/json" "net/http" "git.noroutes.net/NoRoutes/vibetunes/internal/database" ) type lyricsLineJSON struct { Text string `json:"text"` StartMs *int `json:"startMs,omitempty"` } type lyricsResponseJSON struct { Synced bool `json:"synced"` Lines []lyricsLineJSON `json:"lines"` } // handleLyrics serves the web player's lyrics panel: the best available // stored structuredLyrics entry for a song, as line text plus a start // time when the source actually has one. Prefers a synced entry over // an unsynced one so the panel can highlight/click-to-seek whenever // that data exists, but never fabricates timing for an unsynced entry. func (h *Web) handleLyrics(w http.ResponseWriter, r *http.Request) { songID := r.PathValue("id") entries, err := database.GetSongStructuredLyrics(h.DB, songID) if err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } var best *database.StructuredLyricsRow for i := range entries { if best == nil || (entries[i].Synced && !best.Synced) { best = &entries[i] } } out := lyricsResponseJSON{Lines: []lyricsLineJSON{}} if best != nil { out.Synced = best.Synced for _, l := range best.Lines { out.Lines = append(out.Lines, lyricsLineJSON{Text: l.Text, StartMs: l.StartMs}) } } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(out) }