Coverage Summary for Class: DataCollector (cloud.mindbox.mobile_sdk.inapp.presentation.view)

Class Method, % Branch, % Line, % Instruction, %
DataCollector 100% (9/9) 100% (6/6) 100% (43/43) 100% (281/281)
DataCollector$Companion
DataCollector$Provider
DataCollector$Provider$Companion 40% (4/10) 100% (4/4) 21.7% (5/23) 21.8% (26/119)
DataCollector$providers$2 100% (1/1) 100% (12/12) 100% (24/24) 100% (254/254)
Total 70% (14/20) 100% (22/22) 80% (72/90) 85.8% (561/654)


 package cloud.mindbox.mobile_sdk.inapp.presentation.view
 
 import android.content.Context
 import cloud.mindbox.mobile_sdk.BuildConfig
 import cloud.mindbox.mobile_sdk.inapp.data.managers.SessionStorageManager
 import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.PermissionManager
 import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.PermissionStatus
 import cloud.mindbox.mobile_sdk.models.Configuration
 import cloud.mindbox.mobile_sdk.models.InAppEventType
 import cloud.mindbox.mobile_sdk.repository.MindboxPreferences
 import cloud.mindbox.mobile_sdk.utils.Constants
 import com.google.gson.Gson
 import com.google.gson.JsonElement
 import com.google.gson.JsonObject
 import com.google.gson.JsonPrimitive
 import java.util.Locale
 import kotlin.math.roundToInt
 import android.content.res.Configuration as UiConfiguration
 
 internal class DataCollector(
     private val appContext: Context,
     private val sessionStorageManager: SessionStorageManager,
     private val permissionManager: PermissionManager,
     private val configuration: Configuration,
     private val params: Map<String, String>,
     private val inAppInsets: InAppInsets,
     private val gson: Gson,
     private val inAppId: String,
 ) {
 
     private val providers: MutableMap<String, Provider> by lazy {
         mutableMapOf<String, Provider>(
             KEY_DEVICE_UUID to Provider.string(MindboxPreferences.deviceUuid),
             KEY_LOCAL_STATE_VERSION to Provider.number(MindboxPreferences.localStateVersion),
             KEY_ENDPOINT_ID to Provider.string(configuration.endpointId),
             KEY_FIRST_INITIALIZATION_TIME to Provider.string(MindboxPreferences.firstInitializationTime),
             KEY_IN_APP_ID to Provider.string(inAppId),
             KEY_INSETS to createInsetsPayload(inAppInsets),
             KEY_LOCALE to Provider.string(resolveLocale()),
             KEY_OPERATION_NAME to Provider.string((sessionStorageManager.inAppTriggerEvent as? InAppEventType.OrdinalEvent)?.name),
             KEY_OPERATION_BODY to Provider.string((sessionStorageManager.inAppTriggerEvent as? InAppEventType.OrdinalEvent)?.body),
             KEY_PERMISSIONS to createPermissionsPayload(),
             KEY_PLATFORM to Provider.string(VALUE_PLATFORM),
             KEY_SDK_VERSION to Provider.string(BuildConfig.VERSION_NAME),
             KEY_SDK_VERSION_NUMERIC to Provider.string(Constants.SDK_VERSION_NUMERIC.toString()),
             KEY_THEME to Provider.string(resolveTheme()),
             KEY_TRACK_VISIT_SOURCE to Provider.string(sessionStorageManager.lastTrackVisitData?.source),
             KEY_TRACK_VISIT_REQUEST_URL to Provider.string(sessionStorageManager.lastTrackVisitData?.requestUrl),
             KEY_USER_VISIT_COUNT to Provider.string(MindboxPreferences.userVisitCount.toString()),
             KEY_VERSION to Provider.string(configuration.versionName),
         ).apply {
             params.forEach { (key, value) ->
                 put(key, Provider.string(value))
             }
         }
     }
 
     companion object Companion {
         private const val KEY_DEVICE_UUID = "deviceUUID"
         private const val KEY_ENDPOINT_ID = "endpointId"
         private const val KEY_FIRST_INITIALIZATION_TIME = "firstInitializationDateTime"
         private const val KEY_IN_APP_ID = "inAppId"
         private const val KEY_INSETS = "insets"
         private const val KEY_LOCALE = "locale"
         private const val KEY_OPERATION_BODY = "operationBody"
         private const val KEY_OPERATION_NAME = "operationName"
         private const val KEY_PERMISSIONS = "permissions"
         private const val KEY_PERMISSIONS_STATUS = "status"
         private const val KEY_PERMISSIONS_CAMERA = "camera"
         private const val KEY_PERMISSIONS_LOCATION = "location"
         private const val KEY_PERMISSIONS_MICROPHONE = "microphone"
         private const val KEY_PERMISSIONS_NOTIFICATIONS = "notifications"
         private const val KEY_PERMISSIONS_PHOTO_LIBRARY = "photoLibrary"
         private const val KEY_PLATFORM = "platform"
         private const val KEY_SDK_VERSION = "sdkVersion"
         private const val KEY_SDK_VERSION_NUMERIC = "sdkVersionNumeric"
         private const val KEY_THEME = "theme"
         private const val KEY_TRACK_VISIT_SOURCE = "trackVisitSource"
         private const val KEY_TRACK_VISIT_REQUEST_URL = "trackVisitRequestUrl"
         private const val KEY_USER_VISIT_COUNT = "userVisitCount"
         private const val KEY_VERSION = "version"
         private const val KEY_LOCAL_STATE_VERSION = "localStateVersion"
         private const val VALUE_PLATFORM = "android"
         private const val VALUE_THEME_DARK = "dark"
         private const val VALUE_THEME_LIGHT = "light"
     }
 
     internal fun interface Provider {
         fun get(): JsonElement?
 
         companion object {
             fun string(value: String?) = Provider {
                 if (value.isNullOrBlank()) return@Provider null
                 JsonPrimitive(value)
             }
 
             fun number(value: Number) = Provider {
                 JsonPrimitive(value)
             }
 
             fun objectIntParams(vararg pairs: Pair<String, Int>) = Provider {
                 JsonObject().apply {
                     pairs.forEach { (key, value) ->
                         addProperty(key, value)
                     }
                 }
             }
 
             fun objectStringParams(vararg pairs: Pair<String, String?>) = Provider {
                 JsonObject().apply {
                     pairs.forEach { (key, value) ->
                         addProperty(key, value)
                     }
                 }
             }
 
             fun objectStringParams(map: Map<String, String>) = Provider {
                 JsonObject().apply {
                     map.forEach { (key, value) ->
                         addProperty(key, value)
                     }
                 }
             }
         }
     }
 
     internal fun get(): String {
         val payload = JsonObject()
         providers.forEach { (key, provider) ->
             provider.get()?.let { value ->
                 payload.add(key, value)
             }
         }
         return gson.toJson(payload)
     }
 
     private fun createPermissionsPayload(): Provider {
         val map = mapOf(
             KEY_PERMISSIONS_CAMERA to permissionManager.getCameraPermissionStatus().value,
             KEY_PERMISSIONS_LOCATION to permissionManager.getLocationPermissionStatus().value,
             KEY_PERMISSIONS_MICROPHONE to permissionManager.getMicrophonePermissionStatus().value,
             KEY_PERMISSIONS_NOTIFICATIONS to permissionManager.getNotificationPermissionStatus().value,
             KEY_PERMISSIONS_PHOTO_LIBRARY to permissionManager.getPhotoLibraryPermissionStatus().value,
         ).filter { (_, value) -> value == PermissionStatus.GRANTED.value }
 
         return Provider {
             JsonObject().apply {
                 map.forEach { (key, value) ->
                     add(key, JsonObject().apply { addProperty(KEY_PERMISSIONS_STATUS, value) })
                 }
             }
         }
     }
 
     private fun resolveTheme(): String {
         val uiMode: Int = appContext.resources.configuration.uiMode
         val isDarkTheme: Boolean = (uiMode and UiConfiguration.UI_MODE_NIGHT_MASK) == UiConfiguration.UI_MODE_NIGHT_YES
         return if (isDarkTheme) VALUE_THEME_DARK else VALUE_THEME_LIGHT
     }
 
     private fun resolveLocale(): String {
         return Locale.getDefault().toLanguageTag().replace("-", "_")
     }
 
     private fun createInsetsPayload(insets: InAppInsets): Provider {
         val density: Float = appContext.resources.displayMetrics.density
 
         fun Int.toCssPixel(): Int = (this / density).roundToInt()
 
         return Provider {
             JsonObject().apply {
                 addProperty(InAppInsets.BOTTOM, insets.bottom.toCssPixel())
                 addProperty(InAppInsets.LEFT, insets.left.toCssPixel())
                 addProperty(InAppInsets.RIGHT, insets.right.toCssPixel())
                 addProperty(InAppInsets.TOP, insets.top.toCssPixel())
             }
         }
     }
 }