Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Use local Onyx key to throttle location permission prompts. #48237

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ const ONYXKEYS = {
/** The NVP with the last payment method used per policy */
NVP_LAST_PAYMENT_METHOD: 'nvp_private_lastPaymentMethod',

/** Last date (yyyy-MM-dd HH:mm:ss) when the location permission prompt was shown. */
NVP_LAST_LOCATION_PERMISSION_PROMPT: 'nvp_lastLocalPermissionPrompt',

/** This NVP holds to most recent waypoints that a person has used when creating a distance expense */
NVP_RECENT_WAYPOINTS: 'nvp_expensify_recentWaypoints',

Expand Down Expand Up @@ -881,6 +884,7 @@ type OnyxValuesMapping = {
[ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION]: boolean;
[ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean;
[ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: OnyxTypes.LastPaymentMethod;
[ONYXKEYS.NVP_LAST_LOCATION_PERMISSION_PROMPT]: string;
[ONYXKEYS.LAST_EXPORT_METHOD]: OnyxTypes.LastExportMethod;
[ONYXKEYS.NVP_RECENT_WAYPOINTS]: OnyxTypes.RecentWaypoint[];
[ONYXKEYS.NVP_INTRO_SELECTED]: OnyxTypes.IntroSelected;
Expand Down
22 changes: 22 additions & 0 deletions src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
addHours,
addMilliseconds,
addMinutes,
differenceInDays,
eachDayOfInterval,
eachMonthOfInterval,
endOfDay,
Expand Down Expand Up @@ -819,6 +820,25 @@ function isCardExpired(expiryMonth: number, expiryYear: number): boolean {
return expiryYear < currentYear || (expiryYear === currentYear && expiryMonth < currentMonth);
}

/**
* Returns the difference in the number of days from the provided date to/from now.
* @param - The date to compare.
* @returns The difference in days as an integer.
*/
function getDifferenceInDaysFromNow(date: Date) {
return differenceInDays(new Date(), date);
}

/**
* Returns a boolean value indicating whether the provided date string can be parsed as a valid date.
* @param dateString string
* @returns True if the date string is valid, otherwise false.
*/
function isValidDateString(dateString: string) {
const date = new Date(dateString);
return !Number.isNaN(date.getTime());
}

const DateUtils = {
isDate,
formatToDayOfWeek,
Expand Down Expand Up @@ -864,6 +884,8 @@ const DateUtils = {
getFormattedTransportDate,
doesDateBelongToAPastYear,
isCardExpired,
getDifferenceInDaysFromNow,
isValidDateString,
};

export default DateUtils;
5 changes: 5 additions & 0 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8171,6 +8171,10 @@ function mergeDuplicates(params: TransactionMergeParams) {
API.write(WRITE_COMMANDS.TRANSACTION_MERGE, params, {optimisticData, failureData});
}

function updateLastLocationPermissionPrompt() {
Onyx.set(ONYXKEYS.NVP_LAST_LOCATION_PERMISSION_PROMPT, new Date().toISOString());
}

export {
adjustRemainingSplitShares,
approveMoneyRequest,
Expand Down Expand Up @@ -8241,5 +8245,6 @@ export {
updateMoneyRequestTaxAmount,
updateMoneyRequestTaxRate,
mergeDuplicates,
updateLastLocationPermissionPrompt,
};
export type {GPSPoint as GpsPoint, IOURequestType};
25 changes: 20 additions & 5 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx, withOnyx} from 'react-native-onyx';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
Expand All @@ -15,6 +15,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import DateUtils from '@libs/DateUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as FileUtils from '@libs/fileDownload/FileUtils';
import getCurrentPosition from '@libs/getCurrentPosition';
Expand Down Expand Up @@ -92,6 +93,7 @@ function IOURequestStepConfirmation({
const [receiptFile, setReceiptFile] = useState<OnyxEntry<Receipt>>();
const requestType = TransactionUtils.getRequestType(transaction);
const isDistanceRequest = requestType === CONST.IOU.REQUEST_TYPE.DISTANCE;
const [lastLocationPermissionPrompt] = useOnyx(ONYXKEYS.NVP_LAST_LOCATION_PERMISSION_PROMPT);

const receiptFilename = transaction?.filename;
const receiptPath = transaction?.receipt?.source;
Expand Down Expand Up @@ -585,9 +587,16 @@ function IOURequestStepConfirmation({

const onConfirm = (listOfParticipants: Participant[]) => {
setSelectedParticipantList(listOfParticipants);

if (gpsRequired) {
setStartLocationPermissionFlow(true);
return;
const shouldStartLocationPermissionFlow =
!lastLocationPermissionPrompt ||
(DateUtils.isValidDateString(lastLocationPermissionPrompt ?? '') && DateUtils.getDifferenceInDaysFromNow(new Date(lastLocationPermissionPrompt ?? '')) > 7);
Krishna2323 marked this conversation as resolved.
Show resolved Hide resolved

if (shouldStartLocationPermissionFlow) {
setStartLocationPermissionFlow(true);
return;
}
}

createTransaction(listOfParticipants);
Expand Down Expand Up @@ -621,8 +630,14 @@ function IOURequestStepConfirmation({
<LocationPermissionModal
startPermissionFlow={startLocationPermissionFlow}
resetPermissionFlow={() => setStartLocationPermissionFlow(false)}
onGrant={() => createTransaction(selectedParticipantList, true)}
onDeny={() => createTransaction(selectedParticipantList, false)}
onGrant={() => {
IOU.updateLastLocationPermissionPrompt();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krishna2323 Why should I set the permission key on Granting access?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because if the user disables the permission from setting after granting, we will be showing the permission modal again.

createTransaction(selectedParticipantList, true);
}}
onDeny={() => {
IOU.updateLastLocationPermissionPrompt();
createTransaction(selectedParticipantList, false);
}}
/>
)}
<MoneyRequestConfirmationList
Expand Down
Loading