Host: the settings backup commands (collect, export, open, apply) are served for every app; SiteHooks::backup_drafts and backup_apply carry what only the app knows; commands::BACKUP, testkit::assert_backup_guards

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
CRTkafa 2026-10-01 04:41:12 +07:00
parent 198b1160f2
commit 409949edb9
5 changed files with 188 additions and 5 deletions

View file

@ -262,6 +262,18 @@ pub trait SiteHooks: Send + Sync + 'static {
&[]
}
/// The `drafts` backup section (only when the owner ticks "include drafts"), or none. By default none.
fn backup_drafts(&self, _app: &AppHandle) -> Result<Option<serde_json::Value>, String> {
Ok(None)
}
/// Applies the sections of an import the owner chose ([`commands::BACKUP`]): check each the way
/// its own setter does, write nothing if any is bad, and return what was applied and notes for
/// the owner (`{ applied: [..], notes: [..] }`). By default importing is not supported.
fn backup_apply(&self, _app: &AppHandle, _sections: &serde_json::Map<String, serde_json::Value>) -> Result<serde_json::Value, String> {
Err("UNAVAILABLE: this app cannot import a backup".into())
}
/// Developer mode: show the theme file the owner picked (read `path`, make it the theme preview
/// in every site tab). An error is shown with its file and line. By default themes are not
/// supported and this does nothing.
@ -1198,6 +1210,11 @@ fn store_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + '
|_| false
}
/// The backup commands ([`commands::BACKUP`]).
fn backup_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 'static {
crate::backup_commands::handler()
}
/// The developer-mode commands ([`commands::DEV`]).
fn dev_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 'static {
crate::dev_commands::handler()
@ -1271,6 +1288,7 @@ impl App {
let update_handler = update_handler();
let sync_handler = sync_handler();
let dev_handler = dev_handler();
let backup_handler = backup_handler();
let builder = tauri::Builder::<Wry>::default()
// Must be first: a second launch focuses the running window instead of fighting over
// the app's data and WebView profile (and hands over its link).
@ -1383,6 +1401,8 @@ impl App {
sync_handler(invoke)
} else if commands::DEV.contains(&invoke.message.command()) {
dev_handler(invoke)
} else if commands::BACKUP.contains(&invoke.message.command()) {
backup_handler(invoke)
} else if commands::is_host(invoke.message.command()) {
host_handler(invoke)
} else {