From fc858e102457a8cec34e2f151cd65d0fdd78f9d7 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Tue, 27 Dec 2022 09:50:51 -0800 Subject: [PATCH] begin work on adding search to albums page --- backend/albumiterator.go | 7 +-- ui/albumgrid.go | 3 ++ ui/albumspage.go | 57 +++++++++++++++++++++ ui/browsingpane.go | 104 +++++++++++++++++++++++++++++++++++++++ ui/mainwindow.go | 21 ++++---- 5 files changed, 180 insertions(+), 12 deletions(-) create mode 100644 ui/albumspage.go create mode 100644 ui/browsingpane.go diff --git a/backend/albumiterator.go b/backend/albumiterator.go index 122fb52..3443d23 100644 --- a/backend/albumiterator.go +++ b/backend/albumiterator.go @@ -146,9 +146,10 @@ type searchIter struct { func (l *LibraryManager) newSearchIter(query string) *searchIter { return &searchIter{ - query: query, - l: l, - s: l.s.Server, + query: query, + l: l, + s: l.s.Server, + albumIDset: make(map[string]bool), } } diff --git a/ui/albumgrid.go b/ui/albumgrid.go index e867f36..e557e8d 100644 --- a/ui/albumgrid.go +++ b/ui/albumgrid.go @@ -2,6 +2,7 @@ package ui import ( "context" + "fmt" "image" "supersonic/backend" "supersonic/ui/widgets" @@ -84,7 +85,9 @@ func (ag *AlbumGrid) doUpdateAlbumCard(albumIdx int, ac *widgets.AlbumCard) { return default: if err == nil { + fmt.Println("setting image") ac.Cover.SetImage(i) + ag.Refresh() } } }(ctx) diff --git a/ui/albumspage.go b/ui/albumspage.go new file mode 100644 index 0000000..f798a66 --- /dev/null +++ b/ui/albumspage.go @@ -0,0 +1,57 @@ +package ui + +import ( + "log" + "supersonic/backend" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" +) + +var _ fyne.Widget = (*AlbumsPage)(nil) + +type AlbumsPage struct { + widget.BaseWidget + + im *backend.ImageManager + lm *backend.LibraryManager + grid *AlbumGrid + searchGrid *AlbumGrid + gridContainer *fyne.Container + OnPlayAlbum func(string) +} + +func NewAlbumsPage(title string, lm *backend.LibraryManager, im *backend.ImageManager) *AlbumsPage { + a := &AlbumsPage{ + lm: lm, + im: im, + } + a.ExtendBaseWidget(a) + a.grid = NewAlbumGrid(lm.RecentlyAddedIter(), im.GetAlbumThumbnail) + a.grid.OnPlayAlbum = func(id string) { + if a.OnPlayAlbum != nil { + a.OnPlayAlbum(id) + } + } + a.gridContainer = container.NewMax(a.grid) + return a +} + +func (a *AlbumsPage) OnSearched(query string) { + if query == "" { + a.gridContainer.Objects[0] = a.grid + a.searchGrid = nil + a.Refresh() + return + } + log.Printf("searched %s", query) + a.searchGrid = NewAlbumGrid(a.lm.SearchIter(query), a.im.GetAlbumThumbnail) + a.gridContainer.Objects[0] = a.searchGrid + a.Refresh() +} + +func (a *AlbumsPage) CreateRenderer() fyne.WidgetRenderer { + a.ExtendBaseWidget(a) + return widget.NewSimpleRenderer(a.gridContainer) +} diff --git a/ui/browsingpane.go b/ui/browsingpane.go new file mode 100644 index 0000000..8645d6e --- /dev/null +++ b/ui/browsingpane.go @@ -0,0 +1,104 @@ +package ui + +import ( + "context" + "time" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" +) + +type Page interface { + fyne.Widget +} + +type Searchable interface { + OnSearched(string) +} + +type BrowsingPane struct { + widget.BaseWidget + + searchBar *searchField + searchTimer time.Timer + pendingSearch bool + cancelPendingSearch context.CancelFunc + curPage Page + + container *fyne.Container + pageContaner *fyne.Container +} + +type blankPage struct { + widget.Separator +} + +type searchField struct { + widget.Entry + height float32 +} + +func NewSearchField() *searchField { + sf := &searchField{} + sf.ExtendBaseWidget(sf) + // this is a bit hacky + sf.height = widget.NewEntry().MinSize().Height + sf.PlaceHolder = "Search" + return sf +} + +func (s *searchField) MinSize() fyne.Size { + return fyne.NewSize(200, s.height) +} + +func NewBrowsingPane() *BrowsingPane { + b := &BrowsingPane{} + b.ExtendBaseWidget(b) + b.searchBar = NewSearchField() + b.searchBar.OnChanged = b.onSearchTextChanged + b.curPage = &blankPage{} + b.searchTimer = *time.NewTimer(0) + b.pageContaner = container.NewMax(b.curPage) + b.container = container.NewBorder(container.NewHBox(b.searchBar), nil, nil, nil, b.pageContaner) + return b +} + +func (b *BrowsingPane) SetPage(p Page) { + if b.cancelPendingSearch != nil { + b.cancelPendingSearch() + b.cancelPendingSearch = nil + } + b.curPage = p + b.pageContaner.Objects[0] = p + b.Refresh() +} + +func (b *BrowsingPane) onSearchTextChanged(text string) { + b.searchTimer.Reset(300 * time.Millisecond) + if s, ok := b.curPage.(Searchable); ok { + s.OnSearched(text) + } + if !b.pendingSearch { + /* + ctx, cancel := context.WithCancel(context.Background()) + b.cancelPendingSearch = cancel + b.pendingSearch = true + go func(ctx context.Context) { + select { + case <-ctx.Done(): + b.pendingSearch = false + case <-b.searchTimer.C: + if s, ok := b.curPage.(Searchable); ok { + s.OnSearched(b.searchBar.Text) + } + b.pendingSearch = false + } + }(ctx) + */ + } +} + +func (b *BrowsingPane) CreateRenderer() fyne.WidgetRenderer { + return widget.NewSimpleRenderer(b.container) +} diff --git a/ui/mainwindow.go b/ui/mainwindow.go index fa4713d..686637f 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -6,7 +6,6 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/widget" "github.com/dweymouth/go-subsonic" ) @@ -14,18 +13,22 @@ import ( type MainWindow struct { Window fyne.Window - BottomPanel *BottomPanel + BrowsingPane *BrowsingPane + BottomPanel *BottomPanel + + container *fyne.Container } func NewMainWindow(fyneApp fyne.App, appName string, app *backend.App) MainWindow { m := MainWindow{ - Window: fyneApp.NewWindow(appName), - BottomPanel: NewBottomPanel(app.Player), + Window: fyneApp.NewWindow(appName), + BrowsingPane: NewBrowsingPane(), + BottomPanel: NewBottomPanel(app.Player), } m.BottomPanel.SetPlaybackManager(app.PlaybackManager) m.BottomPanel.ImageManager = app.ImageManager - c := container.NewBorder(nil, m.BottomPanel, nil, nil, &layout.Spacer{}) - m.Window.SetContent(c) + m.container = container.NewBorder(nil, m.BottomPanel, nil, nil, m.BrowsingPane) + m.Window.SetContent(m.container) m.Window.Resize(fyne.NewSize(1000, 800)) app.PlaybackManager.OnSongChange(func(song *subsonic.Child) { if song == nil { @@ -35,11 +38,11 @@ func NewMainWindow(fyneApp fyne.App, appName string, app *backend.App) MainWindo m.Window.SetTitle(song.Title) }) app.ServerManager.OnServerConnected(func() { - ag := NewAlbumGrid(app.LibraryManager.RecentlyAddedIter(), app.ImageManager.GetAlbumThumbnail) - ag.OnPlayAlbum = func(albumID string) { + ap := NewAlbumsPage("Albums", app.LibraryManager, app.ImageManager) + ap.OnPlayAlbum = func(albumID string) { _ = app.PlaybackManager.PlayAlbum(albumID) } - m.Window.SetContent(container.NewBorder(nil, m.BottomPanel, nil, nil, ag)) + m.BrowsingPane.SetPage(ap) }) return m }