From ce2e0aca4f1ca3479190a40a59b9730f9911edb7 Mon Sep 17 00:00:00 2001 From: Wind-Explorer Date: Fri, 2 Jan 2026 14:56:52 +0800 Subject: [PATCH] server down screen pt 1 --- src-tauri/src/app.rs | 26 +++++++- src-tauri/src/lib.rs | 19 +++--- src-tauri/src/remotes/health.rs | 47 ++++++++++++++ src-tauri/src/remotes/mod.rs | 3 +- src-tauri/src/services/health_manager.rs | 82 ++++++++++++++++++++++++ src-tauri/src/services/mod.rs | 2 +- src/routes/health-manager/+page.svelte | 21 ++++++ 7 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 src-tauri/src/remotes/health.rs create mode 100644 src-tauri/src/services/health_manager.rs create mode 100644 src/routes/health-manager/+page.svelte diff --git a/src-tauri/src/app.rs b/src-tauri/src/app.rs index 6249114..d5debcb 100644 --- a/src-tauri/src/app.rs +++ b/src-tauri/src/app.rs @@ -4,8 +4,10 @@ use tokio::time::{sleep, Instant}; use tracing::info; use crate::{ + remotes::health::HealthRemote, services::{ auth::{get_access_token, get_tokens}, + health_manager::open_health_manager_window, scene::{close_splash_window, open_scene_window, open_splash_window}, welcome::open_welcome_window, ws::init_ws_client, @@ -16,7 +18,7 @@ use crate::{ pub async fn start_fdoll() { init_system_tray(); - bootstrap().await; + init_startup_sequence().await; } async fn init_ws_after_auth() { @@ -65,6 +67,28 @@ pub async fn bootstrap() { None => { info!("No active session found - showing welcome first"); open_welcome_window(); + close_splash_window(); + } + } +} + +/// Perform checks for environment, network condition +/// and handle situations where startup would not be appropriate. +async fn init_startup_sequence() { + let health_remote = HealthRemote::new(); + let server_health = health_remote.get_health().await; + match server_health { + Ok(response) => { + if response.status == "OK" { + bootstrap().await; + } else { + info!("Server health check failed"); + } + } + Err(err) => { + info!("Server health check failed: {}", err); + open_health_manager_window(); + close_splash_window(); } } } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d2f50a0..2581e08 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,14 +1,16 @@ use crate::{ models::app_data::AppData, - remotes::dolls::{CreateDollDto, DollDto, DollsRemote, UpdateDollDto}, - remotes::friends::{ - FriendRemote, FriendRequestResponseDto, FriendshipResponseDto, SendFriendRequestDto, - UserBasicDto, + remotes::{ + dolls::{CreateDollDto, DollDto, DollsRemote, UpdateDollDto}, + friends::{ + FriendRemote, FriendRequestResponseDto, FriendshipResponseDto, SendFriendRequestDto, + UserBasicDto, + }, + user::UserRemote, }, - remotes::user::UserRemote, services::{ - cursor::start_cursor_tracking, - doll_editor::open_doll_editor_window, + cursor::start_cursor_tracking, doll_editor::open_doll_editor_window, + scene::open_splash_window, }, state::{init_app_data, init_app_data_scoped, AppDataRefreshScope, FDOLL}, }; @@ -78,6 +80,8 @@ fn setup_fdoll() -> Result<(), tauri::Error> { .with(console_layer) .init(); + open_splash_window(); + state::init_fdoll_state(Some(_guard)); async_runtime::spawn(async move { app::start_fdoll().await }); Ok(()) @@ -334,7 +338,6 @@ fn quit_app() -> Result<(), String> { fn restart_app() -> Result<(), String> { let app_handle = get_app_handle(); app_handle.restart(); - Ok(()) } #[tauri::command] diff --git a/src-tauri/src/remotes/health.rs b/src-tauri/src/remotes/health.rs new file mode 100644 index 0000000..dd42d47 --- /dev/null +++ b/src-tauri/src/remotes/health.rs @@ -0,0 +1,47 @@ +use reqwest::{Client, Error}; +use serde::{Deserialize, Serialize}; +use ts_rs::TS; + +use crate::{lock_r, state::FDOLL}; + +#[derive(Default, Serialize, Deserialize, Clone, Debug, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export)] +pub struct HealthResponseDto { + pub status: String, + pub version: String, + pub uptime_secs: u64, + pub db: String, +} + +pub struct HealthRemote { + pub base_url: String, + pub client: Client, +} + +impl HealthRemote { + pub fn new() -> Self { + let guard = lock_r!(FDOLL); + Self { + base_url: guard + .app_config + .api_base_url + .as_ref() + .expect("App configuration error") + .clone(), + client: guard + .clients + .as_ref() + .expect("App configuration error") + .http_client + .clone(), + } + } + + pub async fn get_health(&self) -> Result { + let url = format!("{}/health", self.base_url); + let resp = self.client.get(url).send().await?; + let health = resp.json().await?; + Ok(health) + } +} diff --git a/src-tauri/src/remotes/mod.rs b/src-tauri/src/remotes/mod.rs index 43d77aa..59ffb33 100644 --- a/src-tauri/src/remotes/mod.rs +++ b/src-tauri/src/remotes/mod.rs @@ -1,4 +1,5 @@ pub mod dolls; pub mod friends; -pub mod user; +pub mod health; pub mod session; +pub mod user; diff --git a/src-tauri/src/services/health_manager.rs b/src-tauri/src/services/health_manager.rs new file mode 100644 index 0000000..8310856 --- /dev/null +++ b/src-tauri/src/services/health_manager.rs @@ -0,0 +1,82 @@ +use crate::get_app_handle; +use tauri::Manager; +use tauri_plugin_dialog::{DialogExt, MessageDialogBuilder, MessageDialogKind}; +use tauri_plugin_positioner::WindowExt; +use tracing::{error, info}; + +pub static HEALTH_MANAGER_WINDOW_LABEL: &str = "health_manager"; + +pub fn open_health_manager_window() { + let app_handle = get_app_handle(); + let existing_webview_window = app_handle.get_window(HEALTH_MANAGER_WINDOW_LABEL); + + if let Some(window) = existing_webview_window { + if let Err(e) = window.show() { + error!("Failed to show existing health manager window: {}", e); + MessageDialogBuilder::new( + app_handle.dialog().clone(), + "Window Error", + "Failed to show the health manager screen. Please restart and try again.", + ) + .kind(MessageDialogKind::Error) + .show(|_| {}); + } + return; + } + + let webview_window = match tauri::WebviewWindowBuilder::new( + app_handle, + HEALTH_MANAGER_WINDOW_LABEL, + tauri::WebviewUrl::App("/health-manager".into()), + ) + .title("Health Manager") + .inner_size(420.0, 420.0) + .resizable(false) + .decorations(true) + .transparent(false) + .shadow(true) + .visible(false) + .skip_taskbar(false) + .always_on_top(false) + .visible_on_all_workspaces(false) + .build() + { + Ok(window) => { + info!("{} window builder succeeded", HEALTH_MANAGER_WINDOW_LABEL); + window + } + Err(e) => { + error!( + "Failed to build {} window: {}", + HEALTH_MANAGER_WINDOW_LABEL, e + ); + return; + } + }; + + if let Err(e) = webview_window.move_window(tauri_plugin_positioner::Position::Center) { + error!("Failed to move health manager window to center: {}", e); + } + + if let Err(e) = webview_window.show() { + error!("Failed to show health manager window: {}", e); + MessageDialogBuilder::new( + app_handle.dialog().clone(), + "Window Error", + "Failed to show the health manager screen. Please restart and try again.", + ) + .kind(MessageDialogKind::Error) + .show(|_| {}); + } +} + +pub fn close_health_manager_window() { + let app_handle = get_app_handle(); + if let Some(window) = app_handle.get_window(HEALTH_MANAGER_WINDOW_LABEL) { + if let Err(e) = window.close() { + error!("Failed to close health manager window: {}", e); + } else { + info!("Health manager window closed"); + } + } +} diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs index 01c09eb..cd3109e 100644 --- a/src-tauri/src/services/mod.rs +++ b/src-tauri/src/services/mod.rs @@ -2,8 +2,8 @@ pub mod app_menu; pub mod auth; pub mod cursor; pub mod doll_editor; +pub mod health_manager; pub mod scene; pub mod sprite_recolor; pub mod welcome; pub mod ws; - diff --git a/src/routes/health-manager/+page.svelte b/src/routes/health-manager/+page.svelte new file mode 100644 index 0000000..ab6db22 --- /dev/null +++ b/src/routes/health-manager/+page.svelte @@ -0,0 +1,21 @@ + + +
+
+
+

Something is not right...

+

+ Seems like the server is inaccessible. Check your network? +

+
+ +
+