/* Copyright (c) 2025-2026 马建军. All rights reserved. * 专有软件 — 未经授权禁止复制、传播、转售。 * 详见 LICENSE.zh-CN.txt */ (function () { var deferredPrompt = null; var installBtn = document.getElementById('pwa-install-btn'); var iosHint = document.getElementById('pwa-ios-hint'); function isStandalone() { return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone === true; } function isIOS() { return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; } function isTouchDevice() { return window.matchMedia('(hover: none) and (pointer: coarse)').matches || window.matchMedia('(max-width: 1024px)').matches; } function updateThemeColor() { var meta = document.getElementById('meta-theme-color'); if (!meta) return; var theme = document.documentElement.getAttribute('data-theme'); meta.setAttribute('content', theme === 'light' ? '#e8eef8' : '#050508'); } function showInstallBtn() { if (installBtn && !isStandalone()) { installBtn.hidden = false; } } function showIosHint() { if (iosHint && isIOS() && !isStandalone()) { iosHint.classList.add('show'); } } if ('serviceWorker' in navigator) { window.addEventListener('load', function () { navigator.serviceWorker.register('/sw.js', { scope: '/' }).catch(function () { /* ignore */ }); }); } window.addEventListener('beforeinstallprompt', function (e) { e.preventDefault(); deferredPrompt = e; showInstallBtn(); }); if (installBtn) { installBtn.addEventListener('click', function () { if (!deferredPrompt) { if (isIOS()) showIosHint(); return; } deferredPrompt.prompt(); deferredPrompt.userChoice.then(function () { deferredPrompt = null; installBtn.hidden = true; }); }); } window.addEventListener('appinstalled', function () { deferredPrompt = null; if (installBtn) installBtn.hidden = true; if (iosHint) iosHint.classList.remove('show'); }); document.addEventListener('DOMContentLoaded', function () { updateThemeColor(); showIosHint(); if (isStandalone()) { if (installBtn) installBtn.hidden = true; if (iosHint) iosHint.classList.remove('show'); return; } if (isTouchDevice() && installBtn && deferredPrompt) { showInstallBtn(); } }); document.addEventListener('click', function (e) { var pick = e.target.closest('[data-theme-pick]'); if (pick) setTimeout(updateThemeColor, 80); }); })();