From 5cc27f852b02446659e0ab85305916c9f5e5a5f0 Mon Sep 17 00:00:00 2001
From: Ariel Costas Guerrero <ariel@costas.dev>
Date: Wed, 6 Aug 2025 00:12:19 +0200
Subject: 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.
---
 src/frontend/app/root.tsx | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

(limited to 'src/frontend/app/root.tsx')

diff --git a/src/frontend/app/root.tsx b/src/frontend/app/root.tsx
index 55c6c16..040494f 100644
--- a/src/frontend/app/root.tsx
+++ b/src/frontend/app/root.tsx
@@ -18,23 +18,15 @@ import "maplibre-theme/modern.css";
 import { Protocol } from "pmtiles";
 import maplibregl, { type LngLatLike } from "maplibre-gl";
 import { AppProvider } from "./AppContext";
+import { swManager } from "./utils/serviceWorkerManager";
+import { UpdateNotification } from "./components/UpdateNotification";
+import { useEffect } from "react";
 const pmtiles = new Protocol();
 maplibregl.addProtocol("pmtiles", pmtiles.tile);
 //#endregion
 
 import "./i18n";
 
-if ("serviceWorker" in navigator) {
-  navigator.serviceWorker
-    .register("/sw.js")
-    .then((registration) => {
-      console.log("Service Worker registered with scope:", registration.scope);
-    })
-    .catch((error) => {
-      console.error("Service Worker registration failed:", error);
-    });
-}
-
 export const links: Route.LinksFunction = () => [];
 
 export function HydrateFallback() {
@@ -47,6 +39,9 @@ export function Layout({ children }: { children: React.ReactNode }) {
       <head>
         <meta charSet="utf-8" />
         <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <meta name="mobile-web-app-capable" content="yes" />
+        <meta name="apple-mobile-web-app-capable" content="yes" />
+        <meta name="apple-mobile-web-app-status-bar-style" content="default" />
 
         <link rel="icon" type="image/jpg" href="/logo-512.jpg" />
         <link rel="icon" href="/favicon.ico" sizes="64x64" />
@@ -113,8 +108,14 @@ function isWithinVigo(lngLat: LngLatLike): boolean {
 import NavBar from "./components/NavBar";
 
 export default function App() {
+  useEffect(() => {
+    // Initialize service worker
+    swManager.initialize();
+  }, []);
+
   return (
     <AppProvider>
+      <UpdateNotification />
       <main className="main-content">
         <Outlet />
       </main>
-- 
cgit v1.3

