// Moving to current location is handled by enabling isFollowingUserLocation
const isFollowingUserLocation = useRef(true);
/*
This state is forcefully rendering the moveCameraTo function while onUpdate is triggered
onUpdate doesn't update the value in currentPosition
To update it, the component needs to be rerendered
Its a quick-fix for now, we'll update the library to see if that
works fine with built-in follow location according to our requirements
*/
const [shouldRenderForcefullyOnUpdate, setShouldRenderForcefullyOnUpdate] =
useState(false);
// Function to handle modal confirm button press
const onPressOk = () => {
setPolygons([]);
hideModal();
};
// Runs when current field to edit is changed in edit field flow
useEffect(() => {
if (fieldDetail?.boundary_status === 'incomplete') {
setPolygons([fieldDetail?.boundaries?.coordinates[0][0]] || []);
}
setPolygons(fieldDetail?.boundaries?.coordinates[0] || []);
if (fieldDetail?.boundaries) {
setFieldArea(
helperFunctions.toFormattedArea(area(fieldDetail?.boundaries))
);
}
}, [fieldDetail?.id]);
/*
@param coordinates moves the camera to given coordinates
@param shouldStopFollowLocation This parameter stops follow location in cases
where we don't need to follow the location e.g. edit field or search location
Note: setCamera doesn't work while followLocation is true, so we have to
make it false before using setCamera. And we make it true again in default case
// This callback triggers when the map is moved manually by touch
// So we have to disable follow location
const onTouchMove = () => {
isFollowingUserLocation.current = false;
};
// This useEffect handles the movement of camera while following location
useEffect(() => {
if (isFollowingUserLocation.current && !fieldDetail?.id) {
moveCameraTo(currentPosition.current);
}
}, [currentPosition.current, shouldRenderForcefullyOnUpdate]);
I have made a follow location feature. The camera follows the user if he/she is moving.
During the movement, the onUpdate is triggered but it doesnot uPdates the value in "currentPosition.current".
Instead it passes some previous value in the function which came across the movement.
Expected behavior
"currentPosition.current" must be updated properly and should give the exact current value of "currentPosition.current" whenever the addPoint function is called.
Notes / preliminary analysis
I have also tried this on newer versions (10.1.1 to 10.1.15) and the latest version (10.1.27) but no luck.
When i hanged "minDisplacement" value to 5, it started updating the "curretPosition.current" after moving some meters. But i need that to add that point right where i clicked the button (means right where my current location was displayed)
Mapbox Implementation
Mapbox
Mapbox Version
10.17.0
React Native Version
0.70.15
Platform
iOS, Android
@rnmapbox/maps
version10.0.15
Standalone component to reproduce
import { useEffect, useRef, useState } from 'react'; import { Platform } from 'react-native'; import MapboxGL, { UserLocationRenderMode } from '@rnmapbox/maps'; import { MapState } from '@rnmapbox/maps/lib/typescript/components/MapView'; import { area } from '@turf/turf'; import { isEmpty } from 'lodash'; import { useTranslation } from 'react-i18next'; import { SearchIcon, CurrentLocationIcon, HelpCircleIcon, ResetIcon, OnePinIcon, } from '@ricultx/assets'; import { ConfirmationModal } from '@ricultx/components/Farmer'; import { OutOfAreaModal, WhitePointer } from '@ricultx/components/Field'; import { DistanceLabels, NearbyFields, PolygonDrawing, PolygonJoints, MAP_STYLE_SATELLITE, } from '@ricultx/components/MapComponents'; import { drawFieldNearbyFieldFillLayerStyle } from '@ricultx/components/MapComponents/NearbyBoundaries/NearbyBoundaries.styled'; import { SearchLocationsHandler, SearchLocations, } from '@ricultx/components/SearchLocations'; import { SVGImage } from '@ricultx/components/SVGImage'; import useOrgSpecificConfig from '@ricultx/pattern/ui/hooks/useOrgSpecificConfig'; import { getIsConnected } from '@ricultx/store/nodes/networking'; import { useDeleteRecentUserSearchesMutation, useSaveRecentUserSearchMutation, } from '@ricultx/store/nodes/userSearch'; import { useSelector } from '@ricultx/store/root'; import { useCountryData } from '@ricultx/store/utils'; import { useModalVisible } from '@ricultx/utils/hooks'; import { mapStyle, OptionsContainer, HelpTextContainer, TopOptions, TopOptionItem, CustomControl, HelpTextStyle, AreaTextContainer, } from './DrawFieldFeature.styled'; import { DrawFieldFeatureProps } from './DrawFieldFeature.types'; import { MapButtons } from './MapButtons'; import { useMapDrawing } from './useMapDrawing';
/*
@returns DrawFieldFeature */ export const DrawFieldFeature = ({ onPressHelpIcon, isModalVisible, onModalCancel, onModalConfirm, ...params }: Required) => {
// Hooks
const {
polygons,
onPressAddPoint,
onDragPoint,
onPressUndo,
onPressFinish,
setPolygons,
isOutOFAreaModalVisible,
setIsOutOFAreaModalVisible,
isOverlapping,
isFinishDrawing,
fieldDetail,
isFetchingRecentFieldSearches,
recentFieldSearches,
setRecentFieldSearches,
nearbyFieldsCollection,
onRegionChange,
viewportCoordinates,
isFieldAreaInRange,
helpTextMessage,
isAddPointButtonDisable,
isPolygonInvalid,
onConfirmedReset,
isOnePinButtonDisabled,
onOnePinPress,
onePinFarmCreateConfig,
fieldArea,
setFieldArea,
} = useMapDrawing(params);
const { country: { fallbackCoordinates: { lat, lng }, }, helperFunctions, } = useCountryData();
const isConnected = useSelector(getIsConnected);
const { field_draw_map_style } = useOrgSpecificConfig();
const { isResetModalVisible, showResetModal, hideResetModal } = useModalVisible('reset');
const { isRedrawModalVisible, showRedrawModal, hideRedrawModal } = useModalVisible('redraw');
const searchRef = useRef(null);
const { t } = useTranslation('translation', {
keyPrefix: 'portfolio_page.field.fields',
});
const mapViewRef = useRef(null);
const cameraRef = useRef(null);
const currentPosition = useRef<number[] | null>(null);
const currentSpeed = useRef(5);
const [isLocationFetched, setLocationFetched] = useState(false);
// Moving to current location is handled by enabling isFollowingUserLocation const isFollowingUserLocation = useRef(true);
/*
const [deleteRecentFieldSearches] = useDeleteRecentUserSearchesMutation(); const [saveRecentFieldSearch] = useSaveRecentUserSearchMutation();
// Function to open bottom sheet const handleSearchSheet = () => { isFollowingUserLocation.current = false; searchRef?.current?.openBottomSheet?.(); };
const hideModal = () => { setIsOutOFAreaModalVisible(false); };
const onPressResetIcon = () => { showResetModal(); };
const onPressRedrawFinish = () => { showRedrawModal(); };
// Function to handle modal confirm button press const onPressOk = () => { setPolygons([]); hideModal(); };
// Runs when current field to edit is changed in edit field flow useEffect(() => { if (fieldDetail?.boundary_status === 'incomplete') { setPolygons([fieldDetail?.boundaries?.coordinates[0][0]] || []); } setPolygons(fieldDetail?.boundaries?.coordinates[0] || []); if (fieldDetail?.boundaries) { setFieldArea( helperFunctions.toFormattedArea(area(fieldDetail?.boundaries)) ); } }, [fieldDetail?.id]);
/*
*/
const moveCameraTo = (coordinates) => { cameraRef.current?.setCamera({ centerCoordinate: coordinates, zoomLevel: 17, animationDuration: 1500, });
// moving to current location is handled by enabling isFollowingUserLocation };
/**
const onPressDeleteRecentFieldSearch = async () => { await deleteRecentFieldSearches({ search_feature_type: 'portfolio_field' }); setRecentFieldSearches([]); };
const onRegionIsChanging = (state: MapState) => { onRegionChange(state.properties.center); };
const addPoint = () => { onPressAddPoint(currentPosition.current ?? [0, 0]); };
const saveRecentSearch = async (query) => { const payload = { search_query: query, search_feature_type: 'portfolio_field', };
await saveRecentFieldSearch(payload).unwrap(); };
const setSelectedCoordinates = ({ lat, lng, query }) => { saveRecentSearch(query); moveCameraTo([lng, lat]); };
// This callback triggers when the map is moved manually by touch // So we have to disable follow location const onTouchMove = () => { isFollowingUserLocation.current = false; };
useEffect(() => { if (isEmpty(fieldDetail)) { getLocationPermission(); } else { moveCameraTo(fieldDetail?.boundaries?.coordinates[0][0]); } }, [mapViewRef.current, fieldDetail?.id]);
// This useEffect handles the movement of camera while following location useEffect(() => { if (isFollowingUserLocation.current && !fieldDetail?.id) { moveCameraTo(currentPosition.current); } }, [currentPosition.current, shouldRenderForcefullyOnUpdate]);
const onConfirmReset = () => { onConfirmedReset(); hideResetModal(); };
const onConfirmRedraw = () => { hideRedrawModal(); onPressFinish(); };
return ( <> <OutOfAreaModal isVisible={isOutOFAreaModalVisible} hasBackdrop={false} onOkayPress={onPressOk} /> <MapboxGL.MapView ref={mapViewRef} style={mapStyle.default} onCameraChanged={onRegionIsChanging} logoEnabled={false} attributionEnabled={false} styleURL={isConnected ? field_draw_map_style : MAP_STYLE_SATELLITE} onTouchMove={onTouchMove}
Observed behavior and steps to reproduce
I have made a follow location feature. The camera follows the user if he/she is moving. During the movement, the onUpdate is triggered but it doesnot uPdates the value in "currentPosition.current". Instead it passes some previous value in the function which came across the movement.
Expected behavior
"currentPosition.current" must be updated properly and should give the exact current value of "currentPosition.current" whenever the addPoint function is called.
Notes / preliminary analysis
I have also tried this on newer versions (10.1.1 to 10.1.15) and the latest version (10.1.27) but no luck. When i hanged "minDisplacement" value to 5, it started updating the "curretPosition.current" after moving some meters. But i need that to add that point right where i clicked the button (means right where my current location was displayed)
Additional links and references
No response