@usercentrics/react-native-sdk 2.0.4-rc1 → 2.2.1

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 (52) hide show
  1. package/README.md +2 -0
  2. package/android/build.gradle +1 -1
  3. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/RNUsercentricsModuleTest.kt +41 -2
  4. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/api/FakeUsercentricsProxy.kt +23 -1
  5. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/GetCMPDataMock.kt +2 -1
  6. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/GetConsentsMock.kt +19 -1
  7. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/GetTCFDataMock.kt +2 -0
  8. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/SaveDecisionsForTCFMock.kt +18 -1
  9. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/SaveDecisionsMock.kt +0 -1
  10. package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/ShowFirstLayerMock.kt +27 -0
  11. package/android/src/main/java/com/usercentrics/reactnativeusercentrics/RNUsercentricsModule.kt +44 -0
  12. package/android/src/main/java/com/usercentrics/reactnativeusercentrics/api/UsercentricsProxy.kt +42 -1
  13. package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/FirstLayerOptionsExtensions.kt +160 -0
  14. package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/TCFDataExtensions.kt +1 -0
  15. package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/UsercentricsServiceConsentExtensions.kt +21 -0
  16. package/ios/Extensions/BannerSettings+Dict.swift +180 -0
  17. package/ios/Extensions/TCFData+Dict.swift +2 -1
  18. package/ios/Extensions/UIColor+Extensions.swift +52 -0
  19. package/ios/Extensions/UIFont+UsercentricsFontDict.swift +15 -0
  20. package/ios/Extensions/UIImage+UsercentricsLogoDict.swift +14 -0
  21. package/ios/Extensions/UsercentricsCMPData+Dict.swift +1 -1
  22. package/ios/Extensions/UsercentricsServiceConsents+Dict.swift +14 -0
  23. package/ios/Extensions/UsercentricsUISettings+Dict.swift +1 -0
  24. package/ios/Manager/UsercentricsManager.swift +33 -0
  25. package/ios/RNUsercentricsModule.m +8 -0
  26. package/ios/RNUsercentricsModule.swift +91 -28
  27. package/ios/RNUsercentricsModule.xcodeproj/project.pbxproj +16 -0
  28. package/lib/Usercentrics.d.ts +6 -1
  29. package/lib/Usercentrics.js +11 -0
  30. package/lib/Usercentrics.js.map +1 -1
  31. package/lib/models/BannerSettings.d.ts +6 -0
  32. package/lib/models/BannerSettings.js +7 -0
  33. package/lib/models/BannerSettings.js.map +1 -0
  34. package/lib/models/FirstLayerOptions.d.ts +82 -0
  35. package/lib/models/FirstLayerOptions.js +104 -0
  36. package/lib/models/FirstLayerOptions.js.map +1 -0
  37. package/lib/models/SecondLayerOptions.d.ts +6 -0
  38. package/lib/models/SecondLayerOptions.js +7 -0
  39. package/lib/models/SecondLayerOptions.js.map +1 -0
  40. package/lib/models/TCFData.d.ts +9 -8
  41. package/lib/models/TCFData.js +2 -1
  42. package/lib/models/TCFData.js.map +1 -1
  43. package/lib/models/UsercentricsServiceConsent.d.ts +9 -1
  44. package/lib/models/UsercentricsServiceConsent.js +10 -1
  45. package/lib/models/UsercentricsServiceConsent.js.map +1 -1
  46. package/lib/models/UsercentricsUIOptions.d.ts +2 -1
  47. package/lib/models/UsercentricsUIOptions.js +2 -1
  48. package/lib/models/UsercentricsUIOptions.js.map +1 -1
  49. package/lib/models/index.d.ts +3 -0
  50. package/lib/models/index.js +3 -0
  51. package/lib/models/index.js.map +1 -1
  52. package/package.json +2 -2
@@ -0,0 +1,180 @@
1
+ import Foundation
2
+ import UsercentricsUI
3
+
4
+ extension BannerSettings {
5
+ init?(from dictionary: NSDictionary?) {
6
+ guard let dictionary = dictionary else { return nil }
7
+
8
+ self.init(font: UIFont(from: dictionary["font"] as? NSDictionary),
9
+ logo: UIImage(from: dictionary["logo"] as? NSDictionary))
10
+ }
11
+ }
12
+
13
+ extension FirstLayerStyleSettings {
14
+ init?(from dictionary: NSDictionary?) {
15
+ guard let dictionary = dictionary else { return nil }
16
+
17
+ self.init(headerImage: HeaderImageSettings.from(dictionary: dictionary["headerImage"] as? NSDictionary),
18
+ title: TitleSettings(from: dictionary["title"] as? NSDictionary),
19
+ message: MessageSettings(from: dictionary["message"] as? NSDictionary),
20
+ buttonLayout: ButtonLayout.from(dictionary: dictionary["buttonLayout"] as? NSDictionary),
21
+ backgroundColor: UIColor(unsafeHex: dictionary["backgroundColorHex"] as? String),
22
+ cornerRadius: dictionary["cornerRadius"] as? CGFloat,
23
+ overlayColor: UIColor(unsafeHex: dictionary["overlayColorHex"] as? String))
24
+ }
25
+ }
26
+
27
+
28
+ extension HeaderImageSettings {
29
+ static func from(dictionary: NSDictionary?) -> HeaderImageSettings? {
30
+ guard let dictionary = dictionary else { return nil }
31
+
32
+ if let isHidden = dictionary["isHidden"] as? Bool, isHidden {
33
+ return .hidden
34
+ }
35
+
36
+ let logoDict = dictionary["image"] as? NSDictionary
37
+ let logo = UIImage(from: logoDict)
38
+
39
+ if let isExtended = dictionary["isExtended"] as? Bool, isExtended {
40
+ return .extended(image: logo)
41
+ }
42
+
43
+ let logoUrlString = logoDict?["logoUrl"] as? String
44
+
45
+ return .logo(settings: LogoSettings(image: logo,
46
+ url: URL(string: logoUrlString ?? ""),
47
+ position: SectionPosition.from(enumString: dictionary["alignment"] as? String),
48
+ height: dictionary["height"] as? CGFloat))
49
+ }
50
+ }
51
+
52
+ extension TitleSettings {
53
+ init?(from dictionary: NSDictionary?) {
54
+ guard let dictionary = dictionary else { return nil }
55
+
56
+ self.init(font: UIFont(from: dictionary["font"] as? NSDictionary),
57
+ textColor: UIColor(unsafeHex: dictionary["textColorHex"] as? String ?? ""),
58
+ textAlignment: NSTextAlignment.from(enumString: dictionary["textAlignment"] as? String))
59
+ }
60
+ }
61
+
62
+
63
+ extension MessageSettings {
64
+ init?(from dictionary: NSDictionary?) {
65
+ guard let dictionary = dictionary else { return nil }
66
+
67
+ self.init(font: UIFont(from: dictionary["font"] as? NSDictionary),
68
+ textColor: UIColor(unsafeHex: dictionary["textColorHex"] as? String ?? ""),
69
+ textAlignment: NSTextAlignment.from(enumString: dictionary["textAlignment"] as? String),
70
+ linkTextColor: UIColor(unsafeHex: dictionary["linkTextColorHex"] as? String ?? ""),
71
+ linkTextUnderline: dictionary["linkTextUnderline"] as? Bool ?? true)
72
+ }
73
+ }
74
+
75
+ extension ButtonLayout {
76
+ static func from(dictionary: NSDictionary?) -> ButtonLayout? {
77
+ guard let dictionary = dictionary else { return nil }
78
+
79
+ let layoutDict = dictionary["layout"] as? String
80
+ let buttons = (dictionary["buttons"] as? [[NSDictionary]]) ?? []
81
+
82
+ switch layoutDict {
83
+ case "ROW":
84
+ return .row(buttons: buttons.flatMap { $0 }.compactMap { ButtonSettings(from: $0) })
85
+ case "COLUMN":
86
+ return .column(buttons: buttons.flatMap { $0 }.compactMap { ButtonSettings(from: $0) })
87
+ case "GRID":
88
+ let gridButtons = buttons.map { $0.compactMap { button in ButtonSettings(from: button) }}
89
+ return .grid(buttons: gridButtons)
90
+ default:
91
+ break
92
+ }
93
+
94
+ return nil
95
+ }
96
+ }
97
+
98
+ extension ButtonSettings {
99
+ init?(from dictionary: NSDictionary?) {
100
+ guard
101
+ let dictionary = dictionary,
102
+ let buttonTypeDict = dictionary["buttonType"] as? String,
103
+ let buttonType = ButtonType.from(enumString: buttonTypeDict)
104
+ else { return nil }
105
+
106
+ self.init(type: buttonType,
107
+ font: UIFont(from: dictionary["font"] as? NSDictionary),
108
+ textColor: UIColor(unsafeHex: dictionary["textColorHex"] as? String),
109
+ backgroundColor: UIColor(unsafeHex: dictionary["backgroundColorHex"] as? String),
110
+ cornerRadius: dictionary["cornerRadius"] as? CGFloat)
111
+ }
112
+ }
113
+
114
+ extension ButtonType {
115
+ static func from(enumString: String) -> ButtonType? {
116
+ switch enumString {
117
+ case "ACCEPT_ALL":
118
+ return .acceptAll
119
+ case "DENY_ALL":
120
+ return .denyAll
121
+ case "MORE":
122
+ return .more
123
+ case "SAVE":
124
+ return .save
125
+ default:
126
+ return nil
127
+ }
128
+ }
129
+ }
130
+
131
+ extension UsercentricsLayout {
132
+ static func from(enumString: String) -> UsercentricsLayout? {
133
+ switch enumString {
134
+ case "FULL":
135
+ return .full
136
+ case "SHEET":
137
+ return .sheet
138
+ case "POPUP_CENTER":
139
+ return .popup(position: .center)
140
+ case "POPUP_BOTTOM":
141
+ return .popup(position: .bottom)
142
+ default:
143
+ return nil
144
+ }
145
+ }
146
+ }
147
+
148
+ extension SectionPosition {
149
+ static func from(enumString: String?) -> SectionPosition? {
150
+ guard let enumString = enumString else { return nil }
151
+
152
+ switch enumString {
153
+ case "CENTER":
154
+ return .center
155
+ case "END":
156
+ return .right
157
+ case "START":
158
+ return .left
159
+ default:
160
+ return nil
161
+ }
162
+ }
163
+ }
164
+
165
+ extension NSTextAlignment {
166
+ static func from(enumString: String?) -> NSTextAlignment? {
167
+ guard let enumString = enumString else { return nil }
168
+
169
+ switch enumString {
170
+ case "CENTER":
171
+ return .center
172
+ case "RIGHT":
173
+ return .right
174
+ case "LEFT":
175
+ return .left
176
+ default:
177
+ return nil
178
+ }
179
+ }
180
+ }
@@ -102,7 +102,8 @@ extension TCFVendor {
102
102
  "usesNonCookieAccess" : usesNonCookieAccess,
103
103
  "deviceStorageDisclosureUrl" : deviceStorageDisclosureUrl as Any,
104
104
  "usesCookies" : usesCookies,
105
- "cookieRefresh" : cookieRefresh?.boolValue as Any ,
105
+ "cookieRefresh" : cookieRefresh?.boolValue as Any,
106
+ "dataSharedOutsideEU": dataSharedOutsideEU?.boolValue as Any
106
107
  ]
107
108
  }
108
109
  }
@@ -0,0 +1,52 @@
1
+ import Foundation
2
+
3
+ extension UIColor {
4
+ convenience init?(unsafeHex: String?) {
5
+ guard let unsafeHex = unsafeHex else { return nil }
6
+ if unsafeHex.hasPrefix("#") {
7
+ self.init(hex: unsafeHex)
8
+ } else {
9
+ self.init(hex: "#\(unsafeHex)")
10
+ }
11
+ }
12
+
13
+ convenience init?(hex: String) {
14
+ let r, g, b, a: CGFloat
15
+
16
+ if hex.hasPrefix("#") {
17
+ let start = hex.index(hex.startIndex, offsetBy: 1)
18
+ let hexColor = String(hex[start...])
19
+
20
+ if hexColor.count == 8 {
21
+ let scanner = Scanner(string: hexColor)
22
+ var hexNumber: UInt64 = 0
23
+
24
+ if scanner.scanHexInt64(&hexNumber) {
25
+ r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
26
+ g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
27
+ b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
28
+ a = CGFloat(hexNumber & 0x000000ff) / 255
29
+
30
+ self.init(red: r, green: g, blue: b, alpha: a)
31
+ return
32
+ }
33
+ }
34
+
35
+ if hexColor.count == 6 {
36
+ let scanner = Scanner(string: hexColor)
37
+ var hexNumber: UInt64 = 0
38
+
39
+ if scanner.scanHexInt64(&hexNumber) {
40
+ r = CGFloat((hexNumber & 0xff0000) >> 16) / 255
41
+ g = CGFloat((hexNumber & 0x00ff00) >> 8) / 255
42
+ b = CGFloat(hexNumber & 0x0000ff) / 255
43
+
44
+ self.init(red: r, green: g, blue: b, alpha: 1.0)
45
+ return
46
+ }
47
+ }
48
+ }
49
+
50
+ return nil
51
+ }
52
+ }
@@ -0,0 +1,15 @@
1
+ import Foundation
2
+
3
+
4
+ extension UIFont {
5
+ convenience init?(from dictionary: NSDictionary?) {
6
+ guard let dictionary = dictionary else { return nil }
7
+
8
+ if let customFontName = dictionary["fontName"] as? String,
9
+ let customFontSize = dictionary["fontSize"] as? CGFloat {
10
+ self.init(name: customFontName, size: customFontSize)
11
+ } else {
12
+ return nil
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ import Foundation
2
+
3
+ extension UIImage {
4
+ convenience init?(from dictionary: NSDictionary?) {
5
+ guard
6
+ let dictionary = dictionary,
7
+ let logoName = dictionary["logoName"] as? String
8
+ else {
9
+ return nil
10
+ }
11
+
12
+ self.init(named: logoName)
13
+ }
14
+ }
@@ -22,7 +22,7 @@ extension UsercentricsSettings {
22
22
  "displayOnlyForEU" : self.displayOnlyForEU,
23
23
  "urlConsentInfo" : self.urlConsentInfo,
24
24
  "updatedAt" : self.updatedAt as Any,
25
- "secondLayer" : self.secondLayer?.toDictionary() as Any,
25
+ "secondLayer" : self.secondLayer.toDictionary() as Any,
26
26
  "cookiePolicyUrl": self.cookiePolicyUrl as Any,
27
27
  "tcf2": self.tcf2?.toDictionary() as Any,
28
28
  "ccpa": self.ccpa?.toDictionary() as Any,
@@ -14,6 +14,8 @@ public extension UsercentricsServiceConsent {
14
14
  "status": self.status,
15
15
  "version": self.version,
16
16
  "dataProcessor": self.dataProcessor,
17
+ "isEssential": self.isEssential,
18
+ "history": self.history.toDictionary()
17
19
  ]
18
20
 
19
21
  if let type = self.type?.ordinal {
@@ -23,3 +25,15 @@ public extension UsercentricsServiceConsent {
23
25
  return dict
24
26
  }
25
27
  }
28
+
29
+ public extension Array where Element == UsercentricsConsentHistoryEntry {
30
+ func toDictionary() -> [NSDictionary] {
31
+ self.map {
32
+ [
33
+ "status": $0.status,
34
+ "type": $0.type.ordinal,
35
+ "timestampInMillis": $0.timestampInMillis
36
+ ]
37
+ }
38
+ }
39
+ }
@@ -24,3 +24,4 @@ public extension UsercentricsUISettings {
24
24
  showCloseButton: showCloseButton)
25
25
  }
26
26
  }
27
+
@@ -9,6 +9,18 @@ public protocol UsercentricsManager {
9
9
  func restoreUserSession(controllerId: String, onSuccess: @escaping ((UsercentricsReadyStatus) -> Void), onFailure: @escaping ((Error) -> Void))
10
10
 
11
11
  func getPredefinedUI(settings: UsercentricsUISettings?, dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void) -> UIViewController
12
+
13
+ func showFirstLayer(bannerSettings: BannerSettings?,
14
+ hostView: UINavigationController,
15
+ layout: UsercentricsLayout,
16
+ settings: FirstLayerStyleSettings?,
17
+ dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void)
18
+
19
+ func showSecondLayer(bannerSettings: BannerSettings?,
20
+ hostView: UINavigationController,
21
+ showCloseButton: Bool,
22
+ dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void)
23
+
12
24
  func getTCString() -> String
13
25
  func getControllerId() -> String
14
26
  func getConsents() -> [UsercentricsServiceConsent]
@@ -63,6 +75,27 @@ final class UsercentricsManagerImplementation: UsercentricsManager {
63
75
  return UsercentricsUserInterface.getPredefinedUI(settings: settings, dismissViewHandler: dismissViewHandler)
64
76
  }
65
77
 
78
+ func showFirstLayer(bannerSettings: BannerSettings?,
79
+ hostView: UINavigationController,
80
+ layout: UsercentricsLayout,
81
+ settings: FirstLayerStyleSettings?,
82
+ dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void) {
83
+ UsercentricsBanner(bannerSettings: bannerSettings).showFirstLayer(hostView: hostView,
84
+ layout: layout,
85
+ settings: settings,
86
+ completionHandler: dismissViewHandler)
87
+ }
88
+
89
+ func showSecondLayer(bannerSettings: BannerSettings?,
90
+ hostView: UINavigationController,
91
+ showCloseButton: Bool,
92
+ dismissViewHandler: @escaping (UsercentricsConsentUserResponse) -> Void) {
93
+ UsercentricsBanner(bannerSettings: bannerSettings).showSecondLayer(hostView: hostView,
94
+ showCloseButton: showCloseButton,
95
+ presentationMode: .present,
96
+ completionHandler: dismissViewHandler)
97
+ }
98
+
66
99
  func restoreUserSession(controllerId: String, onSuccess: @escaping ((UsercentricsReadyStatus) -> Void), onFailure: @escaping ((Error) -> Void)) {
67
100
  UsercentricsCore.shared.restoreUserSession(controllerId: controllerId, onSuccess: onSuccess, onFailure: onFailure)
68
101
  }
@@ -14,6 +14,14 @@ RCT_EXTERN_METHOD(showCMP:(NSDictionary *)dict
14
14
  resolve:(RCTPromiseResolveBlock)resolve
15
15
  reject:(RCTPromiseRejectBlock)reject)
16
16
 
17
+ RCT_EXTERN_METHOD(showFirstLayer:(NSDictionary *)dict
18
+ resolve:(RCTPromiseResolveBlock)resolve
19
+ reject:(RCTPromiseRejectBlock)reject)
20
+
21
+ RCT_EXTERN_METHOD(showSecondLayer:(NSDictionary *)dict
22
+ resolve:(RCTPromiseResolveBlock)resolve
23
+ reject:(RCTPromiseRejectBlock)reject)
24
+
17
25
  RCT_EXTERN_METHOD(restoreUserSession:(NSString *)controllerId
18
26
  resolve:(RCTPromiseResolveBlock)resolve
19
27
  reject:(RCTPromiseRejectBlock)reject)
@@ -5,30 +5,30 @@ import UIKit
5
5
 
6
6
  @objc(RNUsercentricsModule)
7
7
  class RNUsercentricsModule: NSObject, RCTBridgeModule {
8
-
8
+
9
9
  var usercentricsManager: UsercentricsManager = UsercentricsManagerImplementation()
10
10
  var queue: DispatchQueueManager = DispatchQueue.main
11
11
  var rootVC: PresentationViewController? = UIApplication.shared.delegate?.window??.rootViewController
12
-
12
+
13
13
  @objc static func moduleName() -> String! {
14
14
  return "RNUsercentricsModule"
15
15
  }
16
-
16
+
17
17
  @objc static func requiresMainQueueSetup() -> Bool {
18
18
  return true
19
19
  }
20
-
20
+
21
21
  @objc func configure(_ dict: NSDictionary) -> Void {
22
22
  queue.async { [weak self] in
23
23
  guard
24
24
  let self = self,
25
25
  let userOptions = UsercentricsOptions(from: dict)
26
26
  else { return }
27
-
27
+
28
28
  self.usercentricsManager.configure(options: userOptions)
29
29
  }
30
30
  }
31
-
31
+
32
32
  @objc func isReady(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
33
33
  usercentricsManager.isReady { status in
34
34
  resolve(status.toDictionary())
@@ -36,7 +36,7 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
36
36
  reject("usercentrics_reactNative_isReady_error", error.localizedDescription, error)
37
37
  }
38
38
  }
39
-
39
+
40
40
  @objc func showCMP(_ dict: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
41
41
  queue.async { [weak self] in
42
42
  guard
@@ -52,16 +52,79 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
52
52
  resolve(response.toDictionary())
53
53
  rootVC.dismiss(animated: true)
54
54
  }
55
-
55
+
56
56
  if #available(iOS 13.0, *) { predefinedUI.isModalInPresentation = true }
57
57
  rootVC.present(predefinedUI)
58
58
  }
59
59
  }
60
-
60
+
61
+ @objc func showFirstLayer(_ dict: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
62
+ queue.async { [weak self] in
63
+ guard
64
+ let self = self,
65
+ let rootVC = self.rootVC,
66
+ let layoutString = dict["layout"] as? String,
67
+ let layout = UsercentricsLayout.from(enumString: layoutString)
68
+ else {
69
+ reject("usercentrics_reactNative_showFirstLayer_error", RNUsercentricsModuleError.invalidData.localizedDescription, RNUsercentricsModuleError.invalidData)
70
+ return
71
+ }
72
+
73
+ let nav = UINavigationController()
74
+ nav.setNavigationBarHidden(true, animated: false)
75
+ nav.modalPresentationStyle = .overFullScreen
76
+ if #available(iOS 13.0, *) {
77
+ nav.isModalInPresentation = true
78
+ }
79
+
80
+ rootVC.present(nav)
81
+ let bannerSettingsDict = dict["bannerSettings"] as? NSDictionary
82
+ let styleSettingsDict = dict["styleSettings"] as? NSDictionary
83
+
84
+ self.usercentricsManager.showFirstLayer(bannerSettings: BannerSettings(from: bannerSettingsDict),
85
+ hostView: nav,
86
+ layout: layout,
87
+ settings: FirstLayerStyleSettings(from: styleSettingsDict)) { response in
88
+ rootVC.dismiss(animated: true)
89
+ resolve(response.toDictionary())
90
+ }
91
+ }
92
+ }
93
+
94
+ @objc func showSecondLayer(_ dict: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
95
+ queue.async { [weak self] in
96
+ guard
97
+ let self = self,
98
+ let rootVC = self.rootVC
99
+ else {
100
+ reject("usercentrics_reactNative_showFirstLayer_error", RNUsercentricsModuleError.invalidData.localizedDescription, RNUsercentricsModuleError.invalidData)
101
+ return
102
+ }
103
+ let bannerSettingsDict = dict["bannerSettings"] as? NSDictionary
104
+ let showCloseButton = (dict["showCloseButton"] as? Bool) ?? false
105
+
106
+ let nav = UINavigationController()
107
+ nav.setNavigationBarHidden(true, animated: false)
108
+ nav.modalPresentationStyle = .overFullScreen
109
+ if #available(iOS 13.0, *) {
110
+ nav.isModalInPresentation = true
111
+ }
112
+
113
+ rootVC.present(nav)
114
+
115
+ self.usercentricsManager.showSecondLayer(bannerSettings: BannerSettings(from: bannerSettingsDict),
116
+ hostView: nav,
117
+ showCloseButton: showCloseButton) { response in
118
+ rootVC.dismiss(animated: true)
119
+ resolve(response.toDictionary())
120
+ }
121
+ }
122
+ }
123
+
61
124
  @objc func setCMPId(_ id: Int) -> Void {
62
125
  usercentricsManager.setCMPId(id: Int32(id))
63
126
  }
64
-
127
+
65
128
  @objc func restoreUserSession(_ controllerId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
66
129
  usercentricsManager.restoreUserSession(controllerId: controllerId) { status in
67
130
  resolve(status.toDictionary())
@@ -69,35 +132,35 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
69
132
  reject("usercentrics_reactNative_restoreUserSession_error", error.localizedDescription, error)
70
133
  }
71
134
  }
72
-
135
+
73
136
  @objc func getTCFString(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
74
137
  resolve(usercentricsManager.getTCString())
75
138
  }
76
-
139
+
77
140
  @objc func getControllerId(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
78
141
  resolve(usercentricsManager.getControllerId())
79
142
  }
80
-
143
+
81
144
  @objc func getConsents(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
82
145
  resolve(usercentricsManager.getConsents().toListOfDictionary())
83
146
  }
84
-
147
+
85
148
  @objc func getCMPData(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
86
149
  resolve(usercentricsManager.getCMPData().toDictionary())
87
150
  }
88
-
151
+
89
152
  @objc func getTCFData(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
90
153
  resolve(usercentricsManager.getTCFData().toDictionary())
91
154
  }
92
-
155
+
93
156
  @objc func getUserSessionData(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
94
157
  resolve(usercentricsManager.getUserSessionData())
95
158
  }
96
-
159
+
97
160
  @objc func getUSPData(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
98
161
  resolve(usercentricsManager.getUSPData().toDictionary())
99
162
  }
100
-
163
+
101
164
  @objc func changeLanguage(_ language: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
102
165
  usercentricsManager.changeLanguage(language: language) {
103
166
  resolve(Void.self)
@@ -105,7 +168,7 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
105
168
  reject("usercentrics_reactNative_changeLanguage_error", error.localizedDescription, error)
106
169
  }
107
170
  }
108
-
171
+
109
172
  @objc func acceptAllForTCF(_ fromLayer: Int,
110
173
  consentType: Int,
111
174
  resolve: @escaping RCTPromiseResolveBlock,
@@ -114,14 +177,14 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
114
177
  consentType: UsercentricsConsentType.initialize(from: consentType))
115
178
  resolve(services.toListOfDictionary())
116
179
  }
117
-
180
+
118
181
  @objc func acceptAll(_ consentType: Int,
119
182
  resolve: @escaping RCTPromiseResolveBlock,
120
183
  reject: @escaping RCTPromiseRejectBlock) -> Void {
121
184
  let services = usercentricsManager.acceptAll(consentType: UsercentricsConsentType.initialize(from: consentType))
122
185
  resolve(services.toListOfDictionary())
123
186
  }
124
-
187
+
125
188
  @objc func denyAllForTCF(_ fromLayer: Int,
126
189
  consentType: Int,
127
190
  resolve: @escaping RCTPromiseResolveBlock,
@@ -129,30 +192,30 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
129
192
  let services = usercentricsManager.denyAllForTCF(fromLayer: .initialize(from: fromLayer), consentType: .initialize(from: consentType))
130
193
  resolve(services.toListOfDictionary())
131
194
  }
132
-
195
+
133
196
  @objc func denyAll(_ consentType: Int,
134
197
  resolve: @escaping RCTPromiseResolveBlock,
135
198
  reject: @escaping RCTPromiseRejectBlock) -> Void {
136
199
  let services = usercentricsManager.denyAll(consentType: .initialize(from: consentType))
137
200
  resolve(services.toListOfDictionary())
138
201
  }
139
-
202
+
140
203
  @objc func saveDecisionsForTCF(_ tcfDecisions: NSDictionary,
141
204
  fromLayer: Int,
142
205
  serviceDecisions: [NSDictionary],
143
206
  consentType: Int,
144
207
  resolve: @escaping RCTPromiseResolveBlock,
145
208
  reject: @escaping RCTPromiseRejectBlock) -> Void {
146
-
209
+
147
210
  let services = usercentricsManager.saveDecisionsForTCF(
148
211
  tcfDecisions: TCFUserDecisions(from: tcfDecisions),
149
212
  fromLayer: .initialize(from: fromLayer),
150
213
  serviceDecisions: serviceDecisions.compactMap { UserDecision(from: $0) },
151
214
  consentType: .initialize(from: consentType))
152
215
  resolve(services.toListOfDictionary())
153
-
216
+
154
217
  }
155
-
218
+
156
219
  @objc func saveDecisions(_ decisions: [NSDictionary],
157
220
  consentType: Int,
158
221
  resolve: @escaping RCTPromiseResolveBlock,
@@ -160,7 +223,7 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
160
223
  let services = usercentricsManager.saveDecisions(decisions: decisions.compactMap { UserDecision.init(from: $0) }, consentType: .initialize(from: consentType))
161
224
  resolve(services.toListOfDictionary())
162
225
  }
163
-
226
+
164
227
  @objc func saveOptOutForCCPA(_ isOptedOut: Bool,
165
228
  consentType: Int,
166
229
  resolve: @escaping RCTPromiseResolveBlock,
@@ -168,7 +231,7 @@ class RNUsercentricsModule: NSObject, RCTBridgeModule {
168
231
  let services = usercentricsManager.saveOptOutForCCPA(isOptedOut: isOptedOut, consentType: .initialize(from: consentType))
169
232
  resolve(services.toListOfDictionary())
170
233
  }
171
-
234
+
172
235
  @objc func reset() -> Void {
173
236
  usercentricsManager.reset()
174
237
  }