diff --git a/configs/jsactions/rollup.config.mjs b/configs/jsactions/rollup.config.mjs index d8691fac1..115f7c3db 100644 --- a/configs/jsactions/rollup.config.mjs +++ b/configs/jsactions/rollup.config.mjs @@ -34,7 +34,8 @@ export default async args => { types: ["mendix-client", "react-native"], allowSyntheticDefaultImports: true, compilerOptions: { - newLine: "CRLF" + newLine: "CRLF", + jsx: "react-native" } }); diff --git a/packages/jsActions/nanoflow-actions-native/package.json b/packages/jsActions/nanoflow-actions-native/package.json index a1b788d35..bfcd77854 100644 --- a/packages/jsActions/nanoflow-actions-native/package.json +++ b/packages/jsActions/nanoflow-actions-native/package.json @@ -1,7 +1,7 @@ { "name": "nanoflow-actions-native", "moduleName": "Nanoflow Commons", - "version": "7.1.0", + "version": "7.2.0", "license": "Apache-2.0", "copyright": "© Mendix Technology BV 2022. All rights reserved.", "repository": { @@ -27,9 +27,10 @@ }, "dependencies": { "@react-native-async-storage/async-storage": "2.2.0", - "@react-native-community/geolocation": "3.4.0", "invariant": "^2.2.4", "js-base64": "~3.7.2", + "react-native-nitro-geolocation": "1.4.3", + "react-native-nitro-modules": "0.36.1", "react-native-permissions": "5.5.1", "react-native-geocoder": "0.5.0" }, diff --git a/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocation.ts b/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocation.ts index b333c81d4..73d714d60 100644 --- a/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocation.ts +++ b/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocation.ts @@ -6,14 +6,8 @@ // - the code between BEGIN EXTRA CODE and END EXTRA CODE // Other code you write will be lost the next time you deploy the project. import { Big } from "big.js"; -import Geolocation, { - GeolocationError, - GeolocationOptions, - GeolocationResponse -} from "@react-native-community/geolocation"; - -import type { Platform, NativeModules } from "react-native"; -import type { GeoError, GeoPosition, GeoOptions } from "../../typings/Geolocation"; +import { Platform } from "react-native"; +import { getCurrentPosition, GeolocationResponse, LocationRequestOptions } from "react-native-nitro-geolocation"; // BEGIN EXTRA CODE // END EXTRA CODE @@ -39,94 +33,68 @@ export async function GetCurrentLocation( ): Promise { // BEGIN USER CODE - let reactNativeModule: { NativeModules: typeof NativeModules; Platform: typeof Platform } | undefined; - let geolocationModule: typeof import("@react-native-community/geolocation").default | Geolocation; - - if (navigator && navigator.product === "ReactNative") { - reactNativeModule = require("react-native"); - - if (!reactNativeModule) { - return Promise.reject(new Error("React Native module could not be found")); - } - - if (reactNativeModule.NativeModules.RNFusedLocation) { - geolocationModule = (await import("@react-native-community/geolocation")).default; - } else if (reactNativeModule.NativeModules.RNCGeolocation) { - geolocationModule = Geolocation; - } else { - return Promise.reject(new Error("Geolocation module could not be found")); - } - } else if (navigator && navigator.geolocation) { - geolocationModule = navigator.geolocation; - } else { - return Promise.reject(new Error("Geolocation module could not be found")); - } - - return new Promise((resolve, reject) => { - const options = getOptions(); - geolocationModule?.getCurrentPosition(onSuccess, onError, options); - - function onSuccess(position: GeolocationResponse | GeoPosition): void { + const options = buildLocationOptions(timeout, maximumAge, highAccuracy); + try { + const position = await getCurrentPosition(options); + return new Promise((resolve, reject) => { mx.data.create({ entity: "NanoflowCommons.Geolocation", callback: mxObject => { - const geolocation = mapPositionToMxObject(mxObject, position); - resolve(geolocation); + resolve(mapPositionToMxObject(mxObject, position)); }, error: () => reject(new Error("Could not create 'NanoflowCommons.Geolocation' object to store location")) }); - } - - function onError(error: GeolocationError | GeoError): void { - return reject(new Error(error.message)); - } + }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return Promise.reject(new Error(`Could not get current location: ${message}`)); + } - function getOptions(): GeolocationOptions | GeoOptions { - let timeoutNumber = timeout && Number(timeout.toString()); - const maximumAgeNumber = maximumAge && Number(maximumAge.toString()); + function buildLocationOptions( + timeout: Big | undefined, + maximumAge: Big | undefined, + highAccuracy: boolean | undefined + ): LocationRequestOptions { + let timeoutNumber = timeout ? timeout.toNumber() : undefined; + const maximumAgeNumber = maximumAge ? maximumAge.toNumber() : undefined; - // If the timeout is 0 or undefined (empty), it causes a crash on iOS. - // If the timeout is undefined (empty); we set timeout to 30 sec (default timeout) - // If the timeout is 0; we set timeout to 1 hour (no timeout) - if (reactNativeModule?.Platform.OS === "ios") { - if (timeoutNumber === undefined) { - timeoutNumber = 30000; - } else if (timeoutNumber === 0) { - timeoutNumber = 3600000; - } + // If the timeout is 0 or undefined (empty), it causes a crash on iOS. + // If the timeout is undefined (empty); we set timeout to 30 sec (default timeout) + // If the timeout is 0; we set timeout to 1 hour (no timeout) + if (Platform.OS === "ios") { + if (timeoutNumber === undefined) { + timeoutNumber = 30000; + } else if (timeoutNumber === 0) { + timeoutNumber = 3600000; } - - return { - timeout: timeoutNumber, - maximumAge: maximumAgeNumber, - enableHighAccuracy: highAccuracy - }; } - function mapPositionToMxObject( - mxObject: mendix.lib.MxObject, - position: GeolocationResponse | GeoPosition - ): mendix.lib.MxObject { - mxObject.set("Timestamp", new Date(position.timestamp)); - mxObject.set("Latitude", new Big(position.coords.latitude.toFixed(8))); - mxObject.set("Longitude", new Big(position.coords.longitude.toFixed(8))); - mxObject.set("Accuracy", new Big(position.coords.accuracy.toFixed(8))); - if (position.coords.altitude != null) { - mxObject.set("Altitude", new Big(position.coords.altitude.toFixed(8))); - } - if (position.coords.altitudeAccuracy != null && position.coords.altitudeAccuracy !== -1) { - mxObject.set("AltitudeAccuracy", new Big(position.coords.altitudeAccuracy.toFixed(8))); - } - if (position.coords.heading != null && position.coords.heading !== -1) { - mxObject.set("Heading", new Big(position.coords.heading.toFixed(8))); - } - if (position.coords.speed != null && position.coords.speed !== -1) { - mxObject.set("Speed", new Big(position.coords.speed.toFixed(8))); - } - return mxObject; + return { + timeout: timeoutNumber, + maximumAge: maximumAgeNumber, + accuracy: highAccuracy ? { android: "high", ios: "best" } : { android: "balanced", ios: "hundredMeters" } + }; + } + function mapPositionToMxObject(mxObject: mendix.lib.MxObject, pos: GeolocationResponse): mendix.lib.MxObject { + mxObject.set("Timestamp", new Date(pos.timestamp)); + mxObject.set("Latitude", new Big(pos.coords.latitude.toFixed(8))); + mxObject.set("Longitude", new Big(pos.coords.longitude.toFixed(8))); + mxObject.set("Accuracy", new Big(pos.coords.accuracy.toFixed(8))); + if (pos.coords.altitude != null) { + mxObject.set("Altitude", new Big(pos.coords.altitude.toFixed(8))); + } + if (pos.coords.altitudeAccuracy != null && pos.coords.altitudeAccuracy !== -1) { + mxObject.set("AltitudeAccuracy", new Big(pos.coords.altitudeAccuracy.toFixed(8))); + } + if (pos.coords.heading != null && pos.coords.heading !== -1) { + mxObject.set("Heading", new Big(pos.coords.heading.toFixed(8))); } - }); + if (pos.coords.speed != null && pos.coords.speed !== -1) { + mxObject.set("Speed", new Big(pos.coords.speed.toFixed(8))); + } + return mxObject; + } // END USER CODE } diff --git a/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocationMinimumAccuracy.ts b/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocationMinimumAccuracy.ts index 7756b3e1b..ffc270b4d 100644 --- a/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocationMinimumAccuracy.ts +++ b/packages/jsActions/nanoflow-actions-native/src/geolocation/GetCurrentLocationMinimumAccuracy.ts @@ -6,14 +6,14 @@ // - the code between BEGIN EXTRA CODE and END EXTRA CODE // Other code you write will be lost the next time you deploy the project. import { Big } from "big.js"; -import Geolocation, { - GeolocationError, - GeolocationOptions, - GeolocationResponse -} from "@react-native-community/geolocation"; - -import type { Platform, NativeModules } from "react-native"; -import type { GeoError, GeoPosition, GeoOptions } from "../../typings/Geolocation"; +import { Platform } from "react-native"; +import { + watchPosition, + unwatch, + LocationError, + GeolocationResponse, + LocationRequestOptions +} from "react-native-nitro-geolocation"; // BEGIN EXTRA CODE // END EXTRA CODE @@ -25,7 +25,7 @@ import type { GeoError, GeoPosition, GeoOptions } from "../../typings/Geolocatio * * On hybrid and native platforms the permission should be requested with the `RequestLocationPermission` action. * - * For good user experience, disable the nanoflow during action using property `Disabled during action` if you’re using `Call a nanoflow button` to run JS Action `Get current location with minimum accuracy`. + * For good user experience, disable the nanoflow during action using property `Disabled during action` if you're using `Call a nanoflow button` to run JS Action `Get current location with minimum accuracy`. * * Best practices: * https://developers.google.com/web/fundamentals/native-hardware/user-location/ @@ -43,63 +43,16 @@ export async function GetCurrentLocationMinimumAccuracy( ): Promise { // BEGIN USER CODE - let reactNativeModule: { NativeModules: typeof NativeModules; Platform: typeof Platform } | undefined; - let geolocationModule: typeof import("@react-native-community/geolocation").default | Geolocation; - - if (navigator && navigator.product === "ReactNative") { - reactNativeModule = require("react-native"); - - if (!reactNativeModule) { - return Promise.reject(new Error("React Native module could not be found")); - } - - if (reactNativeModule.NativeModules.RNFusedLocation) { - geolocationModule = (await import("@react-native-community/geolocation")).default; - } else if (reactNativeModule.NativeModules.RNCGeolocation) { - geolocationModule = Geolocation; - } else { - return Promise.reject(new Error("Geolocation module could not be found")); - } - } else if (navigator && navigator.geolocation) { - geolocationModule = navigator.geolocation; - } else { - return Promise.reject(new Error("Geolocation module could not be found")); - } - return new Promise((resolve, reject) => { - if (!geolocationModule) { - return reject(new Error("Geolocation module could not be found")); - } - - const options = getOptions(); + const options = buildLocationOptions(timeout, maximumAge, highAccuracy); + let lastAccruedPosition: GeolocationResponse | undefined; - // This action is only required while running in PWA or hybrid. - if (navigator && (!navigator.product || navigator.product !== "ReactNative")) { - // This ensures the browser will not ignore the maximumAge https://stackoverflow.com/questions/3397585/navigator-geolocation-getcurrentposition-sometimes-works-sometimes-doesnt/31916631#31916631 - geolocationModule.getCurrentPosition( - // eslint-disable-next-line @typescript-eslint/no-empty-function - () => {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function - () => {}, - {} - ); - } - - const timeoutId = setTimeout(onTimeout, Number(timeout)); - const watchId: number = geolocationModule.watchPosition(onSuccess, onError, options); - let lastAccruedPosition: GeolocationResponse | GeoPosition; - - function createGeolocationObject(position: GeolocationResponse | GeoPosition): void { - mx.data.create({ - entity: "NanoflowCommons.Geolocation", - callback: mxObject => resolve(mapPositionToMxObject(mxObject, position)), - error: () => - reject(new Error("Could not create 'NanoflowCommons.Geolocation' object to store location")) - }); - } + const timeoutMs = timeout ? timeout.toNumber() : 30000; + const timeoutId = setTimeout(onTimeout, timeoutMs); + const token = watchPosition(onSuccess, onError, options); function onTimeout(): void { - geolocationModule?.clearWatch(watchId); + unwatch(token); if (lastAccruedPosition) { createGeolocationObject(lastAccruedPosition); @@ -108,10 +61,10 @@ export async function GetCurrentLocationMinimumAccuracy( } } - function onSuccess(position: GeolocationResponse | GeoPosition): void { + function onSuccess(position: GeolocationResponse): void { if (!minimumAccuracy || Number(minimumAccuracy) >= position.coords.accuracy) { clearTimeout(timeoutId); - geolocationModule?.clearWatch(watchId); + unwatch(token); createGeolocationObject(position); } else { if (!lastAccruedPosition || position.coords.accuracy < lastAccruedPosition.coords.accuracy) { @@ -120,55 +73,66 @@ export async function GetCurrentLocationMinimumAccuracy( } } - function onError(error: GeolocationError | GeoError): void { - return reject(new Error(error.message)); + function onError(error: LocationError): void { + clearTimeout(timeoutId); + unwatch(token); + reject(new Error(error.message)); } - function getOptions(): GeolocationOptions | GeoOptions { - let timeoutNumber = timeout && Number(timeout.toString()); - const maximumAgeNumber = maximumAge && Number(maximumAge.toString()); + function createGeolocationObject(position: GeolocationResponse): void { + mx.data.create({ + entity: "NanoflowCommons.Geolocation", + callback: mxObject => resolve(mapPositionToMxObject(mxObject, position)), + error: () => + reject(new Error("Could not create 'NanoflowCommons.Geolocation' object to store location")) + }); + } + }); - // If the timeout is 0 or undefined (empty), it causes a crash on iOS. - // If the timeout is undefined (empty); we set timeout to 30 sec (default timeout) - // If the timeout is 0; we set timeout to 1 hour (no timeout) - if (reactNativeModule?.Platform.OS === "ios") { - if (timeoutNumber === undefined) { - timeoutNumber = 30000; - } else if (timeoutNumber === 0) { - timeoutNumber = 3600000; - } + function buildLocationOptions( + timeout: Big | undefined, + maximumAge: Big | undefined, + highAccuracy: boolean | undefined + ): LocationRequestOptions { + let timeoutNumber = timeout ? timeout.toNumber() : undefined; + const maximumAgeNumber = maximumAge ? maximumAge.toNumber() : undefined; + + // If the timeout is 0 or undefined (empty), it causes a crash on iOS. + // If the timeout is undefined (empty); we set timeout to 30 sec (default timeout) + // If the timeout is 0; we set timeout to 1 hour (no timeout) + if (Platform.OS === "ios") { + if (timeoutNumber === undefined) { + timeoutNumber = 30000; + } else if (timeoutNumber === 0) { + timeoutNumber = 3600000; } - - return { - timeout: timeoutNumber, - maximumAge: maximumAgeNumber, - enableHighAccuracy: highAccuracy - }; } - function mapPositionToMxObject( - mxObject: mendix.lib.MxObject, - position: GeolocationResponse | GeoPosition - ): mendix.lib.MxObject { - mxObject.set("Timestamp", new Date(position.timestamp)); - mxObject.set("Latitude", new Big(position.coords.latitude.toFixed(8))); - mxObject.set("Longitude", new Big(position.coords.longitude.toFixed(8))); - mxObject.set("Accuracy", new Big(position.coords.accuracy.toFixed(8))); - if (position.coords.altitude != null) { - mxObject.set("Altitude", new Big(position.coords.altitude.toFixed(8))); - } - if (position.coords.altitudeAccuracy != null && position.coords.altitudeAccuracy !== -1) { - mxObject.set("AltitudeAccuracy", new Big(position.coords.altitudeAccuracy.toFixed(8))); - } - if (position.coords.heading != null && position.coords.heading !== -1) { - mxObject.set("Heading", new Big(position.coords.heading.toFixed(8))); - } - if (position.coords.speed != null && position.coords.speed !== -1) { - mxObject.set("Speed", new Big(position.coords.speed.toFixed(8))); - } - return mxObject; + return { + timeout: timeoutNumber, + maximumAge: maximumAgeNumber, + accuracy: highAccuracy ? { android: "high", ios: "best" } : { android: "balanced", ios: "hundredMeters" } + }; + } + function mapPositionToMxObject(mxObject: mendix.lib.MxObject, pos: GeolocationResponse): mendix.lib.MxObject { + mxObject.set("Timestamp", new Date(pos.timestamp)); + mxObject.set("Latitude", new Big(pos.coords.latitude.toFixed(8))); + mxObject.set("Longitude", new Big(pos.coords.longitude.toFixed(8))); + mxObject.set("Accuracy", new Big(pos.coords.accuracy.toFixed(8))); + if (pos.coords.altitude != null) { + mxObject.set("Altitude", new Big(pos.coords.altitude.toFixed(8))); } - }); + if (pos.coords.altitudeAccuracy != null && pos.coords.altitudeAccuracy !== -1) { + mxObject.set("AltitudeAccuracy", new Big(pos.coords.altitudeAccuracy.toFixed(8))); + } + if (pos.coords.heading != null && pos.coords.heading !== -1) { + mxObject.set("Heading", new Big(pos.coords.heading.toFixed(8))); + } + if (pos.coords.speed != null && pos.coords.speed !== -1) { + mxObject.set("Speed", new Big(pos.coords.speed.toFixed(8))); + } + return mxObject; + } // END USER CODE } diff --git a/packages/jsActions/nanoflow-actions-native/typings/Geolocation.d.ts b/packages/jsActions/nanoflow-actions-native/typings/Geolocation.d.ts deleted file mode 100644 index c92f243d4..000000000 --- a/packages/jsActions/nanoflow-actions-native/typings/Geolocation.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { - AuthorizationLevel, - AuthorizationResult, - GeoError, - GeoPosition, - GeoOptions, - getCurrentPosition, - requestAuthorization, - watchPosition, - clearWatch, - stopObserving -} from "@react-native-community/geolocation"; - -type GeolocationServiceStatic = { - getCurrentPosition: typeof getCurrentPosition; - requestAuthorization: typeof requestAuthorization; - watchPosition: typeof watchPosition; - clearWatch: typeof clearWatch; - stopObserving: typeof stopObserving; -}; - -export type { GeolocationServiceStatic, AuthorizationLevel, AuthorizationResult, GeoError, GeoPosition, GeoOptions }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8d5c6189..c78e01966 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -194,9 +194,6 @@ importers: '@react-native-async-storage/async-storage': specifier: 2.2.0 version: 2.2.0(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3)) - '@react-native-community/geolocation': - specifier: 3.4.0 - version: 3.4.0(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) invariant: specifier: ^2.2.4 version: 2.2.4 @@ -206,6 +203,12 @@ importers: react-native-geocoder: specifier: 0.5.0 version: 0.5.0 + react-native-nitro-geolocation: + specifier: 1.4.3 + version: 1.4.3(react-native-nitro-modules@0.36.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) + react-native-nitro-modules: + specifier: 0.36.1 + version: 0.36.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) react-native-permissions: specifier: 5.5.1 version: 5.5.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) @@ -2059,13 +2062,6 @@ packages: peerDependencies: react-native: 0.84.1 - '@react-native-community/geolocation@3.4.0': - resolution: {integrity: sha512-bzZH89/cwmpkPMKKveoC72C4JH0yF4St5Ceg/ZM9pA1SqX9MlRIrIrrOGZ/+yi++xAvFDiYfihtn9TvXWU9/rA==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: 19.2.3 - react-native: 0.84.1 - '@react-native-community/netinfo@11.5.2': resolution: {integrity: sha512-/g0m65BtX9HU+bPiCH2517bOHpEIUsGrWFXDzi1a5nNKn5KujQgm04WhL7/OSXWKHyrT8VVtUoJA0XKRxueBpQ==} peerDependencies: @@ -6088,6 +6084,19 @@ packages: react: 19.2.3 react-native: 0.84.1 + react-native-nitro-geolocation@1.4.3: + resolution: {integrity: sha512-8r09M6fjf7krCXRuF3RskuJpcxE8dvwQtRJnlrk+U3tO4v+ltyXhRRGmAMlO2Y/PEv1II8sgnIgil58RaLPI4A==} + peerDependencies: + react: 19.2.3 + react-native: 0.84.1 + react-native-nitro-modules: '*' + + react-native-nitro-modules@0.36.1: + resolution: {integrity: sha512-kBv/VvKqAmkXAvP1DxJMC9b/fRhh7JdSO4EUnPP46hJjrIFeFR8AwKm8mYaKZEuF014M/TVdv2vomVUW0umsQQ==} + peerDependencies: + react: 19.2.3 + react-native: 0.84.1 + react-native-permissions@5.5.1: resolution: {integrity: sha512-nTKFoj47b6EXNqbbg+8VFwBWMpxF1/UTbrNBLpXkWpt005pH4BeFv/NwpcC1iNhToKBrxQD+5kI0z6+kTYoYWA==} peerDependencies: @@ -8924,11 +8933,6 @@ snapshots: dependencies: react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) - '@react-native-community/geolocation@3.4.0(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3)': - dependencies: - react: 19.2.3 - react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) - '@react-native-community/netinfo@11.5.2(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3)': dependencies: react: 19.2.3 @@ -13871,6 +13875,17 @@ snapshots: react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) react-native-animatable: 1.3.3 + react-native-nitro-geolocation@1.4.3(react-native-nitro-modules@0.36.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3): + dependencies: + react: 19.2.3 + react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) + react-native-nitro-modules: 0.36.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) + + react-native-nitro-modules@0.36.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3): + dependencies: + react: 19.2.3 + react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) + react-native-permissions@5.5.1(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3