Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppImageLoader
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppImageSizeStorage
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.PermissionManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.checkers.Checker
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.FeatureToggleManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.GeoSerializationManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.InAppSerializationManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.MobileConfigSerializationManager
Expand Down Expand Up @@ -157,7 +158,8 @@ internal fun DataModule(
timeSpanPositiveValidator = slidingExpirationParametersValidator,
mobileConfigSettingsManager = mobileConfigSettingsManager,
integerPositiveValidator = integerPositiveValidator,
inappSettingsManager = inappSettingsManager
inappSettingsManager = inappSettingsManager,
featureToggleManager = featureToggleManager
)
}

Expand Down Expand Up @@ -242,6 +244,7 @@ internal fun DataModule(
}
override val integerPositiveValidator: IntegerPositiveValidator by lazy { IntegerPositiveValidator() }
override val inappSettingsManager: InappSettingsManagerImpl by lazy { InappSettingsManagerImpl(sessionStorageManager) }
override val featureToggleManager: FeatureToggleManager by lazy { FeatureToggleManagerImpl() }
override val maxInappsPerSessionLimitChecker: Checker by lazy { MaxInappsPerSessionLimitChecker(sessionStorageManager) }
override val maxInappsPerDayLimitChecker: Checker by lazy { MaxInappsPerDayLimitChecker(inAppRepository, sessionStorageManager, timeProvider) }
override val minIntervalBetweenShowsLimitChecker: Checker by lazy { MinIntervalBetweenShowsLimitChecker(sessionStorageManager, inAppRepository, timeProvider) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ internal interface DataModule : MindboxModule {
val mobileConfigSettingsManager: MobileConfigSettingsManager
val integerPositiveValidator: IntegerPositiveValidator
val inappSettingsManager: InappSettingsManager
val featureToggleManager: FeatureToggleManager
val maxInappsPerSessionLimitChecker: Checker
val maxInappsPerDayLimitChecker: Checker
val minIntervalBetweenShowsLimitChecker: Checker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal fun PresentationModule(
AppContextModule by appContextModule {

override val inAppMessageViewDisplayer by lazy {
InAppMessageViewDisplayerImpl(inAppImageSizeStorage)
InAppMessageViewDisplayerImpl(inAppImageSizeStorage, featureToggleManager)
}

override val inAppMessageManager by lazy {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cloud.mindbox.mobile_sdk.inapp.data.dto.deserializers

import cloud.mindbox.mobile_sdk.models.operation.response.SettingsDtoBlank
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import java.lang.reflect.Type

private typealias FeatureTogglesDtoBlank = SettingsDtoBlank.FeatureTogglesDtoBlank

internal class FeatureTogglesDtoBlankDeserializer : JsonDeserializer<FeatureTogglesDtoBlank> {
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): FeatureTogglesDtoBlank {
val jsonObject = json.asJsonObject
val result = mutableMapOf<String, Boolean?>()

jsonObject.entrySet().forEach { (key, value) ->
result[key] = value?.takeIf { it.isJsonPrimitive && it.asJsonPrimitive.isBoolean }
?.asJsonPrimitive
?.asBoolean
}

return FeatureTogglesDtoBlank(toggles = result)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ internal fun JsonElement.getString(): String? {
else -> null
}
}

internal fun JsonObject.getAsBooleanOrNull(key: String): Boolean? {
return get(key)?.takeIf { it.isJsonPrimitive && it.asJsonPrimitive.isBoolean }
?.asJsonPrimitive
?.asBoolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cloud.mindbox.mobile_sdk.inapp.data.managers

import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.FeatureToggleManager
import cloud.mindbox.mobile_sdk.models.operation.response.InAppConfigResponse
import java.util.concurrent.ConcurrentHashMap

internal const val SEND_INAPP_SHOW_ERROR_FEATURE = "shouldSendInAppShowError"

internal class FeatureToggleManagerImpl : FeatureToggleManager {

private val toggles = ConcurrentHashMap<String, Boolean>()

override fun applyToggles(config: InAppConfigResponse?) {
toggles.clear()
config?.settings?.featureToggles?.forEach { (key, value) ->
value?.let {
toggles[key] = value
}
}
}

override fun isEnabled(key: String): Boolean {
return toggles[key] ?: false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,18 @@ internal class MobileConfigSerializationManagerImpl(private val gson: Gson) :
}

val inappSettings = runCatching {
gson.fromJson(json.asJsonObject.get("inapp"), SettingsDtoBlank.InappSettingsDtoBlank::class.java)?.copy()
gson.fromJson(json.asJsonObject.get("inapp"), InappSettingsDtoBlank::class.java)?.copy()
}.getOrNull {
mindboxLogE("Failed to parse inapp block in settings section ")
}

SettingsDtoBlank(operations, ttl, slidingExpiration, inappSettings)
val featureToggles = runCatching {
gson.fromJson(json.asJsonObject.get("featureToggles"), FeatureTogglesDtoBlank::class.java)?.copy()
}.getOrNull {
mindboxLogE("Failed to parse featureToggles block in settings section")
}

SettingsDtoBlank(operations, ttl, slidingExpiration, inappSettings, featureToggles)
}
}.getOrNull {
mindboxLogE("Failed to parse settings block", it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import cloud.mindbox.mobile_sdk.inapp.data.managers.SessionStorageManager
import cloud.mindbox.mobile_sdk.inapp.data.managers.data_filler.DataManager
import cloud.mindbox.mobile_sdk.inapp.data.mapper.InAppMapper
import cloud.mindbox.mobile_sdk.inapp.data.validators.*
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.FeatureToggleManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.MobileConfigSerializationManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.repositories.MobileConfigRepository
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.validators.InAppValidator
Expand Down Expand Up @@ -49,7 +50,8 @@ internal class MobileConfigRepositoryImpl(
private val timeSpanPositiveValidator: TimeSpanPositiveValidator,
private val mobileConfigSettingsManager: MobileConfigSettingsManager,
private val integerPositiveValidator: IntegerPositiveValidator,
private val inappSettingsManager: InappSettingsManager
private val inappSettingsManager: InappSettingsManager,
private val featureToggleManager: FeatureToggleManager
) : MobileConfigRepository {

private val mutex = Mutex()
Expand Down Expand Up @@ -100,6 +102,7 @@ internal class MobileConfigRepositoryImpl(
mobileConfigSettingsManager.saveSessionTime(config = filteredConfig)
mobileConfigSettingsManager.checkPushTokenKeepalive(config = filteredConfig)
inappSettingsManager.applySettings(config = filteredConfig)
featureToggleManager.applyToggles(config = filteredConfig)
configState.value = updatedInAppConfig
mindboxLogI(message = "Providing config: $updatedInAppConfig")
}
Expand Down Expand Up @@ -182,7 +185,12 @@ internal class MobileConfigRepositoryImpl(
val inappSettings = runCatching { getInappSettings(configBlank) }.getOrNull {
mindboxLogW("Unable to get inapp settings $it")
}
return SettingsDto(operations, ttl, slidingExpiration, inappSettings)

val featureToggles = runCatching { getFeatureToggles(configBlank) }.getOrNull {
mindboxLogW("Unable to get featureToggles settings $it")
}

return SettingsDto(operations, ttl, slidingExpiration, inappSettings, featureToggles)
}

private fun getInAppTtl(configBlank: InAppConfigResponseBlank?): TtlDto? =
Expand Down Expand Up @@ -241,6 +249,9 @@ internal class MobileConfigRepositoryImpl(
null
}

private fun getFeatureToggles(configBlank: InAppConfigResponseBlank?): Map<String, Boolean?>? =
configBlank?.settings?.featureToggles?.toggles

private fun getABTests(configBlank: InAppConfigResponseBlank?): List<ABTestDto> {
return try {
if (configBlank?.abtests == null) return listOf()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers

import cloud.mindbox.mobile_sdk.models.operation.response.InAppConfigResponse

internal interface FeatureToggleManager {

fun applyToggles(config: InAppConfigResponse?)

fun isEnabled(key: String): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import cloud.mindbox.mobile_sdk.di.mindboxInject
import cloud.mindbox.mobile_sdk.fromJson
import cloud.mindbox.mobile_sdk.inapp.data.dto.BackgroundDto
import cloud.mindbox.mobile_sdk.inapp.data.dto.PayloadDto
import cloud.mindbox.mobile_sdk.inapp.data.managers.SEND_INAPP_SHOW_ERROR_FEATURE
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppActionCallbacks
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppImageSizeStorage
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.FeatureToggleManager
import cloud.mindbox.mobile_sdk.inapp.domain.models.InAppType
import cloud.mindbox.mobile_sdk.inapp.domain.models.InAppTypeWrapper
import cloud.mindbox.mobile_sdk.inapp.domain.models.Layer
Expand All @@ -34,7 +36,10 @@ internal interface MindboxView {
fun requestPermission()
}

internal class InAppMessageViewDisplayerImpl(private val inAppImageSizeStorage: InAppImageSizeStorage) :
internal class InAppMessageViewDisplayerImpl(
private val inAppImageSizeStorage: InAppImageSizeStorage,
private val featureToggleManager: FeatureToggleManager
) :
InAppMessageViewDisplayer {

companion object {
Expand Down Expand Up @@ -191,6 +196,11 @@ internal class InAppMessageViewDisplayerImpl(private val inAppImageSizeStorage:
wrapper: InAppTypeWrapper<InAppType>,
isRestored: Boolean = false,
) {
when (featureToggleManager.isEnabled(SEND_INAPP_SHOW_ERROR_FEATURE)) {
true -> mindboxLogI("InApp.ShowFailure sending enabled")
false -> mindboxLogI("InApp.ShowFailure sending disabled")
}

if (!isRestored) isActionExecuted = false
if (isRestored && tryReattachRestoredInApp(wrapper.inAppType.inAppId)) return

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cloud.mindbox.mobile_sdk.models.operation.response

import cloud.mindbox.mobile_sdk.inapp.data.dto.PayloadDto
import cloud.mindbox.mobile_sdk.inapp.data.dto.deserializers.FeatureTogglesDtoBlankDeserializer
import cloud.mindbox.mobile_sdk.inapp.data.dto.deserializers.InAppIsPriorityDeserializer
import cloud.mindbox.mobile_sdk.models.Milliseconds
import cloud.mindbox.mobile_sdk.models.TimeSpan
Expand Down Expand Up @@ -31,7 +32,9 @@ internal data class SettingsDtoBlank(
@SerializedName("slidingExpiration")
val slidingExpiration: SlidingExpirationDtoBlank?,
@SerializedName("inapp")
val inappSettings: InappSettingsDtoBlank?
val inappSettings: InappSettingsDtoBlank?,
@SerializedName("featureToggles")
val featureToggles: FeatureTogglesDtoBlank?
) {
internal data class OperationDtoBlank(
@SerializedName("systemName")
Expand Down Expand Up @@ -60,6 +63,11 @@ internal data class SettingsDtoBlank(
@SerializedName(InappSettingsDtoBlankDeserializer.MIN_INTERVAL_BETWEEN_SHOWS)
val minIntervalBetweenShows: TimeSpan?,
)

@JsonAdapter(FeatureTogglesDtoBlankDeserializer::class)
internal data class FeatureTogglesDtoBlank(
val toggles: Map<String, Boolean?>
)
}

internal data class SettingsDto(
Expand All @@ -70,7 +78,9 @@ internal data class SettingsDto(
@SerializedName("slidingExpiration")
val slidingExpiration: SlidingExpirationDto?,
@SerializedName("inapp")
val inapp: InappSettingsDto?
val inapp: InappSettingsDto?,
@SerializedName("featureToggles")
val featureToggles: Map<String, Boolean?>?
)

internal data class OperationDto(
Expand Down
Loading