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:
2026-10-04 05:54:26 +05:30
parent f6c81a7e7f
commit 2ade618fb5
17 changed files with 891 additions and 36 deletions
+22 -1
View File
@@ -12,6 +12,9 @@ use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
pub struct AppState {
pub db: Mutex<Connection>,
pub data_dir: PathBuf,
/// Machine-local, non-roaming data (the PDF archive). On Windows this is
/// %LOCALAPPDATA%, unlike `data_dir`, which is the roaming location.
pub local_data_dir: PathBuf,
}
/// Show a native error dialog. Release builds have no console on Windows, so
@@ -40,6 +43,17 @@ fn init_state(app: &tauri::App) -> Result<AppState, Box<dyn std::error::Error>>
show_startup_error(app, &format!("Could not create the application data directory: {e}"), Some(&data_dir));
return Err(e.into());
}
let local_data_dir = match app.path().app_local_data_dir() {
Ok(dir) => dir,
Err(e) => {
show_startup_error(app, &format!("Could not resolve the local data directory: {e}"), Some(&data_dir));
return Err(e.into());
}
};
if let Err(e) = std::fs::create_dir_all(&local_data_dir) {
show_startup_error(app, &format!("Could not create the local data directory: {e}"), Some(&local_data_dir));
return Err(e.into());
}
let conn = match db::open(&data_dir.join("voiced.db"), &data_dir.join("backups")) {
Ok(conn) => conn,
Err(e) => {
@@ -54,6 +68,7 @@ fn init_state(app: &tauri::App) -> Result<AppState, Box<dyn std::error::Error>>
Ok(AppState {
db: Mutex::new(conn),
data_dir,
local_data_dir,
})
}
@@ -113,7 +128,13 @@ pub fn run() {
commands::assets::save_asset_bytes,
commands::assets::read_asset_data_uri,
commands::assets::remove_asset,
commands::assets::save_binary_file,
commands::archive::archive_pdf,
commands::archive::read_archive,
commands::archive::archive_status,
commands::files::write_export_file,
commands::files::get_last_export_dir,
commands::files::reveal_in_folder,
commands::files::open_file,
])
.run(tauri::generate_context!());