From ff7c40a94e43258084c7ea9dda6c67299a17e87a Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 29 Oct 2025 15:11:09 +0100 Subject: [PATCH 01/24] getCurrentPosition() using expo-location library --- package-lock.json | 10 ++++ package.json | 1 + .../getCurrentPosition.types.ts | 39 +++++-------- src/libs/getCurrentPosition/index.android.ts | 55 ------------------- src/libs/getCurrentPosition/index.desktop.ts | 2 +- src/libs/getCurrentPosition/index.ios.ts | 14 ----- src/libs/getCurrentPosition/index.ts | 34 +++++++----- 7 files changed, 47 insertions(+), 108 deletions(-) delete mode 100644 src/libs/getCurrentPosition/index.android.ts delete mode 100644 src/libs/getCurrentPosition/index.ios.ts diff --git a/package-lock.json b/package-lock.json index ff445d1073a89..0594f12282941 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,6 +70,7 @@ "expo-font": "^13.0.4", "expo-image": "3.0.8", "expo-image-manipulator": "^13.1.5", + "expo-location": "^19.0.7", "expo-modules-core": "2.4.0", "expo-secure-store": "~14.2.4", "fast-equals": "^5.2.2", @@ -21980,6 +21981,15 @@ "react": "*" } }, + "node_modules/expo-location": { + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-19.0.7.tgz", + "integrity": "sha512-YNkh4r9E6ECbPkBCAMG5A5yHDgS0pw+Rzyd0l2ZQlCtjkhlODB55nMCKr5CZnUI0mXTkaSm8CwfoCO8n2MpYfg==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.1.11.tgz", diff --git a/package.json b/package.json index d61d84c220cc2..0af60e7f940d6 100644 --- a/package.json +++ b/package.json @@ -141,6 +141,7 @@ "expo-font": "^13.0.4", "expo-image": "3.0.8", "expo-image-manipulator": "^13.1.5", + "expo-location": "^19.0.7", "expo-modules-core": "2.4.0", "expo-secure-store": "~14.2.4", "fast-equals": "^5.2.2", diff --git a/src/libs/getCurrentPosition/getCurrentPosition.types.ts b/src/libs/getCurrentPosition/getCurrentPosition.types.ts index a84dc2f0c7815..ae155624db140 100644 --- a/src/libs/getCurrentPosition/getCurrentPosition.types.ts +++ b/src/libs/getCurrentPosition/getCurrentPosition.types.ts @@ -1,3 +1,4 @@ +import type {LocationOptions} from 'expo-location'; import type {ValueOf} from 'type-fest'; type GeolocationSuccessCallback = (position: { @@ -5,7 +6,7 @@ type GeolocationSuccessCallback = (position: { latitude: number; longitude: number; altitude: number | null; - accuracy: number; + accuracy: number | null; altitudeAccuracy: number | null; heading: number | null; speed: number | null; @@ -15,16 +16,7 @@ type GeolocationSuccessCallback = (position: { type GeolocationErrorCodeType = ValueOf | null; -type GeolocationErrorCallback = (error?: { - code: GeolocationErrorCodeType; - message: string; - PERMISSION_DENIED: typeof GeolocationErrorCode.PERMISSION_DENIED; - POSITION_UNAVAILABLE: typeof GeolocationErrorCode.POSITION_UNAVAILABLE; - TIMEOUT: typeof GeolocationErrorCode.TIMEOUT; - - /* Web only */ - NOT_SUPPORTED?: typeof GeolocationErrorCode.NOT_SUPPORTED; -}) => void; +type GeolocationErrorCallback = (error?: {code: GeolocationErrorCodeType; message: string}) => void; const GeolocationErrorCode = { PERMISSION_DENIED: 1, @@ -33,25 +25,22 @@ const GeolocationErrorCode = { NOT_SUPPORTED: -1, }; +/** + * Used for desktop implementation of getCurrentPosition() which uses the Geolocation API. + * {@link https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition#options} + */ type GeolocationOptions = { + /** Desktop only */ timeout?: number; - maximumAge?: number; - enableHighAccuracy?: boolean; - - /** Native only */ - distanceFilter?: number; - /** Native only */ - useSignificantChanges?: boolean; - - /** Native only */ - interval?: number; + /** Desktop only */ + maximumAge?: number; - /** Native only */ - fastestInterval?: number; -}; + /** Desktop only */ + enableHighAccuracy?: boolean; +} & LocationOptions; -type GetCurrentPosition = (success: GeolocationSuccessCallback, error: GeolocationErrorCallback, options?: GeolocationOptions) => void; +type GetCurrentPosition = (success: GeolocationSuccessCallback, error: GeolocationErrorCallback, options?: GeolocationOptions) => Promise; export {GeolocationErrorCode}; diff --git a/src/libs/getCurrentPosition/index.android.ts b/src/libs/getCurrentPosition/index.android.ts deleted file mode 100644 index 8b0d1c76d25fe..0000000000000 --- a/src/libs/getCurrentPosition/index.android.ts +++ /dev/null @@ -1,55 +0,0 @@ -// https://github.com/Richou/react-native-android-location-enabler/issues/40 -// If we update our react native version, we need to test this file again -import Geolocation from '@react-native-community/geolocation'; -import {promptForEnableLocationIfNeeded} from 'react-native-android-location-enabler'; -import type {GetCurrentPosition} from './getCurrentPosition.types'; -import {GeolocationErrorCode} from './getCurrentPosition.types'; - -Geolocation.setRNConfiguration({ - skipPermissionRequests: false, - authorizationLevel: 'whenInUse', - locationProvider: 'auto', -}); - -const getCurrentPosition: GetCurrentPosition = (success, error, config) => { - // Prompt's the user to enable geolocation permission with yes/no options - // If the user selects yes, then this module would enable the native system location - // Otherwise if user selects no, or we have an issue displaying the prompt, it will return an error - promptForEnableLocationIfNeeded({ - interval: 2000, // This updates location after every 2 seconds (required prop). We don't depend on this as we only use the location once. - }) - .then((permissionState) => { - if (permissionState === 'enabled') { - // If the user just enabled the permission by clicking 'Ok', sometimes we need to wait before - // the native system location/gps is setup, this is usually device specific, but a wait of a few - // milliseconds will be enough. Currently its using 500ms, it seemed enough for Android 12 test - // device. In rare cases when the device takes longer than 500ms, then Geolocation.getCurrentPosition - // will throw an error in which case the user can always call the action again to retry (but its rare). - setTimeout(() => { - Geolocation.getCurrentPosition(success, error, config); - }, 500); - return; - } - - // if location permission is 'already-enabled', then directly get the updated location. - Geolocation.getCurrentPosition(success, error, config); - }) - .catch(() => { - // An error here can be because of these reasons - // 1. User denied location permission - // 2. Failure to open the permission dialog - // 3. Device location settings can't be changed or the device doesn't support some location settings - // 4. Any internal error - // For all of these we will return a permission denied error. - error({ - code: GeolocationErrorCode.PERMISSION_DENIED, - message: 'Geolocation is not supported by this environment.', - PERMISSION_DENIED: GeolocationErrorCode.PERMISSION_DENIED, - POSITION_UNAVAILABLE: GeolocationErrorCode.POSITION_UNAVAILABLE, - TIMEOUT: GeolocationErrorCode.TIMEOUT, - NOT_SUPPORTED: GeolocationErrorCode.NOT_SUPPORTED, - }); - }); -}; - -export default getCurrentPosition; diff --git a/src/libs/getCurrentPosition/index.desktop.ts b/src/libs/getCurrentPosition/index.desktop.ts index 1a2d8b1fb73c0..7f0f060bccbce 100644 --- a/src/libs/getCurrentPosition/index.desktop.ts +++ b/src/libs/getCurrentPosition/index.desktop.ts @@ -16,7 +16,7 @@ const makeError = (code: ValueOf, message: string) const isLocationPermissionState = (status: unknown): status is LocationPermissionState => typeof status === 'string' && Object.values(LOCATION_PERMISSION_STATES).includes(status as LocationPermissionState); -const getCurrentPosition: GetCurrentPosition = (success, error, options) => { +const getCurrentPosition: GetCurrentPosition = async (success, error, options) => { const doGeoRequest = () => { try { navigator.geolocation.getCurrentPosition(success, error, options); diff --git a/src/libs/getCurrentPosition/index.ios.ts b/src/libs/getCurrentPosition/index.ios.ts deleted file mode 100644 index e64abb0d4329e..0000000000000 --- a/src/libs/getCurrentPosition/index.ios.ts +++ /dev/null @@ -1,14 +0,0 @@ -import Geolocation from '@react-native-community/geolocation'; -import type {GetCurrentPosition} from './getCurrentPosition.types'; - -Geolocation.setRNConfiguration({ - skipPermissionRequests: false, - authorizationLevel: 'whenInUse', - locationProvider: 'auto', -}); - -const getCurrentPosition: GetCurrentPosition = (success, error, config) => { - Geolocation.getCurrentPosition(success, error, config); -}; - -export default getCurrentPosition; diff --git a/src/libs/getCurrentPosition/index.ts b/src/libs/getCurrentPosition/index.ts index 318d4f64ed344..9e5afe9d1112b 100644 --- a/src/libs/getCurrentPosition/index.ts +++ b/src/libs/getCurrentPosition/index.ts @@ -1,20 +1,28 @@ -import type {GetCurrentPosition} from './getCurrentPosition.types'; +import {getCurrentPositionAsync, PermissionStatus, requestForegroundPermissionsAsync} from 'expo-location'; +import type {PermissionResponse} from 'expo-location'; import {GeolocationErrorCode} from './getCurrentPosition.types'; +import type {GetCurrentPosition} from './getCurrentPosition.types'; + +const getCurrentPosition: GetCurrentPosition = async (success, error, options) => { + const foregroundPermissionResponse: PermissionResponse = await requestForegroundPermissionsAsync(); -const getCurrentPosition: GetCurrentPosition = (success, error, options) => { - if (navigator === undefined || !('geolocation' in navigator)) { - error({ - code: GeolocationErrorCode.NOT_SUPPORTED, - message: 'Geolocation is not supported by this environment.', - PERMISSION_DENIED: GeolocationErrorCode.PERMISSION_DENIED, - POSITION_UNAVAILABLE: GeolocationErrorCode.POSITION_UNAVAILABLE, - TIMEOUT: GeolocationErrorCode.TIMEOUT, - NOT_SUPPORTED: GeolocationErrorCode.NOT_SUPPORTED, - }); - return; + if (foregroundPermissionResponse.status !== PermissionStatus.GRANTED) { + error({code: GeolocationErrorCode.PERMISSION_DENIED, message: 'Geolocation is not supported by this environment.'}); } - navigator.geolocation.getCurrentPosition(success, error, options); + try { + const currentPosition = await getCurrentPositionAsync(options); + success(currentPosition); + } catch (caughtError) { + let message = 'Geolocation call failed'; + if (caughtError instanceof Error) { + message = caughtError.message; + } else if (typeof caughtError === 'string') { + message = caughtError; + } + + error({code: GeolocationErrorCode.POSITION_UNAVAILABLE, message}); + } }; export default getCurrentPosition; From af21aba40789005ca504ec9f68da9ee8cf5d351e Mon Sep 17 00:00:00 2001 From: GCyganek Date: Mon, 3 Nov 2025 18:29:16 +0100 Subject: [PATCH 02/24] Simplify makeError and delete misleading comment --- src/libs/getCurrentPosition/getCurrentPosition.types.ts | 4 ---- src/libs/getCurrentPosition/index.desktop.ts | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/libs/getCurrentPosition/getCurrentPosition.types.ts b/src/libs/getCurrentPosition/getCurrentPosition.types.ts index ae155624db140..54fbbff96c526 100644 --- a/src/libs/getCurrentPosition/getCurrentPosition.types.ts +++ b/src/libs/getCurrentPosition/getCurrentPosition.types.ts @@ -25,10 +25,6 @@ const GeolocationErrorCode = { NOT_SUPPORTED: -1, }; -/** - * Used for desktop implementation of getCurrentPosition() which uses the Geolocation API. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition#options} - */ type GeolocationOptions = { /** Desktop only */ timeout?: number; diff --git a/src/libs/getCurrentPosition/index.desktop.ts b/src/libs/getCurrentPosition/index.desktop.ts index 7f0f060bccbce..964248e8708aa 100644 --- a/src/libs/getCurrentPosition/index.desktop.ts +++ b/src/libs/getCurrentPosition/index.desktop.ts @@ -7,10 +7,6 @@ import {LOCATION_PERMISSION_STATES} from './locationPermission'; const makeError = (code: ValueOf, message: string) => ({ code, message, - PERMISSION_DENIED: GeolocationErrorCode.PERMISSION_DENIED, - POSITION_UNAVAILABLE: GeolocationErrorCode.POSITION_UNAVAILABLE, - TIMEOUT: GeolocationErrorCode.TIMEOUT, - NOT_SUPPORTED: GeolocationErrorCode.NOT_SUPPORTED, }); const isLocationPermissionState = (status: unknown): status is LocationPermissionState => From ecd692145ca266f74605ba01d34861d24373beac Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 4 Nov 2025 15:32:47 +0100 Subject: [PATCH 03/24] Fix gpsPoints not being passed correctly --- .../iou/request/step/IOURequestStepScan/index.native.tsx | 8 ++------ src/pages/iou/request/step/IOURequestStepScan/index.tsx | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 225404d2c9199..8738b283dea8b 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -327,7 +327,7 @@ function IOURequestStepScan({ receipt, billable, reimbursable, - ...(gpsPoints ?? {}), + gpsPoints, }, ...(policyParams ?? {}), shouldHandleNavigation: index === files.length - 1, @@ -341,7 +341,7 @@ function IOURequestStepScan({ participant, }, ...(policyParams ?? {}), - ...(gpsPoints ?? {}), + gpsPoints, transactionParams: { amount: 0, attendees: transaction?.comment?.attendees, @@ -442,10 +442,6 @@ function IOURequestStepScan({ // When there is an error, the money can still be requested, it just won't include the GPS coordinates createTransaction(files, participant); }, - { - maximumAge: CONST.GPS.MAX_AGE, - timeout: CONST.GPS.TIMEOUT, - }, ); return; } diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index fdd193a7c4ab2..d65782c2c8e30 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -386,7 +386,7 @@ function IOURequestStepScan({ receipt, billable, reimbursable, - ...(gpsPoints ?? {}), + gpsPoints, }, ...(policyParams ?? {}), shouldHandleNavigation: index === files.length - 1, @@ -400,7 +400,7 @@ function IOURequestStepScan({ participant, }, ...(policyParams ?? {}), - ...(gpsPoints ?? {}), + gpsPoints, transactionParams: { amount: 0, attendees: transaction?.comment?.attendees, From d340c1b7846060bb0b98241bb18144b8ad21abd7 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 4 Nov 2025 16:07:40 +0100 Subject: [PATCH 04/24] Remove @react-native-community/geolocation --- package-lock.json | 26 ------------------- package.json | 2 -- tests/ui/AddressPageTest.tsx | 4 --- tests/ui/AssignCardFeedPage.tsx | 4 --- tests/ui/IOURequestStartPageTest.tsx | 4 --- tests/ui/MoneyRequestReportPreview.test.tsx | 4 --- tests/ui/OnboardingEmployees.tsx | 4 --- tests/ui/ReportAttachments.tsx | 4 --- tests/ui/WorkEmailOnboarding.tsx | 4 --- .../IOURequestStepConfirmationPageTest.tsx | 3 --- tests/unit/OptionsListUtilsTest.tsx | 4 --- tests/unit/PaymentCardFormTest.tsx | 4 --- tests/unit/useSearchHighlightAndScrollTest.ts | 6 ----- 13 files changed, 73 deletions(-) diff --git a/package-lock.json b/package-lock.json index e24c8c9c957c3..a56021860880b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,6 @@ "@pusher/pusher-websocket-react-native": "^1.3.1", "@react-native-camera-roll/camera-roll": "7.4.0", "@react-native-clipboard/clipboard": "^1.15.0", - "@react-native-community/geolocation": "3.3.0", "@react-native-community/netinfo": "11.2.1", "@react-native-documents/picker": "^10.1.3", "@react-native-firebase/analytics": "^22.2.1", @@ -99,7 +98,6 @@ "react-map-gl": "^7.1.3", "react-native": "0.81.4", "react-native-advanced-input-mask": "1.4.6", - "react-native-android-location-enabler": "^3.0.1", "react-native-app-logs": "0.3.1", "react-native-blob-util": "0.22.2", "react-native-collapsible": "^1.6.2", @@ -10488,17 +10486,6 @@ "node": ">= 4.0.0" } }, - "node_modules/@react-native-community/geolocation": { - "version": "3.3.0", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, "node_modules/@react-native-community/netinfo": { "version": "11.2.1", "license": "MIT", @@ -32890,19 +32877,6 @@ "react-native": "*" } }, - "node_modules/react-native-android-location-enabler": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/react-native-android-location-enabler/-/react-native-android-location-enabler-3.0.1.tgz", - "integrity": "sha512-X4gHdEFf/dqSNhVDQ2cQUibnNRd6xIG34UGDMnwoCKIPLC2wYzALs/gPrDnjrAWsuxjaleZXwUIrX3o9nbtsgw==", - "license": "MIT", - "workspaces": [ - "example" - ], - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, "node_modules/react-native-app-logs": { "version": "0.3.1", "license": "MIT", diff --git a/package.json b/package.json index 9c63d3b4c5d0c..6ea390163838e 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,6 @@ "@pusher/pusher-websocket-react-native": "^1.3.1", "@react-native-camera-roll/camera-roll": "7.4.0", "@react-native-clipboard/clipboard": "^1.15.0", - "@react-native-community/geolocation": "3.3.0", "@react-native-community/netinfo": "11.2.1", "@react-native-documents/picker": "^10.1.3", "@react-native-firebase/analytics": "^22.2.1", @@ -169,7 +168,6 @@ "react-map-gl": "^7.1.3", "react-native": "0.81.4", "react-native-advanced-input-mask": "1.4.6", - "react-native-android-location-enabler": "^3.0.1", "react-native-app-logs": "0.3.1", "react-native-blob-util": "0.22.2", "react-native-collapsible": "^1.6.2", diff --git a/tests/ui/AddressPageTest.tsx b/tests/ui/AddressPageTest.tsx index c607d354988cb..b10f1ebd181fa 100644 --- a/tests/ui/AddressPageTest.tsx +++ b/tests/ui/AddressPageTest.tsx @@ -24,10 +24,6 @@ jest.mock('@rnmapbox/maps', () => { }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - const Stack = createPlatformStackNavigator(); const renderPage = (initialRouteName: typeof SCREENS.SETTINGS.PROFILE.ADDRESS) => { diff --git a/tests/ui/AssignCardFeedPage.tsx b/tests/ui/AssignCardFeedPage.tsx index 9ea1d8ae61516..0c8a9dc17df39 100644 --- a/tests/ui/AssignCardFeedPage.tsx +++ b/tests/ui/AssignCardFeedPage.tsx @@ -38,10 +38,6 @@ jest.mock('@rnmapbox/maps', () => { }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - jest.mock('react-native-plaid-link-sdk', () => ({ dismissLink: jest.fn(), openLink: jest.fn(), diff --git a/tests/ui/IOURequestStartPageTest.tsx b/tests/ui/IOURequestStartPageTest.tsx index e6dec5ce08617..31d9d2aa104fa 100644 --- a/tests/ui/IOURequestStartPageTest.tsx +++ b/tests/ui/IOURequestStartPageTest.tsx @@ -27,10 +27,6 @@ jest.mock('react-native-tab-view', () => ({ TabBar: 'TabBar', })); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - jest.mock('react-native-vision-camera', () => ({ useCameraDevice: jest.fn(), })); diff --git a/tests/ui/MoneyRequestReportPreview.test.tsx b/tests/ui/MoneyRequestReportPreview.test.tsx index 983bd6af16c07..0075de02c17e6 100644 --- a/tests/ui/MoneyRequestReportPreview.test.tsx +++ b/tests/ui/MoneyRequestReportPreview.test.tsx @@ -37,10 +37,6 @@ jest.mock('@rnmapbox/maps', () => { }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - jest.mock('@src/hooks/useReportWithTransactionsAndViolations', () => jest.fn((): [OnyxEntry, Transaction[], OnyxCollection] => { return [mockChatReport, [mockTransaction, {...mockTransaction, transactionID: mockSecondTransactionID}], {violations: mockViolations}]; diff --git a/tests/ui/OnboardingEmployees.tsx b/tests/ui/OnboardingEmployees.tsx index 7075167a43c62..7a844676551c6 100644 --- a/tests/ui/OnboardingEmployees.tsx +++ b/tests/ui/OnboardingEmployees.tsx @@ -30,10 +30,6 @@ jest.mock('@rnmapbox/maps', () => { }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - TestHelper.setupGlobalFetchMock(); const Stack = createPlatformStackNavigator(); diff --git a/tests/ui/ReportAttachments.tsx b/tests/ui/ReportAttachments.tsx index b420334dc81ae..7aae70f2e69c8 100644 --- a/tests/ui/ReportAttachments.tsx +++ b/tests/ui/ReportAttachments.tsx @@ -32,10 +32,6 @@ jest.mock('@rnmapbox/maps', () => { setAccessToken: jest.fn(), }; }); - -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); jest.mock('@src/components/Attachments/AttachmentCarousel/Pager/usePageScrollHandler', () => jest.fn()); const renderPage = (initialRouteName: typeof SCREENS.REPORT_ATTACHMENTS, initialParams: AuthScreensParamList[typeof SCREENS.REPORT_ATTACHMENTS]) => { diff --git a/tests/ui/WorkEmailOnboarding.tsx b/tests/ui/WorkEmailOnboarding.tsx index 0ad303118ca89..65e39f4985a8d 100644 --- a/tests/ui/WorkEmailOnboarding.tsx +++ b/tests/ui/WorkEmailOnboarding.tsx @@ -42,10 +42,6 @@ jest.mock('@rnmapbox/maps', () => { }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - TestHelper.setupGlobalFetchMock(); const Stack = createPlatformStackNavigator(); diff --git a/tests/ui/components/IOURequestStepConfirmationPageTest.tsx b/tests/ui/components/IOURequestStepConfirmationPageTest.tsx index 57736af5bdf73..528d02bbaffec 100644 --- a/tests/ui/components/IOURequestStepConfirmationPageTest.tsx +++ b/tests/ui/components/IOURequestStepConfirmationPageTest.tsx @@ -18,9 +18,6 @@ jest.mock('@rnmapbox/maps', () => { setAccessToken: jest.fn(), }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); jest.mock('@libs/actions/IOU', () => { const actualNav = jest.requireActual('@libs/actions/IOU'); return { diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 714a5e1b790d3..0d699668820c9 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -65,10 +65,6 @@ jest.mock('@rnmapbox/maps', () => { }; }); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - jest.mock('@src/libs/Navigation/Navigation', () => ({ navigate: jest.fn(), dismissModal: jest.fn(), diff --git a/tests/unit/PaymentCardFormTest.tsx b/tests/unit/PaymentCardFormTest.tsx index c61dde67e725e..c845587c9e0c1 100644 --- a/tests/unit/PaymentCardFormTest.tsx +++ b/tests/unit/PaymentCardFormTest.tsx @@ -12,10 +12,6 @@ import AddPaymentCard from '@pages/settings/Subscription/PaymentCard'; import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), -})); - jest.mock('@libs/ReportUtils', () => ({ getReportIDFromLink: jest.fn(() => ''), parseReportRouteParams: jest.fn(() => ({reportID: ''})), diff --git a/tests/unit/useSearchHighlightAndScrollTest.ts b/tests/unit/useSearchHighlightAndScrollTest.ts index 4ed18359bcb10..60ed1a7f186d4 100644 --- a/tests/unit/useSearchHighlightAndScrollTest.ts +++ b/tests/unit/useSearchHighlightAndScrollTest.ts @@ -16,12 +16,6 @@ jest.mock('@rnmapbox/maps', () => ({ MarkerView: {}, setAccessToken: jest.fn(), })); -jest.mock('@react-native-community/geolocation', () => ({ - setRNConfiguration: jest.fn(), - getCurrentPosition: jest.fn(), - watchPosition: jest.fn(), - clearWatch: jest.fn(), -})); const mockUseIsFocused = jest.fn().mockReturnValue(true); From 862835140b64933b5c42f88f9801cef09fdf8025 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 4 Nov 2025 16:35:31 +0100 Subject: [PATCH 05/24] Update Podfile --- Mobile-Expensify | 2 +- ios/Podfile.lock | 62 +++++++++++++++++++----------------------------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 6bc6d49d38b4b..04e2aa998bf04 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 6bc6d49d38b4be2eb1b9f80ccf932e410b45d8b2 +Subproject commit 04e2aa998bf046c06f2e8848dd73dc1b1b565187 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d0255ff13c931..b1c970f6f4ffc 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -140,6 +140,8 @@ PODS: - EXImageLoader - ExpoModulesCore - SDWebImageWebPCoder + - ExpoLocation (19.0.7): + - ExpoModulesCore - ExpoModulesCore (3.0.18): - boost - DoubleConversion @@ -524,6 +526,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -549,6 +552,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -573,6 +577,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -599,6 +604,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -624,6 +630,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -649,6 +656,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -674,6 +682,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -699,6 +708,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -724,6 +734,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -749,6 +760,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -774,6 +786,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -799,6 +812,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -824,6 +838,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -849,6 +864,7 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger + - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -2405,34 +2421,6 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-geolocation (3.3.0): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - RCT-Folly/Fabric - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsi - - React-NativeModulesApple - - React-RCTFabric - - React-renderercss - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - SocketRocket - - Yoga - react-native-get-random-values (1.11.0): - React-Core - react-native-image-picker (7.1.2): @@ -4101,6 +4089,7 @@ DEPENDENCIES: - ExpoFont (from `../node_modules/expo-font/ios`) - ExpoImage (from `../node_modules/expo-image/ios`) - ExpoImageManipulator (from `../node_modules/expo-image-manipulator/ios`) + - ExpoLocation (from `../node_modules/expo-location/ios`) - ExpoModulesCore (from `../node_modules/expo-modules-core`) - ExpoSecureStore (from `../node_modules/expo-secure-store/ios`) - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) @@ -4157,7 +4146,6 @@ DEPENDENCIES: - "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)" - react-native-config (from `../node_modules/react-native-config`) - "react-native-document-picker (from `../node_modules/@react-native-documents/picker`)" - - "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)" - react-native-get-random-values (from `../node_modules/react-native-get-random-values`) - react-native-image-picker (from `../node_modules/react-native-image-picker`) - react-native-key-command (from `../node_modules/react-native-key-command`) @@ -4310,6 +4298,8 @@ EXTERNAL SOURCES: :path: "../node_modules/expo-image/ios" ExpoImageManipulator: :path: "../node_modules/expo-image-manipulator/ios" + ExpoLocation: + :path: "../node_modules/expo-location/ios" ExpoModulesCore: :path: "../node_modules/expo-modules-core" ExpoSecureStore: @@ -4419,8 +4409,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-config" react-native-document-picker: :path: "../node_modules/@react-native-documents/picker" - react-native-geolocation: - :path: "../node_modules/@react-native-community/geolocation" react-native-get-random-values: :path: "../node_modules/react-native-get-random-values" react-native-image-picker: @@ -4574,7 +4562,7 @@ SPEC CHECKSUMS: AirshipServiceExtension: 4c87a84223d347f27e16dbfa3c366fa25015747f AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73 AppLogs: 3bc4e9b141dbf265b9464409caaa40416a9ee0e0 - boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 + boost: 659a89341ea4ab3df8259733813b52f26d8be9a5 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb EXAV: 13d43af15268a3f448a6b994e91574c939f065e6 EXConstants: 59d46d25b89f88cc38291a56dbce4d550758f72d @@ -4586,6 +4574,7 @@ SPEC CHECKSUMS: ExpoFont: d3e56c7cc03d9fd113b90a5513ad32b4bf46b0ff ExpoImage: 306dd755c842dba9f3ee654c51834a9cc657e6ca ExpoImageManipulator: 7096d6bf874c0a0a649f60733fef8a99c4ad0fe2 + ExpoLocation: 1dc9e4c06ef66ed081348a11eb637d1dfecc7d61 ExpoModulesCore: 1f5cb7d443f5c12f9a53ce3e2e536a16ef4728a3 ExpoSecureStore: 833b24a0d7feffef4505184910c058221066011e fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 @@ -4643,7 +4632,7 @@ SPEC CHECKSUMS: React: 2073376f47c71b7e9a0af7535986a77522ce1049 React-callinvoker: 751b6f2c83347a0486391c3f266f291f0f53b27e React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a - React-Core: 7195661f0b48e7ea46c3360ccb575288a20c932c + React-Core: e311ba7bfc9203d887052d5a1be3d8564ee7dc2a React-CoreModules: 14f0054ab46000dd3b816d6528af3bd600d82073 React-cxxreact: 7f602425c63096c398dac13cd7a300efd7c281ae React-debug: d4955c86870792887ed695df6ebf0e94e39dc7e1 @@ -4677,7 +4666,6 @@ SPEC CHECKSUMS: react-native-cameraroll: 557bf71cccc7b97a2f1dc394615b9acca65951b9 react-native-config: e4214ee0806b12c2e5d7b1fd446813e0a2b05ce8 react-native-document-picker: 2b89e7ea851124ec30dd1877ecb2ea60a87735ec - react-native-geolocation: 0e370efd72cd46be05127f45246eea73ed9a5a9e react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06 react-native-image-picker: 86bf00a37006892936db36eb85f219f3084694fe react-native-key-command: ca3ff1a67082a3949790365798f0f4f05d29814a @@ -4695,7 +4683,7 @@ SPEC CHECKSUMS: react-native-webview: 5887b6094417c75a9bee446261f89c32adf6b602 React-NativeModulesApple: dcfbe72c5a47baec0699a2935c080b7de0c8657b React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d - React-perflogger: a03d913e3205b00aee4128082abe42fd45ce0c98 + React-perflogger: 0537875400b4e5b4b7f39b3bbb93bb404464d8c7 React-performancetimeline: e07fcee93986259c74a5be1a98770ed82086fe5b React-RCTActionSheet: 42195ae666e6d79b4af2346770f765b7c29435b9 React-RCTAnimation: 5c10527683128c56ff2c09297fb080f7c35bd293 @@ -4710,7 +4698,7 @@ SPEC CHECKSUMS: React-RCTSettings: b7f4a03f44dba1d3a4dc6770843547b203ca9129 React-RCTText: 91dc597a5f6b27fd1048bb287c41ea05eeca9333 React-RCTVibration: 27b09ddf74bddfa30a58d20e48f885ea6ed6c9d9 - React-rendererconsistency: 612d0f6603d9837bb1236d7fd5194203b35c8799 + React-rendererconsistency: bef28690433e2b4bb00c2f884b22b86e61a430f2 React-renderercss: 5cc9e5e6732dc124dee16b7ab8f48e0b60b3f31d React-rendererdebug: 224a1beff9e5d5bc537e72b454135006a5c02a52 React-RuntimeApple: 9bd8789d7b1d0b5502911da80943b3b2fddfe753 @@ -4760,4 +4748,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: b8d8822965874a00c1e9d5ce99cb02c3618245b2 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 From 16c35dfb13ccb8523117c9cb0044a9210ecec7e0 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 4 Nov 2025 16:38:38 +0100 Subject: [PATCH 06/24] Run CI From 2eace407554f36c878346190ddfff46420032ddc Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 10:30:54 +0100 Subject: [PATCH 07/24] Run CI From 3158a0a3b196413fd70157ba13ae4a538f7093df Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 10:53:30 +0100 Subject: [PATCH 08/24] Fix Podfile.lock cocoapods version --- ios/Podfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b1c970f6f4ffc..6edc762c44354 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -29,7 +29,7 @@ PODS: - AppLogs (0.1.0) - boost (1.84.0) - DoubleConversion (1.1.6) - - EXAV (15.1.5): + - EXAV (15.1.7): - ExpoModulesCore - ReactCommon/turbomodule/core - EXConstants (18.0.9): @@ -4564,7 +4564,7 @@ SPEC CHECKSUMS: AppLogs: 3bc4e9b141dbf265b9464409caaa40416a9ee0e0 boost: 659a89341ea4ab3df8259733813b52f26d8be9a5 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb - EXAV: 13d43af15268a3f448a6b994e91574c939f065e6 + EXAV: 28241f071fd70ea38d278d94096b61d893645946 EXConstants: 59d46d25b89f88cc38291a56dbce4d550758f72d EXImageLoader: ab4fcf9240cf3636a83c00e3fc5229d692899428 expensify-react-native-background-task: 01474352998b00f61c6fc81351c7e7b595058579 @@ -4748,4 +4748,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: b8d8822965874a00c1e9d5ce99cb02c3618245b2 -COCOAPODS: 1.16.2 +COCOAPODS: 1.15.2 From cdae7fad4425b03184114fcd4650c802297b9b91 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 11:11:26 +0100 Subject: [PATCH 09/24] Run CI From 1aed380aae9f3736ceb3f65811ed4ba60c35719b Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 11:27:18 +0100 Subject: [PATCH 10/24] Rerun jest tests From 86a8cf410a6d86d9e00703693bdf4e43b7870e93 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 15:04:49 +0100 Subject: [PATCH 11/24] Podfile.lock cleanup --- ios/Podfile.lock | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6edc762c44354..b901796f92080 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -526,7 +526,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -552,7 +551,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -577,7 +575,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -604,7 +601,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -630,7 +626,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -656,7 +651,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -682,7 +676,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -708,7 +701,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -734,7 +726,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -760,7 +751,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -786,7 +776,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -812,7 +801,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -838,7 +826,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -864,7 +851,6 @@ PODS: - React-jsinspectorcdp - React-jsitooling - React-perflogger - - React-rendererconsistency - React-runtimeexecutor - React-runtimescheduler - React-utils @@ -4562,7 +4548,7 @@ SPEC CHECKSUMS: AirshipServiceExtension: 4c87a84223d347f27e16dbfa3c366fa25015747f AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73 AppLogs: 3bc4e9b141dbf265b9464409caaa40416a9ee0e0 - boost: 659a89341ea4ab3df8259733813b52f26d8be9a5 + boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb EXAV: 28241f071fd70ea38d278d94096b61d893645946 EXConstants: 59d46d25b89f88cc38291a56dbce4d550758f72d @@ -4632,7 +4618,7 @@ SPEC CHECKSUMS: React: 2073376f47c71b7e9a0af7535986a77522ce1049 React-callinvoker: 751b6f2c83347a0486391c3f266f291f0f53b27e React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a - React-Core: e311ba7bfc9203d887052d5a1be3d8564ee7dc2a + React-Core: 7195661f0b48e7ea46c3360ccb575288a20c932c React-CoreModules: 14f0054ab46000dd3b816d6528af3bd600d82073 React-cxxreact: 7f602425c63096c398dac13cd7a300efd7c281ae React-debug: d4955c86870792887ed695df6ebf0e94e39dc7e1 @@ -4683,7 +4669,7 @@ SPEC CHECKSUMS: react-native-webview: 5887b6094417c75a9bee446261f89c32adf6b602 React-NativeModulesApple: dcfbe72c5a47baec0699a2935c080b7de0c8657b React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d - React-perflogger: 0537875400b4e5b4b7f39b3bbb93bb404464d8c7 + React-perflogger: a03d913e3205b00aee4128082abe42fd45ce0c98 React-performancetimeline: e07fcee93986259c74a5be1a98770ed82086fe5b React-RCTActionSheet: 42195ae666e6d79b4af2346770f765b7c29435b9 React-RCTAnimation: 5c10527683128c56ff2c09297fb080f7c35bd293 @@ -4698,7 +4684,7 @@ SPEC CHECKSUMS: React-RCTSettings: b7f4a03f44dba1d3a4dc6770843547b203ca9129 React-RCTText: 91dc597a5f6b27fd1048bb287c41ea05eeca9333 React-RCTVibration: 27b09ddf74bddfa30a58d20e48f885ea6ed6c9d9 - React-rendererconsistency: bef28690433e2b4bb00c2f884b22b86e61a430f2 + React-rendererconsistency: 612d0f6603d9837bb1236d7fd5194203b35c8799 React-renderercss: 5cc9e5e6732dc124dee16b7ab8f48e0b60b3f31d React-rendererdebug: 224a1beff9e5d5bc537e72b454135006a5c02a52 React-RuntimeApple: 9bd8789d7b1d0b5502911da80943b3b2fddfe753 From 1159a1bcc6f4cbc9d00d623548a013ec347c3649 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 15:47:00 +0100 Subject: [PATCH 12/24] Mobile-Expensify --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 04e2aa998bf04..2c47c8396bcbf 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 04e2aa998bf046c06f2e8848dd73dc1b1b565187 +Subproject commit 2c47c8396bcbfb2f39bc15b966e1b7770e101f5e From 70677d4199eff293789ebd769b7467cb0fe6095a Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 15:48:37 +0100 Subject: [PATCH 13/24] Revert Mobile-Expensify changes --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 2c47c8396bcbf..c2cf2911e42e5 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 2c47c8396bcbfb2f39bc15b966e1b7770e101f5e +Subproject commit c2cf2911e42e54dac2b4d95237c8c990afb6ae82 From 500718acc76b0ec126be37dc65f42f0751382a69 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 16:00:11 +0100 Subject: [PATCH 14/24] Rerun CI From 35204912979dea689fc690ac5187155cbbf876a6 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 5 Nov 2025 17:00:05 +0100 Subject: [PATCH 15/24] runOnJS => scheduleOnRN --- .../iou/request/step/IOURequestStepScan/index.native.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 0b3229a9e0915..3eae2921f2885 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -8,9 +8,10 @@ import ReactNativeBlobUtil from 'react-native-blob-util'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; import type {OnyxEntry} from 'react-native-onyx'; import {RESULTS} from 'react-native-permissions'; -import Animated, {runOnJS, useAnimatedStyle, useSharedValue, withDelay, withSequence, withSpring, withTiming} from 'react-native-reanimated'; +import Animated, {useAnimatedStyle, useSharedValue, withDelay, withSequence, withSpring, withTiming} from 'react-native-reanimated'; import type {Camera, PhotoFile, Point} from 'react-native-vision-camera'; import {useCameraDevice} from 'react-native-vision-camera'; +import {scheduleOnRN} from 'react-native-worklets'; import MultiScan from '@assets/images/educational-illustration__multi-scan.svg'; import TestReceipt from '@assets/images/fake-receipt.png'; import Hand from '@assets/images/hand.svg'; @@ -227,7 +228,7 @@ function IOURequestStepScan({ focusIndicatorScale.set(withSpring(1, {damping: 10, stiffness: 200})); focusIndicatorPosition.set(point); - runOnJS(focusCamera)(point); + scheduleOnRN(focusCamera, point); }); useFocusEffect( From bc24fe6dab2f69ae3bd7eba972751abe7a114e86 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Fri, 7 Nov 2025 13:20:08 +0100 Subject: [PATCH 16/24] Rerun Jest tests From 87a3edbd69629215409f6a538ac7f79db09ff83c Mon Sep 17 00:00:00 2001 From: GCyganek Date: Fri, 7 Nov 2025 14:22:06 +0100 Subject: [PATCH 17/24] Rerun Jest tests From 15d72a4d8408453d93ba4271a850287114bdf1ad Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 25 Nov 2025 09:35:52 +0100 Subject: [PATCH 18/24] Fix error by checking if error is instance of GeolocationPositionError --- src/libs/getCurrentPosition/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libs/getCurrentPosition/index.ts b/src/libs/getCurrentPosition/index.ts index 9e5afe9d1112b..4175ef27dd716 100644 --- a/src/libs/getCurrentPosition/index.ts +++ b/src/libs/getCurrentPosition/index.ts @@ -8,6 +8,7 @@ const getCurrentPosition: GetCurrentPosition = async (success, error, options) = if (foregroundPermissionResponse.status !== PermissionStatus.GRANTED) { error({code: GeolocationErrorCode.PERMISSION_DENIED, message: 'Geolocation is not supported by this environment.'}); + return; } try { @@ -15,13 +16,18 @@ const getCurrentPosition: GetCurrentPosition = async (success, error, options) = success(currentPosition); } catch (caughtError) { let message = 'Geolocation call failed'; - if (caughtError instanceof Error) { + let code = GeolocationErrorCode.POSITION_UNAVAILABLE; + + if (caughtError instanceof GeolocationPositionError) { + code = caughtError.code; + message = caughtError.message; + } else if (caughtError instanceof Error) { message = caughtError.message; } else if (typeof caughtError === 'string') { message = caughtError; } - error({code: GeolocationErrorCode.POSITION_UNAVAILABLE, message}); + error({code, message}); } }; From 44642f6ba281ddc6e249714ae506343d5729a65a Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 25 Nov 2025 09:40:03 +0100 Subject: [PATCH 19/24] Better error message when location permission not granted --- src/libs/getCurrentPosition/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/getCurrentPosition/index.ts b/src/libs/getCurrentPosition/index.ts index 4175ef27dd716..e64a8e9b0f5ce 100644 --- a/src/libs/getCurrentPosition/index.ts +++ b/src/libs/getCurrentPosition/index.ts @@ -7,7 +7,7 @@ const getCurrentPosition: GetCurrentPosition = async (success, error, options) = const foregroundPermissionResponse: PermissionResponse = await requestForegroundPermissionsAsync(); if (foregroundPermissionResponse.status !== PermissionStatus.GRANTED) { - error({code: GeolocationErrorCode.PERMISSION_DENIED, message: 'Geolocation is not supported by this environment.'}); + error({code: GeolocationErrorCode.PERMISSION_DENIED, message: 'User denied access to location.'}); return; } From 521e6821b658fc67442566ec0a2735d0b441d162 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Tue, 25 Nov 2025 11:47:56 +0100 Subject: [PATCH 20/24] Fix eslint error --- src/libs/ReportLayoutUtils.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libs/ReportLayoutUtils.ts b/src/libs/ReportLayoutUtils.ts index 26de21aa17723..b5319f9a5a900 100644 --- a/src/libs/ReportLayoutUtils.ts +++ b/src/libs/ReportLayoutUtils.ts @@ -16,7 +16,7 @@ function groupTransactionsByCategory(transactions: Transaction[], report: OnyxEn const groups = new Map(); - transactions.forEach((transaction) => { + for (const transaction of transactions) { const category = getCategory(transaction); const categoryKey = category || ''; @@ -24,10 +24,10 @@ function groupTransactionsByCategory(transactions: Transaction[], report: OnyxEn groups.set(categoryKey, []); } groups.get(categoryKey)?.push(transaction); - }); + } const result: GroupedTransactions[] = []; - groups.forEach((transactionList, categoryKey) => { + for (const [categoryKey, transactionList] of groups) { // Translation handled at component level const displayName = categoryKey; @@ -47,7 +47,7 @@ function groupTransactionsByCategory(transactions: Transaction[], report: OnyxEn totalAmount, isExpanded: true, }); - }); + } // Sort alphabetically (A→Z), empty keys (uncategorized) at the end return result.sort((a, b) => { @@ -72,7 +72,7 @@ function groupTransactionsByTag(transactions: Transaction[], report: OnyxEntry(); - transactions.forEach((transaction) => { + for (const transaction of transactions) { const tag = getTag(transaction); const tagKey = tag || ''; @@ -80,10 +80,10 @@ function groupTransactionsByTag(transactions: Transaction[], report: OnyxEntry { + for (const [tagKey, transactionList] of groups) { // Translation handled at component level const displayName = tagKey; @@ -103,7 +103,7 @@ function groupTransactionsByTag(transactions: Transaction[], report: OnyxEntry { From 48713a82e667987ff4c2416d9bafeb7d42813cc8 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Fri, 28 Nov 2025 09:21:10 +0100 Subject: [PATCH 21/24] Delete desktop code as it's deprecated --- src/libs/getCurrentPosition/index.desktop.ts | 58 -------------------- 1 file changed, 58 deletions(-) delete mode 100644 src/libs/getCurrentPosition/index.desktop.ts diff --git a/src/libs/getCurrentPosition/index.desktop.ts b/src/libs/getCurrentPosition/index.desktop.ts deleted file mode 100644 index 964248e8708aa..0000000000000 --- a/src/libs/getCurrentPosition/index.desktop.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type {ValueOf} from 'type-fest'; -import type {GetCurrentPosition} from './getCurrentPosition.types'; -import {GeolocationErrorCode} from './getCurrentPosition.types'; -import type {LocationPermissionState} from './locationPermission'; -import {LOCATION_PERMISSION_STATES} from './locationPermission'; - -const makeError = (code: ValueOf, message: string) => ({ - code, - message, -}); - -const isLocationPermissionState = (status: unknown): status is LocationPermissionState => - typeof status === 'string' && Object.values(LOCATION_PERMISSION_STATES).includes(status as LocationPermissionState); - -const getCurrentPosition: GetCurrentPosition = async (success, error, options) => { - const doGeoRequest = () => { - try { - navigator.geolocation.getCurrentPosition(success, error, options); - } catch (caughtError) { - let reason = 'Geolocation call failed'; - if (caughtError instanceof Error) { - reason = caughtError.message; - } else if (typeof caughtError === 'string') { - reason = caughtError; - } - - error(makeError(GeolocationErrorCode.POSITION_UNAVAILABLE, reason)); - } - }; - - // IPC-based permission checking - if (typeof window !== 'undefined' && window.electron?.invoke) { - window.electron - .invoke('check-location-permission') - .then((permissionStatus: unknown) => { - if (!isLocationPermissionState(permissionStatus)) { - error(makeError(GeolocationErrorCode.PERMISSION_DENIED, 'Unable to verify location permissions. Enable location access and try again.')); - return; - } - - if (permissionStatus === LOCATION_PERMISSION_STATES.DENIED) { - error(makeError(GeolocationErrorCode.PERMISSION_DENIED, 'Location access denied. Enable location permissions in system settings.')); - return; - } - - doGeoRequest(); - }) - .catch(() => { - error(makeError(GeolocationErrorCode.PERMISSION_DENIED, 'Unable to verify location permissions. Enable location access and try again.')); - }); - - return; // handled via IPC - } - - doGeoRequest(); // Fallback to direct geolocation -}; - -export default getCurrentPosition; From c13b2285f69ab0d87e006314c33841c6d55509dd Mon Sep 17 00:00:00 2001 From: GCyganek Date: Fri, 28 Nov 2025 09:34:32 +0100 Subject: [PATCH 22/24] Rerun Jest tests From 7b4ed22547621da73e4e95ef4e537f26ececa724 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 10 Dec 2025 09:55:00 +0100 Subject: [PATCH 23/24] Delete desktop related code --- desktop/main.ts | 11 +++++++++-- src/components/AddressSearch/index.tsx | 4 ---- .../getCurrentPosition/getCurrentPosition.types.ts | 13 +------------ src/libs/getCurrentPosition/locationPermission.ts | 12 ------------ src/pages/Share/SubmitDetailsPage.tsx | 4 ---- .../iou/request/step/IOURequestStepConfirmation.tsx | 8 -------- .../iou/request/step/IOURequestStepScan/index.tsx | 8 -------- 7 files changed, 10 insertions(+), 50 deletions(-) delete mode 100644 src/libs/getCurrentPosition/locationPermission.ts diff --git a/desktop/main.ts b/desktop/main.ts index 4fb3bfa24c0ba..222db07ea8dc6 100644 --- a/desktop/main.ts +++ b/desktop/main.ts @@ -7,6 +7,7 @@ import log from 'electron-log'; import {autoUpdater} from 'electron-updater'; import type {AuthType, PermissionType} from 'node-mac-permissions'; import {machineId} from 'node-machine-id'; +import type {ValueOf} from 'type-fest'; import checkForUpdates from '@libs/checkForUpdates'; import {translate} from '@libs/Localize'; import Log from '@libs/Log'; @@ -14,14 +15,20 @@ import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import type {TranslationPaths} from '@src/languages/types'; -import type {LocationPermissionState} from '@src/libs/getCurrentPosition/locationPermission'; -import {LOCATION_PERMISSION_STATES} from '@src/libs/getCurrentPosition/locationPermission'; import type PlatformSpecificUpdater from '@src/setup/platformSetup/types'; import type {Locale} from '@src/types/onyx'; import type {CreateDownloadQueueModule, DownloadItem} from './createDownloadQueue'; import serve from './electron-serve'; import ELECTRON_EVENTS from './ELECTRON_EVENTS'; +const LOCATION_PERMISSION_STATES = { + GRANTED: 'granted', + DENIED: 'denied', + PROMPT: 'prompt', +} as const; + +type LocationPermissionState = ValueOf; + const createDownloadQueue = require('./createDownloadQueue').default; const port = process.env.PORT ?? 8082; diff --git a/src/components/AddressSearch/index.tsx b/src/components/AddressSearch/index.tsx index b116d02be8c88..ce6dc086bcf06 100644 --- a/src/components/AddressSearch/index.tsx +++ b/src/components/AddressSearch/index.tsx @@ -286,10 +286,6 @@ function AddressSearch({ setIsFetchingCurrentLocation(false); setLocationErrorCode(errorData?.code ?? null); }, - { - maximumAge: 0, // No cache, always get fresh location info - timeout: 30000, - }, ); }; diff --git a/src/libs/getCurrentPosition/getCurrentPosition.types.ts b/src/libs/getCurrentPosition/getCurrentPosition.types.ts index 54fbbff96c526..a6be3362dde1b 100644 --- a/src/libs/getCurrentPosition/getCurrentPosition.types.ts +++ b/src/libs/getCurrentPosition/getCurrentPosition.types.ts @@ -25,18 +25,7 @@ const GeolocationErrorCode = { NOT_SUPPORTED: -1, }; -type GeolocationOptions = { - /** Desktop only */ - timeout?: number; - - /** Desktop only */ - maximumAge?: number; - - /** Desktop only */ - enableHighAccuracy?: boolean; -} & LocationOptions; - -type GetCurrentPosition = (success: GeolocationSuccessCallback, error: GeolocationErrorCallback, options?: GeolocationOptions) => Promise; +type GetCurrentPosition = (success: GeolocationSuccessCallback, error: GeolocationErrorCallback, options?: LocationOptions) => Promise; export {GeolocationErrorCode}; diff --git a/src/libs/getCurrentPosition/locationPermission.ts b/src/libs/getCurrentPosition/locationPermission.ts deleted file mode 100644 index 00bb8d67e53ad..0000000000000 --- a/src/libs/getCurrentPosition/locationPermission.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type {ValueOf} from 'type-fest'; - -const LOCATION_PERMISSION_STATES = { - GRANTED: 'granted', - DENIED: 'denied', - PROMPT: 'prompt', -} as const; - -type LocationPermissionState = ValueOf; - -export type {LocationPermissionState}; -export {LOCATION_PERMISSION_STATES}; diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index ca885037a80a5..1f74f283b5ca3 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -196,10 +196,6 @@ function SubmitDetailsPage({ Log.info('[SubmitDetailsPage] getCurrentPosition failed', false, errorData); finishRequestAndNavigate(participant, receipt); }, - { - maximumAge: CONST.GPS.MAX_AGE, - timeout: CONST.GPS.TIMEOUT, - }, ); return; } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index e767e20613ddd..6d6517a32e8ad 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1000,10 +1000,6 @@ function IOURequestStepConfirmation({ // When there is an error, the money can still be requested, it just won't include the GPS coordinates trackExpense(selectedParticipants); }, - { - maximumAge: CONST.GPS.MAX_AGE, - timeout: CONST.GPS.TIMEOUT, - }, ); return; } @@ -1050,10 +1046,6 @@ function IOURequestStepConfirmation({ // When there is an error, the money can still be requested, it just won't include the GPS coordinates requestMoney(selectedParticipants); }, - { - maximumAge: CONST.GPS.MAX_AGE, - timeout: CONST.GPS.TIMEOUT, - }, ); return; } diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 75dfae3c90270..3e336505cf954 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -315,10 +315,6 @@ function IOURequestStepScan({ setUserLocation({longitude: successData.coords.longitude, latitude: successData.coords.latitude}); }, () => {}, - { - maximumAge: CONST.GPS.MAX_AGE, - timeout: CONST.GPS.TIMEOUT, - }, ); }); }, [initialTransaction?.amount, iouType]); @@ -523,10 +519,6 @@ function IOURequestStepScan({ // When there is an error, the money can still be requested, it just won't include the GPS coordinates createTransaction(files, participant); }, - { - maximumAge: CONST.GPS.MAX_AGE, - timeout: CONST.GPS.TIMEOUT, - }, ); return; } From 9efc2a44cf73f116bc35bfc114c5693884c3e748 Mon Sep 17 00:00:00 2001 From: GCyganek Date: Wed, 10 Dec 2025 10:52:06 +0100 Subject: [PATCH 24/24] Fix SearchContextTest typecheck error --- tests/unit/Search/SearchContextTest.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/Search/SearchContextTest.tsx b/tests/unit/Search/SearchContextTest.tsx index 2d973768314d4..c53b8a071514d 100644 --- a/tests/unit/Search/SearchContextTest.tsx +++ b/tests/unit/Search/SearchContextTest.tsx @@ -24,6 +24,7 @@ const mockSelectedTransaction: SelectedTransactionInfo = { } as const; const mockTransaction: TransactionListItemType = { + canDelete: true, accountID: 1, amount: 0, category: '',