feat: add a queue to the music player

This commit is contained in:
Araozu 2024-10-09 19:31:31 -05:00
parent 186e6bbab3
commit fea4d8140e
7 changed files with 122 additions and 60 deletions

View File

@ -3,6 +3,7 @@ package album
import ( import (
"acide/src/modules/song" "acide/src/modules/song"
"acide/src/utils" "acide/src/utils"
"encoding/json"
"net/http" "net/http"
"sync" "sync"
@ -10,6 +11,13 @@ import (
"github.com/labstack/gommon/log" "github.com/labstack/gommon/log"
) )
type ClientSong struct {
Title string `json:"title"`
Artist string `json:"artist"`
AlbumId string `json:"albumId"`
SongId string `json:"songId"`
}
func Setup(g *echo.Group) { func Setup(g *echo.Group) {
log.Print("Setting up the album module") log.Print("Setting up the album module")
g.Use(utils.Authed) g.Use(utils.Authed)
@ -68,5 +76,21 @@ func albumPage(c echo.Context) error {
return routineErr return routineErr
} }
return utils.RenderTempl(c, http.StatusOK, albumTempl(albumId, album, songs)) // convert the song list to json
clientSons := make([]ClientSong, len(songs))
for i, song := range songs {
clientSons[i] = ClientSong{
Title: song.Title,
Artist: song.Artist,
AlbumId: album.ID,
SongId: song.ID,
}
}
clientSongsJson, err := json.Marshal(clientSons)
if err != nil {
log.Printf("Error marshaling clientSongs: %s", err)
return err
}
return utils.RenderTempl(c, http.StatusOK, albumTempl(albumId, album, songs, string(clientSongsJson)))
} }

View File

@ -24,9 +24,12 @@ templ allAlbumsTempl(albums []utils.Album) {
} }
// Renders the page of a single Album // Renders the page of a single Album
templ albumTempl(albumId string, album *utils.Album, songs []utils.Song) { templ albumTempl(albumId string, album *utils.Album, songs []utils.Song, songsJson string) {
@utils.SkeletonTempl() { @utils.SkeletonTempl() {
<div class="text-center"> <div
class="text-center"
_={ fmt.Sprintf("init set $songsJson to %s", songsJson) }
>
<img class="inline-block mt-2 rounded shadow" src={ fmt.Sprintf("/covers/%s", albumId) }/> <img class="inline-block mt-2 rounded shadow" src={ fmt.Sprintf("/covers/%s", albumId) }/>
<h1 class="font-bold pt-4 pb-2 text-2xl"> <h1 class="font-bold pt-4 pb-2 text-2xl">
{ album.Name } { album.Name }
@ -35,15 +38,10 @@ templ albumTempl(albumId string, album *utils.Album, songs []utils.Song) {
{ album.Artist } { album.Artist }
</p> </p>
<div> <div>
for _, song := range songs { for i, song := range songs {
<button <button
class="inline-block py-2 pl-2 pr-4 w-full cursor-pointer text-left hover:bg-sky-100 whitespace-nowrap overflow-hidden overflow-ellipsis" class="inline-block py-2 pl-2 pr-4 w-full cursor-pointer text-left hover:bg-sky-100 whitespace-nowrap overflow-hidden overflow-ellipsis"
_={ fmt.Sprintf("on click playSong('%s', '%s', '%s', '%s')", _={ fmt.Sprintf("on click replaceQueueAndPlayAt($songsJson, %d)", i) }
utils.EscapeSingle(song.Title),
utils.EscapeSingle(song.Artist),
albumId,
song.ID,
) }
> >
<span class="inline-block w-6 text-right opacity-75 pr-2"> <span class="inline-block w-6 text-right opacity-75 pr-2">
{ strconv.Itoa(song.TrackNumber) } { strconv.Itoa(song.TrackNumber) }

View File

@ -74,7 +74,7 @@ func allAlbumsTempl(albums []utils.Album) templ.Component {
} }
// Renders the page of a single Album // Renders the page of a single Album
func albumTempl(albumId string, album *utils.Album, songs []utils.Song) templ.Component { func albumTempl(albumId string, album *utils.Album, songs []utils.Song, songsJson string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -107,29 +107,42 @@ func albumTempl(albumId string, album *utils.Album, songs []utils.Song) templ.Co
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-center\"><img class=\"inline-block mt-2 rounded shadow\" src=\"") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"text-center\" _=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/covers/%s", albumId)) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("init set $songsJson to %s", songsJson))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 30, Col: 89} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 31, Col: 58}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><img class=\"inline-block mt-2 rounded shadow\" src=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/covers/%s", albumId))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 33, Col: 89}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><h1 class=\"font-bold pt-4 pb-2 text-2xl\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><h1 class=\"font-bold pt-4 pb-2 text-2xl\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var6 string var templ_7745c5c3_Var7 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(album.Name) templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(album.Name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 32, Col: 16} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 35, Col: 16}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -137,12 +150,12 @@ func albumTempl(albumId string, album *utils.Album, songs []utils.Song) templ.Co
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var7 string var templ_7745c5c3_Var8 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(album.Artist) templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(album.Artist)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 35, Col: 18} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 38, Col: 18}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -150,22 +163,17 @@ func albumTempl(albumId string, album *utils.Album, songs []utils.Song) templ.Co
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _, song := range songs { for i, song := range songs {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"inline-block py-2 pl-2 pr-4 w-full cursor-pointer text-left hover:bg-sky-100 whitespace-nowrap overflow-hidden overflow-ellipsis\" _=\"") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button class=\"inline-block py-2 pl-2 pr-4 w-full cursor-pointer text-left hover:bg-sky-100 whitespace-nowrap overflow-hidden overflow-ellipsis\" _=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var8 string var templ_7745c5c3_Var9 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on click playSong('%s', '%s', '%s', '%s')", templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on click replaceQueueAndPlayAt($songsJson, %d)", i))
utils.EscapeSingle(song.Title),
utils.EscapeSingle(song.Artist),
albumId,
song.ID,
))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 46, Col: 7} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 44, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -173,12 +181,12 @@ func albumTempl(albumId string, album *utils.Album, songs []utils.Song) templ.Co
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var9 string var templ_7745c5c3_Var10 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(song.TrackNumber)) templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(song.TrackNumber))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 49, Col: 39} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 47, Col: 39}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -186,12 +194,12 @@ func albumTempl(albumId string, album *utils.Album, songs []utils.Song) templ.Co
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var10 string var templ_7745c5c3_Var11 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(song.Title) templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(song.Title)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 51, Col: 18} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/modules/album/album.templ`, Line: 49, Col: 18}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -23,12 +23,12 @@ templ IndexTempl(albums []utils.Album) {
} }
templ AlbumCard(album utils.Album) { templ AlbumCard(album utils.Album) {
<div class="inline-block p-1 rounded bg-zinc-200 max-w-32"> <div class="inline-block p-1 rounded bg-zinc-200 w-full max-w-32">
<div class="h-30 relative"> <div class="h-30 relative">
<img src={ fmt.Sprintf("/covers/%s", album.ID) }/> <img src={ fmt.Sprintf("/covers/%s", album.ID) }/>
<a <a
href={ templ.URL(fmt.Sprintf("/album/%s", album.ID)) } href={ templ.URL(fmt.Sprintf("/album/%s", album.ID)) }
class="inline-block w-full overflow-hidden overflow-ellipsis hover:underline" class="inline-block w-full overflow-hidden whitespace-nowrap overflow-ellipsis hover:underline"
> >
{ album.Name } { album.Name }
</a> </a>

View File

@ -95,7 +95,7 @@ func AlbumCard(album utils.Album) templ.Component {
templ_7745c5c3_Var3 = templ.NopComponent templ_7745c5c3_Var3 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"inline-block p-1 rounded bg-zinc-200 max-w-32\"><div class=\"h-30 relative\"><img src=\"") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"inline-block p-1 rounded bg-zinc-200 w-full max-w-32\"><div class=\"h-30 relative\"><img src=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -117,7 +117,7 @@ func AlbumCard(album utils.Album) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"inline-block w-full overflow-hidden overflow-ellipsis hover:underline\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"inline-block w-full overflow-hidden whitespace-nowrap overflow-ellipsis hover:underline\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -30,7 +30,7 @@ templ MusicPlayer() {
<div <div
id="music-player" id="music-player"
class="fixed bottom-0 left-0 w-screen border-t border-sky-500 grid grid-cols-[3rem_auto_3rem_3rem] gap-2 p-1 bg-white" class="fixed bottom-0 left-0 w-screen border-t border-sky-500 grid grid-cols-[3rem_auto_3rem_3rem] gap-2 p-1 bg-white"
_="init set $sound to null then set $playing to false then set $volume to 0.1" _="init set $sound to null then set $playing to false then set $volume to 0.1 then set $queue to [] then set $queueIdx to 0"
> >
<div class="h-12 bg-sky-200 rounded"> <div class="h-12 bg-sky-200 rounded">
<img class="rounded" id="music-player-img"/> <img class="rounded" id="music-player-img"/>
@ -47,14 +47,40 @@ templ MusicPlayer() {
@playIcon(26) @playIcon(26)
@pauseIcon(26) @pauseIcon(26)
</div> </div>
<button class="flex items-center justify-center"> <button
id="next-button"
class="flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed"
_="on click playNext()"
>
@skipForwardIcon(24) @skipForwardIcon(24)
</button> </button>
</div> </div>
<script type="text/hyperscript"> <script type="text/hyperscript">
def onSongEnd() def replaceQueueAndPlayAt(queue, pos)
set $playing to false set $queue to queue
updateUi(false) if pos < queue.length
playAt(pos)
end
end
def playAt(pos)
set $queueIdx to pos
set song to $queue[pos]
playSong(song.title, song.artist, song.albumId, song.songId)
end
def playNext()
if $queueIdx + 1 < $queue.length
playAt($queueIdx + 1)
end
end
def updateNextButton()
if $queueIdx is $queue.length -1
set #next-button's @disabled to "true"
else
remove @disabled from #next-button
end
end end
def playSong(title, artist, albumId, songId) def playSong(title, artist, albumId, songId)
@ -66,6 +92,7 @@ templ MusicPlayer() {
set $playing to true set $playing to true
remove .hidden from #spinner remove .hidden from #spinner
updateUi(false) updateUi(false)
updateNextButton()
if $sound exists if $sound exists
$sound.fade($volume, 0.0, 250) $sound.fade($volume, 0.0, 250)
@ -88,6 +115,11 @@ templ MusicPlayer() {
updateUi(true) updateUi(true)
end end
def onSongEnd()
set $playing to false
updateUi(false)
end
def updateUi(playing) def updateUi(playing)
if playing is true if playing is true
add .hidden to #play-icon add .hidden to #play-icon

View File

@ -68,7 +68,7 @@ func MusicPlayer() templ.Component {
templ_7745c5c3_Var2 = templ.NopComponent templ_7745c5c3_Var2 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"music-player\" class=\"fixed bottom-0 left-0 w-screen border-t border-sky-500 grid grid-cols-[3rem_auto_3rem_3rem] gap-2 p-1 bg-white\" _=\"init set $sound to null then set $playing to false then set $volume to 0.1\"><div class=\"h-12 bg-sky-200 rounded\"><img class=\"rounded\" id=\"music-player-img\"></div><div class=\"w-full overflow-hidden\"><p id=\"music-player-title\" class=\"overflow-hidden overflow-ellipsis whitespace-nowrap w-full\">-</p><p id=\"music-player-artist\" class=\"text-sm opacity-75 overflow-hidden overflow-ellipsis whitespace-nowrap w-full\">-</p></div><div class=\"flex items-center justify-center cursor-pointer relative\" _=\"on click togglePlaying()\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"music-player\" class=\"fixed bottom-0 left-0 w-screen border-t border-sky-500 grid grid-cols-[3rem_auto_3rem_3rem] gap-2 p-1 bg-white\" _=\"init set $sound to null then set $playing to false then set $volume to 0.1 then set $queue to [] then set $queueIdx to 0\"><div class=\"h-12 bg-sky-200 rounded\"><img class=\"rounded\" id=\"music-player-img\"></div><div class=\"w-full overflow-hidden\"><p id=\"music-player-title\" class=\"overflow-hidden overflow-ellipsis whitespace-nowrap w-full\">-</p><p id=\"music-player-artist\" class=\"text-sm opacity-75 overflow-hidden overflow-ellipsis whitespace-nowrap w-full\">-</p></div><div class=\"flex items-center justify-center cursor-pointer relative\" _=\"on click togglePlaying()\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -84,7 +84,7 @@ func MusicPlayer() templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><button class=\"flex items-center justify-center\">") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><button id=\"next-button\" class=\"flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed\" _=\"on click playNext()\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -92,7 +92,7 @@ func MusicPlayer() templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button></div><script type=\"text/hyperscript\">\n\t\tdef onSongEnd()\n\t\t\tset $playing to false\n\t\t\tupdateUi(false)\n\t\tend\n\n\t\tdef playSong(title, artist, albumId, songId)\n\t\t\tset #music-player-img's @src to \"/covers/\" + albumId\n\t\t\tput title into #music-player-title's innerHTML\n\t\t\tput artist into #music-player-artist's innerHTML\n\n\t\t\t-- Update icons\n\t\t\tset $playing to true\n\t\t\tremove .hidden from #spinner\n\t\t\tupdateUi(false)\n\n\t\t\tif $sound exists\n\t\t\t\t$sound.fade($volume, 0.0, 250)\n\t\t\t\twait 250ms\n\t\t\t\t$sound.unload()\n\t\t\tend\n\n\t\t\tmake a Howl from {\n\t\t\t\tsrc: [`https://navidrome.araozu.dev/rest/stream.view?id=${songId}&v=1.13.0&c=music-to-go&u=fernando&s=49805d&t=4148cd1c83ae1bd01334facf4e70a947`],\n\t\t\t\thtml5: true,\n\t\t\t\tvolume: $volume\n\t\t\t} called $sound\n\t\t\t$sound.play()\n\t\t\t$sound.once(\"load\", onSongLoaded)\n\t\t\tjs $sound.once(\"end\", () => onSongEnd())\n\t\tend\n\n\t\tdef onSongLoaded()\n\t\t\tadd .hidden to #spinner\n\t\t\tupdateUi(true)\n\t\tend\n\n\t\tdef updateUi(playing)\n\t\t\tif playing is true\n\t\t\t\tadd .hidden to #play-icon\n\t\t\t\tremove .hidden from #pause-icon\n\t\t\telse\n\t\t\t\tremove .hidden from #play-icon\n\t\t\t\tadd .hidden to #pause-icon\n\t\t\tend\n\t\tend\n\n\t\tdef togglePlaying()\n\t\t\tif $playing is true\n\t\t\t\tset $playing to false\n\t\t\t\tupdateUi(false)\n\t\t\t\t$sound.pause()\n\t\t\telse\n\t\t\t\tset $playing to true\n\t\t\t\tupdateUi(true)\n\t\t\t\t$sound.play()\n\t\t\tend\n\t\tend\n\t</script>") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button></div><script type=\"text/hyperscript\">\n\t\tdef replaceQueueAndPlayAt(queue, pos)\n\t\t\tset $queue to queue\n\t\t\tif pos < queue.length\n\t\t\t\tplayAt(pos)\n\t\t\tend\n\t\tend\n\n\t\tdef playAt(pos)\n\t\t\tset $queueIdx to pos\n\t\t\tset song to $queue[pos]\n\t\t\tplaySong(song.title, song.artist, song.albumId, song.songId)\n\t\tend\n\n\t\tdef playNext()\n\t\t\tif $queueIdx + 1 < $queue.length\n\t\t\t\tplayAt($queueIdx + 1)\n\t\t\tend\n\t\tend\n\n\t\tdef updateNextButton()\n\t\t\tif $queueIdx is $queue.length -1\n\t\t\t\tset #next-button's @disabled to \"true\"\n\t\t\telse\n\t\t\t\tremove @disabled from #next-button\n\t\t\tend\n\t\tend\n\n\t\tdef playSong(title, artist, albumId, songId)\n\t\t\tset #music-player-img's @src to \"/covers/\" + albumId\n\t\t\tput title into #music-player-title's innerHTML\n\t\t\tput artist into #music-player-artist's innerHTML\n\n\t\t\t-- Update icons\n\t\t\tset $playing to true\n\t\t\tremove .hidden from #spinner\n\t\t\tupdateUi(false)\n\t\t\tupdateNextButton()\n\n\t\t\tif $sound exists\n\t\t\t\t$sound.fade($volume, 0.0, 250)\n\t\t\t\twait 250ms\n\t\t\t\t$sound.unload()\n\t\t\tend\n\n\t\t\tmake a Howl from {\n\t\t\t\tsrc: [`https://navidrome.araozu.dev/rest/stream.view?id=${songId}&v=1.13.0&c=music-to-go&u=fernando&s=49805d&t=4148cd1c83ae1bd01334facf4e70a947`],\n\t\t\t\thtml5: true,\n\t\t\t\tvolume: $volume\n\t\t\t} called $sound\n\t\t\t$sound.play()\n\t\t\t$sound.once(\"load\", onSongLoaded)\n\t\t\tjs $sound.once(\"end\", () => onSongEnd())\n\t\tend\n\n\t\tdef onSongLoaded()\n\t\t\tadd .hidden to #spinner\n\t\t\tupdateUi(true)\n\t\tend\n\n\t\tdef onSongEnd()\n\t\t\tset $playing to false\n\t\t\tupdateUi(false)\n\t\tend\n\n\t\tdef updateUi(playing)\n\t\t\tif playing is true\n\t\t\t\tadd .hidden to #play-icon\n\t\t\t\tremove .hidden from #pause-icon\n\t\t\telse\n\t\t\t\tremove .hidden from #play-icon\n\t\t\t\tadd .hidden to #pause-icon\n\t\t\tend\n\t\tend\n\n\t\tdef togglePlaying()\n\t\t\tif $playing is true\n\t\t\t\tset $playing to false\n\t\t\t\tupdateUi(false)\n\t\t\t\t$sound.pause()\n\t\t\telse\n\t\t\t\tset $playing to true\n\t\t\t\tupdateUi(true)\n\t\t\t\t$sound.play()\n\t\t\tend\n\t\tend\n\t</script>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -128,7 +128,7 @@ func playIcon(size int) templ.Component {
var templ_7745c5c3_Var4 string var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 119, Col: 28} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 151, Col: 28}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -141,7 +141,7 @@ func playIcon(size int) templ.Component {
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 120, Col: 29} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 152, Col: 29}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -183,7 +183,7 @@ func pauseIcon(size int) templ.Component {
var templ_7745c5c3_Var7 string var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 139, Col: 28} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 171, Col: 28}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -196,7 +196,7 @@ func pauseIcon(size int) templ.Component {
var templ_7745c5c3_Var8 string var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 140, Col: 29} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 172, Col: 29}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -238,7 +238,7 @@ func skipForwardIcon(size int) templ.Component {
var templ_7745c5c3_Var10 string var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 147, Col: 67} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 179, Col: 67}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -251,7 +251,7 @@ func skipForwardIcon(size int) templ.Component {
var templ_7745c5c3_Var11 string var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 147, Col: 97} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 179, Col: 97}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -298,7 +298,7 @@ func circleNotchIcon(class string, size int) templ.Component {
var templ_7745c5c3_Var14 string var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 160, Col: 28} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 192, Col: 28}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -311,7 +311,7 @@ func circleNotchIcon(class string, size int) templ.Component {
var templ_7745c5c3_Var15 string var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size)) templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(size))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 161, Col: 29} return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/utils/utils.templ`, Line: 193, Col: 29}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {