diff --git a/package-lock.json b/package-lock.json index 48ff0a6..3a7de3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@types/leaflet": "^1.9.21", "comlink": "^4.4.2", "geolib": "^3.3.4", - "gtfs-sqljs": "github:sysdevrun/gtfs-sqljs#7912bef", + "gtfs-sqljs": "github:sysdevrun/gtfs-sqljs#005bf84", "leaflet": "^1.9.4", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -3412,7 +3412,7 @@ }, "node_modules/gtfs-sqljs": { "version": "0.3.0", - "resolved": "git+ssh://git@github.com/sysdevrun/gtfs-sqljs.git#7912bef5dc0dc3c16cb2aa4ca19c6f03e2bcd015", + "resolved": "git+ssh://git@github.com/sysdevrun/gtfs-sqljs.git#005bf84de587b0730c26385fd9fb9b9273189526", "license": "MIT", "dependencies": { "jszip": "^3.10.1", diff --git a/package.json b/package.json index ffa414e..431c8c3 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@types/leaflet": "^1.9.21", "comlink": "^4.4.2", "geolib": "^3.3.4", - "gtfs-sqljs": "github:sysdevrun/gtfs-sqljs#7912bef", + "gtfs-sqljs": "github:sysdevrun/gtfs-sqljs#005bf84", "leaflet": "^1.9.4", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/src/App.tsx b/src/App.tsx index ebc915d..1c9c82e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -160,6 +160,8 @@ function App() { const [loadingProgress, setLoadingProgress] = useState(null) const [error, setError] = useState(null) const [realtimeLastUpdated, setRealtimeLastUpdated] = useState(0) + const [lastRtFetchTimestamp, setLastRtFetchTimestamp] = useState(null) + const [secondsSinceLastUpdate, setSecondsSinceLastUpdate] = useState(null) // Web Worker reference const workerRef = useRef | null>(null) @@ -341,6 +343,10 @@ function App() { setVehicles(sortedVehicles) setTripUpdates(tripUpdatesData) + // Get and store the last realtime fetch timestamp from the library + const rtTimestamp = await workerRef.current.getLastRealtimeFetchTimestamp() + setLastRtFetchTimestamp(rtTimestamp) + // Update timestamp to trigger stop times refresh setRealtimeLastUpdated(Date.now()) } catch (err) { @@ -370,6 +376,25 @@ function App() { return () => clearInterval(interval) }, [gtfsLoaded, config.updateInterval, updateRealtimeData]) + // Update seconds since last realtime update every second + useEffect(() => { + if (lastRtFetchTimestamp === null) { + setSecondsSinceLastUpdate(null) + return + } + + const updateSeconds = () => { + const now = Date.now() + const seconds = Math.floor((now - lastRtFetchTimestamp) / 1000) + setSecondsSinceLastUpdate(seconds) + } + + updateSeconds() + const interval = setInterval(updateSeconds, 1000) + + return () => clearInterval(interval) + }, [lastRtFetchTimestamp]) + // Load trips for selected route (Browse Data tab) useEffect(() => { if (!workerRef.current || !gtfsLoaded || !selectedRoute || !gtfsApiRef.current) return @@ -454,7 +479,9 @@ function App() { {agencies.length > 0 && `${agencies.map(a => a.agency_name).join(', ')} - `}GTFS Real-Time Explorer - Explore transit data with gtfs-sqljs + {secondsSinceLastUpdate !== null + ? `GTFS-RT: last update ${secondsSinceLastUpdate} seconds ago` + : 'Explore transit data with gtfs-sqljs'} diff --git a/src/gtfs.worker.ts b/src/gtfs.worker.ts index e222fa8..f607b08 100644 --- a/src/gtfs.worker.ts +++ b/src/gtfs.worker.ts @@ -67,6 +67,7 @@ export interface GtfsWorkerAPI { // Realtime methods fetchRealtimeData: () => Promise getActiveServiceIds: (date: string) => string[] + getLastRealtimeFetchTimestamp: () => number | null // Database methods getDatabase: () => Uint8Array | null @@ -223,6 +224,13 @@ class GtfsWorker implements GtfsWorkerAPI { await this.gtfs.fetchRealtimeData() } + getLastRealtimeFetchTimestamp(): number | null { + if (!this.gtfs) { + return null + } + return this.gtfs.getLastRealtimeFetchTimestamp() + } + getDatabase(): Uint8Array | null { if (!this.gtfs) { return null