still-loading screen page HTML now on the way to being configurable (ref. #36, #82)

master^2
Michał 'rysiek' Woźniak 2024-03-02 18:17:35 +00:00
rodzic 833ad8b07c
commit 58cb74cb2b
1 zmienionych plików z 161 dodań i 93 usunięć

Wyświetl plik

@ -1309,6 +1309,161 @@ self.addEventListener('activate', async event => {
self.log('service-worker', "activated LibResilient Service Worker (commit: COMMIT_UNKNOWN).");
});
/*
* messages to be used on the still-loading screen and on the error page
*
* TODO: make this configurable via config.json
* TODO: https://gitlab.com/rysiekpl/libresilient/-/issues/82
*/
let still_loading_messages = {
title: "Still loading",
body: "The content is still being loaded, thank you for your patience.<br/><br/>This page will auto-reload in a few seconds. If it does not, please <a href='./'>click here</a>."
}
let success_messages = {
title: "Loaded, redirecting!",
body: "The content has loaded, you are being redirected."
}
let failure_messages = {
title: "Loading failed.",
body: "We're sorry, we were unable to load this page."
}
/**
* this function returns the still-loading screen and error page HTML
*
* @param init_msgs text to initialize the HTML with
* @param success_msgs text to use upon request success; false disables them (false by default)
* @param failure_msgs text to use upon failure; false disables them (false by default)
*/
let getUserFacingHTML = (init_msgs, success_msgs=false, failure_msgs=false) => {
// header and main part of the HTML page
let html =
`<!DOCTYPE html><html><head><title>${init_msgs.title}</title></head><body>
<style>
body {
margin: auto;
width: 30em;
margin: 2em auto;
background: #dddddd;
color: black;
font-family: sans-serif;
}
h1 {
height: 1em;
margin-bottom:
0.2em
}
h1 > span {
animation: throbber 2s infinite 0s linear;
font-size: 70%;
position: relative;
top: 0.2em;
}
#throbber1 {
animation-delay: 0s;
}
#throbber2 {
animation-delay: 0.5s;
}
#throbber3 {
animation-delay: 1s;
}
@keyframes throbber {
0% {opacity: 1.0;}
50% {opacity: 0.1;}
100% {opacity: 1.0;}
}
#working {
color: gray;
font-family: monospace;
font-weight: bold;
display: flex;
flex-wrap: nowrap;
justify-content: left;
margin-top: 0em;
}
a {
color: #2d5589
}
#errors {
font-weight: bold;
font-size: smaller;
marin-top: 1em;
color: maroon;
opacity: 0.5;
font-family: monospace;
}
</style>
<h1 id="header">${init_msgs.title}<span id="throbber1">&#x2022;</span><span id="throbber2">&#x2022;</span><span id="throbber3">&#x2022;</span></h1>
<p id="working">attempts:&nbsp;<span id="status">1</span></p>
<p id="text">${init_msgs.body}</p>
<p id="errors"></p>
<script>
let attempts = 0;
let header = document.getElementById('header')
let text = document.getElementById('text')
let status = document.getElementById('status')
let errors = document.getElementById('errors')
navigator.serviceWorker.addEventListener('message', event => {
if ( event.data.url === window.location.href ) {`
// do we have any success messages?
// if not, ignore the whole success handling bit (including automatic reload!)
//
// try-catch because we really don't want an exception here
try {
if (success_msgs !== false) {
html += `
if ( event.data.state === 'success' ) {
header.innerHTML = "${ success_msgs.title }"
document.title = "${ success_msgs.title }"
text.innerHTML = "${ success_msgs.body }"
window.location.reload()
}`
}
} catch(e) {
self.log('service-worker', `templating the user-facing HTML threw an error: ${e}`)
}
// do we have any failure messages?
// if not, ignore the whole failure handling bit
//
// try-catch because we really don't want an exception here
try {
if (failure_msgs !== false) {
html += `
if ( event.data.state === 'failed' ) {
header.innerHTML = "${ failure_msgs.title }"
document.title = "${ failure_msgs.title }"
text.innerHTML = "${ failure_msgs.body }"
}`
}
} catch(e) {
self.log('service-worker', `templating the user-facing HTML threw an error: ${e}`)
}
// footer
html +=`
if ( 'error' in event.data ) {
attempts += 1;
status.innerHTML = attempts;
errors.innerHTML += '(' + event.data.method + ') ' + event.data.error + '<br/>'
}
}
})
</script></body></html>`
// return what we got out of that
return html
}
self.addEventListener('fetch', async event => {
return void event.respondWith(async function () {
// initialize the SW; this is necessary as SW can be stopped at any time
@ -1434,99 +1589,12 @@ self.addEventListener('fetch', async event => {
//responseInit.headers['X-LibResilient-ETag'] = ???
responseInit.headers['X-LibResilient-Method'] = "still-loading"
// TODO: make this configurable via config.json
// TODO: https://gitlab.com/rysiekpl/libresilient/-/issues/82
let stillLoadingHTML = `<!DOCTYPE html><html><head><title>Still loading...</title></head><body>
<style>
body {
margin: auto;
width: 30em;
margin: 2em auto;
background: #dddddd;
color: black;
font-family: sans-serif;
}
h1 {
height: 1em;
margin-bottom:
0.2em
}
h1 > span {
animation: throbber 2s infinite 0s linear;
font-size: 70%;
position: relative;
top: 0.2em;
}
#throbber1 {
animation-delay: 0s;
}
#throbber2 {
animation-delay: 0.5s;
}
#throbber3 {
animation-delay: 1s;
}
@keyframes throbber {
0% {opacity: 1.0;}
50% {opacity: 0.1;}
100% {opacity: 1.0;}
}
#working {
color: gray;
font-family: monospace;
font-weight: bold;
display: flex;
flex-wrap: nowrap;
justify-content: left;
margin-top: 0em;
}
a {
color: #2d5589
}
#errors {
font-weight: bold;
font-size: smaller;
marin-top: 1em;
color: maroon;
opacity: 0.5;
font-family: monospace;
}
</style>
<h1 id="header">Still loading<span id="throbber1">&#x2022;</span><span id="throbber2">&#x2022;</span><span id="throbber3">&#x2022;</span></h1>
<p id="working">attempts:&nbsp;<span id="status">1</span></p>
<p id="text">The content is still being loaded, thank you for your patience.<br/><br/>This page will auto-reload in a few seconds. If it does not, please <a href="./">click here</a>.</p>
<p id="errors"></p>
<script>
let attempts = 0;
let header = document.getElementById('header')
let text = document.getElementById('text')
let status = document.getElementById('status')
let errors = document.getElementById('errors')
navigator.serviceWorker.addEventListener('message', event => {
if ( event.data.url === window.location.href ) {
if ( event.data.state === 'success' ) {
header.innerHTML = "Loaded, redirecting!"
document.title = "Loaded, redirecting!"
text.innerHTML = "The content has loaded, you are being redirected."
window.location.reload()
} else if ( event.data.state === 'failed' ) {
header.innerHTML = "Loading failed."
document.title = "Loading failed."
text.innerHTML = "We're sorry, we were unable to load this page."
}
if ( 'error' in event.data ) {
attempts += 1;
status.innerHTML = attempts;
errors.innerHTML += '(' + event.data.method + ') ' + event.data.error + '<br/>'
}
}
})
</script></body></html>`
// get the still-loading page contents
let stillLoadingHTML = getUserFacingHTML(
still_loading_messages,
success_messages,
failure_messages
)
let blob = new Blob(
[stillLoadingHTML],