move search bar to within albums page (right hand side)
This commit is contained in:
@@ -21,6 +21,7 @@ type AlbumsPage struct {
|
|||||||
nav func(Route)
|
nav func(Route)
|
||||||
grid *widgets.AlbumGrid
|
grid *widgets.AlbumGrid
|
||||||
searchGrid *widgets.AlbumGrid
|
searchGrid *widgets.AlbumGrid
|
||||||
|
searcher *widgets.Searcher
|
||||||
searchText string
|
searchText string
|
||||||
titleDisp *widget.RichText
|
titleDisp *widget.RichText
|
||||||
sortOrder *selectWidget
|
sortOrder *selectWidget
|
||||||
@@ -70,8 +71,11 @@ func NewAlbumsPage(title string, sortOrder string, lm *backend.LibraryManager, i
|
|||||||
a.grid.OnPlayAlbum = a.onPlayAlbum
|
a.grid.OnPlayAlbum = a.onPlayAlbum
|
||||||
a.grid.OnShowArtistPage = a.onShowArtistPage
|
a.grid.OnShowArtistPage = a.onShowArtistPage
|
||||||
a.grid.OnShowAlbumPage = a.onShowAlbumPage
|
a.grid.OnShowAlbumPage = a.onShowAlbumPage
|
||||||
|
a.searcher = widgets.NewSearcher()
|
||||||
|
a.searcher.OnSearched = a.OnSearched
|
||||||
|
searchVbox := container.NewVBox(layout.NewSpacer(), a.searcher.Entry, layout.NewSpacer())
|
||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.NewHBox(widgets.NewHSpace(9), a.titleDisp, sortVbox),
|
container.NewHBox(widgets.NewHSpace(9), a.titleDisp, sortVbox, layout.NewSpacer(), searchVbox, widgets.NewHSpace(15)),
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ package browsing
|
|||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"supersonic/backend"
|
"supersonic/backend"
|
||||||
"supersonic/ui/widgets"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/canvas"
|
"fyne.io/fyne/v2/canvas"
|
||||||
@@ -23,10 +20,6 @@ type Page interface {
|
|||||||
Route() Route
|
Route() Route
|
||||||
}
|
}
|
||||||
|
|
||||||
type Searchable interface {
|
|
||||||
OnSearched(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
type CanPlayAlbum interface {
|
type CanPlayAlbum interface {
|
||||||
SetPlayAlbumCallback(func(albumID string, startingTrack int))
|
SetPlayAlbumCallback(func(albumID string, startingTrack int))
|
||||||
}
|
}
|
||||||
@@ -52,11 +45,6 @@ type BrowsingPane struct {
|
|||||||
history []Page
|
history []Page
|
||||||
historyIdx int
|
historyIdx int
|
||||||
|
|
||||||
searchBar *widgets.SearchEntry
|
|
||||||
pendingSearchLock sync.Mutex
|
|
||||||
pendingSearch bool
|
|
||||||
searchGoroutine bool
|
|
||||||
|
|
||||||
pageContainer *fyne.Container
|
pageContainer *fyne.Container
|
||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
@@ -64,8 +52,6 @@ type BrowsingPane struct {
|
|||||||
func NewBrowsingPane(app *backend.App) *BrowsingPane {
|
func NewBrowsingPane(app *backend.App) *BrowsingPane {
|
||||||
b := &BrowsingPane{app: app}
|
b := &BrowsingPane{app: app}
|
||||||
b.ExtendBaseWidget(b)
|
b.ExtendBaseWidget(b)
|
||||||
b.searchBar = widgets.NewSearchEntry()
|
|
||||||
b.searchBar.OnTextChanged = b.onSearchTextChanged
|
|
||||||
b.home = widget.NewButtonWithIcon("", theme.HomeIcon(), b.goHome)
|
b.home = widget.NewButtonWithIcon("", theme.HomeIcon(), b.goHome)
|
||||||
b.back = widget.NewButtonWithIcon("", theme.NavigateBackIcon(), b.GoBack)
|
b.back = widget.NewButtonWithIcon("", theme.NavigateBackIcon(), b.GoBack)
|
||||||
b.forward = widget.NewButtonWithIcon("", theme.NavigateNextIcon(), b.GoForward)
|
b.forward = widget.NewButtonWithIcon("", theme.NavigateNextIcon(), b.GoForward)
|
||||||
@@ -75,7 +61,7 @@ func NewBrowsingPane(app *backend.App) *BrowsingPane {
|
|||||||
canvas.NewRectangle(color.RGBA{R: 24, G: 24, B: 24, A: 255}),
|
canvas.NewRectangle(color.RGBA{R: 24, G: 24, B: 24, A: 255}),
|
||||||
layout.NewSpacer())
|
layout.NewSpacer())
|
||||||
b.container = container.NewBorder(
|
b.container = container.NewBorder(
|
||||||
container.NewHBox(b.home, b.back, b.forward, b.reload, b.searchBar),
|
container.NewHBox(b.home, b.back, b.forward, b.reload),
|
||||||
nil, nil, nil, b.pageContainer)
|
nil, nil, nil, b.pageContainer)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@@ -99,8 +85,6 @@ func (b *BrowsingPane) doSetPage(p Page) bool {
|
|||||||
if np, ok := p.(CanShowNowPlaying); ok {
|
if np, ok := p.(CanShowNowPlaying); ok {
|
||||||
np.OnSongChange(b.app.PlaybackManager.NowPlaying())
|
np.OnSongChange(b.app.PlaybackManager.NowPlaying())
|
||||||
}
|
}
|
||||||
_, s := p.(Searchable)
|
|
||||||
b.searchBar.Hidden = !s
|
|
||||||
b.pageContainer.Objects[1] = p
|
b.pageContainer.Objects[1] = p
|
||||||
b.Refresh()
|
b.Refresh()
|
||||||
return true
|
return true
|
||||||
@@ -147,46 +131,6 @@ func (b *BrowsingPane) Reload() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) onSearchTextChanged(text string) {
|
|
||||||
if text == "" {
|
|
||||||
b.sendSearch("")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.pendingSearchLock.Lock()
|
|
||||||
defer b.pendingSearchLock.Unlock()
|
|
||||||
b.pendingSearch = true
|
|
||||||
if !b.searchGoroutine {
|
|
||||||
go b.waitAndSearch()
|
|
||||||
b.searchGoroutine = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) waitAndSearch() {
|
|
||||||
t := time.NewTicker(200 * time.Millisecond)
|
|
||||||
var getReadyToSearch bool
|
|
||||||
var done bool
|
|
||||||
for !done {
|
|
||||||
<-t.C
|
|
||||||
b.pendingSearchLock.Lock()
|
|
||||||
if b.pendingSearch {
|
|
||||||
getReadyToSearch = true
|
|
||||||
b.pendingSearch = false
|
|
||||||
} else if getReadyToSearch {
|
|
||||||
b.sendSearch(b.searchBar.Text)
|
|
||||||
t.Stop()
|
|
||||||
b.searchGoroutine = false
|
|
||||||
done = true
|
|
||||||
}
|
|
||||||
b.pendingSearchLock.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) sendSearch(query string) {
|
|
||||||
if s, ok := b.curPage.(Searchable); ok {
|
|
||||||
s.OnSearched(query)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BrowsingPane) CreateRenderer() fyne.WidgetRenderer {
|
func (b *BrowsingPane) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(b.container)
|
return widget.NewSimpleRenderer(b.container)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package widgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Searcher struct {
|
||||||
|
Entry *SearchEntry
|
||||||
|
OnSearched func(string)
|
||||||
|
|
||||||
|
searchGoroutine bool
|
||||||
|
pendingSearch bool
|
||||||
|
pendingSearchLock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearcher() *Searcher {
|
||||||
|
s := &Searcher{
|
||||||
|
Entry: NewSearchEntry(),
|
||||||
|
}
|
||||||
|
s.Entry.OnTextChanged = s.onSearchTextChanged
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Searcher) onSearchTextChanged(text string) {
|
||||||
|
if text == "" {
|
||||||
|
s.sendSearch("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.pendingSearchLock.Lock()
|
||||||
|
defer s.pendingSearchLock.Unlock()
|
||||||
|
s.pendingSearch = true
|
||||||
|
if !s.searchGoroutine {
|
||||||
|
go s.waitAndSearch()
|
||||||
|
s.searchGoroutine = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Searcher) waitAndSearch() {
|
||||||
|
t := time.NewTicker(200 * time.Millisecond)
|
||||||
|
var getReadyToSearch bool
|
||||||
|
var done bool
|
||||||
|
for !done {
|
||||||
|
<-t.C
|
||||||
|
s.pendingSearchLock.Lock()
|
||||||
|
if s.pendingSearch {
|
||||||
|
getReadyToSearch = true
|
||||||
|
s.pendingSearch = false
|
||||||
|
} else if getReadyToSearch {
|
||||||
|
s.sendSearch(s.Entry.Text)
|
||||||
|
t.Stop()
|
||||||
|
s.searchGoroutine = false
|
||||||
|
done = true
|
||||||
|
}
|
||||||
|
s.pendingSearchLock.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Searcher) sendSearch(text string) {
|
||||||
|
if s.OnSearched != nil {
|
||||||
|
s.OnSearched(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user