Jellyfin does not support 5-star ratings - make it disableable
This commit is contained in:
@@ -312,10 +312,6 @@ func (j *jellyfinMediaProvider) SetFavorite(params mediaprovider.RatingFavoriteP
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *jellyfinMediaProvider) SetRating(params mediaprovider.RatingFavoriteParameters, rating int) error {
|
|
||||||
return errors.New("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *jellyfinMediaProvider) GetStreamURL(trackID string, forceRaw bool) (string, error) {
|
func (j *jellyfinMediaProvider) GetStreamURL(trackID string, forceRaw bool) (string, error) {
|
||||||
return j.client.GetStreamURL(trackID)
|
return j.client.GetStreamURL(trackID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,8 +109,6 @@ type MediaProvider interface {
|
|||||||
|
|
||||||
SetFavorite(params RatingFavoriteParameters, favorite bool) error
|
SetFavorite(params RatingFavoriteParameters, favorite bool) error
|
||||||
|
|
||||||
SetRating(params RatingFavoriteParameters, rating int) error
|
|
||||||
|
|
||||||
GetPlaylists() ([]*Playlist, error)
|
GetPlaylists() ([]*Playlist, error)
|
||||||
|
|
||||||
CreatePlaylist(name string, trackIDs []string) error
|
CreatePlaylist(name string, trackIDs []string) error
|
||||||
@@ -130,6 +128,10 @@ type MediaProvider interface {
|
|||||||
RescanLibrary() error
|
RescanLibrary() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SupportsRating interface {
|
||||||
|
SetRating(params RatingFavoriteParameters, rating int) error
|
||||||
|
}
|
||||||
|
|
||||||
func genresMatch(filterGenres, albumGenres []string) bool {
|
func genresMatch(filterGenres, albumGenres []string) bool {
|
||||||
for _, g1 := range filterGenres {
|
for _, g1 := range filterGenres {
|
||||||
for _, g2 := range albumGenres {
|
for _, g2 := range albumGenres {
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ func newAlbumPage(
|
|||||||
}
|
}
|
||||||
a.tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
a.tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
||||||
a.tracklist.SetSorting(sort)
|
a.tracklist.SetSorting(sort)
|
||||||
|
_, canRate := a.mp.(mediaprovider.SupportsRating)
|
||||||
|
a.tracklist.Options.DisableRating = !canRate
|
||||||
a.tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
a.tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
a.cfg.TracklistColumns = cols
|
a.cfg.TracklistColumns = cols
|
||||||
}
|
}
|
||||||
@@ -154,9 +156,7 @@ func (a *AlbumPage) load() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.header.Update(album, a.im)
|
a.header.Update(album, a.im)
|
||||||
a.tracklist.Options = widgets.TracklistOptions{
|
a.tracklist.Options.ShowDiscNumber = len(album.Tracks) > 0 && album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber
|
||||||
ShowDiscNumber: len(album.Tracks) > 0 && album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber,
|
|
||||||
}
|
|
||||||
a.tracks = album.Tracks
|
a.tracks = album.Tracks
|
||||||
a.tracklist.SetTracks(album.Tracks)
|
a.tracklist.SetTracks(album.Tracks)
|
||||||
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
||||||
|
|||||||
@@ -229,6 +229,8 @@ func (a *ArtistPage) showTopTracks() {
|
|||||||
tl = widgets.NewTracklist(ts)
|
tl = widgets.NewTracklist(ts)
|
||||||
}
|
}
|
||||||
tl.Options = widgets.TracklistOptions{AutoNumber: true}
|
tl.Options = widgets.TracklistOptions{AutoNumber: true}
|
||||||
|
_, canRate := a.mp.(mediaprovider.SupportsRating)
|
||||||
|
tl.Options.DisableRating = !canRate
|
||||||
tl.SetVisibleColumns(a.cfg.TracklistColumns)
|
tl.SetVisibleColumns(a.cfg.TracklistColumns)
|
||||||
tl.SetSorting(a.trackSort)
|
tl.SetSorting(a.trackSort)
|
||||||
tl.OnVisibleColumnsChanged = func(cols []string) {
|
tl.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
|
|||||||
@@ -370,6 +370,8 @@ func (a *FavoritesPage) onShowFavoriteSongs() {
|
|||||||
tracklist = widgets.NewTracklist(fav.Tracks)
|
tracklist = widgets.NewTracklist(fav.Tracks)
|
||||||
}
|
}
|
||||||
tracklist.Options = widgets.TracklistOptions{AutoNumber: true}
|
tracklist.Options = widgets.TracklistOptions{AutoNumber: true}
|
||||||
|
_, canRate := a.mp.(mediaprovider.SupportsRating)
|
||||||
|
tracklist.Options.DisableRating = !canRate
|
||||||
tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
||||||
tracklist.SetSorting(a.trackSort)
|
tracklist.SetSorting(a.trackSort)
|
||||||
tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
|
|||||||
@@ -37,11 +37,12 @@ type NowPlayingPage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type nowPlayingPageState struct {
|
type nowPlayingPageState struct {
|
||||||
contr *controller.Controller
|
contr *controller.Controller
|
||||||
pool *util.WidgetPool
|
pool *util.WidgetPool
|
||||||
conf *backend.NowPlayingPageConfig
|
conf *backend.NowPlayingPageConfig
|
||||||
pm *backend.PlaybackManager
|
pm *backend.PlaybackManager
|
||||||
p *player.Player
|
p *player.Player
|
||||||
|
canRate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNowPlayingPage(
|
func NewNowPlayingPage(
|
||||||
@@ -51,9 +52,10 @@ func NewNowPlayingPage(
|
|||||||
conf *backend.NowPlayingPageConfig,
|
conf *backend.NowPlayingPageConfig,
|
||||||
pm *backend.PlaybackManager,
|
pm *backend.PlaybackManager,
|
||||||
p *player.Player, // TODO: once other player backends are supported (eg uPnP), refactor
|
p *player.Player, // TODO: once other player backends are supported (eg uPnP), refactor
|
||||||
|
canRate bool,
|
||||||
) *NowPlayingPage {
|
) *NowPlayingPage {
|
||||||
a := &NowPlayingPage{nowPlayingPageState: nowPlayingPageState{
|
a := &NowPlayingPage{nowPlayingPageState: nowPlayingPageState{
|
||||||
contr: contr, pool: pool, conf: conf, pm: pm, p: p,
|
contr: contr, pool: pool, conf: conf, pm: pm, p: p, canRate: canRate,
|
||||||
}}
|
}}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
|
|
||||||
@@ -74,6 +76,7 @@ func NewNowPlayingPage(
|
|||||||
a.tracklist.Options = widgets.TracklistOptions{
|
a.tracklist.Options = widgets.TracklistOptions{
|
||||||
AutoNumber: true,
|
AutoNumber: true,
|
||||||
DisablePlaybackMenu: true,
|
DisablePlaybackMenu: true,
|
||||||
|
DisableRating: !canRate,
|
||||||
AuxiliaryMenuItems: []*fyne.MenuItem{
|
AuxiliaryMenuItems: []*fyne.MenuItem{
|
||||||
fyne.NewMenuItem("Remove from queue", a.onRemoveSelectedFromQueue),
|
fyne.NewMenuItem("Remove from queue", a.onRemoveSelectedFromQueue),
|
||||||
},
|
},
|
||||||
@@ -213,5 +216,5 @@ func (a *NowPlayingPage) load(highlightedTrackID string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *nowPlayingPageState) Restore() Page {
|
func (s *nowPlayingPageState) Restore() Page {
|
||||||
return NewNowPlayingPage("", s.contr, s.pool, s.conf, s.pm, s.p)
|
return NewNowPlayingPage("", s.contr, s.pool, s.conf, s.pm, s.p, s.canRate)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,9 @@ func newPlaylistPage(
|
|||||||
fyne.NewMenuItem("Move down", a.onMoveSelectedDown),
|
fyne.NewMenuItem("Move down", a.onMoveSelectedDown),
|
||||||
fyne.NewMenuItem("Move to bottom", a.onMoveSelectedToBottom),
|
fyne.NewMenuItem("Move to bottom", a.onMoveSelectedToBottom),
|
||||||
}...)
|
}...)
|
||||||
|
_, canRate := a.sm.Server.(mediaprovider.SupportsRating)
|
||||||
a.tracklist.Options = widgets.TracklistOptions{
|
a.tracklist.Options = widgets.TracklistOptions{
|
||||||
|
DisableRating: !canRate,
|
||||||
AuxiliaryMenuItems: []*fyne.MenuItem{reorderMenu,
|
AuxiliaryMenuItems: []*fyne.MenuItem{reorderMenu,
|
||||||
fyne.NewMenuItem("Remove from playlist", a.onRemoveSelectedFromPlaylist)},
|
fyne.NewMenuItem("Remove from playlist", a.onRemoveSelectedFromPlaylist)},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package browsing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
"github.com/dweymouth/supersonic/ui/controller"
|
"github.com/dweymouth/supersonic/ui/controller"
|
||||||
"github.com/dweymouth/supersonic/ui/util"
|
"github.com/dweymouth/supersonic/ui/util"
|
||||||
)
|
)
|
||||||
@@ -45,7 +46,8 @@ func (r Router) CreatePage(rte controller.Route) Page {
|
|||||||
case controller.Genres:
|
case controller.Genres:
|
||||||
return NewGenresPage(r.Controller, r.App.ServerManager.Server)
|
return NewGenresPage(r.Controller, r.App.ServerManager.Server)
|
||||||
case controller.NowPlaying:
|
case controller.NowPlaying:
|
||||||
return NewNowPlayingPage(rte.Arg, r.Controller, r.widgetPool, &r.App.Config.NowPlayingPage, r.App.PlaybackManager, r.App.Player)
|
_, canRate := r.App.ServerManager.Server.(mediaprovider.SupportsRating)
|
||||||
|
return NewNowPlayingPage(rte.Arg, r.Controller, r.widgetPool, &r.App.Config.NowPlayingPage, r.App.PlaybackManager, r.App.Player, canRate)
|
||||||
case controller.Playlist:
|
case controller.Playlist:
|
||||||
return NewPlaylistPage(rte.Arg, &r.App.Config.PlaylistPage, r.widgetPool, r.Controller, r.App.ServerManager, r.App.PlaybackManager, r.App.ImageManager)
|
return NewPlaylistPage(rte.Arg, &r.App.Config.PlaylistPage, r.widgetPool, r.Controller, r.App.ServerManager, r.App.PlaybackManager, r.App.ImageManager)
|
||||||
case controller.Playlists:
|
case controller.Playlists:
|
||||||
|
|||||||
@@ -51,8 +51,10 @@ func NewTracksPage(contr *controller.Controller, conf *backend.TracksPageConfig,
|
|||||||
} else {
|
} else {
|
||||||
t.tracklist = widgets.NewTracklist(nil)
|
t.tracklist = widgets.NewTracklist(nil)
|
||||||
}
|
}
|
||||||
|
_, canRate := mp.(mediaprovider.SupportsRating)
|
||||||
t.tracklist.Options = widgets.TracklistOptions{
|
t.tracklist.Options = widgets.TracklistOptions{
|
||||||
DisableSorting: true,
|
DisableSorting: true,
|
||||||
|
DisableRating: !canRate,
|
||||||
AutoNumber: true,
|
AutoNumber: true,
|
||||||
}
|
}
|
||||||
t.tracklist.SetVisibleColumns(conf.TracklistColumns)
|
t.tracklist.SetVisibleColumns(conf.TracklistColumns)
|
||||||
|
|||||||
@@ -577,7 +577,11 @@ func (c *Controller) SetTrackFavorites(trackIDs []string, favorite bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) SetTrackRatings(trackIDs []string, rating int) {
|
func (c *Controller) SetTrackRatings(trackIDs []string, rating int) {
|
||||||
go c.App.ServerManager.Server.SetRating(mediaprovider.RatingFavoriteParameters{
|
r, ok := c.App.ServerManager.Server.(mediaprovider.SupportsRating)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go r.SetRating(mediaprovider.RatingFavoriteParameters{
|
||||||
TrackIDs: trackIDs,
|
TrackIDs: trackIDs,
|
||||||
}, rating)
|
}, rating)
|
||||||
|
|
||||||
|
|||||||
@@ -15,15 +15,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
themedResStarFilled = theme.NewThemedResource(res.ResStarFilledSvg)
|
themedResStarFilled = theme.NewThemedResource(res.ResStarFilledSvg)
|
||||||
themedResStarOutline = theme.NewThemedResource(res.ResStarOutlineSvg)
|
themedResStarOutline = theme.NewThemedResource(res.ResStarOutlineSvg)
|
||||||
|
themedDisabledStarOutline = theme.NewDisabledResource(res.ResStarOutlineSvg)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ fyne.Disableable = (*StarRating)(nil)
|
||||||
|
|
||||||
type StarRating struct {
|
type StarRating struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
Rating int
|
IsDisabled bool
|
||||||
StarSize float32
|
Rating int
|
||||||
|
StarSize float32
|
||||||
|
|
||||||
OnRatingChanged func(int)
|
OnRatingChanged func(int)
|
||||||
|
|
||||||
@@ -44,7 +48,9 @@ func (s *StarRating) createContainer() {
|
|||||||
})
|
})
|
||||||
var im *canvas.Image
|
var im *canvas.Image
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
if s.Rating > i {
|
if s.IsDisabled {
|
||||||
|
im = canvas.NewImageFromResource(themedDisabledStarOutline)
|
||||||
|
} else if s.Rating > i {
|
||||||
im = canvas.NewImageFromResource(themedResStarFilled)
|
im = canvas.NewImageFromResource(themedResStarFilled)
|
||||||
} else {
|
} else {
|
||||||
im = canvas.NewImageFromResource(themedResStarOutline)
|
im = canvas.NewImageFromResource(themedResStarOutline)
|
||||||
@@ -61,6 +67,9 @@ func (s *StarRating) MouseIn(e *desktop.MouseEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *StarRating) MouseMoved(e *desktop.MouseEvent) {
|
func (s *StarRating) MouseMoved(e *desktop.MouseEvent) {
|
||||||
|
if s.IsDisabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
hoverRating := int(math.Ceil(5 * float64(e.Position.X/s.Size().Width)))
|
hoverRating := int(math.Ceil(5 * float64(e.Position.X/s.Size().Width)))
|
||||||
if s.mouseHoverRating != hoverRating {
|
if s.mouseHoverRating != hoverRating {
|
||||||
s.holdRating = false
|
s.holdRating = false
|
||||||
@@ -69,7 +78,24 @@ func (s *StarRating) MouseMoved(e *desktop.MouseEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *StarRating) Disable() {
|
||||||
|
s.IsDisabled = true
|
||||||
|
s.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StarRating) Enable() {
|
||||||
|
s.IsDisabled = false
|
||||||
|
s.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StarRating) Disabled() bool {
|
||||||
|
return s.IsDisabled
|
||||||
|
}
|
||||||
|
|
||||||
func (s *StarRating) MouseOut() {
|
func (s *StarRating) MouseOut() {
|
||||||
|
if s.IsDisabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
s.mouseHoverRating = 0
|
s.mouseHoverRating = 0
|
||||||
s.holdRating = false
|
s.holdRating = false
|
||||||
s.Refresh()
|
s.Refresh()
|
||||||
@@ -105,7 +131,9 @@ func (s *StarRating) Refresh() {
|
|||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
im := s.container.Objects[i].(*canvas.Image)
|
im := s.container.Objects[i].(*canvas.Image)
|
||||||
im.SetMinSize(fyne.NewSize(s.StarSize, s.StarSize))
|
im.SetMinSize(fyne.NewSize(s.StarSize, s.StarSize))
|
||||||
if rating > i {
|
if s.IsDisabled {
|
||||||
|
im.Resource = themedDisabledStarOutline
|
||||||
|
} else if rating > i {
|
||||||
im.Resource = themedResStarFilled
|
im.Resource = themedResStarFilled
|
||||||
} else {
|
} else {
|
||||||
im.Resource = themedResStarOutline
|
im.Resource = themedResStarOutline
|
||||||
|
|||||||
@@ -66,6 +66,9 @@ type TracklistOptions struct {
|
|||||||
|
|
||||||
// Disables sorting the tracklist by clicking individual columns.
|
// Disables sorting the tracklist by clicking individual columns.
|
||||||
DisableSorting bool
|
DisableSorting bool
|
||||||
|
|
||||||
|
// Disables the five star rating widget.
|
||||||
|
DisableRating bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tracklist struct {
|
type Tracklist struct {
|
||||||
@@ -732,6 +735,7 @@ func NewTrackRow(tracklist *Tracklist, playingIcon fyne.CanvasObject) *TrackRow
|
|||||||
favorite.OnTapped = t.toggleFavorited
|
favorite.OnTapped = t.toggleFavorited
|
||||||
t.favorite = container.NewCenter(favorite)
|
t.favorite = container.NewCenter(favorite)
|
||||||
t.rating = NewStarRating()
|
t.rating = NewStarRating()
|
||||||
|
t.rating.IsDisabled = t.tracklist.Options.DisableRating
|
||||||
t.rating.StarSize = 16
|
t.rating.StarSize = 16
|
||||||
t.rating.OnRatingChanged = t.setTrackRating
|
t.rating.OnRatingChanged = t.setTrackRating
|
||||||
t.plays = newTrailingAlignLabel()
|
t.plays = newTrailingAlignLabel()
|
||||||
@@ -842,6 +846,7 @@ func (t *TrackRow) Update(tm *trackModel, rowNum int) {
|
|||||||
t.dur.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnTime)]
|
t.dur.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnTime)]
|
||||||
t.year.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnYear)]
|
t.year.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnYear)]
|
||||||
t.favorite.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnFavorite)]
|
t.favorite.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnFavorite)]
|
||||||
|
t.rating.IsDisabled = t.tracklist.Options.DisableRating
|
||||||
t.rating.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnRating)]
|
t.rating.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnRating)]
|
||||||
t.plays.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnPlays)]
|
t.plays.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnPlays)]
|
||||||
t.bitrate.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnBitrate)]
|
t.bitrate.Hidden = !t.tracklist.visibleColumns[ColNumber(ColumnBitrate)]
|
||||||
|
|||||||
Reference in New Issue
Block a user