updated icons and pwa install

This commit is contained in:
chris 2025-08-10 08:39:50 -04:00
parent 2ecf1fc49f
commit 214d94e819
6 changed files with 103 additions and 22 deletions

BIN
images/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
images/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 B

BIN
images/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,16 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="manifest" href="/manifest.json">
<title>TimeTracker</title>
<title>Time Pulse</title>
<!-- PWA Manifest -->
<link rel="manifest" href="manifest.json">
<!-- Favicons -->
<link rel="apple-touch-icon" sizes="180x180" href="../images/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="../images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="../icons/favicon-16x16.png">
<link rel="icon" href="../images/favicon.ico" type="image/x-icon">
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style/style.css">
<!-- Custom Styles -->
<link rel="stylesheet" href="/style/style.css">
</head>
<body class="bg-gray-100">
@ -19,8 +33,8 @@
<header class="bg-white shadow-md">
<nav class="container mx-auto px-6 py-3 flex justify-between items-center">
<div class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-blue-600"><path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"></path><path d="M12 6v6l4 2"></path></svg>
<h1 class="text-xl font-bold text-gray-800 ml-2">TimeTracker</h1>
<img src="../images/icon-48x48.webp" alt="Time Pulse Logo" width="48" height="48">
<h1 class="text-xl font-bold text-gray-800 ml-2">Time Pulse</h1>
</div>
<div id="nav-user-controls" class="hidden flex items-center">
<span id="welcome-message" class="text-gray-600 mr-3 text-sm sm:text-base truncate"></span>
@ -42,5 +56,41 @@
<div id="modal-container"></div>
</div>
<script type="module" src="js/main.js"></script></body>
</html>
<script type="module" src="/public/js/main.js"></script>
<script>
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
console.log('[PWA] beforeinstallprompt fired');
// Create the install button
const installBtn = document.createElement('button');
installBtn.textContent = 'Install Time Pulse';
installBtn.className = 'fixed bottom-6 right-6 bg-blue-600 text-white px-4 py-2 rounded-lg shadow-lg hover:bg-blue-700 transition';
document.body.appendChild(installBtn);
// When clicked, trigger the prompt
installBtn.addEventListener('click', () => {
installBtn.style.display = 'none'; // hide button
deferredPrompt.prompt();
deferredPrompt.userChoice.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('[PWA] User accepted install');
} else {
console.log('[PWA] User dismissed install');
}
deferredPrompt = null;
});
});
});
// Optional: show a console message when app is installed
window.addEventListener('appinstalled', () => {
console.log('[PWA] Installed');
});
</script>
</body>
</html>

View File

@ -1,5 +1,8 @@
const CACHE_NAME = 'timetracker-v1';
// This list should include all the essential files for your app's shell.
// --- Time Pulse Service Worker ---
const CACHE_NAME = 'timepulse-v1';
// Files to cache (App Shell)
const filesToCache = [
'/',
'/index.html',
@ -8,35 +11,63 @@ const filesToCache = [
'/js/ui.js',
'/js/api.js',
'/js/utils.js',
'/images/icon-192x192.png',
'/images/icon-512x512.png'
'/manifest.json',
'/icons/icon-192x192.webp',
'/icons/icon-512x512.webp'
];
// The install event runs when the service worker is first installed.
// --- Install Event ---
self.addEventListener('install', event => {
console.log('Service worker install event!');
console.log('[SW] Install event');
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Caching app shell');
console.log('[SW] Caching app shell');
return cache.addAll(filesToCache);
})
);
self.skipWaiting(); // Activate worker immediately
});
// The fetch event runs for every network request the page makes.
// --- Activate Event ---
self.addEventListener('activate', event => {
console.log('[SW] Activate event');
event.waitUntil(
caches.keys().then(keys =>
Promise.all(
keys.map(key => {
if (key !== CACHE_NAME) {
console.log('[SW] Removing old cache:', key);
return caches.delete(key);
}
})
)
)
);
self.clients.claim(); // Become available to all pages
});
// --- Fetch Event ---
self.addEventListener('fetch', event => {
// We only want to handle GET requests.
// Ignore non-GET requests and API calls
if (event.request.method !== 'GET' || event.request.url.includes('/api/')) {
return;
}
event.respondWith(
caches.match(event.request)
.then(response => {
// If we have a cached version, return it.
// Otherwise, fetch it from the network.
return response || fetch(event.request);
// Return cached file OR fetch from network
return response || fetch(event.request).then(fetchResponse => {
// Optionally cache new files on the fly
return caches.open(CACHE_NAME).then(cache => {
cache.put(event.request, fetchResponse.clone());
return fetchResponse;
});
});
})
.catch(() => {
// Optional: return a fallback page or image here
})
);
});
});