From 30d700e026d2a37ebfee0594a4ab3957b9608824 Mon Sep 17 00:00:00 2001 From: lungsangg Date: Tue, 8 Oct 2024 14:56:52 +0530 Subject: [PATCH 01/20] service_worker_update --- static/serviceWorker.js | 87 ++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/static/serviceWorker.js b/static/serviceWorker.js index dbb2fde68a..4db25324c9 100644 --- a/static/serviceWorker.js +++ b/static/serviceWorker.js @@ -1,45 +1,62 @@ importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js'); +// Define your cache name const CACHE = "pwabuilder-page"; -// TODO: replace the following with the correct offline fallback page i.e.: const offlineFallbackPage = "offline.html"; -const offlineFallbackPage = "ToDo-replace-this-name.html"; +// Replace this with the actual offline page +const offlineFallbackPage = "/"; + +// Workbox Precache and Routing +workbox.precaching.precacheAndRoute([ + { url: '/', revision: '1' }, + { url: '/index.html', revision: '1' }, + { url: '/styles.css', revision: '1' }, + { url: '/script.js', revision: '1' }, + { url: '/icon.png', revision: '1' }, + { url: `/${offlineFallbackPage}`, revision: '1' } +]); + +// Fallback for offline page +self.addEventListener('install', async event => { + event.waitUntil( + caches.open(CACHE).then(function (cache) { + return cache.addAll([ + offlineFallbackPage, + '/index.html', + '/styles.css', + '/script.js', + '/icon.png' + ]); + }) + ); + self.skipWaiting(); +}); -self.addEventListener("message", (event) => { - if (event.data && event.data.type === "SKIP_WAITING") { - self.skipWaiting(); - } +// Fetch event to serve from cache or fallback to network +self.addEventListener('fetch', event => { + event.respondWith( + caches.match(event.request).then(cachedResponse => { + return cachedResponse || fetch(event.request).catch(() => { + // If both fail, show the offline fallback page + return caches.match(offlineFallbackPage); + }); + }) + ); }); -self.addEventListener('install', async (event) => { +// Activate the new service worker and clean up old caches +self.addEventListener('activate', event => { + const cacheWhitelist = [CACHE]; event.waitUntil( - caches.open(CACHE) - .then((cache) => cache.add(offlineFallbackPage)) + caches.keys().then(keyList => + Promise.all( + keyList.map(key => { + if (!cacheWhitelist.includes(key)) { + return caches.delete(key); + } + }) + ) + ) ); + self.clients.claim(); }); - -if (workbox.navigationPreload.isSupported()) { - workbox.navigationPreload.enable(); -} - -self.addEventListener('fetch', (event) => { - if (event.request.mode === 'navigate') { - event.respondWith((async () => { - try { - const preloadResp = await event.preloadResponse; - - if (preloadResp) { - return preloadResp; - } - - const networkResp = await fetch(event.request); - return networkResp; - } catch (error) { - - const cache = await caches.open(CACHE); - const cachedResp = await cache.match(offlineFallbackPage); - return cachedResp; - } - })()); - } -}); \ No newline at end of file From b586dc5cb76b7c7e617002a2d3d953ac9e421417 Mon Sep 17 00:00:00 2001 From: lungsangg Date: Tue, 8 Oct 2024 15:49:06 +0530 Subject: [PATCH 02/20] service_worker_path_update_to_root --- static/serviceWorker.js => serviceWorker.js | 0 templates/base.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename static/serviceWorker.js => serviceWorker.js (100%) diff --git a/static/serviceWorker.js b/serviceWorker.js similarity index 100% rename from static/serviceWorker.js rename to serviceWorker.js diff --git a/templates/base.html b/templates/base.html index 001b1acc5e..907404f87d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -226,7 +226,7 @@ - + From d100f84b4590b15dcac7a59d2617d9c2d6f5cd27 Mon Sep 17 00:00:00 2001 From: lungsangg Date: Wed, 9 Oct 2024 11:37:58 +0530 Subject: [PATCH 07/20] service_worker_scope_update --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index 1b7a903c05..9f5f359170 100644 --- a/templates/base.html +++ b/templates/base.html @@ -373,7 +373,7 @@ --> - + + --> - - - + - + \ No newline at end of file From e95d6273bf88feefbe4158dd1df30fcda1be0969 Mon Sep 17 00:00:00 2001 From: lungsangg Date: Wed, 9 Oct 2024 12:32:25 +0530 Subject: [PATCH 11/20] manifest_update --- static/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/manifest.json b/static/manifest.json index a82ff893f3..cd3a1f59f3 100644 --- a/static/manifest.json +++ b/static/manifest.json @@ -1,7 +1,7 @@ { "name": "Pecha.org", "short_name": "Pecha.org", - "start_url": "base.html", + "start_url": "/", "display": "standalone", "background_color": "#fdfdfd", "theme_color": "#db4938", From ecc832bae6b646115bc211bddf6f8aa0248894f9 Mon Sep 17 00:00:00 2001 From: lungsangg Date: Wed, 9 Oct 2024 15:37:38 +0530 Subject: [PATCH 12/20] pwa_installer_button_added --- static/js/Footer.jsx | 13 +++++++++++++ static/pwa.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ templates/base.html | 2 ++ 3 files changed, 59 insertions(+) create mode 100644 static/pwa.js diff --git a/static/js/Footer.jsx b/static/js/Footer.jsx index 539a2d17f1..0a4004ca96 100644 --- a/static/js/Footer.jsx +++ b/static/js/Footer.jsx @@ -29,12 +29,25 @@ class Footer extends Component { trackLanguageClick(language){ Sefaria.track.setInterfaceLanguage('interface language footer', language); } + + componentDidMount() { + // Dynamically load pwa.js script + const script = document.createElement("script"); + script.src = "/static/js/pwa.js"; + script.async = true; + document.body.appendChild(script); + } + render() { if (!Sefaria._siteSettings.TORAH_SPECIFIC) { return null; } return (
Version: 1.3.0 + {/* Install PWA Button */} +
); } diff --git a/static/pwa.js b/static/pwa.js new file mode 100644 index 0000000000..9d1e0e4bec --- /dev/null +++ b/static/pwa.js @@ -0,0 +1,44 @@ +let deferredPrompt; + +// Listen for the 'beforeinstallprompt' event and save it +window.addEventListener('beforeinstallprompt', (e) => { + // Prevent the mini-infobar from appearing on mobile + e.preventDefault(); + + // Store the event so it can be triggered later + deferredPrompt = e; + + // Enable the install button once the prompt event is available + const installButton = document.getElementById('install-pwa-button'); + if (installButton) { + installButton.style.display = 'inline-block'; + + // Add a click event listener to the install button + installButton.addEventListener('click', () => { + // Hide the button after it’s clicked + installButton.style.display = 'none'; + + // Show the installation prompt + deferredPrompt.prompt(); + + // Wait for the user's decision + deferredPrompt.userChoice.then((choiceResult) => { + if (choiceResult.outcome === 'accepted') { + console.log('User accepted the install prompt'); + } else { + console.log('User dismissed the install prompt'); + } + deferredPrompt = null; // Clear the deferred prompt + }); + }); + } +}); + +// Optional: Check if the app is already installed and hide the button +window.addEventListener('appinstalled', () => { + console.log('PWA has been installed'); + const installButton = document.getElementById('install-pwa-button'); + if (installButton) { + installButton.style.display = 'none'; + } +}); diff --git a/templates/base.html b/templates/base.html index a2613ee62a..6303af0d41 100644 --- a/templates/base.html +++ b/templates/base.html @@ -236,6 +236,8 @@ } + +