feat(fs/watch): migrate to notify-debouncer-full (#885)

* Add support for notify-debouncer-full

* Add fs watch to demo

* Remove notify-debouncer-mini

* Rename RawEvent to WatchEvent

* Add full type definition for EventKind

* Remove `track file ids` option from fs watcher

* Update plugins/fs/guest-js/index.ts
This commit is contained in:
Daniel Faust
2024-01-18 19:35:49 +01:00
committed by GitHub
parent 0879a87a7e
commit 61edbbec0a
7 changed files with 162 additions and 43 deletions
+2 -2
View File
@@ -21,7 +21,7 @@ anyhow = "1"
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-full" ]
+61 -25
View File
@@ -1098,8 +1098,8 @@ interface DebouncedWatchOptions extends WatchOptions {
/**
* @since 2.0.0
*/
type RawEvent = {
type: RawEventKind;
type WatchEvent = {
type: WatchEventKind;
paths: string[];
attrs: unknown;
};
@@ -1107,28 +1107,60 @@ type RawEvent = {
/**
* @since 2.0.0
*/
type RawEventKind =
| "any "
| {
access?: unknown;
}
| {
create?: unknown;
}
| {
modify?: unknown;
}
| {
remove?: unknown;
}
type WatchEventKind =
| "any"
| { access: WatchEventKindAccess }
| { create: WatchEventKindCreate }
| { modify: WatchEventKindModify }
| { remove: WatchEventKindRemove }
| "other";
/**
* @since 2.0.0
*/
type DebouncedEvent =
| { kind: "Any"; path: string }[]
| { kind: "AnyContinuous"; path: string }[];
type WatchEventKindAccess =
| { kind: "any" }
| { kind: "close"; mode: "any" | "execute" | "read" | "write" | "other" }
| { kind: "open"; mode: "any" | "execute" | "read" | "write" | "other" }
| { kind: "other" };
/**
* @since 2.0.0
*/
type WatchEventKindCreate =
| { kind: "any" }
| { kind: "file" }
| { kind: "folder" }
| { kind: "other" };
/**
* @since 2.0.0
*/
type WatchEventKindModify =
| { kind: "any" }
| { kind: "data"; mode: "any" | "size" | "content" | "other" }
| {
kind: "metadata";
mode:
| "any"
| "access-time"
| "write-time"
| "permissions"
| "ownership"
| "extended"
| "other";
}
| { kind: "name"; mode: "any" | "to" | "from" | "both" | "other" }
| { kind: "other" };
/**
* @since 2.0.0
*/
type WatchEventKindRemove =
| { kind: "any" }
| { kind: "file" }
| { kind: "folder" }
| { kind: "other" };
/**
* @since 2.0.0
@@ -1146,7 +1178,7 @@ async function unwatch(rid: number): Promise<void> {
*/
async function watch(
paths: string | string[] | URL | URL[],
cb: (event: DebouncedEvent) => void,
cb: (event: WatchEvent) => void,
options?: DebouncedWatchOptions,
): Promise<UnwatchFn> {
const opts = {
@@ -1163,7 +1195,7 @@ async function watch(
}
}
const onEvent = new Channel<DebouncedEvent>();
const onEvent = new Channel<WatchEvent>();
onEvent.onmessage = cb;
const rid: number = await invoke("plugin:fs|watch", {
@@ -1184,7 +1216,7 @@ async function watch(
*/
async function watchImmediate(
paths: string | string[] | URL | URL[],
cb: (event: RawEvent) => void,
cb: (event: WatchEvent) => void,
options?: WatchOptions,
): Promise<UnwatchFn> {
const opts = {
@@ -1201,7 +1233,7 @@ async function watchImmediate(
}
}
const onEvent = new Channel<RawEvent>();
const onEvent = new Channel<WatchEvent>();
onEvent.onmessage = cb;
const rid: number = await invoke("plugin:fs|watch", {
@@ -1232,8 +1264,12 @@ export type {
FileInfo,
WatchOptions,
DebouncedWatchOptions,
DebouncedEvent,
RawEvent,
WatchEvent,
WatchEventKind,
WatchEventKindAccess,
WatchEventKindCreate,
WatchEventKindModify,
WatchEventKindRemove,
UnwatchFn,
};
+9 -10
View File
@@ -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::{new_debouncer, DebounceEventResult, Debouncer, FileIdMap};
use serde::Deserialize;
use tauri::{
ipc::Channel,
@@ -43,7 +43,7 @@ impl WatcherResource {
impl Resource for WatcherResource {}
enum WatcherKind {
Debouncer(Debouncer<RecommendedWatcher>),
Debouncer(Debouncer<RecommendedWatcher, FileIdMap>),
Watcher(RecommendedWatcher),
}
@@ -60,10 +60,10 @@ fn watch_raw(on_event: Channel, rx: Receiver<notify::Result<Event>>) {
fn watch_debounced(on_event: Channel, rx: Receiver<DebounceEventResult>) {
spawn(move || {
while let Ok(event) = rx.recv() {
if let Ok(event) = event {
while let Ok(Ok(events)) = rx.recv() {
for event in events {
// TODO: Should errors be emitted too?
let _ = on_event.send(&event);
let _ = on_event.send(&event.event);
}
}
});
@@ -97,10 +97,9 @@ 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();
let mut debouncer = new_debouncer(Duration::from_millis(delay), None, tx)?;
for path in &resolved_paths {
watcher.watch(path.as_ref(), mode)?;
debouncer.watcher().watch(path.as_ref(), mode)?;
}
watch_debounced(on_event, rx);
WatcherKind::Debouncer(debouncer)
@@ -130,14 +129,14 @@ pub async fn unwatch<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> CommandR
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::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())
})?
})?;
}
}
}