minmal-file-cloud-email-pim.../clients/desktop/src-tauri/src/lib.rs

115 lines
3.4 KiB
Rust

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<Option<MiniCloudApi>>,
sync_engine: Mutex<Option<SyncEngine>>,
sync_dir: Mutex<Option<PathBuf>>,
username: Mutex<Option<String>>,
}
#[tauri::command]
async fn login(
state: State<'_, AppState>,
server_url: String,
username: String,
password: String,
) -> Result<serde_json::Value, String> {
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<String, String> {
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<Vec<String>, 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<Vec<String>, 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<serde_json::Value, String> {
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<serde_json::Value, String> {
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");
}