Liked Songs Implementation

This commit is contained in:
aditya-K2
2023-04-12 02:49:55 +05:30
parent 64b6f77ff2
commit c93d68ef57
5 changed files with 142 additions and 8 deletions

View File

@@ -20,6 +20,7 @@ type Album struct {
type SavedAlbums []spotify.SavedAlbum
type UserPlaylists []spotify.SimplePlaylist
type LikedSongs []spotify.SavedTrack
type Playable interface {
Type() string
@@ -180,3 +181,34 @@ func CurrentUserPlaylists(done func(status bool, err error)) (*UserPlaylists, er
return playlists, nil
}
}
// CurrentUserSavedTracks returns the LikedSongs of the current user in a
// specific manner. It returns the first page and then starts a go routine in
// the background and keeps updating the LikedSongs and calls the done
// function with a status of true and nil error if successful else calls the
// done function with a status of false and the corresponding error.
func CurrentUserSavedTracks(done func(status bool, err error)) (*LikedSongs, error) {
_p := make(LikedSongs, 0)
playlists := &_p
if ls, err := Client.CurrentUsersTracks(ctx()); err != nil {
return nil, err
} else {
addTracks := func() {
_p = append(_p, ls.Tracks...)
}
addTracks()
go func() {
for page := 1; ; page++ {
if perr := Client.NextPage(ctx(), ls); perr == spotify.ErrNoMorePages {
done(true, nil)
break
} else if perr != nil {
done(false, perr)
return
}
addTracks()
}
}()
return playlists, nil
}
}

View File

@@ -38,7 +38,12 @@ func NewApplication() *Application {
NavMenu := newNavMenu([]navItem{
{"Albums", NewAction(func(e *tcell.EventKey) *tcell.EventKey { SetCurrentView(albumsView); return nil }, nil)},
{"Artists", NewAction(func(e *tcell.EventKey) *tcell.EventKey { fmt.Println("Artists"); return nil }, nil)},
{"Liked Songs", NewAction(func(e *tcell.EventKey) *tcell.EventKey { fmt.Println("Liked Songs"); return nil }, nil)},
{"Liked Songs", NewAction(func(e *tcell.EventKey) *tcell.EventKey {
likedSongsView.RefreshState()
SetCurrentView(likedSongsView)
App.SetFocus(Main.Table)
return nil
}, nil)},
{"Recently Played", NewAction(func(e *tcell.EventKey) *tcell.EventKey { fmt.Println("Recently Played"); return nil }, nil)},
})
imagePreviewer := tview.NewBox()
@@ -61,13 +66,14 @@ func NewApplication() *Application {
panic(err)
}
Root.AfterContextClose(func() { App.SetFocus(Main.Table) })
playlistNav.Table.SetBackgroundColor(tcell.ColorDefault)
PlaylistActions = map[string]*Action{
"playEntry": NewAction(playlistNav.PlaySelectEntry, nil),
"openEntry": NewAction(func(e *tcell.EventKey) *tcell.EventKey {
Root.AfterContextClose(func() { App.SetFocus(Main.Table) })
r, _ := playlistNav.Table.GetSelection()
playlistView.SetPlaylist(&(*playlistNav.Playlists)[r])
SetCurrentView(playlistView)
App.SetFocus(Main.Table)
return nil
}, nil),

View File

@@ -22,7 +22,7 @@ func newNavMenu(m []navItem) *NavMenu {
T.SetDrawFunc(func(tcell.Screen, int, int, int, int) (int, int, int, int) {
for k := range n.m {
T.SetCell(k, 0,
GetCell(n.m[k].name, tcell.StyleDefault.Foreground(tcell.ColorRed)))
GetCell(n.m[k].name, tcell.StyleDefault.Foreground(tcell.Color64)))
}
return T.GetInnerRect()
})
@@ -70,7 +70,7 @@ func NewPlaylistNav(done func(s bool, e error)) (*PlaylistNav, error) {
func (v *PlaylistNav) Draw() {
for k, p := range *v.Playlists {
v.Table.SetCell(k, 0,
GetCell(p.Name, tcell.StyleDefault.Foreground(tcell.ColorRed)))
GetCell(p.Name, tcell.StyleDefault.Foreground(tcell.ColorTeal)))
}
}

View File

@@ -3,10 +3,11 @@ package ui
import "github.com/gdamore/tcell/v2"
var (
CurrentView View
playlistView = &PlaylistView{}
albumView = &AlbumView{}
albumsView = &AlbumsView{}
CurrentView View
playlistView = &PlaylistView{}
albumView = &AlbumView{}
albumsView = &AlbumsView{}
likedSongsView = &LikedSongsView{}
)
type View interface {

95
ui/view_liked.go Normal file
View File

@@ -0,0 +1,95 @@
package ui
import (
"fmt"
"github.com/aditya-K2/gspt/spt"
"github.com/gdamore/tcell/v2"
"github.com/zmb3/spotify/v2"
)
type LikedSongsView struct {
*PlaylistView
likedSongs *spt.LikedSongs
}
func (p *LikedSongsView) Content() func() [][]Content {
return func() [][]Content {
c := make([][]Content, 0)
if p.likedSongs == nil {
msg := SendNotificationWithChan("Loading Liked Songs...")
if err := p.refreshState(func(s bool, e error) {
go func() {
if !s {
msg <- e.Error()
} else {
msg <- "Done"
}
}()
}); err != nil {
SendNotification(err.Error())
return c
}
}
for _, v := range *p.likedSongs {
c = append(c, []Content{
{Content: v.Name, Style: Defaultstyle.Foreground(tcell.ColorBlue)},
{Content: v.Artists[0].Name, Style: Defaultstyle.Foreground(tcell.ColorPink)},
{Content: v.Album.Name, Style: Defaultstyle.Foreground(tcell.ColorGreen)},
})
}
return c
}
}
func (l *LikedSongsView) ContextHandler() func(start, end, sel int) {
return func(start, end, sel int) {
// Assuming that there are no external effects on the user's playlists
// (i.e Any Creation or Deletion of Playlists while the context Menu is
// open
userPlaylists, err := spt.CurrentUserPlaylists(func(s bool, err error) {})
if err != nil {
SendNotification("Error Retrieving User Playlists")
return
}
tracks := make([]spotify.ID, 0)
for k := start; k <= end; k++ {
tracks = append(tracks, (*l.likedSongs)[k].ID)
}
aerr := spt.AddTracksToPlaylist((*userPlaylists)[sel].ID, tracks...)
if aerr != nil {
SendNotification(aerr.Error())
return
} else {
SendNotification(fmt.Sprintf("Added %d tracks to %s", len(tracks), (*userPlaylists)[sel].Name))
}
}
}
func (l *LikedSongsView) ExternalInputCapture() func(e *tcell.EventKey) *tcell.EventKey {
return func(e *tcell.EventKey) *tcell.EventKey {
if e.Key() == tcell.KeyEnter {
r, _ := Ui.Main.Table.GetSelection()
if err := spt.PlaySong((*l.likedSongs)[r].URI); err != nil {
SendNotification(err.Error())
}
}
return e
}
}
func (l *LikedSongsView) refreshState(f func(bool, error)) error {
pf, err := spt.CurrentUserSavedTracks(f)
if err == nil {
l.likedSongs = pf
}
return err
}
func (l *LikedSongsView) Name() string { return "LikedSongsView" }
func (l *LikedSongsView) RefreshState() {
if err := l.refreshState(func(bool, error) {}); err != nil {
SendNotification(err.Error())
}
}