Skip to content

Commit

Permalink
Merge pull request #129 from akvo/feature/112-fix-gps-accuracy-behavior
Browse files Browse the repository at this point in the history
Feature/112 fix gps accuracy behavior
  • Loading branch information
dedenbangkit committed Aug 9, 2023
2 parents c59559f + 0e5da45 commit d2bcff6
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 234 deletions.
3 changes: 3 additions & 0 deletions app/__mocks__/expo-location.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const getCurrentPositionAsync = jest.fn().mockImplementation(() => {
coords: {
latitude: 37.12345,
longitude: -122.6789,
accuracy: 20,
},
});
});
Expand All @@ -11,6 +12,8 @@ export const requestForegroundPermissionsAsync = jest.fn().mockImplementation(()
return Promise.resolve({ status: 'granted' });
});

export const Accuracy = { High: 4, Highest: 5 };

export const Location = {
getCurrentPositionAsync,
requestForegroundPermissionsAsync,
Expand Down
22 changes: 4 additions & 18 deletions app/assets/map.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,10 @@
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div
id="map"
style="height: 100vh"
data-lat="{{latitude}}"
data-lng="{{longitude}}"
data-radius="{{radius}}"
></div>
<div id="map" style="height: 100vh" data-lat="{{latitude}}" data-lng="{{longitude}}"></div>
<script>
function handleMapClick(event, distance) {
const markerData = { lat: event.latlng.lat, lng: event.latlng.lng, distance };
function handleMapClick(event) {
const markerData = { lat: event.latlng.lat, lng: event.latlng.lng };
const eventData = { type: 'markerClicked', data: markerData };
window.ReactNativeWebView.postMessage(JSON.stringify(eventData));
}
Expand All @@ -49,14 +43,10 @@
//map.locate({setView: true, maxZoom: 19});
const lat = selector.getAttribute('data-lat');
const lng = selector.getAttribute('data-lng');
const radius = parseInt(selector.getAttribute('data-radius'), 10);

map.setView([lat, lng], 19);
let marker = L.marker([lat, lng]).addTo(map);

// add radius
L.circle([lat, lng], { radius }).addTo(map);

L.control
.zoom({
position: 'bottomleft',
Expand All @@ -68,11 +58,7 @@
map.removeLayer(marker);
}

const origin = L.latLng(lat, lng);
const destination = L.latLng(e.latlng.lat, e.latlng.lng);
const distance = Math.ceil(origin.distanceTo(destination));

handleMapClick(e, distance);
handleMapClick(e);
map.invalidateSize();

marker = L.marker([e.latlng.lat, e.latlng.lng]).addTo(map);
Expand Down
3 changes: 2 additions & 1 deletion app/src/build.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"errorHandling": true,
"loggingLevel": "verbose",
"appVersion": "1.2.0",
"lang": "en"
"lang": "en",
"gpsThreshold": 20
}
121 changes: 74 additions & 47 deletions app/src/form/fields/TypeGeo.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import React, { useState, useEffect, useMemo } from 'react';
import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { View } from 'react-native';
import { Text, Button } from '@rneui/themed';
import { useNavigation, useRoute } from '@react-navigation/native';

import { UIState, FormState } from '../../store';
import { UIState, FormState, BuildParamsState } from '../../store';
import { FieldLabel } from '../support';
import { styles } from '../styles';
import { loc, i18n } from '../../lib';

const TypeGeo = ({ onChange, values, keyform, id, name, tooltip, required, requiredSign }) => {
const [errorMsg, setErrorMsg] = useState(null);
const [gpsAccuracy, setGpsAccuracy] = useState(null);
const [currLocation, setCurrLocation] = useState({ lat: null, lng: null });
const [loading, setLoading] = useState({ current: false, map: false });
const currentValues = FormState.useState((s) => s.currentValues);
const [latitude, longitude] = currentValues?.[id] || [];

const gpsThreshold = BuildParamsState.useState((s) => s.gpsThreshold);
const isOnline = UIState.useState((s) => s.online);
const activeLang = FormState.useState((s) => s.lang);

Expand All @@ -22,64 +26,87 @@ const TypeGeo = ({ onChange, values, keyform, id, name, tooltip, required, requi
const route = useRoute();
const requiredValue = required ? requiredSign : null;

const handleGetCurrLocation = async (openMap = false) => {
const loadingKey = openMap ? 'map' : 'current';
setLoading({
...loading,
[loadingKey]: true,
});
await loc.getCurrentLocation(
({ coords }) => {
if (coords) {
const { latitude: lat, longitude: lng } = coords;
onChange(id, [lat, lng]);
const handleOpenMap = () => {
if (latitude && longitude) {
const params = { latitude, longitude, id, current_location: currLocation };
navigation.navigate('MapView', { ...route?.params, ...params });
} else {
handleGetCurrLocation(true);
}
};

const handleGetCurrLocation = useCallback(
async (openMap = false) => {
const loadingKey = openMap ? 'map' : 'current';
setLoading({
...loading,
[loadingKey]: true,
});
await loc.getCurrentLocation(
({ coords }) => {
const { latitude: lat, longitude: lng, accuracy } = coords;
/**
* accuracy number in meters, doc: https://docs.expo.dev/versions/latest/sdk/location/#locationgeocodedlocation
*/
setGpsAccuracy(Math.floor(accuracy));
// console.info('GPS accuracy:', accuracy, 'GPS Threshold:', gpsThreshold);
if ((accuracy <= gpsThreshold && !openMap) || openMap) {
setCurrLocation({
lat,
lng,
});
onChange(id, [lat, lng]);
setLoading({
...loading,
[loadingKey]: false,
});
}
if (openMap) {
const params = { latitude: lat, longitude: lng, id };
const params = { latitude: lat, longitude: lng, id, current_location: { lat, lng } };
navigation.navigate('MapView', { ...route?.params, ...params });
}
}
setLoading({
...loading,
[loadingKey]: false,
});
},
({ message }) => {
setLoading({
...loading,
[loadingKey]: false,
});
setErrorMsg(message);
},
);
};
},
({ message }) => {
setLoading({
...loading,
[loadingKey]: false,
});
setErrorMsg(message);
},
);
},
[gpsThreshold],
);

useEffect(() => {
if (gpsAccuracy && gpsAccuracy >= gpsThreshold && loading.current) {
handleGetCurrLocation(false);
}
}, [handleGetCurrLocation, gpsAccuracy, gpsThreshold, loading.current]);

return (
<View>
<FieldLabel keyform={keyform} name={name} tooltip={tooltip} requiredSign={requiredValue} />
<View style={styles.inputGeoContainer}>
{errorMsg ? (
<Text testID="text-error">{errorMsg}</Text>
) : (
<View>
<Text testID="text-lat">
{trans.latitude}: {latitude}
</Text>
<Text testID="text-lng">
{trans.longitude}: {longitude}
</Text>
</View>
<View>
<Text testID="text-lat">
{trans.latitude}: {latitude}
</Text>
<Text testID="text-lng">
{trans.longitude}: {longitude}
</Text>
</View>
{errorMsg && (
<Text testID="text-error" style={styles.errorText}>
{errorMsg}
</Text>
)}

<View style={styles.geoButtonGroup}>
<Button onPress={() => handleGetCurrLocation(false)} testID="button-curr-location">
{loading.current ? trans.loadingText : trans.buttonCurrLocation}
{loading.current ? trans.fetchingLocation : trans.buttonCurrLocation}
</Button>
{isOnline && (
<Button
type="outline"
onPress={() => handleGetCurrLocation(true)}
testID="button-open-map"
>
<Button type="outline" onPress={handleOpenMap} testID="button-open-map">
{loading.map ? trans.loadingText : trans.buttonOpenMap}
</Button>
)}
Expand Down
Loading

0 comments on commit d2bcff6

Please sign in to comment.