PWA: iOS Installations-Banner + Safe-Area-Fixes

This commit is contained in:
rene 2026-05-22 09:02:54 +02:00
parent 4fee85bd22
commit b12a8e2caa
2 changed files with 63 additions and 1 deletions

View file

@ -7,7 +7,7 @@
<meta name="theme-color" content="#0F172A" /> <meta name="theme-color" content="#0F172A" />
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
%sveltekit.head% %sveltekit.head%

View file

@ -8,10 +8,19 @@
let { children } = $props(); let { children } = $props();
let zeigInstallBanner = $state(false);
onMount(() => { onMount(() => {
if (!$user) { goto('/login'); return; } if (!$user) { goto('/login'); return; }
if (!$user.verein_id) { goto('/onboarding'); return; } if (!$user.verein_id) { goto('/onboarding'); return; }
registerPush(); registerPush();
// iOS Safari: Banner anzeigen wenn App noch nicht installiert
const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent);
const isStandalone = window.matchMedia('(display-mode: standalone)').matches
|| (navigator as any).standalone === true;
const dismissed = sessionStorage.getItem('install-banner-dismissed');
if (isIos && !isStandalone && !dismissed) zeigInstallBanner = true;
}); });
async function registerPush() { async function registerPush() {
@ -88,6 +97,16 @@
</nav> </nav>
</div> </div>
{#if zeigInstallBanner}
<div class="install-banner">
<div class="install-text">
<strong>Zum Homescreen hinzufügen</strong>
<span>Tippe auf <strong>Teilen</strong><strong>Zum Home-Bildschirm</strong> für die Vollbild-App</span>
</div>
<button class="install-close" onclick={() => { zeigInstallBanner = false; sessionStorage.setItem('install-banner-dismissed', '1'); }}>✕</button>
</div>
{/if}
<style> <style>
.shell { .shell {
display: flex; display: flex;
@ -95,6 +114,11 @@
min-height: 100dvh; min-height: 100dvh;
} }
/* iOS PWA: Statusleiste oben nicht überlagern */
@supports (padding-top: env(safe-area-inset-top)) {
header { padding-top: calc(0.75rem + env(safe-area-inset-top)); }
}
header { header {
position: sticky; position: sticky;
top: 0; top: 0;
@ -170,4 +194,42 @@
font-size: 0.65rem; font-size: 0.65rem;
font-weight: 500; font-weight: 500;
} }
/* iOS Installations-Banner */
.install-banner {
position: fixed;
bottom: calc(60px + env(safe-area-inset-bottom) + 0.5rem);
left: 1rem;
right: 1rem;
background: var(--c-dark);
color: #fff;
border-radius: 12px;
padding: 0.85rem 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
z-index: 50;
box-shadow: 0 4px 20px rgba(0,0,0,0.25);
animation: slide-up 0.25s ease;
}
@keyframes slide-up {
from { transform: translateY(1rem); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.install-text {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.2rem;
font-size: 0.82rem;
line-height: 1.4;
}
.install-close {
background: none;
border: none;
color: var(--c-text-hint);
font-size: 1rem;
padding: 0.25rem;
flex-shrink: 0;
}
</style> </style>