mod sync; use std::path::PathBuf; use std::sync::Mutex; use tauri::State; use sync::api::MiniCloudApi; use sync::engine::SyncEngine; struct AppState { api: Mutex>, sync_engine: Mutex>, sync_dir: Mutex>, username: Mutex>, } #[tauri::command] async fn login( state: State<'_, AppState>, server_url: String, username: String, password: String, ) -> Result { let mut api = MiniCloudApi::new(&server_url); let result = api.login(&username, &password).await?; *state.api.lock().unwrap() = Some(api); *state.username.lock().unwrap() = Some(username); Ok(serde_json::json!({ "username": result.user.username, "role": result.user.role, })) } #[tauri::command] fn set_sync_dir(state: State<'_, AppState>, path: String) -> Result { let sync_path = PathBuf::from(&path); if !sync_path.exists() { std::fs::create_dir_all(&sync_path).map_err(|e| e.to_string())?; } *state.sync_dir.lock().unwrap() = Some(sync_path); Ok(format!("Sync-Ordner gesetzt: {}", path)) } #[tauri::command] async fn start_sync(state: State<'_, AppState>) -> Result, String> { let api = state.api.lock().unwrap().clone() .ok_or("Nicht eingeloggt")?; let sync_dir = state.sync_dir.lock().unwrap().clone() .ok_or("Kein Sync-Ordner gesetzt")?; let mut engine = SyncEngine::new(sync_dir, api); let log = engine.full_sync().await?; *state.sync_engine.lock().unwrap() = Some(engine); Ok(log) } #[tauri::command] async fn delta_sync(state: State<'_, AppState>) -> Result, String> { // Extract engine from state, dropping the MutexGuard before .await let mut engine = { let mut guard = state.sync_engine.lock().unwrap(); guard.take().ok_or("Sync nicht gestartet")? }; let result = engine.delta_sync().await; // Put engine back *state.sync_engine.lock().unwrap() = Some(engine); result } #[tauri::command] async fn get_status(state: State<'_, AppState>) -> Result { let logged_in = state.api.lock().unwrap().is_some(); let sync_dir = state.sync_dir.lock().unwrap().clone(); let username = state.username.lock().unwrap().clone(); Ok(serde_json::json!({ "logged_in": logged_in, "username": username, "sync_dir": sync_dir.map(|p| p.to_string_lossy().to_string()), })) } #[tauri::command] async fn get_file_tree(state: State<'_, AppState>) -> Result { let api = state.api.lock().unwrap().clone() .ok_or("Nicht eingeloggt")?; let tree = api.get_sync_tree().await?; Ok(serde_json::to_value(tree).map_err(|e| e.to_string())?) } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .manage(AppState { api: Mutex::new(None), sync_engine: Mutex::new(None), sync_dir: Mutex::new(None), username: Mutex::new(None), }) .invoke_handler(tauri::generate_handler![ login, set_sync_dir, start_sync, delta_sync, get_status, get_file_tree, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }