use i_slint_backend_winit::WinitWindowAccessor; use slint::Weak; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; use crate::error::Result; use crate::get_current_unix_timestamp; use crate::handler::ui::SlintHandlerUiOperator; use crate::slint_ui::*; use crate::{err_with_loc, error::app::AppError}; use std::sync::Arc; use tracing::{error, info}; pub fn spawn_ui_task( slint_handler: Arc, ui_weak: Weak, cancellation_token: CancellationToken, shutdown_tx: tokio::sync::mpsc::Sender<()>, ) -> JoinHandle> { tokio::spawn(async move { ui_weak .clone() .upgrade_in_event_loop(move |ui| { // Window dragging ui.on_start_drag_window({ let ui_weak = ui.as_weak(); move || { let _ = ui_weak.upgrade_in_event_loop(|ui| { let _ = ui.window().with_winit_window( |winit_window: &winit::window::Window| { let _ = winit_window.drag_window(); }, ); }); } }); // Window minimize ui.on_minimize_window({ let ui_weak = ui_weak.clone(); move || { let _ = ui_weak.upgrade_in_event_loop(|ui| { let _ = ui.window().with_winit_window( |winit_window: &winit::window::Window| { winit_window.set_minimized(true); }, ); }); } }); // Window maximize/restore ui.on_maximize_window({ let ui_weak = ui_weak.clone(); move || { let _ = ui_weak.upgrade_in_event_loop(|ui| { let _ = ui.window().with_winit_window( |winit_window: &winit::window::Window| { let is_maximized = winit_window.is_maximized(); winit_window.set_maximized(!is_maximized); }, ); }); } }); // Theme toggle ui.on_theme_toggle_clicked({ let ui_weak = ui_weak.clone(); move || { let _ = ui_weak.upgrade_in_event_loop(|ui| { ui.invoke_toggle_theme(); info!("Theme toggled"); }); } }); // Navigation callback ui.on_navigation_changed({ move |page| { info!("Navigation changed to: {}", page); } }); let new_tokens_handler = slint_handler.clone(); ui.on_clear_new_tokens(move || { let handler = new_tokens_handler.clone(); handler.clear_new_tokens(); }); let cex_tokens_handler = slint_handler.clone(); ui.on_clear_cex_tokens(move || { let handler = cex_tokens_handler.clone(); handler.clear_cex_tokens(); }); let analysis_tokens_handler = slint_handler.clone(); ui.on_clear_analysis_tokens(move || { let handler = analysis_tokens_handler.clone(); handler.clear_analysis_tokens(); }); // Other callbacks (placeholder implementations) ui.on_logout_clicked({ move || { info!("Logout clicked"); } }); // Window close - with proper task cleanup ui.on_close_window({ let ui_weak = ui_weak.clone(); let shutdown_tx = shutdown_tx.clone(); let cancellation_token = cancellation_token.clone(); move || { let _ = ui_weak.upgrade_in_event_loop({ let shutdown_tx = shutdown_tx.clone(); let cancellation_token = cancellation_token.clone(); move |ui| { info!("close_window::shutting_down_all_tasks"); // Signal shutdown to all subscriber tasks cancellation_token.cancel(); // Hide window immediately for responsive UI let _ = ui.window().hide(); // Send shutdown signal let _ = shutdown_tx.try_send(()); info!("close_window::all_tasks_cleaned_up"); // Quit the event loop after cleanup let _ = slint::quit_event_loop(); } }); } }); }) .map_err(|e| { error!("failed_to_setup_ui_callbacks: {}", e); err_with_loc!(AppError::Slint(format!( "failed_to_setup_ui_callbacks: {}", e ))) }) }) }