Three related TUI correctness bugs:
- download_selector navigation (select_previous/next/last) computed
items.len() - 1, panicking with an arithmetic underflow when the list was
empty (e.g. a filter matched nothing). Index math is now in wrap-safe
helpers that return no selection for an empty list.
- update_search_results overwrote the filtered results view with the full
unfiltered list on every ~100ms poll, so an active filter silently stopped
working as new results streamed in. It now re-derives the filtered view
from the current query.
- The results pane rendered selection checkboxes by testing the display-row
index against a selection set that stores unfiltered indices, so under an
active filter the wrong rows showed as checked. It now maps the display
index back through the filtered-index table.
Filtering and index-mapping logic extracted into pure, unit-tested helpers.
Splits the downloads area 60/40 with a new info pane that adapts to the
selected download's status: header (filename, user, size, status, save
path, bitrate, length) plus queued-specific fields (queue position, peer
slots, peer upload speed) or live progress/speed/ETA when transferring.
Plumbs queue position via a new ClientOperation::PlaceInQueueUpdate so
PlaceInQueueResponse messages from peers reach DownloadStore, and threads
search-time metadata (bitrate, length, peer slots/speed) onto Download
through a new download_with_metadata entry point.