diff --git a/backend/mediaprovider/subsonic/searchall.go b/backend/mediaprovider/subsonic/searchall.go index f2e38b0..6abd9b8 100644 --- a/backend/mediaprovider/subsonic/searchall.go +++ b/backend/mediaprovider/subsonic/searchall.go @@ -6,6 +6,7 @@ import ( "strings" "sync" + "github.com/deluan/sanitize" "github.com/dweymouth/go-subsonic/subsonic" "github.com/dweymouth/supersonic/backend/mediaprovider" "github.com/dweymouth/supersonic/sharedutil" @@ -34,14 +35,14 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([ wg.Done() }() - queryLowerWords := strings.Fields(strings.ToLower(searchQuery)) + queryLowerWords := strings.Fields(strings.ToLower(sanitize.Accents(searchQuery))) wg.Add(1) go func() { p, e := s.client.GetPlaylists(nil) if e == nil { playlists = sharedutil.FilterSlice(p, func(p *subsonic.Playlist) bool { - return allTermsMatch(strings.ToLower(p.Name), queryLowerWords) + return allTermsMatch(strings.ToLower(sanitize.Accents(p.Name)), queryLowerWords) }) } wg.Done() @@ -52,7 +53,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([ g, e := s.client.GetGenres() if e == nil { genres = sharedutil.FilterSlice(g, func(g *subsonic.Genre) bool { - return allTermsMatch(strings.ToLower(g.Name), queryLowerWords) + return allTermsMatch(strings.ToLower(sanitize.Accents(g.Name)), queryLowerWords) }) } wg.Done() @@ -64,7 +65,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([ } results := mergeResults(result, playlists, genres) - //rankResults(results, queryLowerWords) // TODO + rankResults(results, queryLowerWords) if len(results) > maxResults { results = results[:maxResults] } @@ -143,9 +144,42 @@ func mergeResults( } func rankResults(results []*mediaprovider.SearchResult, queryTerms []string) { - // TODO - sort.Slice(results, func(a, b int) bool { - return false + if len(queryTerms) == 0 || len(results) < 2 { + return + } + + sanitizeMemo := make([]string, len(results)) + sanitized := func(s string, i int) string { + if x := sanitizeMemo[i]; x != "" { + return x + } + x := strings.ToLower(sanitize.Accents(s)) + sanitizeMemo[i] = x + return x + } + + sort.Slice(results, func(i, j int) bool { + // Compare by search query terms + a, b := results[i], results[j] + aName := sanitized(a.Name, i) + bName := sanitized(b.Name, j) + + for _, term := range queryTerms { + firstTermIdxA, firstTermIdxB := strings.Index(aName, term), strings.Index(bName, term) + if firstTermIdxA >= 0 && firstTermIdxB < 0 { + return true // item A has a direct match with the query term and B does not + } else if firstTermIdxB >= 0 && firstTermIdxA < 0 { + return false // item B matches but not A + } + + if firstTermIdxA < firstTermIdxB { + return true // item A matches the query term starting at an earlier position + } else if firstTermIdxB < firstTermIdxA { + return false // item B matches first + } + } + // Defer to item type for priority order + return a.Type < b.Type }) } diff --git a/go.mod b/go.mod index 9a43360..1726f11 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( fyne.io/fyne/v2 v2.4.1 github.com/20after4/configdir v0.1.1 + github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1 github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee github.com/dweymouth/go-subsonic v0.0.0-20231105161622-54b5aec28363 github.com/fsnotify/fsnotify v1.6.0 diff --git a/go.sum b/go.sum index 9ec00f2..6b0f3f1 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7h github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1 h1:mGvOb3zxl4vCLv+dbf7JA6CAaM2UH/AGP1KX4DsJmTI= +github.com/deluan/sanitize v0.0.0-20230310221930-6e18967d9fc1/go.mod h1:ZNCLJfehvEf34B7BbLKjgpsL9lyW7q938w/GY1XgV4E= github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231104060932-f124004dd651 h1:szaOWq1a8gthqA55qq1egRj660DQM3Pp0nkrmjUwR48= github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20231104060932-f124004dd651/go.mod h1:AWM1iPM2YfliduZ4u/kQzP9E6ARIWm0gg+57GpYzWro= github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee h1:ZGyJ6wp7CAfT31BugypcF/TPKEy2RrGR9JFq1JOjOpY= diff --git a/ui/dialogs/quicksearch.go b/ui/dialogs/quicksearch.go index d1e8884..2698aaf 100644 --- a/ui/dialogs/quicksearch.go +++ b/ui/dialogs/quicksearch.go @@ -136,6 +136,7 @@ func (q *QuickSearch) onSearched(query string) { q.resultsMutex.Unlock() q.list.Refresh() q.list.ScrollToTop() + q.selectedIndex = 0 q.list.Select(0) }