diff --git a/app/(dashboard)/transactions/page.tsx b/app/(dashboard)/transactions/page.tsx index 0e76da7a..0a3b0f2f 100644 --- a/app/(dashboard)/transactions/page.tsx +++ b/app/(dashboard)/transactions/page.tsx @@ -745,7 +745,11 @@ export default function TransactionsPage() { ) const sourceItems = useMemo(() => { - const showSkvSource = skvRows.length > 0 + // Keep the Skatteverket source pickable while reconnect is needed even + // though the rows fetch fails then (401 -> skvRows []): the reconnect + // attn line only renders under this source, so dropping the option would + // hide the reconnect path exactly when it applies. + const showSkvSource = skvRows.length > 0 || skvNeedsReconnect const items: ContextPickerItem[] = [ { id: 'all', @@ -771,7 +775,7 @@ export default function TransactionsPage() { items.push({ id: 'skatteverket', label: t('source_skatteverket_label') }) } return items - }, [cashAccounts, hasUnassignedBankRows, skvRows.length, t, totalSourceBalance]) + }, [cashAccounts, hasUnassignedBankRows, skvNeedsReconnect, skvRows.length, t, totalSourceBalance]) // A narrowed filter can go stale (account disabled, skv rows drained, // "övriga" bucket emptied): fall back to everything rather than filtering @@ -3161,7 +3165,10 @@ export default function TransactionsPage() { setIsDialogOpen(true)} /> - {skvNeedsReconnect ? ( + {skvNeedsReconnect && sourceFilter === 'skatteverket' ? ( + // Only when the user is actually looking at skattekonto rows: as a + // permanent page-wide line it read as noise (feedback 2026-08-14). + // The skattekonto page keeps its own reconnect line. {t('skv_reconnect_body')} diff --git a/components/bookkeeping/DocumentViewButton.tsx b/components/bookkeeping/DocumentViewButton.tsx index c61f6552..3c3ec14f 100644 --- a/components/bookkeeping/DocumentViewButton.tsx +++ b/components/bookkeeping/DocumentViewButton.tsx @@ -40,7 +40,14 @@ export function DocumentViewButton({ documentId, label = 'Visa dokument', classN return } - if (!window.open(`/api/documents/${documentId}/inline`, '_blank', 'noopener,noreferrer')) { + // window.open() returns null BY SPEC when 'noopener' is in the features + // string, even on success, so passing it here made this toast fire on + // every successful open. Open with a real return value and sever the + // reverse channel manually (same pattern as lib/browser/deferred-tab.ts). + const tab = window.open(`/api/documents/${documentId}/inline`, '_blank') + if (tab) { + tab.opener = null + } else { toast({ title: 'Kunde inte öppna dokumentet', description: 'Tillåt popupfönster för Accounted i webbläsaren och försök igen.',