Add PDF archive store, raw-body IPC and export file helpers
The searchable PDF can be archived content-addressed under the local data dir with its sha256 and layout fingerprint; a different PDF for an archived invoice is refused and reads verify the hash. Export writes go through a raw-body command that remembers the last folder; reveal-in-folder and open fall back to xdg-open / explorer. Adds a Windows-safe export file name builder. Migration M4 adds the archive columns and last export dir.
This commit is contained in:
@@ -133,22 +133,6 @@ pub fn remove_asset(state: State<AppState>, path: String) -> Result<(), String>
|
||||
remove_asset_file(&state.data_dir, &path)
|
||||
}
|
||||
|
||||
/// Write a base64 payload (e.g. a generated PDF) to a user-chosen path.
|
||||
#[tauri::command]
|
||||
pub fn save_binary_file(path: String, data_base64: String) -> Result<(), String> {
|
||||
if path.trim().is_empty() {
|
||||
return Err("No file path given".into());
|
||||
}
|
||||
let bytes = STANDARD
|
||||
.decode(data_base64.as_bytes())
|
||||
.map_err(|e| e.to_string())?;
|
||||
if let Some(parent) = Path::new(&path).parent() {
|
||||
// A missing parent is created; if that fails the write below reports the real error.
|
||||
std::fs::create_dir_all(parent).ok();
|
||||
}
|
||||
std::fs::write(&path, bytes).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -248,9 +232,4 @@ mod tests {
|
||||
assert!(remove_asset_file(dir.path(), "voiced.db").is_err());
|
||||
assert!(dir.path().join("voiced.db").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn save_binary_file_rejects_empty_path() {
|
||||
assert!(save_binary_file(" ".into(), "AAAA".into()).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user