Das Banner merkte sich „geschlossen“ nur in localStorage. Bei gesperrtem Speicher (privates Fenster, gesperrte Website-Daten) baute der Neuaufbau des Rahmens beim Sprachwechsel (main.ts) es wieder auf. - donate-banner.ts: zusätzlich ein Merker im Speicher des Moduls (closedThisSession); er gilt neben localStorage. - Tests: donate-banner.test.ts lädt je Test eine frische Modulkopie (der Merker lebt im Modul); neue Fälle: gesperrter Speicher, erneutes Einhängen nach dem Schließen (bleibt weg) und ohne Schließen (kommt wieder); main.test.ts: Sprachwechsel nach dem Schließen bei gesperrtem Speicher. Die beiden schon vorhandenen Fälle zum gesperrten Speicher sperren jetzt wirklich (vi.stubGlobal): vi.spyOn(Storage.prototype, …) greift in happy-dom nicht, die Fälle waren leer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
// Schließbares Spenden-Banner ganz oben. Ohne Spenden-Link (config.ts) oder nach dem Schließen wird nichts angezeigt.
|
||
import './shell.css';
|
||
import { el } from '../editor/dom';
|
||
import { t } from '../i18n/i18n';
|
||
|
||
const CLOSED_KEY = 'aircard.donateBannerClosed';
|
||
|
||
// Auch im Speicher des Moduls gemerkt: bei gesperrtem localStorage bringt sonst der Neuaufbau des Rahmens (Sprachwechsel) das Banner zurück.
|
||
let closedThisSession = false;
|
||
|
||
function isClosed(): boolean {
|
||
if (closedThisSession) return true;
|
||
try {
|
||
return localStorage.getItem(CLOSED_KEY) !== null;
|
||
} catch {
|
||
return false; // Speicher gesperrt: das Banner bleibt sichtbar, bis es jemand schließt
|
||
}
|
||
}
|
||
|
||
function rememberClosed(): void {
|
||
closedThisSession = true;
|
||
try {
|
||
localStorage.setItem(CLOSED_KEY, '1');
|
||
} catch {
|
||
// gilt dann nur, solange die Seite offen ist
|
||
}
|
||
}
|
||
|
||
export function mountDonateBanner(slot: HTMLElement, url: string): void {
|
||
slot.replaceChildren();
|
||
if (!url.trim() || isClosed()) return;
|
||
|
||
const close = el('button', { type: 'button', class: 'donate-banner-close', 'aria-label': t('Banner schließen') }, '×');
|
||
close.addEventListener('click', () => {
|
||
rememberClosed();
|
||
slot.replaceChildren();
|
||
});
|
||
|
||
slot.append(
|
||
el(
|
||
'div',
|
||
{ class: 'donate-banner' },
|
||
el(
|
||
'p',
|
||
{ class: 'donate-banner-text' },
|
||
el('span', { 'aria-hidden': 'true' }, '☕'),
|
||
` ${t('Gefällt dir AirCard-IOS? Spendier uns einen Kaffee – damit das Projekt weiterläuft.')}`,
|
||
),
|
||
el('a', { class: 'donate-banner-link', href: url, target: '_blank', rel: 'noopener noreferrer' }, `${t('Unterstützen')} →`),
|
||
close,
|
||
),
|
||
);
|
||
}
|