Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add offline page using service worker #1583

Open
wants to merge 3 commits into
base: stable
Choose a base branch
from
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
96 changes: 96 additions & 0 deletions assets/offline/offline.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<html>

<head>
<head>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Freefeed</title>
</head>
<style>

body,
.content {
display: flex;
}
h1{
font-weight: 600;
margin-top: 50px;
}
h4 {
font-weight: 600;
line-height: 32px;
margin: 24px auto;
}

.content {
align-items: center;
flex-direction: column;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 20px;
margin: auto;
max-width: 376px;
text-align: center;
}
@media (prefers-color-scheme: dark) {
body {
background: hsl(220deg, 9%, 10%);
}

h1,h4 {
color: hsl(0deg, 0%, 70%);
}
}

</style>
</head>

<body>
<div class="content">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 16 16" width="80" height="80">
<symbol id="snake">
<path d="M 1.5,10 l 6.5,0 a 2,2 0,0,0 2,-2 l 0,-6.5 a 1,1 0 0 1 3,0 l 0,6.5 a 5,5 0 0 1 -5,5 l -6.5,0 a 1,1 0 0 1 0,-3 z"/>
</symbol>
<use xlink:href="#snake" fill="#d43e1b" x="0" y="0"/>
<use xlink:href="#snake" fill="#f9b616" x="-16" y="-16" transform="rotate(180)"/>
<rect fill="#d43e1b" x="2" y="10" width="5" height="3"/>
</svg>
<h1>Connection error</h1>
<h4>Your device may be offline or our servers may be experiencing problems.</h4>
</div>
<script>
const OFFLINE_MESSAGE = 'Connection error';
const BACK_ONLINE_MESSAGE = 'Back online!';
const ERROR_DESCRIPTION = 'Your device may be offline or our servers may be experiencing problems.';

const h1Element = document.getElementsByTagName('h1')[0];
const h4Element = document.getElementsByTagName('h4')[0];

const backOnline = () => {
h1Element.innerHTML = BACK_ONLINE_MESSAGE;
h4Element.innerHTML = '';
};

const reloadPage = () => {
clearInterval(checkOnlineInterval);
location.reload();
};

const checkOnlineStatus = () => {
const online = navigator.onLine;
if (online) {
backOnline();
setTimeout(reloadPage, 1000);
} else {
h1Element.innerHTML = OFFLINE_MESSAGE;
h4Element.innerHTML = ERROR_DESCRIPTION;
}
};

let checkOnlineInterval = setInterval(checkOnlineStatus, 1000);
</script>
</body>

</html>
73 changes: 73 additions & 0 deletions assets/offline/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const CACHE_NAME = 'offline';

// Customize this with a different URL if needed.
const OFFLINE_URL = `${location.origin}/offline.html`;

self.addEventListener('install', (event) => {
event.waitUntil(
(async () => {

const cache = await caches.open(CACHE_NAME);

// Setting {cache: 'reload'} in the new request will ensure that the
// response isn't fulfilled from the HTTP cache; i.e., it will be from
// the network.
await cache.add(new Request(OFFLINE_URL, { cache: 'reload' }));

})(),
);

// Force the waiting service worker to become the active service worker.
self.skipWaiting();
});

self.addEventListener('activate', (event) => {
event.waitUntil(
(async () => {
// Enable navigation preload if it's supported.
// See https://developers.google.com/web/updates/2017/02/navigation-preload
if ('navigationPreload' in self.registration) {
await self.registration.navigationPreload.enable();
}
})(),
);

// Tell the active service worker to take control of the page immediately.
self.clients.claim();
});

self.addEventListener('fetch', (event) => {
// We only want to call event.respondWith() if this is a navigation request
// for an HTML page.
if (event.request.mode === 'navigate') {
event.respondWith(
(async () => {
try {
// First, try to use the navigation preload response if it's supported.
const preloadResponse = await event.preloadResponse;

if (preloadResponse) {
return preloadResponse;
}

// Always try the network first.
const networkResponse = await fetch(event.request);

return networkResponse;
} catch (error) {
// catch is only triggered if an exception is thrown, which is likely
// due to a network error.
// If fetch() returns a valid HTTP response with a response code in
// the 4xx or 5xx range, the catch() will NOT be called.
console.log('Fetch failed; returning offline page instead.', error);

const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(OFFLINE_URL);

return cachedResponse;
}
})(),
);
}

});
12 changes: 12 additions & 0 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ ReactDOM.render(
document.querySelector('#app'),
);

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register(`${location.origin}/service-worker.js`)
// eslint-disable-next-line promise/always-return
.then((reg) => {
console.log('Service worker registered.', reg);
})
.catch((err) => {
console.log(err);
});
}

function checkPath(Component, checker) {
return (props) => {
return checker(props) ? <Component {...props} /> : <NotFound {...props} />;
Expand Down
2 changes: 2 additions & 0 deletions webpack.config.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ const config = {
'assets/images/favicon.*',
'assets/images/ios/*.png',
'assets/ext-auth/auth-return.html',
'assets/offline/offline.html',
'assets/offline/service-worker.js',
opts.dev && { from: 'config.json', noErrorOnMissing: true },
]),
}),
Expand Down