From 2736f57e73e057f15c306253c3e4c304f5bbf501 Mon Sep 17 00:00:00 2001
From: luandro
Date: Tue, 16 Mar 2021 20:10:06 -0300
Subject: [PATCH 01/22] feat: Add coordinate system page to settings with
ability to change between LatLon, UTM, DMS, DD
---
messages/en.json | 28 +++++
src/frontend/AppStack.js | 3 +
src/frontend/hooks/useCoordinateSystem.js | 39 +++++++
src/frontend/lib/utils.js | 69 ++++++++++--
.../screens/Settings/CoordinateSystem.js | 100 ++++++++++++++++++
src/frontend/screens/Settings/Settings.js | 20 ++++
6 files changed, 250 insertions(+), 9 deletions(-)
create mode 100644 src/frontend/hooks/useCoordinateSystem.js
create mode 100644 src/frontend/screens/Settings/CoordinateSystem.js
diff --git a/messages/en.json b/messages/en.json
index f2e16074b..3836829d3 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -58,6 +58,26 @@
"description": "Title for category chooser screen",
"message": "Choose what is happening"
},
+ "screens.CoordinateSystem.dd": {
+ "description": "Decimal Degrees coordinate system",
+ "message": "Decimal Degrees (DD)"
+ },
+ "screens.CoordinateSystem.dms": {
+ "description": "Degrees/Minutes/Seconds coordinate system",
+ "message": "Degrees/Minutes/Seconds (DMS)"
+ },
+ "screens.CoordinateSystem.latlong": {
+ "description": "Latitude and Longitude coordinate system",
+ "message": "Latitude and Longitude"
+ },
+ "screens.CoordinateSystem.title": {
+ "description": "Title coordinate system screen",
+ "message": "Coordinate System"
+ },
+ "screens.CoordinateSystem.utm": {
+ "description": "Universal Transverse Mercator coordinate system",
+ "message": "Universal Transverse Mercator (UTM)"
+ },
"screens.GpsModal.details": {
"description": "Section title for details about current position",
"message": "Details"
@@ -296,6 +316,14 @@
"description": "Title of error dialog when there is an error importing a config file",
"message": "Import Error"
},
+ "screens.Settings.coordinateSystem": {
+ "description": "Settings for coordinate systems",
+ "message": "Coordinate System"
+ },
+ "screens.Settings.coordinateSystemDesc": {
+ "description": "Description of the 'Coordinate System' page",
+ "message": "UTM, Lat/Long, DMS"
+ },
"screens.Settings.currentConfig": {
"description": "Label for name & version of current configuration",
"message": "Current Configuration"
diff --git a/src/frontend/AppStack.js b/src/frontend/AppStack.js
index a9924e86a..afb24e70e 100644
--- a/src/frontend/AppStack.js
+++ b/src/frontend/AppStack.js
@@ -21,6 +21,7 @@ import CustomHeaderLeft from "./sharedComponents/CustomHeaderLeft";
import ProjectConfig from "./screens/Settings/ProjectConfig";
import AboutMapeo from "./screens/Settings/AboutMapeo";
import LanguageSettings from "./screens/Settings/LanguageSettings";
+import CoordinateSystem from "./screens/Settings/CoordinateSystem";
import HomeHeader from "./sharedComponents/HomeHeader";
const HomeTabs = createBottomTabNavigator(
@@ -68,6 +69,8 @@ const AppStack = createStackNavigator(
// $FlowFixMe
LanguageSettings,
// $FlowFixMe
+ CoordinateSystem,
+ // $FlowFixMe
PhotosModal: PhotosModal,
// $FlowFixMe
CategoryChooser: CategoryChooser,
diff --git a/src/frontend/hooks/useCoordinateSystem.js b/src/frontend/hooks/useCoordinateSystem.js
new file mode 100644
index 000000000..87aa3bf21
--- /dev/null
+++ b/src/frontend/hooks/useCoordinateSystem.js
@@ -0,0 +1,39 @@
+import React from "react";
+import AsyncStorage from "@react-native-community/async-storage";
+
+const STORE_KEY = "@MapeoCoordinateSystem@2";
+const defaultValue = "utm";
+
+export default () => {
+ const [value, setLocalValue] = React.useState(defaultValue);
+ const [isLoading, setIsLoading] = React.useState(true);
+ const setValue = async value => {
+ setIsLoading(true);
+ await AsyncStorage.setItem(STORE_KEY, value);
+ setLocalValue(value);
+ setIsLoading(false);
+ };
+ React.useEffect(() => {
+ const getValue = async () => {
+ try {
+ setIsLoading(true);
+
+ const value = await AsyncStorage.getItem(STORE_KEY);
+
+ if (value === null) {
+ return setValue(defaultValue);
+ }
+
+ if (value !== null) {
+ setLocalValue(value);
+ }
+ } catch (e) {
+ setValue(defaultValue);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+ getValue();
+ }, []);
+ return [value, setValue, isLoading];
+};
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index 740ad9939..43c459401 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -121,15 +121,27 @@ export function getLastPhotoAttachment(
return filterPhotosFromAttachments(attachments).pop();
}
-export function formatCoords({
- lon,
- lat,
- format = "utm",
-}: {
- lon: number,
- lat: number,
- format?: "utm",
-}): string {
+// Coordinates conversions
+function toDegreesMinutesAndSeconds(coordinate) {
+ var absolute = Math.abs(coordinate);
+ var degrees = Math.floor(absolute);
+ var minutesNotTruncated = (absolute - degrees) * 60;
+ var minutes = Math.floor(minutesNotTruncated);
+ var seconds = Math.floor((minutesNotTruncated - minutes) * 60);
+
+ return `${degrees} ${minutes} ${seconds}`;
+}
+
+function convertToDMS(lat, lon) {
+ var latitude = toDegreesMinutesAndSeconds(lat);
+ var latitudeCardinal = lat >= 0 ? "N" : "S";
+
+ var longitude = toDegreesMinutesAndSeconds(lon);
+ var longitudeCardinal = lon >= 0 ? "E" : "W";
+ return `${latitude} ${latitudeCardinal} ${longitude} ${longitudeCardinal}`;
+}
+
+function convertToUTM(lat, lon) {
try {
let { easting, northing, zoneNum, zoneLetter } = fromLatLon(lat, lon);
easting = leftPad(easting.toFixed(), 6, "0");
@@ -143,6 +155,45 @@ export function formatCoords({
}
}
+function convertDMSToDD(degrees, minutes, seconds, direction) {
+ let dd = Number(degrees) + Number(minutes) / 60 + Number(seconds) / (60 * 60);
+ if (direction === "S" || direction === "W") {
+ dd = dd * -1;
+ } // Don't do anything for N or E
+ return dd;
+}
+
+function convertToDD(lat, lon) {
+ const [latD, latM, latS, latDi, lonD, lonM, lonS, lonDi] = convertToDMS(
+ lat,
+ lon
+ ).split(" ");
+ const latDD = convertDMSToDD(latD, latM, latS, latDi);
+ const lonDD = convertDMSToDD(lonD, lonM, lonS, lonDi);
+ return `${latDD} ${lonDD}`;
+}
+
+export function formatCoords({
+ lon,
+ lat,
+ format = "utm",
+}: {
+ lon: number,
+ lat: number,
+ format?: "utm",
+}): string {
+ switch (format) {
+ case "utm":
+ return convertToUTM(lat, lon);
+ case "dms":
+ return convertToDMS(lat, lon);
+ case "dd":
+ return convertToDD(lat, lon);
+ default:
+ return convertToUTM(lat, lon);
+ }
+}
+
export function getProp(tags: any, fieldKey: Key, defaultValue: any) {
// TODO: support deeply nested tags.
const shallowKey = Array.isArray(fieldKey) ? fieldKey[0] : fieldKey;
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
new file mode 100644
index 000000000..fd7f9cbe7
--- /dev/null
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -0,0 +1,100 @@
+// @flow
+import React from "react";
+import { ScrollView } from "react-native";
+import { FormattedMessage, defineMessages, useIntl } from "react-intl";
+
+import useCoodinateSystem from "../../hooks/useCoordinateSystem";
+import LocationContext from "../../context/LocationContext";
+import { formatCoords } from "../../lib/utils";
+
+import HeaderTitle from "../../sharedComponents/HeaderTitle";
+import Loading from "../../sharedComponents/Loading";
+import SelectOne from "./SelectOne";
+
+const m = defineMessages({
+ title: {
+ id: "screens.CoordinateSystem.title",
+ defaultMessage: "Coordinate System",
+ description: "Title coordinate system screen",
+ },
+ latlong: {
+ id: "screens.CoordinateSystem.latlong",
+ defaultMessage: "Latitude and Longitude",
+ description: "Latitude and Longitude coordinate system",
+ },
+ dms: {
+ id: "screens.CoordinateSystem.dms",
+ defaultMessage: "Degrees/Minutes/Seconds (DMS)",
+ description: "Degrees/Minutes/Seconds coordinate system",
+ },
+ utm: {
+ id: "screens.CoordinateSystem.utm",
+ defaultMessage: "Universal Transverse Mercator (UTM)",
+ description: "Universal Transverse Mercator coordinate system",
+ },
+ dd: {
+ id: "screens.CoordinateSystem.dd",
+ defaultMessage: "Decimal Degrees (DD)",
+ description: "Decimal Degrees coordinate system",
+ },
+});
+
+const CoordinateSystem = () => {
+ const intl = useIntl();
+ const location = React.useContext(LocationContext);
+ const [system, setSystem] = useCoodinateSystem();
+ if (!location) return ;
+ else {
+ const { latitude = 0, longitude = 0 } = location.position.coords;
+ const options = [
+ {
+ value: "latlong",
+ label: intl.formatMessage({ ...m.latlong }),
+ hint: `${latitude} ${longitude}`,
+ },
+ {
+ value: "dms",
+ label: intl.formatMessage({ ...m.dms }),
+ hint: formatCoords({
+ lon: longitude,
+ lat: latitude,
+ format: "dms",
+ }),
+ },
+ {
+ value: "utm",
+ label: intl.formatMessage({ ...m.utm }),
+ hint: formatCoords({
+ lon: longitude,
+ lat: latitude,
+ format: "utm",
+ }),
+ },
+ {
+ value: "dd",
+ label: intl.formatMessage({ ...m.dd }),
+ hint: formatCoords({
+ lon: longitude,
+ lat: latitude,
+ format: "dd",
+ }),
+ },
+ ];
+
+ return (
+
+
+
+ );
+ }
+};
+
+CoordinateSystem.navigationOptions = {
+ headerTitle: () => (
+
+
+
+ ),
+};
+
+export default CoordinateSystem;
diff --git a/src/frontend/screens/Settings/Settings.js b/src/frontend/screens/Settings/Settings.js
index a02bf0e0a..61cac45db 100644
--- a/src/frontend/screens/Settings/Settings.js
+++ b/src/frontend/screens/Settings/Settings.js
@@ -48,6 +48,16 @@ const m = defineMessages({
defaultMessage: "Version and build number",
description: "Description of the 'About Mapeo' page",
},
+ coordinateSystem: {
+ id: "screens.Settings.coordinateSystem",
+ defaultMessage: "Coordinate System",
+ description: "Settings for coordinate systems",
+ },
+ coordinateSystemDesc: {
+ id: "screens.Settings.coordinateSystemDesc",
+ defaultMessage: "UTM, Lat/Long, DMS, DD",
+ description: "Description of the 'Coordinate System' page",
+ },
});
const Settings = () => {
@@ -84,6 +94,16 @@ const Settings = () => {
secondary={}
>
+ navigate("CoordinateSystem")}
+ testID="settingsCoodinatesButton"
+ >
+
+ }
+ secondary={}
+ >
+
);
};
From cf4be4fa217cd7ab4ad45de012b016548ba0b7a7 Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 17 Mar 2021 08:32:34 -0300
Subject: [PATCH 02/22] fix: Add latlon to formatCoords switch
---
src/frontend/lib/utils.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index 43c459401..4e71a8d22 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -183,6 +183,8 @@ export function formatCoords({
format?: "utm",
}): string {
switch (format) {
+ case "latlon":
+ return `${lat} ${lon}`;
case "utm":
return convertToUTM(lat, lon);
case "dms":
From 81953d003d8fa1406abede67c111a9f626cb4b8e Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 17 Mar 2021 08:41:27 -0300
Subject: [PATCH 03/22] feat: Add information on GpsModal based on selected
coordinate system
---
messages/en.json | 16 +++++++-
src/frontend/screens/GpsModal.js | 37 +++++++++++++++++--
.../screens/Settings/CoordinateSystem.js | 8 ++--
.../sharedComponents/FormattedData.js | 12 +++++-
4 files changed, 62 insertions(+), 11 deletions(-)
diff --git a/messages/en.json b/messages/en.json
index 3836829d3..461187405 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -66,7 +66,7 @@
"description": "Degrees/Minutes/Seconds coordinate system",
"message": "Degrees/Minutes/Seconds (DMS)"
},
- "screens.CoordinateSystem.latlong": {
+ "screens.CoordinateSystem.latlon": {
"description": "Latitude and Longitude coordinate system",
"message": "Latitude and Longitude"
},
@@ -90,6 +90,18 @@
"description": "Section title for time of last GPS update",
"message": "Last update"
},
+ "screens.GpsModal.locationDD": {
+ "description": "Section title for DD coordinates",
+ "message": "Coordinates Decimal Degrees"
+ },
+ "screens.GpsModal.locationDMS": {
+ "description": "Section title for DMS coordinates",
+ "message": "Coordinates DMS"
+ },
+ "screens.GpsModal.locationLatLon": {
+ "description": "Section title for latitude and longitude coordinates",
+ "message": "Coordinates Latitude and Longitude"
+ },
"screens.GpsModal.locationSensors": {
"description": "Heading for section about location sensor status",
"message": "Sensor Status"
@@ -322,7 +334,7 @@
},
"screens.Settings.coordinateSystemDesc": {
"description": "Description of the 'Coordinate System' page",
- "message": "UTM, Lat/Long, DMS"
+ "message": "UTM, Lat/Long, DMS, DD"
},
"screens.Settings.currentConfig": {
"description": "Label for name & version of current configuration",
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index 21bfe3d23..2ff1e5198 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -5,6 +5,8 @@ import Text from "../sharedComponents/Text";
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
import LocationContext from "../context/LocationContext";
+import useCoodinateSystem from "../hooks/useCoordinateSystem";
+
import { FormattedCoords } from "../sharedComponents/FormattedData";
import DateDistance from "../sharedComponents/DateDistance";
import HeaderTitle from "../sharedComponents/HeaderTitle";
@@ -27,6 +29,21 @@ const m = defineMessages({
defaultMessage: "Coordinates UTM",
description: "Section title for UTM coordinates",
},
+ locationLatLon: {
+ id: "screens.GpsModal.locationLatLon",
+ defaultMessage: "Coordinates Latitude and Longitude",
+ description: "Section title for latitude and longitude coordinates",
+ },
+ locationDMS: {
+ id: "screens.GpsModal.locationDMS",
+ defaultMessage: "Coordinates DMS",
+ description: "Section title for DMS coordinates",
+ },
+ locationDD: {
+ id: "screens.GpsModal.locationDD",
+ defaultMessage: "Coordinates Decimal Degrees",
+ description: "Section title for DD coordinates",
+ },
details: {
id: "screens.GpsModal.details",
defaultMessage: "Details",
@@ -63,6 +80,21 @@ type Props = {
const GpsModal = ({ navigation }: Props) => {
const location = React.useContext(LocationContext);
const { formatMessage: t } = useIntl();
+ const [system] = useCoodinateSystem();
+ const coordinateMessage = () => {
+ switch (system) {
+ case "latlon":
+ return ;
+ case "utm":
+ return ;
+ case "dms":
+ return ;
+ case "dd":
+ return ;
+ default:
+ return ;
+ }
+ };
return (
@@ -76,13 +108,12 @@ const GpsModal = ({ navigation }: Props) => {
/>
{location.position && (
<>
-
-
-
+ {coordinateMessage()}
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index fd7f9cbe7..9b3d01f22 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -17,8 +17,8 @@ const m = defineMessages({
defaultMessage: "Coordinate System",
description: "Title coordinate system screen",
},
- latlong: {
- id: "screens.CoordinateSystem.latlong",
+ latlon: {
+ id: "screens.CoordinateSystem.latlon",
defaultMessage: "Latitude and Longitude",
description: "Latitude and Longitude coordinate system",
},
@@ -48,8 +48,8 @@ const CoordinateSystem = () => {
const { latitude = 0, longitude = 0 } = location.position.coords;
const options = [
{
- value: "latlong",
- label: intl.formatMessage({ ...m.latlong }),
+ value: "latlon",
+ label: intl.formatMessage({ ...m.latlon }),
hint: `${latitude} ${longitude}`,
},
{
diff --git a/src/frontend/sharedComponents/FormattedData.js b/src/frontend/sharedComponents/FormattedData.js
index 0213c99cc..7d92cfb49 100644
--- a/src/frontend/sharedComponents/FormattedData.js
+++ b/src/frontend/sharedComponents/FormattedData.js
@@ -29,8 +29,16 @@ const m = defineMessages({
// pattern of the other components in this file (which take a Field, Observation
// or Preset as a prop) because it is also used in contexts other than
// observation coords, e.g. for displaying current GPS coords.
-export const FormattedCoords = ({ lat, lon }: { lat: number, lon: number }) => {
- return <>{formatCoords({ lon, lat })}>;
+export const FormattedCoords = ({
+ lat,
+ lon,
+ format,
+}: {
+ lat: number,
+ lon: number,
+ format: string,
+}) => {
+ return <>{formatCoords({ lon, lat, format })}>;
};
// Render the translated value of a translatable Field property (one of
From 330c8823a54bb5df0dcf3915eac119c407ce8800 Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 17 Mar 2021 09:04:26 -0300
Subject: [PATCH 04/22] feat: Show coordinates on observation screens based on
selected system
---
src/frontend/screens/Observation/ObservationShare.js | 4 +++-
src/frontend/screens/Observation/ObservationView.js | 4 +++-
src/frontend/screens/ObservationEdit/ObservationEditView.js | 4 +++-
src/frontend/sharedComponents/LocationField.js | 3 +++
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/frontend/screens/Observation/ObservationShare.js b/src/frontend/screens/Observation/ObservationShare.js
index fbaf0f5f5..35d5d2f69 100644
--- a/src/frontend/screens/Observation/ObservationShare.js
+++ b/src/frontend/screens/Observation/ObservationShare.js
@@ -15,6 +15,7 @@ import {
import { getProp } from "../../lib/utils";
import type { PresetWithFields } from "../../context/ConfigContext";
import type { Observation } from "../../context/ObservationsContext";
+import useCoodinateSystem from "../../hooks/useCoordinateSystem";
const m = defineMessages({
alertSubject: {
@@ -52,6 +53,7 @@ export const ShareSubject = ({ observation, preset }: ShareMessageProps) => {
export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
const { formatMessage: t } = useIntl();
+ const [system] = useCoodinateSystem();
const { value } = observation;
const { lon, lat } = value;
@@ -81,7 +83,7 @@ export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
{lon != null && lat != null ? (
-
+
) : null}
{value.tags.notes ? {value.tags.notes}
: null}
diff --git a/src/frontend/screens/Observation/ObservationView.js b/src/frontend/screens/Observation/ObservationView.js
index 84d833b5d..c44ef16dc 100644
--- a/src/frontend/screens/Observation/ObservationView.js
+++ b/src/frontend/screens/Observation/ObservationView.js
@@ -33,6 +33,7 @@ import type { PresetWithFields } from "../../context/ConfigContext";
import type { Observation } from "../../context/ObservationsContext";
import useMapStyle from "../../hooks/useMapStyle";
import useDeviceId from "../../hooks/useDeviceId";
+import useCoodinateSystem from "../../hooks/useCoordinateSystem";
import Loading from "../../sharedComponents/Loading";
import OfflineMapLayers from "../../sharedComponents/OfflineMapLayers";
import { ShareMessage, ShareSubject, renderToString } from "./ObservationShare";
@@ -125,6 +126,7 @@ const ObservationView = ({
onPressDelete,
}: ODVProps) => {
const intl = useIntl();
+ const [system] = useCoodinateSystem();
const { formatMessage: t } = intl;
const deviceId = useDeviceId();
const isMine = deviceId === observation.value.deviceId;
@@ -173,7 +175,7 @@ const ObservationView = ({
-
+
diff --git a/src/frontend/screens/ObservationEdit/ObservationEditView.js b/src/frontend/screens/ObservationEdit/ObservationEditView.js
index e227e97cc..d96c57db8 100644
--- a/src/frontend/screens/ObservationEdit/ObservationEditView.js
+++ b/src/frontend/screens/ObservationEdit/ObservationEditView.js
@@ -55,10 +55,12 @@ const m = defineMessages({
const LocationView = ({
longitude,
latitude,
+ system,
accuracy,
}: {
longitude?: number | null,
latitude?: number | null,
+ system?: string,
accuracy?: number,
}) => (
@@ -75,7 +77,7 @@ const LocationView = ({
style={{ marginRight: 5 }}
/>
-
+
{accuracy === undefined ? null : (
diff --git a/src/frontend/sharedComponents/LocationField.js b/src/frontend/sharedComponents/LocationField.js
index 1ed7802fe..2a866339d 100644
--- a/src/frontend/sharedComponents/LocationField.js
+++ b/src/frontend/sharedComponents/LocationField.js
@@ -3,6 +3,7 @@ import * as React from "react";
import omit from "lodash/omit";
import useDraftObservation from "../hooks/useDraftObservation";
+import useCoodinateSystem from "../hooks/useCoordinateSystem";
import LocationContext from "../context/LocationContext";
type Props = {
@@ -25,6 +26,7 @@ type Props = {
const LocationField = ({ children }: Props) => {
const [{ value }, { updateDraft }] = useDraftObservation();
const location = React.useContext(LocationContext);
+ const [system] = useCoodinateSystem();
React.useEffect(() => {
if (!location.position || !value) return;
@@ -55,6 +57,7 @@ const LocationField = ({ children }: Props) => {
return children({
longitude: value.lon,
latitude: value.lat,
+ system,
accuracy:
value.metadata &&
value.metadata.location &&
From 32fbe0a6ca49bf9a9111562a9304014401bf7ad7 Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 17 Mar 2021 09:13:14 -0300
Subject: [PATCH 05/22] fix: Add value check before setting AsyncStorage
---
src/frontend/hooks/useCoordinateSystem.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/frontend/hooks/useCoordinateSystem.js b/src/frontend/hooks/useCoordinateSystem.js
index 87aa3bf21..8e96c21ab 100644
--- a/src/frontend/hooks/useCoordinateSystem.js
+++ b/src/frontend/hooks/useCoordinateSystem.js
@@ -8,10 +8,12 @@ export default () => {
const [value, setLocalValue] = React.useState(defaultValue);
const [isLoading, setIsLoading] = React.useState(true);
const setValue = async value => {
- setIsLoading(true);
- await AsyncStorage.setItem(STORE_KEY, value);
- setLocalValue(value);
- setIsLoading(false);
+ if (value) {
+ setIsLoading(true);
+ await AsyncStorage.setItem(STORE_KEY, value);
+ setLocalValue(value);
+ setIsLoading(false);
+ }
};
React.useEffect(() => {
const getValue = async () => {
From 2c07212c1548715289acf8c59569390386c19f0e Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 24 Mar 2021 18:06:51 -0300
Subject: [PATCH 06/22] fix: Have Coordinate System before About Mapeo on
configuration menu
---
src/frontend/screens/Settings/Settings.js | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/frontend/screens/Settings/Settings.js b/src/frontend/screens/Settings/Settings.js
index 61cac45db..3548d21ed 100644
--- a/src/frontend/screens/Settings/Settings.js
+++ b/src/frontend/screens/Settings/Settings.js
@@ -84,16 +84,6 @@ const Settings = () => {
secondary={}
>
- navigate("AboutMapeo")}
- testID="settingsAboutButton"
- >
-
- }
- secondary={}
- >
-
navigate("CoordinateSystem")}
testID="settingsCoodinatesButton"
@@ -104,6 +94,16 @@ const Settings = () => {
secondary={}
>
+ navigate("AboutMapeo")}
+ testID="settingsAboutButton"
+ >
+
+ }
+ secondary={}
+ >
+
);
};
From f8530301e3d1e8c3e6e1689cb8e5f3fc9bc7fdf5 Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 24 Mar 2021 18:46:01 -0300
Subject: [PATCH 07/22] fix: Remove Decimal Degrees which is same as Lat Long
---
messages/en.json | 6 +-----
src/frontend/lib/utils.js | 2 --
src/frontend/screens/GpsModal.js | 2 --
src/frontend/screens/Settings/CoordinateSystem.js | 11 +----------
src/frontend/screens/Settings/Settings.js | 2 +-
5 files changed, 3 insertions(+), 20 deletions(-)
diff --git a/messages/en.json b/messages/en.json
index 461187405..06ad259ee 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -58,10 +58,6 @@
"description": "Title for category chooser screen",
"message": "Choose what is happening"
},
- "screens.CoordinateSystem.dd": {
- "description": "Decimal Degrees coordinate system",
- "message": "Decimal Degrees (DD)"
- },
"screens.CoordinateSystem.dms": {
"description": "Degrees/Minutes/Seconds coordinate system",
"message": "Degrees/Minutes/Seconds (DMS)"
@@ -334,7 +330,7 @@
},
"screens.Settings.coordinateSystemDesc": {
"description": "Description of the 'Coordinate System' page",
- "message": "UTM, Lat/Long, DMS, DD"
+ "message": "UTM, Lat/Long, DMS"
},
"screens.Settings.currentConfig": {
"description": "Label for name & version of current configuration",
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index 4e71a8d22..ec25df645 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -189,8 +189,6 @@ export function formatCoords({
return convertToUTM(lat, lon);
case "dms":
return convertToDMS(lat, lon);
- case "dd":
- return convertToDD(lat, lon);
default:
return convertToUTM(lat, lon);
}
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index 2ff1e5198..60fe006f0 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -89,8 +89,6 @@ const GpsModal = ({ navigation }: Props) => {
return ;
case "dms":
return ;
- case "dd":
- return ;
default:
return ;
}
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index 9b3d01f22..6af8642b7 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -69,16 +69,7 @@ const CoordinateSystem = () => {
lat: latitude,
format: "utm",
}),
- },
- {
- value: "dd",
- label: intl.formatMessage({ ...m.dd }),
- hint: formatCoords({
- lon: longitude,
- lat: latitude,
- format: "dd",
- }),
- },
+ }
];
return (
diff --git a/src/frontend/screens/Settings/Settings.js b/src/frontend/screens/Settings/Settings.js
index 3548d21ed..e6f0a7c6f 100644
--- a/src/frontend/screens/Settings/Settings.js
+++ b/src/frontend/screens/Settings/Settings.js
@@ -55,7 +55,7 @@ const m = defineMessages({
},
coordinateSystemDesc: {
id: "screens.Settings.coordinateSystemDesc",
- defaultMessage: "UTM, Lat/Long, DMS, DD",
+ defaultMessage: "UTM, Lat/Long, DMS",
description: "Description of the 'Coordinate System' page",
},
});
From 873a6b59deb8b8d76b73bc9a109ee316d2bbfe6b Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 24 Mar 2021 18:50:11 -0300
Subject: [PATCH 08/22] fix: Round decimal degrees to 6 decimal places
---
src/frontend/lib/utils.js | 27 ++++++++++-----------------
1 file changed, 10 insertions(+), 17 deletions(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index ec25df645..e44f851e2 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -155,22 +155,15 @@ function convertToUTM(lat, lon) {
}
}
-function convertDMSToDD(degrees, minutes, seconds, direction) {
- let dd = Number(degrees) + Number(minutes) / 60 + Number(seconds) / (60 * 60);
- if (direction === "S" || direction === "W") {
- dd = dd * -1;
- } // Don't do anything for N or E
- return dd;
-}
-
-function convertToDD(lat, lon) {
- const [latD, latM, latS, latDi, lonD, lonM, lonS, lonDi] = convertToDMS(
- lat,
- lon
- ).split(" ");
- const latDD = convertDMSToDD(latD, latM, latS, latDi);
- const lonDD = convertDMSToDD(lonD, lonM, lonS, lonDi);
- return `${latDD} ${lonDD}`;
+function formatLatLong(lat, lon) {
+ const decimals = 6;
+ const formattedLat = Number(
+ Math.round(lat + "e" + decimals) + "e-" + decimals
+ );
+ const formattedLon = Number(
+ Math.round(lon + "e" + decimals) + "e-" + decimals
+ );
+ return `${formattedLat} ${formattedLon}`;
}
export function formatCoords({
@@ -184,7 +177,7 @@ export function formatCoords({
}): string {
switch (format) {
case "latlon":
- return `${lat} ${lon}`;
+ return formatLatLong(lat, lon);
case "utm":
return convertToUTM(lat, lon);
case "dms":
From 48e815b2ccbe7afa956494d070a8bcb8445cd7e1 Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 24 Mar 2021 18:57:45 -0300
Subject: [PATCH 09/22] chore: Cleanup and add better formating for DMS
---
src/frontend/hooks/useCoordinateSystem.js | 3 ---
src/frontend/lib/utils.js | 2 +-
src/frontend/screens/Settings/CoordinateSystem.js | 9 ++-------
3 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/src/frontend/hooks/useCoordinateSystem.js b/src/frontend/hooks/useCoordinateSystem.js
index 8e96c21ab..5cef89658 100644
--- a/src/frontend/hooks/useCoordinateSystem.js
+++ b/src/frontend/hooks/useCoordinateSystem.js
@@ -19,13 +19,10 @@ export default () => {
const getValue = async () => {
try {
setIsLoading(true);
-
const value = await AsyncStorage.getItem(STORE_KEY);
-
if (value === null) {
return setValue(defaultValue);
}
-
if (value !== null) {
setLocalValue(value);
}
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index e44f851e2..fb784a4e6 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -129,7 +129,7 @@ function toDegreesMinutesAndSeconds(coordinate) {
var minutes = Math.floor(minutesNotTruncated);
var seconds = Math.floor((minutesNotTruncated - minutes) * 60);
- return `${degrees} ${minutes} ${seconds}`;
+ return `${degrees}° ${minutes}' ${seconds}"`;
}
function convertToDMS(lat, lon) {
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index 6af8642b7..fc4324c93 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -32,18 +32,13 @@ const m = defineMessages({
defaultMessage: "Universal Transverse Mercator (UTM)",
description: "Universal Transverse Mercator coordinate system",
},
- dd: {
- id: "screens.CoordinateSystem.dd",
- defaultMessage: "Decimal Degrees (DD)",
- description: "Decimal Degrees coordinate system",
- },
});
const CoordinateSystem = () => {
const intl = useIntl();
const location = React.useContext(LocationContext);
const [system, setSystem] = useCoodinateSystem();
- if (!location) return ;
+ if (!location || !location.position) return ;
else {
const { latitude = 0, longitude = 0 } = location.position.coords;
const options = [
@@ -69,7 +64,7 @@ const CoordinateSystem = () => {
lat: latitude,
format: "utm",
}),
- }
+ },
];
return (
From 930346b115769f23aff95148a496819cc296d15c Mon Sep 17 00:00:00 2001
From: luandro
Date: Wed, 24 Mar 2021 19:16:03 -0300
Subject: [PATCH 10/22] fix: Add 3 decimal degrees to DMS coordinates
---
src/frontend/lib/utils.js | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index fb784a4e6..06efcc24b 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -123,21 +123,24 @@ export function getLastPhotoAttachment(
// Coordinates conversions
function toDegreesMinutesAndSeconds(coordinate) {
- var absolute = Math.abs(coordinate);
- var degrees = Math.floor(absolute);
- var minutesNotTruncated = (absolute - degrees) * 60;
- var minutes = Math.floor(minutesNotTruncated);
- var seconds = Math.floor((minutesNotTruncated - minutes) * 60);
-
- return `${degrees}° ${minutes}' ${seconds}"`;
+ const absolute = Math.abs(coordinate);
+ const degrees = Math.floor(absolute);
+ const minutesNotTruncated = (absolute - degrees) * 60;
+ const minutes = Math.floor(minutesNotTruncated);
+ const seconds = (minutesNotTruncated - minutes) * 60;
+ const decimals = 3;
+ const formattedSeconds = Number(
+ Math.round(seconds + "e" + decimals) + "e-" + decimals
+ );
+ return `${degrees}° ${minutes}' ${formattedSeconds}"`;
}
function convertToDMS(lat, lon) {
- var latitude = toDegreesMinutesAndSeconds(lat);
- var latitudeCardinal = lat >= 0 ? "N" : "S";
+ const latitude = toDegreesMinutesAndSeconds(lat);
+ const latitudeCardinal = lat >= 0 ? "N" : "S";
- var longitude = toDegreesMinutesAndSeconds(lon);
- var longitudeCardinal = lon >= 0 ? "E" : "W";
+ const longitude = toDegreesMinutesAndSeconds(lon);
+ const longitudeCardinal = lon >= 0 ? "E" : "W";
return `${latitude} ${latitudeCardinal} ${longitude} ${longitudeCardinal}`;
}
From 70b3d1c40133c121cd44d77f63df071f92b3892a Mon Sep 17 00:00:00 2001
From: luandro
Date: Fri, 26 Mar 2021 14:44:13 -0300
Subject: [PATCH 11/22] fix: Pass lat/lon explicitly within an object on
formatting functions
---
src/frontend/lib/utils.js | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index 06efcc24b..e61f5bea2 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -135,7 +135,7 @@ function toDegreesMinutesAndSeconds(coordinate) {
return `${degrees}° ${minutes}' ${formattedSeconds}"`;
}
-function convertToDMS(lat, lon) {
+function convertToDMS({ lat, lon }) {
const latitude = toDegreesMinutesAndSeconds(lat);
const latitudeCardinal = lat >= 0 ? "N" : "S";
@@ -144,7 +144,7 @@ function convertToDMS(lat, lon) {
return `${latitude} ${latitudeCardinal} ${longitude} ${longitudeCardinal}`;
}
-function convertToUTM(lat, lon) {
+function convertToUTM({ lat, lon }) {
try {
let { easting, northing, zoneNum, zoneLetter } = fromLatLon(lat, lon);
easting = leftPad(easting.toFixed(), 6, "0");
@@ -158,7 +158,7 @@ function convertToUTM(lat, lon) {
}
}
-function formatLatLong(lat, lon) {
+function formatDD({ lat, lon }) {
const decimals = 6;
const formattedLat = Number(
Math.round(lat + "e" + decimals) + "e-" + decimals
@@ -176,17 +176,17 @@ export function formatCoords({
}: {
lon: number,
lat: number,
- format?: "utm",
+ format?: "utm" | "dd" | "dms",
}): string {
switch (format) {
- case "latlon":
- return formatLatLong(lat, lon);
+ case "dd":
+ return formatDD({ lat, lon });
case "utm":
- return convertToUTM(lat, lon);
+ return convertToUTM({ lat, lon });
case "dms":
- return convertToDMS(lat, lon);
+ return convertToDMS({ lat, lon });
default:
- return convertToUTM(lat, lon);
+ return convertToUTM({ lat, lon });
}
}
From 31c127a8ac34ce02ddc513bcd46081566345c158 Mon Sep 17 00:00:00 2001
From: luandro
Date: Fri, 26 Mar 2021 15:06:52 -0300
Subject: [PATCH 12/22] fix: Use Decimal Degrees naming instead of lat/lon
---
src/frontend/lib/utils.js | 2 +-
src/frontend/screens/GpsModal.js | 4 ++--
.../screens/Settings/CoordinateSystem.js | 18 +++++++++++-------
src/frontend/screens/Settings/Settings.js | 2 +-
4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index e61f5bea2..cde3a3446 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -166,7 +166,7 @@ function formatDD({ lat, lon }) {
const formattedLon = Number(
Math.round(lon + "e" + decimals) + "e-" + decimals
);
- return `${formattedLat} ${formattedLon}`;
+ return `lat ${formattedLat} lon ${formattedLon}`;
}
export function formatCoords({
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index 60fe006f0..1c42defda 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -83,8 +83,8 @@ const GpsModal = ({ navigation }: Props) => {
const [system] = useCoodinateSystem();
const coordinateMessage = () => {
switch (system) {
- case "latlon":
- return ;
+ case "dd":
+ return ;
case "utm":
return ;
case "dms":
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index fc4324c93..b4ae94537 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -17,10 +17,10 @@ const m = defineMessages({
defaultMessage: "Coordinate System",
description: "Title coordinate system screen",
},
- latlon: {
- id: "screens.CoordinateSystem.latlon",
- defaultMessage: "Latitude and Longitude",
- description: "Latitude and Longitude coordinate system",
+ dd: {
+ id: "screens.CoordinateSystem.dd",
+ defaultMessage: "Decimal Degrees",
+ description: "Decimal Degrees coordinate system",
},
dms: {
id: "screens.CoordinateSystem.dms",
@@ -43,9 +43,13 @@ const CoordinateSystem = () => {
const { latitude = 0, longitude = 0 } = location.position.coords;
const options = [
{
- value: "latlon",
- label: intl.formatMessage({ ...m.latlon }),
- hint: `${latitude} ${longitude}`,
+ value: "dd",
+ label: intl.formatMessage({ ...m.dd }),
+ hint: formatCoords({
+ lon: longitude,
+ lat: latitude,
+ format: "dd",
+ }),
},
{
value: "dms",
diff --git a/src/frontend/screens/Settings/Settings.js b/src/frontend/screens/Settings/Settings.js
index e6f0a7c6f..28a0a5e2a 100644
--- a/src/frontend/screens/Settings/Settings.js
+++ b/src/frontend/screens/Settings/Settings.js
@@ -55,7 +55,7 @@ const m = defineMessages({
},
coordinateSystemDesc: {
id: "screens.Settings.coordinateSystemDesc",
- defaultMessage: "UTM, Lat/Long, DMS",
+ defaultMessage: "DD, UTM, DMS",
description: "Description of the 'Coordinate System' page",
},
});
From 72fa39ebebc6e44ccfac1a860502198ecc189bea Mon Sep 17 00:00:00 2001
From: luandro
Date: Fri, 26 Mar 2021 15:13:18 -0300
Subject: [PATCH 13/22] chore: Extract messages and add DD to naming in config
menu
---
messages/en.json | 10 +++++-----
src/frontend/screens/Settings/CoordinateSystem.js | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/messages/en.json b/messages/en.json
index 06ad259ee..aac8e7845 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -58,14 +58,14 @@
"description": "Title for category chooser screen",
"message": "Choose what is happening"
},
+ "screens.CoordinateSystem.dd": {
+ "description": "Decimal Degrees coordinate system",
+ "message": "Decimal Degrees (DD)"
+ },
"screens.CoordinateSystem.dms": {
"description": "Degrees/Minutes/Seconds coordinate system",
"message": "Degrees/Minutes/Seconds (DMS)"
},
- "screens.CoordinateSystem.latlon": {
- "description": "Latitude and Longitude coordinate system",
- "message": "Latitude and Longitude"
- },
"screens.CoordinateSystem.title": {
"description": "Title coordinate system screen",
"message": "Coordinate System"
@@ -330,7 +330,7 @@
},
"screens.Settings.coordinateSystemDesc": {
"description": "Description of the 'Coordinate System' page",
- "message": "UTM, Lat/Long, DMS"
+ "message": "DD, UTM, DMS"
},
"screens.Settings.currentConfig": {
"description": "Label for name & version of current configuration",
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index b4ae94537..52f8cf268 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -19,7 +19,7 @@ const m = defineMessages({
},
dd: {
id: "screens.CoordinateSystem.dd",
- defaultMessage: "Decimal Degrees",
+ defaultMessage: "Decimal Degrees (DD)",
description: "Decimal Degrees coordinate system",
},
dms: {
From e4ee80d66e96ef146b6f55e86b86cf594e18a943 Mon Sep 17 00:00:00 2001
From: luandro
Date: Thu, 1 Apr 2021 10:19:25 -0300
Subject: [PATCH 14/22] chore: Add settings context
---
src/frontend/context/SettingsContext.js | 84 +++++++++++++++++++++++++
1 file changed, 84 insertions(+)
create mode 100644 src/frontend/context/SettingsContext.js
diff --git a/src/frontend/context/SettingsContext.js b/src/frontend/context/SettingsContext.js
new file mode 100644
index 000000000..085250b8a
--- /dev/null
+++ b/src/frontend/context/SettingsContext.js
@@ -0,0 +1,84 @@
+// @flow
+import * as React from "react";
+import AsyncStorage from "@react-native-community/async-storage";
+
+const STORE_KEY = "@MapeoSettings@36";
+
+export type SettingsContextType = {
+ coordinateSystem?: string,
+};
+
+const initialState = {
+ coordinateSystem: "utm",
+};
+
+const defaultContext = [initialState, () => {}];
+const SettingsContext = React.createContext(defaultContext);
+
+function reducer(state: State, action: Action): State {
+ switch (action.type) {
+ case "set": {
+ return action.value;
+ }
+ case "set_coordinate_system": {
+ try {
+ return { ...state, coordinateSystem: action.value };
+ } catch {
+ return state;
+ }
+ }
+ default:
+ return state;
+ }
+}
+
+const getData = async dispatch => {
+ try {
+ // AsyncStorage.clear()
+ const state = await AsyncStorage.getItem(STORE_KEY);
+ if (state) {
+ const parsedState = JSON.parse(state);
+ dispatch({ type: "set", value: parsedState });
+ return parsedState;
+ } else return initialState;
+ } catch (e) {
+ console.log("Failed to fetch the data from storage");
+ return initialState;
+ }
+};
+
+const saveData = async value => {
+ try {
+ const stringified = JSON.stringify(value);
+ await AsyncStorage.setItem(STORE_KEY, stringified);
+ return value;
+ } catch (e) {
+ console.log("Failed to save the data to the storage");
+ }
+};
+
+export const SettingsProvider = ({ children }: { children: React.Node }) => {
+ const didMountRef = React.useRef(false);
+ const [state, dispatch] = React.useReducer(reducer, defaultContext[0]);
+ const contextValue = React.useMemo(() => [state, dispatch], [
+ state,
+ dispatch,
+ ]);
+ React.useEffect(() => {
+ if (didMountRef.current) {
+ saveData(contextValue[0]);
+ } else {
+ didMountRef.current = true;
+ getData(dispatch);
+ }
+ }, [contextValue]);
+ return (
+
+ {children}
+
+ );
+};
+
+export default SettingsContext;
From 4caa86245e7e6a314a1ca27aec7fe92c1e3ff2df Mon Sep 17 00:00:00 2001
From: luandro
Date: Thu, 1 Apr 2021 10:22:05 -0300
Subject: [PATCH 15/22] chore: Update screens and components to use settings
context
---
src/frontend/context/AppProvider.js | 5 ++-
src/frontend/hooks/useCoordinateSystem.js | 38 -------------------
src/frontend/screens/GpsModal.js | 10 +++--
.../screens/Observation/ObservationShare.js | 9 +++--
.../screens/Observation/ObservationView.js | 12 ++++--
.../screens/Settings/CoordinateSystem.js | 11 ++++--
.../sharedComponents/LocationField.js | 9 +++--
7 files changed, 38 insertions(+), 56 deletions(-)
delete mode 100644 src/frontend/hooks/useCoordinateSystem.js
diff --git a/src/frontend/context/AppProvider.js b/src/frontend/context/AppProvider.js
index c69d38480..a30172e31 100644
--- a/src/frontend/context/AppProvider.js
+++ b/src/frontend/context/AppProvider.js
@@ -4,6 +4,7 @@ import * as React from "react";
import { LocationProvider } from "./LocationContext";
import { ObservationsProvider } from "./ObservationsContext";
import { ConfigProvider } from "./ConfigContext";
+import { SettingsProvider } from "./SettingsContext";
import { DraftObservationProvider } from "./DraftObservationContext";
// This is a convenience wrapper for providing all App contexts to the tree,
@@ -12,7 +13,9 @@ const AppProvider = ({ children }: { children: React.Node }) => (
- {children}
+
+ {children}
+
diff --git a/src/frontend/hooks/useCoordinateSystem.js b/src/frontend/hooks/useCoordinateSystem.js
deleted file mode 100644
index 5cef89658..000000000
--- a/src/frontend/hooks/useCoordinateSystem.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from "react";
-import AsyncStorage from "@react-native-community/async-storage";
-
-const STORE_KEY = "@MapeoCoordinateSystem@2";
-const defaultValue = "utm";
-
-export default () => {
- const [value, setLocalValue] = React.useState(defaultValue);
- const [isLoading, setIsLoading] = React.useState(true);
- const setValue = async value => {
- if (value) {
- setIsLoading(true);
- await AsyncStorage.setItem(STORE_KEY, value);
- setLocalValue(value);
- setIsLoading(false);
- }
- };
- React.useEffect(() => {
- const getValue = async () => {
- try {
- setIsLoading(true);
- const value = await AsyncStorage.getItem(STORE_KEY);
- if (value === null) {
- return setValue(defaultValue);
- }
- if (value !== null) {
- setLocalValue(value);
- }
- } catch (e) {
- setValue(defaultValue);
- } finally {
- setIsLoading(false);
- }
- };
- getValue();
- }, []);
- return [value, setValue, isLoading];
-};
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index 1c42defda..d34d4f939 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -5,7 +5,7 @@ import Text from "../sharedComponents/Text";
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
import LocationContext from "../context/LocationContext";
-import useCoodinateSystem from "../hooks/useCoordinateSystem";
+import SettingsContext from "../context/SettingsContext";
import { FormattedCoords } from "../sharedComponents/FormattedData";
import DateDistance from "../sharedComponents/DateDistance";
@@ -79,10 +79,12 @@ type Props = {
const GpsModal = ({ navigation }: Props) => {
const location = React.useContext(LocationContext);
+ const {
+ settings: { coordinateSystem },
+ } = React.useContext(SettingsContext);
const { formatMessage: t } = useIntl();
- const [system] = useCoodinateSystem();
const coordinateMessage = () => {
- switch (system) {
+ switch (coordinateSystem) {
case "dd":
return ;
case "utm":
@@ -111,7 +113,7 @@ const GpsModal = ({ navigation }: Props) => {
diff --git a/src/frontend/screens/Observation/ObservationShare.js b/src/frontend/screens/Observation/ObservationShare.js
index 35d5d2f69..c59fc64e4 100644
--- a/src/frontend/screens/Observation/ObservationShare.js
+++ b/src/frontend/screens/Observation/ObservationShare.js
@@ -15,7 +15,7 @@ import {
import { getProp } from "../../lib/utils";
import type { PresetWithFields } from "../../context/ConfigContext";
import type { Observation } from "../../context/ObservationsContext";
-import useCoodinateSystem from "../../hooks/useCoordinateSystem";
+import SettingsContext from "../../context/SettingsContext";
const m = defineMessages({
alertSubject: {
@@ -53,7 +53,10 @@ export const ShareSubject = ({ observation, preset }: ShareMessageProps) => {
export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
const { formatMessage: t } = useIntl();
- const [system] = useCoodinateSystem();
+ const {
+ settings: { coordinateSystem },
+ } = React.useContext(SettingsContext);
+
const { value } = observation;
const { lon, lat } = value;
@@ -83,7 +86,7 @@ export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
{lon != null && lat != null ? (
-
+
) : null}
{value.tags.notes ? {value.tags.notes}
: null}
diff --git a/src/frontend/screens/Observation/ObservationView.js b/src/frontend/screens/Observation/ObservationView.js
index c44ef16dc..020635811 100644
--- a/src/frontend/screens/Observation/ObservationView.js
+++ b/src/frontend/screens/Observation/ObservationView.js
@@ -30,10 +30,10 @@ import {
} from "../../lib/styles";
import { TouchableOpacity } from "../../sharedComponents/Touchables";
import type { PresetWithFields } from "../../context/ConfigContext";
+import SettingsContext from "../../context/SettingsContext";
import type { Observation } from "../../context/ObservationsContext";
import useMapStyle from "../../hooks/useMapStyle";
import useDeviceId from "../../hooks/useDeviceId";
-import useCoodinateSystem from "../../hooks/useCoordinateSystem";
import Loading from "../../sharedComponents/Loading";
import OfflineMapLayers from "../../sharedComponents/OfflineMapLayers";
import { ShareMessage, ShareSubject, renderToString } from "./ObservationShare";
@@ -126,7 +126,9 @@ const ObservationView = ({
onPressDelete,
}: ODVProps) => {
const intl = useIntl();
- const [system] = useCoodinateSystem();
+ const {
+ settings: { coordinateSystem },
+ } = React.useContext(SettingsContext);
const { formatMessage: t } = intl;
const deviceId = useDeviceId();
const isMine = deviceId === observation.value.deviceId;
@@ -175,7 +177,11 @@ const ObservationView = ({
-
+
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index 52f8cf268..40e49e528 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -2,9 +2,9 @@
import React from "react";
import { ScrollView } from "react-native";
import { FormattedMessage, defineMessages, useIntl } from "react-intl";
-
-import useCoodinateSystem from "../../hooks/useCoordinateSystem";
import LocationContext from "../../context/LocationContext";
+import SettingsContext from "../../context/SettingsContext";
+
import { formatCoords } from "../../lib/utils";
import HeaderTitle from "../../sharedComponents/HeaderTitle";
@@ -37,7 +37,12 @@ const m = defineMessages({
const CoordinateSystem = () => {
const intl = useIntl();
const location = React.useContext(LocationContext);
- const [system, setSystem] = useCoodinateSystem();
+ const { settings, dispatch } = React.useContext(SettingsContext);
+ const setSystem = React.useCallback(
+ value => dispatch({ type: "set_coordinate_system", value }),
+ [dispatch]
+ );
+ const system = settings.coordinateSystem;
if (!location || !location.position) return ;
else {
const { latitude = 0, longitude = 0 } = location.position.coords;
diff --git a/src/frontend/sharedComponents/LocationField.js b/src/frontend/sharedComponents/LocationField.js
index 2a866339d..899481db2 100644
--- a/src/frontend/sharedComponents/LocationField.js
+++ b/src/frontend/sharedComponents/LocationField.js
@@ -3,8 +3,8 @@ import * as React from "react";
import omit from "lodash/omit";
import useDraftObservation from "../hooks/useDraftObservation";
-import useCoodinateSystem from "../hooks/useCoordinateSystem";
import LocationContext from "../context/LocationContext";
+import SettingsContext from "../context/SettingsContext";
type Props = {
children: ({
@@ -26,8 +26,9 @@ type Props = {
const LocationField = ({ children }: Props) => {
const [{ value }, { updateDraft }] = useDraftObservation();
const location = React.useContext(LocationContext);
- const [system] = useCoodinateSystem();
-
+ const {
+ settings: { coordinateSystem },
+ } = React.useContext(SettingsContext);
React.useEffect(() => {
if (!location.position || !value) return;
const draftHasManualLocation =
@@ -57,7 +58,7 @@ const LocationField = ({ children }: Props) => {
return children({
longitude: value.lon,
latitude: value.lat,
- system,
+ system: coordinateSystem,
accuracy:
value.metadata &&
value.metadata.location &&
From d4499e8428a6c781ee81f47cf22f4313a3e7bc94 Mon Sep 17 00:00:00 2001
From: Gregor MacLennan
Date: Fri, 16 Apr 2021 17:51:36 +0100
Subject: [PATCH 16/22] fixes & cleanup
---
src/frontend/context/SettingsContext.js | 95 +++++++------------
src/frontend/hooks/useSettingsValue.js | 10 ++
src/frontend/screens/GpsModal.js | 43 ++++-----
.../screens/Observation/ObservationShare.js | 6 +-
.../screens/Observation/ObservationView.js | 6 +-
.../ObservationEdit/ObservationEditView.js | 54 ++++++-----
.../screens/Settings/CoordinateSystem.js | 68 +++++--------
src/frontend/screens/Settings/SelectOne.js | 2 +-
.../sharedComponents/LocationField.js | 6 +-
9 files changed, 116 insertions(+), 174 deletions(-)
create mode 100644 src/frontend/hooks/useSettingsValue.js
diff --git a/src/frontend/context/SettingsContext.js b/src/frontend/context/SettingsContext.js
index 085250b8a..b325bb83a 100644
--- a/src/frontend/context/SettingsContext.js
+++ b/src/frontend/context/SettingsContext.js
@@ -1,82 +1,51 @@
// @flow
import * as React from "react";
-import AsyncStorage from "@react-native-community/async-storage";
+import createPersistedState from "../hooks/usePersistedState";
-const STORE_KEY = "@MapeoSettings@36";
+// Increment if the shape of settings changes, but try to avoid doing this
+// because it will reset everybody's settings back to the defaults = bad :(
+const STORE_KEY = "@MapeoSettings@1";
-export type SettingsContextType = {
- coordinateSystem?: string,
+export type CoordinateSystem = "utm" | "dd" | "dms";
+
+export type SettingsState = {
+ coordinateSystem: CoordinateSystem,
};
-const initialState = {
+type SettingsContextType = [
+ SettingsState,
+ (key: $Keys, value: any) => void
+];
+
+const DEFAULT_SETTINGS = {
coordinateSystem: "utm",
};
-const defaultContext = [initialState, () => {}];
-const SettingsContext = React.createContext(defaultContext);
+const SettingsContext = React.createContext([
+ DEFAULT_SETTINGS,
+ () => {},
+]);
-function reducer(state: State, action: Action): State {
- switch (action.type) {
- case "set": {
- return action.value;
- }
- case "set_coordinate_system": {
- try {
- return { ...state, coordinateSystem: action.value };
- } catch {
- return state;
- }
- }
- default:
- return state;
- }
-}
+const usePersistedState = createPersistedState(STORE_KEY);
-const getData = async dispatch => {
- try {
- // AsyncStorage.clear()
- const state = await AsyncStorage.getItem(STORE_KEY);
- if (state) {
- const parsedState = JSON.parse(state);
- dispatch({ type: "set", value: parsedState });
- return parsedState;
- } else return initialState;
- } catch (e) {
- console.log("Failed to fetch the data from storage");
- return initialState;
- }
-};
+export const SettingsProvider = ({ children }: { children: React.Node }) => {
+ const [state, status, setState] = usePersistedState(
+ DEFAULT_SETTINGS
+ );
-const saveData = async value => {
- try {
- const stringified = JSON.stringify(value);
- await AsyncStorage.setItem(STORE_KEY, stringified);
- return value;
- } catch (e) {
- console.log("Failed to save the data to the storage");
- }
-};
+ const setSettings = React.useCallback(
+ (key, value) => setState({ ...state, [key]: value }),
+ [setState, state]
+ );
-export const SettingsProvider = ({ children }: { children: React.Node }) => {
- const didMountRef = React.useRef(false);
- const [state, dispatch] = React.useReducer(reducer, defaultContext[0]);
- const contextValue = React.useMemo(() => [state, dispatch], [
+ const contextValue = React.useMemo(() => [state, setSettings], [
state,
- dispatch,
+ setSettings,
]);
- React.useEffect(() => {
- if (didMountRef.current) {
- saveData(contextValue[0]);
- } else {
- didMountRef.current = true;
- getData(dispatch);
- }
- }, [contextValue]);
+
return (
-
- {children}
+
+ {status === "loading" ? null : children}
);
};
diff --git a/src/frontend/hooks/useSettingsValue.js b/src/frontend/hooks/useSettingsValue.js
new file mode 100644
index 000000000..a118196cf
--- /dev/null
+++ b/src/frontend/hooks/useSettingsValue.js
@@ -0,0 +1,10 @@
+// @flow
+import React from "react";
+import SettingsContext, {
+ type SettingsState,
+} from "../context/SettingsContext";
+
+export default function useSettingsValue(key: $Keys) {
+ const [state] = React.useContext(SettingsContext);
+ return state[key];
+}
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index d34d4f939..62cd09adf 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -5,7 +5,7 @@ import Text from "../sharedComponents/Text";
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
import LocationContext from "../context/LocationContext";
-import SettingsContext from "../context/SettingsContext";
+import useSettingsValue from "../hooks/useSettingsValue";
import { FormattedCoords } from "../sharedComponents/FormattedData";
import DateDistance from "../sharedComponents/DateDistance";
@@ -24,7 +24,7 @@ const m = defineMessages({
defaultMessage: "Last update",
description: "Section title for time of last GPS update",
},
- locationUTM: {
+ utm: {
id: "screens.GpsModal.locationUTM",
defaultMessage: "Coordinates UTM",
description: "Section title for UTM coordinates",
@@ -34,12 +34,12 @@ const m = defineMessages({
defaultMessage: "Coordinates Latitude and Longitude",
description: "Section title for latitude and longitude coordinates",
},
- locationDMS: {
+ dms: {
id: "screens.GpsModal.locationDMS",
defaultMessage: "Coordinates DMS",
description: "Section title for DMS coordinates",
},
- locationDD: {
+ dd: {
id: "screens.GpsModal.locationDD",
defaultMessage: "Coordinates Decimal Degrees",
description: "Section title for DD coordinates",
@@ -79,22 +79,11 @@ type Props = {
const GpsModal = ({ navigation }: Props) => {
const location = React.useContext(LocationContext);
- const {
- settings: { coordinateSystem },
- } = React.useContext(SettingsContext);
+ // This is necessary for Flow type checking (if we use location.position in a
+ // conditional it does not know if something else can change it)
+ const { position, provider } = location;
+ const coordinateSystem = useSettingsValue("coordinateSystem");
const { formatMessage: t } = useIntl();
- const coordinateMessage = () => {
- switch (coordinateSystem) {
- case "dd":
- return ;
- case "utm":
- return ;
- case "dms":
- return ;
- default:
- return ;
- }
- };
return (
@@ -106,20 +95,22 @@ const GpsModal = ({ navigation }: Props) => {
style={styles.rowValue}
date={new Date(getLastUpdateText(location))}
/>
- {location.position && (
+ {position && (
<>
- {coordinateMessage()}
+
+
+
- {Object.entries(location.position.coords).map(([key, value]) => (
+ {Object.entries(position.coords).map(([key, value]) => (
{
))}
>
)}
- {location.provider && (
+ {provider && (
<>
- {Object.entries(location.provider).map(([key, value]) => (
+ {Object.entries(provider).map(([key, value]) => (
{
export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
const { formatMessage: t } = useIntl();
- const {
- settings: { coordinateSystem },
- } = React.useContext(SettingsContext);
+ const coordinateSystem = useSettingsValue("coordinateSystem");
const { value } = observation;
const { lon, lat } = value;
diff --git a/src/frontend/screens/Observation/ObservationView.js b/src/frontend/screens/Observation/ObservationView.js
index 020635811..e10e9e7bc 100644
--- a/src/frontend/screens/Observation/ObservationView.js
+++ b/src/frontend/screens/Observation/ObservationView.js
@@ -30,10 +30,10 @@ import {
} from "../../lib/styles";
import { TouchableOpacity } from "../../sharedComponents/Touchables";
import type { PresetWithFields } from "../../context/ConfigContext";
-import SettingsContext from "../../context/SettingsContext";
import type { Observation } from "../../context/ObservationsContext";
import useMapStyle from "../../hooks/useMapStyle";
import useDeviceId from "../../hooks/useDeviceId";
+import useSettingsValue from "../../hooks/useSettingsValue";
import Loading from "../../sharedComponents/Loading";
import OfflineMapLayers from "../../sharedComponents/OfflineMapLayers";
import { ShareMessage, ShareSubject, renderToString } from "./ObservationShare";
@@ -126,9 +126,7 @@ const ObservationView = ({
onPressDelete,
}: ODVProps) => {
const intl = useIntl();
- const {
- settings: { coordinateSystem },
- } = React.useContext(SettingsContext);
+ const coordinateSystem = useSettingsValue("coordinateSystem");
const { formatMessage: t } = intl;
const deviceId = useDeviceId();
const isMine = deviceId === observation.value.deviceId;
diff --git a/src/frontend/screens/ObservationEdit/ObservationEditView.js b/src/frontend/screens/ObservationEdit/ObservationEditView.js
index d96c57db8..ef73839ac 100644
--- a/src/frontend/screens/ObservationEdit/ObservationEditView.js
+++ b/src/frontend/screens/ObservationEdit/ObservationEditView.js
@@ -14,6 +14,7 @@ import {
CategoryCircleIcon,
} from "../../sharedComponents/icons";
import useDraftObservation from "../../hooks/useDraftObservation";
+import useSettingsValue from "../../hooks/useSettingsValue";
import ThumbnailScrollView from "../../sharedComponents/ThumbnailScrollView";
import TextButton from "../../sharedComponents/TextButton";
import { BLACK, LIGHT_GREY, LIGHT_BLUE } from "../../lib/styles";
@@ -55,39 +56,40 @@ const m = defineMessages({
const LocationView = ({
longitude,
latitude,
- system,
accuracy,
}: {
longitude?: number | null,
latitude?: number | null,
- system?: string,
accuracy?: number,
-}) => (
-
- {longitude == null || latitude == null ? (
-
-
-
- ) : (
- <>
-
-
-
+}) => {
+ const system = useSettingsValue("coordinateSystem");
+ return (
+
+ {longitude == null || latitude == null ? (
+
+
- {accuracy === undefined ? null : (
-
- {" ±" + accuracy.toFixed(2) + "m"}
+ ) : (
+ <>
+
+
+
- )}
- >
- )}
-
-);
+ {accuracy === undefined ? null : (
+
+ {" ±" + accuracy.toFixed(2) + "m"}
+
+ )}
+ >
+ )}
+
+ );
+};
const CategoryView = ({
preset = {},
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateSystem.js
index 40e49e528..fbe9d0e08 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateSystem.js
@@ -8,7 +8,6 @@ import SettingsContext from "../../context/SettingsContext";
import { formatCoords } from "../../lib/utils";
import HeaderTitle from "../../sharedComponents/HeaderTitle";
-import Loading from "../../sharedComponents/Loading";
import SelectOne from "./SelectOne";
const m = defineMessages({
@@ -34,54 +33,33 @@ const m = defineMessages({
},
});
+// Default location used to show how coordinates will be formatted. Uses current
+// user location if available
+const EXAMPLE_LOCATION = { longitude: -72.312023, latitude: -10.38787 };
+
const CoordinateSystem = () => {
const intl = useIntl();
const location = React.useContext(LocationContext);
- const { settings, dispatch } = React.useContext(SettingsContext);
- const setSystem = React.useCallback(
- value => dispatch({ type: "set_coordinate_system", value }),
- [dispatch]
- );
- const system = settings.coordinateSystem;
- if (!location || !location.position) return ;
- else {
- const { latitude = 0, longitude = 0 } = location.position.coords;
- const options = [
- {
- value: "dd",
- label: intl.formatMessage({ ...m.dd }),
- hint: formatCoords({
- lon: longitude,
- lat: latitude,
- format: "dd",
- }),
- },
- {
- value: "dms",
- label: intl.formatMessage({ ...m.dms }),
- hint: formatCoords({
- lon: longitude,
- lat: latitude,
- format: "dms",
- }),
- },
- {
- value: "utm",
- label: intl.formatMessage({ ...m.utm }),
- hint: formatCoords({
- lon: longitude,
- lat: latitude,
- format: "utm",
- }),
- },
- ];
+ const [{ coordinateSystem }, setSettings] = React.useContext(SettingsContext);
+
+ const { latitude: lat, longitude: lon } =
+ (location.position && location.position.coords) || EXAMPLE_LOCATION;
- return (
-
-
-
- );
- }
+ const options = ["dd", "dms", "utm"].map(format => ({
+ value: format,
+ label: intl.formatMessage(m[format]),
+ hint: formatCoords({ lon, lat, format }),
+ }));
+
+ return (
+
+ setSettings("coordinateSystem", format)}
+ />
+
+ );
};
CoordinateSystem.navigationOptions = {
diff --git a/src/frontend/screens/Settings/SelectOne.js b/src/frontend/screens/Settings/SelectOne.js
index 3697c3289..6a97e51e6 100644
--- a/src/frontend/screens/Settings/SelectOne.js
+++ b/src/frontend/screens/Settings/SelectOne.js
@@ -24,7 +24,7 @@ const SelectOne = ({ value, options, onChange }: Props) => (
onChange(value === item.value ? null : item.value)}
+ onPress={() => value !== item.value && onChange(item.value)}
>
{
const [{ value }, { updateDraft }] = useDraftObservation();
const location = React.useContext(LocationContext);
- const {
- settings: { coordinateSystem },
- } = React.useContext(SettingsContext);
+
React.useEffect(() => {
if (!location.position || !value) return;
const draftHasManualLocation =
@@ -58,7 +55,6 @@ const LocationField = ({ children }: Props) => {
return children({
longitude: value.lon,
latitude: value.lat,
- system: coordinateSystem,
accuracy:
value.metadata &&
value.metadata.location &&
From a41fddf854424ac3b4e46211c7a7f3b32a12b39a Mon Sep 17 00:00:00 2001
From: Gregor MacLennan
Date: Fri, 16 Apr 2021 18:32:01 +0100
Subject: [PATCH 17/22] remove unused message
---
src/frontend/screens/GpsModal.js | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index 62cd09adf..03e9f4a55 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -29,11 +29,6 @@ const m = defineMessages({
defaultMessage: "Coordinates UTM",
description: "Section title for UTM coordinates",
},
- locationLatLon: {
- id: "screens.GpsModal.locationLatLon",
- defaultMessage: "Coordinates Latitude and Longitude",
- description: "Section title for latitude and longitude coordinates",
- },
dms: {
id: "screens.GpsModal.locationDMS",
defaultMessage: "Coordinates DMS",
From 9e8eeaaa244f223f26fc8c2e82d48af9a195cf1c Mon Sep 17 00:00:00 2001
From: Gregor MacLennan
Date: Fri, 16 Apr 2021 18:44:20 +0100
Subject: [PATCH 18/22] Update language to coordinate format
---
messages/en.json | 34 ++++++++-----------
src/frontend/AppStack.js | 4 +--
src/frontend/context/SettingsContext.js | 6 ++--
src/frontend/screens/GpsModal.js | 6 ++--
.../screens/Observation/ObservationShare.js | 4 +--
.../screens/Observation/ObservationView.js | 4 +--
.../ObservationEdit/ObservationEditView.js | 4 +--
...oordinateSystem.js => CoordinateFormat.js} | 32 ++++++++---------
src/frontend/screens/Settings/Settings.js | 22 ++++++------
9 files changed, 56 insertions(+), 60 deletions(-)
rename src/frontend/screens/Settings/{CoordinateSystem.js => CoordinateFormat.js} (65%)
diff --git a/messages/en.json b/messages/en.json
index aac8e7845..de2516ca3 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -58,20 +58,20 @@
"description": "Title for category chooser screen",
"message": "Choose what is happening"
},
- "screens.CoordinateSystem.dd": {
- "description": "Decimal Degrees coordinate system",
+ "screens.CoordinateFormat.dd": {
+ "description": "Decimal Degrees coordinate format",
"message": "Decimal Degrees (DD)"
},
- "screens.CoordinateSystem.dms": {
- "description": "Degrees/Minutes/Seconds coordinate system",
+ "screens.CoordinateFormat.dms": {
+ "description": "Degrees/Minutes/Seconds coordinate format",
"message": "Degrees/Minutes/Seconds (DMS)"
},
- "screens.CoordinateSystem.title": {
- "description": "Title coordinate system screen",
- "message": "Coordinate System"
+ "screens.CoordinateFormat.title": {
+ "description": "Title coordinate format screen",
+ "message": "Coordinate Format"
},
- "screens.CoordinateSystem.utm": {
- "description": "Universal Transverse Mercator coordinate system",
+ "screens.CoordinateFormat.utm": {
+ "description": "Universal Transverse Mercator coordinate format",
"message": "Universal Transverse Mercator (UTM)"
},
"screens.GpsModal.details": {
@@ -94,10 +94,6 @@
"description": "Section title for DMS coordinates",
"message": "Coordinates DMS"
},
- "screens.GpsModal.locationLatLon": {
- "description": "Section title for latitude and longitude coordinates",
- "message": "Coordinates Latitude and Longitude"
- },
"screens.GpsModal.locationSensors": {
"description": "Heading for section about location sensor status",
"message": "Sensor Status"
@@ -324,13 +320,13 @@
"description": "Title of error dialog when there is an error importing a config file",
"message": "Import Error"
},
- "screens.Settings.coordinateSystem": {
- "description": "Settings for coordinate systems",
- "message": "Coordinate System"
+ "screens.Settings.coordinateFormat": {
+ "description": "Settings for coordinate format",
+ "message": "Coordinate Format"
},
- "screens.Settings.coordinateSystemDesc": {
- "description": "Description of the 'Coordinate System' page",
- "message": "DD, UTM, DMS"
+ "screens.Settings.coordinateFormatDesc": {
+ "description": "Description of the 'Coordinate Format' page",
+ "message": "Choose how coordinates are displayed"
},
"screens.Settings.currentConfig": {
"description": "Label for name & version of current configuration",
diff --git a/src/frontend/AppStack.js b/src/frontend/AppStack.js
index afb24e70e..449d86d5b 100644
--- a/src/frontend/AppStack.js
+++ b/src/frontend/AppStack.js
@@ -21,7 +21,7 @@ import CustomHeaderLeft from "./sharedComponents/CustomHeaderLeft";
import ProjectConfig from "./screens/Settings/ProjectConfig";
import AboutMapeo from "./screens/Settings/AboutMapeo";
import LanguageSettings from "./screens/Settings/LanguageSettings";
-import CoordinateSystem from "./screens/Settings/CoordinateSystem";
+import CoordinateFormat from "./screens/Settings/CoordinateFormat";
import HomeHeader from "./sharedComponents/HomeHeader";
const HomeTabs = createBottomTabNavigator(
@@ -69,7 +69,7 @@ const AppStack = createStackNavigator(
// $FlowFixMe
LanguageSettings,
// $FlowFixMe
- CoordinateSystem,
+ CoordinateFormat,
// $FlowFixMe
PhotosModal: PhotosModal,
// $FlowFixMe
diff --git a/src/frontend/context/SettingsContext.js b/src/frontend/context/SettingsContext.js
index b325bb83a..38a53b4e5 100644
--- a/src/frontend/context/SettingsContext.js
+++ b/src/frontend/context/SettingsContext.js
@@ -6,10 +6,10 @@ import createPersistedState from "../hooks/usePersistedState";
// because it will reset everybody's settings back to the defaults = bad :(
const STORE_KEY = "@MapeoSettings@1";
-export type CoordinateSystem = "utm" | "dd" | "dms";
+export type CoordinateFormat = "utm" | "dd" | "dms";
export type SettingsState = {
- coordinateSystem: CoordinateSystem,
+ coordinateFormat: CoordinateFormat,
};
type SettingsContextType = [
@@ -18,7 +18,7 @@ type SettingsContextType = [
];
const DEFAULT_SETTINGS = {
- coordinateSystem: "utm",
+ coordinateFormat: "utm",
};
const SettingsContext = React.createContext([
diff --git a/src/frontend/screens/GpsModal.js b/src/frontend/screens/GpsModal.js
index 03e9f4a55..5cda881ae 100644
--- a/src/frontend/screens/GpsModal.js
+++ b/src/frontend/screens/GpsModal.js
@@ -77,7 +77,7 @@ const GpsModal = ({ navigation }: Props) => {
// This is necessary for Flow type checking (if we use location.position in a
// conditional it does not know if something else can change it)
const { position, provider } = location;
- const coordinateSystem = useSettingsValue("coordinateSystem");
+ const coordinateFormat = useSettingsValue("coordinateFormat");
const { formatMessage: t } = useIntl();
return (
@@ -93,13 +93,13 @@ const GpsModal = ({ navigation }: Props) => {
{position && (
<>
-
+
diff --git a/src/frontend/screens/Observation/ObservationShare.js b/src/frontend/screens/Observation/ObservationShare.js
index bdadf727d..fb4395af8 100644
--- a/src/frontend/screens/Observation/ObservationShare.js
+++ b/src/frontend/screens/Observation/ObservationShare.js
@@ -53,7 +53,7 @@ export const ShareSubject = ({ observation, preset }: ShareMessageProps) => {
export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
const { formatMessage: t } = useIntl();
- const coordinateSystem = useSettingsValue("coordinateSystem");
+ const coordinateFormat = useSettingsValue("coordinateFormat");
const { value } = observation;
const { lon, lat } = value;
@@ -84,7 +84,7 @@ export const ShareMessage = ({ observation, preset }: ShareMessageProps) => {
{lon != null && lat != null ? (
-
+
) : null}
{value.tags.notes ? {value.tags.notes}
: null}
diff --git a/src/frontend/screens/Observation/ObservationView.js b/src/frontend/screens/Observation/ObservationView.js
index e10e9e7bc..54b735562 100644
--- a/src/frontend/screens/Observation/ObservationView.js
+++ b/src/frontend/screens/Observation/ObservationView.js
@@ -126,7 +126,7 @@ const ObservationView = ({
onPressDelete,
}: ODVProps) => {
const intl = useIntl();
- const coordinateSystem = useSettingsValue("coordinateSystem");
+ const coordinateFormat = useSettingsValue("coordinateFormat");
const { formatMessage: t } = intl;
const deviceId = useDeviceId();
const isMine = deviceId === observation.value.deviceId;
@@ -176,7 +176,7 @@ const ObservationView = ({
diff --git a/src/frontend/screens/ObservationEdit/ObservationEditView.js b/src/frontend/screens/ObservationEdit/ObservationEditView.js
index ef73839ac..0e9ed3cfa 100644
--- a/src/frontend/screens/ObservationEdit/ObservationEditView.js
+++ b/src/frontend/screens/ObservationEdit/ObservationEditView.js
@@ -62,7 +62,7 @@ const LocationView = ({
latitude?: number | null,
accuracy?: number,
}) => {
- const system = useSettingsValue("coordinateSystem");
+ const format = useSettingsValue("coordinateFormat");
return (
{longitude == null || latitude == null ? (
@@ -78,7 +78,7 @@ const LocationView = ({
style={{ marginRight: 5 }}
/>
-
+
{accuracy === undefined ? null : (
diff --git a/src/frontend/screens/Settings/CoordinateSystem.js b/src/frontend/screens/Settings/CoordinateFormat.js
similarity index 65%
rename from src/frontend/screens/Settings/CoordinateSystem.js
rename to src/frontend/screens/Settings/CoordinateFormat.js
index fbe9d0e08..f35a1bdb5 100644
--- a/src/frontend/screens/Settings/CoordinateSystem.js
+++ b/src/frontend/screens/Settings/CoordinateFormat.js
@@ -12,24 +12,24 @@ import SelectOne from "./SelectOne";
const m = defineMessages({
title: {
- id: "screens.CoordinateSystem.title",
- defaultMessage: "Coordinate System",
- description: "Title coordinate system screen",
+ id: "screens.CoordinateFormat.title",
+ defaultMessage: "Coordinate Format",
+ description: "Title coordinate format screen",
},
dd: {
- id: "screens.CoordinateSystem.dd",
+ id: "screens.CoordinateFormat.dd",
defaultMessage: "Decimal Degrees (DD)",
- description: "Decimal Degrees coordinate system",
+ description: "Decimal Degrees coordinate format",
},
dms: {
- id: "screens.CoordinateSystem.dms",
+ id: "screens.CoordinateFormat.dms",
defaultMessage: "Degrees/Minutes/Seconds (DMS)",
- description: "Degrees/Minutes/Seconds coordinate system",
+ description: "Degrees/Minutes/Seconds coordinate format",
},
utm: {
- id: "screens.CoordinateSystem.utm",
+ id: "screens.CoordinateFormat.utm",
defaultMessage: "Universal Transverse Mercator (UTM)",
- description: "Universal Transverse Mercator coordinate system",
+ description: "Universal Transverse Mercator coordinate format",
},
});
@@ -37,10 +37,10 @@ const m = defineMessages({
// user location if available
const EXAMPLE_LOCATION = { longitude: -72.312023, latitude: -10.38787 };
-const CoordinateSystem = () => {
+const CoordinateFormat = () => {
const intl = useIntl();
const location = React.useContext(LocationContext);
- const [{ coordinateSystem }, setSettings] = React.useContext(SettingsContext);
+ const [{ coordinateFormat }, setSettings] = React.useContext(SettingsContext);
const { latitude: lat, longitude: lon } =
(location.position && location.position.coords) || EXAMPLE_LOCATION;
@@ -52,17 +52,17 @@ const CoordinateSystem = () => {
}));
return (
-
+
setSettings("coordinateSystem", format)}
+ onChange={format => setSettings("coordinateFormat", format)}
/>
);
};
-CoordinateSystem.navigationOptions = {
+CoordinateFormat.navigationOptions = {
headerTitle: () => (
@@ -70,4 +70,4 @@ CoordinateSystem.navigationOptions = {
),
};
-export default CoordinateSystem;
+export default CoordinateFormat;
diff --git a/src/frontend/screens/Settings/Settings.js b/src/frontend/screens/Settings/Settings.js
index 28a0a5e2a..4eaa7dd93 100644
--- a/src/frontend/screens/Settings/Settings.js
+++ b/src/frontend/screens/Settings/Settings.js
@@ -48,15 +48,15 @@ const m = defineMessages({
defaultMessage: "Version and build number",
description: "Description of the 'About Mapeo' page",
},
- coordinateSystem: {
- id: "screens.Settings.coordinateSystem",
- defaultMessage: "Coordinate System",
- description: "Settings for coordinate systems",
+ coordinateFormat: {
+ id: "screens.Settings.coordinateFormat",
+ defaultMessage: "Coordinate Format",
+ description: "Settings for coordinate format",
},
- coordinateSystemDesc: {
- id: "screens.Settings.coordinateSystemDesc",
- defaultMessage: "DD, UTM, DMS",
- description: "Description of the 'Coordinate System' page",
+ coordinateFormatDesc: {
+ id: "screens.Settings.coordinateFormatDesc",
+ defaultMessage: "Choose how coordinates are displayed",
+ description: "Description of the 'Coordinate Format' page",
},
});
@@ -85,13 +85,13 @@ const Settings = () => {
>
navigate("CoordinateSystem")}
+ onPress={() => navigate("CoordinateFormat")}
testID="settingsCoodinatesButton"
>
}
- secondary={}
+ primary={}
+ secondary={}
>
Date: Fri, 16 Apr 2021 18:47:22 +0100
Subject: [PATCH 19/22] Use Number.toFixed() for rounding coordinates
---
src/frontend/lib/utils.js | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index cde3a3446..91d9b6949 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -128,11 +128,7 @@ function toDegreesMinutesAndSeconds(coordinate) {
const minutesNotTruncated = (absolute - degrees) * 60;
const minutes = Math.floor(minutesNotTruncated);
const seconds = (minutesNotTruncated - minutes) * 60;
- const decimals = 3;
- const formattedSeconds = Number(
- Math.round(seconds + "e" + decimals) + "e-" + decimals
- );
- return `${degrees}° ${minutes}' ${formattedSeconds}"`;
+ return `${degrees}° ${minutes}' ${seconds.toFixed(3)}"`;
}
function convertToDMS({ lat, lon }) {
@@ -159,14 +155,7 @@ function convertToUTM({ lat, lon }) {
}
function formatDD({ lat, lon }) {
- const decimals = 6;
- const formattedLat = Number(
- Math.round(lat + "e" + decimals) + "e-" + decimals
- );
- const formattedLon = Number(
- Math.round(lon + "e" + decimals) + "e-" + decimals
- );
- return `lat ${formattedLat} lon ${formattedLon}`;
+ return `Lat ${lat.toFixed(6)} Lon ${lon.toFixed(6)}`;
}
export function formatCoords({
From 46fe0301fa26d9409f63ef9062d5cc2f77718f8f Mon Sep 17 00:00:00 2001
From: Gregor MacLennan
Date: Fri, 16 Apr 2021 19:42:46 +0100
Subject: [PATCH 20/22] Fix flow type error
---
src/frontend/sharedComponents/FormattedData.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/frontend/sharedComponents/FormattedData.js b/src/frontend/sharedComponents/FormattedData.js
index 7d92cfb49..7e321d44b 100644
--- a/src/frontend/sharedComponents/FormattedData.js
+++ b/src/frontend/sharedComponents/FormattedData.js
@@ -7,6 +7,7 @@ import DateDistance from "./DateDistance";
import { type Observation } from "../context/ObservationsContext";
import { formats } from "../context/IntlContext";
import type { Field, Preset, PresetWithFields } from "../context/ConfigContext";
+import { type CoordinateFormat } from "../context/SettingsContext";
const m = defineMessages({
noAnswer: {
@@ -36,7 +37,7 @@ export const FormattedCoords = ({
}: {
lat: number,
lon: number,
- format: string,
+ format: CoordinateFormat,
}) => {
return <>{formatCoords({ lon, lat, format })}>;
};
From fa8a738dfb9a466ca15088b1c923d4e47b218c39 Mon Sep 17 00:00:00 2001
From: Gregor MacLennan
Date: Fri, 16 Apr 2021 19:51:11 +0100
Subject: [PATCH 21/22] Add comma to DMS formatting
---
src/frontend/lib/utils.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index 91d9b6949..419083e9b 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -137,7 +137,7 @@ function convertToDMS({ lat, lon }) {
const longitude = toDegreesMinutesAndSeconds(lon);
const longitudeCardinal = lon >= 0 ? "E" : "W";
- return `${latitude} ${latitudeCardinal} ${longitude} ${longitudeCardinal}`;
+ return `${latitude} ${latitudeCardinal}, ${longitude} ${longitudeCardinal}`;
}
function convertToUTM({ lat, lon }) {
From 7e02d1917c159705aaee4f1504382671dff5a841 Mon Sep 17 00:00:00 2001
From: Gregor MacLennan
Date: Fri, 16 Apr 2021 19:51:29 +0100
Subject: [PATCH 22/22] Format lat/long DD according to Nat Geo style guide
---
src/frontend/lib/utils.js | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/frontend/lib/utils.js b/src/frontend/lib/utils.js
index 419083e9b..d33ca3d42 100644
--- a/src/frontend/lib/utils.js
+++ b/src/frontend/lib/utils.js
@@ -131,6 +131,8 @@ function toDegreesMinutesAndSeconds(coordinate) {
return `${degrees}° ${minutes}' ${seconds.toFixed(3)}"`;
}
+// Style from National Geographic style guide
+// https://sites.google.com/a/ngs.org/ngs-style-manual/home/L/latitude-and-longitude
function convertToDMS({ lat, lon }) {
const latitude = toDegreesMinutesAndSeconds(lat);
const latitudeCardinal = lat >= 0 ? "N" : "S";
@@ -154,8 +156,14 @@ function convertToUTM({ lat, lon }) {
}
}
+// Style from National Geographic style guide
+// https://sites.google.com/a/ngs.org/ngs-style-manual/home/L/latitude-and-longitude
function formatDD({ lat, lon }) {
- return `Lat ${lat.toFixed(6)} Lon ${lon.toFixed(6)}`;
+ const formattedLat = Math.abs(lat).toFixed(6);
+ const formattedLon = Math.abs(lon).toFixed(6);
+ const latCardinal = lat >= 0 ? "N" : "S";
+ const lonCardinal = lon >= 0 ? "E" : "W";
+ return `${formattedLat}° ${latCardinal}, ${formattedLon}° ${lonCardinal}`;
}
export function formatCoords({