diff --git a/index.html b/index.html
index e55616d71..3726b8c9f 100644
--- a/index.html
+++ b/index.html
@@ -12,9 +12,9 @@
-
+
diff --git a/public/assets/images/favicon/site.webmanifest b/public/assets/images/favicon/site.webmanifest
deleted file mode 100644
index 122a030b8..000000000
--- a/public/assets/images/favicon/site.webmanifest
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "Vite ma dose",
- "short_name": "Vite ma dose",
- "icons": [
- {
- "src": "/assets/images/favicon/android-chrome-192x192.png?v=oLnE8zppbY",
- "sizes": "192x192",
- "type": "image/png"
- },
- {
- "src": "/assets/images/favicon/android-chrome-512x512.png?v=oLnE8zppbY",
- "sizes": "512x512",
- "type": "image/png"
- }
- ],
- "theme_color": "#ffffff",
- "background_color": "#ffffff",
- "display": "standalone"
-}
diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest
new file mode 100644
index 000000000..09486b5f2
--- /dev/null
+++ b/public/manifest.webmanifest
@@ -0,0 +1,29 @@
+{
+ "short_name": "ViteMaDose",
+ "name": "ViteMaDose : Trouver un vaccin facilement et rapidement",
+ "icons": [
+ {
+ "src": "/assets/images/favicon/android-chrome-192x192.png",
+ "type": "image/png",
+ "sizes": "192x192"
+ },
+ {
+ "src": "/assets/images/favicon/android-chrome-512x512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }
+ ],
+ "start_url": "/",
+ "background_color": "#5561d9",
+ "display": "minimal-ui",
+ "theme_color": "#5561d9",
+ "shortcuts": [],
+ "description": "Trouver un vaccin facilement et rapidement",
+ "screenshots": [
+ {
+ "src": "/assets/images/social/vitemadose.png",
+ "type": "image/png",
+ "sizes": "2704x1476"
+ }
+ ]
+}
diff --git a/public/sw.js b/public/sw.js
new file mode 100644
index 000000000..20cffb7a2
--- /dev/null
+++ b/public/sw.js
@@ -0,0 +1,31 @@
+
+function clientRootUrl() {
+ return self.location.href.replace("sw.js","");
+}
+
+function env() {
+ return (self.location.hostname === "vitemadose.covidtracker.fr")?'prod':'dev';
+}
+
+
+self.addEventListener('install', function(event) {
+ console.log('Service Worker activating...');
+ // event.waitUntil(self.skipWaiting()); // Activate worker immediately
+});
+
+self.addEventListener('activate', function(event) {
+ console.log('Service Worker activating...');
+ event.waitUntil(
+ Promise.all([
+ Promise.resolve()
+ ]).then(function() {
+ console.log('SW activation finished !');
+ return self.clients.claim();
+ })
+ );
+});
+
+// Dummy fetch handler to make PWA installable (without this, we won't have the installation CTA on the website)
+self.addEventListener('fetch', function(event) {
+ //console.log("in dummy fetch handler");
+});
diff --git a/src/utils/ServiceWorkers.ts b/src/utils/ServiceWorkers.ts
new file mode 100644
index 000000000..0893b5890
--- /dev/null
+++ b/src/utils/ServiceWorkers.ts
@@ -0,0 +1,50 @@
+import {Router} from "../routing/Router";
+
+export class ServiceWorkers {
+
+ public static readonly INSTANCE = new ServiceWorkers();
+
+ private constructor() {
+ }
+
+ async startup() {
+ // Registering background synchronization
+ if (!navigator.serviceWorker){
+ console.info("Service Worker not supported")
+ return false;
+ }
+
+ // Waiting for 'load' event to start service worker registration
+ // see https://developers.google.com/web/fundamentals/primers/service-workers/registration#improving_the_boilerplate
+ await new Promise((resolve) => window.addEventListener('load', resolve));
+
+ const serviceWorkerRegistration = await navigator.serviceWorker.register(`${Router.basePath}sw.js`);
+
+ navigator.serviceWorker.addEventListener('controllerchange', () => {
+ console.log("controllerchange called !");
+ });
+
+ // Cases :
+ // - navigator.serviceWorker.controller is undefined : this occurs the first time the sw is installed
+ // in that case, we should look for updatefound + statechange=activated events to resolve controller
+ // - navigator.serviceWorker.controller is defined, we should play with is, but don't forget to register a
+ // controller change event in case a new version of the sw is deployed
+
+ await new Promise<{controller: ServiceWorker, updated: boolean}>((resolve) => {
+ if(navigator.serviceWorker.controller) {
+ resolve({controller: navigator.serviceWorker.controller, updated: false});
+ }
+
+ serviceWorkerRegistration.addEventListener('updatefound', () => {
+ const newWorker = serviceWorkerRegistration.installing!;
+ newWorker.addEventListener('statechange', () => {
+ if(newWorker.state === 'activated') {
+ resolve({ controller: navigator.serviceWorker.controller!, updated: true});
+ }
+ })
+ });
+ })
+
+ return true;
+ }
+}
diff --git a/src/vmd-app.component.ts b/src/vmd-app.component.ts
index a174a3f76..1cd097c77 100644
--- a/src/vmd-app.component.ts
+++ b/src/vmd-app.component.ts
@@ -2,6 +2,7 @@ import {LitElement, html, customElement, property, css } from 'lit-element';
import {Router, SlottedTemplateResultFactory} from "./routing/Router";
import smoothscroll from 'smoothscroll-polyfill';
import {CSS_Global} from "./styles/ConstructibleStyleSheets";
+import {ServiceWorkers} from "./utils/ServiceWorkers";
@customElement('vmd-app')
export class VmdAppComponent extends LitElement {
@@ -27,6 +28,8 @@ export class VmdAppComponent extends LitElement {
Router.installRoutes((viewTemplateResult) => {
this.viewTemplateResult = viewTemplateResult;
})
+
+ ServiceWorkers.INSTANCE.startup();
}
render() {