securiti-consent-sdk 1.141.0-11rc → 1.141.0-13rc

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.
Files changed (94) hide show
  1. package/NitroSecuritiConsentSdk.podspec +1 -1
  2. package/README.md +508 -2
  3. package/android/build.gradle +2 -2
  4. package/android/src/main/java/com/margelo/nitro/securiticonsentsdk/HybridConsentSDK.kt +168 -34
  5. package/android/src/main/java/com/margelo/nitro/securiticonsentsdk/NullTypeCompat.kt +19 -0
  6. package/ios/HybridConsentSDK.swift +78 -32
  7. package/lib/ConsentSDK.nitro.d.ts +8 -0
  8. package/lib/ConsentSDK.nitro.js +6 -0
  9. package/lib/index.js +8 -1
  10. package/nitrogen/generated/.gitattributes +1 -1
  11. package/nitrogen/generated/android/NitroSecuritiConsentSdk+autolinking.cmake +10 -4
  12. package/nitrogen/generated/android/NitroSecuritiConsentSdkOnLoad.cpp +1 -3
  13. package/nitrogen/generated/android/c++/JAppPermission.hpp +5 -1
  14. package/nitrogen/generated/android/c++/JBannerConfig.hpp +5 -1
  15. package/nitrogen/generated/android/c++/JCmpSDKOptions.hpp +5 -1
  16. package/nitrogen/generated/android/c++/JCustomColors.hpp +5 -1
  17. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +2 -1
  18. package/nitrogen/generated/android/c++/JHybridConsentSDKSpec.cpp +55 -14
  19. package/nitrogen/generated/android/c++/JHybridConsentSDKSpec.hpp +7 -3
  20. package/nitrogen/generated/android/c++/JPermissionConsent.hpp +5 -1
  21. package/nitrogen/generated/android/c++/JPostConsentsRequest.hpp +9 -3
  22. package/nitrogen/generated/android/c++/JPurpose.hpp +7 -2
  23. package/nitrogen/generated/android/c++/JPurposeConsent.hpp +5 -1
  24. package/nitrogen/generated/android/c++/JSDK.hpp +7 -2
  25. package/nitrogen/generated/android/c++/JSettingsPrompt.hpp +7 -2
  26. package/nitrogen/generated/android/c++/JVariant_NullType_BannerConfig.cpp +26 -0
  27. package/nitrogen/generated/android/c++/JVariant_NullType_BannerConfig.hpp +76 -0
  28. package/nitrogen/generated/android/c++/JVariant_NullType_CmpSDKOptions.cpp +26 -0
  29. package/nitrogen/generated/android/c++/JVariant_NullType_CmpSDKOptions.hpp +73 -0
  30. package/nitrogen/generated/android/c++/JVariant_NullType_SettingsPrompt.cpp +26 -0
  31. package/nitrogen/generated/android/c++/JVariant_NullType_SettingsPrompt.hpp +74 -0
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/AppPermission.kt +44 -16
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/BannerConfig.kt +113 -39
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/CmpSDKOptions.kt +50 -18
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/CustomColors.kt +41 -15
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/Func_void_bool.kt +1 -1
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/HybridConsentSDKSpec.kt +16 -5
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/PermissionConsent.kt +24 -8
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/PostConsentsRequest.kt +53 -19
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/Purpose.kt +53 -19
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/PurposeConsent.kt +27 -9
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/SDK.kt +44 -16
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/SettingsPrompt.kt +30 -10
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/Variant_NullType_BannerConfig.kt +59 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/Variant_NullType_CmpSDKOptions.kt +59 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/securiticonsentsdk/Variant_NullType_SettingsPrompt.kt +59 -0
  47. package/nitrogen/generated/ios/NitroSecuritiConsentSdk-Swift-Cxx-Bridge.cpp +28 -19
  48. package/nitrogen/generated/ios/NitroSecuritiConsentSdk-Swift-Cxx-Bridge.hpp +313 -163
  49. package/nitrogen/generated/ios/NitroSecuritiConsentSdk-Swift-Cxx-Umbrella.hpp +4 -1
  50. package/nitrogen/generated/ios/NitroSecuritiConsentSdkAutolinking.mm +1 -1
  51. package/nitrogen/generated/ios/NitroSecuritiConsentSdkAutolinking.swift +2 -2
  52. package/nitrogen/generated/ios/c++/HybridConsentSDKSpecSwift.hpp +25 -10
  53. package/nitrogen/generated/ios/swift/AppPermission.swift +21 -7
  54. package/nitrogen/generated/ios/swift/BannerConfig.swift +111 -38
  55. package/nitrogen/generated/ios/swift/CmpSDKOptions.swift +9 -4
  56. package/nitrogen/generated/ios/swift/CustomColors.swift +17 -8
  57. package/nitrogen/generated/ios/swift/Func_void_bool.swift +6 -5
  58. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -0
  59. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -0
  60. package/nitrogen/generated/ios/swift/Func_void_std__unordered_map_std__string__std__string_.swift +55 -0
  61. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__BannerConfig_.swift +59 -0
  62. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__SettingsPrompt_.swift +59 -0
  63. package/nitrogen/generated/ios/swift/Func_void_std__vector_AppPermission_.swift +1 -0
  64. package/nitrogen/generated/ios/swift/Func_void_std__vector_Purpose_.swift +1 -0
  65. package/nitrogen/generated/ios/swift/Func_void_std__vector_SDK_.swift +1 -0
  66. package/nitrogen/generated/ios/swift/HybridConsentSDKSpec.swift +13 -4
  67. package/nitrogen/generated/ios/swift/HybridConsentSDKSpec_cxx.swift +85 -40
  68. package/nitrogen/generated/ios/swift/PermissionConsent.swift +1 -0
  69. package/nitrogen/generated/ios/swift/PostConsentsRequest.swift +5 -2
  70. package/nitrogen/generated/ios/swift/Purpose.swift +47 -11
  71. package/nitrogen/generated/ios/swift/PurposeConsent.swift +1 -0
  72. package/nitrogen/generated/ios/swift/SDK.swift +23 -8
  73. package/nitrogen/generated/ios/swift/SettingsPrompt.swift +11 -5
  74. package/nitrogen/generated/ios/swift/Variant_NullType_BannerConfig.swift +18 -0
  75. package/nitrogen/generated/ios/swift/Variant_NullType_CmpSDKOptions.swift +18 -0
  76. package/nitrogen/generated/ios/swift/Variant_NullType_SettingsPrompt.swift +18 -0
  77. package/nitrogen/generated/shared/c++/AppPermission.hpp +12 -6
  78. package/nitrogen/generated/shared/c++/BannerConfig.hpp +15 -9
  79. package/nitrogen/generated/shared/c++/CmpSDKOptions.hpp +12 -6
  80. package/nitrogen/generated/shared/c++/CustomColors.hpp +13 -7
  81. package/nitrogen/generated/shared/c++/HybridConsentSDKSpec.cpp +1 -0
  82. package/nitrogen/generated/shared/c++/HybridConsentSDKSpec.hpp +9 -6
  83. package/nitrogen/generated/shared/c++/PermissionConsent.hpp +12 -6
  84. package/nitrogen/generated/shared/c++/PostConsentsRequest.hpp +19 -13
  85. package/nitrogen/generated/shared/c++/Purpose.hpp +16 -10
  86. package/nitrogen/generated/shared/c++/PurposeConsent.hpp +12 -6
  87. package/nitrogen/generated/shared/c++/SDK.hpp +12 -6
  88. package/nitrogen/generated/shared/c++/SettingsPrompt.hpp +13 -7
  89. package/package.json +1 -1
  90. package/src/ConsentSDK.nitro.ts +11 -0
  91. package/src/index.ts +11 -0
  92. package/lib/index.d.ts +0 -20
  93. package/nitrogen/generated/ios/swift/Func_void_std__optional_BannerConfig_.swift +0 -52
  94. package/nitrogen/generated/ios/swift/Func_void_std__optional_SettingsPrompt_.swift +0 -52
@@ -164,19 +164,30 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
164
164
 
165
165
  /**
166
166
  * Get consent status for a purpose by ID.
167
+ * Also updates Google Consent Mode parameters if the purpose is mapped to GCM.
167
168
  */
168
169
  override fun getConsentByPurposeId(purposeId: Double): Promise<String> {
169
170
  Log.d(TAG, "getConsentByPurposeId called with id: $purposeId")
170
-
171
+
171
172
  return Promise.async {
172
173
  try {
173
174
  if (!SecuritiMobileCmp.isReady()) {
174
175
  Log.e(TAG, "SDK is not ready, cannot get consent by purpose ID")
175
176
  return@async "not_determined"
176
177
  }
177
-
178
+
179
+ // Get consent status from the native SDK
178
180
  val consentStatus = SecuritiMobileCmp.getConsent(purposeId.toInt())
179
- convertConsentStatusToString(consentStatus)
181
+ val consentStatusString = convertConsentStatusToString(consentStatus)
182
+
183
+ // Update Google Consent Mode if applicable
184
+ try {
185
+ updateGoogleConsentMode()
186
+ } catch (e: Exception) {
187
+ Log.w(TAG, "Failed to update Google Consent Mode: ${e.message}")
188
+ }
189
+
190
+ consentStatusString
180
191
  } catch (e: Exception) {
181
192
  Log.e(TAG, "Error getting consent by purpose ID: ${e.message}")
182
193
  "not_determined"
@@ -186,19 +197,30 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
186
197
 
187
198
  /**
188
199
  * Get consent status for a permission by ID.
200
+ * Also updates Google Consent Mode parameters.
189
201
  */
190
202
  override fun getConsentByPermissionId(permissionId: String): Promise<String> {
191
203
  Log.d(TAG, "getConsentByPermissionId called with id: $permissionId")
192
-
204
+
193
205
  return Promise.async {
194
206
  try {
195
207
  if (!SecuritiMobileCmp.isReady()) {
196
208
  Log.e(TAG, "SDK is not ready, cannot get consent by permission ID")
197
209
  return@async "not_determined"
198
210
  }
199
-
211
+
212
+ // Get consent status from the native SDK
200
213
  val consentStatus = SecuritiMobileCmp.getConsent(permissionId)
201
- convertConsentStatusToString(consentStatus)
214
+ val consentStatusString = convertConsentStatusToString(consentStatus)
215
+
216
+ // Update Google Consent Mode
217
+ try {
218
+ updateGoogleConsentMode()
219
+ } catch (e: Exception) {
220
+ Log.w(TAG, "Failed to update Google Consent Mode: ${e.message}")
221
+ }
222
+
223
+ consentStatusString
202
224
  } catch (e: Exception) {
203
225
  Log.e(TAG, "Error getting consent by permission ID: ${e.message}")
204
226
  "not_determined"
@@ -411,19 +433,19 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
411
433
  /**
412
434
  * Get the banner configuration.
413
435
  */
414
- override fun getBannerConfig(): Promise<BannerConfig?> {
436
+ override fun getBannerConfig(): Promise<Variant_NullType_BannerConfig> {
415
437
  Log.d(TAG, "getBannerConfig called")
416
438
 
417
439
  return Promise.async {
418
440
  try {
419
441
  if (!SecuritiMobileCmp.isReady()) {
420
442
  Log.e(TAG, "SDK is not ready, cannot get banner config")
421
- return@async null
443
+ return@async Variant_NullType_BannerConfig.First(NullTypeCompat.getInstance())
422
444
  }
423
-
445
+
424
446
  // Pass null for now since converting MainConfiguration is complex
425
447
  val nativeBannerConfig = SecuritiMobileCmp.getBannerConfig(null)
426
-
448
+
427
449
  if (nativeBannerConfig != null) {
428
450
  // Convert native banner config to our format
429
451
  val customColors = nativeBannerConfig.customPaletteTheme?.let {
@@ -438,9 +460,9 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
438
460
  preferenceCenterFooterSelector = it.preferenceCenterFooterSelector
439
461
  )
440
462
  }
441
-
463
+
442
464
  // Create our BannerConfig from the native one
443
- BannerConfig(
465
+ val bannerConfig = BannerConfig(
444
466
  hideCloseButton = nativeBannerConfig.hideCloseButton,
445
467
  hideAcceptButton = nativeBannerConfig.hideAcceptButton,
446
468
  embedDSRPortalLink = nativeBannerConfig.embedDSRPortalLink,
@@ -482,12 +504,13 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
482
504
  parentKey to value
483
505
  }
484
506
  )
507
+ Variant_NullType_BannerConfig.Second(bannerConfig)
485
508
  } else {
486
- null
509
+ Variant_NullType_BannerConfig.First(NullTypeCompat.getInstance())
487
510
  }
488
511
  } catch (e: Exception) {
489
512
  Log.e(TAG, "Error getting banner config: ${e.message}")
490
- null
513
+ Variant_NullType_BannerConfig.First(NullTypeCompat.getInstance())
491
514
  }
492
515
  }
493
516
  }
@@ -495,32 +518,33 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
495
518
  /**
496
519
  * Get the current SDK options.
497
520
  */
498
- override fun options(): CmpSDKOptions? {
521
+ override fun options(): Variant_NullType_CmpSDKOptions {
499
522
  Log.d(TAG, "options called")
500
- return sdkOptions
523
+ return sdkOptions?.let { Variant_NullType_CmpSDKOptions.Second(it) }
524
+ ?: Variant_NullType_CmpSDKOptions.First(NullTypeCompat.getInstance())
501
525
  }
502
-
526
+
503
527
  /**
504
528
  * Get the settings prompt configuration.
505
529
  */
506
- override fun getSettingsPrompt(): Promise<SettingsPrompt?> {
530
+ override fun getSettingsPrompt(): Promise<Variant_NullType_SettingsPrompt> {
507
531
  Log.d(TAG, "getSettingsPrompt called")
508
-
532
+
509
533
  return Promise.async {
510
534
  try {
511
535
  if (!SecuritiMobileCmp.isReady()) {
512
536
  Log.e(TAG, "SDK is not ready, cannot get settings prompt")
513
- return@async null
537
+ return@async Variant_NullType_SettingsPrompt.First(NullTypeCompat.getInstance())
514
538
  }
515
-
539
+
516
540
  try {
517
541
  // Get the native SettingsPrompt from the SDK
518
542
  val nativeSettingsPrompt = SecuritiMobileCmp.getSettingsPrompt()
519
-
543
+
520
544
  if (nativeSettingsPrompt != null) {
521
545
  // Log the structure and content of the native SettingsPrompt
522
546
  Log.d(TAG, "Native SettingsPrompt found")
523
-
547
+
524
548
  // Convert boolean permissions map to string-based permissions map
525
549
  val permissionsMap = mutableListOf<String>()
526
550
  nativeSettingsPrompt.permissions?.forEach { (key, value) ->
@@ -529,49 +553,53 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
529
553
  permissionsMap.add(key)
530
554
  }
531
555
  }
532
-
556
+
533
557
  // Return our Nitro SettingsPrompt with converted values
534
- return@async SettingsPrompt(
558
+ val settingsPrompt = SettingsPrompt(
535
559
  promptHeading = this.getString(nativeSettingsPrompt.promptHeading),
536
560
  promptMessage = this.getString(nativeSettingsPrompt.promptMessage),
537
561
  settingsButtonText = this.getString(nativeSettingsPrompt.settingsButtonText),
538
562
  notNowButtonText = this.getString(nativeSettingsPrompt.notNowButtonText),
539
563
  permissions = permissionsMap.toTypedArray()
540
564
  )
565
+ return@async Variant_NullType_SettingsPrompt.Second(settingsPrompt)
541
566
  } else {
542
567
  // If native SDK returns null, return an empty SettingsPrompt
543
568
  Log.d(TAG, "Native SettingsPrompt is null, returning empty SettingsPrompt")
544
- return@async SettingsPrompt(
569
+ val emptyPrompt = SettingsPrompt(
545
570
  promptHeading = "",
546
571
  promptMessage = "",
547
572
  settingsButtonText = "",
548
573
  notNowButtonText = "",
549
574
  permissions = emptyArray()
550
575
  )
576
+ return@async Variant_NullType_SettingsPrompt.Second(emptyPrompt)
551
577
  }
552
578
  } catch (e: Exception) {
553
579
  Log.e(TAG, "Error processing settings prompt: ${e.message}", e)
554
580
  // Return an empty SettingsPrompt in case of error
555
581
  Log.d(TAG, "Returning empty SettingsPrompt due to error")
556
- return@async SettingsPrompt(
582
+ val emptyPrompt = SettingsPrompt(
557
583
  promptHeading = "",
558
584
  promptMessage = "",
559
585
  settingsButtonText = "",
560
586
  notNowButtonText = "",
561
587
  permissions = emptyArray()
562
588
  )
589
+ return@async Variant_NullType_SettingsPrompt.Second(emptyPrompt)
563
590
  }
564
591
  } catch (e: Exception) {
565
592
  Log.e(TAG, "Error getting settings prompt: ${e.message}")
566
593
  // Return an empty SettingsPrompt in case of error
567
594
  Log.d(TAG, "Returning empty SettingsPrompt due to error")
568
- return@async SettingsPrompt(
569
- promptHeading = "",
595
+ val emptyPrompt = SettingsPrompt(
596
+ promptHeading = "",
570
597
  promptMessage = "",
571
598
  settingsButtonText = "",
572
599
  notNowButtonText = "",
573
600
  permissions = emptyArray()
574
601
  )
602
+ return@async Variant_NullType_SettingsPrompt.Second(emptyPrompt)
575
603
  }
576
604
  }
577
605
  }
@@ -581,14 +609,14 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
581
609
  */
582
610
  override fun uploadConsents(request: PostConsentsRequest): Promise<Boolean> {
583
611
  Log.d(TAG, "uploadConsents called")
584
-
612
+
585
613
  return Promise.async {
586
614
  try {
587
615
  if (!SecuritiMobileCmp.isReady()) {
588
616
  Log.e(TAG, "SDK is not ready, cannot upload consents")
589
617
  return@async false
590
618
  }
591
-
619
+
592
620
  // Convert our request to native request
593
621
  val purposeConsents = request.purposeConsents.map { purposeConsent ->
594
622
  ai.securiti.cmpsdkcore.network.models.request.PurposeConsent(
@@ -598,7 +626,7 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
598
626
  isEssential = purposeConsent.isEssential
599
627
  )
600
628
  }
601
-
629
+
602
630
  val permissionConsents = request.permissions.map { permissionConsent ->
603
631
  ai.securiti.cmpsdkcore.network.models.request.PermissionConsent(
604
632
  permission = permissionConsent.permission,
@@ -606,7 +634,7 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
606
634
  timestamp = permissionConsent.timestamp.toLong()
607
635
  )
608
636
  }
609
-
637
+
610
638
  val nativeRequest = ai.securiti.cmpsdkcore.network.models.request.PostConsentsRequest(
611
639
  uuid = request.uuid,
612
640
  appUUID = request.appUUID,
@@ -621,7 +649,7 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
621
649
  sdkVersion = request.sdkVersion,
622
650
  platform = request.platform ?: "android"
623
651
  )
624
-
652
+
625
653
  // Upload consents
626
654
  SecuritiMobileCmp.uploadConsents(nativeRequest)
627
655
  } catch (e: Exception) {
@@ -630,6 +658,45 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
630
658
  }
631
659
  }
632
660
  }
661
+
662
+ /**
663
+ * Get Google Consent Mode (GCM) consents.
664
+ * Returns a map of Google Consent Type to Consent Status.
665
+ */
666
+ override fun getGCMConsents(): Promise<Map<String, String>> {
667
+ Log.d(TAG, "getGCMConsents called")
668
+
669
+ return Promise.async {
670
+ try {
671
+ if (!SecuritiMobileCmp.isReady()) {
672
+ Log.e(TAG, "SDK is not ready, cannot get GCM consents")
673
+ return@async emptyMap()
674
+ }
675
+
676
+ // Get GCM consents from native SDK
677
+ val nativeGcmConsents = SecuritiMobileCmp.getGCMConsents()
678
+
679
+ // Convert the map to string keys and string values
680
+ val result = mutableMapOf<String, String>()
681
+ for ((consentType, consentStatus) in nativeGcmConsents) {
682
+ // Convert GoogleConsentType enum to its string representation
683
+ val key = when (consentType) {
684
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.ANALYTICS_STORAGE -> "analytics_storage"
685
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.AD_STORAGE -> "ad_storage"
686
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.AD_USER_DATA -> "ad_user_data"
687
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.AD_PERSONALIZATION -> "ad_personalization"
688
+ }
689
+ // Convert ConsentStatus enum to lowercase string
690
+ result[key] = convertConsentStatusToString(consentStatus)
691
+ }
692
+
693
+ result
694
+ } catch (e: Exception) {
695
+ Log.e(TAG, "Error getting GCM consents: ${e.message}")
696
+ emptyMap()
697
+ }
698
+ }
699
+ }
633
700
 
634
701
  /**
635
702
  * Convert Securiti SDK's ConsentStatus to string representation.
@@ -666,4 +733,71 @@ class HybridConsentSDK : HybridConsentSDKSpec() {
666
733
  private fun getString(value: String?) : String {
667
734
  return value ?: ""
668
735
  }
736
+
737
+ /**
738
+ * Update Google Consent Mode parameters based on current consent states.
739
+ * This method gets the GCM consents from the SDK and updates Firebase Analytics.
740
+ */
741
+ private fun updateGoogleConsentMode() {
742
+ try {
743
+ if (!SecuritiMobileCmp.isReady()) {
744
+ Log.w(TAG, "SDK is not ready, cannot update Google Consent Mode")
745
+ return
746
+ }
747
+
748
+ // Get Google Consent Mode consents from the native SDK using runBlocking
749
+ // since getGCMConsents() is a suspend function
750
+ val gcmConsents = runBlocking {
751
+ SecuritiMobileCmp.getGCMConsents()
752
+ }
753
+
754
+ if (gcmConsents.isEmpty()) {
755
+ Log.d(TAG, "No GCM consents available")
756
+ return
757
+ }
758
+
759
+ // Try to update Firebase Analytics consent if available
760
+ try {
761
+ val firebaseAnalyticsClass = Class.forName("com.google.firebase.analytics.FirebaseAnalytics")
762
+ val getInstanceMethod = firebaseAnalyticsClass.getMethod("getInstance", android.content.Context::class.java)
763
+ val setConsentMethod = firebaseAnalyticsClass.getMethod("setConsent", Map::class.java)
764
+
765
+ val appContext = NitroModules.applicationContext
766
+ if (appContext != null) {
767
+ val firebaseAnalytics = getInstanceMethod.invoke(null, appContext)
768
+
769
+ // Build consent map for Firebase Analytics
770
+ val consentMap = mutableMapOf<String, Any>()
771
+
772
+ gcmConsents.forEach { (consentType, consentStatus) ->
773
+ val consentKey = when (consentType) {
774
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.ANALYTICS_STORAGE -> "analytics_storage"
775
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.AD_STORAGE -> "ad_storage"
776
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.AD_USER_DATA -> "ad_user_data"
777
+ ai.securiti.cmpsdkcore.network.models.common.GoogleConsentType.AD_PERSONALIZATION -> "ad_personalization"
778
+ }
779
+
780
+ // Convert consent status to Firebase Analytics format
781
+ val consentValue = when (consentStatus) {
782
+ ai.securiti.cmpsdkcore.network.models.common.ConsentStatus.GRANTED -> "granted"
783
+ ai.securiti.cmpsdkcore.network.models.common.ConsentStatus.DECLINED -> "denied"
784
+ else -> "denied"
785
+ }
786
+
787
+ consentMap[consentKey] = consentValue
788
+ }
789
+
790
+ // Set consent in Firebase Analytics
791
+ setConsentMethod.invoke(firebaseAnalytics, consentMap)
792
+ Log.d(TAG, "Google Consent Mode updated in Firebase Analytics: $consentMap")
793
+ }
794
+ } catch (e: ClassNotFoundException) {
795
+ Log.d(TAG, "Firebase Analytics not found in classpath, skipping GCM update")
796
+ } catch (e: Exception) {
797
+ Log.w(TAG, "Failed to update Firebase Analytics consent: ${e.message}")
798
+ }
799
+ } catch (e: Exception) {
800
+ Log.e(TAG, "Error updating Google Consent Mode: ${e.message}")
801
+ }
802
+ }
669
803
  }
@@ -0,0 +1,19 @@
1
+ package com.margelo.nitro.securiticonsentsdk
2
+
3
+ import com.margelo.nitro.core.NullType
4
+
5
+ /**
6
+ * Compatibility helper to work around NullType's private constructor.
7
+ * This uses reflection to create NullType instances.
8
+ */
9
+ object NullTypeCompat {
10
+ fun getInstance(): NullType {
11
+ return try {
12
+ val constructor = NullType::class.java.getDeclaredConstructor()
13
+ constructor.isAccessible = true
14
+ constructor.newInstance()
15
+ } catch (e: Exception) {
16
+ throw RuntimeException("Failed to create NullType instance", e)
17
+ }
18
+ }
19
+ }
@@ -46,7 +46,6 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
46
46
  testingMode: options.testingMode,
47
47
  logLevel: logLevel,
48
48
  consentsCheckInterval: Int(options.consentsCheckInterval),
49
- subjectId: options.subjectId,
50
49
  languageCode: options.languageCode,
51
50
  locationCode: options.locationCode
52
51
  ))
@@ -315,22 +314,22 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
315
314
  }
316
315
  }
317
316
 
318
- public func getBannerConfig() throws -> Promise<BannerConfig?> {
317
+ public func getBannerConfig() throws -> Promise<Variant_NullType_BannerConfig> {
319
318
  print("*** getBannerConfig method called ***")
320
319
  os_log("*** getBannerConfig method called in os_log ***")
321
-
320
+
322
321
  return Promise.async {
323
-
322
+
324
323
  if ConsentSDK.shared.getStatus() != .available {
325
324
  debugPrint(NSError(domain: "HybridConsentSDK", code: 1,
326
325
  userInfo: [NSLocalizedDescriptionKey: "SDK is not ready"]))
327
- return BannerConfig()
326
+ return .first(.null)
328
327
  }
329
-
328
+
330
329
  // Otherwise try to get config from the SDK
331
330
  if let nativeBannerConfig = await ConsentSDK.shared.getBannerConfig() {
332
331
  var bannerConfig = BannerConfig()
333
-
332
+
334
333
  // Map properties from native BannerConfig to our model
335
334
  bannerConfig.hideCloseButton = nativeBannerConfig.hideCloseButton
336
335
  bannerConfig.hideAcceptButton = nativeBannerConfig.hideAcceptButton
@@ -364,16 +363,16 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
364
363
  // Convert nested dictionary structure to a flattened Map
365
364
  if let nestedTranslations = nativeBannerConfig.translations {
366
365
  var flattenedTranslations: [String: String] = [:]
367
-
366
+
368
367
  // For each parent key (e.g., "Go back")
369
368
  for (parentKey, innerDict) in nestedTranslations {
370
369
  // Get the inner dictionary and extract its values directly
371
370
  flattenedTranslations[parentKey] = self.getString(innerDict)
372
371
  }
373
-
372
+
374
373
  bannerConfig.translations = flattenedTranslations
375
374
  }
376
-
375
+
377
376
  // Map custom colors if available
378
377
  if let nativeColors = nativeBannerConfig.customPaletteTheme {
379
378
  var customColors = CustomColors()
@@ -385,58 +384,62 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
385
384
  customColors.bannerLinks = nativeColors.bannerLinks
386
385
  customColors.preferenceCenterFooterBackground = nativeColors.preferenceCenterFooterBackground
387
386
  customColors.preferenceCenterFooterSelector = nativeColors.preferenceCenterFooterSelector
388
-
387
+
389
388
  bannerConfig.customPaletteTheme = customColors
390
389
  }
391
-
392
- return bannerConfig
390
+
391
+ return .second(bannerConfig)
393
392
  } else {
394
- return nil
393
+ return .first(.null)
395
394
  }
396
395
  }
397
396
  }
398
397
 
399
- public func options() throws -> CmpSDKOptions? {
398
+ public func options() throws -> Variant_NullType_CmpSDKOptions {
400
399
  print("*** options method called ***")
401
400
  os_log("*** options method called in os_log ***")
402
-
401
+
403
402
  // Just return the stored options from the initialize call
404
- return self.sdkOptions
403
+ if let options = self.sdkOptions {
404
+ return .second(options)
405
+ } else {
406
+ return .first(.null)
407
+ }
405
408
  }
406
409
 
407
- public func getSettingsPrompt() throws -> Promise<SettingsPrompt?> {
410
+ public func getSettingsPrompt() throws -> Promise<Variant_NullType_SettingsPrompt> {
408
411
  print("*** getSettingsPrompt method called ***")
409
412
  os_log("*** getSettingsPrompt method called in os_log ***")
410
-
413
+
411
414
  return Promise.async {
412
415
  if ConsentSDK.shared.getStatus() != .available {
413
416
  debugPrint(NSError(domain: "HybridConsentSDK", code: 1,
414
417
  userInfo: [NSLocalizedDescriptionKey: "SDK is not ready"]))
415
- return SettingsPrompt()
418
+ return .first(.null)
416
419
  }
417
-
420
+
418
421
  // Get settings prompt configuration
419
422
  if let nativeSettingsPrompt = await ConsentSDK.shared.getSettingsPrompt() {
420
423
  var settingsPrompt = SettingsPrompt()
421
-
424
+
422
425
  var settingPromptPermissions: [String] = []
423
-
426
+
424
427
  nativeSettingsPrompt.permissions?.keys.forEach {
425
428
  if(nativeSettingsPrompt.permissions?[$0] == true) {
426
429
  settingPromptPermissions.append($0)
427
430
  }
428
431
  }
429
-
432
+
430
433
  // Map properties from native SettingsPrompt to our model
431
434
  settingsPrompt.promptHeading = self.getString(nativeSettingsPrompt.promptHeading)
432
435
  settingsPrompt.promptMessage = self.getString(nativeSettingsPrompt.promptMessage)
433
436
  settingsPrompt.settingsButtonText = self.getString(nativeSettingsPrompt.settingsButtonText)
434
437
  settingsPrompt.notNowButtonText = self.getString(nativeSettingsPrompt.notNowButtonText)
435
438
  settingsPrompt.permissions = settingPromptPermissions
436
-
437
- return settingsPrompt
439
+
440
+ return .second(settingsPrompt)
438
441
  } else {
439
- return SettingsPrompt()
442
+ return .first(.null)
440
443
  }
441
444
  }
442
445
  }
@@ -444,14 +447,14 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
444
447
  public func uploadConsents(request: PostConsentsRequest) throws -> Promise<Bool> {
445
448
  print("*** uploadConsents method called ***")
446
449
  os_log("*** uploadConsents method called in os_log ***")
447
-
450
+
448
451
  return Promise.async {
449
452
  if ConsentSDK.shared.getStatus() != .available {
450
453
  debugPrint(NSError(domain: "HybridConsentSDK", code: 1,
451
454
  userInfo: [NSLocalizedDescriptionKey: "SDK is not ready"]))
452
455
  return false
453
456
  }
454
-
457
+
455
458
  // Create native purpose consents array
456
459
  var nativePurposeConsents: [ConsentUI.PurposeConsent] = []
457
460
  for purposeConsent in request.purposeConsents {
@@ -464,7 +467,7 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
464
467
  )
465
468
  nativePurposeConsents.append(nativePurposeConsent)
466
469
  }
467
-
470
+
468
471
  // Create native permission consents array
469
472
  var nativePermissionConsents: [ConsentUI.PermissionConsent] = []
470
473
  for permissionConsent in request.permissions {
@@ -476,7 +479,7 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
476
479
  )
477
480
  nativePermissionConsents.append(nativePermissionConsent)
478
481
  }
479
-
482
+
480
483
  // Create the request object for native SDK
481
484
  let nativeRequest = ConsentUI.PostConsentsRequest(
482
485
  uuid: request.uuid,
@@ -490,12 +493,55 @@ public class HybridConsentSDK : HybridConsentSDKSpec {
490
493
  adId: request.adId,
491
494
  bannerInfo: request.bannerInfo
492
495
  )
493
-
496
+
494
497
  // Upload consents
495
498
  await ConsentSDK.shared.uploadConsents(url: self.sdkOptions?.appURL ?? "", request: nativeRequest)
496
499
  return true
497
500
  }
498
501
  }
502
+
503
+ public func getGCMConsents() throws -> Promise<[String: String]> {
504
+ print("*** getGCMConsents method called ***")
505
+ os_log("*** getGCMConsents method called in os_log ***")
506
+
507
+ return Promise.async {
508
+ if ConsentSDK.shared.getStatus() != .available {
509
+ debugPrint(NSError(domain: "HybridConsentSDK", code: 1,
510
+ userInfo: [NSLocalizedDescriptionKey: "SDK is not ready"]))
511
+ return [:]
512
+ }
513
+
514
+ // Get GCM consents from native SDK
515
+ let nativeGcmConsents = await ConsentSDK.shared.getGCMConsents()
516
+
517
+ // Convert the map to string keys and string values
518
+ var result: [String: String] = [:]
519
+
520
+ for (consentType, purpose) in nativeGcmConsents {
521
+ // Get the raw value string from the GoogleConsentType enum
522
+ let key = consentType.rawValue
523
+
524
+ // Convert ConsentStatus to lowercase string
525
+ let statusString: String
526
+ switch purpose.consentStatus {
527
+ case .granted:
528
+ statusString = "granted"
529
+ case .declined:
530
+ statusString = "declined"
531
+ case .notDetermined:
532
+ statusString = "not_determined"
533
+ case .withDrawn:
534
+ statusString = "withdrawn"
535
+ @unknown default:
536
+ statusString = "not_determined"
537
+ }
538
+
539
+ result[key] = statusString
540
+ }
541
+
542
+ return result
543
+ }
544
+ }
499
545
 
500
546
  public func getConsentByPermissionId(permissionId: String) throws -> Promise<String> {
501
547
  print("*** getConsentByPermissionId method called with permissionId: \(permissionId) ***")
@@ -167,6 +167,13 @@ export interface PurposeObject {
167
167
  export interface PermissionObject {
168
168
  permissionId: string;
169
169
  }
170
+ export type GoogleConsentType = string;
171
+ export declare const GoogleConsentTypeValues: {
172
+ ANALYTICS_STORAGE: GoogleConsentType;
173
+ AD_STORAGE: GoogleConsentType;
174
+ AD_USER_DATA: GoogleConsentType;
175
+ AD_PERSONALIZATION: GoogleConsentType;
176
+ };
170
177
  export interface ConsentSDK extends HybridObject<{
171
178
  ios: 'swift';
172
179
  android: 'kotlin';
@@ -184,6 +191,7 @@ export interface ConsentSDK extends HybridObject<{
184
191
  getSdksInPurpose(purposeId: number): Promise<Array<SDK>>;
185
192
  setPurposeConsent(purpose: Purpose, consent: string): boolean;
186
193
  setPermissionConsent(permission: AppPermission, consent: string): boolean;
194
+ getGCMConsents(): Promise<Record<string, string>>;
187
195
  getBannerConfig(): Promise<BannerConfig | null>;
188
196
  options(): CmpSDKOptions | null;
189
197
  getSettingsPrompt(): Promise<SettingsPrompt | null>;
@@ -31,3 +31,9 @@ export const ButtonShapeValues = {
31
31
  PILL: 'pill',
32
32
  OUTLINED: 'outlined',
33
33
  };
34
+ export const GoogleConsentTypeValues = {
35
+ ANALYTICS_STORAGE: 'analytics_storage',
36
+ AD_STORAGE: 'ad_storage',
37
+ AD_USER_DATA: 'ad_user_data',
38
+ AD_PERSONALIZATION: 'ad_personalization',
39
+ };
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { NitroModules } from 'react-native-nitro-modules';
2
- export { LoggerLevel, ModeValues, ConsentStatusValues, ComplianceTypeValues, BannerPositionValues, ButtonShapeValues, } from './ConsentSDK.nitro';
2
+ export { LoggerLevel, ModeValues, ConsentStatusValues, ComplianceTypeValues, BannerPositionValues, ButtonShapeValues, GoogleConsentTypeValues, } from './ConsentSDK.nitro';
3
3
  // Create the hybrid object
4
4
  const ConsentSDKHybridObject = NitroModules.createHybridObject('ConsentSDK');
5
5
  // Core methods
@@ -56,3 +56,10 @@ export function getSettingsPrompt() {
56
56
  export function uploadConsents(request) {
57
57
  return ConsentSDKHybridObject.uploadConsents(request);
58
58
  }
59
+ /**
60
+ * Get Google Consent Mode (GCM) consents
61
+ * Returns a map of Google Consent Type to Consent Status
62
+ */
63
+ export function getGCMConsents() {
64
+ return ConsentSDKHybridObject.getGCMConsents();
65
+ }