155 lines
3.6 KiB
Go
155 lines
3.6 KiB
Go
package dialogs
|
|
|
|
import (
|
|
"image"
|
|
"sync"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/canvas"
|
|
"fyne.io/fyne/v2/container"
|
|
"fyne.io/fyne/v2/layout"
|
|
"fyne.io/fyne/v2/theme"
|
|
"fyne.io/fyne/v2/widget"
|
|
"github.com/dweymouth/supersonic/backend"
|
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
|
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
|
"github.com/dweymouth/supersonic/ui/widgets"
|
|
)
|
|
|
|
type QuickSearch struct {
|
|
widget.BaseWidget
|
|
|
|
mp *mediaprovider.MediaProvider
|
|
im *backend.ImageManager
|
|
|
|
resultsMutex sync.RWMutex
|
|
searchResults []*mediaprovider.SearchResult
|
|
list *widget.List
|
|
selectedIndex int
|
|
|
|
content *fyne.Container
|
|
}
|
|
|
|
func NewQuickSearch(mp *mediaprovider.MediaProvider, im *backend.ImageManager) *QuickSearch {
|
|
q := &QuickSearch{
|
|
mp: mp,
|
|
im: im,
|
|
}
|
|
q.ExtendBaseWidget(q)
|
|
|
|
searchEntry := widgets.NewSearchEntry()
|
|
searchEntry.OnChanged = q.onSearched
|
|
q.list = widget.NewList(
|
|
func() int {
|
|
q.resultsMutex.RLock()
|
|
defer q.resultsMutex.RUnlock()
|
|
return len(q.searchResults)
|
|
},
|
|
func() fyne.CanvasObject { return newQuickSearchResult(im) },
|
|
func(lii widget.ListItemID, co fyne.CanvasObject) {
|
|
var result *mediaprovider.SearchResult
|
|
q.resultsMutex.RLock()
|
|
if len(q.searchResults) > lii {
|
|
result = q.searchResults[lii]
|
|
}
|
|
q.resultsMutex.RUnlock()
|
|
co.(*quickSearchResult).Update(result)
|
|
},
|
|
)
|
|
q.content = container.NewVBox(
|
|
container.NewHBox(
|
|
layout.NewSpacer(),
|
|
widget.NewRichText(&widget.TextSegment{Text: "Quick Search", Style: boldStyle}),
|
|
layout.NewSpacer()),
|
|
container.NewBorder(searchEntry, nil, nil, nil, q.list),
|
|
)
|
|
return q
|
|
}
|
|
|
|
func (q *QuickSearch) onSearched(query string) {
|
|
}
|
|
|
|
func (q *QuickSearch) CreateRenderer() fyne.WidgetRenderer {
|
|
return widget.NewSimpleRenderer(q.content)
|
|
}
|
|
|
|
type quickSearchResult struct {
|
|
widget.BaseWidget
|
|
|
|
// parent *QuickSearch
|
|
|
|
imageLoader backend.ThumbnailLoader
|
|
|
|
image *widgets.ImagePlaceholder
|
|
title *widget.Label
|
|
secondary *widget.RichText
|
|
selection *canvas.Rectangle
|
|
|
|
content *fyne.Container
|
|
}
|
|
|
|
func newQuickSearchResult(im *backend.ImageManager) *quickSearchResult {
|
|
qs := &quickSearchResult{
|
|
image: widgets.NewImagePlaceholder(myTheme.AlbumIcon, 64),
|
|
title: widget.NewLabel(""),
|
|
secondary: widget.NewRichText(),
|
|
}
|
|
qs.ExtendBaseWidget(qs)
|
|
qs.imageLoader = im.NewThumbnailLoader(func(im image.Image) {
|
|
qs.image.SetImage(im, false)
|
|
})
|
|
qs.imageLoader.OnBeforeLoad = func() {
|
|
qs.image.SetImage(nil, false)
|
|
}
|
|
|
|
return qs
|
|
}
|
|
|
|
func (q *quickSearchResult) Update(result *mediaprovider.SearchResult) {
|
|
if result == nil {
|
|
return
|
|
}
|
|
q.image.CenterIcon = placeholderIconForContentType(result.Type)
|
|
q.imageLoader.Load(result.CoverID)
|
|
q.title.SetText(result.Name)
|
|
//TODO: q.secondary.Segments =
|
|
}
|
|
|
|
func (q *quickSearchResult) CreateRenderer() fyne.WidgetRenderer {
|
|
if q.selection == nil {
|
|
q.selection = canvas.NewRectangle(theme.SelectionColor())
|
|
}
|
|
if q.content == nil {
|
|
q.content = container.NewMax(
|
|
q.selection,
|
|
container.NewBorder(nil, nil, q.image, nil,
|
|
container.NewVBox(
|
|
q.title,
|
|
q.secondary,
|
|
)),
|
|
)
|
|
}
|
|
return widget.NewSimpleRenderer(q.content)
|
|
}
|
|
|
|
func (q *quickSearchResult) Refresh() {
|
|
q.BaseWidget.Refresh()
|
|
}
|
|
|
|
func placeholderIconForContentType(c mediaprovider.ContentType) fyne.Resource {
|
|
switch c {
|
|
case mediaprovider.ContentTypeAlbum:
|
|
return myTheme.AlbumIcon
|
|
case mediaprovider.ContentTypeArtist:
|
|
return myTheme.ArtistIcon
|
|
case mediaprovider.ContentTypeTrack:
|
|
return myTheme.TracksIcon
|
|
case mediaprovider.ContentTypeGenre:
|
|
return myTheme.GenreIcon
|
|
case mediaprovider.ContentTypePlaylist:
|
|
return myTheme.PlaylistIcon
|
|
default:
|
|
return theme.WarningIcon() // unreached
|
|
}
|
|
}
|