Skip to content

Commit dac4d53

Browse files
refactor(fs): reduce overhead of watch (#2613)
1 parent 5e78988 commit dac4d53

File tree

12 files changed

+95
-155
lines changed

12 files changed

+95
-155
lines changed

.changes/fs-watch-cleanup.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fs: minor
3+
fs-js: minor
4+
---
5+
6+
Reduce the overhead of `watch` and `unwatch`

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/api/src-tauri/capabilities/base.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"fs:allow-mkdir",
7070
"fs:allow-remove",
7171
"fs:allow-write-text-file",
72+
"fs:read-meta",
7273
"fs:scope-download-recursive",
7374
"fs:scope-resource-recursive",
7475
{

examples/api/src/views/FileSystem.svelte

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22
import * as fs from "@tauri-apps/plugin-fs";
33
import { convertFileSrc } from "@tauri-apps/api/core";
44
import { arrayBufferToBase64 } from "../lib/utils";
5+
import { onDestroy } from "svelte";
56
67
export let onMessage;
78
export let insecureRenderHtml;
89
910
let path = "";
1011
let img;
12+
/** @type {fs.FileHandle} */
1113
let file;
1214
let renameTo;
1315
let watchPath = "";
14-
let watchDebounceDelay = 0;
16+
let watchDebounceDelay = "0";
1517
let watchRecursive = false;
1618
let unwatchFn;
1719
let unwatchPath = "";
@@ -118,7 +120,7 @@
118120
.getElementById("file-save")
119121
.addEventListener("click", function () {
120122
fs.writeTextFile(path, fileInput.value, {
121-
dir: getDir(),
123+
baseDir: getDir(),
122124
}).catch(onMessage);
123125
});
124126
});
@@ -170,6 +172,15 @@
170172
unwatchFn = undefined;
171173
unwatchPath = undefined;
172174
}
175+
176+
onDestroy(() => {
177+
if (file) {
178+
file.close();
179+
}
180+
if (unwatchFn) {
181+
unwatchFn();
182+
}
183+
})
173184
</script>
174185

175186
<div class="flex flex-col">

plugins/fs/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ tauri = { workspace = true }
3535
thiserror = { workspace = true }
3636
url = { workspace = true }
3737
anyhow = "1"
38-
uuid = { version = "1", features = ["v4"] }
3938
glob = { workspace = true }
4039
# TODO: Remove `serialization-compat-6` in v3
4140
notify = { version = "8", optional = true, features = [

plugins/fs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ fn main() {
6868
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
6969

7070
```javascript
71-
import { metadata } from '@tauri-apps/plugin-fs'
71+
import { stat } from '@tauri-apps/plugin-fs'
7272

73-
await metadata('/path/to/file')
73+
await stat('/path/to/file')
7474
```
7575

7676
## Contributing

plugins/fs/api-iife.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/fs/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const COMMANDS: &[(&str, &[&str])] = &[
101101
("fstat", &[]),
102102
("exists", &[]),
103103
("watch", &[]),
104+
// TODO: Remove this in v3
104105
("unwatch", &[]),
105106
("size", &[]),
106107
];

plugins/fs/guest-js/index.ts

Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,31 +1245,19 @@ type WatchEventKindRemove =
12451245
| { kind: 'folder' }
12461246
| { kind: 'other' }
12471247

1248+
// TODO: Remove this in v3, return `Watcher` instead
12481249
/**
12491250
* @since 2.0.0
12501251
*/
12511252
type UnwatchFn = () => void
12521253

1253-
async function unwatch(rid: number): Promise<void> {
1254-
await invoke('plugin:fs|unwatch', { rid })
1255-
}
1254+
class Watcher extends Resource {}
12561255

1257-
/**
1258-
* Watch changes (after a delay) on files or directories.
1259-
*
1260-
* @since 2.0.0
1261-
*/
1262-
async function watch(
1256+
async function watchInternal(
12631257
paths: string | string[] | URL | URL[],
12641258
cb: (event: WatchEvent) => void,
1265-
options?: DebouncedWatchOptions
1259+
options: DebouncedWatchOptions
12661260
): Promise<UnwatchFn> {
1267-
const opts = {
1268-
recursive: false,
1269-
delayMs: 2000,
1270-
...options
1271-
}
1272-
12731261
const watchPaths = Array.isArray(paths) ? paths : [paths]
12741262

12751263
for (const path of watchPaths) {
@@ -1283,15 +1271,35 @@ async function watch(
12831271

12841272
const rid: number = await invoke('plugin:fs|watch', {
12851273
paths: watchPaths.map((p) => (p instanceof URL ? p.toString() : p)),
1286-
options: opts,
1274+
options,
12871275
onEvent
12881276
})
12891277

1278+
const watcher = new Watcher(rid)
1279+
12901280
return () => {
1291-
void unwatch(rid)
1281+
void watcher.close()
12921282
}
12931283
}
12941284

1285+
// TODO: Return `Watcher` instead in v3
1286+
/**
1287+
* Watch changes (after a delay) on files or directories.
1288+
*
1289+
* @since 2.0.0
1290+
*/
1291+
async function watch(
1292+
paths: string | string[] | URL | URL[],
1293+
cb: (event: WatchEvent) => void,
1294+
options?: DebouncedWatchOptions
1295+
): Promise<UnwatchFn> {
1296+
return await watchInternal(paths, cb, {
1297+
delayMs: 2000,
1298+
...options
1299+
})
1300+
}
1301+
1302+
// TODO: Return `Watcher` instead in v3
12951303
/**
12961304
* Watch changes on files or directories.
12971305
*
@@ -1302,32 +1310,10 @@ async function watchImmediate(
13021310
cb: (event: WatchEvent) => void,
13031311
options?: WatchOptions
13041312
): Promise<UnwatchFn> {
1305-
const opts = {
1306-
recursive: false,
1313+
return await watchInternal(paths, cb, {
13071314
...options,
1308-
delayMs: null
1309-
}
1310-
1311-
const watchPaths = Array.isArray(paths) ? paths : [paths]
1312-
1313-
for (const path of watchPaths) {
1314-
if (path instanceof URL && path.protocol !== 'file:') {
1315-
throw new TypeError('Must be a file URL.')
1316-
}
1317-
}
1318-
1319-
const onEvent = new Channel<WatchEvent>()
1320-
onEvent.onmessage = cb
1321-
1322-
const rid: number = await invoke('plugin:fs|watch', {
1323-
paths: watchPaths.map((p) => (p instanceof URL ? p.toString() : p)),
1324-
options: opts,
1325-
onEvent
1315+
delayMs: undefined
13261316
})
1327-
1328-
return () => {
1329-
void unwatch(rid)
1330-
}
13311317
}
13321318

13331319
/**

plugins/fs/src/commands.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,6 @@ pub fn open<R: Runtime>(
150150
Ok(rid)
151151
}
152152

153-
#[tauri::command]
154-
pub fn close<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> CommandResult<()> {
155-
webview.resources_table().close(rid).map_err(Into::into)
156-
}
157-
158153
#[derive(Debug, Clone, Deserialize)]
159154
#[serde(rename_all = "camelCase")]
160155
pub struct CopyFileOptions {

plugins/fs/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
397397
commands::create,
398398
commands::open,
399399
commands::copy_file,
400-
commands::close,
401400
commands::mkdir,
402401
commands::read_dir,
403402
commands::read,
@@ -420,8 +419,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
420419
commands::size,
421420
#[cfg(feature = "watch")]
422421
watcher::watch,
423-
#[cfg(feature = "watch")]
424-
watcher::unwatch
425422
])
426423
.setup(|app, api| {
427424
let scope = Scope {

0 commit comments

Comments
 (0)