Skip to content

Commit 464459e

Browse files
committed
feat: installable as Progressive Web App
1 parent 68bed27 commit 464459e

File tree

7 files changed

+118
-3
lines changed

7 files changed

+118
-3
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
.DS_Store
33
Thumbs.db
44

5-
# IDE configuration files
6-
.vscode/
7-
85
# Temporary files
96
*.swp
107
*.swo

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"liveServer.settings.root": "/public",
3+
}

public/icons/icon-192.png

3.93 KB
Loading

public/icons/icon-512.png

11.7 KB
Loading

public/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<link rel="stylesheet" href="3rd-party/bootstrap/bootstrap.min.css" />
1111
<link rel="stylesheet" href="3rd-party/bootstrap-icons/bootstrap-icons.min.css" />
1212
<link rel="stylesheet" href="app.css" />
13+
<link rel="manifest" href="manifest.webmanifest" />
1314
</head>
1415

1516
<body class="d-flex flex-column h-100">
@@ -177,6 +178,7 @@ <h1 id="current-word" class="display-3 fw-bold mb-0">単語</h1>
177178
<script src="3rd-party/bootstrap/bootstrap.bundle.min.js"></script>
178179
<script src="3rd-party/jquery/jquery-3.7.1.min.js"></script>
179180
<script src="js/app.js" type="module" ></script>
181+
<script> navigator.serviceWorker?.register('service-worker.js')</script>
180182

181183
</body>
182184

public/manifest.webmanifest

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "LED Matrix Vocab",
3+
"description": " Cycle through Japanese vocabulary on Framework 16 LED Matrix Modules",
4+
"lang": "en-US",
5+
"start_url": "./index.html",
6+
"scope": "./",
7+
"display": "standalone",
8+
"orientation": "any",
9+
"categories": ["education", "utilities"],
10+
"icons": [
11+
{
12+
"src": "icons/icon-192.png",
13+
"sizes": "192x192",
14+
"type": "image/png"
15+
},
16+
{
17+
"src": "icons/icon-512.png",
18+
"sizes": "512x512",
19+
"type": "image/png"
20+
}
21+
]
22+
}

public/service-worker.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const CACHE_VERSION = 'v1';
2+
const CACHE_NAME = `led-vocab-${CACHE_VERSION}`;
3+
4+
const ASSETS_TO_CACHE = [
5+
'./',
6+
'index.html',
7+
'app.css',
8+
'manifest.webmanifest',
9+
'favicon.ico',
10+
'3rd-party/bootstrap/bootstrap.bundle.min.js',
11+
'3rd-party/bootstrap/bootstrap.bundle.min.js.map',
12+
'3rd-party/bootstrap/bootstrap.min.css',
13+
'3rd-party/bootstrap-icons/bootstrap-icons.css',
14+
'3rd-party/bootstrap-icons/bootstrap-icons.min.css',
15+
'3rd-party/bootstrap-icons/fonts/bootstrap-icons.woff',
16+
'3rd-party/bootstrap-icons/fonts/bootstrap-icons.woff2',
17+
'3rd-party/jquery/jquery-3.7.1.min.js',
18+
'fonts/JF-Dot-jiskan16-1990.woff2',
19+
'js/app.js',
20+
'js/constants.js',
21+
'js/data-sources.js',
22+
'js/DisplayBuffer.js',
23+
'js/DisplayBufferPair.js',
24+
'js/effects.js',
25+
'js/MarqueeText.js',
26+
'js/ModuleController.js',
27+
'js/PortMutex.js',
28+
'js/RawPortOperations.js',
29+
'js/util.js',
30+
'datasets/jlpt-words-by-level.json',
31+
'datasets/jawiki-2022-08-29.json',
32+
'icons/icon-192.png',
33+
'icons/icon-512.png',
34+
];
35+
36+
self.addEventListener('install', event => {
37+
console.log('[ServiceWorker] Installing...');
38+
event.waitUntil(
39+
caches.open(CACHE_NAME).then(cache => {
40+
console.log('[ServiceWorker] Caching assets...');
41+
return cache.addAll(ASSETS_TO_CACHE);
42+
})
43+
);
44+
});
45+
46+
self.addEventListener('activate', event => {
47+
console.log('[ServiceWorker] Activating...');
48+
event.waitUntil(
49+
caches.keys().then(cacheNames => {
50+
return Promise.all(
51+
cacheNames.map(cacheName => {
52+
if (cacheName !== CACHE_NAME) {
53+
console.log('[ServiceWorker] Deleting old cache:', cacheName);
54+
return caches.delete(cacheName);
55+
}
56+
})
57+
);
58+
})
59+
);
60+
self.clients.claim();
61+
});
62+
63+
self.addEventListener('fetch', event => {
64+
const isSameOrigin = new URL(event.request.url).origin === location.origin;
65+
const isGetRequest = event.request.method === 'GET';
66+
67+
// Assume cross-origin requests aren't cacheable (no CDNs!)
68+
if (!isGetRequest || !isSameOrigin) return;
69+
70+
const req = event.request;
71+
72+
// Avoid the gnarly `then` chain
73+
const res = (async () => {
74+
try {
75+
let response = await caches.match(req);
76+
if (!response) {
77+
response = await fetch(req);
78+
if (response && response.status == 200) {
79+
console.log('[ServiceWorker] Cache miss:', req.url);
80+
const copy = response.clone();
81+
caches.open(CACHE_NAME).then(cache => cache.put(req, copy));
82+
}
83+
}
84+
return response;
85+
} catch {
86+
console.log('[ServiceWorker] Fetch failed:', req.url);
87+
}
88+
})();
89+
90+
event.respondWith(res);
91+
});

0 commit comments

Comments
 (0)