@usercentrics/react-native-sdk 2.2.1 → 2.4.0
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.
- package/CHANGELOG.md +74 -0
- package/android/build.gradle +1 -1
- package/android/src/androidTest/java/com/usercentrics/reactnativemodule/RNUsercentricsModuleTest.kt +13 -144
- package/android/src/androidTest/java/com/usercentrics/reactnativemodule/api/FakeUsercentricsProxy.kt +4 -31
- package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/GetTCFDataMock.kt +3 -1
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/RNUsercentricsModule.kt +25 -76
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/api/UsercentricsProxy.kt +12 -64
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/BannerFontExtensions.kt +26 -0
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/FirstLayerOptionsExtensions.kt +39 -14
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/TCFDataExtensions.kt +2 -1
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/UsercentricsReadyStatusExtensions.kt +1 -1
- package/ios/Extensions/BannerSettings+Dict.swift +103 -16
- package/ios/Extensions/ReadyStatus+Dict.swift +1 -1
- package/ios/Manager/UsercentricsManager.swift +12 -25
- package/ios/RNUsercentricsModule.swift +19 -55
- package/ios/RNUsercentricsModule.xcodeproj/project.pbxproj +0 -8
- package/lib/Usercentrics.d.ts +4 -5
- package/lib/Usercentrics.js +3 -7
- package/lib/Usercentrics.js.map +1 -1
- package/lib/models/BannerSettings.d.ts +26 -4
- package/lib/models/BannerSettings.js +25 -1
- package/lib/models/BannerSettings.js.map +1 -1
- package/lib/models/FirstLayerOptions.d.ts +14 -12
- package/lib/models/FirstLayerOptions.js +10 -8
- package/lib/models/FirstLayerOptions.js.map +1 -1
- package/lib/models/SecondLayerOptions.d.ts +7 -3
- package/lib/models/SecondLayerOptions.js +6 -1
- package/lib/models/SecondLayerOptions.js.map +1 -1
- package/lib/models/TCFData.d.ts +2 -1
- package/lib/models/TCFData.js +2 -1
- package/lib/models/TCFData.js.map +1 -1
- package/lib/models/UsercentricsReadyStatus.d.ts +2 -2
- package/lib/models/UsercentricsReadyStatus.js +2 -2
- package/lib/models/UsercentricsReadyStatus.js.map +1 -1
- package/lib/models/index.d.ts +2 -3
- package/lib/models/index.js +2 -3
- package/lib/models/index.js.map +1 -1
- package/package.json +2 -2
- package/android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/UsercentricsUserInterfaceExtensions.kt +0 -45
- package/ios/Extensions/UIFont+UsercentricsFontDict.swift +0 -15
- package/ios/Extensions/UsercentricsUISettings+Dict.swift +0 -27
- package/lib/models/UsercentricsUIOptions.d.ts +0 -18
- package/lib/models/UsercentricsUIOptions.js +0 -21
- package/lib/models/UsercentricsUIOptions.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
[Release Notes](https://docs.usercentrics.com/cmp_in_app_sdk/latest/about/history/)
|
|
2
|
+
|
|
3
|
+
# 2.4.0
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **[Customization]** You now have full control over the appearance of the First & Second Layer via our Admin Interface Style options and our Programmatic API. We have updated and extended our Programmatic API to simplify banner customization.
|
|
8
|
+
- **[UI]** Legal links are now added to our the First Layer, and can be hidden or shown as desired via programmatic API.
|
|
9
|
+
- **[CCPA]** Consent button can now be customized via the Admin Interface.
|
|
10
|
+
|
|
11
|
+
## Improvements
|
|
12
|
+
|
|
13
|
+
- Improve initialization flow for stability and avoid edge case crashes.
|
|
14
|
+
|
|
15
|
+
## Resolved Issues
|
|
16
|
+
|
|
17
|
+
- Solve stability issues and bug fixes.
|
|
18
|
+
|
|
19
|
+
# 2.3.0
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **[API Update]** `shouldShowCMP` has been deprecated in favor of `shouldCollectConsent`. See [Initializing the SDK](https://docs.usercentrics.com/cmp_in_app_sdk/latest/getting_started/initialize/#initializing-the-sdk)
|
|
24
|
+
- **[Banner API v2]** Banner API v1 is now discontinued and removed from the SDK. If you don't wish to upgrade, please stick to v2.0.3 to avoid unexpected behaviour. See the [alert in the "Banner API V1" tab](https://docs.usercentrics.com/cmp_in_app_sdk/latest/collect_consent/present_cmp/)
|
|
25
|
+
- **[Banner API v2]** BannerSettings now requires a BannerFont object to pass a Bold and Regular font separately to apply for both layers. See [Banner Settings](https://docs.usercentrics.com/cmp_in_app_sdk/latest/collect_consent/customize_cmp/#banner-style-settings)
|
|
26
|
+
- **[Demo App]** You can now find a demo app in our documentation to test out your configuration before writing a single line of code. See [Sample Apps](https://docs.usercentrics.com/cmp_in_app_sdk/latest/samples/ios-android-demos/).
|
|
27
|
+
|
|
28
|
+
## Improvements
|
|
29
|
+
|
|
30
|
+
- Updates to TCF 2.0 framework.
|
|
31
|
+
|
|
32
|
+
## Resolved Issues
|
|
33
|
+
|
|
34
|
+
- Issue with position of logo on Second Layer is now solved.
|
|
35
|
+
- UI/UX improvements and fixes.
|
|
36
|
+
|
|
37
|
+
# 2.2.1
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **[Banner API v2]** A complete revamp of our banner API will enable you to have high customisation and versatility to build a end-user friendly consent banner. We can't wait for you to give it a try. For more details, see: Presenting the Banner.
|
|
42
|
+
- Add a Header Image to your banner.
|
|
43
|
+
- Have full control over the layour of your action buttons with Column, Row or Grid configurations.
|
|
44
|
+
- Launch the second layer directly.
|
|
45
|
+
- Landscape Mode support.
|
|
46
|
+
- You can now add a "More Information" link to your banner message to forward users to the 2nd Layer. Appearance > Settings > More Information Link in Banner Message. Then you will be able to add this link in the banner message text editor.
|
|
47
|
+
- **[Usability]** Collect consent only at a category level. Option available in your Admin Interface: Configure > Legal Specifications > Settings > Category Consent.
|
|
48
|
+
- **[CNIL]** "Continue wthout Accepting" feature is now supported. (French regulation)
|
|
49
|
+
- **[Fonts]** Admin Interface fonts are now deprecated for App. To enable custom fonts, please inject the font via banner API.
|
|
50
|
+
|
|
51
|
+
## Improvements
|
|
52
|
+
|
|
53
|
+
- **[API]** Expose user's consent history.
|
|
54
|
+
- **[TCF 2.0]** Adding support to actively inform users when vendors are sharing data outside a region.
|
|
55
|
+
- **[CCPA]** Improve API to facilitate compliance with new Banner API.
|
|
56
|
+
|
|
57
|
+
## Resolved Issues
|
|
58
|
+
- **[TCF 2.0]** Minor design upgrades to improve usability.
|
|
59
|
+
- **[iOS]** Edge case with RestoreUserSession failing is now solved.
|
|
60
|
+
- **[iOS]** Issue with local and remote images losing quality is now solved.
|
|
61
|
+
- UI/UX improvements and fixes.
|
|
62
|
+
|
|
63
|
+
# 2.0.3
|
|
64
|
+
|
|
65
|
+
- Minor fix on UI related to consent toggles.
|
|
66
|
+
- Corner radius on iOS.
|
|
67
|
+
|
|
68
|
+
# 2.0.2
|
|
69
|
+
|
|
70
|
+
- Custom UI API.
|
|
71
|
+
|
|
72
|
+
# 2.0.1
|
|
73
|
+
|
|
74
|
+
- Initial version of the library.
|
package/android/build.gradle
CHANGED
package/android/src/androidTest/java/com/usercentrics/reactnativemodule/RNUsercentricsModuleTest.kt
CHANGED
|
@@ -19,11 +19,11 @@ import com.usercentrics.sdk.models.common.UsercentricsLoggerLevel
|
|
|
19
19
|
import com.usercentrics.sdk.models.common.UsercentricsVariant
|
|
20
20
|
import com.usercentrics.sdk.models.settings.UsercentricsConsentType
|
|
21
21
|
import com.usercentrics.sdk.services.tcf.TCFDecisionUILayer
|
|
22
|
+
import com.usercentrics.sdk.services.tcf.interfaces.TCFData
|
|
22
23
|
import io.mockk.every
|
|
23
24
|
import io.mockk.mockk
|
|
24
25
|
import io.mockk.verify
|
|
25
26
|
import org.junit.Assert.assertEquals
|
|
26
|
-
import org.junit.Assert.assertThrows
|
|
27
27
|
import org.junit.Before
|
|
28
28
|
import org.junit.Test
|
|
29
29
|
import org.junit.runner.RunWith
|
|
@@ -48,7 +48,7 @@ class RNUsercentricsModuleTest {
|
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
private val usercentricsReadyStatus = UsercentricsReadyStatus(
|
|
51
|
-
|
|
51
|
+
shouldCollectConsent = false,
|
|
52
52
|
consents = listOf(
|
|
53
53
|
UsercentricsServiceConsent(
|
|
54
54
|
templateId = "ocv9HNX_g",
|
|
@@ -61,37 +61,6 @@ class RNUsercentricsModuleTest {
|
|
|
61
61
|
)
|
|
62
62
|
)
|
|
63
63
|
)
|
|
64
|
-
|
|
65
|
-
private val usercentricsUIOptions = JavaOnlyMap().apply {
|
|
66
|
-
putBoolean("showCloseButton", false)
|
|
67
|
-
putMap("customLogo", JavaOnlyMap().apply {
|
|
68
|
-
putString("logoName", "logo.png")
|
|
69
|
-
putString(
|
|
70
|
-
"logoPath",
|
|
71
|
-
"http://10.0.2.2:8081/assets/assets/images/logo.png"
|
|
72
|
-
)
|
|
73
|
-
})
|
|
74
|
-
putMap("customFont", JavaOnlyMap().apply {
|
|
75
|
-
putString("fontName", "Lora")
|
|
76
|
-
putInt("fontSize", 14)
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private val usercentricsConsentUserResponse = UsercentricsConsentUserResponse(
|
|
81
|
-
consents = listOf(
|
|
82
|
-
UsercentricsServiceConsent(
|
|
83
|
-
templateId = "ocv9HNX_g",
|
|
84
|
-
status = false,
|
|
85
|
-
dataProcessor = "Facebook SDK",
|
|
86
|
-
type = UsercentricsConsentType.EXPLICIT,
|
|
87
|
-
version = "1.0.1",
|
|
88
|
-
isEssential = false,
|
|
89
|
-
history = usercentricsConsentHistoryEntries
|
|
90
|
-
)
|
|
91
|
-
),
|
|
92
|
-
controllerId = "8620135313b043696b806868b20da905886a3a2598ddddc2b52973f9807d6b45",
|
|
93
|
-
userInteraction = UsercentricsUserInteraction.ACCEPT_ALL
|
|
94
|
-
)
|
|
95
64
|
}
|
|
96
65
|
|
|
97
66
|
@Before
|
|
@@ -151,7 +120,7 @@ class RNUsercentricsModuleTest {
|
|
|
151
120
|
val consent = result.getArray("consents")?.getMap(0)!!
|
|
152
121
|
|
|
153
122
|
assertEquals(1, usercentricsProxy.isReadyCount)
|
|
154
|
-
assertEquals(false, result.getBoolean("
|
|
123
|
+
assertEquals(false, result.getBoolean("shouldCollectConsent"))
|
|
155
124
|
assertEquals(false, consent.getBoolean("status"))
|
|
156
125
|
assertEquals("ocv9HNX_g", consent.getString("templateId"))
|
|
157
126
|
assertEquals("Facebook SDK", consent.getString("dataProcessor"))
|
|
@@ -194,7 +163,7 @@ class RNUsercentricsModuleTest {
|
|
|
194
163
|
val result = promise.resolveValue as WritableMap
|
|
195
164
|
val consent = result.getArray("consents")?.getMap(0)!!
|
|
196
165
|
|
|
197
|
-
assertEquals(false, result.getBoolean("
|
|
166
|
+
assertEquals(false, result.getBoolean("shouldCollectConsent"))
|
|
198
167
|
assertEquals(false, consent.getBoolean("status"))
|
|
199
168
|
assertEquals("ocv9HNX_g", consent.getString("templateId"))
|
|
200
169
|
assertEquals("Facebook SDK", consent.getString("dataProcessor"))
|
|
@@ -239,7 +208,9 @@ class RNUsercentricsModuleTest {
|
|
|
239
208
|
@Test
|
|
240
209
|
fun testGetTCString() {
|
|
241
210
|
val usercentricsSDK = mockk<UsercentricsSDK>()
|
|
242
|
-
every { usercentricsSDK.getTCString() }.
|
|
211
|
+
every { usercentricsSDK.getTCString(any()) }.answers {
|
|
212
|
+
firstArg<(String) -> Unit>().invoke("abc")
|
|
213
|
+
}
|
|
243
214
|
val usercentricsProxy = FakeUsercentricsProxy(usercentricsSDK)
|
|
244
215
|
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
245
216
|
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
|
|
@@ -247,87 +218,10 @@ class RNUsercentricsModuleTest {
|
|
|
247
218
|
|
|
248
219
|
module.getTCFString(promise)
|
|
249
220
|
|
|
250
|
-
verify(exactly = 1) { usercentricsSDK.getTCString() }
|
|
221
|
+
verify(exactly = 1) { usercentricsSDK.getTCString(any()) }
|
|
251
222
|
assertEquals("abc", promise.resolveValue)
|
|
252
223
|
}
|
|
253
224
|
|
|
254
|
-
@Test
|
|
255
|
-
fun testShowCMP() {
|
|
256
|
-
val usercentricsProxy = FakeUsercentricsProxy()
|
|
257
|
-
usercentricsProxy.createIntentValue = mockk(relaxed = true)
|
|
258
|
-
|
|
259
|
-
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
260
|
-
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
|
|
261
|
-
val promise = FakePromise()
|
|
262
|
-
|
|
263
|
-
module.showCMP(usercentricsUIOptions, promise)
|
|
264
|
-
|
|
265
|
-
val responseUsercentricsOptions = usercentricsProxy.usercentricsOptions!!
|
|
266
|
-
val customLogoURL =
|
|
267
|
-
(responseUsercentricsOptions.customLogo as UsercentricsImage.ImageUrl).imageUrl
|
|
268
|
-
|
|
269
|
-
assertEquals(false, responseUsercentricsOptions.showCloseButton)
|
|
270
|
-
assertEquals(
|
|
271
|
-
"http://10.0.2.2:8081/assets/assets/images/logo.png",
|
|
272
|
-
customLogoURL
|
|
273
|
-
)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
@Test
|
|
277
|
-
fun testOnActivityResultWithOtherCode() {
|
|
278
|
-
val usercentricsProxy = FakeUsercentricsProxy()
|
|
279
|
-
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
280
|
-
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
|
|
281
|
-
|
|
282
|
-
val otherRequestCode = 123
|
|
283
|
-
val consumed = module.parseActivityResult(otherRequestCode, 123, null)
|
|
284
|
-
|
|
285
|
-
assertEquals(false, consumed)
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
@Test
|
|
289
|
-
fun testOnActivityResultWithNoPendingResult() {
|
|
290
|
-
val usercentricsProxy = FakeUsercentricsProxy()
|
|
291
|
-
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
292
|
-
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
|
|
293
|
-
|
|
294
|
-
assertThrows(AssertionError::class.java) {
|
|
295
|
-
module.parseActivityResult(81420, 123, null)
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
@Test
|
|
300
|
-
fun testOnActivityResultWithPendingResult() {
|
|
301
|
-
val resultCode = 123
|
|
302
|
-
val usercentricsProxy = FakeUsercentricsProxy()
|
|
303
|
-
usercentricsProxy.createIntentValue = mockk(relaxed = true)
|
|
304
|
-
usercentricsProxy.parseResultValue = usercentricsConsentUserResponse
|
|
305
|
-
|
|
306
|
-
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
307
|
-
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
|
|
308
|
-
|
|
309
|
-
val promise = FakePromise()
|
|
310
|
-
module.showCMP(usercentricsUIOptions, promise)
|
|
311
|
-
|
|
312
|
-
module.parseActivityResult(81420, resultCode, null)
|
|
313
|
-
|
|
314
|
-
assertEquals(resultCode, usercentricsProxy.parseResultResultCodeArgument)
|
|
315
|
-
|
|
316
|
-
val result = promise.resolveValue as WritableMap
|
|
317
|
-
val consent = result.getArray("consents")?.getMap(0)!!
|
|
318
|
-
|
|
319
|
-
assertEquals(
|
|
320
|
-
"8620135313b043696b806868b20da905886a3a2598ddddc2b52973f9807d6b45",
|
|
321
|
-
result.getString("controllerId")
|
|
322
|
-
)
|
|
323
|
-
assertEquals(0, result.getInt("userInteraction"))
|
|
324
|
-
assertEquals(false, consent.getBoolean("status"))
|
|
325
|
-
assertEquals("ocv9HNX_g", consent.getString("templateId"))
|
|
326
|
-
assertEquals("Facebook SDK", consent.getString("dataProcessor"))
|
|
327
|
-
assertEquals(0, consent.getInt("type"))
|
|
328
|
-
assertEquals("1.0.1", consent.getString("version"))
|
|
329
|
-
}
|
|
330
|
-
|
|
331
225
|
@Test
|
|
332
226
|
fun testGetConsents() {
|
|
333
227
|
val usercentricsSDK = mockk<UsercentricsSDK>()
|
|
@@ -415,7 +309,9 @@ class RNUsercentricsModuleTest {
|
|
|
415
309
|
@Test
|
|
416
310
|
fun testGetTCFData() {
|
|
417
311
|
val usercentricsSDK = mockk<UsercentricsSDK>()
|
|
418
|
-
every { usercentricsSDK.getTCFData() }.
|
|
312
|
+
every { usercentricsSDK.getTCFData(any()) }.answers {
|
|
313
|
+
firstArg<(TCFData) -> Unit>().invoke(GetTCFDataMock.fake)
|
|
314
|
+
}
|
|
419
315
|
|
|
420
316
|
val usercentricsProxy = FakeUsercentricsProxy(usercentricsSDK)
|
|
421
317
|
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
@@ -426,7 +322,7 @@ class RNUsercentricsModuleTest {
|
|
|
426
322
|
|
|
427
323
|
val result = promise.resolveValue
|
|
428
324
|
|
|
429
|
-
verify(exactly = 1) { usercentricsSDK.getTCFData() }
|
|
325
|
+
verify(exactly = 1) { usercentricsSDK.getTCFData(any()) }
|
|
430
326
|
assertEquals(GetTCFDataMock.expected.toWritableMap(), result)
|
|
431
327
|
}
|
|
432
328
|
|
|
@@ -699,31 +595,4 @@ class RNUsercentricsModuleTest {
|
|
|
699
595
|
|
|
700
596
|
assertEquals(1, usercentricsProxy.resetCount)
|
|
701
597
|
}
|
|
702
|
-
|
|
703
|
-
@Test
|
|
704
|
-
fun testShowFirstLayer() {
|
|
705
|
-
val usercentricsProxy = FakeUsercentricsProxy()
|
|
706
|
-
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
|
|
707
|
-
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
|
|
708
|
-
|
|
709
|
-
val promise = FakePromise()
|
|
710
|
-
module.showFirstLayer(ShowFirstLayerMock.arguments, promise)
|
|
711
|
-
|
|
712
|
-
assertEquals(
|
|
713
|
-
FirstLayerStyleSettings(
|
|
714
|
-
title = TitleSettings(alignment = SectionAlignment.END),
|
|
715
|
-
message = MessageSettings(alignment = SectionAlignment.CENTER),
|
|
716
|
-
cornerRadius = 50
|
|
717
|
-
),
|
|
718
|
-
usercentricsProxy.showFirstLayerStyle
|
|
719
|
-
)
|
|
720
|
-
assertEquals(
|
|
721
|
-
BannerSettings(font = null, logo = null),
|
|
722
|
-
usercentricsProxy.showFirstLayerBannerSettings
|
|
723
|
-
)
|
|
724
|
-
assertEquals(
|
|
725
|
-
UsercentricsLayout.Popup(PopupPosition.CENTER),
|
|
726
|
-
usercentricsProxy.showFirstLayerLayout
|
|
727
|
-
)
|
|
728
|
-
}
|
|
729
|
-
}
|
|
598
|
+
}
|
package/android/src/androidTest/java/com/usercentrics/reactnativemodule/api/FakeUsercentricsProxy.kt
CHANGED
|
@@ -42,26 +42,6 @@ internal class FakeUsercentricsProxy(
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
var createIntentValue: Intent? = null
|
|
46
|
-
var usercentricsOptions: UsercentricsUISettings? = null
|
|
47
|
-
private set
|
|
48
|
-
|
|
49
|
-
override fun createIntent(
|
|
50
|
-
context: Context,
|
|
51
|
-
usercentricsOptions: UsercentricsUISettings
|
|
52
|
-
): Intent {
|
|
53
|
-
this.usercentricsOptions = usercentricsOptions
|
|
54
|
-
return createIntentValue!!
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
var parseResultResultCodeArgument: Int = 0
|
|
58
|
-
private set
|
|
59
|
-
var parseResultValue: UsercentricsConsentUserResponse? = null
|
|
60
|
-
override fun parseResult(resultCode: Int, data: Intent?): UsercentricsConsentUserResponse? {
|
|
61
|
-
this.parseResultResultCodeArgument = resultCode
|
|
62
|
-
return parseResultValue
|
|
63
|
-
}
|
|
64
|
-
|
|
65
45
|
var resetCount: Int = 0
|
|
66
46
|
private set
|
|
67
47
|
|
|
@@ -73,19 +53,12 @@ internal class FakeUsercentricsProxy(
|
|
|
73
53
|
var showFirstLayerBannerSettings: BannerSettings? = null
|
|
74
54
|
var showFirstLayerStyle: FirstLayerStyleSettings? = null
|
|
75
55
|
|
|
76
|
-
override fun showFirstLayer(
|
|
77
|
-
activity: Activity,
|
|
78
|
-
layout: UsercentricsLayout,
|
|
79
|
-
bannerSettings: BannerSettings?,
|
|
80
|
-
firstLayerStyleSettings: FirstLayerStyleSettings?,
|
|
81
|
-
promise: Promise
|
|
82
|
-
) {
|
|
56
|
+
override fun showFirstLayer(activity: Activity, layout: UsercentricsLayout, bannerSettings: BannerSettings?, promise: Promise) {
|
|
83
57
|
this.showFirstLayerLayout = layout
|
|
84
58
|
this.showFirstLayerBannerSettings = bannerSettings
|
|
85
|
-
this.showFirstLayerStyle =
|
|
59
|
+
this.showFirstLayerStyle = bannerSettings?.firstLayerSettings
|
|
86
60
|
}
|
|
87
61
|
|
|
88
|
-
override fun showSecondLayer() {
|
|
89
|
-
|
|
62
|
+
override fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, promise: Promise) {
|
|
90
63
|
}
|
|
91
|
-
}
|
|
64
|
+
}
|
package/android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/GetTCFDataMock.kt
CHANGED
|
@@ -95,6 +95,7 @@ internal class GetTCFDataMock {
|
|
|
95
95
|
dataSharedOutsideEU = false
|
|
96
96
|
)
|
|
97
97
|
),
|
|
98
|
+
tcString = "abc"
|
|
98
99
|
)
|
|
99
100
|
|
|
100
101
|
// From the debugger
|
|
@@ -186,6 +187,7 @@ internal class GetTCFDataMock {
|
|
|
186
187
|
"dataSharedOutsideEU" to false
|
|
187
188
|
),
|
|
188
189
|
),
|
|
190
|
+
"tcString" to "abc"
|
|
189
191
|
)
|
|
190
192
|
}
|
|
191
|
-
}
|
|
193
|
+
}
|
package/android/src/main/java/com/usercentrics/reactnativeusercentrics/RNUsercentricsModule.kt
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
package com.usercentrics.reactnativeusercentrics
|
|
2
2
|
|
|
3
|
-
import android.app.Activity
|
|
4
|
-
import android.content.Intent
|
|
5
3
|
import com.facebook.react.bridge.*
|
|
6
4
|
import com.usercentrics.reactnativeusercentrics.api.UsercentricsProxy
|
|
7
5
|
import com.usercentrics.reactnativeusercentrics.extensions.*
|
|
8
6
|
import com.usercentrics.sdk.UsercentricsBanner
|
|
9
|
-
import com.usercentrics.sdk.UsercentricsLayout
|
|
10
7
|
import com.usercentrics.sdk.models.settings.UsercentricsConsentType
|
|
11
8
|
import com.usercentrics.sdk.services.tcf.TCFDecisionUILayer
|
|
12
|
-
import java.lang.Exception
|
|
13
9
|
|
|
14
10
|
internal class RNUsercentricsModule(
|
|
15
11
|
reactContext: ReactApplicationContext,
|
|
@@ -19,26 +15,6 @@ internal class RNUsercentricsModule(
|
|
|
19
15
|
|
|
20
16
|
override fun getName() = "RNUsercentricsModule"
|
|
21
17
|
|
|
22
|
-
private var pendingPromise: Promise? = null
|
|
23
|
-
private val listener: ActivityEventListener = object : BaseActivityEventListener() {
|
|
24
|
-
override fun onActivityResult(
|
|
25
|
-
activity: Activity?,
|
|
26
|
-
requestCode: Int,
|
|
27
|
-
resultCode: Int,
|
|
28
|
-
data: Intent?
|
|
29
|
-
) {
|
|
30
|
-
parseActivityResult(requestCode, resultCode, data)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
init {
|
|
35
|
-
reactApplicationContext.addActivityEventListener(listener)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
companion object {
|
|
39
|
-
private const val showCMPRequestCode = 81420
|
|
40
|
-
}
|
|
41
|
-
|
|
42
18
|
@ReactMethod
|
|
43
19
|
fun configure(options: ReadableMap) {
|
|
44
20
|
var alreadyConfigured = false
|
|
@@ -63,68 +39,36 @@ internal class RNUsercentricsModule(
|
|
|
63
39
|
})
|
|
64
40
|
}
|
|
65
41
|
|
|
66
|
-
@ReactMethod
|
|
67
|
-
fun showCMP(options: ReadableMap, promise: Promise) {
|
|
68
|
-
val usercentricsOptions = options.usercentricsUISettingsFromMap(currentActivity!!.assets)
|
|
69
|
-
this.pendingPromise = promise
|
|
70
|
-
|
|
71
|
-
val intent = usercentricsProxy.createIntent(reactApplicationContext, usercentricsOptions)
|
|
72
|
-
currentActivity?.startActivityForResult(intent, showCMPRequestCode)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
42
|
@ReactMethod
|
|
76
43
|
fun showFirstLayer(options: ReadableMap, promise: Promise) {
|
|
77
|
-
|
|
78
|
-
|
|
44
|
+
UiThreadUtil.runOnUiThread {
|
|
45
|
+
try {
|
|
46
|
+
val assetManager = currentActivity!!.assets
|
|
79
47
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
48
|
+
val layout = options.getString("layout")!!.usercentricsLayoutFromEnumString()
|
|
49
|
+
val bannerSettings = options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
|
|
50
|
+
usercentricsProxy.showFirstLayer(currentActivity!!, layout, bannerSettings, promise)
|
|
83
51
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
bannerSettings,
|
|
88
|
-
styleSettings,
|
|
89
|
-
promise
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
} catch (e: Exception) {
|
|
93
|
-
promise.reject(e)
|
|
52
|
+
} catch (e: Exception) {
|
|
53
|
+
promise.reject(e)
|
|
54
|
+
}
|
|
94
55
|
}
|
|
95
56
|
}
|
|
96
57
|
|
|
97
58
|
@ReactMethod
|
|
98
59
|
fun showSecondLayer(options: ReadableMap, promise: Promise) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
showCloseButton
|
|
108
|
-
) {
|
|
109
|
-
promise.resolve(it?.toWritableMap())
|
|
60
|
+
UiThreadUtil.runOnUiThread {
|
|
61
|
+
try {
|
|
62
|
+
val assetManager = currentActivity!!.assets
|
|
63
|
+
|
|
64
|
+
val bannerSettings = options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
|
|
65
|
+
usercentricsProxy.showSecondLayer(currentActivity!!, bannerSettings, promise)
|
|
66
|
+
} catch (e: Exception) {
|
|
67
|
+
promise.reject(e)
|
|
110
68
|
}
|
|
111
|
-
} catch (e: Exception) {
|
|
112
|
-
promise.reject(e)
|
|
113
69
|
}
|
|
114
70
|
}
|
|
115
71
|
|
|
116
|
-
internal fun parseActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
|
|
117
|
-
if (requestCode != showCMPRequestCode) return false
|
|
118
|
-
assert(pendingPromise != null)
|
|
119
|
-
|
|
120
|
-
val response = usercentricsProxy.parseResult(resultCode, data)?.toWritableMap()
|
|
121
|
-
|
|
122
|
-
pendingPromise?.resolve(response)
|
|
123
|
-
pendingPromise = null
|
|
124
|
-
|
|
125
|
-
return true
|
|
126
|
-
}
|
|
127
|
-
|
|
128
72
|
@ReactMethod
|
|
129
73
|
fun restoreUserSession(controllerId: String, promise: Promise) {
|
|
130
74
|
usercentricsProxy.instance.restoreUserSession(controllerId, {
|
|
@@ -135,8 +79,11 @@ internal class RNUsercentricsModule(
|
|
|
135
79
|
}
|
|
136
80
|
|
|
137
81
|
@ReactMethod
|
|
82
|
+
@Deprecated("Please, call getTCFData() to get the 'tcString' from that model")
|
|
138
83
|
fun getTCFString(promise: Promise) {
|
|
139
|
-
|
|
84
|
+
usercentricsProxy.instance.getTCString {
|
|
85
|
+
promise.resolve(it)
|
|
86
|
+
}
|
|
140
87
|
}
|
|
141
88
|
|
|
142
89
|
@ReactMethod
|
|
@@ -161,7 +108,9 @@ internal class RNUsercentricsModule(
|
|
|
161
108
|
|
|
162
109
|
@ReactMethod
|
|
163
110
|
fun getTCFData(promise: Promise) {
|
|
164
|
-
|
|
111
|
+
usercentricsProxy.instance.getTCFData {
|
|
112
|
+
promise.resolve(it.serialize())
|
|
113
|
+
}
|
|
165
114
|
}
|
|
166
115
|
|
|
167
116
|
@ReactMethod
|
|
@@ -263,4 +212,4 @@ internal class RNUsercentricsModule(
|
|
|
263
212
|
fun reset() {
|
|
264
213
|
usercentricsProxy.reset()
|
|
265
214
|
}
|
|
266
|
-
}
|
|
215
|
+
}
|
package/android/src/main/java/com/usercentrics/reactnativeusercentrics/api/UsercentricsProxy.kt
CHANGED
|
@@ -2,45 +2,19 @@ package com.usercentrics.reactnativeusercentrics.api
|
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
4
|
import android.content.Context
|
|
5
|
-
import android.content.Intent
|
|
6
|
-
import android.util.Log
|
|
7
5
|
import com.facebook.react.bridge.Promise
|
|
8
|
-
import com.facebook.react.bridge.ReadableMap
|
|
9
|
-
import com.usercentrics.reactnativeusercentrics.extensions.bannerSettingsFromMap
|
|
10
|
-
import com.usercentrics.reactnativeusercentrics.extensions.firstLayerStyleSettingsFromMap
|
|
11
6
|
import com.usercentrics.reactnativeusercentrics.extensions.toWritableMap
|
|
12
|
-
import com.usercentrics.reactnativeusercentrics.extensions.usercentricsLayoutFromEnumString
|
|
13
7
|
import com.usercentrics.sdk.*
|
|
14
8
|
import com.usercentrics.sdk.errors.UsercentricsError
|
|
15
|
-
import java.lang.Exception
|
|
16
9
|
|
|
17
10
|
interface UsercentricsProxy {
|
|
11
|
+
|
|
18
12
|
val instance: UsercentricsSDK
|
|
19
13
|
|
|
20
14
|
fun initialize(context: Context, options: UsercentricsOptions)
|
|
21
|
-
|
|
22
|
-
fun
|
|
23
|
-
|
|
24
|
-
onFailure: (UsercentricsError) -> Unit
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
fun createIntent(
|
|
28
|
-
context: Context,
|
|
29
|
-
usercentricsOptions: UsercentricsUISettings
|
|
30
|
-
): Intent
|
|
31
|
-
|
|
32
|
-
fun parseResult(resultCode: Int, data: Intent?): UsercentricsConsentUserResponse?
|
|
33
|
-
|
|
34
|
-
fun showFirstLayer(
|
|
35
|
-
activity: Activity,
|
|
36
|
-
layout: UsercentricsLayout,
|
|
37
|
-
bannerSettings: BannerSettings?,
|
|
38
|
-
firstLayerStyleSettings: FirstLayerStyleSettings?,
|
|
39
|
-
promise: Promise
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
fun showSecondLayer()
|
|
43
|
-
|
|
15
|
+
fun isReady(onSuccess: (UsercentricsReadyStatus) -> Unit, onFailure: (UsercentricsError) -> Unit)
|
|
16
|
+
fun showFirstLayer(activity: Activity, layout: UsercentricsLayout, bannerSettings: BannerSettings?, promise: Promise)
|
|
17
|
+
fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, promise: Promise)
|
|
44
18
|
fun reset()
|
|
45
19
|
}
|
|
46
20
|
|
|
@@ -57,45 +31,19 @@ internal class UsercentricsProxyImpl : UsercentricsProxy {
|
|
|
57
31
|
}
|
|
58
32
|
}
|
|
59
33
|
|
|
60
|
-
override fun isReady(
|
|
61
|
-
onSuccess: (UsercentricsReadyStatus) -> Unit,
|
|
62
|
-
onFailure: (UsercentricsError) -> Unit
|
|
63
|
-
) = Usercentrics.isReady(onSuccess, onFailure)
|
|
64
|
-
|
|
65
|
-
override fun createIntent(
|
|
66
|
-
context: Context,
|
|
67
|
-
usercentricsOptions: UsercentricsUISettings
|
|
68
|
-
): Intent {
|
|
69
|
-
return UsercentricsActivityContract().createIntent(
|
|
70
|
-
context,
|
|
71
|
-
usercentricsOptions
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
override fun parseResult(resultCode: Int, data: Intent?): UsercentricsConsentUserResponse? {
|
|
76
|
-
return UsercentricsActivityContract()
|
|
77
|
-
.parseResult(resultCode, data)
|
|
78
|
-
}
|
|
34
|
+
override fun isReady(onSuccess: (UsercentricsReadyStatus) -> Unit, onFailure: (UsercentricsError) -> Unit) = Usercentrics.isReady(onSuccess, onFailure)
|
|
79
35
|
|
|
80
|
-
override fun showFirstLayer(
|
|
81
|
-
activity
|
|
82
|
-
layout: UsercentricsLayout,
|
|
83
|
-
bannerSettings: BannerSettings?,
|
|
84
|
-
firstLayerStyleSettings: FirstLayerStyleSettings?,
|
|
85
|
-
promise: Promise
|
|
86
|
-
) {
|
|
87
|
-
UsercentricsBanner(activity, bannerSettings).showFirstLayer(
|
|
88
|
-
layout,
|
|
89
|
-
firstLayerStyleSettings
|
|
90
|
-
) {
|
|
36
|
+
override fun showFirstLayer(activity: Activity, layout: UsercentricsLayout, bannerSettings: BannerSettings?, promise: Promise) {
|
|
37
|
+
UsercentricsBanner(activity, bannerSettings).showFirstLayer(layout) {
|
|
91
38
|
promise.resolve(it?.toWritableMap())
|
|
92
39
|
}
|
|
93
40
|
}
|
|
94
41
|
|
|
95
|
-
override fun showSecondLayer() {
|
|
96
|
-
|
|
42
|
+
override fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, promise: Promise) {
|
|
43
|
+
UsercentricsBanner(activity, bannerSettings).showSecondLayer {
|
|
44
|
+
promise.resolve(it?.toWritableMap())
|
|
45
|
+
}
|
|
97
46
|
}
|
|
98
47
|
|
|
99
48
|
override fun reset() = Usercentrics.reset()
|
|
100
|
-
|
|
101
|
-
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.usercentrics.reactnativeusercentrics.extensions
|
|
2
|
+
|
|
3
|
+
import android.content.res.AssetManager
|
|
4
|
+
import android.graphics.Typeface
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.usercentrics.sdk.BannerFont
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
internal fun ReadableMap.bannerFontFromMap(assetManager: AssetManager): BannerFont? {
|
|
10
|
+
val size = getDoubleOrNull("fontSize") ?: return null
|
|
11
|
+
val regularTypeface = assetManager.createFontFromName(getString("regularFont")) ?: return null
|
|
12
|
+
val boldTypeface = assetManager.createFontFromName(getString("boldFont")) ?: return null
|
|
13
|
+
|
|
14
|
+
return BannerFont(
|
|
15
|
+
regularTypeface,
|
|
16
|
+
boldTypeface,
|
|
17
|
+
size.toFloat()
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
internal fun AssetManager.createFontFromName(fontName: String?): Typeface? {
|
|
22
|
+
if (fontName == null) { return null }
|
|
23
|
+
val fontsFolder = this.list("fonts")
|
|
24
|
+
val regularFontName = fontsFolder?.firstOrNull { it.startsWith(fontName) } ?: return null
|
|
25
|
+
return Typeface.createFromAsset(this, "fonts/$regularFontName")
|
|
26
|
+
}
|