Skip to content

Commit 12cdc5f

Browse files
feat: Implement PWA features for LoveCipher
Converts the LoveCipher game into a basic Progressive Web App (PWA). Changes include: - Added `manifest.json` to define PWA properties (name, icons, start_url, display mode, theme colors). - Created `sw.js` (service worker) to cache core assets (HTML, CSS, JS, manifest, icons) for offline availability using a cache-first strategy. - Updated `script.js` to register the service worker. - Updated `index.html` to link the manifest file and include theme-color meta tag and a basic apple-touch-icon. - Added placeholder icon files in an `icons` directory and included them in the service worker cache list.
1 parent dc39db2 commit 12cdc5f

File tree

6 files changed

+122
-0
lines changed

6 files changed

+122
-0
lines changed
Lines changed: 2 additions & 0 deletions
Loading
Lines changed: 2 additions & 0 deletions
Loading

lovecipher_game/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>LoveCipher</title>
7+
<link rel="manifest" href="manifest.json">
8+
<meta name="theme-color" content="#ff69b4">
79
<link rel="stylesheet" href="style.css">
10+
<link rel="apple-touch-icon" href="icons/icon-192x192.png"> <!-- Basic iOS support -->
811
</head>
912
<body>
1013
<div id="game-container">

lovecipher_game/manifest.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "LoveCipher",
3+
"short_name": "LoveCipher",
4+
"description": "A narrative puzzle game of love and ciphers.",
5+
"start_url": ".",
6+
"display": "standalone",
7+
"background_color": "#ffe4e1",
8+
"theme_color": "#ff69b4",
9+
"icons": [
10+
{
11+
"src": "icons/icon-192x192.png",
12+
"sizes": "192x192",
13+
"type": "image/png",
14+
"purpose": "any maskable"
15+
},
16+
{
17+
"src": "icons/icon-512x512.png",
18+
"sizes": "512x512",
19+
"type": "image/png",
20+
"purpose": "any maskable"
21+
}
22+
]
23+
}

lovecipher_game/script.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,4 +476,19 @@ document.addEventListener('DOMContentLoaded', () => {
476476
}
477477

478478
startGame();
479+
480+
// --- PWA Service Worker Registration ---
481+
if ('serviceWorker' in navigator) {
482+
window.addEventListener('load', () => {
483+
navigator.serviceWorker.register('./sw.js')
484+
.then(registration => {
485+
console.log('SW: Registered successfully:', registration.scope);
486+
})
487+
.catch(error => {
488+
console.error('SW: Registration failed:', error);
489+
});
490+
});
491+
} else {
492+
console.log('SW: Service Worker not supported by this browser.');
493+
}
479494
});

lovecipher_game/sw.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
const CACHE_NAME = 'lovecipher-cache-v1';
2+
const CORE_ASSETS = [
3+
'.', // Alias for index.html
4+
'index.html',
5+
'style.css',
6+
'script.js',
7+
'manifest.json', // Good to cache the manifest too
8+
'icons/icon-192x192.png',
9+
'icons/icon-512x512.png'
10+
];
11+
12+
// Install event: Cache core assets
13+
self.addEventListener('install', event => {
14+
console.log('SW: Install event');
15+
event.waitUntil(
16+
caches.open(CACHE_NAME)
17+
.then(cache => {
18+
console.log('SW: Caching core assets');
19+
return cache.addAll(CORE_ASSETS);
20+
})
21+
.then(() => self.skipWaiting()) // Activate worker immediately
22+
.catch(error => {
23+
console.error('SW: Failed to cache core assets:', error);
24+
})
25+
);
26+
});
27+
28+
// Activate event: Clean up old caches if any
29+
self.addEventListener('activate', event => {
30+
console.log('SW: Activate event');
31+
event.waitUntil(
32+
caches.keys().then(cacheNames => {
33+
return Promise.all(
34+
cacheNames.map(cacheName => {
35+
if (cacheName !== CACHE_NAME) {
36+
console.log('SW: Deleting old cache:', cacheName);
37+
return caches.delete(cacheName);
38+
}
39+
})
40+
);
41+
}).then(() => self.clients.claim()) // Claim clients immediately
42+
);
43+
});
44+
45+
// Fetch event: Serve from cache first, then network
46+
self.addEventListener('fetch', event => {
47+
// console.log('SW: Fetch event for:', event.request.url);
48+
event.respondWith(
49+
caches.match(event.request)
50+
.then(cachedResponse => {
51+
if (cachedResponse) {
52+
// console.log('SW: Serving from cache:', event.request.url);
53+
return cachedResponse;
54+
}
55+
// console.log('SW: Fetching from network:', event.request.url);
56+
return fetch(event.request).then(networkResponse => {
57+
// Optionally, cache new requests dynamically if needed
58+
// For this basic setup, we only cache core assets on install.
59+
// If you want to cache other things (e.g., images loaded by CSS/JS, API calls):
60+
/*
61+
if (networkResponse && networkResponse.status === 200 && networkResponse.type === 'basic') {
62+
const responseToCache = networkResponse.clone();
63+
caches.open(CACHE_NAME)
64+
.then(cache => {
65+
cache.put(event.request, responseToCache);
66+
});
67+
}
68+
*/
69+
return networkResponse;
70+
}).catch(error => {
71+
console.error('SW: Fetch failed; returning offline page or error for:', event.request.url, error);
72+
// Optionally, return a fallback offline page if appropriate
73+
// For a single-page app like this, if index.html is cached, it should mostly work.
74+
});
75+
})
76+
);
77+
});

0 commit comments

Comments
 (0)