feat: 📲 Install-Button in Topbar — umgeht Chrome Engagement-Heuristik
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s

Chrome zeigt 'App installieren' im Menü erst nach mehrmaligem Besuch
mit User-Interaktion. Das ist die sog. Site-Engagement-Heuristik —
keine technische Voraussetzung, sondern UX-Gate.

Workaround: beforeinstallprompt-Event abfangen und manuell auslösen.

- 📲 Install-Button in Topbar (standardmäßig versteckt)
- Bei beforeinstallprompt: Event speichern, Button anzeigen
- Klick → prompt() aufrufen → Install-Dialog öffnet sich
- appinstalled-Event: Button wieder verstecken
- iOS-Fallback: Hinweis zum manuellen 'Zum Home-Bildschirm'

Damit ist die Install-Funktion jederzeit sichtbar und nutzbar,
unabhängig davon wie oft der User die Seite vorher besucht hat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
This commit is contained in:
Eduard Wisch 2026-04-09 01:31:16 +02:00
parent 7c9563ec90
commit d19e4eb41e

View file

@ -42,6 +42,7 @@ header('Expires: 0');
<header id="topbar"> <header id="topbar">
<button id="back-btn" class="icon-btn" style="display:none"></button> <button id="back-btn" class="icon-btn" style="display:none"></button>
<h1 id="page-title">Baustelle</h1> <h1 id="page-title">Baustelle</h1>
<button id="install-btn" class="icon-btn" title="Als App installieren" style="display:none">📲</button>
<button id="help-btn" class="icon-btn" title="Hilfe"></button> <button id="help-btn" class="icon-btn" title="Hilfe"></button>
<span id="status-badge">🟢</span> <span id="status-badge">🟢</span>
</header> </header>
@ -63,6 +64,36 @@ header('Expires: 0');
<script src="lib/router.js?v=<?php echo $jsVersion; ?>"></script> <script src="lib/router.js?v=<?php echo $jsVersion; ?>"></script>
<script src="app.js?v=<?php echo $jsVersion; ?>"></script> <script src="app.js?v=<?php echo $jsVersion; ?>"></script>
<script> <script>
/* PWA Install Prompt abfangen */
let deferredInstallPrompt = null;
window.addEventListener('beforeinstallprompt', function (e) {
e.preventDefault();
deferredInstallPrompt = e;
var btn = document.getElementById('install-btn');
if (btn) btn.style.display = '';
console.log('PWA: Install-Prompt ist verfügbar');
});
document.addEventListener('DOMContentLoaded', function () {
var btn = document.getElementById('install-btn');
if (btn) btn.addEventListener('click', async function () {
if (!deferredInstallPrompt) {
alert('Installation nicht verfügbar. Falls du die App bereits installiert hast, öffne sie über das Home-Screen-Icon.\n\nAuf iPhone: Safari → Teilen → "Zum Home-Bildschirm".');
return;
}
deferredInstallPrompt.prompt();
var choice = await deferredInstallPrompt.userChoice;
if (choice.outcome === 'accepted') {
btn.style.display = 'none';
}
deferredInstallPrompt = null;
});
});
window.addEventListener('appinstalled', function () {
var btn = document.getElementById('install-btn');
if (btn) btn.style.display = 'none';
console.log('PWA: Installation abgeschlossen');
});
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
window.addEventListener('load', function () { window.addEventListener('load', function () {
navigator.serviceWorker.register('sw.js?v=<?php echo $swVersion; ?>').then(function (reg) { navigator.serviceWorker.register('sw.js?v=<?php echo $swVersion; ?>').then(function (reg) {