Filter dialog: only offer options that yield results

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 20:48:57 +02:00
co-authored by Claude Sonnet 5.5
parent ac1c2ebce2
commit 8a357f7418
7 changed files with 215 additions and 81 deletions
+34 -6
View File
@@ -208,6 +208,8 @@ type libraryView struct {
seriesFiles map[int]seriesFiles
fileGen int // invalidates running fetches
filePending int
refreshDialog func() // re-evaluates the options of the open filter dialog
}
type seriesFiles struct {
@@ -271,7 +273,7 @@ func (v *libraryView) handleKey(ev *tcell.EventKey) *tcell.EventKey {
v.filter = (v.filter + 1) % len(libFilters)
v.render()
case 'F':
v.app.openAttrFilter(v.attr, languagesOf(v.panes[kindMovies].all, v.panes[kindSeries].all), v.setAttrFilter)
v.openFilterDialog()
case 'r':
v.seriesFiles = map[int]seriesFiles{} // a manual reload also refreshes file properties
v.reload()
@@ -334,7 +336,7 @@ func (v *libraryView) reloadPane(p *libPane) {
}
p.err = err
if err == nil && kind == kindSeries {
defer v.loadSeriesFiles()
defer v.loadSeriesFiles(false)
}
if err != nil {
// Keep showing the last good list; say why it is stale.
@@ -494,7 +496,29 @@ func (v *libraryView) run(doing, done string, fn func(ctx context.Context) error
func (v *libraryView) setAttrFilter(f attrFilter) {
v.attr = f
v.render()
v.loadSeriesFiles()
v.loadSeriesFiles(false)
}
// openFilterDialog opens the property filter. The files of all series are read
// so the dialog can leave out options that would match nothing.
func (v *libraryView) openFilterDialog() {
v.refreshDialog = v.app.openAttrFilter(v.attr, v.filterPool, v.setAttrFilter, func() { v.refreshDialog = nil })
v.loadSeriesFiles(true)
}
// filterPool lists the files of the items that pass the status and text
// filters, for the filter dialog.
func (v *libraryView) filterPool() filterPool {
var p filterPool
for _, pane := range v.panes {
for _, it := range filterItems(pane.all, v.filter, v.input.GetText(), attrFilter{}) {
if !it.attrsKnown {
p.unknown = true
}
p.files = append(p.files, it.attrs)
}
}
return p
}
// withCachedFiles fills in the file properties of a series from the cache.
@@ -510,9 +534,10 @@ func (v *libraryView) withCachedFiles(it libItem) libItem {
}
// loadSeriesFiles fetches the file properties of all series that lack them,
// but only while a property filter is active (it costs one request per series).
func (v *libraryView) loadSeriesFiles() {
if !v.attr.active() {
// but only while a property filter is active or the filter dialog is open
// (it costs one request per series).
func (v *libraryView) loadSeriesFiles(force bool) {
if !force && !v.attr.active() {
return
}
p := v.panes[kindSeries]
@@ -580,6 +605,9 @@ func (v *libraryView) loadSeriesFiles() {
}
if v.filePending%10 == 0 { // keep redraws cheap for big libraries
v.render()
if v.refreshDialog != nil {
v.refreshDialog()
}
}
})
}