Web UI: setup wizard, auth pages, library browsing, player, admin, streaming, cover art
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"git.noroutes.net/NoRoutes/vibetunes/internal/database"
|
||||
)
|
||||
|
||||
// View-model structs shape database rows for templates, keeping SQL
|
||||
// scanning details (sql.Null*) out of the .html files.
|
||||
|
||||
type ArtistView struct {
|
||||
ID string
|
||||
Name string
|
||||
}
|
||||
|
||||
type AlbumView struct {
|
||||
ID string
|
||||
Title string
|
||||
ArtistName string
|
||||
Year int64
|
||||
CoverArtID string
|
||||
}
|
||||
|
||||
type SongRow struct {
|
||||
ID string
|
||||
Title string
|
||||
ArtistName string
|
||||
AlbumTitle string
|
||||
AlbumID string
|
||||
CoverArtID string
|
||||
TrackNumber int64
|
||||
DurationSeconds float64
|
||||
Starred bool
|
||||
}
|
||||
|
||||
func toArtistView(a *database.Artist) ArtistView {
|
||||
return ArtistView{ID: a.ID, Name: a.Name}
|
||||
}
|
||||
|
||||
func toAlbumView(db *sql.DB, a *database.Album) AlbumView {
|
||||
v := AlbumView{ID: a.ID, Title: a.Title}
|
||||
if a.Year.Valid {
|
||||
v.Year = a.Year.Int64
|
||||
}
|
||||
if a.CoverArtID.Valid {
|
||||
v.CoverArtID = a.CoverArtID.String
|
||||
}
|
||||
if a.PrimaryAlbumArtistID.Valid {
|
||||
if artist, err := database.GetArtist(db, a.PrimaryAlbumArtistID.String); err == nil {
|
||||
v.ArtistName = artist.Name
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// toSongRow builds a display row for a song, given its owning album (may
|
||||
// be nil for albumless tracks) and the current user (for the starred
|
||||
// flag; pass "" userID to skip that lookup).
|
||||
func toSongRow(db *sql.DB, s *database.Song, album *database.Album, userID string) SongRow {
|
||||
row := SongRow{
|
||||
ID: s.ID,
|
||||
Title: s.Title,
|
||||
DurationSeconds: 0,
|
||||
}
|
||||
if s.TrackNumber.Valid {
|
||||
row.TrackNumber = s.TrackNumber.Int64
|
||||
}
|
||||
if names, err := database.ListSongArtistNames(db, s.ID); err == nil && len(names) > 0 {
|
||||
row.ArtistName = names[0]
|
||||
for _, n := range names[1:] {
|
||||
row.ArtistName += ", " + n
|
||||
}
|
||||
}
|
||||
if album != nil {
|
||||
row.AlbumTitle = album.Title
|
||||
row.AlbumID = album.ID
|
||||
if album.CoverArtID.Valid {
|
||||
row.CoverArtID = album.CoverArtID.String
|
||||
}
|
||||
}
|
||||
if mf, err := database.GetMediaFile(db, s.MediaFileID); err == nil {
|
||||
row.DurationSeconds = mf.DurationSeconds
|
||||
}
|
||||
if userID != "" {
|
||||
if starred, err := database.IsStarred(db, userID, "song", s.ID); err == nil {
|
||||
row.Starred = starred
|
||||
}
|
||||
}
|
||||
return row
|
||||
}
|
||||
|
||||
// albumOf loads a song's album, tolerating albumless songs.
|
||||
func albumOf(db *sql.DB, s *database.Song) *database.Album {
|
||||
if !s.AlbumID.Valid {
|
||||
return nil
|
||||
}
|
||||
album, err := database.GetAlbum(db, s.AlbumID.String)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return album
|
||||
}
|
||||
|
||||
type SessionView struct {
|
||||
ID string
|
||||
UserAgent string
|
||||
IPAddress string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
Reference in New Issue
Block a user