Compare commits
11 commits
bdff7622c5
...
cdf12411a2
Author | SHA1 | Date | |
---|---|---|---|
|
cdf12411a2 | ||
|
26f230e039 | ||
|
9248852713 | ||
|
1fc5dc2bf8 | ||
|
aeaef11341 | ||
|
44dd0ddd9c | ||
|
cfbb8a47f7 | ||
|
58f59017dd | ||
|
2c2efaaca2 | ||
|
bb19b095b6 | ||
|
bddc82399b |
20
NOTES.md
20
NOTES.md
|
@ -45,12 +45,12 @@
|
||||||
- [ ] Select tracks in results
|
- [ ] Select tracks in results
|
||||||
- [ ] `Add` selected tracks to queue button
|
- [ ] `Add` selected tracks to queue button
|
||||||
- Playlist browser
|
- Playlist browser
|
||||||
- [ ] Show current playlists
|
- [x] Show current playlists
|
||||||
- [ ] `Replace` current queue with playlist button
|
- [x] `Replace` current queue with playlist button
|
||||||
- [ ] `Attach` playlist to current queue button
|
- [x] `Attach` playlist to current queue button
|
||||||
- [ ] `Save` current queue as playlist button
|
- [x] `Save` current queue as playlist button
|
||||||
- [x] Show dialog
|
- [x] Show dialog
|
||||||
- [ ] `Delete` selected playlist button
|
- [x] `Delete` selected playlist button
|
||||||
|
|
||||||
## backend
|
## backend
|
||||||
|
|
||||||
|
@ -77,8 +77,10 @@
|
||||||
- [ ] POST `/api/queue` `{"song_id": 123}`
|
- [ ] POST `/api/queue` `{"song_id": 123}`
|
||||||
- [x] GET `/api/queue/:song_id/delete`
|
- [x] GET `/api/queue/:song_id/delete`
|
||||||
- [x] GET `/api/queue/:song_id/move/:position`
|
- [x] GET `/api/queue/:song_id/move/:position`
|
||||||
|
- [x] GET `/api/queue/replace/:playlist_name`
|
||||||
|
- [x] GET `/api/queue/attach/:playlist_name`
|
||||||
- [ ] `/api/list_database/:path`
|
- [ ] `/api/list_database/:path`
|
||||||
- [ ] `/api/list_playlists`
|
- [x] GET `/api/playlists`
|
||||||
- [ ] `/api/save_playlist`
|
- [x] POST `/api/playlists/:name`
|
||||||
- [ ] `/api/delete_playlist`
|
- [x] GET `/api/playlists/:name`
|
||||||
|
- [x] DELETE `/api/playlists/:name`
|
||||||
|
|
|
@ -43,11 +43,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710889954,
|
"lastModified": 1713284584,
|
||||||
"narHash": "sha256-Pr6F5Pmd7JnNEMHHmspZ0qVqIBVxyZ13ik1pJtm2QXk=",
|
"narHash": "sha256-rRuPBJD9+yjz7tY3xC/BvFUwloutynR9piiVE6fhGqo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "7872526e9c5332274ea5932a0c3270d6e4724f3b",
|
"rev": "2b6ee326ad047870526d9a3ae88dfd0197da898d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -1,11 +1,11 @@
|
||||||
module git.berlin.ccc.de/cccb/sanic
|
module gitlab.com/XenGi/sanic
|
||||||
|
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fhs/gompd/v2 v2.3.0
|
github.com/fhs/gompd/v2 v2.3.0
|
||||||
github.com/labstack/echo-contrib v0.16.0
|
github.com/labstack/echo-contrib v0.17.0
|
||||||
github.com/labstack/echo/v4 v4.11.4
|
github.com/labstack/echo/v4 v4.12.0
|
||||||
golang.org/x/net v0.24.0
|
golang.org/x/net v0.24.0
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,7 @@ require (
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/prometheus/client_golang v1.19.0 // indirect
|
github.com/prometheus/client_golang v1.19.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.52.2 // indirect
|
github.com/prometheus/common v0.52.3 // indirect
|
||||||
github.com/prometheus/procfs v0.13.0 // indirect
|
github.com/prometheus/procfs v0.13.0 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
|
|
12
go.sum
12
go.sum
|
@ -10,10 +10,10 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/labstack/echo-contrib v0.16.0 h1:vk5Kd+egpTOJxD3l+3IvZzQWPbrXiYxhkkgkJL99j/w=
|
github.com/labstack/echo-contrib v0.17.0 h1:xam8wakZOsiQYM14Z0og1xF3w/heWNeDF5AtC5PlX8E=
|
||||||
github.com/labstack/echo-contrib v0.16.0/go.mod h1:mjX5VB3OqJcroIEycptBOY9Hr7rK+unq79W8QFKGNV0=
|
github.com/labstack/echo-contrib v0.17.0/go.mod h1:mjX5VB3OqJcroIEycptBOY9Hr7rK+unq79W8QFKGNV0=
|
||||||
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
|
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||||
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
@ -27,8 +27,8 @@ github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7km
|
||||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.52.2 h1:LW8Vk7BccEdONfrJBDffQGRtpSzi5CQaRZGtboOO2ck=
|
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
|
||||||
github.com/prometheus/common v0.52.2/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q=
|
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||||
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
|
||||||
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
|
|
@ -14,11 +14,11 @@ schema = 3
|
||||||
version = "v3.2.2+incompatible"
|
version = "v3.2.2+incompatible"
|
||||||
hash = "sha256-LOkpuXhWrFayvVf1GOaOmZI5YKEsgqVSb22aF8LnCEM="
|
hash = "sha256-LOkpuXhWrFayvVf1GOaOmZI5YKEsgqVSb22aF8LnCEM="
|
||||||
[mod."github.com/labstack/echo-contrib"]
|
[mod."github.com/labstack/echo-contrib"]
|
||||||
version = "v0.16.0"
|
version = "v0.17.0"
|
||||||
hash = "sha256-YnO4Ngu+gb/upIo856FDCtcTev36Vs/xUvP2qMiSGnA="
|
hash = "sha256-J5S8vO8Zg9uV9A3zbILswn/oPdwLKRXncsXdEjDOmU8="
|
||||||
[mod."github.com/labstack/echo/v4"]
|
[mod."github.com/labstack/echo/v4"]
|
||||||
version = "v4.11.4"
|
version = "v4.12.0"
|
||||||
hash = "sha256-pVKfkZtxi5e/1MTK2RcKWSgNpEbRDo3lKUVKo01WYO0="
|
hash = "sha256-TPXJv/6C53bnmcEYxa9g5Mft8u/rLT96q64tQ9+RtKU="
|
||||||
[mod."github.com/labstack/gommon"]
|
[mod."github.com/labstack/gommon"]
|
||||||
version = "v0.4.2"
|
version = "v0.4.2"
|
||||||
hash = "sha256-395+BETDpv15L2lsCiEccwakXgEQxKHlYBAU0Ot3qhY="
|
hash = "sha256-395+BETDpv15L2lsCiEccwakXgEQxKHlYBAU0Ot3qhY="
|
||||||
|
@ -35,8 +35,8 @@ schema = 3
|
||||||
version = "v0.6.1"
|
version = "v0.6.1"
|
||||||
hash = "sha256-rIDyUzNfxRA934PIoySR0EhuBbZVRK/25Jlc/r8WODw="
|
hash = "sha256-rIDyUzNfxRA934PIoySR0EhuBbZVRK/25Jlc/r8WODw="
|
||||||
[mod."github.com/prometheus/common"]
|
[mod."github.com/prometheus/common"]
|
||||||
version = "v0.52.2"
|
version = "v0.52.3"
|
||||||
hash = "sha256-XQUvk9/Kwf9NDlDUVl7mOWRD7z7z9QEbLH/rNU4D2nI="
|
hash = "sha256-JzNAt7pimXZMnPxv8droAHJq+5OKWi9BYkGtMvqpyd0="
|
||||||
[mod."github.com/prometheus/procfs"]
|
[mod."github.com/prometheus/procfs"]
|
||||||
version = "v0.13.0"
|
version = "v0.13.0"
|
||||||
hash = "sha256-J31K36TkIiQU2EGOcmqDa+dkoKXiVuxafPVT4rKbEsg="
|
hash = "sha256-J31K36TkIiQU2EGOcmqDa+dkoKXiVuxafPVT4rKbEsg="
|
||||||
|
|
119
mpd.go
119
mpd.go
|
@ -273,3 +273,122 @@ func moveTrackInQueue(c echo.Context) error {
|
||||||
|
|
||||||
return c.String(http.StatusOK, fmt.Sprintf("Moved song %d to position %d", songId, position))
|
return c.String(http.StatusOK, fmt.Sprintf("Moved song %d to position %d", songId, position))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func attachPlaylist(c echo.Context) error {
|
||||||
|
// Connect to MPD server
|
||||||
|
conn, err := mpd.Dial("tcp", "localhost:6600")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
name := c.Param("playlist_name")
|
||||||
|
|
||||||
|
err = conn.PlaylistLoad(name, -1, -1)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceQueue(c echo.Context) error {
|
||||||
|
// Connect to MPD server
|
||||||
|
conn, err := mpd.Dial("tcp", "localhost:6600")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
name := c.Param("playlist_name")
|
||||||
|
|
||||||
|
err = conn.Clear()
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
err = conn.PlaylistLoad(name, -1, -1)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Playlists
|
||||||
|
|
||||||
|
func listPlaylists(c echo.Context) error {
|
||||||
|
// Connect to MPD server
|
||||||
|
conn, err := mpd.Dial("tcp", "localhost:6600")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
playlists, err := conn.ListPlaylists()
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, playlists)
|
||||||
|
}
|
||||||
|
|
||||||
|
func listPlaylist(c echo.Context) error {
|
||||||
|
// Connect to MPD server
|
||||||
|
conn, err := mpd.Dial("tcp", "localhost:6600")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
name := c.Param("name")
|
||||||
|
|
||||||
|
playlist, err := conn.PlaylistContents(name)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, playlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deletePlaylist(c echo.Context) error {
|
||||||
|
// Connect to MPD server
|
||||||
|
conn, err := mpd.Dial("tcp", "localhost:6600")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
name := c.Param("name")
|
||||||
|
|
||||||
|
err = conn.PlaylistRemove(name)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusNoContent, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func savePlaylist(c echo.Context) error {
|
||||||
|
// Connect to MPD server
|
||||||
|
conn, err := mpd.Dial("tcp", "localhost:6600")
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
name := c.Param("name")
|
||||||
|
|
||||||
|
err = conn.PlaylistSave(name)
|
||||||
|
if err != nil {
|
||||||
|
c.Logger().Error(err)
|
||||||
|
return c.String(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusCreated, "")
|
||||||
|
}
|
||||||
|
|
|
@ -91,6 +91,13 @@ func main() {
|
||||||
|
|
||||||
g.GET("/queue/:song_id/delete", deleteTrackFromQueue)
|
g.GET("/queue/:song_id/delete", deleteTrackFromQueue)
|
||||||
g.GET("/queue/:song_id/move/:position", moveTrackInQueue)
|
g.GET("/queue/:song_id/move/:position", moveTrackInQueue)
|
||||||
|
g.GET("/queue/replace/:playlist_name", replaceQueue)
|
||||||
|
g.GET("/queue/attach/:playlist_name", attachPlaylist)
|
||||||
|
|
||||||
|
g.GET("/playlists", listPlaylists)
|
||||||
|
g.POST("/playlists/:name", savePlaylist)
|
||||||
|
g.GET("/playlists/:name", listPlaylist)
|
||||||
|
g.DELETE("/playlists/:name", deletePlaylist)
|
||||||
|
|
||||||
g.GET("/download", downloadTrack)
|
g.GET("/download", downloadTrack)
|
||||||
|
|
||||||
|
|
117
static/index.js
117
static/index.js
|
@ -7,7 +7,7 @@ const VOLUME_STEP = 5;
|
||||||
|
|
||||||
const dialog_save_playlist = document.getElementById("save-playlist");
|
const dialog_save_playlist = document.getElementById("save-playlist");
|
||||||
const control_playlist_name = document.getElementById("control-playlist-name");
|
const control_playlist_name = document.getElementById("control-playlist-name");
|
||||||
const dialog_save_playlist_submit = document.querySelector("#save-playlist button");
|
const dialog_save_playlist_submit = document.querySelector("#save-playlist form button");
|
||||||
const dialog_save_playlist_close = document.querySelector("#save-playlist .close");
|
const dialog_save_playlist_close = document.querySelector("#save-playlist .close");
|
||||||
|
|
||||||
const connection_state = document.getElementById("connection-state");
|
const connection_state = document.getElementById("connection-state");
|
||||||
|
@ -37,6 +37,7 @@ const control_replace_playlist = document.getElementById("control-replace-playli
|
||||||
const control_attach_playlist = document.getElementById("control-attach-playlist");
|
const control_attach_playlist = document.getElementById("control-attach-playlist");
|
||||||
const control_save_playlist = document.getElementById("control-save-playlist");
|
const control_save_playlist = document.getElementById("control-save-playlist");
|
||||||
const control_delete_playlist = document.getElementById("control-delete-playlist");
|
const control_delete_playlist = document.getElementById("control-delete-playlist");
|
||||||
|
const result_table = document.querySelector("#result tbody");
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
|
|
||||||
|
@ -68,6 +69,46 @@ moveTrackInQueue = (event, direction) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshPlaylists = () => {
|
||||||
|
console.log("Refreshing playlists from MPD server")
|
||||||
|
fetch(`${API_URL}/playlists`).then(async r => {
|
||||||
|
if (r.status === 200) {
|
||||||
|
const playlists = await r.json();
|
||||||
|
control_playlist_list.options.length = 0; // clear playlists
|
||||||
|
playlists.forEach(p => {
|
||||||
|
const option = document.createElement("option")
|
||||||
|
option.innerText = p["playlist"];
|
||||||
|
option.value = p["playlist"];
|
||||||
|
option.addEventListener("click", () => {
|
||||||
|
fetch(`${API_URL}/playlists/${p["playlist"]}`).then(async r => {
|
||||||
|
if (r.status === 200) {
|
||||||
|
const songs = await r.json();
|
||||||
|
console.log(songs)
|
||||||
|
result_table.innerHTML = "";
|
||||||
|
songs.forEach(song => {
|
||||||
|
const tr = document.createElement("tr");
|
||||||
|
const artist = document.createElement("td");
|
||||||
|
artist.innerText = song["Artist"];
|
||||||
|
const title = document.createElement("td");
|
||||||
|
title.innerText = song["Title"];
|
||||||
|
const time = document.createElement("td");
|
||||||
|
time.innerText = secondsToTrackTime(parseInt(song["Time"]))
|
||||||
|
tr.appendChild(artist);
|
||||||
|
tr.appendChild(title);
|
||||||
|
tr.appendChild(document.createElement("td")); // album
|
||||||
|
tr.appendChild(document.createElement("td")); // genre
|
||||||
|
tr.appendChild(time);
|
||||||
|
result_table.appendChild(tr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
control_playlist_list.appendChild(option)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// UI controls
|
// UI controls
|
||||||
|
|
||||||
tab_browser.addEventListener("click", () => {
|
tab_browser.addEventListener("click", () => {
|
||||||
|
@ -103,10 +144,12 @@ tab_playlists.addEventListener("click", () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Show "Save playlist" modal
|
||||||
control_save_playlist.addEventListener("click", () => {
|
control_save_playlist.addEventListener("click", () => {
|
||||||
dialog_save_playlist.showModal()
|
dialog_save_playlist.showModal()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Close "Save playlist" modal
|
||||||
dialog_save_playlist_close.addEventListener("click", () => {
|
dialog_save_playlist_close.addEventListener("click", () => {
|
||||||
dialog_save_playlist.close()
|
dialog_save_playlist.close()
|
||||||
});
|
});
|
||||||
|
@ -117,42 +160,83 @@ dialog_save_playlist_close.addEventListener("click", () => {
|
||||||
|
|
||||||
// Add API calls to controls
|
// Add API calls to controls
|
||||||
|
|
||||||
control_replace_playlist.addEventListener("click", e => {
|
control_replace_playlist.addEventListener("click", () => {
|
||||||
fetch(`${API_URL}/`).then(async r => {
|
fetch(`${API_URL}/queue/replace/${control_playlist_list.value}`).then(async r => {
|
||||||
if (r.status !== 200) {
|
if (r.status !== 200) {
|
||||||
console.error(`API returned ${r.status}: ${r.statusText}`);
|
console.error(`API returned ${r.status}: ${r.statusText}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
control_attach_playlist.addEventListener("click", e => {
|
control_attach_playlist.addEventListener("click", () => {
|
||||||
fetch(`${API_URL}/`).then(async r => {
|
fetch(`${API_URL}/queue/attach/${control_playlist_list.value}`).then(async r => {
|
||||||
if (r.status !== 200) {
|
if (r.status !== 200) {
|
||||||
console.error(`API returned ${r.status}: ${r.statusText}`);
|
console.error(`API returned ${r.status}: ${r.statusText}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Save current queue as new playlist and refresh playlist list
|
||||||
dialog_save_playlist_submit.addEventListener("click", () => {
|
dialog_save_playlist_submit.addEventListener("click", () => {
|
||||||
fetch(`${API_URL}/playlists`, {method: "PUT"}).then(async r => {
|
fetch(`${API_URL}/playlists/${control_playlist_name.value}`, {method: "POST"}).then(async r => {
|
||||||
if (r.status === 201) {
|
if (r.status === 201) {
|
||||||
console.log(`Playlist "${control_playlist_name.value}" saved`)
|
console.log(`Playlist "${control_playlist_name.value}" saved`)
|
||||||
}
|
refreshPlaylists()
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
control_delete_playlist.addEventListener("click", () => {
|
|
||||||
const playlist_id = control_playlist_list.value;
|
|
||||||
fetch(`${API_URL}/playlists/${playlist_id}`, {method: "DELETE"}).then(r => {
|
|
||||||
if (r.status === 204) {
|
|
||||||
console.log(`Playlist ${playlist_id} successfully deleted.`);
|
|
||||||
} else {
|
} else {
|
||||||
console.error(`API returned ${r.status}: ${r.statusText}`);
|
console.error(`API returned ${r.status}: ${r.statusText}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
control_update_db.addEventListener("click", event => {
|
control_delete_playlist.addEventListener("click", () => {
|
||||||
|
const playlist_name = control_playlist_list.value;
|
||||||
|
fetch(`${API_URL}/playlists/${control_playlist_list.value}`, {method: "DELETE"}).then(r => {
|
||||||
|
if (r.status === 204) {
|
||||||
|
console.log(`Playlist "${playlist_name}" successfully deleted.`);
|
||||||
|
refreshPlaylists();
|
||||||
|
} else {
|
||||||
|
console.error(`API returned ${r.status}: ${r.statusText}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tab_browser.addEventListener("click", () => {
|
||||||
|
if (!tab_browser.classList.contains("active")) {
|
||||||
|
tab_browser.classList.add("active");
|
||||||
|
tab_search.classList.remove("active")
|
||||||
|
tab_playlists.classList.remove("active")
|
||||||
|
document.getElementById("file-browser").style.display = "block";
|
||||||
|
document.getElementById("search").style.display = "none";
|
||||||
|
document.getElementById("playlist-browser").style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tab_search.addEventListener("click", () => {
|
||||||
|
if (!tab_search.classList.contains("active")) {
|
||||||
|
tab_browser.classList.remove("active");
|
||||||
|
tab_search.classList.add("active")
|
||||||
|
tab_playlists.classList.remove("active")
|
||||||
|
document.getElementById("file-browser").style.display = "none";
|
||||||
|
document.getElementById("search").style.display = "block";
|
||||||
|
document.getElementById("playlist-browser").style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tab_playlists.addEventListener("click", () => {
|
||||||
|
refreshPlaylists();
|
||||||
|
if (!tab_playlists.classList.contains("active")) {
|
||||||
|
tab_browser.classList.remove("active");
|
||||||
|
tab_search.classList.remove("active")
|
||||||
|
tab_playlists.classList.add("active")
|
||||||
|
document.getElementById("file-browser").style.display = "none";
|
||||||
|
document.getElementById("search").style.display = "none";
|
||||||
|
document.getElementById("playlist-browser").style.display = "block";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add API calls to controls
|
||||||
|
|
||||||
|
control_update_db.addEventListener("click", () => {
|
||||||
console.log("Issuing database update")
|
console.log("Issuing database update")
|
||||||
fetch(`${API_URL}/update_db`).then(async r => {
|
fetch(`${API_URL}/update_db`).then(async r => {
|
||||||
if (r.status === 200) {
|
if (r.status === 200) {
|
||||||
|
@ -472,3 +556,4 @@ window.setInterval(() => {
|
||||||
connection_state.innerHTML = "❌ Disconnected"; // ❌ Cross Mark
|
connection_state.innerHTML = "❌ Disconnected"; // ❌ Cross Mark
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue