add top tracks view to artist page
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"supersonic/backend"
|
"supersonic/backend"
|
||||||
"supersonic/res"
|
"supersonic/res"
|
||||||
|
"supersonic/sharedutil"
|
||||||
"supersonic/ui/controller"
|
"supersonic/ui/controller"
|
||||||
"supersonic/ui/layouts"
|
"supersonic/ui/layouts"
|
||||||
"supersonic/ui/util"
|
"supersonic/ui/util"
|
||||||
@@ -37,6 +38,9 @@ type ArtistPage struct {
|
|||||||
|
|
||||||
artistInfo *subsonic.ArtistID3
|
artistInfo *subsonic.ArtistID3
|
||||||
|
|
||||||
|
albumGrid *widgets.AlbumGrid
|
||||||
|
tracklistCtr *fyne.Container
|
||||||
|
nowPlayingID string
|
||||||
header *ArtistPageHeader
|
header *ArtistPageHeader
|
||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
@@ -51,9 +55,17 @@ func NewArtistPage(artistID string, pm *backend.PlaybackManager, sm *backend.Ser
|
|||||||
}}
|
}}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.header = NewArtistPageHeader(a)
|
a.header = NewArtistPageHeader(a)
|
||||||
|
viewToggle := widgets.NewToggleText(0, []string{"Discography", "Top Tracks"})
|
||||||
|
viewToggle.OnChanged = a.onViewChange
|
||||||
|
//line := canvas.NewLine(theme.TextColor())
|
||||||
|
viewToggleRow := container.NewBorder(nil, nil,
|
||||||
|
container.NewHBox(&widgets.HSpace{Width: 5}, viewToggle), nil,
|
||||||
|
layout.NewSpacer(),
|
||||||
|
)
|
||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
||||||
nil, nil, nil, layout.NewSpacer())
|
nil, nil, nil,
|
||||||
|
container.NewBorder(viewToggleRow, nil, nil, nil, layout.NewSpacer()))
|
||||||
go a.load()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
@@ -71,6 +83,17 @@ func (a *ArtistPage) Save() SavedPage {
|
|||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ CanShowNowPlaying = (*ArtistPage)(nil)
|
||||||
|
|
||||||
|
func (a *ArtistPage) OnSongChange(track *subsonic.Child, lastScrobbledIfAny *subsonic.Child) {
|
||||||
|
a.nowPlayingID = sharedutil.TrackIDOrEmptyStr(track)
|
||||||
|
if a.tracklistCtr != nil {
|
||||||
|
tl := a.tracklistCtr.Objects[0].(*widgets.Tracklist)
|
||||||
|
tl.SetNowPlaying(a.nowPlayingID)
|
||||||
|
tl.IncrementPlayCount(sharedutil.TrackIDOrEmptyStr(lastScrobbledIfAny))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ArtistPage) onPlayAlbum(albumID string) {
|
func (a *ArtistPage) onPlayAlbum(albumID string) {
|
||||||
a.pm.PlayAlbum(albumID, 0)
|
a.pm.PlayAlbum(albumID, 0)
|
||||||
}
|
}
|
||||||
@@ -97,11 +120,7 @@ func (a *ArtistPage) load() {
|
|||||||
}
|
}
|
||||||
a.artistInfo = artist
|
a.artistInfo = artist
|
||||||
a.header.Update(artist)
|
a.header.Update(artist)
|
||||||
ag := widgets.NewFixedAlbumGrid(artist.Album, a.im, true /*showYear*/)
|
a.showAlbumGrid()
|
||||||
ag.OnPlayAlbum = a.onPlayAlbum
|
|
||||||
ag.OnShowAlbumPage = a.onShowAlbumPage
|
|
||||||
a.container.Objects[0] = ag
|
|
||||||
a.container.Refresh()
|
|
||||||
info, err := a.sm.Server.GetArtistInfo2(a.artistID, nil)
|
info, err := a.sm.Server.GetArtistInfo2(a.artistID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get artist info: %s", err.Error())
|
log.Printf("Failed to get artist info: %s", err.Error())
|
||||||
@@ -109,6 +128,46 @@ func (a *ArtistPage) load() {
|
|||||||
a.header.UpdateInfo(info)
|
a.header.UpdateInfo(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPage) showAlbumGrid() {
|
||||||
|
if a.albumGrid == nil {
|
||||||
|
a.albumGrid = widgets.NewFixedAlbumGrid(a.artistInfo.Album, a.im, true /*showYear*/)
|
||||||
|
a.albumGrid.OnPlayAlbum = a.onPlayAlbum
|
||||||
|
a.albumGrid.OnShowAlbumPage = a.onShowAlbumPage
|
||||||
|
}
|
||||||
|
a.container.Objects[0].(*fyne.Container).Objects[0] = a.albumGrid
|
||||||
|
a.container.Objects[0].Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPage) showTopTracks() {
|
||||||
|
if a.tracklistCtr == nil {
|
||||||
|
ts, err := a.sm.Server.GetTopSongs(a.artistInfo.Name, map[string]string{"count": "20"})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("error getting top songs: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tl := widgets.NewTracklist(ts)
|
||||||
|
tl.AutoNumber = true
|
||||||
|
tl.SetVisibleColumns([]string{"Album", "Time", "Year", "Plays"})
|
||||||
|
tl.SetNowPlaying(a.nowPlayingID)
|
||||||
|
a.contr.ConnectTracklistActions(tl)
|
||||||
|
a.tracklistCtr = container.New(
|
||||||
|
&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadBottom: 10},
|
||||||
|
tl)
|
||||||
|
}
|
||||||
|
a.container.Objects[0].(*fyne.Container).Objects[0] = a.tracklistCtr
|
||||||
|
a.container.Objects[0].Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPage) onViewChange(num int) {
|
||||||
|
if num == 0 {
|
||||||
|
a.showAlbumGrid()
|
||||||
|
} else {
|
||||||
|
// needs to request info from server if first time,
|
||||||
|
// so call it asynchronously
|
||||||
|
go a.showTopTracks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ArtistPage) CreateRenderer() fyne.WidgetRenderer {
|
func (a *ArtistPage) CreateRenderer() fyne.WidgetRenderer {
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
return widget.NewSimpleRenderer(a.container)
|
return widget.NewSimpleRenderer(a.container)
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package widgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ToggleText struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
|
||||||
|
OnChanged func(int)
|
||||||
|
|
||||||
|
labels []string
|
||||||
|
activeLabelIdx int
|
||||||
|
container *fyne.Container
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewToggleText(activeLblIdx int, labels []string) *ToggleText {
|
||||||
|
t := &ToggleText{labels: labels, activeLabelIdx: activeLblIdx}
|
||||||
|
t.ExtendBaseWidget(t)
|
||||||
|
t.container = container.NewHBox()
|
||||||
|
for i, lbl := range labels {
|
||||||
|
if i == activeLblIdx {
|
||||||
|
t.container.Add(t.newBoldRichText(lbl))
|
||||||
|
} else {
|
||||||
|
hl := widget.NewHyperlink(lbl, nil)
|
||||||
|
hl.OnTapped = t.buildOnTapped(i)
|
||||||
|
t.container.Add(hl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ToggleText) buildOnTapped(i int) func() {
|
||||||
|
return func() {
|
||||||
|
t.onActivated(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ToggleText) newBoldRichText(text string) *widget.RichText {
|
||||||
|
return widget.NewRichText(&widget.TextSegment{
|
||||||
|
Text: text,
|
||||||
|
Style: widget.RichTextStyle{TextStyle: fyne.TextStyle{Bold: true}},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ToggleText) onActivated(idx int) {
|
||||||
|
if idx == t.activeLabelIdx {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// update old label to hyperlink
|
||||||
|
hl := widget.NewHyperlink(t.labels[t.activeLabelIdx], nil)
|
||||||
|
hl.OnTapped = t.buildOnTapped(t.activeLabelIdx)
|
||||||
|
t.container.Objects[t.activeLabelIdx] = hl
|
||||||
|
// update activated label to bold text
|
||||||
|
t.container.Objects[idx] = t.newBoldRichText(t.labels[idx])
|
||||||
|
t.activeLabelIdx = idx
|
||||||
|
t.Refresh()
|
||||||
|
if t.OnChanged != nil {
|
||||||
|
t.OnChanged(t.activeLabelIdx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ToggleText) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
return widget.NewSimpleRenderer(t.container)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user