Skip to content

Commit 6896175

Browse files
uc-leoleocabral
authored andcommitted
Release 2.4.0 (#35)
Release 2.4.0
1 parent e2fcea7 commit 6896175

25 files changed

+443
-345
lines changed

CHANGELOG.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
[Release Notes](https://docs.usercentrics.com/cmp_in_app_sdk/latest/about/history/)
22

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+
319
# 2.3.0
420

521
## Features
@@ -55,4 +71,4 @@
5571

5672
# 2.0.1
5773

58-
- Initial version of the library.
74+
- Initial version of the library.

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
def usercentrics_version = "2.3.0"
1+
def usercentrics_version = "2.4.0"
22
version usercentrics_version
33

44
buildscript {

android/src/androidTest/java/com/usercentrics/reactnativemodule/RNUsercentricsModuleTest.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.usercentrics.sdk.models.common.UsercentricsLoggerLevel
1919
import com.usercentrics.sdk.models.common.UsercentricsVariant
2020
import com.usercentrics.sdk.models.settings.UsercentricsConsentType
2121
import com.usercentrics.sdk.services.tcf.TCFDecisionUILayer
22+
import com.usercentrics.sdk.services.tcf.interfaces.TCFData
2223
import io.mockk.every
2324
import io.mockk.mockk
2425
import io.mockk.verify
@@ -207,15 +208,17 @@ class RNUsercentricsModuleTest {
207208
@Test
208209
fun testGetTCString() {
209210
val usercentricsSDK = mockk<UsercentricsSDK>()
210-
every { usercentricsSDK.getTCString() }.returns("abc")
211+
every { usercentricsSDK.getTCString(any()) }.answers {
212+
firstArg<(String) -> Unit>().invoke("abc")
213+
}
211214
val usercentricsProxy = FakeUsercentricsProxy(usercentricsSDK)
212215
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
213216
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
214217
val promise = FakePromise()
215218

216219
module.getTCFString(promise)
217220

218-
verify(exactly = 1) { usercentricsSDK.getTCString() }
221+
verify(exactly = 1) { usercentricsSDK.getTCString(any()) }
219222
assertEquals("abc", promise.resolveValue)
220223
}
221224

@@ -306,7 +309,9 @@ class RNUsercentricsModuleTest {
306309
@Test
307310
fun testGetTCFData() {
308311
val usercentricsSDK = mockk<UsercentricsSDK>()
309-
every { usercentricsSDK.getTCFData() }.returns(GetTCFDataMock.fake)
312+
every { usercentricsSDK.getTCFData(any()) }.answers {
313+
firstArg<(TCFData) -> Unit>().invoke(GetTCFDataMock.fake)
314+
}
310315

311316
val usercentricsProxy = FakeUsercentricsProxy(usercentricsSDK)
312317
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
@@ -317,7 +322,7 @@ class RNUsercentricsModuleTest {
317322

318323
val result = promise.resolveValue
319324

320-
verify(exactly = 1) { usercentricsSDK.getTCFData() }
325+
verify(exactly = 1) { usercentricsSDK.getTCFData(any()) }
321326
assertEquals(GetTCFDataMock.expected.toWritableMap(), result)
322327
}
323328

@@ -563,7 +568,6 @@ class RNUsercentricsModuleTest {
563568
GetConsentsMock.fakeWithData
564569
)
565570

566-
567571
val usercentricsProxy = FakeUsercentricsProxy(usercentricsSDK)
568572
val contextMock = mockk<ReactApplicationContext>(relaxed = true)
569573
val module = RNUsercentricsModule(contextMock, usercentricsProxy)
@@ -590,4 +594,4 @@ class RNUsercentricsModuleTest {
590594

591595
assertEquals(1, usercentricsProxy.resetCount)
592596
}
593-
}
597+
}

android/src/androidTest/java/com/usercentrics/reactnativemodule/api/FakeUsercentricsProxy.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,12 @@ internal class FakeUsercentricsProxy(
5353
var showFirstLayerBannerSettings: BannerSettings? = null
5454
var showFirstLayerStyle: FirstLayerStyleSettings? = null
5555

56-
override fun showFirstLayer(
57-
activity: Activity,
58-
layout: UsercentricsLayout,
59-
bannerSettings: BannerSettings?,
60-
firstLayerStyleSettings: FirstLayerStyleSettings?,
61-
promise: Promise
62-
) {
56+
override fun showFirstLayer(activity: Activity, layout: UsercentricsLayout, bannerSettings: BannerSettings?, promise: Promise) {
6357
this.showFirstLayerLayout = layout
6458
this.showFirstLayerBannerSettings = bannerSettings
65-
this.showFirstLayerStyle = firstLayerStyleSettings
59+
this.showFirstLayerStyle = bannerSettings?.firstLayerSettings
6660
}
6761

68-
override fun showSecondLayer() {
69-
62+
override fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, promise: Promise) {
7063
}
71-
}
64+
}

android/src/androidTest/java/com/usercentrics/reactnativemodule/mock/GetTCFDataMock.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ internal class GetTCFDataMock {
9595
dataSharedOutsideEU = false
9696
)
9797
),
98+
tcString = "abc"
9899
)
99100

100101
// From the debugger
@@ -186,6 +187,7 @@ internal class GetTCFDataMock {
186187
"dataSharedOutsideEU" to false
187188
),
188189
),
190+
"tcString" to "abc"
189191
)
190192
}
191-
}
193+
}

android/src/main/java/com/usercentrics/reactnativeusercentrics/RNUsercentricsModule.kt

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,8 @@ internal class RNUsercentricsModule(
1717

1818
@ReactMethod
1919
fun configure(options: ReadableMap) {
20-
var alreadyConfigured = false
21-
usercentricsProxy.isReady({
22-
alreadyConfigured = true
23-
}, {
24-
alreadyConfigured = true
25-
})
26-
27-
if (!alreadyConfigured) {
28-
val usercentricsOptions = options.usercentricsOptionsFromMap() ?: return
29-
usercentricsProxy.initialize(reactApplicationContext, usercentricsOptions)
30-
}
20+
val usercentricsOptions = options.usercentricsOptionsFromMap() ?: return
21+
usercentricsProxy.initialize(reactApplicationContext, usercentricsOptions)
3122
}
3223

3324
@ReactMethod
@@ -46,18 +37,8 @@ internal class RNUsercentricsModule(
4637
val assetManager = currentActivity!!.assets
4738

4839
val layout = options.getString("layout")!!.usercentricsLayoutFromEnumString()
49-
val bannerSettings =
50-
options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
51-
val styleSettings =
52-
options.getMap("styleSettings")?.firstLayerStyleSettingsFromMap(assetManager)
53-
54-
usercentricsProxy.showFirstLayer(
55-
currentActivity!!,
56-
layout,
57-
bannerSettings,
58-
styleSettings,
59-
promise
60-
)
40+
val bannerSettings = options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
41+
usercentricsProxy.showFirstLayer(currentActivity!!, layout, bannerSettings, promise)
6142

6243
} catch (e: Exception) {
6344
promise.reject(e)
@@ -71,17 +52,8 @@ internal class RNUsercentricsModule(
7152
try {
7253
val assetManager = currentActivity!!.assets
7354

74-
val bannerSettings =
75-
options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
76-
val showCloseButton = options.getBoolean("showCloseButton")
77-
78-
79-
UsercentricsBanner(currentActivity!!, bannerSettings).showSecondLayer(
80-
showCloseButton
81-
) {
82-
promise.resolve(it?.toWritableMap())
83-
}
84-
55+
val bannerSettings = options.getMap("bannerSettings")?.bannerSettingsFromMap(assetManager)
56+
usercentricsProxy.showSecondLayer(currentActivity!!, bannerSettings, promise)
8557
} catch (e: Exception) {
8658
promise.reject(e)
8759
}
@@ -98,8 +70,11 @@ internal class RNUsercentricsModule(
9870
}
9971

10072
@ReactMethod
73+
@Deprecated("Please, call getTCFData() to get the 'tcString' from that model")
10174
fun getTCFString(promise: Promise) {
102-
promise.resolve(usercentricsProxy.instance.getTCString())
75+
usercentricsProxy.instance.getTCString {
76+
promise.resolve(it)
77+
}
10378
}
10479

10580
@ReactMethod
@@ -124,7 +99,9 @@ internal class RNUsercentricsModule(
12499

125100
@ReactMethod
126101
fun getTCFData(promise: Promise) {
127-
promise.resolve(usercentricsProxy.instance.getTCFData().serialize())
102+
usercentricsProxy.instance.getTCFData {
103+
promise.resolve(it.serialize())
104+
}
128105
}
129106

130107
@ReactMethod
@@ -226,4 +203,4 @@ internal class RNUsercentricsModule(
226203
fun reset() {
227204
usercentricsProxy.reset()
228205
}
229-
}
206+
}

android/src/main/java/com/usercentrics/reactnativeusercentrics/api/UsercentricsProxy.kt

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,19 @@ package com.usercentrics.reactnativeusercentrics.api
22

33
import android.app.Activity
44
import android.content.Context
5-
import android.content.Intent
6-
import android.util.Log
75
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
116
import com.usercentrics.reactnativeusercentrics.extensions.toWritableMap
12-
import com.usercentrics.reactnativeusercentrics.extensions.usercentricsLayoutFromEnumString
137
import com.usercentrics.sdk.*
148
import com.usercentrics.sdk.errors.UsercentricsError
15-
import java.lang.Exception
169

1710
interface UsercentricsProxy {
11+
1812
val instance: UsercentricsSDK
1913

2014
fun initialize(context: Context, options: UsercentricsOptions)
21-
22-
fun isReady(
23-
onSuccess: (UsercentricsReadyStatus) -> Unit,
24-
onFailure: (UsercentricsError) -> Unit
25-
)
26-
27-
fun showFirstLayer(
28-
activity: Activity,
29-
layout: UsercentricsLayout,
30-
bannerSettings: BannerSettings?,
31-
firstLayerStyleSettings: FirstLayerStyleSettings?,
32-
promise: Promise
33-
)
34-
35-
fun showSecondLayer()
36-
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)
3718
fun reset()
3819
}
3920

@@ -50,30 +31,19 @@ internal class UsercentricsProxyImpl : UsercentricsProxy {
5031
}
5132
}
5233

53-
override fun isReady(
54-
onSuccess: (UsercentricsReadyStatus) -> Unit,
55-
onFailure: (UsercentricsError) -> Unit
56-
) = Usercentrics.isReady(onSuccess, onFailure)
34+
override fun isReady(onSuccess: (UsercentricsReadyStatus) -> Unit, onFailure: (UsercentricsError) -> Unit) = Usercentrics.isReady(onSuccess, onFailure)
5735

58-
override fun showFirstLayer(
59-
activity: Activity,
60-
layout: UsercentricsLayout,
61-
bannerSettings: BannerSettings?,
62-
firstLayerStyleSettings: FirstLayerStyleSettings?,
63-
promise: Promise
64-
) {
65-
UsercentricsBanner(activity, bannerSettings).showFirstLayer(
66-
layout,
67-
firstLayerStyleSettings
68-
) {
36+
override fun showFirstLayer(activity: Activity, layout: UsercentricsLayout, bannerSettings: BannerSettings?, promise: Promise) {
37+
UsercentricsBanner(activity, bannerSettings).showFirstLayer(layout) {
6938
promise.resolve(it?.toWritableMap())
7039
}
7140
}
7241

73-
override fun showSecondLayer() {
74-
42+
override fun showSecondLayer(activity: Activity, bannerSettings: BannerSettings?, promise: Promise) {
43+
UsercentricsBanner(activity, bannerSettings).showSecondLayer {
44+
promise.resolve(it?.toWritableMap())
45+
}
7546
}
7647

7748
override fun reset() = Usercentrics.reset()
78-
79-
}
49+
}

android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/FirstLayerOptionsExtensions.kt

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,16 @@ internal fun ReadableMap.bannerSettingsFromMap(assetManager: AssetManager): Bann
2020
val customFont = getMap("font")
2121
val customLogo = getMap("logo")
2222

23+
val rawFirstLayerStyleSettings = getMap("firstLayerSettings")
24+
val rawSecondLayerStyleSettings = getMap("secondLayerSettings")
25+
val rawLegalLinkSettings = getString("links")
26+
2327
return BannerSettings(
24-
customFont?.bannerFontFromMap(assetManager),
25-
customLogo?.bannerLogoFromMap()
28+
font = customFont?.bannerFontFromMap(assetManager),
29+
logo = customLogo?.bannerLogoFromMap(),
30+
firstLayerSettings = rawFirstLayerStyleSettings?.firstLayerStyleSettingsFromMap(assetManager),
31+
secondLayerSettings = rawSecondLayerStyleSettings?.secondLayerStyleSettingsFromMap(assetManager),
32+
links = rawLegalLinkSettings?.legalLinksFromEnumString()
2633
)
2734
}
2835

@@ -146,6 +153,23 @@ internal fun String.deserializeButtonType(): ButtonType {
146153
return ButtonType.valueOf(this)
147154
}
148155

156+
internal fun ReadableMap.secondLayerStyleSettingsFromMap(assetManager: AssetManager): SecondLayerStyleSettings {
157+
return SecondLayerStyleSettings(
158+
buttonLayout = getMap("buttonLayout")?.buttonLayoutFromMap(assetManager),
159+
showCloseButton = getBoolean("showCloseButton"),
160+
)
161+
}
162+
163+
internal fun String?.legalLinksFromEnumString(): LegalLinksSettings? {
164+
return when (this) {
165+
"BOTH" -> LegalLinksSettings.BOTH
166+
"NONE" -> LegalLinksSettings.NONE
167+
"FIRST_LAYER_ONLY" -> LegalLinksSettings.FIRST_LAYER_ONLY
168+
"SECOND_LAYER_ONLY" -> LegalLinksSettings.SECOND_LAYER_ONLY
169+
else -> null
170+
}
171+
}
172+
149173
@ColorInt
150174
internal fun String.deserializeColor(): Int? {
151175
val colorString: String =

android/src/main/java/com/usercentrics/reactnativeusercentrics/extensions/TCFDataExtensions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ internal fun TCFData.serialize(): WritableMap {
1010
"specialFeatures" to specialFeatures.map { it.serialize() },
1111
"specialPurposes" to specialPurposes.map { it.serialize() },
1212
"stacks" to stacks.map { it.serialize() },
13-
"vendors" to vendors.map { it.serialize() }
13+
"vendors" to vendors.map { it.serialize() },
14+
"tcString" to tcString
1415
).toWritableMap()
1516
}
1617

0 commit comments

Comments
 (0)