fix: hide install button when PWA already installed

- Button hidden by default; async isPwaInstalled() check (standalone mode,
  ponomar-installed flag, getInstalledRelatedApps) unhides only if installable
- Click hint 'already installed' branch uses same multi-signal detection
- manifest id '/' for getInstalledRelatedApps matching on desktop Chrome
This commit is contained in:
catarrh committed 2026-08-22 23:14:25 +03:00
1 parent 8c4f60d635
commit 193038a671
2 files changed
+27 -3

No files matched your search

+26 -3
View File
@@ -253,7 +253,7 @@ export class SettingsView {
<!-- Install PWA --> <!-- Install PWA -->
<div class="mb-6"> <div class="mb-6">
<button id="install-pwa" class="w-full bg-navy text-parchment rounded p-3 font-bold hover:bg-navy-light transition-colors ${!('serviceWorker' in navigator) || window.matchMedia('(display-mode: standalone)').matches ? 'hidden' : ''}"> <button id="install-pwa" class="hidden w-full bg-navy text-parchment rounded p-3 font-bold hover:bg-navy-light transition-colors">
${t.settings.installPwa} ${t.settings.installPwa}
</button> </button>
<p id="install-hint" class="hidden text-sm text-navy-light mt-2"></p> <p id="install-hint" class="hidden text-sm text-navy-light mt-2"></p>
@@ -416,9 +416,8 @@ export class SettingsView {
} }
if (!hintEl) return; if (!hintEl) return;
const ua = navigator.userAgent; const ua = navigator.userAgent;
const isStandalone = window.matchMedia('(display-mode: standalone)').matches || (window.navigator as any).standalone === true;
let hint: string; let hint: string;
if (isStandalone) { if (await this.isPwaInstalled()) {
hint = t.settings.installPwaAlreadyInstalled; hint = t.settings.installPwaAlreadyInstalled;
} else if (/firefox/i.test(ua)) { } else if (/firefox/i.test(ua)) {
hint = t.settings.installPwaHintFirefox; hint = t.settings.installPwaHintFirefox;
@@ -431,6 +430,15 @@ export class SettingsView {
hintEl.classList.remove('hidden'); hintEl.classList.remove('hidden');
}); });
// Show install button only when actually installable
(async () => {
const btn = document.getElementById('install-pwa');
if (!btn || !('serviceWorker' in navigator)) return;
try {
if (!(await this.isPwaInstalled())) btn.classList.remove('hidden');
} catch { /* stay hidden */ }
})();
// Location // Location
const saveLatLng = () => { const saveLatLng = () => {
const lat = parseFloat((document.getElementById('latitude') as HTMLInputElement)?.value); const lat = parseFloat((document.getElementById('latitude') as HTMLInputElement)?.value);
@@ -729,4 +737,19 @@ export class SettingsView {
preview.style.fontSize = `${this.settings.fontSize}px`; preview.style.fontSize = `${this.settings.fontSize}px`;
} }
} }
private async isPwaInstalled(): Promise<boolean> {
if (window.matchMedia('(display-mode: standalone)').matches || (window.navigator as any).standalone === true) {
return true;
}
if (localStorage.getItem('ponomar-installed')) return true;
try {
const navAny = navigator as any;
if (typeof navAny.getInstalledRelatedApps === 'function') {
const apps = await navAny.getInstalledRelatedApps();
if (Array.isArray(apps) && apps.length > 0) return true;
}
} catch { /* not supported */ }
return false;
}
} }
+1
View File
@@ -42,6 +42,7 @@ export default defineConfig({
], ],
}, },
manifest: { manifest: {
id: '/',
name: 'Ponomar — Orthodox Calendar', name: 'Ponomar — Orthodox Calendar',
short_name: 'Ponomar', short_name: 'Ponomar',
description: 'Orthodox Church calendar and liturgical information', description: 'Orthodox Church calendar and liturgical information',