feat(qt): merge media-server rows into both local search paths

`media_servers_qt::search_tracks` was written with the rest of the stack
and never called — the compiler's dead-code warning was the only thing
that said so. Both places that merge Plex now merge the media servers
too: the Local Library Tracks tab and the cortinilla's local section.

Two asymmetries are deliberate:

- Page 0 only, in the Tracks tab, for the same reason the Plex arm is
  page 0 only: these caches are bounded sets read whole, so re-merging
  them per page would repeat every remote row once per local page.
- BOUNDED in the cortinilla, unlike the Plex arm. The Plex cache is read
  whole because it always was; a media-server mirror can hold 50k rows
  and that path runs on every keystroke, so it takes the same limit the
  caller asked the local query for.

Verified on the bench: "totsugeki" in the Tracks tab returns Jellyfin
rows first, then the Plex ones.

cc
This commit is contained in:
vicrodh committed 2026-08-20 13:49:45 -06:00
1 parent 322b9374fb
commit 13e938727c
2 files changed
+26 -8

No files matched your search

+11 -2
View File
@@ -305,8 +305,17 @@ pub fn load_tracks_page_blocking(reset: bool) -> Result<(Vec<TrackRow>, bool), S
// make pagination over-report.
let has_more = page.len() as u64 == TRACKS_PAGE;
if crate::local_plex::is_enabled() && offset == 0 {
let mut merged = crate::local_plex::search_tracks(&query);
if offset == 0 {
// Plex AND the media servers, in one merge. Page 0 only, for the same
// reason the Plex arm was page 0 only: these caches are bounded sets
// read whole, so re-merging them on every page would repeat every
// remote row once per page of local results.
let mut merged = if crate::local_plex::is_enabled() {
crate::local_plex::search_tracks(&query)
} else {
Vec::new()
};
merged.extend(crate::media_servers_qt::search_tracks(&query, None));
if !merged.is_empty() {
merged.append(&mut page);
if sort != "default" {
+15 -6
View File
@@ -426,12 +426,21 @@ pub(crate) async fn load_cortinilla_local(
db.search_with_filter_page(q.trim(), 0, limit, true, exclude_network, "default")
})
.unwrap_or_default();
if plex_enabled {
// PREPEND so Plex content is visible without scrolling past a full
// local page. See the module header: this can starve the local-file
// tracks out of the track section, and that is the reference's
// behaviour, reproduced.
let mut merged = crate::local_plex::search_tracks(q.trim());
// PREPEND so remote content is visible without scrolling past a full
// local page. See the module header: this can starve the local-file
// tracks out of the track section, and that is the reference's
// behaviour, reproduced — now for every remote source, not just Plex.
let mut merged = if plex_enabled {
crate::local_plex::search_tracks(q.trim())
} else {
Vec::new()
};
// BOUNDED, unlike the Plex arm. The Plex cache is read whole because
// it always was; a media-server mirror can hold 50k rows and this runs
// on every keystroke of the cortinilla, so it takes the same limit the
// caller asked the local query for.
merged.extend(crate::media_servers_qt::search_tracks(q.trim(), Some(limit as u32)));
if !merged.is_empty() {
merged.append(&mut rows);
rows = merged;
}