summaryrefslogtreecommitdiff
path: root/clients
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-21 22:07:58 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-21 22:07:58 +0200
commitad8e1707374ca56bed3dbf472dc8b6bb6cb1f38b (patch)
tree16aa7a868b4a95a8ee12c8e371f6f4e57c37b6a6 /clients
parentf2c8f68763494f64a0a2d2e48d852bd83bd6df65 (diff)
downloadbokf-ad8e1707374ca56bed3dbf472dc8b6bb6cb1f38b.tar.gz
bokf-ad8e1707374ca56bed3dbf472dc8b6bb6cb1f38b.zip
tui: granska/ladda ned underlag via pagern eller skrivbordsvisarenv0.1.61
Diffstat (limited to 'clients')
-rw-r--r--clients/screens_attachments.c2
-rw-r--r--clients/screens_invoices.c4
-rw-r--r--clients/screens_payroll.c2
-rw-r--r--clients/screens_vouchers.c2
-rw-r--r--clients/ui.c98
-rw-r--r--clients/ui.h6
6 files changed, 84 insertions, 30 deletions
diff --git a/clients/screens_attachments.c b/clients/screens_attachments.c
index 3eeb9e9..c72ee67 100644
--- a/clients/screens_attachments.c
+++ b/clients/screens_attachments.c
@@ -158,6 +158,6 @@ void inbox_screen(struct app *a)
continue;
}
if (sel_id)
- attachment_download(a, sel_id);
+ attachment_view_or_download(a, sel_id);
}
}
diff --git a/clients/screens_invoices.c b/clients/screens_invoices.c
index 8fb32eb..d685e83 100644
--- a/clients/screens_invoices.c
+++ b/clients/screens_invoices.c
@@ -476,7 +476,7 @@ static void inv_detail_pdf(struct invctx *ctx)
char fname[800];
snprintf(fname, sizeof fname, "Faktura %lld %s.pdf",
(long long)ctx->number, ctx->customer);
- pdf_save_and_open(b64, fname, "Faktura PDF");
+ file_save_and_open(b64, fname, "Faktura PDF");
free(b64);
}
free(resp);
@@ -967,7 +967,7 @@ static void iform_preview(struct iform *f)
}
char *b64 = jstr_dup(resp, "result.content_base64");
if (b64) {
- pdf_save_and_open(b64, "Faktura förhandsvisning.pdf", "Faktura PDF");
+ file_save_and_open(b64, "Faktura förhandsvisning.pdf", "Faktura PDF");
free(b64);
}
free(resp);
diff --git a/clients/screens_payroll.c b/clients/screens_payroll.c
index 234778c..8a27ec8 100644
--- a/clients/screens_payroll.c
+++ b/clients/screens_payroll.c
@@ -898,7 +898,7 @@ static void payroll_run_payslip(struct payroll_run *r)
char *fname = jstr_dup(resp, "result.filename");
free(resp);
if (b64 && fname)
- pdf_save_and_open(b64, fname, "Lönebesked");
+ file_save_and_open(b64, fname, "Lönebesked");
free(b64);
free(fname);
}
diff --git a/clients/screens_vouchers.c b/clients/screens_vouchers.c
index d884b6e..52d29da 100644
--- a/clients/screens_vouchers.c
+++ b/clients/screens_vouchers.c
@@ -137,7 +137,7 @@ static int vd_key(void *ud, int ch)
int asel = tui_select_list("Underlag", alines, (int)ctx->natts, 0, 0,
&acursor, 0, "ta bort", 0);
if (asel >= 0) {
- attachment_download(a, aids[asel]);
+ attachment_view_or_download(a, aids[asel]);
} else if (asel == -6 && acursor >= 0 &&
(size_t)acursor < ctx->natts) {
char q[320];
diff --git a/clients/ui.c b/clients/ui.c
index e6f6e07..cda0883 100644
--- a/clients/ui.c
+++ b/clients/ui.c
@@ -472,26 +472,9 @@ static void safe_fname(const char *in, char *out, size_t n)
out[o] = '\0';
}
-static int write_pdf_b64(const char *b64, const char *path)
-{
- unsigned char *data = NULL;
- size_t len = 0;
- if (!b64 || util_b64_decode(b64, strlen(b64), &data, &len) != 0)
- return -1;
- FILE *fp = fopen(path, "wb");
- if (!fp) {
- free(data);
- return -1;
- }
- size_t wrote = fwrite(data, 1, len, fp);
- fclose(fp);
- free(data);
- return wrote == len ? 0 : -1;
-}
-
-/* Open a saved PDF with xdg-open when a desktop session is present;
+/* Open a saved file with xdg-open when a desktop session is present;
otherwise (or on fork failure) show where it was saved. */
-static void open_pdf(const char *path, const char *title)
+static void open_saved(const char *path, const char *title)
{
const char *display = getenv("DISPLAY");
const char *wayland = getenv("WAYLAND_DISPLAY");
@@ -515,8 +498,8 @@ static void open_pdf(const char *path, const char *title)
tui_message(title, "Sparad: %s", path);
}
-void pdf_save_and_open(const char *b64, const char *filename,
- const char *title)
+static void save_cache_and_open(const unsigned char *data, size_t n,
+ const char *filename, const char *title)
{
char dir[512], path[700], safe[600];
pdf_cache_dir(dir, sizeof dir);
@@ -526,11 +509,80 @@ void pdf_save_and_open(const char *b64, const char *filename,
return;
}
config_mkdirs(path);
- if (write_pdf_b64(b64, path) != 0) {
+ FILE *fp = fopen(path, "wb");
+ if (!fp || (n > 0 && fwrite(data, 1, n, fp) != n)) {
+ if (fp)
+ fclose(fp);
tui_message(title, "Kunde inte spara %s", path);
return;
}
- open_pdf(path, title);
+ fclose(fp);
+ open_saved(path, title);
+}
+
+void file_save_and_open(const char *b64, const char *filename,
+ const char *title)
+{
+ unsigned char *data = NULL;
+ size_t n = 0;
+ if (!b64 || util_b64_decode(b64, strlen(b64), &data, &n) != 0) {
+ tui_message(title, "Kunde inte avkoda innehållet.");
+ return;
+ }
+ save_cache_and_open(data, n, filename, title);
+ free(data);
+}
+
+/* Show one attachment: text inline in a pager, anything else through the
+ desktop viewer (or a message with the saved path). */
+void attachment_open(struct app *a, int64_t att_id)
+{
+ char args[64];
+ snprintf(args, sizeof args, "{\"id\":%lld}", (long long)att_id);
+ char *resp =
+ client_rpc(&a->conn, "attachment.get", a->session, a->org, args);
+ if (!resp || !client_ok(resp)) {
+ show_error("Kunde inte hämta underlaget", resp);
+ free(resp);
+ return;
+ }
+ char *fn = jstr_dup(resp, "result.filename");
+ char *mime = jstr_dup(resp, "result.mime");
+ char *b64 = jstr_dup(resp, "result.content_base64");
+ unsigned char *data = NULL;
+ size_t n = 0;
+ if (!b64 || util_b64_decode(b64, strlen(b64), &data, &n) != 0) {
+ tui_message("Underlag", "Kunde inte avkoda innehållet.");
+ goto done;
+ }
+ int is_text = (mime && strncmp(mime, "text/", 5) == 0) ||
+ (n > 0 && bytes_look_text(data, n));
+ if (is_text && n <= 256 * 1024) {
+ char *copy = xmalloc(n + 1);
+ memcpy(copy, data, n);
+ copy[n] = '\0';
+ tui_pager("Underlag", copy, NULL);
+ free(copy);
+ } else {
+ save_cache_and_open(data, n, fn && *fn ? fn : "underlag", "Underlag");
+ }
+done:
+ free(data);
+ free(b64);
+ free(mime);
+ free(fn);
+ free(resp);
+}
+
+/* Enter on an attachment row: granska or ladda ned. */
+void attachment_view_or_download(struct app *a, int64_t att_id)
+{
+ static const char *const opts[] = { "Granska", "Ladda ned…" };
+ int c = tui_choice_prompt("Underlag: ", opts, 2, 0);
+ if (c == 0)
+ attachment_open(a, att_id);
+ else if (c == 1)
+ attachment_download(a, att_id);
}
/* Fetch one attachment, save it to a prompted path and verify its hash.
diff --git a/clients/ui.h b/clients/ui.h
index b4ce5f5..393d5ff 100644
--- a/clients/ui.h
+++ b/clients/ui.h
@@ -79,9 +79,11 @@ char *rpc_dry(struct app *a, const char *cmd, const char *args);
char *read_file_b64(const char *path);
char *file_browser(struct app *a, const char *start_dir);
void attachment_download(struct app *a, int64_t att_id);
+void attachment_open(struct app *a, int64_t att_id);
+void attachment_view_or_download(struct app *a, int64_t att_id);
int64_t pick_voucher(struct app *a);
-void pdf_save_and_open(const char *b64, const char *filename,
- const char *title);
+void file_save_and_open(const char *b64, const char *filename,
+ const char *title);
/* generated-document helpers (reports, bokslut) */
void buf_line(struct buf *b, const char *fmt, ...)