mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-06 02:30:47 -08:00
feat: add service-worker plugin
This commit is contained in:
parent
353bfc25e8
commit
6c37677c2a
6 changed files with 231 additions and 1 deletions
|
|
@ -0,0 +1,165 @@
|
|||
<link rel="manifest" href="manifest.webmanifest" />
|
||||
|
||||
<script type="text/javascript">
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
|
||||
);
|
||||
|
||||
function register(config) {
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = 'service-worker.js';
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's do additional checks to see if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
console.log('Register service worker');
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
console.log('Service worker is speeding up this wiki.')
|
||||
registration.onupdatefound = () => {
|
||||
console.log('New content is found, prepare to fetch', registration);
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but normally the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
// but we have set self.skipWaiting() in the service worker, so just inform user to reload the page to take effect.
|
||||
console.log('New content is available and will be used when after refresh or refetch');
|
||||
|
||||
// Execute callback, prepare an info to inform user refresh here.
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
})
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('No internet connection found. App is running in offline mode.');
|
||||
});
|
||||
}
|
||||
|
||||
function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function informUserToReloadToGetLatestContent() {
|
||||
const body = document.querySelector('body');
|
||||
const infoElement = document.createElement('div');
|
||||
infoElement.className = 'ask-user-reload';
|
||||
infoElement.innerHTML =
|
||||
navigator.language === 'zh-CN'
|
||||
? '新内容已准备好,点击此处刷新页面更新到新版。'
|
||||
: 'New content available. Click here to Refresh this page to get update.';
|
||||
infoElement.onclick = () => location.reload();
|
||||
infoElement.onKeyDown = () => location.reload();
|
||||
infoElement.tabindex = 1;
|
||||
infoElement.role = 'button';
|
||||
|
||||
const closeElement = document.createElement('div');
|
||||
closeElement.className = 'ask-user-reload-close';
|
||||
closeElement.innerHTML = navigator.language === 'zh-CN' ? '关闭 ×' : 'close ×';
|
||||
closeElement.onclick = () => body.removeChild(infoElement);
|
||||
closeElement.onKeyDown = () => body.removeChild(infoElement);
|
||||
closeElement.tabindex = 0;
|
||||
closeElement.role = 'button';
|
||||
infoElement.appendChild(closeElement);
|
||||
|
||||
body.appendChild(infoElement);
|
||||
}
|
||||
|
||||
register({ onUpdate: informUserToReloadToGetLatestContent });
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ask-user-reload {
|
||||
padding: 25px;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 5px;
|
||||
background: wheat;
|
||||
z-index: 9999;
|
||||
cursor: alias;
|
||||
}
|
||||
.ask-user-reload-close {
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
creator: LinOnetwo
|
||||
tags: $:/tags/RawMarkup
|
||||
title: $:/plugins/linonetwo/service-worker/load-service-worker.html
|
||||
type: text/html
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"title": "$:/plugins/linonetwo/service-worker",
|
||||
"description": "Use service worker to cache content, make it works even offline, and can be add to the desktop as an App.",
|
||||
"author": "LinOnetwo",
|
||||
"core-version": ">=5.1.22",
|
||||
"plugin-type": "plugin",
|
||||
"version": "0.0.1",
|
||||
"list": "readme"
|
||||
}
|
||||
51
template/wiki/plugins/linonetwo/service-worker/readme.tid
Executable file
51
template/wiki/plugins/linonetwo/service-worker/readme.tid
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
title: $:/plugins/linonetwo/service-worker/readme
|
||||
created: 20200414135748497
|
||||
modified: 20200602062349232
|
||||
creator: LinOnetwo
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
!! Usage
|
||||
|
||||
After install, you have to publish your wiki as a HTTPS website to make it work.
|
||||
|
||||
!!! Make sure to include all necessary step in the build process
|
||||
|
||||
Add following files to your `/public` folder after build, you can use a script to copy them to the build folder after the wiki build process:
|
||||
|
||||
1. Add a `manifest.webmanifest` like:
|
||||
|
||||
```json
|
||||
{
|
||||
"background_color": "white",
|
||||
"theme_color": "white",
|
||||
"description": "Meme of LinOnetwo 林一二的模因和想法 - TiddlyWiki 非线性的知识库和博客",
|
||||
"display": "standalone",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/TiddlyWikiIconBlack.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/TiddlyWikiIconWhite.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"name": "TiddlyWiki",
|
||||
"short_name": "Wiki",
|
||||
"lang": "zh-CN",
|
||||
"start_url": "/",
|
||||
"scope": "/"
|
||||
}
|
||||
```
|
||||
|
||||
Make sure icon size is at least 144x144. And change all necessary fields.
|
||||
|
||||
2. Add `service-worker.js`:
|
||||
|
||||
See [[https://github.com/linonetwo/Meme-of-LinOnetwo/public/service-worker.js|https://github.com/linonetwo/Meme-of-LinOnetwo/blob/d088f72a2b95ee21b68af1b349d9993a3997bf19/Meme-of-LinOnetwo/public/service-worker.js]] for example.
|
||||
|
||||
!!! Config router
|
||||
|
||||
Sometimes request from this plugin to your `service-worker.js` will resulted in 404, this is basically because you are not putting `service-worker.js` just besides your `index.html`, or the router config is wrong.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.3/workbox-sw.js');
|
||||
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.4/workbox-sw.js');
|
||||
|
||||
if (workbox) {
|
||||
console.log(`Yay! Workbox is loaded 🎉Service Worker is working!`);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"felixhayashi/topstoryview",
|
||||
"mat/field-value-selector",
|
||||
"linonetwo/opened-tiddlers-bar",
|
||||
"linonetwo/service-worker",
|
||||
"linonetwo/copy-on-select",
|
||||
"linonetwo/source-control-management",
|
||||
"linonetwo/prevent-edit"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue