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 cedf4839bd
commit 7162dac6e7
17 changed files with 891 additions and 36 deletions
+22 -2
View File
@@ -10,6 +10,13 @@ import type {
Settings,
} from "./types";
export interface ArchiveStatus {
archived: boolean;
sha256?: string;
fingerprint?: string;
archivedAt?: string;
}
export const api = {
getSettings: () => invoke<Settings>("get_settings"),
saveSettings: (settings: Settings) => invoke<Settings>("save_settings", { settings }),
@@ -47,6 +54,19 @@ export const api = {
invoke<string>("save_asset_bytes", { kind, fileName, dataBase64 }),
readAssetDataUri: (path: string) => invoke<string>("read_asset_data_uri", { path }),
removeAsset: (path: string) => invoke<void>("remove_asset", { path }),
saveBinaryFile: (path: string, dataBase64: string) =>
invoke<void>("save_binary_file", { path, dataBase64 }),
// Raw-body commands: the payload is the bytes themselves (no base64); metadata goes in headers.
// Header values must be visible ASCII, hence the encodeURIComponent on paths.
archivePdf: (invoiceId: number, bytes: Uint8Array, fingerprint: string) =>
invoke<string>("archive_pdf", bytes, {
headers: { "x-invoice-id": String(invoiceId), "x-fingerprint": fingerprint },
}),
readArchive: async (invoiceId: number): Promise<Uint8Array> =>
new Uint8Array(await invoke<ArrayBuffer>("read_archive", { invoiceId })),
archiveStatus: (invoiceId: number) => invoke<ArchiveStatus>("archive_status", { invoiceId }),
writeExportFile: (path: string, bytes: Uint8Array) =>
invoke<string>("write_export_file", bytes, { headers: { "x-path": encodeURIComponent(path) } }),
getLastExportDir: () => invoke<string>("get_last_export_dir"),
revealInFolder: (path: string) => invoke<void>("reveal_in_folder", { path }),
openFile: (path: string) => invoke<void>("open_file", { path }),
};