#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] mod api; mod app_state; mod commands; mod config; mod poller; mod settings; mod state; mod token; mod tray; use app_state::AppState; use std::sync::Arc; use tauri::Manager; fn main() { tauri::Builder::default() // 单实例插件必须最先注册 .plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| { if let Some(win) = app.get_webview_window("main") { let _ = win.show(); let _ = win.set_focus(); } })) .setup(|app| { let config_dir = app.path().app_config_dir().map_err(|e| e.to_string())?; let settings = settings::SettingsStore::new(config_dir); let cfg = settings.load(); let token = token::TokenStore::new().load().ok().flatten().unwrap_or_else(|| "dev-token".into()); let api = Arc::new(api::ApiClient::new(cfg.base_url.clone(), token)); let handle = poller::spawn(app.handle().clone(), api.clone()); app.manage(settings); app.manage(AppState { passthrough: std::sync::Mutex::new(false), poll_handle: std::sync::Mutex::new(Some(handle)), pending_task: std::sync::Mutex::new(None), api, }); tray::setup_tray(app)?; Ok(()) }) .invoke_handler(tauri::generate_handler![ commands::on_interact, commands::drag_start, commands::drag_end, commands::get_settings, commands::save_settings, commands::open_settings, commands::quit_app, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }