mod commands; mod config; mod distro; mod notify; mod patterns; mod tray; mod watcher; use commands::AppState; use config::RobinConfig; use std::sync::{Arc, Mutex}; use tauri::Manager; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let config = RobinConfig::load().unwrap_or_default(); tauri::Builder::default() .plugin(tauri_plugin_log::Builder::default().build()) .plugin(tauri_plugin_notification::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_fs::init()) .manage(AppState { config: Mutex::new(config), }) .setup(|app| { tray::build_tray(&app.handle())?; let state = app.state::(); let cfg = state .config .lock() .unwrap_or_else(|e| e.into_inner()) .clone(); let pattern_file = if let Some(ref migration) = cfg.migration { let family = distro::distro_family(&migration.distro); let source = match migration.source_os { config::SourceOs::Macos => "macos", config::SourceOs::Windows => "windows", config::SourceOs::Linux => "linux", config::SourceOs::Unknown => "unknown", }; patterns::load(source, family).ok() } else { None }; let log_paths = pattern_file .as_ref() .map(|pf| pf.log_paths.clone()) .unwrap_or_default(); let rx = watcher::spawn(log_paths); let pf = Arc::new(pattern_file); let app_handle = app.handle().clone(); tauri::async_runtime::spawn(async move { let mut rx = rx; while let Some(event) = rx.recv().await { if let Some(ref pf) = *pf { if let Some(matched) = patterns::classify(&event, pf) { notify::dispatch(&app_handle, matched); } } } }); Ok(()) }) .invoke_handler(tauri::generate_handler![ commands::get_config, commands::needs_onboarding, commands::complete_onboarding, commands::update_notification_level, commands::get_pending_events, commands::panel_opened, commands::panel_closed, ]) .run(tauri::generate_context!()) .expect("error while running Robin"); }