45 lines
3.1 KiB
JavaScript
45 lines
3.1 KiB
JavaScript
/* PWA (RENCANA 4.7): menangkap `beforeinstallprompt` supaya Pengaturan bisa menawarkan "Pasang aplikasi", hanya bila peramban mengizinkannya.
|
|
Dimuat di index.html dan mobile.html (sinkron di <head>, agar event tidak terlewat). Event dikirim ke dokumen paling atas: di HP dokumen itu mobile.html
|
|
dan game berjalan di iframe, jadi iframe memakai window.parent.KonohaPWA (satu asal; dipanggil langsung supaya ketukan pemain tetap dianggap gestur untuk prompt()).
|
|
window.KonohaPWA = { available(), install() -> 'accepted' | 'dismissed' | 'unavailable', onChange(fn) -> fungsi berhenti }.
|
|
iOS tidak punya event ini (pasang lewat Bagikan > Tambah ke Layar Utama), jadi di sana tombol tidak pernah tampil. */
|
|
(() => {
|
|
'use strict';
|
|
let host = null;
|
|
try { host = window.parent !== window ? window.parent.KonohaPWA || null : null; } catch (_) { host = null; }
|
|
if (!host) {
|
|
let saved = null, installed = false;
|
|
const subs = new Set();
|
|
const standalone = () => { try { return matchMedia('(display-mode: standalone)').matches || matchMedia('(display-mode: fullscreen)').matches || navigator.standalone === true; } catch (_) { return false; } };
|
|
const emit = () => { for (const fn of [...subs]) { try { fn(); } catch (_) { subs.delete(fn); } } };
|
|
host = window.KonohaPWA = {
|
|
available: () => !!saved && !installed && !standalone(),
|
|
onChange(fn) { subs.add(fn); return () => subs.delete(fn); },
|
|
async install() {
|
|
const ev = saved;
|
|
if (!ev) return 'unavailable';
|
|
saved = null; emit(); // satu event hanya bisa dipakai sekali
|
|
try { ev.prompt(); return (await ev.userChoice).outcome; } catch (_) { return 'unavailable'; }
|
|
},
|
|
};
|
|
window.addEventListener('beforeinstallprompt', e => { e.preventDefault(); saved = e; emit(); });
|
|
window.addEventListener('appinstalled', () => { installed = true; saved = null; emit(); });
|
|
}
|
|
|
|
// Baris di Pengaturan (hanya di halaman game, bukan di mobile.html): tampil hanya selama pemasangan tersedia.
|
|
function mountRow() {
|
|
const panel = document.getElementById('settings-panel');
|
|
if (!panel || panel.querySelector('#pwa-row')) return;
|
|
const row = document.createElement('div');
|
|
row.className = 'setting-row'; row.id = 'pwa-row'; row.style.display = 'none';
|
|
row.innerHTML = '<span>Pasang aplikasi<small>Buka dari layar utama, layar penuh tanpa bilah alamat</small></span><button type="button" class="kf-set-btn" id="pwa-install">PASANG</button>';
|
|
(panel.querySelector('.dialog-buttons') || panel.lastElementChild).before(row);
|
|
const sync = () => { let ok = false; try { ok = host.available(); } catch (_) { /* host dari dokumen yang sudah dibongkar */ } row.style.display = ok ? '' : 'none'; };
|
|
row.querySelector('#pwa-install').onclick = () => { host.install(); };
|
|
try { host.onChange(sync); } catch (_) { /* tanpa langganan: status tetap dibaca lagi tiap Pengaturan dibuka */ }
|
|
new MutationObserver(sync).observe(panel, { attributes: true, attributeFilter: ['open'] });
|
|
sync();
|
|
}
|
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', mountRow); else mountRow();
|
|
})();
|