Skip to content

Commit 10842c3

Browse files
feat: Add PWA install banner to all pages (above footer and below reader links)
1 parent 5f62a9c commit 10842c3

8 files changed

Lines changed: 160 additions & 52 deletions

File tree

‎frontend/js/pwa.js‎

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -121,58 +121,67 @@
121121
// ── Install Banner UI ──────────────────────────────────────────────────────
122122

123123
function _showInstallBanner() {
124-
if (document.getElementById('pwa-install-banner')) return; // already shown
125-
126-
const banner = document.createElement('div');
127-
banner.id = 'pwa-install-banner';
128-
banner.setAttribute('role', 'banner');
129-
banner.setAttribute('aria-label', 'Install BiblioDrift app');
130-
banner.innerHTML = `
131-
<div class="pwa-banner-content">
132-
<img src="../assets/images/biblioDrift_favicon.png"
133-
alt="BiblioDrift icon" class="pwa-banner-icon">
134-
<div class="pwa-banner-text">
135-
<strong>Install BiblioDrift.</strong>
136-
<span>Read offline, anytime.</span>
124+
let banner = document.getElementById('pwa-install-banner');
125+
if (!banner) {
126+
banner = document.createElement('div');
127+
banner.id = 'pwa-install-banner';
128+
banner.setAttribute('role', 'banner');
129+
banner.setAttribute('aria-label', 'Install BiblioDrift app');
130+
banner.innerHTML = `
131+
<div class="pwa-banner-content">
132+
<img src="../assets/images/biblioDrift_favicon.png"
133+
alt="BiblioDrift icon" class="pwa-banner-icon">
134+
<div class="pwa-banner-text">
135+
<strong>Install BiblioDrift.</strong>
136+
<span>Read offline, anytime.</span>
137+
</div>
137138
</div>
138-
</div>
139-
<div class="pwa-banner-actions">
140-
<button class="pwa-install-btn" id="pwa-install-btn"
141-
aria-label="Install BiblioDrift as an app">
142-
Install
143-
</button>
144-
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn"
145-
aria-label="Dismiss install prompt">
146-
<i class="fa-solid fa-xmark"></i>
147-
</button>
148-
</div>
149-
`;
150-
151-
const footer = document.querySelector(".main-footer");
152-
if (footer) {
153-
footer.parentNode.insertBefore(banner, footer);
154-
} else {
155-
const main = document.querySelector("main");
156-
if (main) main.appendChild(banner);
157-
else document.body.appendChild(banner);
139+
<div class="pwa-banner-actions">
140+
<button class="pwa-install-btn" id="pwa-install-btn"
141+
aria-label="Install BiblioDrift as an app">
142+
Install
143+
</button>
144+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn"
145+
aria-label="Dismiss install prompt">
146+
<i class="fa-solid fa-xmark"></i>
147+
</button>
148+
</div>
149+
`;
150+
151+
const footer = document.querySelector(".main-footer");
152+
if (footer) {
153+
footer.parentNode.insertBefore(banner, footer);
154+
} else {
155+
const main = document.querySelector("main");
156+
if (main) main.appendChild(banner);
157+
else document.body.appendChild(banner);
158+
}
158159
}
159160

160161
// Animate in
161162
requestAnimationFrame(() => banner.classList.add('pwa-banner-visible'));
162163

163-
document.getElementById('pwa-install-btn').addEventListener('click', async () => {
164-
if (!_deferredPrompt) return;
165-
_deferredPrompt.prompt();
166-
const { outcome } = await _deferredPrompt.userChoice;
167-
_deferredPrompt = null;
168-
_hideInstallBanner();
169-
console.log(`[PWA] Install prompt outcome: ${outcome}`);
170-
});
164+
const installBtn = document.getElementById('pwa-install-btn');
165+
if (installBtn && !installBtn.dataset.listenerAttached) {
166+
installBtn.dataset.listenerAttached = 'true';
167+
installBtn.addEventListener('click', async () => {
168+
if (!_deferredPrompt) return;
169+
_deferredPrompt.prompt();
170+
const { outcome } = await _deferredPrompt.userChoice;
171+
_deferredPrompt = null;
172+
_hideInstallBanner();
173+
console.log(`[PWA] Install prompt outcome: ${outcome}`);
174+
});
175+
}
171176

172-
document.getElementById('pwa-dismiss-btn').addEventListener('click', () => {
173-
sessionStorage.setItem('pwa-install-dismissed', '1');
174-
_hideInstallBanner();
175-
});
177+
const dismissBtn = document.getElementById('pwa-dismiss-btn');
178+
if (dismissBtn && !dismissBtn.dataset.listenerAttached) {
179+
dismissBtn.dataset.listenerAttached = 'true';
180+
dismissBtn.addEventListener('click', () => {
181+
sessionStorage.setItem('pwa-install-dismissed', '1');
182+
_hideInstallBanner();
183+
});
184+
}
176185
}
177186

178187
function _hideInstallBanner() {

‎frontend/pages/app.html‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,19 @@ <h3>Your Reading Mood Tags</h3>
445445

446446

447447
<!--The footer is being called usingt footer.js.-->
448+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
449+
<div class="pwa-banner-content">
450+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
451+
<div class="pwa-banner-text">
452+
<strong>Install BiblioDrift.</strong>
453+
<span>Read offline, anytime.</span>
454+
</div>
455+
</div>
456+
<div class="pwa-banner-actions">
457+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
458+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
459+
</div>
460+
</div>
448461
<script src="../js/config.js"></script>
449462
<script src="../js/security.js"></script>
450463
<script src="../js/app.js"></script>
@@ -588,3 +601,4 @@ <h4>Elara</h4>
588601
</body>
589602

590603
</html>
604+

‎frontend/pages/auth.html‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,20 @@ <h3 style="color: var(--text-main) !important;">Ambient Sanctuary</h3>
765765
</div>
766766

767767

768-
<script src="../js/config.js"></script>
768+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
769+
<div class="pwa-banner-content">
770+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
771+
<div class="pwa-banner-text">
772+
<strong>Install BiblioDrift.</strong>
773+
<span>Read offline, anytime.</span>
774+
</div>
775+
</div>
776+
<div class="pwa-banner-actions">
777+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
778+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
779+
</div>
780+
</div>
781+
<script src="../js/config.js"></script>
769782
<script src="../js/auth-password-reset.js"></script>
770783
<script src="../js/footer.js"></script>
771784
<script src="../js/app.js"></script>
@@ -1066,4 +1079,4 @@ <h3 style="color: var(--text-main) !important;">Ambient Sanctuary</h3>
10661079
<script src="../js/ambient.js"></script>
10671080
</body>
10681081

1069-
</html>
1082+
</html>

‎frontend/pages/chat.html‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,20 @@ <h3>Ambient Sanctuary</h3>
523523
window.renderAuthNavigation?.(link, tooltip, false);
524524
});
525525
</script>
526-
<script src="../js/config.js"></script>
526+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
527+
<div class="pwa-banner-content">
528+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
529+
<div class="pwa-banner-text">
530+
<strong>Install BiblioDrift.</strong>
531+
<span>Read offline, anytime.</span>
532+
</div>
533+
</div>
534+
<div class="pwa-banner-actions">
535+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
536+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
537+
</div>
538+
</div>
539+
<script src="../js/config.js"></script>
527540
<script src="../js/theme-manager.js"></script>
528541
<script src="../js/ambient.js"></script>
529542
<script src="../js/chat.js"></script>
@@ -534,3 +547,4 @@ <h3>Ambient Sanctuary</h3>
534547
</body>
535548

536549
</html>
550+

‎frontend/pages/community-stories.html‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,23 @@ <h2 id="readTitle"></h2>
576576
onclick="window.scrollTo({top: 0, behavior: 'smooth'});">
577577
<i class="fa-solid fa-arrow-up"></i>
578578
</button>
579-
<script src="../js/pwa.js"></script>
579+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
580+
<div class="pwa-banner-content">
581+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
582+
<div class="pwa-banner-text">
583+
<strong>Install BiblioDrift.</strong>
584+
<span>Read offline, anytime.</span>
585+
</div>
586+
</div>
587+
<div class="pwa-banner-actions">
588+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
589+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
590+
</div>
591+
</div>
592+
<script src="../js/pwa.js"></script>
580593
</body>
581594
</html>
582595

583596

597+
598+

‎frontend/pages/index.html‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,6 +2615,21 @@ <h2>Keep exploring BiblioDrift</h2>
26152615
<a class="footer-pill" href="contributing.html"><i class="fa-solid fa-handshake-angle"></i> Contribute</a>
26162616
</div>
26172617
</div>
2618+
2619+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
2620+
<div class="pwa-banner-content">
2621+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
2622+
<div class="pwa-banner-text">
2623+
<strong>Install BiblioDrift.</strong>
2624+
<span>Read offline, anytime.</span>
2625+
</div>
2626+
</div>
2627+
<div class="pwa-banner-actions">
2628+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
2629+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
2630+
</div>
2631+
</div>
2632+
26182633
<div class="footer-grid">
26192634
<div class="footer-block">
26202635
<a class="landing-brand" href="#top" aria-label="Back to top">

‎frontend/pages/library.html‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,20 @@ <h3>Reader Reviews</h3>
588588

589589
</main>
590590

591-
<script src="../js/config.js"></script>
591+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
592+
<div class="pwa-banner-content">
593+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
594+
<div class="pwa-banner-text">
595+
<strong>Install BiblioDrift.</strong>
596+
<span>Read offline, anytime.</span>
597+
</div>
598+
</div>
599+
<div class="pwa-banner-actions">
600+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
601+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
602+
</div>
603+
</div>
604+
<script src="../js/config.js"></script>
592605
<script src="../js/library-3d.js"></script>
593606
<script src="../js/app.js"></script>
594607
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
@@ -732,4 +745,4 @@ <h4>Elara</h4>
732745

733746
</body>
734747

735-
</html>
748+
</html>

‎frontend/pages/nearby-bookstores.html‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,25 @@ <h1 class="bookstores-heading">
178178
<script src="../js/ambient.js"></script>
179179
<script src="../js/nearby-bookstores.js"></script>
180180

181-
<script src="../js/pwa.js"></script>
181+
<div id="pwa-install-banner" role="banner" aria-label="Install BiblioDrift app" class="pwa-banner-visible">
182+
<div class="pwa-banner-content">
183+
<img src="../assets/images/biblioDrift_favicon.png" alt="BiblioDrift icon" class="pwa-banner-icon">
184+
<div class="pwa-banner-text">
185+
<strong>Install BiblioDrift.</strong>
186+
<span>Read offline, anytime.</span>
187+
</div>
188+
</div>
189+
<div class="pwa-banner-actions">
190+
<button class="pwa-install-btn" id="pwa-install-btn" aria-label="Install BiblioDrift as an app">Install</button>
191+
<button class="pwa-dismiss-btn" id="pwa-dismiss-btn" aria-label="Dismiss install prompt"><i class="fa-solid fa-xmark"></i></button>
192+
</div>
193+
</div>
194+
<script src="../js/pwa.js"></script>
182195
</body>
183196
</html>
184197

185198

186199

187200

201+
202+

0 commit comments

Comments
 (0)