add lyrics to sidebar
This commit is contained in:
+3
-3
@@ -69,7 +69,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
}
|
}
|
||||||
m.Controller = controller.New(app, appVersion, m.Window)
|
m.Controller = controller.New(app, appVersion, m.Window)
|
||||||
m.BrowsingPane = browsing.NewBrowsingPane(app.PlaybackManager, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) })
|
m.BrowsingPane = browsing.NewBrowsingPane(app.PlaybackManager, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) })
|
||||||
m.Sidebar = NewSidebar(m.Controller, m.App.ImageManager)
|
m.Sidebar = NewSidebar(m.Controller, m.App.PlaybackManager, m.App.ImageManager, m.App.LyricsManager)
|
||||||
m.ToastOverlay = NewToastOverlay()
|
m.ToastOverlay = NewToastOverlay()
|
||||||
m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane)
|
m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane)
|
||||||
goHomeFn := func() { m.Router.NavigateTo(m.StartupPage()) }
|
goHomeFn := func() { m.Router.NavigateTo(m.StartupPage()) }
|
||||||
@@ -167,12 +167,12 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
func (m *MainWindow) UpdateOnTrackChange(item mediaprovider.MediaItem) {
|
func (m *MainWindow) UpdateOnTrackChange(item mediaprovider.MediaItem) {
|
||||||
if item == nil {
|
if item == nil {
|
||||||
m.Window.SetTitle(res.DisplayName)
|
m.Window.SetTitle(res.DisplayName)
|
||||||
m.Sidebar.SetNowPlaying("")
|
m.Sidebar.SetNowPlaying(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := item.Metadata()
|
meta := item.Metadata()
|
||||||
m.Sidebar.SetNowPlaying(meta.ID)
|
m.Sidebar.SetNowPlaying(item)
|
||||||
artistDisp := ""
|
artistDisp := ""
|
||||||
if tr, ok := item.(*mediaprovider.Track); ok {
|
if tr, ok := item.(*mediaprovider.Track); ok {
|
||||||
artistDisp = " – " + strings.Join(tr.ArtistNames, ", ")
|
artistDisp = " – " + strings.Join(tr.ArtistNames, ", ")
|
||||||
|
|||||||
+100
-7
@@ -15,15 +15,58 @@ import (
|
|||||||
type Sidebar struct {
|
type Sidebar struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
queueList *widgets.PlayQueueList
|
lm *backend.LyricsManager
|
||||||
|
|
||||||
|
queueList *widgets.PlayQueueList
|
||||||
|
lyricsViewer *widgets.LyricsViewer
|
||||||
|
lyricsLoading *widgets.LoadingDots
|
||||||
|
tabs *container.AppTabs
|
||||||
|
|
||||||
|
nowPlaying mediaprovider.MediaItem
|
||||||
|
nowPlayingID string
|
||||||
|
curLyrics *mediaprovider.Lyrics
|
||||||
|
curLyricsID string
|
||||||
|
lastPlayPos float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSidebar(contr *controller.Controller, im *backend.ImageManager) *Sidebar {
|
func NewSidebar(contr *controller.Controller, pm *backend.PlaybackManager, im *backend.ImageManager, lm *backend.LyricsManager) *Sidebar {
|
||||||
s := &Sidebar{
|
s := &Sidebar{
|
||||||
|
lm: lm,
|
||||||
queueList: widgets.NewPlayQueueList(im, false),
|
queueList: widgets.NewPlayQueueList(im, false),
|
||||||
}
|
}
|
||||||
s.queueList.Reorderable = true
|
s.queueList.Reorderable = true
|
||||||
contr.ConnectPlayQueuelistActions(s.queueList)
|
contr.ConnectPlayQueuelistActions(s.queueList)
|
||||||
|
|
||||||
|
s.lyricsViewer = widgets.NewLyricsViewer(func(i int) {
|
||||||
|
if s.curLyrics != nil && len(s.curLyrics.Lines) > i-1 {
|
||||||
|
time := s.curLyrics.Lines[i-1].Start
|
||||||
|
pm.SeekSeconds(time)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
s.lyricsLoading = widgets.NewLoadingDots()
|
||||||
|
|
||||||
|
s.tabs = container.NewAppTabs(
|
||||||
|
container.NewTabItem(lang.L("Play Queue"), container.NewPadded(s.queueList)),
|
||||||
|
container.NewTabItem(lang.L("Lyrics"), container.NewStack(
|
||||||
|
s.lyricsViewer,
|
||||||
|
container.NewCenter(s.lyricsLoading))),
|
||||||
|
)
|
||||||
|
s.tabs.OnSelected = func(*container.TabItem) {
|
||||||
|
idx := s.tabs.SelectedIndex()
|
||||||
|
if idx == 1 /*lyrics*/ {
|
||||||
|
s.updateLyrics()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.OnPlayTimeUpdate(func(curTime, _ float64, seeked bool) {
|
||||||
|
s.lastPlayPos = curTime
|
||||||
|
if seeked {
|
||||||
|
fyne.Do(func() { s.lyricsViewer.OnSeeked(curTime) })
|
||||||
|
} else {
|
||||||
|
fyne.Do(func() { s.lyricsViewer.UpdatePlayPos(curTime) })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
s.ExtendBaseWidget(s)
|
s.ExtendBaseWidget(s)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -32,15 +75,65 @@ func (s *Sidebar) SetQueueTracks(items []mediaprovider.MediaItem) {
|
|||||||
s.queueList.SetItems(items)
|
s.queueList.SetItems(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sidebar) SetNowPlaying(itemID string) {
|
func (s *Sidebar) SetNowPlaying(item mediaprovider.MediaItem) {
|
||||||
s.queueList.SetNowPlaying(itemID)
|
s.nowPlaying = item
|
||||||
|
id := ""
|
||||||
|
if item != nil {
|
||||||
|
id = item.Metadata().ID
|
||||||
|
}
|
||||||
|
s.queueList.SetNowPlaying(id)
|
||||||
|
s.nowPlayingID = id
|
||||||
|
if s.tabs.SelectedIndex() == 1 /*lyrics*/ {
|
||||||
|
s.updateLyrics()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this is more or less copy-paste from the Now Playing page
|
||||||
|
// refactor this shared logic somewhere else?
|
||||||
|
func (s *Sidebar) updateLyrics() {
|
||||||
|
if s.nowPlayingID == s.curLyricsID {
|
||||||
|
if s.nowPlayingID != "" {
|
||||||
|
// just need to sync the current time
|
||||||
|
s.lyricsViewer.OnSeeked(s.lastPlayPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.nowPlaying == nil || s.nowPlaying.Metadata().Type == mediaprovider.MediaItemTypeRadioStation {
|
||||||
|
s.lyricsViewer.SetLyrics(nil)
|
||||||
|
s.curLyrics = nil
|
||||||
|
s.curLyricsID = ""
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.curLyricsID = s.nowPlayingID
|
||||||
|
s.lyricsLoading.Start()
|
||||||
|
// set the widget to an empty (not nil) lyric during fetch
|
||||||
|
// to keep it from showing "Lyrics not available"
|
||||||
|
s.lyricsViewer.DisableTapToSeek()
|
||||||
|
s.lyricsViewer.SetLyrics(&mediaprovider.Lyrics{
|
||||||
|
Synced: true,
|
||||||
|
Lines: []mediaprovider.LyricLine{{Text: ""}},
|
||||||
|
})
|
||||||
|
tr, _ := s.nowPlaying.(*mediaprovider.Track)
|
||||||
|
|
||||||
|
s.lm.FetchLyricsAsync(tr, func(id string, lyrics *mediaprovider.Lyrics) {
|
||||||
|
if id != s.nowPlayingID {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fyne.Do(func() {
|
||||||
|
s.lyricsLoading.Stop()
|
||||||
|
s.lyricsViewer.EnableTapToSeek()
|
||||||
|
s.lyricsViewer.SetLyrics(lyrics)
|
||||||
|
s.curLyrics = lyrics
|
||||||
|
if lyrics != nil {
|
||||||
|
s.lyricsViewer.OnSeeked(s.lastPlayPos)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sidebar) CreateRenderer() fyne.WidgetRenderer {
|
func (s *Sidebar) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(container.NewStack(
|
return widget.NewSimpleRenderer(container.NewStack(
|
||||||
theme.NewThemedRectangle(theme.ColorNamePageBackground),
|
theme.NewThemedRectangle(theme.ColorNamePageBackground),
|
||||||
container.NewAppTabs(
|
container.NewPadded(s.tabs),
|
||||||
container.NewTabItem(lang.L("Play Queue"), container.NewPadded(s.queueList)),
|
|
||||||
),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user