diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2025-08-06 00:12:19 +0200 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2025-08-06 00:12:19 +0200 |
| commit | 5cc27f852b02446659e0ab85305916c9f5e5a5f0 (patch) | |
| tree | 622636a2a7eade5442a3efb1726d822657d30295 /src/frontend/app/utils | |
| parent | b04fd7d33d07f9eddea2eb53e1389d5ca5453413 (diff) | |
feat: Implement pull-to-refresh functionality across various components
- Added `PullToRefresh` component to enable pull-to-refresh behavior in `StopList` and `Estimates` pages.
- Integrated `usePullToRefresh` hook to manage pull-to-refresh state and actions.
- Created `UpdateNotification` component to inform users of available updates from the service worker.
- Enhanced service worker management with `ServiceWorkerManager` class for better update handling and caching strategies.
- Updated CSS styles for new components and improved layout for better user experience.
- Refactored API caching logic in service worker to handle multiple endpoints and dynamic cache expiration.
- Added auto-refresh functionality for estimates data to keep information up-to-date.
Diffstat (limited to 'src/frontend/app/utils')
| -rw-r--r-- | src/frontend/app/utils/serviceWorkerManager.ts | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/frontend/app/utils/serviceWorkerManager.ts b/src/frontend/app/utils/serviceWorkerManager.ts new file mode 100644 index 0000000..cbff748 --- /dev/null +++ b/src/frontend/app/utils/serviceWorkerManager.ts @@ -0,0 +1,80 @@ +export class ServiceWorkerManager { + private registration: ServiceWorkerRegistration | null = null; + private updateAvailable = false; + private onUpdateCallback?: () => void; + + async initialize() { + if (!("serviceWorker" in navigator)) { + console.log("Service Workers not supported"); + return; + } + + try { + this.registration = await navigator.serviceWorker.register("/sw.js"); + console.log("Service Worker registered with scope:", this.registration.scope); + + // Listen for updates + this.registration.addEventListener("updatefound", () => { + const newWorker = this.registration!.installing; + if (newWorker) { + newWorker.addEventListener("statechange", () => { + if (newWorker.state === "installed" && navigator.serviceWorker.controller) { + // New service worker is installed and ready + this.updateAvailable = true; + this.onUpdateCallback?.(); + } + }); + } + }); + + // Listen for messages from the service worker + navigator.serviceWorker.addEventListener("message", (event) => { + if (event.data.type === "SW_UPDATED") { + this.updateAvailable = true; + this.onUpdateCallback?.(); + } + }); + + // Check for updates periodically + setInterval(() => { + this.checkForUpdates(); + }, 60 * 1000); // Check every minute + + } catch (error) { + console.error("Service Worker registration failed:", error); + } + } + + async checkForUpdates() { + if (this.registration) { + try { + await this.registration.update(); + } catch (error) { + console.error("Failed to check for updates:", error); + } + } + } + + activateUpdate() { + if (this.registration && this.registration.waiting) { + this.registration.waiting.postMessage({ type: "SKIP_WAITING" }); + this.updateAvailable = false; + } + } + + onUpdate(callback: () => void) { + this.onUpdateCallback = callback; + } + + isUpdateAvailable() { + return this.updateAvailable; + } + + async clearCache() { + if (this.registration && this.registration.active) { + this.registration.active.postMessage({ type: "CLEAR_CACHE" }); + } + } +} + +export const swManager = new ServiceWorkerManager(); |
