67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import type { FeatureMeta, FeatureFilters } from '../types';
|
|
import { stateToParams } from '../lib/url-state';
|
|
import type { OverlayId } from '../lib/overlays';
|
|
import type { BasemapId } from '../lib/basemaps';
|
|
import type { TravelTimeEntry } from './useTravelTime';
|
|
|
|
const URL_DEBOUNCE_MS = 300;
|
|
|
|
export function useUrlSync(
|
|
currentView: { latitude: number; longitude: number; zoom: number } | null,
|
|
filters: FeatureFilters,
|
|
features: FeatureMeta[],
|
|
selectedPOICategories: Set<string>,
|
|
rightPaneTab: 'properties' | 'area',
|
|
travelTimeEntries?: TravelTimeEntry[],
|
|
share?: string,
|
|
selectedOverlays?: Set<OverlayId>,
|
|
basemap?: BasemapId,
|
|
selectedCrimeTypes?: Set<string>,
|
|
selectedPostcode?: string,
|
|
colorOpacity?: number
|
|
) {
|
|
const urlDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (urlDebounceRef.current) {
|
|
clearTimeout(urlDebounceRef.current);
|
|
}
|
|
urlDebounceRef.current = setTimeout(() => {
|
|
const params = stateToParams(
|
|
currentView,
|
|
filters,
|
|
features,
|
|
selectedPOICategories,
|
|
rightPaneTab,
|
|
travelTimeEntries,
|
|
share,
|
|
selectedOverlays,
|
|
basemap,
|
|
selectedCrimeTypes,
|
|
selectedPostcode,
|
|
colorOpacity
|
|
);
|
|
const search = params.toString();
|
|
const newUrl = search ? `${window.location.pathname}?${search}` : window.location.pathname;
|
|
window.history.replaceState({ ...window.history.state }, '', newUrl);
|
|
}, URL_DEBOUNCE_MS);
|
|
|
|
return () => {
|
|
if (urlDebounceRef.current) clearTimeout(urlDebounceRef.current);
|
|
};
|
|
}, [
|
|
currentView,
|
|
filters,
|
|
features,
|
|
selectedPOICategories,
|
|
rightPaneTab,
|
|
travelTimeEntries,
|
|
share,
|
|
selectedOverlays,
|
|
basemap,
|
|
selectedCrimeTypes,
|
|
selectedPostcode,
|
|
colorOpacity,
|
|
]);
|
|
}
|