import React, { useState, useMemo, useCallback, useRef, useEffect } from 'react'; import { GeoJson } from '../types/geojson'; import debounce from 'lodash.debounce'; interface CustomSliderProps { geoJsons: GeoJson[]; setDisplayGeoJsons: React.Dispatch>; setOpenPopup: React.Dispatch>; markerValue: number; minTimestamp: number; maxTimestamp: number; replayId: string; } const CustomSlider: React.FC = ({ geoJsons, setDisplayGeoJsons, setOpenPopup, markerValue, minTimestamp, maxTimestamp }) => { // State variables const [currentTimestamp, setCurrentTimestamp] = useState(minTimestamp); const [isPlaying, setIsPlaying] = useState(false); const [playbackSpeed, setPlaybackSpeed] = useState(1); const [filterParty, setFilterParty] = useState(null); const intervalRef = useRef(null); // Worker Reference for background processing const workerRef = useRef(null); useEffect(() => { workerRef.current = new Worker(new URL('../utils/workers.ts', import.meta.url)); return () => workerRef.current?.terminate(); }, []); // Debounced update function const debouncedUpdateGeoJsons = useMemo(() => { return debounce((timestamp: number) => { if (!workerRef.current) return; workerRef.current.postMessage({ geoJsons, timestamp, filterParty }); }, 200); }, [geoJsons, filterParty]); // Listen for worker messages useEffect(() => { if (!workerRef.current) return; workerRef.current.onmessage = (e) => { setDisplayGeoJsons(e.data); }; }, [setDisplayGeoJsons]); // Handle timestamp and update GeoJSONs const handleSliderChange = (event: React.ChangeEvent) => { const timestamp = Number(event.target.value); setCurrentTimestamp(timestamp); debouncedUpdateGeoJsons(timestamp); }; // Toggle play/pause functionality const togglePlayback = () => { if (isPlaying) { clearInterval(intervalRef.current!); } else { intervalRef.current = setInterval(() => { setCurrentTimestamp((prev) => { const nextTimestamp = prev + 1000 * playbackSpeed; if (nextTimestamp >= maxTimestamp) { clearInterval(intervalRef.current!); setIsPlaying(false); return maxTimestamp; } debouncedUpdateGeoJsons(nextTimestamp); return nextTimestamp; }); }, 1000); } setIsPlaying((prev) => !prev); }; // Toggle playback speed const toggleSpeed = () => setPlaybackSpeed((prev) => (prev === 1 ? 2 : 1)); // Handle filter change const handleFilterChange = (event: React.ChangeEvent) => { setFilterParty(event.target.value || null); }; // Return early if no data if (!geoJsons.length) return
Loading...
; return (
{/* Slider */}
{new Date(currentTimestamp).toLocaleString()}
{/* Playback Controls */}
{/* Filter Dropdown */}
); }; export default CustomSlider;