Skip to content

Commit 705bc68

Browse files
authored
Merge pull request #79558 from software-mansion-labs/@GCyganek/gps/handle-reconnection
Handle reconnection while there is an ongoing GPS trip
2 parents b7887d3 + 2df5c75 commit 705bc68

File tree

6 files changed

+88
-25
lines changed

6 files changed

+88
-25
lines changed

src/components/GPSInProgressModal/index.native.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ConfirmModal from '@components/ConfirmModal';
22
import useLocalize from '@hooks/useLocalize';
3+
import useNetwork from '@hooks/useNetwork';
34
import useOnyx from '@hooks/useOnyx';
45
import {closeReactNativeApp} from '@libs/actions/HybridApp';
56
import {setIsGPSInProgressModalOpen} from '@libs/actions/isGPSInProgressModalOpen';
@@ -9,10 +10,11 @@ import ONYXKEYS from '@src/ONYXKEYS';
910
function GPSInProgressModal() {
1011
const [isGPSInProgressModalOpen] = useOnyx(ONYXKEYS.IS_GPS_IN_PROGRESS_MODAL_OPEN, {canBeMissing: true});
1112
const {translate} = useLocalize();
13+
const {isOffline} = useNetwork();
1214

1315
const stopGpsAndSwitchToOD = async () => {
1416
setIsGPSInProgressModalOpen(false);
15-
await stopGpsTrip();
17+
await stopGpsTrip(isOffline);
1618
closeReactNativeApp({shouldSetNVP: true, isTrackingGPS: false});
1719
};
1820

src/components/GPSTripStateChecker/index.native.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, {useEffect, useState} from 'react';
33
import OnyxUtils from 'react-native-onyx/dist/OnyxUtils';
44
import ConfirmModal from '@components/ConfirmModal';
55
import useLocalize from '@hooks/useLocalize';
6+
import useNetwork from '@hooks/useNetwork';
67
import useOnyx from '@hooks/useOnyx';
78
import {stopGpsTrip} from '@libs/GPSDraftDetailsUtils';
89
import Navigation from '@libs/Navigation/Navigation';
@@ -12,14 +13,18 @@ import CONST from '@src/CONST';
1213
import ONYXKEYS from '@src/ONYXKEYS';
1314
import ROUTES from '@src/ROUTES';
1415
import {useSplashScreenState} from '@src/SplashScreenStateContext';
16+
import useUpdateGpsTripOnReconnect from './useUpdateGpsTripOnReconnect';
1517

1618
function GPSTripStateChecker() {
1719
const {translate} = useLocalize();
1820
const [showContinueTripModal, setShowContinueTripModal] = useState(false);
1921
const [gpsDraftDetails] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS, {canBeMissing: true});
22+
const {isOffline} = useNetwork();
2023

2124
const {splashScreenState} = useSplashScreenState();
2225

26+
useUpdateGpsTripOnReconnect();
27+
2328
useEffect(() => {
2429
async function handleGpsTripInProgressOnAppRestart() {
2530
const gpsTrip = await OnyxUtils.get(ONYXKEYS.GPS_DRAFT_DETAILS);
@@ -72,7 +77,7 @@ function GPSTripStateChecker() {
7277

7378
const onViewTrip = () => {
7479
setShowContinueTripModal(false);
75-
stopGpsTrip();
80+
stopGpsTrip(isOffline);
7681
navigateToGpsScreen();
7782
};
7883

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import useNetwork from '@hooks/useNetwork';
2+
import useOnyx from '@hooks/useOnyx';
3+
import {setEndAddress, setStartAddress} from '@libs/actions/GPSDraftDetails';
4+
import {addressFromGpsPoint} from '@libs/GPSDraftDetailsUtils';
5+
import ONYXKEYS from '@src/ONYXKEYS';
6+
import type {GpsDraftDetails} from '@src/types/onyx';
7+
8+
function useUpdateGpsTripOnReconnect() {
9+
const [gpsDraftDetails] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS, {canBeMissing: true});
10+
11+
const updateAddressToHumanReadable = async (gpsPoint: GpsDraftDetails['gpsPoints'][number] | undefined, setAddress: typeof setStartAddress) => {
12+
if (!gpsPoint) {
13+
return;
14+
}
15+
16+
const address = await addressFromGpsPoint(gpsPoint);
17+
18+
if (address !== null) {
19+
setAddress({value: address, type: 'address'});
20+
}
21+
};
22+
23+
const updateAddressesToHumanReadable = () => {
24+
if (!gpsDraftDetails) {
25+
return;
26+
}
27+
28+
const {gpsPoints, startAddress, endAddress} = gpsDraftDetails;
29+
30+
if (startAddress.type === 'coordinates') {
31+
updateAddressToHumanReadable(gpsPoints.at(0), setStartAddress);
32+
}
33+
34+
if (endAddress.type === 'coordinates') {
35+
updateAddressToHumanReadable(gpsPoints.at(-1), setEndAddress);
36+
}
37+
};
38+
39+
// This is intentional to use async/await pattern for better readability
40+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
41+
useNetwork({onReconnect: updateAddressesToHumanReadable});
42+
}
43+
44+
export default useUpdateGpsTripOnReconnect;

src/libs/GPSDraftDetailsUtils.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ function coordinatesToString(gpsPoint: {lat: number; long: number}): string {
9191
return `${gpsPoint.lat},${gpsPoint.long}`;
9292
}
9393

94-
async function stopGpsTrip() {
94+
async function stopGpsTrip(isOffline: boolean) {
9595
const isBackgroundTaskRunning = await hasStartedLocationUpdatesAsync(BACKGROUND_LOCATION_TRACKING_TASK_NAME);
9696

9797
if (isBackgroundTaskRunning) {
@@ -108,15 +108,17 @@ async function stopGpsTrip() {
108108
return;
109109
}
110110

111-
const endAddress = await addressFromGpsPoint(lastPoint);
111+
if (!isOffline) {
112+
const endAddress = await addressFromGpsPoint(lastPoint);
112113

113-
if (endAddress === null) {
114-
const formattedCoordinates = coordinatesToString(lastPoint);
115-
setEndAddress({value: formattedCoordinates, type: 'coordinates'});
116-
return;
114+
if (endAddress !== null) {
115+
setEndAddress({value: endAddress, type: 'address'});
116+
return;
117+
}
117118
}
118119

119-
setEndAddress({value: endAddress, type: 'address'});
120+
const formattedCoordinates = coordinatesToString(lastPoint);
121+
setEndAddress({value: formattedCoordinates, type: 'coordinates'});
120122
}
121123

122124
export {getGPSRoutes, getGPSWaypoints, stopGpsTrip, getGPSConvertedDistance, getGPSCoordinates, addressFromGpsPoint, coordinatesToString, calculateGPSDistance};

src/pages/iou/request/step/IOURequestStepDistanceGPS/GPSButtons/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ConfirmModal from '@components/ConfirmModal';
66
import {loadIllustration} from '@components/Icon/IllustrationLoader';
77
import {useMemoizedLazyAsset} from '@hooks/useLazyAsset';
88
import useLocalize from '@hooks/useLocalize';
9+
import useNetwork from '@hooks/useNetwork';
910
import useOnyx from '@hooks/useOnyx';
1011
import useThemeStyles from '@hooks/useThemeStyles';
1112
import {initGpsDraft, resetGPSDraftDetails} from '@libs/actions/GPSDraftDetails';
@@ -29,6 +30,7 @@ function GPSButtons({navigateToNextStep, setShouldShowStartError, setShouldShowP
2930
const [showStopConfirmation, setShowStopConfirmation] = useState(false);
3031
const [showZeroDistanceModal, setShowZeroDistanceModal] = useState(false);
3132
const [showDisabledServicesModal, setShowDisabledServicesModal] = useState(false);
33+
const {isOffline} = useNetwork();
3234

3335
const {asset: ReceiptLocationMarker} = useMemoizedLazyAsset(() => loadIllustration('ReceiptLocationMarker'));
3436
const [gpsDraftDetails] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS, {canBeMissing: true});
@@ -129,7 +131,7 @@ function GPSButtons({navigateToNextStep, setShouldShowStartError, setShouldShowP
129131
isVisible={showStopConfirmation}
130132
onConfirm={() => {
131133
setShowStopConfirmation(false);
132-
stopGpsTrip();
134+
stopGpsTrip(isOffline);
133135
}}
134136
onCancel={() => setShowStopConfirmation(false)}
135137
confirmText={translate('gps.stopGpsTrackingModal.confirm')}

src/setup/backgroundLocationTrackingTask/index.native.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {addGpsPoints, setStartAddress} from '@libs/actions/GPSDraftDetails';
55
import {addressFromGpsPoint, coordinatesToString} from '@libs/GPSDraftDetailsUtils';
66
import {BACKGROUND_LOCATION_TRACKING_TASK_NAME} from '@pages/iou/request/step/IOURequestStepDistanceGPS/const';
77
import ONYXKEYS from '@src/ONYXKEYS';
8+
import type {GpsDraftDetails} from '@src/types/onyx';
89

910
type BackgroundLocationTrackingTaskData = {locations: LocationObject[]};
1011

@@ -14,25 +15,32 @@ defineTask<BackgroundLocationTrackingTaskData>(BACKGROUND_LOCATION_TRACKING_TASK
1415
return;
1516
}
1617

17-
const gpsDraftDetails = await OnyxUtils.get(ONYXKEYS.GPS_DRAFT_DETAILS);
18+
const [gpsDraftDetailsPromiseResult, networkPromiseResult] = await Promise.allSettled([OnyxUtils.get(ONYXKEYS.GPS_DRAFT_DETAILS), OnyxUtils.get(ONYXKEYS.NETWORK)]);
1819

19-
const currentPoints = gpsDraftDetails?.gpsPoints ?? [];
20+
const gpsDraftDetails = gpsDraftDetailsPromiseResult.status === 'fulfilled' ? gpsDraftDetailsPromiseResult.value : undefined;
21+
const network = networkPromiseResult.status === 'fulfilled' ? networkPromiseResult.value : undefined;
22+
const isOffline = network?.isOffline ?? false;
2023

21-
if (currentPoints.length === 0) {
22-
const startPoint = data.locations.at(0);
23-
24-
if (startPoint) {
25-
const address = await addressFromGpsPoint({lat: startPoint.coords.latitude, long: startPoint.coords.longitude});
26-
27-
if (address !== null) {
28-
setStartAddress({value: address, type: 'address'});
29-
} else {
30-
setStartAddress({value: coordinatesToString({lat: startPoint.coords.latitude, long: startPoint.coords.longitude}), type: 'coordinates'});
31-
}
32-
}
33-
}
24+
updateStartAddress(gpsDraftDetails?.gpsPoints ?? [], data.locations.at(0), isOffline);
3425

3526
const newGpsPoints = data.locations.map((location) => ({lat: location.coords.latitude, long: location.coords.longitude}));
3627

3728
addGpsPoints(gpsDraftDetails, newGpsPoints);
3829
});
30+
31+
async function updateStartAddress(currentGpsPoints: GpsDraftDetails['gpsPoints'], startPoint: LocationObject | undefined, isOffline: boolean) {
32+
if (currentGpsPoints.length !== 0 || !startPoint) {
33+
return;
34+
}
35+
36+
if (!isOffline) {
37+
const address = await addressFromGpsPoint({lat: startPoint.coords.latitude, long: startPoint.coords.longitude});
38+
39+
if (address !== null) {
40+
setStartAddress({value: address, type: 'address'});
41+
return;
42+
}
43+
}
44+
45+
setStartAddress({value: coordinatesToString({lat: startPoint.coords.latitude, long: startPoint.coords.longitude}), type: 'coordinates'});
46+
}

0 commit comments

Comments
 (0)