Skip to content

Commit cc85f61

Browse files
feat: Implement Jetpack compose (#53)
1 parent b5df02b commit cc85f61

File tree

3 files changed

+105
-11
lines changed

3 files changed

+105
-11
lines changed

build.gradle

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ buildscript {
1919
plugins {
2020
id "org.sonarqube" version "3.5.0.2730"
2121
id "org.jlleitschuh.gradle.ktlint" version "13.0.0"
22+
id "org.jetbrains.kotlin.plugin.compose" version "2.0.0"
2223
}
2324

2425
sonarqube {
@@ -29,7 +30,7 @@ sonarqube {
2930
}
3031
}
3132

32-
apply plugin: 'org.jlleitschuh.gradle.ktlint'
33+
3334
apply plugin: "kotlin-android"
3435
apply plugin: 'com.mparticle.kit'
3536

@@ -48,6 +49,9 @@ android {
4849
jvmArgs += ['--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED']
4950
}
5051
}
52+
buildFeatures {
53+
compose true
54+
}
5155
}
5256

5357
repositories {
@@ -58,12 +62,16 @@ repositories {
5862
dependencies {
5963
implementation 'androidx.annotation:annotation:1.5.0'
6064
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
65+
implementation 'androidx.compose.runtime:runtime-android:1.8.3'
6166
api 'com.rokt:roktsdk:4.11.0'
6267

6368
testImplementation files('libs/java-json.jar')
6469
testImplementation 'com.squareup.assertj:assertj-android:1.2.0'
6570
testImplementation ("io.mockk:mockk:1.13.4")
6671
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4'
72+
compileOnly 'androidx.compose.ui:ui:1.0.0'
73+
compileOnly 'androidx.compose.material:material:1.0.0'
74+
compileOnly 'androidx.compose.ui:ui-tooling:1.0.0'
6775
}
6876

6977
ktlint {

src/main/kotlin/com/mparticle/kits/RoktKit.kt

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@ import com.mparticle.rokt.RoktConfig
2323
import com.mparticle.rokt.RoktEmbeddedView
2424
import com.rokt.roktsdk.CacheConfig
2525
import com.rokt.roktsdk.Rokt
26+
import com.rokt.roktsdk.Rokt.RoktCallback
2627
import com.rokt.roktsdk.Rokt.SdkFrameworkType.Android
2728
import com.rokt.roktsdk.Rokt.SdkFrameworkType.Cordova
2829
import com.rokt.roktsdk.Rokt.SdkFrameworkType.Flutter
2930
import com.rokt.roktsdk.Rokt.SdkFrameworkType.ReactNative
3031
import com.rokt.roktsdk.RoktEvent
3132
import com.rokt.roktsdk.RoktWidgetDimensionCallBack
3233
import com.rokt.roktsdk.Widget
34+
import kotlinx.coroutines.CompletableDeferred
35+
import kotlinx.coroutines.CoroutineScope
36+
import kotlinx.coroutines.Dispatchers
3337
import kotlinx.coroutines.flow.Flow
3438
import kotlinx.coroutines.flow.map
39+
import kotlinx.coroutines.launch
3540
import java.lang.ref.WeakReference
3641
import java.math.BigDecimal
3742

@@ -56,7 +61,10 @@ class RoktKit :
5661

5762
override fun getInstance(): RoktKit = this
5863

64+
private var deferredAttributes: CompletableDeferred<Map<String, String>>? = null
65+
5966
public override fun onKitCreate(settings: Map<String, String>, ctx: Context): List<ReportingMessage> {
67+
register(this)
6068
applicationContext = ctx.applicationContext
6169
val roktTagId = settings[ROKT_ACCOUNT_ID]
6270
if (KitUtils.isEmpty(roktTagId)) {
@@ -186,6 +194,23 @@ class RoktKit :
186194
}?.toMap()
187195

188196
this.mpRoktEventCallback = mpRoktEventCallback
197+
val finalAttributes = prepareFinalAttributes(filterUser, attributes)
198+
val roktConfig = mpRoktConfig?.let { mapToRoktConfig(it) }
199+
Rokt.execute(
200+
viewName,
201+
finalAttributes,
202+
this,
203+
// Pass placeholders and fontTypefaces only if they are not empty or null
204+
placeholders.takeIf { it?.isNotEmpty() == true },
205+
fontTypefaces.takeIf { it?.isNotEmpty() == true },
206+
roktConfig,
207+
)
208+
}
209+
210+
private fun prepareFinalAttributes(
211+
filterUser: FilteredMParticleUser?,
212+
attributes: Map<String, String>,
213+
): Map<String, String> {
189214
val finalAttributes = mutableMapOf<String, String>()
190215
filterUser?.userAttributes?.let { userAttrs ->
191216
for ((key, value) in userAttrs) {
@@ -203,16 +228,7 @@ class RoktKit :
203228
finalAttributes.put(ROKT_ATTRIBUTE_SANDBOX_MODE, value)
204229
}
205230
verifyHashedEmail(finalAttributes)
206-
val roktConfig = mpRoktConfig?.let { mapToRoktConfig(it) }
207-
Rokt.execute(
208-
viewName,
209-
finalAttributes,
210-
this,
211-
// Pass placeholders and fontTypefaces only if they are not empty or null
212-
placeholders.takeIf { it?.isNotEmpty() == true },
213-
fontTypefaces.takeIf { it?.isNotEmpty() == true },
214-
roktConfig,
215-
)
231+
return finalAttributes
216232
}
217233

218234
override fun events(identifier: String): Flow<com.mparticle.RoktEvent> = Rokt.events(identifier).map { event ->
@@ -274,6 +290,26 @@ class RoktKit :
274290
Rokt.close()
275291
}
276292

293+
override fun enrichAttributes(attributes: MutableMap<String, String>, user: FilteredMParticleUser?) {
294+
val finalAttributes = prepareFinalAttributes(user, attributes)
295+
deferredAttributes?.complete(finalAttributes)
296+
}
297+
298+
suspend fun runComposableWithCallback(
299+
attributes: Map<String, String>,
300+
mpRoktEventCallback: MpRoktEventCallback?,
301+
onResult: (Map<String, String>, RoktCallback) -> Unit,
302+
) {
303+
val instance = MParticle.getInstance()
304+
deferredAttributes = CompletableDeferred()
305+
instance?.Internal()?.kitManager?.prepareAttributesAsync(attributes)
306+
this.mpRoktEventCallback = mpRoktEventCallback
307+
CoroutineScope(Dispatchers.Default).launch {
308+
val resultAttributes = deferredAttributes!!.await()
309+
onResult(resultAttributes, this@RoktKit)
310+
}
311+
}
312+
277313
private fun mapToRoktConfig(config: RoktConfig): com.rokt.roktsdk.RoktConfig {
278314
val colorMode = when (config.colorMode) {
279315
RoktConfig.ColorMode.LIGHT -> com.rokt.roktsdk.RoktConfig.ColorMode.LIGHT
@@ -367,6 +403,14 @@ class RoktKit :
367403
}
368404

369405
companion object {
406+
@Volatile
407+
var instance: RoktKit? = null
408+
private set
409+
410+
fun register(kit: RoktKit) {
411+
instance = kit
412+
}
413+
370414
const val NAME = "Rokt"
371415
const val ROKT_ACCOUNT_ID = "accountId"
372416
const val MPID = "mpid"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.mparticle.kits
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.LaunchedEffect
5+
import androidx.compose.runtime.mutableStateOf
6+
import androidx.compose.runtime.remember
7+
import androidx.compose.ui.Modifier
8+
import com.mparticle.MpRoktEventCallback
9+
import com.rokt.roktsdk.Rokt
10+
11+
@Composable
12+
@Suppress("FunctionName")
13+
fun RoktLayout(
14+
sdkTriggered: Boolean,
15+
viewName: String,
16+
attributes: Map<String, String>,
17+
location: String,
18+
modifier: Modifier = Modifier,
19+
mpRoktEventCallback: MpRoktEventCallback? = null,
20+
) {
21+
val instance = RoktKit.instance
22+
val resultMapState = remember { mutableStateOf<RoktResult?>(null) }
23+
if (sdkTriggered) {
24+
LaunchedEffect(Unit) {
25+
instance?.runComposableWithCallback(attributes, mpRoktEventCallback, { resultMap, callback ->
26+
resultMapState.value = RoktResult(resultMap, callback)
27+
})
28+
}
29+
}
30+
31+
resultMapState.value?.let { resultMap ->
32+
com.rokt.roktsdk.RoktLayout(
33+
sdkTriggered, viewName, modifier, resultMap.attributes, location,
34+
onLoad = { resultMap.callback.onLoad() },
35+
onShouldShowLoadingIndicator = { resultMap.callback.onShouldShowLoadingIndicator() },
36+
onShouldHideLoadingIndicator = { resultMap.callback.onShouldHideLoadingIndicator() },
37+
onUnload = { reason -> resultMap.callback.onUnload(reason) },
38+
)
39+
}
40+
}
41+
42+
data class RoktResult(val attributes: Map<String, String>, val callback: Rokt.RoktCallback)

0 commit comments

Comments
 (0)