added dockerfile and updated Readme
4
apps.js
@@ -62,7 +62,7 @@ createSoundToggleButton();
|
|||||||
|
|
||||||
// Load data from localStorage or use defaults
|
// Load data from localStorage or use defaults
|
||||||
function loadData() {
|
function loadData() {
|
||||||
const savedData = localStorage.getItem('chessTimerData');
|
const savedData = localStorage.getItem('gameTimerData');
|
||||||
if (savedData) {
|
if (savedData) {
|
||||||
const parsedData = JSON.parse(savedData);
|
const parsedData = JSON.parse(savedData);
|
||||||
players = parsedData.players;
|
players = parsedData.players;
|
||||||
@@ -87,7 +87,7 @@ function saveData() {
|
|||||||
gameState,
|
gameState,
|
||||||
currentPlayerIndex
|
currentPlayerIndex
|
||||||
};
|
};
|
||||||
localStorage.setItem('chessTimerData', JSON.stringify(dataToSave));
|
localStorage.setItem('gameTimerData', JSON.stringify(dataToSave));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render players to carousel
|
// Render players to carousel
|
||||||
|
|||||||
4
audio.js
@@ -14,7 +14,7 @@ const audioManager = {
|
|||||||
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
|
|
||||||
// Check for saved mute preference
|
// Check for saved mute preference
|
||||||
const savedMute = localStorage.getItem('chessTimerMuted');
|
const savedMute = localStorage.getItem('gameTimerMuted');
|
||||||
this.muted = savedMute === 'true';
|
this.muted = savedMute === 'true';
|
||||||
|
|
||||||
// Create all the sounds
|
// Create all the sounds
|
||||||
@@ -270,7 +270,7 @@ const audioManager = {
|
|||||||
// Toggle mute state
|
// Toggle mute state
|
||||||
toggleMute() {
|
toggleMute() {
|
||||||
this.muted = !this.muted;
|
this.muted = !this.muted;
|
||||||
localStorage.setItem('chessTimerMuted', this.muted);
|
localStorage.setItem('gameTimerMuted', this.muted);
|
||||||
return this.muted;
|
return this.muted;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 398 B |
|
Before Width: | Height: | Size: 770 B After Width: | Height: | Size: 770 B |
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="theme-color" content="#2c3e50">
|
<meta name="theme-color" content="#2c3e50">
|
||||||
<title>Multi-Player Chess Timer</title>
|
<title>Game Timer</title>
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
@@ -85,5 +85,12 @@
|
|||||||
|
|
||||||
<script type="module" src="audio.js"></script>
|
<script type="module" src="audio.js"></script>
|
||||||
<script type="module" src="apps.js"></script>
|
<script type="module" src="apps.js"></script>
|
||||||
|
<script>
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
navigator.serviceWorker.register("/sw.js")
|
||||||
|
.then(() => console.log("Service Worker Registered"))
|
||||||
|
.catch((err) => console.log("Service Worker Failed", err));
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,38 +1,49 @@
|
|||||||
{
|
{
|
||||||
"name": "Chess Timer PWA",
|
"name": "Game Timer PWA",
|
||||||
"short_name": "Chess Timer",
|
"short_name": "Game Timer",
|
||||||
"description": "Multi-player chess timer with carousel navigation",
|
"description": "Multi-player chess-like timer with carousel navigation",
|
||||||
"start_url": "/",
|
"start_url": "/index.html",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"background_color": "#f5f5f5",
|
"background_color": "#f5f5f5",
|
||||||
"theme_color": "#2c3e50",
|
"theme_color": "#2c3e50",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "android-chrome-192x192.png",
|
"src": "/icons/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png"
|
||||||
"purpose": "any maskable"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "android-chrome-512x512.png",
|
"src": "/icons/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png"
|
||||||
"purpose": "any maskable"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "apple-touch-icon.png",
|
"src": "/icons/apple-touch-icon.png",
|
||||||
"sizes": "180x180",
|
"sizes": "180x180",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "favicon-32x32.png",
|
"src": "/icons/favicon-32x32.png",
|
||||||
"sizes": "32x32",
|
"sizes": "32x32",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "favicon-16x16.png",
|
"src": "/icons/favicon-16x16.png",
|
||||||
"sizes": "16x16",
|
"sizes": "16x16",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"screenshots": [
|
||||||
|
{
|
||||||
|
"src": "/screenshots/screenshot1.png",
|
||||||
|
"sizes": "1302x1122",
|
||||||
|
"type": "image/png",
|
||||||
|
"form_factor": "wide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/screenshots/screenshot2.png",
|
||||||
|
"sizes": "1082x2402",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
BIN
screenshots/screenshot1.png
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
screenshots/screenshot2.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
@@ -3,12 +3,12 @@
|
|||||||
"short_name": "Game Timer",
|
"short_name": "Game Timer",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/icons/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "/icons/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|
|||||||
14
sw.js
@@ -1,11 +1,19 @@
|
|||||||
// Updated service worker code - sw.js
|
// Updated service worker code - sw.js
|
||||||
const CACHE_NAME = 'chess-timer-cache-v1';
|
const CACHE_NAME = 'timer-cache-v1';
|
||||||
const urlsToCache = [
|
const urlsToCache = [
|
||||||
'/',
|
'/',
|
||||||
'/index.html',
|
'/index.html',
|
||||||
'/styles.css',
|
'/styles.css',
|
||||||
'/script.js'
|
'/apps.js',
|
||||||
// Only include files that you're sure exist
|
'/audio.js',
|
||||||
|
'/icons/android-chrome-192x192.png',
|
||||||
|
'/icons/android-chrome-512x512.png',
|
||||||
|
'/icons/apple-touch-icon.png',
|
||||||
|
'/icons/favicon-32x32.png',
|
||||||
|
'/icons/favicon-16x16.png',
|
||||||
|
'/favicon.ico',
|
||||||
|
'/manifest.json',
|
||||||
|
'/site.webmanifest'
|
||||||
];
|
];
|
||||||
|
|
||||||
self.addEventListener('install', event => {
|
self.addEventListener('install', event => {
|
||||||
|
|||||||