Skip to content

Commit

Permalink
Add support for notify-debouncer-full
Browse files Browse the repository at this point in the history
  • Loading branch information
dfaust committed Jan 11, 2024
1 parent 1b1d795 commit d37c4b8
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changes/fs-add-notify-debouncer-full.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"fs": "patch"
"fs-js": "patch"
---

Add support for `notify-debouncer-full`. [(plugins-workspace#885)](https://github.com/tauri-apps/plugins-workspace/pull/885)
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion plugins/fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ uuid = { version = "1", features = [ "v4" ] }
glob = "0.3"
notify = { version = "6", optional = true, features = [ "serde" ] }
notify-debouncer-mini = { version = "0.4", optional = true, features = [ "serde" ] }
notify-debouncer-full = { version = "0.3", optional = true }

[features]
watch = [ "notify", "notify-debouncer-mini" ]
watch = [ "notify", "notify-debouncer-mini", "notify-debouncer-full" ]
4 changes: 4 additions & 0 deletions plugins/fs/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,10 @@ interface WatchOptions {
interface DebouncedWatchOptions extends WatchOptions {
/** Debounce delay */
delayMs?: number;
/** Use {@link https://docs.rs/notify-debouncer-full | full debouncer} instead of the {@link https://docs.rs/notify-debouncer-mini | mini debouncer} */
debounceFull?: boolean;
/** Keep track of the file system IDs of all files */
trackFileIds?: boolean;
}

/**
Expand Down
74 changes: 61 additions & 13 deletions plugins/fs/src/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT

use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher};
use notify_debouncer_mini::{new_debouncer, DebounceEventResult, Debouncer};
use notify_debouncer_full::FileIdCache;
use serde::Deserialize;
use tauri::{
ipc::Channel,
Expand Down Expand Up @@ -43,7 +43,10 @@ impl WatcherResource {
impl Resource for WatcherResource {}

enum WatcherKind {
Debouncer(Debouncer<RecommendedWatcher>),
DebouncerMini(notify_debouncer_mini::Debouncer<RecommendedWatcher>),
DebouncerFull(
notify_debouncer_full::Debouncer<RecommendedWatcher, notify_debouncer_full::FileIdMap>,
),
Watcher(RecommendedWatcher),
}

Expand All @@ -58,7 +61,10 @@ fn watch_raw(on_event: Channel, rx: Receiver<notify::Result<Event>>) {
});
}

fn watch_debounced(on_event: Channel, rx: Receiver<DebounceEventResult>) {
fn watch_debounced_mini(
on_event: Channel,
rx: Receiver<notify_debouncer_mini::DebounceEventResult>,
) {
spawn(move || {
while let Ok(event) = rx.recv() {
if let Ok(event) = event {
Expand All @@ -69,12 +75,32 @@ fn watch_debounced(on_event: Channel, rx: Receiver<DebounceEventResult>) {
});
}

fn watch_debounced_full(
on_event: Channel,
rx: Receiver<notify_debouncer_full::DebounceEventResult>,
) {
spawn(move || {
while let Ok(events) = rx.recv() {
if let Ok(events) = events {
for event in events {
// TODO: Should errors be emitted too?
let _ = on_event.send(&event.event);
}
}
}
});
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WatchOptions {
dir: Option<BaseDirectory>,
recursive: bool,
delay_ms: Option<u64>,
#[serde(default)]
debounce_full: bool,
#[serde(default)]
track_file_ids: bool,
}

#[tauri::command]
Expand All @@ -96,14 +122,28 @@ pub async fn watch<R: Runtime>(
};

let kind = if let Some(delay) = options.delay_ms {
let (tx, rx) = channel();
let mut debouncer = new_debouncer(Duration::from_millis(delay), tx)?;
let watcher = debouncer.watcher();
for path in &resolved_paths {
watcher.watch(path.as_ref(), mode)?;
if options.debounce_full {
let (tx, rx) = channel();
let mut debouncer =
notify_debouncer_full::new_debouncer(Duration::from_millis(delay), None, tx)?;
for path in &resolved_paths {
debouncer.watcher().watch(path.as_ref(), mode)?;
if options.track_file_ids {
debouncer.cache().add_path(path.as_ref());
}
}
watch_debounced_full(on_event, rx);
WatcherKind::DebouncerFull(debouncer)
} else {
let (tx, rx) = channel();
let mut debouncer =
notify_debouncer_mini::new_debouncer(Duration::from_millis(delay), tx)?;
for path in &resolved_paths {
debouncer.watcher().watch(path.as_ref(), mode)?;
}
watch_debounced_mini(on_event, rx);
WatcherKind::DebouncerMini(debouncer)
}
watch_debounced(on_event, rx);
WatcherKind::Debouncer(debouncer)
} else {
let (tx, rx) = channel();
let mut watcher = RecommendedWatcher::new(tx, Config::default())?;
Expand All @@ -126,18 +166,26 @@ pub async fn unwatch<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> CommandR
let watcher = app.resources_table().take::<WatcherResource>(rid)?;
WatcherResource::with_lock(&watcher, |watcher| {
match &mut watcher.kind {
WatcherKind::Debouncer(ref mut debouncer) => {
WatcherKind::DebouncerMini(ref mut debouncer) => {
for path in &watcher.paths {
debouncer.watcher().unwatch(path.as_ref()).map_err(|e| {
format!("failed to unwatch path: {} with error: {e}", path.display())
})?;
}
}
WatcherKind::DebouncerFull(ref mut debouncer) => {
for path in &watcher.paths {
debouncer.watcher().unwatch(path.as_ref()).map_err(|e| {
format!("failed to unwatch path: {} with error: {e}", path.display())
})?
})?;
debouncer.cache().remove_path(path.as_ref());
}
}
WatcherKind::Watcher(ref mut w) => {
for path in &watcher.paths {
w.unwatch(path.as_ref()).map_err(|e| {
format!("failed to unwatch path: {} with error: {e}", path.display())
})?
})?;
}
}
}
Expand Down

0 comments on commit d37c4b8

Please sign in to comment.