ユーザーがウィンドウを閉じようとした際に、誤操作防止のための確認ダイアログを表示する方法を紹介します。
ドキュメントの編集内容が保存されていない場合や、重要な処理の実行中に、うっかりアプリを閉じてしまう事故を防ぎます。
フロントエンドの onCloseRequested メソッドを使用した実装方法を解説します。
前提条件
Permissions (権限) の設定
src-tauri/capabilities/default.json に以下の権限を追加します。
destroy メソッドを使用する場合は、core:window:allow-destroy が必要です。
{
"permissions": [
...,
"core:window:default",
"core:window:allow-destroy"
]
}
1. フロントエンドから変更する (TypeScript)
onCloseRequested メソッドを使用し、ウィンドウが閉じられるイベントをフックします。
ユーザーがキャンセルを選択した場合、event.preventDefault() を呼び出すことでウィンドウの終了を阻止できます。
サンプルコード
import { getCurrentWindow } from '@tauri-apps/api/window';
const appWindow = getCurrentWindow();
await appWindow.onCloseRequested(async (event) => {
const confirmed = window.confirm('保存せずに終了しますか?');
if (!confirmed) {
// ユーザーがキャンセルした場合、ウィンドウを閉じる動作をキャンセル
event.preventDefault();
}
});
2. 非同期の確認処理を行う場合 (TypeScript)
window.confirm は処理をブロックしますが、独自のUIを使用した確認ダイアログなどは非同期で結果を待ちます。
このような場合、onCloseRequested 内で即座に event.preventDefault() を呼び出して一旦終了をキャンセルし、ユーザーの確認が取れた後に destroy メソッドでウィンドウを破棄します。
注意: ユーザー確認後にcloseメソッドを使うと、再度onCloseRequestedが発火して無限ループになる恐れがあるため、destroyを使用して強制的に閉じます。destroyメソッドを使用するには、権限設定にcore:window:allow-destroyが必要です。
import { getCurrentWindow } from '@tauri-apps/api/window';
const appWindow = getCurrentWindow();
await appWindow.onCloseRequested(async (event) => {
// 非同期処理を行う前に、一旦イベントをキャンセルしておく
event.preventDefault();
// 独自の確認ダイアログを表示する関数(ここでは window.confirm を非同期的にラップして代用)
const confirmed = await new Promise<boolean>((resolve) => {
// setTimeout を使い、非同期処理をシミュレート
setTimeout(() => {
const result = window.confirm('【非同期】保存せずに終了しますか?');
resolve(result);
}, 0);
});
if (confirmed) {
// ユーザーが許可した場合、再チェックなしで強制的に破棄する
await appWindow.destroy();
}
});
3. バックエンドで検知してフロントエンドに通知する (Rust)
Rust 側で CloseRequested イベントをフックし、フロントエンドに通知する方法です。
バックエンドの状態に応じて制御したい場合などに有効です。
Rust 側 (src-tauri/src/lib.rs)
Tauri v2 では lib.rs の run 関数に記述するのが一般的です。
api.prevent_close() でウィンドウが閉じるのを防ぎ、window.emit で通知を送ります。
emit を使用するには tauri::Emitter トレイトのインポートが必要です。
use tauri::{Emitter, WindowEvent};
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.on_window_event(|window, event| {
if let WindowEvent::CloseRequested { api, .. } = event {
// ウィンドウのクローズを一旦キャンセル
api.prevent_close();
// フロントエンドへイベントを通知
// ペイロードは必要に応じて変更してください
let _ = window.emit("close-requested", ());
}
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
フロントエンド側での受け取り (TypeScript)
フロントエンドではイベントを受け取り、確認後に destroy メソッドで終了します。
注意:destroyメソッドを使用するには、権限設定にcore:window:allow-destroyが必要です。
import { listen } from '@tauri-apps/api/event';
import { getCurrentWindow } from '@tauri-apps/api/window';
const appWindow = getCurrentWindow();
listen('close-requested', async () => {
const confirmed = await window.confirm('終了しますか?');
if (confirmed) {
// 確認が取れたら強制的に閉じる
await appWindow.destroy();
}
});