Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions public/_partials/layout.jade
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ html(id=id)

include ../_partials/footer

include ../_partials/sw

<!--[if gt IE 8]><!-->
script(src='/js/sticky-pagination-fixer.js')
script(src='/js/raf.js')
Expand Down
76 changes: 76 additions & 0 deletions public/_partials/sw.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
script#service-worker-template(type='text/x-template')
|<button title="Dismiss" onclick="swToggle(false)" class="service-worker-dismiss">
| <svg viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
| <path d="M21 8l-5 5-5-5-3 3 5 5-5 5 3 3 5-5 5 5 3-3-5-5 5-5z"></path>
| </svg>
|</button><img src="/images/sw.png">
|<div class="service-worker-bubble">
| <p id="service-worker-message"></p>
|</div>


div#service-worker.service-worker-wrapper


script.
if ('serviceWorker' in navigator) {
function swExists() {
document.querySelector('#service-worker').innerHTML = document.querySelector('#service-worker-template').innerHTML;
}
function swToggle(status) {
document.querySelector('#service-worker').classList.toggle('service-worker-wrapper--show', status);
}
function swMsg(msg) {
document.querySelector('#service-worker-message').innerHTML = msg;
swToggle(true);
}
swExists();

// Very fist activation
function onFirstLoad() {
var msg = 'Service Worker magic activated!';
console.log(msg);
swMsg(msg);
}

function onNewUpdate() {
var msg = 'New update available. Refresh!';
console.log(msg);
swMsg(msg);
}

function onInstalled() {
console.log('sw installed');
}

function onStateChange(newWorker) {
if (newWorker.state === 'activated') {
if (navigator.serviceWorker.controller) {
onNewUpdate();
}
else {
onFirstLoad();
}
}
else if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
onInstalled();
}
}

function onUpdateFound(registration) {
var newWorker = registration.installing;

registration.installing.addEventListener('statechange',
() => onStateChange(newWorker));
}

navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
// Registration was successful
registration.addEventListener('updatefound', () => onUpdateFound(registration));
})
.catch(function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
}
111 changes: 111 additions & 0 deletions public/css/_sw.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* Service Worker
========================================================================== */
$c-bubble: #000;
$bubble-size: 30px;

.service-worker-wrapper {
background: rgba(0, 0, 0, .75);
bottom: 0;
position: fixed;
padding: 10px 0 0;
transform: translate3d(0, 100%, 0);
transition: transform ease-in-out 0.5s;
width: 100%;

& img {
display: block;
max-width: 320px;
width: 100%
}
}
.service-worker-bubble {
align-items: center;
background: $c-white;
border: 2px solid $c-bubble;
border-radius: 100%;
color: $c-bubble;
display: flex;
font-size: 12px;
height: 120px;
justify-content: center;
line-height: 1.4;
margin: 5px 5px 0 0;
padding: 1em;
position: absolute;
right: 0;
text-align: center;
top: 0;
width: 40%;

@include mq-min-check(360px) {
& {
font-size: inherit;
line-height: inherit;
width: 170px;
}
}
@include mq-min-check(400px) {
& {
left: 200px
}
}
@include mq-min-check(768px) {
& {
height: 150px;
width: 200px;
}
}
}
.service-worker-bubble:before,
.service-worker-bubble:after {
border-color: transparent $c-bubble;
border-style: solid;
border-width: ($bubble-size / 2) $bubble-size ($bubble-size / 2) 0;
content: '';
height: $bubble-size;
left: -26px;
position: absolute;
top: calc(67% - 15px);
transform: rotate(-20deg);
width: $bubble-size;
}
.service-worker-bubble:after {
border-color: transparent $c-white;
left: -22px;
top: calc(67% - 16px);
}
.service-worker-wrapper--show {
transform: translate3d(0, 0, 0);
}
.service-worker-dismiss {
background: $c-blue;
border: 0 none;
color: $c-white;
cursor: pointer;
display: block;
padding: 0;
position: absolute;
left: 0;
top: 0;
width: 32px;
-webkit-appearance: none;

&:hover, &:focus {
background: $c-green;
outline: 0 none;
}

& svg {
display: block;
fill: currentColor;
height: 100%;
width: 100%;
}

@include mq-min-check(400px) {
& {
left: auto;
right: 0;
}
}
}
11 changes: 11 additions & 0 deletions public/css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ ul, ol, li {
display: inline-block;
vertical-align: middle;
width: 100%;

&:after {
background: $c-grey-subtitle;
bottom: 0;
content: '';
left: 0;
position: absolute;
right: 0;
top: 0;
}
}

@supports (object-fit: cover) {
Expand Down Expand Up @@ -442,3 +452,4 @@ ul, ol, li {


@import "mq";
@import "sw";
Empty file modified public/images/sponsors/amex.png
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/sw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 70 additions & 12 deletions public/sw.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,80 @@
/* jshint esnext: true */
var CACHE_NAME = 'ffconf-v1.2.6';

// It's too early to implement offline support or other niceties
// TODO: decide which files
var urlsToCache = [
'/',
'/workshops',
'/css/style.css',
'/js/script.js',
'/images/left-logic.svg'
];

// https://remysharp.com/2016/03/22/the-copy--paste-guide-to-your-first-service-worker
const cacheName = 'v1::static';

self.addEventListener('install', e => {
e.waitUntil(
caches.open(cacheName).then(cache => {
return cache.addAll([
'/',
]).then(() => self.skipWaiting());
})
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
return cache.addAll(urlsToCache);
})
.then(function() {
return self.skipWaiting();
})
);
});

self.addEventListener('fetch', event => {

self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(res => res || fetch(event.request))
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}

// IMPORTANT: Clone the request. A request is a stream and
// can only be consumed once. Since we are consuming this
// once by cache and once by the browser for fetch, we need
// to clone the response
var fetchRequest = event.request.clone();

return fetch(fetchRequest).then(
function(response) {
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}

// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have 2 stream.
var responseToCache = response.clone();

caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});

return response;
}
);
})
);
});


self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys()
.then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== CACHE_NAME) {
return caches.delete(key);
}
}));
})
);
});