From 3391ae0bdb74796cc9d0932843f6378564cbd201 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 29 Sep 2026 11:09:37 +0000 Subject: [PATCH] fix(tui): refresh valid cached ROM lists Co-authored-by: Patrick Mill --- romm-tui/src/tui/app/rom_load.rs | 7 +++---- romm-tui/src/tui/app/tests.rs | 17 +++++++++++------ romm-tui/src/tui/app/update.rs | 29 ++++++++++++++++------------- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/romm-tui/src/tui/app/rom_load.rs b/romm-tui/src/tui/app/rom_load.rs index 796d01c..9b81ca3 100644 --- a/romm-tui/src/tui/app/rom_load.rs +++ b/romm-tui/src/tui/app/rom_load.rs @@ -64,8 +64,7 @@ impl super::App { /// Paint from disk cache when possible, then queue a network refresh only when needed. /// - /// - Valid cache hit (`expected_count` matches): paint and skip fetch. - /// - Complete but stale: paint immediately, keep `[Loading...]`, queue fetch. + /// - Valid or stale complete cache hit: paint immediately, keep `[Loading...]`, queue fetch. /// - Miss: clear only when needed, queue fetch when `expected > 0`. pub(in crate::tui::app) fn apply_selection_rom_load( &mut self, @@ -99,10 +98,10 @@ impl super::App { if let AppScreen::LibraryBrowse(ref mut lib) = self.screen { if let Some(list) = list { lib.set_roms(list); - lib.set_rom_loading(false); + lib.set_rom_loading(true); } } - self.cancel_primary_rom_load(); + self.queue_primary_rom_load(key, req, expected, context); } PaintKind::Stale => { let list = key diff --git a/romm-tui/src/tui/app/tests.rs b/romm-tui/src/tui/app/tests.rs index 8409762..36d89c1 100644 --- a/romm-tui/src/tui/app/tests.rs +++ b/romm-tui/src/tui/app/tests.rs @@ -422,7 +422,7 @@ async fn list_move_to_zero_rom_selection_does_not_queue_deferred_load() { } #[tokio::test] -async fn list_move_with_complete_cache_keeps_roms_visible() { +async fn list_move_with_complete_cache_paints_and_queues_refresh() { let mut app = app_with_library(vec![platform(9101, "NES", 1), platform(9102, "SNES", 1)]); let list = RomList { items: vec![rom_fixture()], @@ -445,14 +445,19 @@ async fn list_move_with_complete_cache_keeps_roms_visible() { "cached console must paint immediately without blanking the pane" ); assert_eq!(lib.roms.as_ref().map(|r| r.items.len()), Some(1)); - assert!(!lib.rom_loading, "valid cache hit must not stay in loading"); + assert!( + lib.rom_loading, + "valid cache hit should keep [Loading...] until refresh completes" + ); } _ => panic!("expected library browse"), } - assert!( - app.deferred_load_roms.is_none(), - "valid cache hit must not queue a network fetch" - ); + let Some((key, _, expected, context, _)) = &app.deferred_load_roms else { + panic!("valid cache hit should queue a background refresh"); + }; + assert_eq!(key, &Some(RomCacheKey::Platform(9102))); + assert_eq!(expected, &1); + assert_eq!(context, &"list_move_down"); } #[tokio::test] diff --git a/romm-tui/src/tui/app/update.rs b/romm-tui/src/tui/app/update.rs index 94e771b..41ede56 100644 --- a/romm-tui/src/tui/app/update.rs +++ b/romm-tui/src/tui/app/update.rs @@ -173,11 +173,13 @@ impl App { }; if let Some(ref k) = key { + let mut painted_valid_cache = false; if let Some(cached) = self.rom_cache.get_valid(k, expected) { if let AppScreen::LibraryBrowse(ref mut lib) = self.screen { if super::rom_load::primary_rom_load_result_matches_selection(lib, &key) { lib.set_roms(cached.clone()); - lib.set_rom_loading(false); + lib.set_rom_loading(expected > 0); + painted_valid_cache = true; tracing::debug!( "rom-list-render context={} latency_ms={} (cache_hit)", context, @@ -191,21 +193,22 @@ impl App { ); } } - return; } // Stale-complete: paint immediately so the pane is never blank during debounce/fetch. - if let Some(stale) = self.rom_cache.get_complete(k) { - if let AppScreen::LibraryBrowse(ref mut lib) = self.screen { - if super::rom_load::primary_rom_load_result_matches_selection(lib, &key) { - if lib.roms.is_none() { - lib.set_roms(stale.clone()); + if !painted_valid_cache { + if let Some(stale) = self.rom_cache.get_complete(k) { + if let AppScreen::LibraryBrowse(ref mut lib) = self.screen { + if super::rom_load::primary_rom_load_result_matches_selection(lib, &key) { + if lib.roms.is_none() { + lib.set_roms(stale.clone()); + } + lib.set_rom_loading(expected > 0); + tracing::debug!( + "rom-list-render context={} latency_ms={} (stale_complete)", + context, + started.elapsed().as_millis() + ); } - lib.set_rom_loading(expected > 0); - tracing::debug!( - "rom-list-render context={} latency_ms={} (stale_complete)", - context, - started.elapsed().as_millis() - ); } } }