2.3 KiB
TUI / search filter
Pressing / in the library or queue pane opens a search input that
filters that pane's items live as you type (case-insensitive
substring). A small feature; recorded here for the couple of decisions
that were not obvious.
Decisions
D1 — filter, not jump
Vim's / jumps to the next match; here / narrows the visible list
to matching rows. For a music library ("show me everything with
'radiohead'") filtering is the more useful reading of "search in the
items", and it composes with the existing queue/mark actions — you
filter, then act on what is left.
D2 — the filter lives on the pane, the input on the app
The pane (Library/Queue) owns a Filter (the query plus the list
of visible real indices). The / input mode (App::search) only holds
the editing buffer and which pane is focused. So the filter survives
closing the input: Enter keeps it applied and returns to navigation,
Esc clears it. This matches the other modal overlays (input, confirm)
in how keys are routed while it is open.
D3 — view indices vs real indices
The panes keep their full item list; the filter maps between the
view index (what the selection bar and StatefulList navigation key
off) and the real index into the list. This matters most for the
queue: removal and set-current send real queue positions to the
server, so a filtered selection must map back before it is sent —
otherwise d on the third visible row would remove the wrong track.
Marks likewise live on the full list, so a marked-but-hidden item still
counts when queueing.
Because StatefulList already routes through get_size/select/
selected, pointing those at the filtered view made all the movement
keys (j/k/g/G/Ctrl-d/Ctrl-u) work on the filtered list with
no per-key changes.
D4 — lifecycle
- Library: entering a node is a fresh listing, so search mode is reset there (a stale filter from the previous folder would be confusing).
- Queue: the queue is re-sent constantly (position ticks, resolving), so an active search is preserved across updates and only its visible set is recomputed.
Scope
Implemented in the TUI only, per the request. The web client
(architecture/web-client.md) could mirror it later for parity; noted
as a follow-up, not done here.