Files
Webklar-Kundenbereich/public/neu/install-hinweis.js
T
2026-10-16 16:51:44 +00:00

60 lines
2.7 KiB
JavaScript
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.
/* Kundenansicht neu (P2): Hinweis "WEBklar als App" (Logik aus app.js renderInstallOffers). Chrome/Android per Installationsdialog,
iPhone über Teilen und Zum Home-Bildschirm. Kein DOM-Zugriff beim Import. */
import { h } from './dom.js'
const SCHLUESSEL = 'kb-install-dismissed'
/** Zeigen nur auf dem Handy, nicht installiert, mit Installationsdialog oder iOS und nicht ausgeblendet. */
export function installAngebot({ appLayout, standalone, canPrompt, ios, dismissed }) {
const zeigen = Boolean(appLayout) && !standalone && Boolean(canPrompt || ios) && !dismissed
return { zeigen, art: zeigen ? (canPrompt ? 'prompt' : 'ios') : null }
}
export function baueInstallHinweis({ art, onInstall, onDismiss }) {
const text = art === 'prompt'
? 'Mit einem Tipp auf deinem Homescreen – ohne App-Store.'
: 'Tippe auf „Teilen“ und dann auf „Zum Home-Bildschirm“.'
return h('div', { class: 'kn-install', role: 'region', 'aria-label': 'WEBklar als App' },
h('div', { class: 'kn-install-text' }, h('strong', null, 'WEBklar als App'), h('span', null, text)),
art === 'prompt' ? h('button', { type: 'button', class: 'kn-knopf', on: { click: () => onInstall?.() } }, 'Installieren') : null,
h('button', { type: 'button', class: 'kn-textknopf', 'aria-label': 'Hinweis ausblenden', on: { click: () => onDismiss?.() } }, '×'))
}
const quellen = new WeakMap()
/** Je Fenster genau eine Quelle: merkt den Installationsdialog (beforeinstallprompt), räumt bei appinstalled. */
export function starteInstallQuelle(win = window) {
if (quellen.has(win)) return quellen.get(win)
const nav = win.navigator ?? {}
const ios = /iphone|ipad|ipod/i.test(nav.userAgent ?? '') || (nav.platform === 'MacIntel' && nav.maxTouchPoints > 1)
let angebot = null
const hoerer = []
const melde = () => { for (const fn of [...hoerer]) fn() }
const quelle = {
ios,
standalone: () => Boolean(typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)')?.matches) || nav.standalone === true,
kannPrompt: () => angebot !== null,
async installiere() {
const p = angebot
if (!p) return
angebot = null
try { await p.prompt() } catch { /* abgebrochen */ }
melde()
},
beiAenderung(fn) { hoerer.push(fn) },
}
win.addEventListener('beforeinstallprompt', (ev) => { ev.preventDefault?.(); angebot = ev; melde() })
win.addEventListener('appinstalled', () => { angebot = null; melde() })
quellen.set(win, quelle)
return quelle
}
export function istAusgeblendet() {
try { return localStorage.getItem(SCHLUESSEL) === '1' } catch { return false }
}
export function merkeAusgeblendet() {
try { localStorage.setItem(SCHLUESSEL, '1') } catch { /* ohne Speicher wird der Hinweis wieder gezeigt */ }
}