Files
supersonic/ui/widgets/playqueuelist.go
T
2024-03-02 13:34:09 -08:00

154 lines
3.6 KiB
Go

package widgets
import (
"sync"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/widget"
"github.com/dweymouth/supersonic/ui/layouts"
"github.com/dweymouth/supersonic/ui/os"
"github.com/dweymouth/supersonic/ui/theme"
"github.com/dweymouth/supersonic/ui/util"
)
type PlayQueueList struct {
FocusList
OnShowArtistPage func(artistID string)
OnPlayTrackAt func(idx int)
nowPlayingID string
colLayout *layouts.ColumnsLayout
tracksMutex sync.Mutex
tracks []*util.TrackListModel
}
func (t *PlayQueueList) onArtistTapped(artistID string) {
if t.OnShowArtistPage != nil {
t.OnShowArtistPage(artistID)
}
}
func (p *PlayQueueList) onPlayTrackAt(idx int) {
if p.OnPlayTrackAt != nil {
p.OnPlayTrackAt(idx)
}
}
func (p *PlayQueueList) onSelectTrack(idx int) {
if d, ok := fyne.CurrentApp().Driver().(desktop.Driver); ok {
mod := d.CurrentKeyModifiers()
if mod&os.ControlModifier != 0 {
p.selectAddOrRemove(idx)
} else if mod&fyne.KeyModifierShift != 0 {
p.selectRange(idx)
} else {
p.selectTrack(idx)
}
} else {
p.selectTrack(idx)
}
p.Refresh()
}
func (p *PlayQueueList) selectTrack(idx int) {
p.tracksMutex.Lock()
defer p.tracksMutex.Unlock()
util.SelectTrack(p.tracks, idx)
}
func (p *PlayQueueList) selectAddOrRemove(idx int) {
p.tracksMutex.Lock()
defer p.tracksMutex.Unlock()
p.tracks[idx].Selected = !p.tracks[idx].Selected
}
func (p *PlayQueueList) selectRange(idx int) {
p.tracksMutex.Lock()
defer p.tracksMutex.Unlock()
util.SelectTrackRange(p.tracks, idx)
}
type PlayQueueListRow struct {
FocusListRowBase
playQueueList *PlayQueueList
trackID string
isPlaying bool
playingIcon fyne.CanvasObject
num *widget.Label
cover *ImagePlaceholder
title *widget.Label
artist *MultiHyperlink
time *widget.Label
}
func NewPlayQueueListRow(playQueueList *PlayQueueList, playingIcon fyne.CanvasObject) *PlayQueueListRow {
p := &PlayQueueListRow{
playingIcon: playingIcon,
playQueueList: playQueueList,
num: widget.NewLabel(""),
cover: NewImagePlaceholder(theme.TracksIcon, 64),
title: util.NewTruncatingLabel(),
artist: NewMultiHyperlink(),
time: util.NewTrailingAlignLabel(),
}
p.artist.OnTapped = playQueueList.onArtistTapped
p.OnDoubleTapped = func() {
playQueueList.onPlayTrackAt(p.ItemID())
}
p.OnTapped = func() {
playQueueList.onSelectTrack(p.ItemID())
}
//p.title.TextStyle.Bold = true
p.ExtendBaseWidget(p)
p.Content = container.New(playQueueList.colLayout,
container.NewCenter(p.num),
p.cover,
container.New(&layouts.VboxCustomPadding{ExtraPad: -15},
p.title, p.artist),
container.NewCenter(p.time),
)
return p
}
func (p *PlayQueueListRow) Update(tm *util.TrackListModel, rowNum int) {
changed := false
if tm.Selected != p.Selected {
p.Selected = tm.Selected
changed = true
}
// Update info that can change if this row is bound to
// a new track (*mediaprovider.Track)
tr := tm.Track
if tr.ID != p.trackID {
p.EnsureUnfocused()
p.trackID = tr.ID
p.artist.BuildSegments(tr.ArtistNames, tr.ArtistIDs)
p.time.Text = util.SecondsToTimeString(float64(tr.Duration))
changed = true
}
// Render whether track is playing or not
if isPlaying := p.playQueueList.nowPlayingID == tr.ID; isPlaying != p.isPlaying {
p.isPlaying = isPlaying
p.title.TextStyle.Bold = isPlaying
if isPlaying {
p.Content.(*fyne.Container).Objects[0] = p.playingIcon
} else {
p.Content.(*fyne.Container).Objects[0] = p.num
}
changed = true
}
if changed {
p.Refresh()
}
}