diff --git a/web/src/hooks/useLocation.tsx b/web/src/hooks/useLocation.tsx index fca73f9..4ce0ca6 100755 --- a/web/src/hooks/useLocation.tsx +++ b/web/src/hooks/useLocation.tsx @@ -43,6 +43,10 @@ export interface LocationState { interface LocationContextType { location: LocationState | null; savedLocations: SavedLocation[]; + // True once the initial sync from the server (the source of truth) has completed. + // Consumers that push the location onward (e.g. Discover → Feeld) should wait for this + // so they assert the server's authoritative value, not this device's stale cache. + locationReady: boolean; // Throws BannedCountryError if the LocationState has a banned country/countryCode. setLocation: (location: LocationState | null) => void; // Throws BannedCountryError if the country is on the Feeld-restricted list. @@ -106,18 +110,17 @@ export function LocationProvider({ children }: { children: ReactNode }) { }); } - // Restore current location if we don't have one - const cleanCurrent = sanitizeCurrent(serverData.currentLocation); - if (cleanCurrent && !location) { - setLocationState(cleanCurrent); - localStorage.setItem(CURRENT_LOCATION_KEY, JSON.stringify(cleanCurrent)); - } - - // Restore custom location if we don't have one - const cleanCustom = sanitizeCurrent(serverData.customLocation); - if (cleanCustom && !location) { - setLocationState(cleanCustom); - localStorage.setItem(CURRENT_LOCATION_KEY, JSON.stringify(cleanCustom)); + // The server is the single source of truth for the active location. + // Adopt whatever it currently holds (prefer currentLocation, fall back to + // customLocation), OVERRIDING this device's local cache — so two devices on + // the same account always converge to the same place instead of each + // re-asserting its own stale copy. Only keep local if the server has none. + const serverActive = + sanitizeCurrent(serverData.currentLocation) || + sanitizeCurrent(serverData.customLocation); + if (serverActive) { + setLocationState(serverActive); + localStorage.setItem(CURRENT_LOCATION_KEY, JSON.stringify(serverActive)); } } } catch (e) { @@ -199,6 +202,7 @@ export function LocationProvider({ children }: { children: ReactNode }) { value={{ location, savedLocations, + locationReady: hasSyncedFromServer, setLocation, saveLocation, deleteLocation, diff --git a/web/src/pages/Discover.tsx b/web/src/pages/Discover.tsx index 31d4b42..d474e0c 100755 --- a/web/src/pages/Discover.tsx +++ b/web/src/pages/Discover.tsx @@ -291,24 +291,29 @@ export function DiscoverPage() { }); const initialLoadDone = useRef(false); const savedLikedMeProfiles = useRef>(new Set()); - const { location } = useLocation(); + const { location, locationReady } = useLocation(); const { isFavorite, toggleFavorite } = useFavorites(); - // Set device location on Feeld when Discover page loads (emulates app open GPS) + // Push the location to Feeld whenever the authoritative location changes. + // Gate on `locationReady` so we wait for the server (the source of truth) to load + // first — otherwise this device would stamp its own stale localStorage location onto + // Feeld's single shared account-location slot, overriding what another device just set. + // Dedupe by coordinates so we don't re-push the same place on every re-render. const [updateDeviceLocation] = useMutation(DEVICE_LOCATION_UPDATE_MUTATION); - const locationSetRef = useRef(false); + const lastPushedRef = useRef(null); useEffect(() => { - if (location && !locationSetRef.current) { - locationSetRef.current = true; - updateDeviceLocation({ - variables: { input: { latitude: location.latitude, longitude: location.longitude } }, - }).then(() => { - console.log(`[Discover] Location set to ${location.name || `${location.latitude},${location.longitude}`}`); - }).catch((err) => { - console.error('[Discover] Failed to set location:', err); - }); - } - }, [location, updateDeviceLocation]); + if (!locationReady || !location) return; + const coordKey = `${location.latitude},${location.longitude}`; + if (lastPushedRef.current === coordKey) return; + lastPushedRef.current = coordKey; + updateDeviceLocation({ + variables: { input: { latitude: location.latitude, longitude: location.longitude } }, + }).then(() => { + console.log(`[Discover] Location set to ${location.name || coordKey}`); + }).catch((err) => { + console.error('[Discover] Failed to set location:', err); + }); + }, [locationReady, location, updateDeviceLocation]); // Fetch rotation location (what the cron actually set on Feeld) const [rotationLocation, setRotationLocation] = useState(null);