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

Configures to enable offline support #137

Open
wants to merge 8 commits into
base: master
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ tests/Release

/*.js
/*.ulx
/*.z5
/*.z5

!service-worker.js
38 changes: 37 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
<script src="dist/web/jquery.min.js"></script>
<script src="dist/web/ie.js" nomodule></script>
<script src="dist/web/main.js" type="module"></script>
<link rel="stylesheet" href="dist/web/web.css">
<script>navigator.serviceWorker.register("service-worker.js")</script>
<link rel="manifest" href="manifest.json" /> <link rel="stylesheet" href="dist/web/web.css">
</head>
<body>
<div id="gameport">
Expand All @@ -24,6 +25,9 @@ <h1>Parchment</h1>
<p>Or, click here to play a story file on your device</p>
</label>
<input id="file-upload" type="file" style="display: none"/>
<button id="pwainstallbutton" type="button">
Install
</button>
<noscript><p>Parchment requires Javascript. Please enable it in your browser.</p></noscript>
</div>
<div id="windowport"></div>
Expand All @@ -34,4 +38,36 @@ <h1>Parchment</h1>
<div id="errorpane" style="display:none;"><div id="errorcontent">...</div></div>
</div>
</body>

<!-- This allows us to display an on-screen Install button in addition to the automatic browser prompt
Feel free to move this script elsewhere -->
<script>
// Initialize deferredPrompt for use later to show browser install prompt.
let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
// Prevent the mini-infobar from appearing on mobile
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
});

const pwainstallbutton = document.getElementById('pwainstallbutton');

pwainstallbutton.addEventListener('click', async () => {
const promptEvent = deferredPrompt;
if (!promptEvent) {
// The deferred prompt isn't available.
console.log("no event available")
return;
}
// Show the install prompt.
promptEvent.prompt();
// Log the result
const result = await promptEvent.userChoice;

window.deferredPrompt = null;
});
</script>

</html>
54 changes: 54 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "Parchment",
"short_name": "Parchment",
"start_url": "/",
"display": "standalone",
"description": "An interpreter for Interactive Fiction",
"lang": "en-us",
"dir": "auto",
"theme_color": "#000000",
"background_color": "#000000",
"orientation": "portrait-primary",
"icons": [
{
"src": "src/web/icons/manifest-icon-192.maskable.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "src/web/icons/manifest-icon-192.maskable.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "src/web/icons/manifest-icon-512.maskable.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "src/web/icons/manifest-icon-512.maskable.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"screenshots": [
{
"src": "/src/web/icons/parchment-screenshot.png",
"sizes": "1920x984",
"type": "image/png",
"description": "A screenshot of the home page"
}
],
"prefer_related_applications": false,
"shortcuts": [
{
"name": "Parchment",
"url": "/",
"description": "Opens the main application"
}
]
}
93 changes: 93 additions & 0 deletions service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@

// Based off of https://github.com/pwa-builder/PWABuilder/blob/main/docs/sw.js

/*
Welcome to our basic Service Worker! This Service Worker offers a basic offline experience
while also being easily customizeable. You can add in your own code to implement the capabilities
listed below, or change anything else you would like.


Need an introduction to Service Workers? Check our docs here: https://docs.pwabuilder.com/#/home/sw-intro
Want to learn more about how our Service Worker generation works? Check our docs here: https://docs.pwabuilder.com/#/studio/existing-app?id=add-a-service-worker

Did you know that Service Workers offer many more capabilities than just offline?
- Background Sync: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/06
- Periodic Background Sync: https://web.dev/periodic-background-sync/
- Push Notifications: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/07?id=push-notifications-on-the-web
- Badges: https://microsoft.github.io/win-student-devs/#/30DaysOfPWA/advanced-capabilities/07?id=application-badges
*/

const HOSTNAME_WHITELIST = [
self.location.hostname,
'fonts.gstatic.com',
'fonts.googleapis.com',
'cdn.jsdelivr.net'
]

// The Util Function to hack URLs of intercepted requests
const getFixedUrl = (req) => {
var now = Date.now()
var url = new URL(req.url)

// 1. fixed http URL
// Just keep syncing with location.protocol
// fetch(httpURL) belongs to active mixed content.
// And fetch(httpRequest) is not supported yet.
url.protocol = self.location.protocol

// 2. add query for caching-busting.
// Github Pages served with Cache-Control: max-age=600
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
if (url.hostname === self.location.hostname) {
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
}
return url.href
}

/**
* @Lifecycle Activate
* New one activated when old isnt being used.
*
* waitUntil(): activating ====> activated
*/
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim())
})

/**
* @Functional Fetch
* All network requests are being intercepted here.
*
* void respondWith(Promise<Response> r)
*/
self.addEventListener('fetch', event => {
// Skip some of cross-origin requests, like those for Google Analytics.
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
// Stale-while-revalidate
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
const cached = caches.match(event.request)
const fixedUrl = getFixedUrl(event.request)
const fetched = fetch(fixedUrl, { cache: 'no-store' })
const fetchedCopy = fetched.then(resp => resp.clone())

// Call respondWith() with whatever we get first.
// If the fetch fails (e.g disconnected), wait for the cache.
// If there’s nothing in cache, wait for the fetch.
// If neither yields a response, return offline pages.
event.respondWith(
Promise.race([fetched.catch(_ => cached), cached])
.then(resp => resp || fetched)
.catch(_ => { /* eat any errors */ })
)

// Update the cache with the version we fetched (only for ok status)
event.waitUntil(
Promise.all([fetchedCopy, caches.open("pwa-cache")])
.then(([response, cache]) => response.ok && cache.put(event.request, response))
.catch(_ => { /* eat any errors */ })
)
}
})
Binary file added src/web/icons/apple-icon-180.png
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 src/web/icons/manifest-icon-192.maskable.png
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 src/web/icons/manifest-icon-512.maskable.png
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 src/web/icons/parchment-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions src/web/parchment.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,20 @@ body {
bottom: 0;
position: absolute;
width: 100%;
}

/* Hides the install button if loaded as a standalone app
since that would mean that it's already installed*/
@media all and (display-mode: standalone) {
#pwainstallbutton {
display: none;
}
}

/* Firefox Desktop does not support PWA install
So we hide the install button */
@-moz-document url-prefix() {
#pwainstallbutton {
display: none;
}
}