use std::fs; use std::path::PathBuf; use tauri::Manager; /// Subdirectory under the user's Documents folder where pre-migration backups /// are written by default. Keeping the location predictable makes it easy for /// users to find their backup files even if the app is uninstalled. const BACKUP_SUBDIR: &str = "Simpl-Resultat/backups"; fn resolve_backup_dir(app: &tauri::AppHandle) -> Result { let documents = app .path() .document_dir() .map_err(|e| format!("Cannot resolve Documents directory: {}", e))?; Ok(documents.join(BACKUP_SUBDIR)) } /// Resolve `~/Documents/Simpl-Resultat/backups/` and create it if missing. /// Returns the absolute path as a string. Used by the pre-migration backup /// flow to place SREF files in a predictable, user-visible location. #[tauri::command] pub fn ensure_backup_dir(app: tauri::AppHandle) -> Result { let dir = resolve_backup_dir(&app)?; if !dir.exists() { fs::create_dir_all(&dir).map_err(|e| { // Surface permission issues explicitly — the TS layer maps this to // a user-facing i18n key. if e.kind() == std::io::ErrorKind::PermissionDenied { format!("permission_denied: {}", dir.to_string_lossy()) } else { format!("create_dir_failed: {}: {}", dir.to_string_lossy(), e) } })?; } Ok(dir.to_string_lossy().to_string()) } /// Return the size of a file on disk in bytes. Used to report the size of a /// freshly-written backup to the UI. Returns a clear error if the file does /// not exist or cannot be read. #[tauri::command] pub fn get_file_size(file_path: String) -> Result { let metadata = fs::metadata(&file_path).map_err(|e| format!("Cannot stat file {}: {}", file_path, e))?; Ok(metadata.len()) } /// Return true when the given path points to an existing regular file. Used /// by the post-migration restore flow to detect that the recorded backup /// path is still reachable before opening the confirmation modal — when the /// file was moved or deleted, the UI falls back to a manual file picker. /// Never throws on a missing file (just returns `false`); only returns an /// error for unexpected I/O conditions other than "not found". #[tauri::command] pub fn file_exists(file_path: String) -> Result { match fs::metadata(&file_path) { Ok(meta) => Ok(meta.is_file()), Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(false), Err(e) => Err(format!("Cannot stat file {}: {}", file_path, e)), } }