Created
March 26, 2021 22:02
-
-
Save prof3ssorSt3v3/4ae0c69283f4b555bceadcce3e62077e to your computer and use it in GitHub Desktop.
PWA 6 - Handling Install Events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const APP = { | |
deferredInstall: null, | |
init() { | |
if ('serviceWorker' in navigator) { | |
//register our service worker | |
navigator.serviceWorker | |
.register('/sw.js', { | |
updateViaCache: 'none', | |
scope: '/', | |
}) | |
.then(() => { | |
//finished registering | |
}) | |
.catch((err) => { | |
console.warn('Failed to register', err.message); | |
}); | |
//listen for messages | |
navigator.serviceWorker.addEventListener('message', ({ data }) => { | |
//received a message from the service worker | |
console.log(data, 'from service worker'); | |
}); | |
//listen for `appinstalled` event | |
window.addEventListener('appinstalled', (evt) => { | |
//deprecated but still runs in Chrome-based browsers. | |
//Not very useful event. | |
//Better to use the DOMContentLoaded and then look at how it was launched | |
}); | |
//listen for `beforeinstallprompt` event | |
window.addEventListener('beforeinstallprompt', (ev) => { | |
// Prevent the mini-infobar from appearing on mobile | |
ev.preventDefault(); | |
// Stash the event so it can be triggered later. | |
APP.deferredInstall = ev; | |
console.log('saved the install event'); | |
// Update UI notify the user they can install the PWA | |
// if you want here... | |
}); | |
let btn = document.getElementById('btnInstall'); | |
btn?.addEventListener('click', APP.startChromeInstall); | |
} | |
}, | |
startChromeInstall() { | |
if (APP.deferredInstall) { | |
console.log(APP.deferredInstall); | |
APP.deferredInstall.prompt(); | |
APP.deferredInstall.userChoice.then((choice) => { | |
if (choice.outcome == 'accepted') { | |
//they installed | |
console.log('installed'); | |
} else { | |
console.log('cancel'); | |
} | |
}); | |
} | |
}, | |
}; | |
document.addEventListener('DOMContentLoaded', APP.init); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>PWA Install Events</title> | |
<link rel="stylesheet" href="./main.css" /> | |
<!-- pwa manifest --> | |
<link rel="manifest" href="/manifest.json" /> | |
<!-- Older android support --> | |
<meta name="theme-color" content="#bada55" /> | |
<!-- ios support --> | |
<link rel="apple-touch-icon" href="/img/apple-touch-icon.png" /> | |
<meta name="apple-mobile-web-app-status-bar" content="#bada55" /> | |
</head> | |
<body> | |
<header> | |
<h1>PWA Install Events</h1> | |
</header> | |
<main> | |
<p> | |
Access to these events is currently limited to the Chrome|Chromium|Blink | |
based browsers - Chrome, Edge, and Opera. | |
</p> | |
<p> | |
Important to note, on iOS, all browsers are forced to use the Safari | |
Webkit JavaScript Engine. This means that Firefox and Chrome lose some | |
of their capabilities when running on an iOS device. | |
</p> | |
<p> | |
<button id="btnInstall">INSTALL APP</button><br /> | |
Hide this button unless: | |
<dl> | |
<dt>Desktop</dt> | |
<dd>Chrome</dd> | |
<dd>Opera</dd> | |
<dd>Edge</dd> | |
<dt>Mobile</dt> | |
<dd>Chrome</dd> | |
<dd>Opera</dd> | |
<dd>Edge</dd> | |
<dd>Safari</dd> | |
<dd>Firefox</dd> | |
</dl><br/> | |
For Safari and Firefox it will have to display instructions. | |
</p> | |
</main> | |
<script src="app.js" defer></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html { | |
font-size: 20px; | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, | |
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; | |
font-weight: 300; | |
line-height: 1.5; | |
background-color: #222; | |
color: #eee; | |
} | |
body { | |
background-color: inherit; | |
color: inherit; | |
min-height: 100vh; | |
margin: 0; | |
} | |
header { | |
padding: 1rem 2rem; | |
background-color: #333; | |
min-height: 10vw; | |
width: 100vw; | |
margin: 0; | |
} | |
main { | |
background-color: #222; | |
min-height: 85vw; | |
margin: 0; | |
padding: 5vw 2rem; | |
} | |
h1 { | |
color: orangered; | |
font-size: 4rem; | |
line-height: 1; | |
margin: 0.1rem 0; | |
} | |
h2 { | |
color: orange; | |
font-size: 2.4rem; | |
line-height: 2; | |
margin: 3rem 0 1rem; | |
opacity: 0.64; | |
} | |
h3 { | |
color: cornflowerblue; | |
text-shadow: 1px 1px 1px white; | |
font-size: 3.6rem; | |
} | |
span.isOnOff { | |
font-weight: 900; | |
color: cornflowerblue; | |
} | |
p { | |
padding: 0; | |
margin: 1rem 0; | |
font-size: 1.2rem; | |
} | |
img { | |
max-width: 100%; | |
margin: 1rem; | |
} | |
/* PWA specific styles */ | |
body.pwa main { | |
position: relative; | |
padding-left: 8rem; | |
} | |
body.pwa main::before { | |
position: absolute; | |
transform-origin: top left; | |
transform: rotate(90deg) translateY(-4rem); | |
content: 'PWA Rules!'; | |
font-size: 8rem; | |
width: 10ch; | |
line-height: 6rem; | |
font-weight: 900; | |
letter-spacing: 1px; | |
padding: 0 10vw 0 0; | |
margin: 1rem; | |
color: #444; | |
top: 0; | |
left: 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "Sample App", | |
"short_name": "App", | |
"display": "standalone", | |
"start_url": "/index.html", | |
"icons": [ | |
{ | |
"src": "/img/icon-152x152.png", | |
"sizes": "152x152", | |
"type": "image/png" | |
}, | |
{ | |
"src": "/img/icon-192x192.png", | |
"sizes": "192x192", | |
"type": "image/png" | |
}, | |
{ | |
"src": "/img/icon-384x384.png", | |
"sizes": "384x384", | |
"type": "image/png" | |
}, | |
{ | |
"src": "/img/icon-512x512.png", | |
"sizes": "512x512", | |
"type": "image/png" | |
} | |
], | |
"orientation": "portrait-primary", | |
"theme_color": "#bada55", | |
"background_color": "#eeeeee", | |
"prefer_related_applications": false | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const version = 6; | |
const preCacheName = `static-${version}`; | |
const preCache = ['/', '/index.html', '/404.html']; | |
self.addEventListener('install', (ev) => { | |
//installed | |
ev.waitUntil( | |
caches | |
.open(preCacheName) | |
.then((cache) => { | |
console.log('caching the static files'); | |
cache.addAll(preCache); | |
}) | |
.catch(console.warn) | |
); | |
//load pre-cache | |
}); | |
self.addEventListener('activate', (ev) => { | |
//activating | |
ev.waitUntil( | |
caches | |
.keys() | |
.then((keys) => { | |
return Promise.all( | |
keys | |
.filter((key) => key !== preCacheName) | |
.map((key) => caches.delete(key)) | |
); | |
}) | |
.catch(console.warn) | |
); | |
//delete old caches | |
}); | |
self.addEventListener('fetch', (ev) => { | |
//fetch request received | |
//send back a response from cache or fetch | |
ev.respondWith( | |
caches.match(ev.request).then((cacheRes) => { | |
return ( | |
cacheRes || | |
fetch(ev.request).then( | |
(response) => { | |
return response; | |
}, | |
(err) => { | |
//network failure | |
//send something else from the cache? | |
if ( | |
ev.request.url.indexOf('.html') > -1 || | |
ev.request.mode == 'navigation' | |
) { | |
return caches.match('/404.html'); | |
} | |
} | |
) | |
); | |
}) | |
); | |
}); | |
self.addEventListener('message', (ev) => { | |
//message received | |
//do things based on message props | |
let data = ev.data; | |
console.log('SW received', data); | |
}); | |
const sendMessage = async (msg) => { | |
let allClients = await clients.matchAll({ includeUncontrolled: true }); | |
return Promise.all( | |
allClients.map((client) => { | |
let channel = new MessageChannel(); | |
return client.postMessage(msg); | |
}) | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment