diff --git a/android/nativebrik/build.gradle.kts b/android/nativebrik/build.gradle.kts index 945b8d1..675eac3 100644 --- a/android/nativebrik/build.gradle.kts +++ b/android/nativebrik/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "com.nativebrik" -version = "0.0.6" +version = "0.1.0" android { namespace = "com.nativebrik.sdk" diff --git a/android/nativebrik/src/main/java/com/nativebrik/sdk/data/container.kt b/android/nativebrik/src/main/java/com/nativebrik/sdk/data/container.kt index f48c22c..97b4dea 100644 --- a/android/nativebrik/src/main/java/com/nativebrik/sdk/data/container.kt +++ b/android/nativebrik/src/main/java/com/nativebrik/sdk/data/container.kt @@ -25,6 +25,8 @@ class FailedToDecodeException: Exception("Failed to decode") class SkipHttpRequestException: Exception("Skip http request") internal interface Container { + fun initWith(arguments: Any?): Container + fun handleEvent(it: Event) {} fun createVariableForTemplate(data: JsonElement? = null, properties: List? = null): JsonElement @@ -42,6 +44,8 @@ internal class ContainerImpl( private val config: Config, private val user: NativebrikUser, private val db: SQLiteDatabase, + private val arguments: Any? = null, + private val formRepository: FormRepository? = null, private val context: Context, ): Container { private val componentRepository: ComponentRepository by lazy { @@ -56,13 +60,22 @@ internal class ContainerImpl( private val httpRequestRepository: HttpRequestRepository by lazy { HttpRequestRepositoryImpl() } - private val formRepository: FormRepository by lazy { - FormRepositoryImpl() - } private val databaseRepository: DatabaseRepository by lazy { DatabaseRepositoryImpl(db) } + override fun initWith(arguments: Any?): Container { + return ContainerImpl( + config = this.config, + user = this.user, + db = this.db, + arguments = arguments, + formRepository = FormRepositoryImpl(), + context = this.context, + ) + } + + override fun handleEvent(it: Event) { this.config.onEvent?.let { it1 -> it1(it) } } @@ -72,17 +85,18 @@ internal class ContainerImpl( user = this.user, data = data, properties = properties, - form = formRepository.getFormData(), + form = formRepository?.getFormData(), + arguments = arguments, projectId = config.projectId, ) } override fun getFormValue(key: String): FormValue? { - return this.formRepository.getValue(key) + return this.formRepository?.getValue(key) } override fun setFormValue(key: String, value: FormValue) { - this.formRepository.setValue(key, value) + this.formRepository?.setValue(key, value) } override suspend fun sendHttpRequest(req: ApiHttpRequest, variable: JsonElement?): Result { diff --git a/android/nativebrik/src/main/java/com/nativebrik/sdk/data/variable.kt b/android/nativebrik/src/main/java/com/nativebrik/sdk/data/variable.kt index 15eec2f..7244913 100644 --- a/android/nativebrik/src/main/java/com/nativebrik/sdk/data/variable.kt +++ b/android/nativebrik/src/main/java/com/nativebrik/sdk/data/variable.kt @@ -2,17 +2,18 @@ package com.nativebrik.sdk.data import com.nativebrik.sdk.data.user.NativebrikUser import com.nativebrik.sdk.schema.Property -import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.jsonObject internal fun createVariableForTemplate( user: NativebrikUser? = null, data: JsonElement? = null, properties: List? = null, form: Map? = null, + arguments: Any? = null, projectId: String? = null, ): JsonElement { val userJsonObject = JsonObject(mapOf("id" to JsonPrimitive(user?.id ?: ""))) @@ -24,32 +25,42 @@ internal fun createVariableForTemplate( "user" to userJsonObject, "props" to propertiesJsonObject, "form" to formJsonObject, - "data" to (data ?: JsonPrimitive(null)), + "args" to buildJsonElement(arguments), + "data" to (data ?: JsonNull), "project" to JsonObject(mapOf( "id" to JsonPrimitive(projectId), )) )) } -@OptIn(ExperimentalSerializationApi::class) -internal fun mergeVariableForTemplate( - a: JsonElement, - b: JsonElement -): JsonElement { - if (a !is JsonObject && b !is JsonObject) { - return JsonObject(emptyMap()) - } - if (a !is JsonObject) { - return b - } - if (b !is JsonObject) { - return a +internal fun buildJsonElement(value: Any?): JsonElement { + if (value == null) return JsonNull + when (value) { + is Map<*, *> -> { + return JsonObject(value.map { + it.key.toString() to buildJsonElement(it.value) + }.toMap()) + } + is List<*> -> { + return JsonArray(value.map { buildJsonElement(it) }) + } + is Array<*> -> { + return JsonArray(value.map { buildJsonElement(it) }) + } + is Int -> { + return JsonPrimitive(value) + } + is Float -> { + return JsonPrimitive(value) + } + is Double -> { + return JsonPrimitive(value) + } + is String -> { + return JsonPrimitive(value) + } + else -> { + return JsonPrimitive(value.toString()) + } } - return JsonObject(mapOf( - "user" to (b.jsonObject["user"] ?: a.jsonObject["user"] ?: JsonPrimitive(null)), - "props" to (b.jsonObject["props"] ?: a.jsonObject["props"] ?: JsonPrimitive(null)), - "forms" to (b.jsonObject["forms"] ?: a.jsonObject["forms"] ?: JsonPrimitive(null)), - "data" to (b.jsonObject["data"] ?: a.jsonObject["data"] ?: JsonPrimitive(null)), - "project" to (b.jsonObject["project"] ?: a.jsonObject["project"] ?: JsonPrimitive(null)), - )) -} +} \ No newline at end of file diff --git a/android/nativebrik/src/main/java/com/nativebrik/sdk/remoteconfig/config.kt b/android/nativebrik/src/main/java/com/nativebrik/sdk/remoteconfig/config.kt index 18f74f7..45c6bad 100644 --- a/android/nativebrik/src/main/java/com/nativebrik/sdk/remoteconfig/config.kt +++ b/android/nativebrik/src/main/java/com/nativebrik/sdk/remoteconfig/config.kt @@ -105,12 +105,13 @@ class RemoteConfigVariant internal constructor( @Composable fun GetAsEmbedding( key: String, + arguments: Any? = null, onEvent: ((event: Event) -> Unit)? = null, content: (@Composable() (state: EmbeddingLoadingState) -> Unit)? = null ) { val componentId = this.get(key) ?: return return Embedding( - container = this.container, + container = this.container.initWith(arguments), experimentId = this.experimentId, componentId = componentId, onEvent = onEvent, diff --git a/android/nativebrik/src/main/java/com/nativebrik/sdk/sdk.kt b/android/nativebrik/src/main/java/com/nativebrik/sdk/sdk.kt index aba7ad6..fee0d90 100644 --- a/android/nativebrik/src/main/java/com/nativebrik/sdk/sdk.kt +++ b/android/nativebrik/src/main/java/com/nativebrik/sdk/sdk.kt @@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.compositionLocalOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.nativebrik.sdk.component.Embedding @@ -23,7 +24,7 @@ import com.nativebrik.sdk.data.user.NativebrikUser import com.nativebrik.sdk.remoteconfig.RemoteConfigLoadingState import com.nativebrik.sdk.schema.UIBlock -const val VERSION = "0.0.6" +const val VERSION = "0.1.0" data class Endpoint( val cdn: String = "https://cdn.nativebrik.com", @@ -137,10 +138,11 @@ public class NativebrikExperiment { public fun Embedding( id: String, modifier: Modifier = Modifier, + arguments: Any? = null, onEvent: ((event: Event) -> Unit)? = null, content: (@Composable() (state: EmbeddingLoadingState) -> Unit)? = null ) { - Embedding(container = this.container, id, modifier = modifier, onEvent = onEvent, content = content) + Embedding(container = this.container.initWith(arguments), id, modifier = modifier, onEvent = onEvent, content = content) } @Composable @@ -166,7 +168,10 @@ public class __DO_NOT_USE_THIS_INTERNAL_BRIDGE(private val client: NativebrikCli } @Composable - fun render(modifier: Modifier = Modifier, data: Any?, onEvent: ((event: Event) -> Unit)) { + fun render(modifier: Modifier = Modifier, arguments: Any? = null, data: Any?, onEvent: ((event: Event) -> Unit)) { + val container = remember(arguments) { + client.experiment.container.initWith(arguments) + } if (data is UIBlock.UnionUIRootBlock) { Row( modifier = modifier.fillMaxSize(), @@ -175,7 +180,7 @@ public class __DO_NOT_USE_THIS_INTERNAL_BRIDGE(private val client: NativebrikCli ) { Root( modifier = Modifier.fillMaxSize(), - container = client.experiment.container, + container = container, root = data.data, onEvent = onEvent, )