mod sidecar; use std::sync::Mutex; use tauri::Manager; /// App log directory, set during setup. static LOG_DIR: std::sync::OnceLock = std::sync::OnceLock::new(); /// Write a log message to the app's log file (for debugging). #[tauri::command] fn write_log(message: String) { if let Some(log_dir) = LOG_DIR.get() { let log_path = log_dir.join("frontend.log"); use std::io::Write; if let Ok(mut f) = std::fs::OpenOptions::new() .create(true) .append(true) .open(&log_path) { let _ = writeln!(f, "[{}] {}", chrono::Local::now().format("%H:%M:%S%.3f"), message); } } eprintln!("[frontend] {}", message); } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_process::init()) .manage(sidecar::ManagedSidecar(std::sync::Arc::new(Mutex::new( sidecar::SidecarManager::new(), )))) .setup(|app| { let resource_dir = app .path() .resource_dir() .expect("failed to resolve resource dir"); let data_dir = app .path() .app_data_dir() .expect("failed to resolve app data dir"); std::fs::create_dir_all(&data_dir).expect("failed to create app data dir"); // Set up logging LOG_DIR.set(data_dir.clone()).ok(); let log_path = data_dir.join("app.log"); if let Ok(mut f) = std::fs::OpenOptions::new() .create(true) .append(true) .open(&log_path) { use std::io::Write; let _ = writeln!(f, "\n=== App started at {} ===", chrono::Local::now()); let _ = writeln!(f, "Resource dir: {}", resource_dir.display()); let _ = writeln!(f, "Data dir: {}", data_dir.display()); } sidecar::init_dirs(resource_dir, data_dir); Ok(()) }) .invoke_handler(tauri::generate_handler![ sidecar::check_sidecar, sidecar::download_sidecar, sidecar::check_sidecar_update, sidecar::get_sidecar_port, sidecar::start_sidecar, sidecar::stop_sidecar, sidecar::reset_sidecar, write_log, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }