diff --git a/src/cm_popup.rs b/src/cm_popup.rs index eb64b59..19e6ade 100644 --- a/src/cm_popup.rs +++ b/src/cm_popup.rs @@ -140,9 +140,26 @@ impl InvokeUiCM for HeadlessCm { fn remove_connection(&self, id: i32, _close: bool) { trace(&format!("remove_connection: id={id}")); - let entry = self.approved.lock().unwrap().remove(&id); + // Remove this session and read how many approved sessions remain, while + // holding the lock so the check is atomic against concurrent add/remove. + let (entry, remaining) = { + let mut approved = self.approved.lock().unwrap(); + let entry = approved.remove(&id); + (entry, approved.len()) + }; if let Some((peer_id, name)) = entry { - std::thread::spawn(move || show_session_ended(&peer_id, &name)); + // Only notify once EVERY approved session has ended. With multiple + // concurrent sessions (a second supporter, or a file-transfer + // session running alongside remote control) the user shouldn't get + // a "session ended" banner while other sessions are still open — + // they'd see one banner per close even though support is ongoing. + if remaining == 0 { + std::thread::spawn(move || show_session_ended(&peer_id, &name)); + } else { + trace(&format!( + "remove_connection: {remaining} approved session(s) still open; suppressing banner" + )); + } } }