Files
AirCardIOS/web/src/shell/donate-banner.ts
T
ClaudeandClaude Opus 5.5 0bcdfe258d fix(shell): geschlossenes Spenden-Banner kommt beim Sprachwechsel auch ohne localStorage nicht zurück
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>
2026-10-05 05:31:38 +00:00

54 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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,
),
);
}