fix: false popup-blocked toast on Visa dokument + scope SKV reconnect line to skattekonto source (#1613)

* fix(documents): stop false popup-blocked toast on Visa dokument

window.open() returns null BY SPEC when 'noopener' is in the features
string, even when the tab opens, so the destructive 'Tillåt popupfönster'
toast fired on every successful open. Open without the features string and
sever the reverse channel manually (tab.opener = null), the same pattern
lib/browser/deferred-tab.ts already uses; the toast now fires only on a
genuine popup block.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(transactions): scope the SKV reconnect line to the skattekonto source

The reconnect attn line rendered on /transactions whenever the SKV
connection needed renewal, regardless of what the user was looking at, so
it read as permanent noise. It now shows only when the source picker is on
Skatteverket (the rows it actually explains); the skattekonto page keeps
its own reconnect line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(transactions): keep Skatteverket source pickable while reconnect is needed

In the reconnect-needed state the transaktioner fetch 401s, skvRows goes
empty, the Skatteverket option left the source picker, and the stale-filter
effect reset the filter to 'all': the source-gated reconnect line became
unreachable exactly when it applied. Show the source whenever rows exist OR
reconnect is needed (skvNeedsReconnect already requires connected=true, so
never-connected companies get no phantom source).

No component test: repo test scope is lib/ + app/api/ (no component tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-14 10:04:36 +02:00
committed by GitHub
co-authored by Claude Fable 5 Jakob Wennberg
parent 9686b54b41
commit 2d97fbf1bc
2 changed files with 18 additions and 4 deletions
+10 -3
View File
@@ -745,7 +745,11 @@ export default function TransactionsPage() {
)
const sourceItems = useMemo<ContextPickerItem[]>(() => {
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() {
<TransactionStatusBar onOpenCreateDialog={() => 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.
<AttnLine action={{ label: t('skv_reconnect_cta'), href: '/settings/tax' }}>
{t('skv_reconnect_body')}
</AttnLine>
@@ -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.',