#![cfg_attr( all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] use tauri::{AppHandle, Manager, async_runtime as rt}; use once_cell::sync::OnceCell; mod config; mod errors; mod clientinfo; mod ipc; mod state; mod server; mod tray; use crate::errors::*; use state::AppState; pub static APP: OnceCell = OnceCell::new(); fn main() { let initial_state = match rt::block_on(state::AppState::load()) { Ok(state) => state, Err(e) => {eprintln!("{}", e); return;} }; tauri::Builder::default() .manage(initial_state) .system_tray(tray::create()) .on_system_tray_event(tray::handle_event) .invoke_handler(tauri::generate_handler![ ipc::unlock, ipc::respond, ipc::get_session_status, ipc::save_credentials, ipc::get_config, ]) .setup(|app| { APP.set(app.handle()).unwrap(); let state = app.state::(); let config = state.config.read().unwrap(); let addr = std::net::SocketAddrV4::new(config.listen_addr, config.listen_port); tauri::async_runtime::spawn(server::serve(addr, app.handle())); if !config.start_minimized { app.get_window("main") .ok_or(RequestError::NoMainWindow)? .show()?; } Ok(()) }) .build(tauri::generate_context!()) .expect("error while running tauri application") .run(|app, run_event| match run_event { tauri::RunEvent::WindowEvent { label, event, .. } => match event { tauri::WindowEvent::CloseRequested { api, .. } => { let _ = app.get_window(&label).map(|w| w.hide()); api.prevent_close(); } _ => () } _ => () }) } macro_rules! get_state { ($prop:ident as $name:ident) => { use tauri::Manager; let app = crate::APP.get().unwrap(); // as long as the app is running, this is fine let state = app.state::(); let $name = state.$prop.read().unwrap(); // only panics if another thread has already panicked }; (config.$prop:ident as $name:ident) => { use tauri::Manager; let app = crate::APP.get().unwrap(); let state = app.state::(); let config = state.config.read().unwrap(); let $name = config.$prop; }; (mut $prop:ident as $name:ident) => { use tauri::Manager; let app = crate::APP.get().unwrap(); let state = app.state::(); let $name = state.$prop.write().unwrap(); }; (mut config.$prop:ident as $name:ident) => { use tauri::Manager; let app = crate::APP.get().unwrap(); let state = app.state::(); let config = state.config.write().unwrap(); let $name = config.$prop; } } pub(crate) use get_state;