Menu
Public repository / master
AkurAI-Drive / desktop/src-tauri/src/main.rs
Latest change 76b668ab797c5342c1cccf4955c8f1943cba1bb7 - OLI-13: pin toolchain 1.98.1 at repo root; desktop: fmt, clippy, plist/quick-xml advisory fix, first unit tests by AkurAI Agent
//! AkurAI Drive desktop — a KDE-tray, Google-Drive-style file browser that reuses
//! the `akurai-drive-sync` library for auth, the API client, and bidirectional
//! sync. The window lives in the tray (starts hidden; closing hides it), a single
//! background task runs the debounced sync loop, and everything is logged to both
//! stdout and `~/.local/state/akurai-drive/desktop.log` for screenshot-free
//! diagnosis.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod commands;
mod logging;
mod sync;
mod tray;
use std::sync::Arc;
use crate::sync::SyncManager;
use akurai_drive_sync::config::Config;
fn main() {
// Logging first, so even startup + config resolution is captured.
logging::init();
tracing::info!(
version = env!("CARGO_PKG_VERSION"),
log = %logging::log_path().display(),
"AkurAI Drive desktop starting"
);
let manager = Arc::new(SyncManager::new());
let result = tauri::Builder::default()
// single-instance MUST be registered first.
.plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
tracing::info!(?argv, "second instance launched; focusing existing window");
tray::show_window(app);
}))
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_dialog::init())
.manage(manager.clone())
.invoke_handler(tauri::generate_handler![
commands::login,
commands::login_password,
commands::me,
commands::sign_out,
commands::buckets,
commands::set_target,
commands::list,
commands::pick_files,
commands::upload,
commands::download,
commands::delete,
commands::rename,
commands::mkdir,
commands::sync_now,
commands::status,
commands::open_folder,
commands::log_frontend,
])
.on_window_event(|window, event| {
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
if window.label() == "main" {
tracing::info!("close requested → hiding window to tray");
if let Err(e) = window.hide() {
tracing::error!(error = %e, "hide-to-tray failed");
}
api.prevent_close();
}
}
})
.setup(move |app| {
let handle = app.handle().clone();
// Log resolved config at startup (never the token itself).
let cfg = Config::load().unwrap_or_default();
tracing::info!(
api = %cfg.resolved_api(),
folder = cfg.folder.as_deref().unwrap_or("(unset)"),
bucket = cfg.bucket.as_deref().unwrap_or("(unset)"),
logged_in = cfg.is_logged_in(),
"resolved config"
);
tray::build_tray(&handle)?;
sync::spawn_sync_loop(handle.clone(), manager.clone());
Ok(())
})
.run(tauri::generate_context!());
if let Err(e) = result {
tracing::error!(error = %e, "fatal: tauri run failed");
std::process::exit(1);
}
}