react-native-iap 14.4.32 → 14.4.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,6 +70,9 @@ def getExtOrIntegerDefault(name) {
70
70
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroIap_" + name]).toInteger()
71
71
  }
72
72
 
73
+ // Read horizonEnabled from gradle.properties, default to false (play)
74
+ def horizonEnabled = project.findProperty('horizonEnabled')?.toBoolean() ?: false
75
+
73
76
  android {
74
77
  namespace "com.margelo.nitro.iap"
75
78
 
@@ -83,6 +86,10 @@ android {
83
86
  // Ship consumer keep rules so Nitro HybridObjects aren't stripped in app release builds
84
87
  consumerProguardFiles 'consumer-rules.pro'
85
88
 
89
+ // Use horizonEnabled to determine platform flavor
90
+ def flavor = horizonEnabled ? 'horizon' : 'play'
91
+ missingDimensionStrategy "platform", flavor
92
+
86
93
  externalNativeBuild {
87
94
  cmake {
88
95
  cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
@@ -172,13 +179,21 @@ dependencies {
172
179
  if (findProject(':react-native-nitro-modules') != null) {
173
180
  implementation project(":react-native-nitro-modules")
174
181
  }
175
-
182
+
176
183
  // Google Play Services
177
184
  implementation 'com.google.android.gms:play-services-base:18.5.0'
178
-
185
+
179
186
  // Kotlin coroutines
180
187
  implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0'
181
- implementation "io.github.hyochan.openiap:openiap-google:${googleVersionString}"
188
+
189
+ // Determine which OpenIAP dependency to use based on horizonEnabled flag
190
+ if (horizonEnabled) {
191
+ // Use openiap-google-horizon for Meta Quest when horizonEnabled is true
192
+ implementation "io.github.hyochan.openiap:openiap-google-horizon:${googleVersionString}"
193
+ } else {
194
+ // Use standard Google Play Billing
195
+ implementation "io.github.hyochan.openiap:openiap-google:${googleVersionString}"
196
+ }
182
197
  }
183
198
 
184
199
  configurations.all {
@@ -68,9 +68,22 @@ class HybridRnIap : HybridRnIapSpec() {
68
68
  return@async true
69
69
  }
70
70
 
71
- // Set current activity best-effort; don't fail init if missing
71
+ // CRITICAL: Set Activity BEFORE calling initConnection
72
+ // Horizon SDK needs Activity to initialize OVRPlatform with proper returnComponent
73
+ // https://github.com/meta-quest/Meta-Spatial-SDK-Samples/issues/82#issuecomment-3452577530
72
74
  withContext(Dispatchers.Main) {
73
- runCatching { openIap.setActivity(context.currentActivity) }
75
+ runCatching { context.currentActivity }
76
+ .onSuccess { activity ->
77
+ if (activity != null) {
78
+ RnIapLog.debug("Activity available: ${activity.javaClass.name}")
79
+ openIap.setActivity(activity)
80
+ } else {
81
+ RnIapLog.warn("Activity is null during initConnection")
82
+ }
83
+ }
84
+ .onFailure {
85
+ RnIapLog.warn("Activity not available during initConnection - OpenIAP will use Context")
86
+ }
74
87
  }
75
88
 
76
89
  // Single-flight: capture or create the shared Deferred atomically
@@ -432,12 +445,33 @@ class HybridRnIap : HybridRnIapSpec() {
432
445
  }
433
446
 
434
447
  val result: List<OpenIapPurchase> = if (normalizedType != null) {
435
- val typeEnum = parseProductQueryType(normalizedType)
436
448
  RnIapLog.payload(
437
449
  "getAvailablePurchases.native",
438
- mapOf("type" to typeEnum.rawValue)
450
+ mapOf("type" to normalizedType)
439
451
  )
440
- openIap.getAvailableItems(typeEnum)
452
+ // OpenIAP's getAvailablePurchases doesn't support type filtering
453
+ // Get all purchases and filter manually
454
+ val allPurchases = openIap.getAvailablePurchases(null)
455
+
456
+ // Partition purchases to handle cases where product type is not yet cached
457
+ val (knownTypePurchases, unknownTypePurchases) = allPurchases.partition {
458
+ productTypeBySku.containsKey(it.productId)
459
+ }
460
+
461
+ if (unknownTypePurchases.isNotEmpty()) {
462
+ RnIapLog.warn(
463
+ "getAvailablePurchases: Could not determine type for product IDs: " +
464
+ "${unknownTypePurchases.map { it.productId }.joinToString()}. " +
465
+ "These will be excluded from '$normalizedType' filtered lists. " +
466
+ "Call fetchProducts first to populate product type cache."
467
+ )
468
+ }
469
+
470
+ when (normalizedType) {
471
+ "in-app" -> knownTypePurchases.filter { productTypeBySku[it.productId] == "in-app" }
472
+ "subs" -> knownTypePurchases.filter { productTypeBySku[it.productId] == "subs" }
473
+ else -> allPurchases
474
+ }
441
475
  } else {
442
476
  RnIapLog.payload("getAvailablePurchases.native", mapOf("type" to "all"))
443
477
  openIap.getAvailablePurchases(null)
@@ -1,5 +1,5 @@
1
1
  {
2
- "apple": "1.2.30",
3
- "google": "1.3.2",
2
+ "apple": "1.2.31",
3
+ "google": "1.3.4",
4
4
  "gql": "1.2.3"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "14.4.32",
3
+ "version": "14.4.33",
4
4
  "description": "React Native In-App Purchases module for iOS and Android using Nitro",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",