Drop MOW fallback on flights-map, match Angular's geo-only seed

Angular's FlightsMapFilterComponent only sets departure when
UserLocationService.location emits an actual position — there's no
fallback to Moscow. Removing the React fallback aligns the empty
initial state (no splines drawn before user input).
This commit is contained in:
2026-04-19 22:49:13 +03:00
parent 8ccf560bf5
commit bdd3a099bc
2 changed files with 13 additions and 32 deletions
@@ -126,20 +126,23 @@ describe("useGeolocationDefault", () => {
expect(lastState.departure).toBeUndefined();
});
it("falls back to MOW when geolocation permission is denied", () => {
it("leaves departure empty when geolocation permission is denied", () => {
installGeolocation(errorMock());
renderHook(() =>
useGeolocationDefault(dictionaries, lastState, setFilterState),
);
expect(lastState.departure).toBe("MOW");
// Angular's FlightsMapFilterComponent only seeds departure when
// UserLocationService.location emits — there's no fallback when
// the user denies geo access.
expect(lastState.departure).toBeUndefined();
});
it("falls back to MOW when navigator.geolocation is missing", () => {
it("leaves departure empty when navigator.geolocation is missing", () => {
installGeolocation(undefined);
renderHook(() =>
useGeolocationDefault(dictionaries, lastState, setFilterState),
);
expect(lastState.departure).toBe("MOW");
expect(lastState.departure).toBeUndefined();
});
it("does nothing when dictionaries is null at callback time", () => {
@@ -2,7 +2,9 @@
* Sets the flights-map filter's departure to the nearest city based on
* browser geolocation, if the user has not already typed a departure or
* arrival. Fires once per mount. Silent on permission denial or missing
* geolocation API. Matches Angular `UserLocationService` + `DictionariesService.locate`.
* geolocation API. Matches Angular `FlightsMapFilterComponent.ngOnInit`
* which only seeds departure when `UserLocationService.location` emits
* — i.e. on actual geo permission, with no MOW fallback.
*/
import { useEffect, useRef } from "react";
@@ -20,7 +22,6 @@ export function useGeolocationDefault(
) => void,
): void {
const appliedRef = useRef(false);
const fallbackAppliedRef = useRef(false);
const dictRef = useRef(dictionaries);
dictRef.current = dictionaries;
const filterRef = useRef(filterState);
@@ -28,26 +29,6 @@ export function useGeolocationDefault(
const setFilterRef = useRef(setFilterState);
setFilterRef.current = setFilterState;
// MOW fallback seed: fires as soon as dictionaries load so the
// orange Moscow marker shows even without geo permission. Runs at
// most once. Geo response below may overwrite with a closer city.
useEffect(() => {
if (fallbackAppliedRef.current) return;
if (!dictionaries) return;
if (filterRef.current.departure || filterRef.current.arrival) {
fallbackAppliedRef.current = true;
return;
}
const moscow = dictionaries.cityByCode.get("MOW");
if (!moscow) return;
fallbackAppliedRef.current = true;
setFilterRef.current((prev) =>
prev.departure || prev.arrival
? prev
: { ...prev, departure: "MOW" },
);
}, [dictionaries]);
useEffect(() => {
if (appliedRef.current) return;
if (typeof navigator === "undefined" || !navigator.geolocation) {
@@ -62,10 +43,6 @@ export function useGeolocationDefault(
const d = dictRef.current;
const f = filterRef.current;
if (!d) return;
// Don't override anything that's already in state — neither
// the MOW fallback above nor an explicit user choice. Matches
// Angular which keeps the orange marker on Moscow once the
// initial render has placed it.
if (f.departure || f.arrival) return;
const city = findCityByCoord(
@@ -82,8 +59,9 @@ export function useGeolocationDefault(
);
},
() => {
// Silent: permission denied / timeout / unavailable. The MOW
// fallback above already seeded the marker.
// Silent: permission denied / timeout / unavailable. Matches
// Angular which leaves the filter empty when no location is
// available.
},
{ enableHighAccuracy: false, timeout: 5000 },
);