diff --git a/android/buildSrc/src/main/kotlin/BuildConfigs.kt b/android/buildSrc/src/main/kotlin/BuildConfigs.kt index b4ac17129a9..7b8368968ea 100644 --- a/android/buildSrc/src/main/kotlin/BuildConfigs.kt +++ b/android/buildSrc/src/main/kotlin/BuildConfigs.kt @@ -2,8 +2,8 @@ object BuildConfigs { const val minSdk = 26 const val compileSdk = 34 const val targetSdk = 34 - const val versionCode = 11 - const val versionName = "2.0.1" + const val versionCode = 12 + const val versionName = "2.0.2" const val applicationId = "org.smartregister.opensrp" const val jvmToolchain = 17 const val kotlinCompilerExtensionVersion = "1.5.8" diff --git a/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt b/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt index 3069b43521e..c50c839ce95 100644 --- a/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt +++ b/android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt @@ -21,6 +21,7 @@ import android.database.SQLException import ca.uhn.fhir.context.ConfigurationException import ca.uhn.fhir.parser.DataFormatException import com.google.android.fhir.FhirEngine +import com.google.android.fhir.datacapture.extensions.logicalId import com.google.android.fhir.db.ResourceNotFoundException import com.google.android.fhir.get import com.google.android.fhir.knowledge.KnowledgeManager @@ -47,6 +48,7 @@ import org.hl7.fhir.r4.model.ImplementationGuide import org.hl7.fhir.r4.model.ListResource import org.hl7.fhir.r4.model.MetadataResource import org.hl7.fhir.r4.model.Parameters +import org.hl7.fhir.r4.model.Reference import org.hl7.fhir.r4.model.Resource import org.hl7.fhir.r4.model.ResourceType import org.hl7.fhir.r4.model.SearchParameter @@ -336,19 +338,19 @@ constructor( } } } else { - composition.retrieveCompositionSections().forEach { - if (it.hasFocus() && it.focus.hasReferenceElement() && it.focus.hasIdentifier()) { - val configIdentifier = it.focus.identifier.value - val referenceResourceType = it.focus.reference.substringBefore(TYPE_REFERENCE_DELIMITER) - if (isAppConfig(referenceResourceType) && !isIconConfig(configIdentifier)) { - val extractedId = it.focus.extractId() - try { - val configBinary = fhirEngine.get(extractedId) - configsJsonMap[configIdentifier] = configBinary.content.decodeToString() - } catch (resourceNotFoundException: ResourceNotFoundException) { - Timber.e("Missing Binary file with ID :$extractedId") - withContext(dispatcherProvider.main()) { configsLoadedCallback(false) } - } + composition.retrieveCompositionSections().forEach { sectionComponent -> + if (sectionComponent.hasFocus()) { + addBinaryToConfigsJsonMap( + sectionComponent.focus, + configsLoadedCallback, + ) + } + if (sectionComponent.hasEntry() && sectionComponent.entry.isNotEmpty()) { + sectionComponent.entry.forEach { entryReference -> + addBinaryToConfigsJsonMap( + entryReference, + configsLoadedCallback, + ) } } } @@ -356,6 +358,26 @@ constructor( configsLoadedCallback(true) } + private suspend fun addBinaryToConfigsJsonMap( + entryReference: Reference, + configsLoadedCallback: (Boolean) -> Unit, + ) { + if (entryReference.hasReferenceElement() && entryReference.hasIdentifier()) { + val configIdentifier = entryReference.identifier.value + val referenceResourceType = entryReference.reference.substringBefore(TYPE_REFERENCE_DELIMITER) + if (isAppConfig(referenceResourceType) && !isIconConfig(configIdentifier)) { + val extractedId = entryReference.extractId() + try { + val configBinary = fhirEngine.get(extractedId.toString()) + configsJsonMap[configIdentifier] = configBinary.content.decodeToString() + } catch (resourceNotFoundException: ResourceNotFoundException) { + Timber.e("Missing Binary file with ID :$extractedId") + withContext(dispatcherProvider.main()) { configsLoadedCallback(false) } + } + } + } + } + private fun isAppConfig(referenceResourceType: String) = referenceResourceType in arrayOf(ResourceType.Binary.name, ResourceType.Parameters.name) @@ -413,41 +435,30 @@ constructor( val parsedAppId = appId.substringBefore(TYPE_REFERENCE_DELIMITER).trim() val compositionResource = fetchRemoteCompositionByAppId(parsedAppId) compositionResource?.let { composition -> - composition - .retrieveCompositionSections() - .asSequence() - .filter { it.hasFocus() && it.focus.hasReferenceElement() } - .groupBy { section -> - section.focus.reference.substringBefore( - TYPE_REFERENCE_DELIMITER, - missingDelimiterValue = "", - ) + val compositionSections = composition.retrieveCompositionSections() + val sectionComponentMap = mutableMapOf>() + compositionSections.forEach { sectionComponent -> + if (sectionComponent.hasFocus() && sectionComponent.focus.hasReferenceElement()) { + val key = + sectionComponent.focus.reference.substringBefore( + delimiter = TYPE_REFERENCE_DELIMITER, + missingDelimiterValue = "", + ) + sectionComponentMap.getOrPut(key) { mutableListOf() }.apply { add(sectionComponent) } } - .filter { entry -> entry.key in FILTER_RESOURCE_LIST } - .forEach { entry: Map.Entry> -> - if (entry.key == ResourceType.List.name) { - processCompositionListResources(entry) - } else { - val chunkedResourceIdList = entry.value.chunked(MANIFEST_PROCESSOR_BATCH_SIZE) - - chunkedResourceIdList.forEach { sectionComponents -> - Timber.d( - "Fetching config resource ${entry.key}: with ids ${ - sectionComponents.joinToString( - ",", - ) - }", - ) - fetchResources( - resourceType = entry.key, - resourceIdList = - sectionComponents.map { sectionComponent -> - sectionComponent.focus.extractId() - }, + if (sectionComponent.hasEntry() && sectionComponent.entry.isNotEmpty()) { + sectionComponent.entry.forEach { + val key = + it.reference.substringBefore( + delimiter = TYPE_REFERENCE_DELIMITER, + missingDelimiterValue = "", ) - } + sectionComponentMap.getOrPut(key) { mutableListOf() }.apply { add(sectionComponent) } } } + } + + processCompositionSectionComponent(sectionComponentMap) // Save composition after fetching all the referenced section resources addOrUpdate(compositionResource) @@ -457,6 +468,35 @@ constructor( } } + private suspend fun processCompositionSectionComponent( + sectionComponentMap: Map>, + ) { + sectionComponentMap + .filter { entry -> entry.key in FILTER_RESOURCE_LIST } + .forEach { entry: Map.Entry> -> + if (entry.key == ResourceType.List.name) { + processCompositionListResources(entry) + } else { + val chunkedResourceIdList = entry.value.chunked(MANIFEST_PROCESSOR_BATCH_SIZE) + + chunkedResourceIdList.forEach { sectionComponents -> + Timber.d( + "Fetching config resource ${entry.key}: with ids ${ + sectionComponents.joinToString( + ",", + ) + }", + ) + fetchResources( + resourceType = entry.key, + resourceIdList = + sectionComponents.map { sectionComponent -> sectionComponent.focus.extractId() }, + ) + } + } + } + } + suspend fun fetchRemoteImplementationGuideByAppId( appId: String?, appVersionCode: Int?, @@ -636,11 +676,11 @@ constructor( } @VisibleForTesting - fun saveLastConfigUpdatedTimestamp(resource: Resource) { + fun saveLastConfigUpdatedTimestamp(resource: Resource) { sharedPreferencesHelper.write( lastConfigUpdatedTimestampKey( resource.resourceType.name.uppercase(), - resource.id.extractLogicalIdUuid(), + resource.logicalId, ), resource.meta?.lastUpdated?.toTimeZoneString(), ) @@ -656,8 +696,9 @@ constructor( fun setNonProxy(nonProxy: Boolean) { _isNonProxy = nonProxy } + @VisibleForTesting - fun generateRequestBundle(resourceType: String, idList: List): Bundle { + fun generateRequestBundle(resourceType: String, idList: List): Bundle { val bundleEntryComponents = mutableListOf() idList.forEach { @@ -678,7 +719,8 @@ constructor( } } - private fun getLastConfigUpdatedTimestampParam(resourceType: String, resourceId: String): String { + @VisibleForTesting + fun getLastConfigUpdatedTimestampParam(resourceType: String, resourceId: String): String { val timestamp = sharedPreferencesHelper .read(lastConfigUpdatedTimestampKey(resourceType.uppercase(), resourceId), "") @@ -695,7 +737,11 @@ constructor( entry = resourceIds .map { - fhirResourceDataSource.getResource("$resourceType?${Composition.SP_RES_ID}=$it").entry + fhirResourceDataSource + .getResource( + "$resourceType?${Composition.SP_RES_ID}=$it${getLastConfigUpdatedTimestampParam(resourceType, it)}", + ) + .entry } .flatten() } diff --git a/android/engine/src/main/res/values-fr/strings.xml b/android/engine/src/main/res/values-fr/strings.xml index c6da7575988..f4370ff398a 100644 --- a/android/engine/src/main/res/values-fr/strings.xml +++ b/android/engine/src/main/res/values-fr/strings.xml @@ -24,7 +24,7 @@ Synchronisation terminée Synchronisation Synchronisation… - Synchronisation en cours… + Synchronisation… Synchronisation initiée… La synchronisation a échoué. Vérifier la connexion internet ou réessayer plus tard La synchronisation s\'est terminée avec des erreurs. Réessayer... @@ -55,7 +55,7 @@ Réessayer la synchronisation Synchronisation en cours Chargement - Chargement… + Chargement Message d\'erreur de déconnexion %1$s Impossible de se déconnecter : Déjà déconnecté ou l\'appareil est hors ligne. Impossible de charger la configuration. Veuillez réessayer plus tard @@ -75,6 +75,8 @@ Des erreurs de validation ont été détectées. Corrigez les erreurs et soumettez à nouveau. Échec de la validation D\'ACCORD + Projet ouvert + Supprimer le projet Nom d\'utilisateur Mot de passe Mot de passe oublié @@ -184,4 +186,6 @@ APPLIQUER LE FILLTRE Enregistrer les modifications du brouillon Voulez-vous enregistrer les modifications du brouillon ? + Modifications du projet en cours + Vous pouvez rouvrir un projet de formulaire enregistré pour le poursuivre ou le supprimer diff --git a/android/engine/src/main/res/values-in/strings.xml b/android/engine/src/main/res/values-in/strings.xml index 9e674f4fc50..d7d55b464b5 100644 --- a/android/engine/src/main/res/values-in/strings.xml +++ b/android/engine/src/main/res/values-in/strings.xml @@ -1,9 +1,12 @@ Sinkronisasi manual + Sinkronkan Bahasa Keluar sebagai Tampilkan yang terlambat Cari nama atau nomor ID + Cari nama + SINKRONKAN DATA PINDAI BARCODE Tidak Ada Hasil Maaf, kami tidak dapat menemukan klien dengan nama atau nomor ID tersebut @@ -65,12 +68,15 @@ Apakah Anda yakin ingin membuang jawabannya? Buang perubahan Buang - Simpan sebagian draf + Simpan sebagai draf Batal + Batalkan Perubahan Ya Detail yang diberikan mengalami kesalahan validasi. Atasi kesalahan dan kirim lagi Validasi Gagal OK + Buka draf + Hapus draf Username Password Lupa Password @@ -123,6 +129,7 @@ PELAYANAN SELANJUTNYA KARTU PELAYANAN Pasien lainnya + Pilih lokasi RESPONS (%1$s) Mencoba masuk dengan pengguna lain Mohon tunggu... @@ -144,6 +151,7 @@ Pekan/minggu Hari Menginisiasi pengaturan … + Initializing application … e.g JohnDoe %1$d%% Ada yang salah... @@ -157,6 +165,7 @@ Info perangkat Muat ulang Resources Tidak Disinkronkan + Semua data telah tersinkronisasi Statistik Tersinkronisasi Semua data disinkronkan Diperlukan pengaturan pengguna. Aktifkan koneksi internet Anda @@ -175,4 +184,25 @@ Tanggal Perangkat Versi migrasi data + Oke + TAMBAH + Memulai migrasi data dari versi %1$d + Data aplikasi berhasil dimigrasikan ke versi %1$d + Bantu + Tidak ada data yang disetel + Sinkronisasi selesai + Kesalahan sinkronisasi + Menghitung sisa waktu dalam menit… + %1$d%% Sinkronisasi ke atas… + %1$d%% Sinkronisasi ke bawah… + COBA LAGI + Ada beberapa data yang belum tersinkronisasi + Kontak supervisor hilang atau nomor telepon yang diberikan tidak valid + TERAPKAN FILTER + Simpan perubahan draf + Apakah Anda ingin menyimpan perubahan draf? + Buka perubahan draf + Anda dapat membuka kembali formulir draf yang disimpan untuk melanjutkan atau menghapusnya + Berikutnya + Sebelumnya diff --git a/android/engine/src/test/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistryTest.kt b/android/engine/src/test/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistryTest.kt index c1487341730..d28f3a41380 100644 --- a/android/engine/src/test/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistryTest.kt +++ b/android/engine/src/test/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistryTest.kt @@ -24,6 +24,7 @@ import com.google.android.fhir.FhirEngine import com.google.android.fhir.SearchResult import com.google.android.fhir.datacapture.extensions.logicalId import com.google.android.fhir.db.ResourceNotFoundException +import com.google.android.fhir.get import com.google.android.fhir.search.Search import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest @@ -32,6 +33,7 @@ import io.mockk.coEvery import io.mockk.coVerify import io.mockk.mockk import io.mockk.spyk +import java.util.Date import javax.inject.Inject import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest @@ -79,7 +81,6 @@ import org.smartregister.fhircore.engine.util.SharedPreferencesHelper import org.smartregister.fhircore.engine.util.extension.getPayload import org.smartregister.fhircore.engine.util.extension.second import org.smartregister.fhircore.engine.util.extension.toTimeZoneString -import java.util.Date @HiltAndroidTest class ConfigurationRegistryTest : RobolectricTest() { @@ -621,7 +622,7 @@ class ConfigurationRegistryTest : RobolectricTest() { } returns Binary().apply { content = ByteArray(0) } runTest { configRegistry.loadConfigurations(appId, context) } - Assert.assertFalse(configRegistry.configsJsonMap.isEmpty()) + assertFalse(configRegistry.configsJsonMap.isEmpty()) } @Test @@ -1084,12 +1085,144 @@ class ConfigurationRegistryTest : RobolectricTest() { assertEquals(questionnaireId, questionnaire.logicalId) } } + + @Test + fun testFetchNonWorkflowConfigResourcesWithNoFocusOrEntry() = runTest { + val appId = "app-id" + val composition = + Composition().apply { + identifier = Identifier().apply { value = appId } + section = listOf(SectionComponent()) // Neither focus nor entry + } + + configRegistry.fetchNonWorkflowConfigResources() + + // Validate no crash occurs and configsJsonMap remains empty + assertTrue(configRegistry.configsJsonMap.isEmpty()) + } + + @Test + fun testPopulateConfigurationsMapWithNeitherFocusNorEntry() = runTest { + val composition = Composition() + + configRegistry.populateConfigurationsMap(context, composition, false, "app-id") {} + + assertTrue(configRegistry.configsJsonMap.isEmpty()) + } + + @Test + fun testPopulateConfigurationsMapWithAllFocus() = runTest { + val composition = + Composition().apply { + section = + listOf( + SectionComponent().apply { + focus = + Reference().apply { + reference = "Binary/1" + identifier = Identifier().apply { value = "resource1" } + } + }, + ) + } + + coEvery { fhirEngine.get(any()) } returns Binary().apply { content = ByteArray(0) } + configRegistry.populateConfigurationsMap(context, composition, false, "app-id") {} + assertEquals(1, configRegistry.configsJsonMap.size) + assertTrue(configRegistry.configsJsonMap.containsKey("resource1")) + } + + @Test + fun testPopulateConfigurationsMapWithAllEntry() = runTest { + val composition = + Composition().apply { + section = + listOf( + SectionComponent().apply { + entry = + listOf( + Reference().apply { + reference = "Binary/1" + identifier = Identifier().apply { value = "resource1" } + }, + Reference().apply { + reference = "Binary/2" + identifier = Identifier().apply { value = "resource2" } + }, + ) + }, + ) + } + + coEvery { fhirEngine.get(any()) } returns Binary().apply { content = ByteArray(0) } + configRegistry.populateConfigurationsMap(context, composition, false, "app-id") {} + assertEquals(2, configRegistry.configsJsonMap.size) + assertTrue(configRegistry.configsJsonMap.containsKey("resource1")) + assertTrue(configRegistry.configsJsonMap.containsKey("resource2")) + } + + @Test + fun testPopulateConfigurationsMapWithEntryMissingId() = runTest { + val composition = + Composition().apply { + section = + listOf( + SectionComponent().apply { + entry = + listOf( + Reference().apply { reference = "Binary/1" }, + Reference().apply { + reference = "Binary/2" + identifier = Identifier().apply { value = "resource2" } + }, + ) + }, + ) + } + + coEvery { fhirEngine.get(any()) } returns Binary().apply { content = ByteArray(0) } + configRegistry.populateConfigurationsMap(context, composition, false, "app-id") {} + assertEquals(1, configRegistry.configsJsonMap.size) + assertTrue(configRegistry.configsJsonMap.containsKey("resource2")) + } + + @Test + fun testPopulateConfigurationsMapWithFocusAndEntry() = runTest { + val composition = + Composition().apply { + section = + listOf( + SectionComponent().apply { + focus = + Reference().apply { + reference = "Binary/1" + identifier = Identifier().apply { value = "resource1" } + } + entry = + listOf( + Reference().apply { + reference = "Binary/2" + identifier = Identifier().apply { value = "resource2" } + }, + ) + }, + ) + } + + coEvery { fhirEngine.get(any()) } returns Binary().apply { content = ByteArray(0) } + configRegistry.populateConfigurationsMap(context, composition, false, "app-id") {} + assertEquals(2, configRegistry.configsJsonMap.size) + assertTrue(configRegistry.configsJsonMap.containsKey("resource1")) + assertTrue(configRegistry.configsJsonMap.containsKey("resource2")) + } + @Test fun testSaveLastConfigUpdatedTimestamp() { - val resource = Binary().apply { - id = "test-binary-id" - meta = Meta().setLastUpdated(Date()) - } + val resource = + Binary().apply { + id = "test-binary-id" + meta = Meta().setLastUpdated(Date()) + } val expectedKey = "BINARY_test-binary-id_LAST_CONFIG_SYNC_TIMESTAMP" val expectedValue = resource.meta.lastUpdated.toTimeZoneString() @@ -1111,8 +1244,7 @@ class ConfigurationRegistryTest : RobolectricTest() { } @Test - fun testGenerateRequestBundleIncludesLastUpdated() { - + fun testGetLastConfigUpdatedTimestampParam() { val resourceType = "BINARY" val resourceId = "test-binary-id" val timestamp = "2024-01-15T10:00:00Z" @@ -1120,47 +1252,62 @@ class ConfigurationRegistryTest : RobolectricTest() { configRegistry.sharedPreferencesHelper.write(expectedKey, timestamp) + val result = configRegistry.getLastConfigUpdatedTimestampParam(resourceType, resourceId) + assertEquals("&_lastUpdated=gt2024-01-15T10:00:00Z", result) + } - val resultBundle = configRegistry.generateRequestBundle(resourceType, listOf(resourceId)) + @Test + fun testGetLastConfigUpdatedTimestampParamWithNoLastUpdated() { + val resourceType = "BINARY" + val resourceId = "test-binary-id" + + val result = configRegistry.getLastConfigUpdatedTimestampParam(resourceType, resourceId) + + assertEquals("", result) + } + @Test + fun testGenerateRequestBundleIncludesLastUpdated() { + val resourceType = "BINARY" + val resourceId = "test-binary-id" + val timestamp = "2024-01-15T10:00:00Z" + val expectedKey = "${resourceType}_${resourceId}_LAST_CONFIG_SYNC_TIMESTAMP" + + configRegistry.sharedPreferencesHelper.write(expectedKey, timestamp) + + val resultBundle = configRegistry.generateRequestBundle(resourceType, listOf(resourceId)) assertEquals( "$resourceType?_id=$resourceId&_lastUpdated=gt$timestamp", - resultBundle.entry.first().request.url + resultBundle.entry.first().request.url, ) } @Test fun testGenerateRequestBundleWithNoLastUpdated() { - val resourceType = "BINARY" val resourceId = "test-binary-id" - val resultBundle = configRegistry.generateRequestBundle(resourceType, listOf(resourceId)) - assertEquals( "$resourceType?_id=$resourceId", - resultBundle.entry.first().request.url + resultBundle.entry.first().request.url, ) } @Test fun testCreateOrUpdateRemoteUpdatesTimestamp() = runTest { - - val resource = Binary().apply { - id = "test-binary-id" - meta = Meta().setLastUpdated(Date()) - } + val resource = + Binary().apply { + id = "test-binary-id" + meta = Meta().setLastUpdated(Date()) + } val expectedKey = "BINARY_test-binary-id_LAST_CONFIG_SYNC_TIMESTAMP" - configRegistry.createOrUpdateRemote(resource) - val savedTimestamp = configRegistry.sharedPreferencesHelper.read(expectedKey, "") assertFalse(savedTimestamp.isNullOrEmpty()) } - } diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 90702e4b7c7..8a5199492ad 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -142,6 +142,7 @@ junit = { group = "androidx.test.ext", name = "junit", version.ref = "junit" } junit-jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit-jupiter" } junit-jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit-jupiter" } junit-ktx = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "junit-ktx" } +junit-platform-launcher = { group = "org.junit.platform", name = "junit-platform-launcher"} junit-vintage-engine = { group = "org.junit.vintage", name = "junit-vintage-engine", version.ref = "junit-jupiter" } knowledge = { group = "org.smartregister", name = "knowledge", version.ref = "fhir-sdk-knowledge" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } @@ -222,7 +223,7 @@ compose = ["activity-compose","activity-ktx", "ui", "ui-tooling-preview", "const compose-ui-test = ["ui-test-junit4","ui-test-manifest"] coroutines = ["kotlinx-coroutines-core", "kotlinx-coroutines-android"] datastore-kt = ["datastore-preferences", "datastore"] -junit-jupiter-runtime = ["junit-jupiter-engine","junit-vintage-engine"] +junit-jupiter-runtime = ["junit-platform-launcher", "junit-jupiter-engine","junit-vintage-engine"] junit-test = ["junit-ktx", "junit"] klint = ["ktlint-cli-ruleset", "ktlint-rule-engine-core"] lifecycle = ["lifecycle-viewmodel-ktx", "lifecycle-viewmodel-compose", "lifecycle-livedata-ktx"] diff --git a/android/quest/build.gradle.kts b/android/quest/build.gradle.kts index 6baf09f5a1b..cd1fc372fd5 100644 --- a/android/quest/build.gradle.kts +++ b/android/quest/build.gradle.kts @@ -378,7 +378,7 @@ android { dimension = "apps" applicationIdSuffix = ".jobaids" versionNameSuffix = "-kaderjobaids" - manifestPlaceholders["appLabel"] = "Kader Job Aids" + manifestPlaceholders["appLabel"] = "Kader Kesehatan" } } diff --git a/android/quest/src/kaderjobaids/res/drawable/ic_app_logo.png b/android/quest/src/kaderjobaids/res/drawable/ic_app_logo.png index 8caf2e3da25..3a0f7e0617d 100644 Binary files a/android/quest/src/kaderjobaids/res/drawable/ic_app_logo.png and b/android/quest/src/kaderjobaids/res/drawable/ic_app_logo.png differ diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/components/TopScreenSection.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/components/TopScreenSection.kt index 29c14d7acc6..cf12ec26452 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/components/TopScreenSection.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/main/components/TopScreenSection.kt @@ -146,7 +146,7 @@ fun TopScreenSection( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { - Row(verticalAlignment = Alignment.CenterVertically) { + Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.weight(4f)) { Icon( when (toolBarHomeNavigation) { ToolBarHomeNavigation.OPEN_DRAWER -> Icons.Filled.Menu @@ -169,7 +169,7 @@ fun TopScreenSection( Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(start = 8.dp), + modifier = Modifier.padding(start = 8.dp).weight(1f), ) { SetupToolbarIcons( menuIcons = topScreenSection?.menuIcons, @@ -412,7 +412,7 @@ private fun RenderMenuIcon( @Composable fun TopScreenSectionWithFilterItemOverNinetyNinePreview() { TopScreenSection( - title = "All Clients", + title = "All Clients All Clients All Clients All Clients All Clients", searchQuery = SearchQuery("Eddy"), filteredRecordsCount = 120, onSearchTextChanged = { _, _ -> }, diff --git a/android/quest/src/main/res/values-fr/strings.xml b/android/quest/src/main/res/values-fr/strings.xml index c8d989da499..491e08ba699 100644 --- a/android/quest/src/main/res/values-fr/strings.xml +++ b/android/quest/src/main/res/values-fr/strings.xml @@ -119,6 +119,7 @@ La ressource de base pour la configuration du GeoWidget DOIT être l\'emplacement. Aucune configuration fournie pour la barre de recherche. Aucun emplacement trouvé correspondant au texte \"%1$s\" + Autre code_QR Demande d\'autorisation de caméra refusée. Le code-barres pourrait ne pas fonctionner comme prévu. Placez votre caméra sur le code QR pour commencer à scanner. @@ -133,6 +134,9 @@ Tous Les emplacements ont été rendus avec succès\" %1$d Les emplacements correspondants ont été rendus avec succès. Annuler l\'ajout de l\'emplacement + Erreur de rendu du profil + Êtes-vous sûr de vouloir soumettre? + Vous êtes sur le point de soumettre @@ -182,7 +186,6 @@ Autre - Saisissez une option personnalisée Ajouter une autre réponse Cochez toutes les cases qui s\'appliquent Sauvegardez