Skip to content

Commit 21b3bc5

Browse files
committed
Bugfix: MTP event debouncer drops events
Now ALL MTP E2E tests are passing! This is a milestone! We have reliable MTP, and reliable MTP E2E tests! - `emit_directory_changed` permanently dropped events suppressed by the 500ms debounce window. Now schedules a trailing emit after the window expires, so the last event in a burst always gets processed. - Formatting fix in `watcher.rs` (indentation only).
1 parent c10e061 commit 21b3bc5

2 files changed

Lines changed: 21 additions & 10 deletions

File tree

apps/desktop/src-tauri/src/file_system/watcher.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,15 @@ pub fn handle_directory_change(listing_id: &str) {
356356
use crate::file_system::listing::caching::LISTING_CACHE;
357357
if let Ok(cache) = LISTING_CACHE.read()
358358
&& let Some(listing) = cache.get(listing_id)
359-
&& let Some(vol) = crate::file_system::get_volume_manager().get(&listing.volume_id)
360-
&& !vol.supports_watching() {
361-
log::debug!(
362-
"handle_directory_change: skipping non-watchable volume (volume={})",
363-
listing.volume_id
364-
);
365-
return;
366-
}
359+
&& let Some(vol) = crate::file_system::get_volume_manager().get(&listing.volume_id)
360+
&& !vol.supports_watching()
361+
{
362+
log::debug!(
363+
"handle_directory_change: skipping non-watchable volume (volume={})",
364+
listing.volume_id
365+
);
366+
return;
367+
}
367368
}
368369

369370
// Get old entries and path from the unified LISTING_CACHE

apps/desktop/src-tauri/src/mtp/connection/event_loop.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,22 @@ impl MtpConnectionManager {
155155
/// Uses the unified diff system shared with local file watching, providing
156156
/// smooth incremental UI updates without full directory reloads.
157157
fn emit_directory_changed(device_id: &str, app: &AppHandle) {
158-
// Check debouncer via the global connection manager
158+
// Check debouncer via the global connection manager.
159+
// When suppressed, schedule a trailing emit after the debounce window
160+
// so the last event in a burst is never permanently dropped.
159161
if !connection_manager().event_debouncer.should_emit(device_id) {
160162
debug!(
161-
"MTP event loop: directory change DEBOUNCED for device={} (within {}ms window)",
163+
"MTP event loop: directory change DEBOUNCED for device={} (within {}ms window), scheduling trailing emit",
162164
device_id, EVENT_DEBOUNCE_MS
163165
);
166+
let device_id_owned = device_id.to_string();
167+
let app_clone = app.clone();
168+
tokio::spawn(async move {
169+
tokio::time::sleep(Duration::from_millis(EVENT_DEBOUNCE_MS + 50)).await;
170+
// Re-emit — this goes through the debouncer again (which will pass
171+
// since the window has expired) to avoid duplicate processing.
172+
Self::emit_directory_changed(&device_id_owned, &app_clone);
173+
});
164174
return;
165175
}
166176

0 commit comments

Comments
 (0)