host: the drafts vault commands (draft_list/save/revisions/status, observation_list, data_export) are the host's (AppConfig::with_vault, commands::VAULT); the app takes the vault through vault_commands::lock

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
CRTkafa 2026-10-01 16:17:30 +07:00
parent fc08bc89cb
commit 400f22c40c
6 changed files with 147 additions and 11 deletions

View file

@ -102,6 +102,10 @@ pub struct AppConfig {
/// Keyword alert settings (saved in app data, handed to the page runtime): serves
/// [`commands::ALERTS`]; the match and the notification are the app's.
pub alerts: Option<&'static crate::alerts_commands::AlertsConfig>,
/// The drafts vault (a SQLite database in app data with CAS revisions): serves
/// [`commands::VAULT`]; the rules (kinds, limits, capture ownership) are the app's.
#[cfg(feature = "vault")]
pub vault: Option<&'static crate::vault_commands::VaultConfig>,
/// Native updates and the hotfix channel: serves [`commands::UPDATE`] and runs the update loop.
/// Needs `updater` (the plugin) and the `net` feature.
#[cfg(feature = "net")]
@ -134,6 +138,8 @@ impl AppConfig {
dev: false,
themes: None,
alerts: None,
#[cfg(feature = "vault")]
vault: None,
#[cfg(feature = "net")]
updates: None,
}
@ -164,6 +170,13 @@ impl AppConfig {
self
}
/// Serves the drafts vault commands ([`commands::VAULT`]) over this database and rules.
#[cfg(feature = "vault")]
pub const fn with_vault(mut self, vault: &'static crate::vault_commands::VaultConfig) -> Self {
self.vault = Some(vault);
self
}
/// Serves the sync commands ([`commands::SYNC`]).
pub const fn with_sync(mut self) -> Self {
self.sync = true;
@ -1281,6 +1294,14 @@ fn alerts_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync +
crate::alerts_commands::handler()
}
/// The drafts vault commands ([`commands::VAULT`]); without the `vault` feature none are served.
fn vault_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 'static {
#[cfg(feature = "vault")]
return crate::vault_commands::handler();
#[cfg(not(feature = "vault"))]
|_: tauri::ipc::Invoke<Wry>| false
}
/// The theme commands ([`commands::THEME`]).
fn theme_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 'static {
crate::theme_commands::handler()
@ -1356,6 +1377,7 @@ impl App {
let dev_handler = dev_handler();
let theme_handler = theme_handler();
let alerts_handler = alerts_handler();
let vault_handler = vault_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
@ -1444,6 +1466,8 @@ impl App {
crate::dev_commands::init(&handle);
crate::theme_commands::init(&handle);
crate::alerts_commands::init(&handle);
#[cfg(feature = "vault")]
crate::vault_commands::init(&handle)?;
#[cfg(feature = "net")]
crate::fonts_commands::init(&handle);
#[cfg(feature = "net")]
@ -1480,14 +1504,30 @@ impl App {
theme_handler(invoke)
} else if commands::ALERTS.contains(&invoke.message.command()) {
alerts_handler(invoke)
} else if commands::VAULT.contains(&invoke.message.command()) {
vault_handler(invoke)
} else if commands::is_host(invoke.message.command()) {
host_handler(invoke)
} else {
handler(invoke)
}
})
.run(context)
.unwrap_or_else(|error| panic!("Failed to launch {}: {error}", config.title));
.build(context)
.unwrap_or_else(|error| panic!("Failed to launch {}: {error}", config.title))
.run(|_, event| log_run_event(&event));
}
}
/// Why the app is going away, for `--diag` ([`crate::diag`]): an exit request with its code (None is a
/// polite quit from outside: Cmd+Q, the Dock, or another app such as an auto-quitter closing the last
/// window), window close/destroy events and the final exit. Nothing is written without diagnostics.
fn log_run_event(event: &tauri::RunEvent) {
match event {
tauri::RunEvent::ExitRequested { code, .. } => crate::diag::log("host", &format!("exit requested code={code:?}")),
tauri::RunEvent::Exit => crate::diag::log("host", "exit"),
tauri::RunEvent::WindowEvent { label, event: tauri::WindowEvent::CloseRequested { .. }, .. } => crate::diag::log("host", &format!("window {label} close requested")),
tauri::RunEvent::WindowEvent { label, event: tauri::WindowEvent::Destroyed, .. } => crate::diag::log("host", &format!("window {label} destroyed")),
_ => {}
}
}