include playlists and genres in results; UI improvement
This commit is contained in:
@@ -39,7 +39,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
p, e := s.client.GetPlaylists(nil)
|
p, e := s.client.GetPlaylists(nil)
|
||||||
if e != nil {
|
if e == nil {
|
||||||
playlists = sharedutil.FilterSlice(p, func(p *subsonic.Playlist) bool {
|
playlists = sharedutil.FilterSlice(p, func(p *subsonic.Playlist) bool {
|
||||||
return allTermsMatch(strings.ToLower(p.Name), queryLowerWords)
|
return allTermsMatch(strings.ToLower(p.Name), queryLowerWords)
|
||||||
})
|
})
|
||||||
@@ -50,7 +50,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
g, e := s.client.GetGenres()
|
g, e := s.client.GetGenres()
|
||||||
if e != nil {
|
if e == nil {
|
||||||
genres = sharedutil.FilterSlice(g, func(g *subsonic.Genre) bool {
|
genres = sharedutil.FilterSlice(g, func(g *subsonic.Genre) bool {
|
||||||
return allTermsMatch(strings.ToLower(g.Name), queryLowerWords)
|
return allTermsMatch(strings.ToLower(g.Name), queryLowerWords)
|
||||||
})
|
})
|
||||||
@@ -120,6 +120,25 @@ func mergeResults(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, pl := range matchingPlaylists {
|
||||||
|
results = append(results, &mediaprovider.SearchResult{
|
||||||
|
Type: mediaprovider.ContentTypePlaylist,
|
||||||
|
ID: pl.ID,
|
||||||
|
CoverID: pl.CoverArt,
|
||||||
|
Name: pl.Name,
|
||||||
|
Size: pl.SongCount,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, g := range matchingGenres {
|
||||||
|
results = append(results, &mediaprovider.SearchResult{
|
||||||
|
Type: mediaprovider.ContentTypeGenre,
|
||||||
|
ID: g.Name,
|
||||||
|
Name: g.Name,
|
||||||
|
Size: g.AlbumCount,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+57
-17
@@ -1,6 +1,7 @@
|
|||||||
package dialogs
|
package dialogs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -48,22 +49,8 @@ func NewQuickSearch(mp mediaprovider.MediaProvider, im *backend.ImageManager) *Q
|
|||||||
se.OnSubmitted = func(_ string) {
|
se.OnSubmitted = func(_ string) {
|
||||||
q.onSelected(q.selectedIndex)
|
q.onSelected(q.selectedIndex)
|
||||||
}
|
}
|
||||||
se.OnTypedDown = func() {
|
se.OnTypedDown = q.moveSelectionDown
|
||||||
q.resultsMutex.RLock()
|
se.OnTypedUp = q.moveSelectionUp
|
||||||
if q.selectedIndex < len(q.searchResults)-1 {
|
|
||||||
q.selectedIndex++
|
|
||||||
}
|
|
||||||
q.resultsMutex.RUnlock()
|
|
||||||
q.list.Select(q.selectedIndex)
|
|
||||||
}
|
|
||||||
se.OnTypedUp = func() {
|
|
||||||
q.resultsMutex.RLock()
|
|
||||||
if q.selectedIndex > 0 {
|
|
||||||
q.selectedIndex--
|
|
||||||
}
|
|
||||||
q.resultsMutex.RUnlock()
|
|
||||||
q.list.Select(q.selectedIndex)
|
|
||||||
}
|
|
||||||
se.OnTypedEscape = q.onDismiss
|
se.OnTypedEscape = q.onDismiss
|
||||||
q.SearchEntry = se
|
q.SearchEntry = se
|
||||||
q.list = widget.NewList(
|
q.list = widget.NewList(
|
||||||
@@ -117,6 +104,24 @@ func (q *QuickSearch) onSelected(idx int) {
|
|||||||
q.OnNavigateTo(typ, id)
|
q.OnNavigateTo(typ, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *QuickSearch) moveSelectionDown() {
|
||||||
|
q.resultsMutex.RLock()
|
||||||
|
if q.selectedIndex < len(q.searchResults)-1 {
|
||||||
|
q.selectedIndex++
|
||||||
|
}
|
||||||
|
q.resultsMutex.RUnlock()
|
||||||
|
q.list.Select(q.selectedIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *QuickSearch) moveSelectionUp() {
|
||||||
|
q.resultsMutex.RLock()
|
||||||
|
if q.selectedIndex > 0 {
|
||||||
|
q.selectedIndex--
|
||||||
|
}
|
||||||
|
q.resultsMutex.RUnlock()
|
||||||
|
q.list.Select(q.selectedIndex)
|
||||||
|
}
|
||||||
|
|
||||||
func (q *QuickSearch) onSearched(query string) {
|
func (q *QuickSearch) onSearched(query string) {
|
||||||
var results []*mediaprovider.SearchResult
|
var results []*mediaprovider.SearchResult
|
||||||
if query != "" {
|
if query != "" {
|
||||||
@@ -192,7 +197,42 @@ func (q *quickSearchResult) Update(result *mediaprovider.SearchResult) {
|
|||||||
q.image.CenterIcon = placeholderIconForContentType(result.Type)
|
q.image.CenterIcon = placeholderIconForContentType(result.Type)
|
||||||
q.imageLoader.Load(result.CoverID)
|
q.imageLoader.Load(result.CoverID)
|
||||||
q.title.SetText(result.Name)
|
q.title.SetText(result.Name)
|
||||||
q.secondary.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: result.Type.String()}}
|
|
||||||
|
maybePluralize := func(s string, size int) string {
|
||||||
|
if size != 1 {
|
||||||
|
return s + "s"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
var secondaryText string
|
||||||
|
switch result.Type {
|
||||||
|
case mediaprovider.ContentTypeAlbum:
|
||||||
|
secondaryText = result.ArtistName
|
||||||
|
case mediaprovider.ContentTypeArtist:
|
||||||
|
secondaryText = fmt.Sprintf("%d %s", result.Size, maybePluralize("album", result.Size))
|
||||||
|
case mediaprovider.ContentTypeTrack:
|
||||||
|
secondaryText = result.ArtistName
|
||||||
|
case mediaprovider.ContentTypePlaylist:
|
||||||
|
secondaryText = fmt.Sprintf("%d %s", result.Size, maybePluralize("track", result.Size))
|
||||||
|
case mediaprovider.ContentTypeGenre:
|
||||||
|
secondaryText = fmt.Sprintf("%d %s", result.Size, maybePluralize("album", result.Size))
|
||||||
|
}
|
||||||
|
q.secondary.Segments = []widget.RichTextSegment{
|
||||||
|
&widget.TextSegment{
|
||||||
|
Text: result.Type.String(),
|
||||||
|
Style: widget.RichTextStyle{SizeName: theme.SizeNameCaptionText, TextStyle: fyne.TextStyle{Bold: true}, Inline: true},
|
||||||
|
},
|
||||||
|
&widget.TextSegment{
|
||||||
|
Text: " · ",
|
||||||
|
Style: widget.RichTextStyle{SizeName: theme.SizeNameCaptionText, Inline: true},
|
||||||
|
},
|
||||||
|
&widget.TextSegment{
|
||||||
|
Text: secondaryText,
|
||||||
|
Style: widget.RichTextStyle{SizeName: theme.SizeNameCaptionText, Inline: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
q.secondary.Refresh()
|
q.secondary.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user