From 89cfa82f2f3e06ef410b7658533f376572d830df Mon Sep 17 00:00:00 2001 From: Jakob Wennberg Date: Wed, 12 Aug 2026 14:59:51 +0200 Subject: [PATCH] feat(inbox): show the hunt working, not just spinning (#1526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pass runs for over two minutes and reports nothing until it lands. The only sign of life was a spinner inside a button and a number that did not move, so the honest reading was that nothing was happening. A band under the header now names the mailboxes actually being read, keeps a running count of omgång and hämtade as passes land, and offers Avbryt without hunting for it in Settings. The bar is deliberately indeterminate. There is no honest percentage inside a pass, and inventing one to look finished is worse than admitting the wait. Reduced motion holds the sweep still and dims it instead of removing it, because the band still has to read as active. The result line waits for the run to end rather than sitting under a live one, so a press replaces itself in place. Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) --- app/globals.css | 20 ++++++++ .../general/InvoiceInboxWorkspace.tsx | 46 +++++++++++++++++-- messages/en.json | 3 ++ messages/sv.json | 3 ++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/app/globals.css b/app/globals.css index d61eb094..5c725377 100644 --- a/app/globals.css +++ b/app/globals.css @@ -704,3 +704,23 @@ input[type="number"] { opacity: 1; } } + +/* Indeterminate sweep for the receipt hunt. + A pass runs for over two minutes and reports nothing until it lands, so + there is no honest percentage to show inside one. This says "still working" + without inventing progress. Reduced motion holds it still and dims it + rather than removing it: the band still has to read as active. */ +@keyframes hunt-sweep { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(400%); } +} +.hunt-sweep { + animation: hunt-sweep 1.6s ease-in-out infinite; +} +@media (prefers-reduced-motion: reduce) { + .hunt-sweep { + animation: none; + width: 100%; + opacity: 0.35; + } +} diff --git a/components/extensions/general/InvoiceInboxWorkspace.tsx b/components/extensions/general/InvoiceInboxWorkspace.tsx index 9c6bba9f..5a03d373 100644 --- a/components/extensions/general/InvoiceInboxWorkspace.tsx +++ b/components/extensions/general/InvoiceInboxWorkspace.tsx @@ -49,6 +49,7 @@ import { } from 'lucide-react' import Link from 'next/link' import { cn, formatCurrency, formatDate, formatDateLong } from '@/lib/utils' +import { QUIET_LINK_CLASS } from '@/components/ui/dry-table' import { GoogleMark, MicrosoftMark } from '@/components/ui/provider-marks' import EditKonteringDialog from '@/components/extensions/general/EditKonteringDialog' import { WhatsAppMark } from '@/components/extensions/general/WhatsAppMark' @@ -1136,9 +1137,7 @@ export default function InvoiceInboxWorkspace(_props: WorkspaceComponentProps) { {hunting ? ( <> - {huntProgress - ? `Letar… ${huntProgress.fetched} hittade` - : 'Letar…'} + {t('hunt_stop')} ) : ( <> @@ -1168,7 +1167,46 @@ export default function InvoiceInboxWorkspace(_props: WorkspaceComponentProps) { - {huntResult && ( + {/* A pass takes over two minutes and reports nothing until it lands, so + a spinner alone leaves somebody watching a button. This says which + mailboxes are being read, what has been found so far, and keeps + moving while the pass is silent. The bar is deliberately + indeterminate: there is no honest percentage inside a pass, and a + fake one is worse than none. */} + {hunting && ( +
+
+
+
+
+ + + + {t('hunt_reading', { + mailboxes: mailConnections + .filter((c) => c.status === 'active') + .map((c) => c.emailAddress) + .join(', '), + })} + + + + {huntProgress && ( + + {t('hunt_progress', { + pass: huntProgress.passes, + found: huntProgress.fetched, + })} + + )} + +
+
+ )} + + {!hunting && huntResult && (
{huntResult.failed ? ( diff --git a/messages/en.json b/messages/en.json index 48cff1b4..fc560ab4 100644 --- a/messages/en.json +++ b/messages/en.json @@ -3049,6 +3049,9 @@ "mixed_currency_note": "Documents in different currencies cannot be summed into a single amount. Each document is still booked separately, against its matched bank transaction and the amount the bank actually settled in SEK." }, "inbox_workspace": { + "hunt_stop": "Stop", + "hunt_reading": "Reading {mailboxes}", + "hunt_progress": "pass {pass} · {found} fetched", "dialog_no_document": "No document", "sources_one": "{count} source", "sources_many": "{count} sources", diff --git a/messages/sv.json b/messages/sv.json index 62c5038a..ae577235 100644 --- a/messages/sv.json +++ b/messages/sv.json @@ -3049,6 +3049,9 @@ "mixed_currency_note": "Underlag i olika valutor kan inte summeras till ett belopp. Varje underlag bokförs ändå var för sig, mot sin matchade banktransaktion och det belopp banken faktiskt drog i SEK." }, "inbox_workspace": { + "hunt_stop": "Avbryt", + "hunt_reading": "Läser {mailboxes}", + "hunt_progress": "omgång {pass} · {found} hämtade", "dialog_no_document": "Ingen handling", "sources_one": "{count} källa", "sources_many": "{count} källor",