diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/navigation/NavigationMenuConfig.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/navigation/NavigationMenuConfig.kt index 935e9fad56..760f9f2700 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/navigation/NavigationMenuConfig.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/navigation/NavigationMenuConfig.kt @@ -40,9 +40,12 @@ data class NavigationMenuConfig( @Serializable @Parcelize data class ImageConfig( - val type: String = ICON_TYPE_LOCAL, + var type: String = ICON_TYPE_LOCAL, val reference: String? = null, val color: String? = null, + val alpha: Float = 1.0f, + val imageType: ImageType = ImageType.SVG, + val contentScale: ContentScaleType = ContentScaleType.FIT, @Contextual var decodedBitmap: Bitmap? = null, ) : Parcelable, java.io.Serializable { fun interpolate(computedValuesMap: Map): ImageConfig { @@ -55,3 +58,18 @@ data class ImageConfig( const val ICON_TYPE_LOCAL = "local" const val ICON_TYPE_REMOTE = "remote" + +enum class ImageType { + JPEG, + PNG, + SVG, +} + +enum class ContentScaleType { + FIT, + CROP, + FILLHEIGHT, + INSIDE, + NONE, + FILLBOUNDS, +} diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt index e93465fdd9..2899523ebd 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/AppMainViewModel.kt @@ -39,7 +39,6 @@ import javax.inject.Inject import kotlin.time.Duration import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.hl7.fhir.r4.model.Binary import org.hl7.fhir.r4.model.Enumerations import org.hl7.fhir.r4.model.QuestionnaireResponse import org.hl7.fhir.r4.model.ResourceType @@ -68,7 +67,6 @@ import org.smartregister.fhircore.engine.util.DispatcherProvider import org.smartregister.fhircore.engine.util.SecureSharedPreference import org.smartregister.fhircore.engine.util.SharedPreferenceKey import org.smartregister.fhircore.engine.util.SharedPreferencesHelper -import org.smartregister.fhircore.engine.util.extension.decodeToBitmap import org.smartregister.fhircore.engine.util.extension.extractLogicalIdUuid import org.smartregister.fhircore.engine.util.extension.fetchLanguages import org.smartregister.fhircore.engine.util.extension.getActivity @@ -82,6 +80,7 @@ import org.smartregister.fhircore.quest.navigation.NavigationArg import org.smartregister.fhircore.quest.ui.report.measure.worker.MeasureReportMonthPeriodWorker import org.smartregister.fhircore.quest.ui.shared.QuestionnaireHandler import org.smartregister.fhircore.quest.ui.shared.models.QuestionnaireSubmission +import org.smartregister.fhircore.quest.util.extensions.decodeBinaryResourcesToBitmap import org.smartregister.fhircore.quest.util.extensions.handleClickEvent import org.smartregister.fhircore.quest.util.extensions.schedulePeriodically @@ -131,14 +130,7 @@ constructor( it.menuIconConfig?.type == ICON_TYPE_REMOTE && !it.menuIconConfig!!.reference.isNullOrEmpty() } - .forEach { - val resourceId = it.menuIconConfig!!.reference!!.extractLogicalIdUuid() - viewModelScope.launch(dispatcherProvider.io()) { - registerRepository.loadResource(resourceId)?.let { binary -> - it.menuIconConfig!!.decodedBitmap = binary.data.decodeToBitmap() - } - } - } + .decodeBinaryResourcesToBitmap(viewModelScope, registerRepository) } suspend fun retrieveAppMainUiState(refreshAll: Boolean = true) { diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileViewModel.kt index 9ec4339bda..d5bd1d4f62 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileViewModel.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileViewModel.kt @@ -48,7 +48,6 @@ import org.smartregister.fhircore.engine.domain.model.ResourceData import org.smartregister.fhircore.engine.domain.model.SnackBarMessageConfig import org.smartregister.fhircore.engine.rulesengine.ResourceDataRulesExecutor import org.smartregister.fhircore.engine.util.DispatcherProvider -import org.smartregister.fhircore.engine.util.extension.decodeToBitmap import org.smartregister.fhircore.engine.util.extension.extractId import org.smartregister.fhircore.engine.util.extension.extractLogicalIdUuid import org.smartregister.fhircore.engine.util.extension.getActivity @@ -56,7 +55,9 @@ import org.smartregister.fhircore.engine.util.fhirpath.FhirPathDataExtractor import org.smartregister.fhircore.quest.R import org.smartregister.fhircore.quest.ui.profile.bottomSheet.ProfileBottomSheetFragment import org.smartregister.fhircore.quest.ui.profile.model.EligibleManagingEntity +import org.smartregister.fhircore.quest.util.extensions.decodeBinaryResourcesToBitmap import org.smartregister.fhircore.quest.util.extensions.handleClickEvent +import org.smartregister.fhircore.quest.util.extensions.loadRemoteImagesBitmaps import org.smartregister.fhircore.quest.util.extensions.toParamDataMap import timber.log.Timber @@ -97,14 +98,7 @@ constructor( ) profileConfig.overFlowMenuItems .filter { it.icon != null && !it.icon!!.reference.isNullOrEmpty() } - .forEach { - val resourceId = it.icon!!.reference!!.extractLogicalIdUuid() - viewModelScope.launch(dispatcherProvider.io()) { - registerRepository.loadResource(resourceId)?.let { binary -> - it.icon!!.decodedBitmap = binary.data.decodeToBitmap() - } - } - } + .decodeBinaryResourcesToBitmap(viewModelScope, registerRepository) } suspend fun retrieveProfileUiState( @@ -142,6 +136,21 @@ constructor( computedValuesMap = resourceData.computedValuesMap.plus(paramsMap), listResourceDataStateMap = listResourceDataStateMap, ) + if ( + listResourceDataStateMap[listProperties.id] != null && + listResourceDataStateMap[listProperties.id]?.size!! > 0 + ) { + val computedMap = listResourceDataStateMap[listProperties.id]?.get(0)?.computedValuesMap + viewModelScope.launch(dispatcherProvider.io()) { + if (computedMap != null) { + loadRemoteImagesBitmaps( + profileConfiguration.views, + registerRepository, + computedMap, + ) + } + } + } } } } diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/Image.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/Image.kt index 5641bee585..181cb2d335 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/Image.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/Image.kt @@ -45,9 +45,11 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import org.hl7.fhir.r4.model.ResourceType +import org.smartregister.fhircore.engine.configuration.navigation.ContentScaleType import org.smartregister.fhircore.engine.configuration.navigation.ICON_TYPE_LOCAL import org.smartregister.fhircore.engine.configuration.navigation.ICON_TYPE_REMOTE import org.smartregister.fhircore.engine.configuration.navigation.ImageConfig +import org.smartregister.fhircore.engine.configuration.navigation.ImageType import org.smartregister.fhircore.engine.configuration.view.ImageProperties import org.smartregister.fhircore.engine.configuration.view.ImageShape import org.smartregister.fhircore.engine.domain.model.ResourceData @@ -175,6 +177,11 @@ fun ClickableImageIcon( } ICON_TYPE_REMOTE -> if (imageConfig.decodedBitmap != null) { + val imageType = imageProperties.imageConfig?.imageType + val colorFilter = + if (imageType == ImageType.SVG || imageType == ImageType.PNG) tint else null + val contentScale = + convertContentScaleTypeToContentScale(imageProperties.imageConfig!!.contentScale) Image( modifier = Modifier.testTag(SIDE_MENU_ITEM_REMOTE_ICON_TEST_TAG) @@ -183,14 +190,28 @@ fun ClickableImageIcon( .fillMaxSize(0.9f), bitmap = imageConfig.decodedBitmap!!.asImageBitmap(), contentDescription = null, - contentScale = ContentScale.Crop, - colorFilter = ColorFilter.tint(tint ?: imageProperties.imageConfig?.color.parseColor()), + alpha = imageProperties.imageConfig!!.alpha, + contentScale = contentScale, + colorFilter = colorFilter?.let { ColorFilter.tint(it) }, ) } } } } +fun convertContentScaleTypeToContentScale( + contentScale: ContentScaleType, +): ContentScale { + return when (contentScale) { + ContentScaleType.FIT -> ContentScale.Fit + ContentScaleType.CROP -> ContentScale.Crop + ContentScaleType.FILLHEIGHT -> ContentScale.Crop + ContentScaleType.INSIDE -> ContentScale.Inside + ContentScaleType.NONE -> ContentScale.None + ContentScaleType.FILLBOUNDS -> ContentScale.FillBounds + } +} + @PreviewWithBackgroundExcludeGenerated @Composable fun ImagePreview() { diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensions.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensions.kt index a82dd9f024..9ecb03972a 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensions.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensions.kt @@ -26,14 +26,28 @@ import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.navigation.NavController import androidx.navigation.NavOptions +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import org.hl7.fhir.r4.model.Binary +import org.smartregister.fhircore.engine.configuration.navigation.ICON_TYPE_REMOTE import org.smartregister.fhircore.engine.configuration.navigation.NavigationMenuConfig +import org.smartregister.fhircore.engine.configuration.view.CardViewProperties +import org.smartregister.fhircore.engine.configuration.view.ColumnProperties +import org.smartregister.fhircore.engine.configuration.view.ImageProperties +import org.smartregister.fhircore.engine.configuration.view.ListProperties +import org.smartregister.fhircore.engine.configuration.view.RowProperties +import org.smartregister.fhircore.engine.configuration.view.ViewProperties import org.smartregister.fhircore.engine.configuration.workflow.ActionTrigger import org.smartregister.fhircore.engine.configuration.workflow.ApplicationWorkflow +import org.smartregister.fhircore.engine.data.local.register.RegisterRepository import org.smartregister.fhircore.engine.domain.model.ActionConfig import org.smartregister.fhircore.engine.domain.model.ActionParameter import org.smartregister.fhircore.engine.domain.model.ActionParameterType +import org.smartregister.fhircore.engine.domain.model.OverflowMenuItemConfig import org.smartregister.fhircore.engine.domain.model.ResourceData +import org.smartregister.fhircore.engine.domain.model.ViewType import org.smartregister.fhircore.engine.util.extension.decodeJson +import org.smartregister.fhircore.engine.util.extension.decodeToBitmap import org.smartregister.fhircore.engine.util.extension.encodeJson import org.smartregister.fhircore.engine.util.extension.extractLogicalIdUuid import org.smartregister.fhircore.engine.util.extension.interpolate @@ -206,3 +220,78 @@ fun Array?.toParamDataMap(): Map = this?.asSequence() ?.filter { it.paramType == ActionParameterType.PARAMDATA } ?.associate { it.key to it.value } ?: emptyMap() + +fun List.decodeBinaryResourcesToBitmap( + coroutineScope: CoroutineScope, + registerRepository: RegisterRepository, +) { + this.forEach { + val resourceId = it.icon!!.reference!!.extractLogicalIdUuid() + coroutineScope.launch() { + registerRepository.loadResource(resourceId)?.let { binary -> + it.icon!!.decodedBitmap = binary.data.decodeToBitmap() + } + } + } +} + +fun Sequence.decodeBinaryResourcesToBitmap( + coroutineScope: CoroutineScope, + registerRepository: RegisterRepository, +) { + this.forEach { + val resourceId = it.menuIconConfig!!.reference!!.extractLogicalIdUuid() + coroutineScope.launch() { + registerRepository.loadResource(resourceId)?.let { binary -> + it.menuIconConfig!!.decodedBitmap = binary.data.decodeToBitmap() + } + } + } +} + +suspend fun loadRemoteImagesBitmaps( + views: List, + registerRepository: RegisterRepository, + computedValuesMap: Map, +) { + suspend fun ViewProperties.loadIcons() { + when (this.viewType) { + ViewType.IMAGE -> { + val imageProps = this as ImageProperties + if ( + !imageProps.imageConfig?.reference.isNullOrEmpty() && + imageProps.imageConfig?.type == ICON_TYPE_REMOTE + ) { + val resourceId = + imageProps.imageConfig!! + .reference!! + .interpolate(computedValuesMap) + .extractLogicalIdUuid() + registerRepository.loadResource(resourceId)?.let { binary -> + imageProps.imageConfig?.decodedBitmap = binary.data.decodeToBitmap() + } + } + } + ViewType.ROW -> { + val container = this as RowProperties + container.children.forEach { it.loadIcons() } + } + ViewType.COLUMN -> { + val container = this as ColumnProperties + container.children.forEach { it.loadIcons() } + } + ViewType.CARD -> { + val card = this as CardViewProperties + card.content.forEach { it.loadIcons() } + } + ViewType.LIST -> { + val list = this as ListProperties + list.registerCard.views.forEach { it.loadIcons() } + } + else -> { + // Handle any other view types if needed + } + } + } + views.forEach { it.loadIcons() } +} diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/app/fakes/Faker.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/app/fakes/Faker.kt index 994e88e0a0..cde9695e13 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/app/fakes/Faker.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/app/fakes/Faker.kt @@ -31,6 +31,7 @@ import java.util.Date import kotlinx.coroutines.runBlocking import kotlinx.serialization.json.Json import org.hl7.fhir.r4.model.Basic +import org.hl7.fhir.r4.model.Binary import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.DateType import org.hl7.fhir.r4.model.Enumerations @@ -58,6 +59,14 @@ object Faker { private const val APP_DEBUG = "app/debug" + val sampleImageJSONString = + "{\n" + + " \"id\": \"d60ff460-7671-466a-93f4-c93a2ebf2077\",\n" + + " \"resourceType\": \"Binary\",\n" + + " \"contentType\": \"image/jpeg\",\n" + + " \"data\": \"iVBORw0KGgoAAAANSUhEUgAAAFMAAABTCAYAAADjsjsAAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAAtdEVYdENyZWF0aW9uIFRpbWUARnJpIDE5IEFwciAyMDI0IDA3OjIxOjM4IEFNIEVBVIqENmYAAADTSURBVHic7dDBCcAgAMBAdf/p+nQZXSIglLsJQube3xkk1uuAPzEzZGbIzJCZITNDZobMDJkZMjNkZsjMkJkhM0NmhswMmRkyM2RmyMyQmSEzQ2aGzAyZGTIzZGbIzJCZITNDZobMDJkZMjNkZsjMkJkhM0NmhswMmRkyM2RmyMyQmSEzQ2aGzAyZGTIzZGbIzJCZITNDZobMDJkZMjNkZsjMkJkhM0NmhswMmRkyM2RmyMyQmSEzQ2aGzAyZGTIzZGbIzJCZITNDZobMDJkZMjN0AXiwBCviCqIRAAAAAElFTkSuQmCC\"\n" + + "}" + fun buildTestConfigurationRegistry(): ConfigurationRegistry { val fhirResourceService = mockk() val fhirResourceDataSource = spyk(FhirResourceDataSource(fhirResourceService)) @@ -150,4 +159,14 @@ object Faker { override fun deviceOnline() = true } + + fun buildBinaryResource( + id: String = "d60ff460-7671-466a-93f4-c93a2ebf2077", + ): Binary { + return Binary().apply { + this.id = id + this.contentType = "image/jpeg" + this.data = sampleImageJSONString.toByteArray() + } + } } diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensionsTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensionsTest.kt index 0f9a6fb7bd..2a25810f0c 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensionsTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ConfigExtensionsTest.kt @@ -26,27 +26,46 @@ import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.NavOptions import com.google.android.fhir.logicalId +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest import io.mockk.every import io.mockk.mockk import io.mockk.slot import io.mockk.verify +import javax.inject.Inject +import junit.framework.TestCase.assertNotNull import kotlin.test.assertEquals +import kotlinx.coroutines.runBlocking import org.hl7.fhir.r4.model.ContactPoint import org.hl7.fhir.r4.model.ResourceType import org.junit.Assert import org.junit.Before +import org.junit.Rule import org.junit.Test import org.smartregister.fhircore.engine.configuration.QuestionnaireConfig +import org.smartregister.fhircore.engine.configuration.navigation.ICON_TYPE_REMOTE +import org.smartregister.fhircore.engine.configuration.navigation.ImageConfig import org.smartregister.fhircore.engine.configuration.navigation.NavigationMenuConfig +import org.smartregister.fhircore.engine.configuration.profile.ProfileConfiguration +import org.smartregister.fhircore.engine.configuration.register.RegisterCardConfig +import org.smartregister.fhircore.engine.configuration.view.CardViewProperties +import org.smartregister.fhircore.engine.configuration.view.ColumnProperties +import org.smartregister.fhircore.engine.configuration.view.ImageProperties +import org.smartregister.fhircore.engine.configuration.view.ListProperties +import org.smartregister.fhircore.engine.configuration.view.RowProperties import org.smartregister.fhircore.engine.configuration.workflow.ActionTrigger import org.smartregister.fhircore.engine.configuration.workflow.ApplicationWorkflow +import org.smartregister.fhircore.engine.data.local.DefaultRepository +import org.smartregister.fhircore.engine.data.local.register.RegisterRepository import org.smartregister.fhircore.engine.domain.model.ActionConfig import org.smartregister.fhircore.engine.domain.model.ActionParameter import org.smartregister.fhircore.engine.domain.model.ActionParameterType import org.smartregister.fhircore.engine.domain.model.FhirResourceConfig +import org.smartregister.fhircore.engine.domain.model.OverflowMenuItemConfig import org.smartregister.fhircore.engine.domain.model.ResourceConfig import org.smartregister.fhircore.engine.domain.model.ResourceData import org.smartregister.fhircore.engine.domain.model.ToolBarHomeNavigation +import org.smartregister.fhircore.engine.domain.model.ViewType import org.smartregister.fhircore.engine.util.extension.showToast import org.smartregister.fhircore.quest.R import org.smartregister.fhircore.quest.app.fakes.Faker @@ -55,13 +74,98 @@ import org.smartregister.fhircore.quest.navigation.NavigationArg import org.smartregister.fhircore.quest.robolectric.RobolectricTest import org.smartregister.fhircore.quest.ui.shared.QuestionnaireHandler +@HiltAndroidTest class ConfigExtensionsTest : RobolectricTest() { + @get:Rule(order = 0) val hiltAndroidRule = HiltAndroidRule(this) + + @Inject lateinit var defaultRepository: DefaultRepository + + @Inject lateinit var registerRepository: RegisterRepository private val navController = mockk(relaxUnitFun = true) private val context = mockk(relaxUnitFun = true, relaxed = true) private val navigationMenuConfig by lazy { - NavigationMenuConfig(id = "id", display = "menu", visible = true) + NavigationMenuConfig( + id = "id", + display = "menu", + visible = true, + menuIconConfig = + ImageConfig( + type = ICON_TYPE_REMOTE, + reference = "d60ff460-7671-466a-93f4-c93a2ebf2077", + ), + ) } + private val overflowMenuItemConfig by lazy { + OverflowMenuItemConfig( + visible = "true", + icon = + ImageConfig( + type = ICON_TYPE_REMOTE, + reference = "d60ff460-7671-466a-93f4-c93a2ebf2077", + ), + ) + } + private val imageProperties = + ImageProperties( + imageConfig = + ImageConfig( + type = ICON_TYPE_REMOTE, + reference = "d60ff460-7671-466a-93f4-c93a2ebf2077", + ), + ) + + private val profileConfiguration = + ProfileConfiguration( + id = "1", + appId = "a", + fhirResource = + FhirResourceConfig( + baseResource = ResourceConfig(resource = ResourceType.Patient), + relatedResources = + listOf( + ResourceConfig( + resource = ResourceType.Encounter, + ), + ResourceConfig( + resource = ResourceType.Task, + ), + ), + ), + views = + listOf( + CardViewProperties( + viewType = ViewType.CARD, + content = + listOf( + ListProperties( + viewType = ViewType.LIST, + registerCard = + RegisterCardConfig( + views = + listOf( + ColumnProperties( + viewType = ViewType.COLUMN, + children = + listOf( + RowProperties( + viewType = ViewType.ROW, + children = + listOf( + imageProperties, + ), + ), + ), + ), + ), + ), + ), + ), + ), + ), + ) + + private val binaryImage = Faker.buildBinaryResource() private val patient = Faker.buildPatient() private val resourceData by lazy { ResourceData( @@ -73,6 +177,7 @@ class ConfigExtensionsTest : RobolectricTest() { @Before fun setUp() { + hiltAndroidRule.inject() every { navController.context } returns context } @@ -545,4 +650,83 @@ class ConfigExtensionsTest : RobolectricTest() { listOf(clickAction).handleClickEvent(navController, resourceData, context = context) verify { context.showToast(text, Toast.LENGTH_LONG) } } + + @Test + fun decodeBinaryResourcesToBitmapOnNavigationMenuClientRegistersDoneCorrectly(): Unit = + runBlocking { + defaultRepository.create(addResourceTags = true, binaryImage) + val navigationMenuConfigs = sequenceOf(navigationMenuConfig) + runBlocking { navigationMenuConfigs.decodeBinaryResourcesToBitmap(this, registerRepository) } + assertNotNull(navigationMenuConfig.menuIconConfig!!.decodedBitmap) + } + + @Test + fun decodeBinaryResourcesToBitmapOnOverflowMenuConfigDoneCorrectly(): Unit = runBlocking { + defaultRepository.create(addResourceTags = true, binaryImage) + val navigationMenuConfigs = listOf(overflowMenuItemConfig) + runBlocking { navigationMenuConfigs.decodeBinaryResourcesToBitmap(this, registerRepository) } + assertNotNull(navigationMenuConfig.menuIconConfig!!.decodedBitmap) + } + + @Test + fun testImageBitmapUpdatedCorrectlyGivenProfileConfiguration(): Unit = runBlocking { + defaultRepository.create(addResourceTags = true, binaryImage) + loadRemoteImagesBitmaps( + profileConfiguration.views, + computedValuesMap = emptyMap(), + registerRepository = registerRepository, + ) + assertNotNull(imageProperties.imageConfig?.decodedBitmap) + } + + @Test + fun testImageBitmapUpdatedCorrectlyGivenCardViewProperties(): Unit = runBlocking { + val cardViewProperties = profileConfiguration.views[0] as CardViewProperties + defaultRepository.create(addResourceTags = true, binaryImage) + loadRemoteImagesBitmaps( + listOf(cardViewProperties), + computedValuesMap = emptyMap(), + registerRepository = registerRepository, + ) + assertNotNull(imageProperties.imageConfig?.decodedBitmap) + } + + @Test + fun testImageBitmapUpdatedCorrectlyGivenListViewProperties(): Unit = runBlocking { + val cardViewProperties = profileConfiguration.views[0] as CardViewProperties + defaultRepository.create(addResourceTags = true, binaryImage) + loadRemoteImagesBitmaps( + listOf(cardViewProperties.content[0]), + computedValuesMap = emptyMap(), + registerRepository = registerRepository, + ) + assertNotNull(imageProperties.imageConfig?.decodedBitmap) + } + + @Test + fun testImageBitmapUpdatedCorrectlyGivenColumnProperties(): Unit = runBlocking { + val cardViewProperties = profileConfiguration.views[0] as CardViewProperties + val listViewProperties = cardViewProperties.content[0] as ListProperties + defaultRepository.create(addResourceTags = true, binaryImage) + loadRemoteImagesBitmaps( + listOf(listViewProperties.registerCard.views[0]), + computedValuesMap = emptyMap(), + registerRepository = registerRepository, + ) + assertNotNull(imageProperties.imageConfig?.decodedBitmap) + } + + @Test + fun testImageBitmapUpdatedCorrectlyGivenRowProperties(): Unit = runBlocking { + val cardViewProperties = profileConfiguration.views[0] as CardViewProperties + val listViewProperties = cardViewProperties.content[0] as ListProperties + val columnProperties = listViewProperties.registerCard.views[0] as ColumnProperties + defaultRepository.create(addResourceTags = true, binaryImage) + loadRemoteImagesBitmaps( + listOf(columnProperties.children[0]), + computedValuesMap = emptyMap(), + registerRepository = registerRepository, + ) + assertNotNull(imageProperties.imageConfig?.decodedBitmap) + } }