v0.2.6-pre.002

This commit is contained in:
2026-08-20 16:51:08 +02:00
parent 927b9e4709
commit 1a57cdeef0
50 changed files with 2960 additions and 9 deletions

View File

@@ -0,0 +1,96 @@
// file: crates/ksp-app-wallet-desk/src/tw_splash.rs
// version: 1
//! Tauri-window lifecycle for the Wallet Desk splash window.
use tauri::Emitter; // rust-rules: trait-import
use tauri::Manager; // rust-rules: trait-import
/// Crate-internal splash window label.
pub(crate) const WINDOW_LABEL_SPLASH: &str = "splash";
const SPLASH_EVENT_NAME: &str = "ksp-splash-order";
/// Resolves the required splash window or returns a typed error.
pub(crate) fn require_splash_window(manager: &impl Manager<tauri::Wry>) -> ksp_core_lib::Result<tauri::WebviewWindow> {
let window = manager.get_webview_window(WINDOW_LABEL_SPLASH);
return match window {
std::option::Option::Some(value) => std::result::Result::Ok(value),
std::option::Option::None => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_WINDOW_MISSING, "Wallet Desk splash window is missing")
.with_context("window_label", WINDOW_LABEL_SPLASH),
),
};
}
/// Starts the one-shot splash lifecycle after the splash frontend reports readiness.
pub(crate) async fn splash_frontend_ready_service(
app: tauri::AppHandle,
invoking_window: tauri::WebviewWindow,
state: &crate::AppState,
) -> ksp_core_lib::Result<()> {
if invoking_window.label() != WINDOW_LABEL_SPLASH {
return std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_SPLASH_ORIGIN_INVALID, "Splash readiness may only originate from the splash window")
.with_context("window_label", invoking_window.label()),
);
}
if !state.begin_splash_sequence() {
ksp_logging_lib::trace!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, window_label = WINDOW_LABEL_SPLASH, "duplicate splash frontend readiness ignored");
return std::result::Result::Ok(());
}
let settings = state.splash_settings();
let lifecycle_started = std::time::Instant::now();
ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, window_label = WINDOW_LABEL_SPLASH, minimum_ms = settings.minimum_ms(), minimum_source = settings.minimum_source(), fade_ms = settings.fade_ms(), fade_source = settings.fade_source(), expected_backend_lifecycle_ms = settings.expected_backend_lifecycle_ms(), "splash frontend readiness accepted; starting splash to main lifecycle");
let fade_in = emit_order(
&invoking_window,
crate::SplashOrderDto::new("fade_in", std::option::Option::Some("Initialisation de KSP Wallet Desk..."), std::option::Option::Some(settings.fade_ms())),
);
if let std::result::Result::Err(error) = fade_in {
return std::result::Result::Err(error);
}
let minimum_wait_started = std::time::Instant::now();
tokio::time::sleep(std::time::Duration::from_millis(settings.minimum_ms())).await;
ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, window_label = WINDOW_LABEL_SPLASH, configured_wait_ms = settings.minimum_ms(), actual_wait_ms = minimum_wait_started.elapsed().as_secs_f64() * 1000.0, lifecycle_elapsed_ms = lifecycle_started.elapsed().as_secs_f64() * 1000.0, "splash minimum wait completed");
let fade_out = emit_order(
&invoking_window,
crate::SplashOrderDto::new("fade_out", std::option::Option::Some("Initialisation terminée."), std::option::Option::Some(settings.fade_ms())),
);
if let std::result::Result::Err(error) = fade_out {
return std::result::Result::Err(error);
}
let fade_wait_started = std::time::Instant::now();
tokio::time::sleep(std::time::Duration::from_millis(u64::from(settings.fade_ms()))).await;
ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, window_label = WINDOW_LABEL_SPLASH, configured_wait_ms = settings.fade_ms(), actual_wait_ms = fade_wait_started.elapsed().as_secs_f64() * 1000.0, lifecycle_elapsed_ms = lifecycle_started.elapsed().as_secs_f64() * 1000.0, "splash fade-out wait completed");
let show_main = crate::show_main_window(&app);
if let std::result::Result::Err(error) = show_main {
return std::result::Result::Err(error);
}
let destroyed = invoking_window.destroy();
if let std::result::Result::Err(error) = destroyed {
return std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_WINDOW_OPERATION_FAILED, "Cannot destroy Wallet Desk splash window")
.with_context("window_label", WINDOW_LABEL_SPLASH)
.with_source(error),
);
}
ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, window_label = WINDOW_LABEL_SPLASH, expected_backend_lifecycle_ms = settings.expected_backend_lifecycle_ms(), actual_backend_lifecycle_ms = lifecycle_started.elapsed().as_secs_f64() * 1000.0, "splash window destroyed after main activation");
return std::result::Result::Ok(());
}
fn emit_order(window: &tauri::WebviewWindow, order: crate::SplashOrderDto) -> ksp_core_lib::Result<()> {
let action = order.action.clone();
let emitted = window.emit(SPLASH_EVENT_NAME, order);
return match emitted {
std::result::Result::Ok(()) => {
ksp_logging_lib::trace!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WINDOWS, window_label = WINDOW_LABEL_SPLASH, action = action.as_str(), "splash order emitted");
std::result::Result::Ok(())
},
std::result::Result::Err(error) => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_WINDOW_OPERATION_FAILED, "Cannot emit Wallet Desk splash order")
.with_context("window_label", WINDOW_LABEL_SPLASH)
.with_context("action", action)
.with_source(error),
),
};
}