use dynamic gradient as background of Now Playing page

This commit is contained in:
Drew Weymouth
2024-05-29 07:22:08 -07:00
parent e455501b2d
commit 906c951cc9
5 changed files with 65 additions and 9 deletions
+48 -8
View File
@@ -4,11 +4,14 @@ import (
"context"
"fmt"
"image"
"image/color"
"log"
"slices"
"strings"
"sync"
"time"
"github.com/cenkalti/dominantcolor"
"github.com/dweymouth/supersonic/backend"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/backend/player"
@@ -21,6 +24,7 @@ import (
"github.com/dweymouth/supersonic/ui/widgets"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
@@ -46,6 +50,7 @@ type NowPlayingPage struct {
relatedLock sync.Mutex
// widgets for render
background *canvas.LinearGradient
queueList *widgets.PlayQueueList
relatedList *widgets.PlayQueueList
lyricsViewer *widgets.LyricsViewer
@@ -201,13 +206,18 @@ func (a *NowPlayingPage) CreateRenderer() fyne.WidgetRenderer {
} else if initialTab == 2 /*related*/ {
a.updateRelatedList()
}
c := theme.Color(myTheme.ColorNamePageBackground)
a.background = canvas.NewLinearGradient(c, c, 0)
mainContent := container.NewGridWithColumns(2,
container.New(paddedLayout, a.card),
container.New(paddedLayout,
container.NewStack(
util.AddHeaderBackground(a.tabs),
util.AddHeaderBackgroundWithColorName(
a.tabs, myTheme.ColorNameNowPlayingPanel),
container.NewCenter(a.tabLoading))))
a.container = container.NewStack(
a.background,
mainContent,
container.NewVBox(
layout.NewSpacer(),
@@ -248,13 +258,7 @@ func (a *NowPlayingPage) OnSongChange(song, _ *mediaprovider.Track) {
if song == nil {
a.card.SetCoverImage(nil)
} else {
a.imageLoadCancel = a.im.GetFullSizeCoverArtAsync(song.CoverArtID, func(img image.Image, err error) {
if err != nil {
log.Printf("error loading cover art: %v\n", err)
} else {
a.card.SetCoverImage(img)
}
})
a.imageLoadCancel = a.im.GetFullSizeCoverArtAsync(song.CoverArtID, a.onImageLoaded)
}
if a.tabs != nil && a.tabs.SelectedIndex() == 1 /*lyrics*/ {
@@ -264,6 +268,31 @@ func (a *NowPlayingPage) OnSongChange(song, _ *mediaprovider.Track) {
}
}
func (a *NowPlayingPage) onImageLoaded(img image.Image, err error) {
if err != nil {
log.Printf("error loading cover art: %v\n", err)
return
}
a.card.SetCoverImage(img)
c := dominantcolor.Find(img)
if c == a.background.StartColor {
return
}
evenFrame := true
anim := canvas.NewColorRGBAAnimation(
a.background.StartColor, c, 50*time.Millisecond, func(c color.Color) {
// reduce fps to reduce mem allocations
if evenFrame {
a.background.StartColor = c
a.background.Refresh()
}
evenFrame = !evenFrame
})
anim.Start()
}
func (a *NowPlayingPage) updateLyrics() {
a.lyricLock.Lock()
defer a.lyricLock.Unlock()
@@ -413,6 +442,17 @@ func (a *NowPlayingPage) Tapped(*fyne.PointEvent) {
a.queueList.UnselectAll()
}
func (a *NowPlayingPage) Refresh() {
if a.background != nil {
c := theme.Color(myTheme.ColorNamePageBackground)
if c != a.background.EndColor {
a.background.EndColor = c
a.background.Refresh()
}
}
a.BaseWidget.Refresh()
}
func (a *NowPlayingPage) doSetNewTrackOrder(trackIDs []string, op sharedutil.TrackReorderOp) {
trackIDSet := sharedutil.ToSet(trackIDs)
idxs := make([]int, 0, len(trackIDs))
+5
View File
@@ -25,6 +25,7 @@ const (
ColorNameInactiveLyric fyne.ThemeColorName = "InactiveLyric"
ColorNameIconButton fyne.ThemeColorName = "IconButton"
ColorNameHoveredIconButton fyne.ThemeColorName = "HoveredIconButton"
ColorNameNowPlayingPanel fyne.ThemeColorName = "NowPlayingPanel"
)
var (
@@ -124,6 +125,10 @@ func (m *MyTheme) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Col
return darkenColor(foreground, 0.05)
}
return brightenColor(foreground, 0.2)
case ColorNameNowPlayingPanel:
pageHeader := colorOrDefault(colors.PageHeader, defColors.PageHeader, name, variant).(color.RGBA)
pageHeader.A = 180
return pageHeader
case ColorNameListHeader:
return colorOrDefault(colors.ListHeader, defColors.ListHeader, name, variant)
case ColorNamePageBackground:
+5 -1
View File
@@ -204,7 +204,11 @@ func NewReorderTracksSubmenu(onReorderTracks func(sharedutil.TrackReorderOp)) *f
}
func AddHeaderBackground(obj fyne.CanvasObject) *fyne.Container {
bgrnd := myTheme.NewThemedRectangle(myTheme.ColorNamePageHeader)
return AddHeaderBackgroundWithColorName(obj, myTheme.ColorNamePageBackground)
}
func AddHeaderBackgroundWithColorName(obj fyne.CanvasObject, colorName fyne.ThemeColorName) *fyne.Container {
bgrnd := myTheme.NewThemedRectangle(colorName)
bgrnd.CornerRadiusName = theme.SizeNameInputRadius
return container.NewStack(bgrnd,
container.New(&layout.CustomPaddedLayout{LeftPadding: 10, RightPadding: 10, TopPadding: 10, BottomPadding: 10},