179 lines
6.2 KiB
Rust
179 lines
6.2 KiB
Rust
// file: kb-app-demo-desktop/src/splash.rs
|
|
// version: 5
|
|
|
|
//! Splash-window payloads and startup sequencing helpers.
|
|
|
|
use tauri::Emitter; // rust-rules: trait-import
|
|
use tauri::Manager; // rust-rules: trait-import
|
|
use ts_rs::TS; // rust-rules: derive-import
|
|
|
|
/// Minimum splash duration before the main window is shown.
|
|
pub(crate) const SPLASH_MINIMUM_MS: u64 = 12100;
|
|
/// Splash fade duration.
|
|
pub(crate) const SPLASH_FADE_MS: u32 = 12000;
|
|
/// Delay after fade-out before destroying the splash window.
|
|
pub(crate) const SPLASH_CLOSE_WAIT_MS: u64 = 12100;
|
|
|
|
/// Command sent from Rust to the splash frontend.
|
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, TS)]
|
|
#[ts(
|
|
export,
|
|
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/splash/SplashOrder.ts"
|
|
)]
|
|
pub(crate) struct SplashOrder {
|
|
/// Command name.
|
|
pub(crate) order: std::string::String,
|
|
/// Optional message.
|
|
pub(crate) msg: std::option::Option<std::string::String>,
|
|
/// Optional status.
|
|
pub(crate) status: std::option::Option<std::string::String>,
|
|
/// Optional animation duration in milliseconds.
|
|
pub(crate) duration_ms: std::option::Option<u32>,
|
|
}
|
|
|
|
/// Emits one splash command.
|
|
pub(crate) fn emit_splash_order(
|
|
splash_window: &tauri::WebviewWindow,
|
|
order: &str,
|
|
msg: std::option::Option<&str>,
|
|
status: std::option::Option<&str>,
|
|
duration_ms: std::option::Option<u32>,
|
|
) {
|
|
let payload = crate::SplashOrder {
|
|
order: order.to_string(),
|
|
msg: msg.map(std::string::ToString::to_string),
|
|
status: status.map(std::string::ToString::to_string),
|
|
duration_ms,
|
|
};
|
|
let emit_result = splash_window.emit("splash", payload);
|
|
if let std::result::Result::Err(error) = emit_result {
|
|
tracing::error!(target: crate::TRACING_TARGET, "cannot emit splash order '{order}': {error:?}");
|
|
}
|
|
}
|
|
|
|
/// Runs the startup sequence after the splash frontend installed its listener.
|
|
pub(crate) async fn splash_frontend_ready(
|
|
app: tauri::AppHandle,
|
|
window: tauri::WebviewWindow,
|
|
state: &crate::AppState,
|
|
) -> std::result::Result<(), std::string::String> {
|
|
if window.label() != "splash" {
|
|
return std::result::Result::Err(
|
|
"splash readiness may only originate from splash".to_string(),
|
|
);
|
|
}
|
|
if !state.begin_startup_sequence() {
|
|
return std::result::Result::Ok(());
|
|
}
|
|
let main_window = match app.get_webview_window("main") {
|
|
std::option::Option::Some(value) => value,
|
|
std::option::Option::None => {
|
|
return std::result::Result::Err("main window is missing".to_string());
|
|
},
|
|
};
|
|
let started_at = tokio::time::Instant::now();
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"fadein",
|
|
std::option::Option::None,
|
|
std::option::Option::None,
|
|
std::option::Option::Some(crate::SPLASH_FADE_MS),
|
|
);
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"add_msg",
|
|
std::option::Option::Some("Chargement de la configuration terminé."),
|
|
std::option::Option::Some("success"),
|
|
std::option::Option::None,
|
|
);
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"add_log",
|
|
std::option::Option::Some(
|
|
format!("Profil actif : {}", state.active_profile().name).as_str(),
|
|
),
|
|
std::option::Option::None,
|
|
std::option::Option::None,
|
|
);
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"add_msg",
|
|
std::option::Option::Some(
|
|
format!("Logging initialisé : {} routes actives.", state.logging_route_count())
|
|
.as_str(),
|
|
),
|
|
std::option::Option::Some("success"),
|
|
std::option::Option::None,
|
|
);
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"add_msg",
|
|
std::option::Option::Some("Pool HTTP initialisé."),
|
|
std::option::Option::Some("success"),
|
|
std::option::Option::None,
|
|
);
|
|
crate::initialize_postgres_schema_for_startup(state, &window).await;
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"add_msg",
|
|
std::option::Option::Some("Initialisation terminée."),
|
|
std::option::Option::Some("success"),
|
|
std::option::Option::None,
|
|
);
|
|
wait_until_minimum(started_at, crate::SPLASH_MINIMUM_MS).await;
|
|
crate::emit_splash_order(
|
|
&window,
|
|
"fadeout",
|
|
std::option::Option::None,
|
|
std::option::Option::None,
|
|
std::option::Option::Some(crate::SPLASH_FADE_MS),
|
|
);
|
|
tokio::time::sleep(std::time::Duration::from_millis(crate::SPLASH_CLOSE_WAIT_MS)).await;
|
|
if let std::result::Result::Err(error) = main_window.show() {
|
|
return std::result::Result::Err(format!("cannot show main window: {error:?}"));
|
|
}
|
|
if let std::result::Result::Err(error) = main_window.set_focus() {
|
|
return std::result::Result::Err(format!("cannot focus main window: {error:?}"));
|
|
}
|
|
if let std::result::Result::Err(error) = window.destroy() {
|
|
return std::result::Result::Err(format!("cannot destroy splash window: {error:?}"));
|
|
}
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
/// Waits until the configured minimum splash duration has elapsed.
|
|
async fn wait_until_minimum(start: tokio::time::Instant, minimum_ms: u64) {
|
|
let minimum = std::time::Duration::from_millis(minimum_ms);
|
|
let elapsed = start.elapsed();
|
|
if elapsed >= minimum {
|
|
return;
|
|
}
|
|
tokio::time::sleep(minimum - elapsed).await;
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#[test]
|
|
fn splash_order_serializes_duration_ms() {
|
|
let order = crate::SplashOrder {
|
|
order: "fadein".to_string(),
|
|
msg: std::option::Option::None,
|
|
status: std::option::Option::None,
|
|
duration_ms: std::option::Option::Some(500),
|
|
};
|
|
let value_result = serde_json::to_value(order);
|
|
let value = match value_result {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => panic!("cannot serialize splash order: {error}"),
|
|
};
|
|
assert_eq!(value["duration_ms"], serde_json::json!(500));
|
|
}
|
|
|
|
#[test]
|
|
fn splash_timing_is_ordered() {
|
|
assert_eq!(crate::SPLASH_MINIMUM_MS, 12100);
|
|
assert_eq!(crate::SPLASH_FADE_MS, 12000);
|
|
assert!(crate::SPLASH_CLOSE_WAIT_MS >= u64::from(crate::SPLASH_FADE_MS));
|
|
}
|
|
}
|