From 7e45e621a38d2f9cf1163d64b1298266f01834d3 Mon Sep 17 00:00:00 2001 From: jeremy <94247773+1jehuang@users.noreply.github.com> Date: Tue, 1 Sep 2026 12:24:51 -0700 Subject: [PATCH] fix: clear inline images with session (fixes #1123) --- .../jcode-tui/src/tui/app/commands_review.rs | 1 + .../src/tui/app/remote/key_handling.rs | 1 + crates/jcode-tui/src/tui/app/state_ui.rs | 9 +++++++ crates/jcode-tui/src/tui/app/tests.rs | 26 +++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/crates/jcode-tui/src/tui/app/commands_review.rs b/crates/jcode-tui/src/tui/app/commands_review.rs index bd2189c150..b08a7b5242 100644 --- a/crates/jcode-tui/src/tui/app/commands_review.rs +++ b/crates/jcode-tui/src/tui/app/commands_review.rs @@ -305,6 +305,7 @@ pub(super) fn reset_current_session(app: &mut App) { app.queued_messages.clear(); app.pasted_contents.clear(); app.pending_images.clear(); + app.clear_inline_image_state(); app.active_skill = None; app.improve_mode = None; let mut session = Session::create(None, None); diff --git a/crates/jcode-tui/src/tui/app/remote/key_handling.rs b/crates/jcode-tui/src/tui/app/remote/key_handling.rs index aec68a9732..88a5c9c339 100644 --- a/crates/jcode-tui/src/tui/app/remote/key_handling.rs +++ b/crates/jcode-tui/src/tui/app/remote/key_handling.rs @@ -1677,6 +1677,7 @@ async fn handle_remote_key_internal( app.queued_messages.clear(); app.pasted_contents.clear(); app.pending_images.clear(); + app.clear_inline_image_state(); app.clear_streaming_render_state(); app.clear_live_usage_state(); // Full transcript discard: diagrams and side panel pages diff --git a/crates/jcode-tui/src/tui/app/state_ui.rs b/crates/jcode-tui/src/tui/app/state_ui.rs index f74f295c50..7c366d9f00 100644 --- a/crates/jcode-tui/src/tui/app/state_ui.rs +++ b/crates/jcode-tui/src/tui/app/state_ui.rs @@ -185,6 +185,15 @@ impl App { self.side_pane_images_signature_cache.set(None); } + /// Drop rendered inline images and every cache keyed by their contents. + /// Use this when the entire transcript is discarded. + pub(crate) fn clear_inline_image_state(&mut self) { + self.remote_side_pane_images.clear(); + self.invalidate_side_pane_images_signature(); + self.expanded_images.clear(); + self.expanded_images_version = self.expanded_images_version.wrapping_add(1); + } + /// Bump the display-messages version without rescanning the transcript to /// recompute counters. Callers that have already maintained the cached /// counters incrementally (e.g. a single append) use this to stay O(1). diff --git a/crates/jcode-tui/src/tui/app/tests.rs b/crates/jcode-tui/src/tui/app/tests.rs index 926ceb8c8c..f58a899976 100644 --- a/crates/jcode-tui/src/tui/app/tests.rs +++ b/crates/jcode-tui/src/tui/app/tests.rs @@ -1723,16 +1723,40 @@ fn assert_clear_usage_reset(app: &App) { assert!(!app.kv_cache.current_api_usage_recorded); } +fn seed_stale_clear_image(app: &mut App) -> u64 { + app.remote_side_pane_images = vec![crate::session::RenderedImage { + media_type: "image/png".to_string(), + data: "stale-image".to_string(), + label: Some("stale.png".to_string()), + source: crate::session::RenderedImageSource::UserInput, + anchor: None, + }]; + let _ = crate::tui::TuiState::side_pane_images_signature(app); + app.expanded_images_version +} + +fn assert_clear_image_reset(app: &App, previous_version: u64) { + assert!(app.remote_side_pane_images.is_empty()); + assert_eq!(app.side_pane_images_signature_cache.get(), None); + assert!(app.expanded_images.is_empty()); + assert_eq!( + app.expanded_images_version, + previous_version.wrapping_add(1) + ); +} + #[test] fn local_clear_resets_provider_reported_context_usage() { let mut app = create_test_app(); seed_stale_clear_usage(&mut app); seed_stale_clear_swarm_plan(&mut app); + let image_version = seed_stale_clear_image(&mut app); assert!(super::commands::handle_session_command(&mut app, "/clear")); assert_clear_usage_reset(&app); assert_clear_swarm_plan_reset(&app); + assert_clear_image_reset(&app, image_version); } #[test] @@ -1745,6 +1769,7 @@ fn remote_clear_resets_provider_reported_context_usage() { app.is_remote = true; seed_stale_clear_usage(&mut app); seed_stale_clear_swarm_plan(&mut app); + let image_version = seed_stale_clear_image(&mut app); app.input = "/clear".to_string(); app.cursor_pos = app.input.len(); @@ -1753,6 +1778,7 @@ fn remote_clear_resets_provider_reported_context_usage() { assert_clear_usage_reset(&app); assert_clear_swarm_plan_reset(&app); + assert_clear_image_reset(&app, image_version); } fn seed_stale_clear_swarm_plan(app: &mut App) {