ファイルやディレクトリの変更(作成、更新、削除)を検知するには、Rust エコシステムの標準的なクレートである notify を使用するのが最も確実です。Rust 側で実装しイベントでフロントエンドに通知するパターンを解説します。
1. 依存関係の追加
# src-tauri ディレクトリで実行します
cd src-tauri
cargo add notify --features serde
2. 監視ロジックの実装
setup フックなどで監視を開始し、変更があればフロントエンドへイベントを emit します。
src-tauri/src/lib.rs:
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
use std::sync::mpsc::channel;
use tauri::{AppHandle, Manager, Emitter};
fn setup_watcher(app: &AppHandle) {
let app_handle = app.clone();
// イベント監視はブロッキング操作を含むため、専用のスレッドで実行します
std::thread::spawn(move || {
let (tx, rx) = channel();
// ウォッチャーの作成
let mut watcher = RecommendedWatcher::new(tx, Config::default()).unwrap();
// 監視対象のパス (例: ドキュメントフォルダ)
// 注意: 実際のアプリでは権限やパスの存在確認を行ってください
let path_to_watch = match app_handle.path().document_dir() {
Ok(path) => path,
Err(e) => {
eprintln!("Failed to get document dir: {}", e);
return;
}
};
// 監視開始 (RecursiveMode::Recursive でサブディレクトリも監視)
if let Err(e) = watcher.watch(&path_to_watch, RecursiveMode::Recursive) {
eprintln!("Watcher error: {:?}", e);
return;
}
// イベントループ (チャンネルからの受信待機でブロックする)
for res in rx {
match res {
Ok(event) => {
println!("Change detected: {:?}", event);
// フロントエンドに通知 (notify の Event は serde feature でシリアライズ可能)
if let Err(e) = app_handle.emit("file-changed", event) {
eprintln!("Failed to emit event: {}", e);
}
},
Err(e) => println!("Watch error: {:?}", e),
}
}
});
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app| {
setup_watcher(app.handle());
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
3. フロントエンドでの受信
import { listen } from '@tauri-apps/api/event';
type FileEvent = {
kind: any; // 作成、変更、削除など
paths: string[];
};
await listen<FileEvent>('file-changed', (event) => {
console.log('File changed:', event.payload);
// UIを更新など
});
注意点
notifyは OS ごとの API (inotify, FSEvents, ReadDirectoryChangesW) を抽象化していますが、挙動に差異がある場合があります。