diff --git a/.gitignore b/.gitignore
index 132dccfa9c2..5c346b4cdb0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,6 @@ node_modules/
.gradle/
build/
-
# Local configuration file (sdk path, etc)
local.properties
@@ -38,6 +37,7 @@ android/quest/src/main/assets/configs/*
# Project resource directories
android/quest/src/main/assets/resources/echis/
-# Claude Code documentation (local only)
CLAUDE.md
-android/CLAUDE.md
+.claude/
+.claude.json
+.mcp.json
diff --git a/android/buildSrc/src/main/kotlin/BuildConfigs.kt b/android/buildSrc/src/main/kotlin/BuildConfigs.kt
index 34baa2404b7..2f30bd0da7d 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 = 35
const val targetSdk = 35
- const val versionCode = 19
- const val versionName = "2.2.2"
+ const val versionCode = 22
+ const val versionName = "2.2.4"
const val applicationId = "org.smartregister.opensrp"
const val jvmToolchain = 17
const val kotlinCompilerExtensionVersion = "1.5.14"
diff --git a/android/engine/src/main/res/values-ar/strings.xml b/android/engine/src/main/res/values-ar/strings.xml
index 91dacdcc502..874d6ad86d2 100644
--- a/android/engine/src/main/res/values-ar/strings.xml
+++ b/android/engine/src/main/res/values-ar/strings.xml
@@ -11,7 +11,7 @@
لا توجد نتائج
نأسف، لم نتمكن من العثور على العميل بالاسم أو المعرف المحدد
تسجيل عميل جديد
- Fhir App
+ OpenSRP
شعار التطبيق
مدعوم من
نسخة التطبيق %1$d(%2$s)
@@ -99,7 +99,7 @@
معرف التطبيق
e.g. ecbis, quest, cha
تكوينات التحميل
- FHIRCORE APP
+ OPENSRP 2
تذكر التطبيق
منتهي
استبدال الصورة
@@ -184,6 +184,7 @@
فريق الرعاية
موقع
رمز إصدار التطبيق
+ نوع خطة التطبيق
تاريخ البناء
الشركة المصنعة
نسخة التطبيق
diff --git a/android/engine/src/main/res/values-es/strings.xml b/android/engine/src/main/res/values-es/strings.xml
index c73132c61e8..a30069722b2 100644
--- a/android/engine/src/main/res/values-es/strings.xml
+++ b/android/engine/src/main/res/values-es/strings.xml
@@ -10,7 +10,7 @@
Sin resultados
Lo sentimos, no pudimos encontrar el cliente con su nombre o ID
Registrar nuevo cliente
- Aplicación Fhir
+ OpenSRP
Logotipo de la aplicación
Desarrollado por
Versión de la aplicación %1$d(%2$s)
@@ -94,7 +94,7 @@
ID de aplicación
por ejemplo, ecbis, quest, cha
CARGAR CONFIGURACIONES
- APLICACIÓN FHIRCORE
+ OpenSRP
Recordar aplicación
Listo
Reemplazar foto
@@ -176,6 +176,7 @@
Equipo de atención
Ubicación
Código de versión de la aplicación
+ Tipo de compilación de la aplicación
Fecha de compilación
Fabricante
Versión de la aplicación
diff --git a/android/engine/src/main/res/values-fr/strings.xml b/android/engine/src/main/res/values-fr/strings.xml
index 6781dead11e..12176ad15d3 100644
--- a/android/engine/src/main/res/values-fr/strings.xml
+++ b/android/engine/src/main/res/values-fr/strings.xml
@@ -162,6 +162,7 @@
Care Team
Localisation
Code de version de l\'application
+ Type de build d\'application
Date de création
Fabricant
Version de l\'application
diff --git a/android/engine/src/main/res/values-in/strings.xml b/android/engine/src/main/res/values-in/strings.xml
index 4ad457cee9a..36b3e2d66d9 100644
--- a/android/engine/src/main/res/values-in/strings.xml
+++ b/android/engine/src/main/res/values-in/strings.xml
@@ -11,7 +11,7 @@
Tidak Ada Hasil
Maaf, kami tidak dapat menemukan klien dengan nama atau nomor ID tersebut
Daftarkan klien baru
- Fhir App
+ OpenSRP
Logo aplikasi
Dipersembahkan oleh
App versi %1$d(%2$s)
@@ -97,7 +97,7 @@
ID Aplikasi
e.g. ecbis, quest, cha
MEMUAT KONFIGURASI
- FHIRCORE APP
+ OPENSRP 2
Ingat aplikasi
Selesai
Ganti foto
@@ -177,6 +177,7 @@
Tim Perawatan
Lokasi
Kode versi aplikasi
+ Jenis pembuatan aplikasi
Tanggal build
Manufaktur
Versi Aplikasi
diff --git a/android/engine/src/main/res/values-sw/strings.xml b/android/engine/src/main/res/values-sw/strings.xml
index f1da30bc55e..b601bd40cb6 100644
--- a/android/engine/src/main/res/values-sw/strings.xml
+++ b/android/engine/src/main/res/values-sw/strings.xml
@@ -139,4 +139,5 @@
Usanidi wa mtumiaji unahitajika. Washa mtandao
Usawazishaji umekamilika na hitilafu. Inajaribu tena…
Hitilafu fulani imetokea…
+ Aina ya uundaji wa programu
diff --git a/android/engine/src/main/res/values/strings.xml b/android/engine/src/main/res/values/strings.xml
index ec06e3d0b9f..6eea1b501fe 100644
--- a/android/engine/src/main/res/values/strings.xml
+++ b/android/engine/src/main/res/values/strings.xml
@@ -11,7 +11,7 @@
No Results
Sorry, we could not find client with given name or ID
Register new client
- Fhir App
+ OpenSRP
Application logo
Powered By
App version %1$d(%2$s)
@@ -99,7 +99,7 @@
Application ID
e.g. ecbis, quest, cha
LOAD CONFIGURATIONS
- FHIRCORE APP
+ OPENSRP 2
Remember application
Done
Replace photo
@@ -182,10 +182,11 @@
User
Team
Locality
- Team(Organization)
+ Team (Organization)
Care Team
Location
App version code
+ App build type
Build date
Manufacturer
App version
@@ -205,7 +206,7 @@
%1$d%% Syncing down…
file
RETRY
- There\'s some un-synced data
+ There\'s some unsynced data
Supervisor contact missing or the provided phone number is invalid
APPLY FILTER
Save draft changes
diff --git a/android/engine/src/test/assets/configs/dirext/json/sample_config.json b/android/engine/src/test/assets/configs/dirext/json/sample_config.json
new file mode 100644
index 00000000000..30a942de789
--- /dev/null
+++ b/android/engine/src/test/assets/configs/dirext/json/sample_config.json
@@ -0,0 +1,4 @@
+{
+ "appId": "dirext",
+ "configType": "sample"
+}
diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml
index c0f74691666..020885eb195 100644
--- a/android/gradle/libs.versions.toml
+++ b/android/gradle/libs.versions.toml
@@ -28,9 +28,9 @@ dokkaBase = "1.9.20"
easyRulesCore = "4.1.1"
espresso-core = "3.6.1"
fhir-sdk-common = "0.1.0-alpha05-preview3-SNAPSHOT"
-fhir-sdk-contrib-barcode = "0.1.0-beta3-preview7-SNAPSHOT"
-fhir-sdk-contrib-locationwidget = "0.1.0-alpha01-preview2-SNAPSHOT"
-fhir-sdk-data-capture = "1.3.0-preview1-SNAPSHOT"
+fhir-sdk-contrib-barcode = "0.1.0-beta3-preview8-SNAPSHOT"
+fhir-sdk-contrib-locationwidget = "0.1.0-alpha01-preview3-SNAPSHOT"
+fhir-sdk-data-capture = "1.3.0-preview9-SNAPSHOT"
fhir-sdk-engine = "1.2.0-preview1-SNAPSHOT"
fhir-sdk-knowledge = "0.1.0-beta01-preview1-SNAPSHOT"
fhir-sdk-workflow = "0.1.0-beta01-preview2-SNAPSHOT"
diff --git a/android/quest/build.gradle.kts b/android/quest/build.gradle.kts
index f146deb7712..59b219e0a7d 100644
--- a/android/quest/build.gradle.kts
+++ b/android/quest/build.gradle.kts
@@ -1,4 +1,5 @@
import com.android.build.api.variant.FilterConfiguration.FilterType
+import com.android.build.gradle.internal.api.BaseVariantOutputImpl
import io.sentry.android.gradle.extensions.InstrumentationFeature
import io.sentry.android.gradle.instrumentation.logcat.LogcatLevel
import java.io.FileReader
@@ -429,6 +430,20 @@ android {
versionNameSuffix = "-trueCover"
manifestPlaceholders["appLabel"] = "True Cover"
}
+
+ create("echisDataFi") {
+ dimension = "apps"
+ applicationId = "org.dataforimplementation.echis"
+ versionNameSuffix = "-echis"
+ manifestPlaceholders["appLabel"] = "Data.FI eCHIS Reference"
+ }
+
+ create("echisNawi") {
+ dimension = "apps"
+ applicationId = "ke.nawi.echis"
+ versionNameSuffix = "-echis"
+ manifestPlaceholders["appLabel"] = "Nawi eCHIS"
+ }
}
applicationVariants.all {
@@ -439,6 +454,13 @@ android {
"app_name",
"\"${variant.mergedFlavor.manifestPlaceholders["appLabel"]}\"",
)
+
+ variant.outputs
+ .map { it as BaseVariantOutputImpl }
+ .forEach { output ->
+ output.outputFileName =
+ "quest-${variant.flavorName}-${variant.buildType.name}-${variant.versionName}.apk"
+ }
}
applicationVariants.all {
diff --git a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/pin/PinLoginScreenKtTest.kt b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/pin/PinLoginScreenKtTest.kt
index d993c907fef..22e1c74c278 100644
--- a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/pin/PinLoginScreenKtTest.kt
+++ b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/pin/PinLoginScreenKtTest.kt
@@ -73,7 +73,7 @@ class PinLoginScreenKtTest {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
onSetPin = {},
showProgressBar = false,
@@ -111,7 +111,7 @@ class PinLoginScreenKtTest {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
onSetPin = {},
showProgressBar = false,
@@ -155,7 +155,7 @@ class PinLoginScreenKtTest {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
onSetPin = {},
showProgressBar = false,
@@ -185,7 +185,7 @@ class PinLoginScreenKtTest {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
onSetPin = {},
showProgressBar = true,
@@ -219,7 +219,7 @@ class PinLoginScreenKtTest {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
onSetPin = {},
showProgressBar = false,
diff --git a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt
index b50e02d3123..15642f04369 100644
--- a/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt
+++ b/android/quest/src/androidTest/java/org/smartregister/fhircore/quest/integration/ui/usersetting/UserSettingInsightScreenTest.kt
@@ -128,6 +128,7 @@ class UserSettingInsightScreenTest {
location = "location",
appVersionCode = "v.123",
appVersion = "3",
+ appBuildType = "debug",
buildDate = "29 jan 2023",
unsyncedResourcesFlow = unsyncedResourcesFlow,
navController = rememberNavController(),
diff --git a/android/quest/src/echisDataFi/res/drawable/ic_app_logo.xml b/android/quest/src/echisDataFi/res/drawable/ic_app_logo.xml
new file mode 100644
index 00000000000..2d6821f2da3
--- /dev/null
+++ b/android/quest/src/echisDataFi/res/drawable/ic_app_logo.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/quest/src/echisDataFi/res/drawable/ic_launcher.xml b/android/quest/src/echisDataFi/res/drawable/ic_launcher.xml
new file mode 100644
index 00000000000..831d0d69272
--- /dev/null
+++ b/android/quest/src/echisDataFi/res/drawable/ic_launcher.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/android/quest/src/echisNawi/res/drawable/ic_app_logo.xml b/android/quest/src/echisNawi/res/drawable/ic_app_logo.xml
new file mode 100644
index 00000000000..f33506b1c7e
--- /dev/null
+++ b/android/quest/src/echisNawi/res/drawable/ic_app_logo.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/quest/src/echisNawi/res/drawable/ic_launcher.xml b/android/quest/src/echisNawi/res/drawable/ic_launcher.xml
new file mode 100644
index 00000000000..57f31357f32
--- /dev/null
+++ b/android/quest/src/echisNawi/res/drawable/ic_launcher.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/geowidget/GeoWidgetLauncherFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/geowidget/GeoWidgetLauncherFragment.kt
index b5740e6af55..0ae6c501885 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/geowidget/GeoWidgetLauncherFragment.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/geowidget/GeoWidgetLauncherFragment.kt
@@ -76,6 +76,7 @@ import org.smartregister.fhircore.quest.ui.shared.viewmodels.SearchViewModel
import org.smartregister.fhircore.quest.util.extensions.handleClickEvent
import org.smartregister.fhircore.quest.util.extensions.hookSnackBar
import org.smartregister.fhircore.quest.util.extensions.rememberLifecycleEvent
+import org.smartregister.fhircore.quest.util.extensions.shouldEnableDrawerGestures
import timber.log.Timber
@AndroidEntryPoint
@@ -142,7 +143,10 @@ class GeoWidgetLauncherFragment : Fragment(), OnSyncListener {
AppTheme {
Scaffold(
- drawerGesturesEnabled = scaffoldState.drawerState.isOpen,
+ drawerGesturesEnabled =
+ navArgs.toolBarHomeNavigation.shouldEnableDrawerGestures(
+ scaffoldState.drawerState.isOpen,
+ ),
scaffoldState = scaffoldState,
drawerContent = {
AppDrawer(
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/login/LoginScreen.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/login/LoginScreen.kt
index d5fdf3adc5c..c2f4e4d0044 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/login/LoginScreen.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/login/LoginScreen.kt
@@ -455,7 +455,7 @@ fun LoginScreenPreview() {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
username = "",
onUsernameChanged = {},
@@ -475,7 +475,7 @@ fun LoginScreenPreviewDarkMode() {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
username = "",
onUsernameChanged = {},
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/pin/PinLoginScreen.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/pin/PinLoginScreen.kt
index 283bce50155..fcbeffab615 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/pin/PinLoginScreen.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/pin/PinLoginScreen.kt
@@ -353,7 +353,7 @@ private fun PinSetupPreview() {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
showProgressBar = false,
showError = false,
@@ -381,7 +381,7 @@ private fun PinSetupPreviewWithProgress() {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
showProgressBar = true,
showError = false,
@@ -409,7 +409,7 @@ private fun PinLoginPreview() {
ApplicationConfiguration(
appId = "appId",
configType = "application",
- appTitle = "FHIRCore App",
+ appTitle = "OPENSRP 2",
),
showProgressBar = false,
showError = false,
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileFragment.kt
index 25756100884..68c2dc06209 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileFragment.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/profile/ProfileFragment.kt
@@ -137,10 +137,11 @@ class ProfileFragment : Fragment() {
profileViewModel.emitSnackBarState(snackBarMessageConfig)
}
+ appMainViewModel.retrieveAppMainUiState(refreshAll = false)
+
// Perform optional on submit actions
val onSubmitActions = questionnaireConfig.onSubmitActions
if (onSubmitActions != null) {
- appMainViewModel.retrieveAppMainUiState(refreshAll = false)
onSubmitActions.handleClickEvent(
navController = findNavController(),
resourceData = profileViewModel.profileUiState.value.resourceData,
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl.kt
index 734d275686b..74163d80b23 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/questionnaire/QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl.kt
@@ -29,9 +29,6 @@ const val OPENSRP_ITEM_VIEWHOLDER_FACTORY_MATCHERS_PROVIDER =
"org.smartregister.fhircore.quest.QuestionnaireItemViewHolderFactoryMatchersProvider"
private const val BARCODE_URL = "https://smartregister.org/barcode-type-widget-extension"
const val BARCODE_NAME = "barcode"
-private const val PASSWORD_EXTENSION_URL =
- "https://github.com/google/android-fhir/StructureDefinition/questionnaire-itemControl"
-private const val PASSWORD_VALUE = "password-widget"
object QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl :
QuestionnaireItemViewHolderFactoryMatchersProviderFactory {
@@ -52,12 +49,9 @@ object QuestionnaireItemViewHolderFactoryMatchersProviderFactoryImpl :
override fun get(): List {
return listOf(
QuestionnaireFragment.QuestionnaireItemViewHolderFactoryMatcher(
- PasswordViewHolderFactory,
- ) { questionnaireItem ->
- questionnaireItem.getExtensionByUrl(PASSWORD_EXTENSION_URL).let {
- if (it == null) false else it.value.toString() == PASSWORD_VALUE
- }
- },
+ factory = PasswordViewHolderFactory,
+ matches = PasswordViewHolderFactory::matcher,
+ ),
QuestionnaireFragment.QuestionnaireItemViewHolderFactoryMatcher(
BarCodeReaderViewHolderFactory,
) { questionnaireItem ->
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/register/RegisterFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/register/RegisterFragment.kt
index 7d9df7aa3ee..dbb081d5d79 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/register/RegisterFragment.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/register/RegisterFragment.kt
@@ -71,6 +71,7 @@ import org.smartregister.fhircore.quest.ui.shared.viewmodels.SearchViewModel
import org.smartregister.fhircore.quest.util.extensions.handleClickEvent
import org.smartregister.fhircore.quest.util.extensions.hookSnackBar
import org.smartregister.fhircore.quest.util.extensions.rememberLifecycleEvent
+import org.smartregister.fhircore.quest.util.extensions.shouldEnableDrawerGestures
@ExperimentalMaterialApi
@AndroidEntryPoint
@@ -134,7 +135,10 @@ class RegisterFragment : Fragment(), OnSyncListener {
.collectAsLazyPagingItems()
Scaffold(
- drawerGesturesEnabled = scaffoldState.drawerState.isOpen,
+ drawerGesturesEnabled =
+ registerFragmentArgs.toolBarHomeNavigation.shouldEnableDrawerGestures(
+ scaffoldState.drawerState.isOpen,
+ ),
scaffoldState = scaffoldState,
drawerContent = {
AppDrawer(
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/password/PasswordViewHolderFactory.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/password/PasswordViewHolderFactory.kt
index e355405f9a4..0a00474f16f 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/password/PasswordViewHolderFactory.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/password/PasswordViewHolderFactory.kt
@@ -31,8 +31,8 @@ import com.google.android.fhir.datacapture.extensions.itemControlCode
import com.google.android.fhir.datacapture.extensions.tryUnwrapContext
import com.google.android.fhir.datacapture.views.HeaderView
import com.google.android.fhir.datacapture.views.QuestionnaireViewItem
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolderDelegate
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolderFactory
+import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemAndroidViewHolderDelegate
+import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemAndroidViewHolderFactory
import com.google.android.material.textfield.TextInputEditText
import kotlinx.coroutines.launch
import org.hl7.fhir.r4.model.Questionnaire
@@ -40,11 +40,11 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse
import org.hl7.fhir.r4.model.StringType
object PasswordViewHolderFactory :
- QuestionnaireItemViewHolderFactory(
+ QuestionnaireItemAndroidViewHolderFactory(
org.smartregister.fhircore.quest.R.layout.password_view,
) {
override fun getQuestionnaireItemViewHolderDelegate() =
- object : QuestionnaireItemViewHolderDelegate {
+ object : QuestionnaireItemAndroidViewHolderDelegate {
override lateinit var questionnaireViewItem: QuestionnaireViewItem
private lateinit var header: HeaderView
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactory.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactory.kt
index 468f58c079f..e5db3cf7dab 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactory.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactory.kt
@@ -20,17 +20,25 @@ import android.annotation.SuppressLint
import android.content.Context
import android.text.Editable
import android.text.InputType
+import android.text.TextWatcher
import android.view.MotionEvent
import android.view.View
+import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.widget.doAfterTextChanged
+import androidx.lifecycle.lifecycleScope
+import com.google.android.fhir.datacapture.extensions.getRequiredOrOptionalText
import com.google.android.fhir.datacapture.extensions.getValidationErrorMessage
+import com.google.android.fhir.datacapture.extensions.localizedFlyoverSpanned
import com.google.android.fhir.datacapture.extensions.tryUnwrapContext
+import com.google.android.fhir.datacapture.views.HeaderView
import com.google.android.fhir.datacapture.views.QuestionnaireViewItem
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemEditTextViewHolderDelegate
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolderDelegate
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolderFactory
+import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemAndroidViewHolderDelegate
+import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemAndroidViewHolderFactory
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
+import kotlinx.coroutines.launch
import org.hl7.fhir.r4.model.QuestionnaireResponse
import org.hl7.fhir.r4.model.StringType
import org.smartregister.fhircore.quest.R
@@ -38,15 +46,34 @@ import org.smartregister.fhircore.quest.util.QrCodeScanUtils
internal class EditTextQrCodeItemViewHolderFactory(
private val qrCodeAnswerChangeListener: QrCodeChangeListener,
-) : QuestionnaireItemViewHolderFactory(R.layout.edit_text_single_line_qr_code_item_view) {
- override fun getQuestionnaireItemViewHolderDelegate(): QuestionnaireItemViewHolderDelegate =
- object :
- QuestionnaireItemEditTextViewHolderDelegate(
- InputType.TYPE_NULL,
- ) {
+) : QuestionnaireItemAndroidViewHolderFactory(R.layout.edit_text_single_line_qr_code_item_view) {
+ override fun getQuestionnaireItemViewHolderDelegate():
+ QuestionnaireItemAndroidViewHolderDelegate =
+ object : QuestionnaireItemAndroidViewHolderDelegate {
+ override lateinit var questionnaireViewItem: QuestionnaireViewItem
+
+ private lateinit var context: AppCompatActivity
+ private lateinit var header: HeaderView
+ private lateinit var textInputLayout: TextInputLayout
+ private lateinit var textInputEditText: TextInputEditText
+ private var textWatcher: TextWatcher? = null
+
@SuppressLint("ClickableViewAccessibility")
override fun init(itemView: View) {
- super.init(itemView)
+ context = itemView.context.tryUnwrapContext()!!
+ header = itemView.findViewById(R.id.header)
+ textInputLayout = itemView.findViewById(R.id.text_input_layout)
+ textInputEditText = itemView.findViewById(R.id.text_input_edit_text)
+
+ textInputEditText.setRawInputType(InputType.TYPE_NULL)
+ // Override `setOnEditorActionListener` to avoid crash with `IllegalStateException` if it's
+ // not possible to move focus forward.
+ textInputEditText.setOnEditorActionListener { view, actionId, _ ->
+ if (actionId != EditorInfo.IME_ACTION_NEXT) {
+ return@setOnEditorActionListener false
+ }
+ view.focusSearch(View.FOCUS_DOWN)?.requestFocus(View.FOCUS_DOWN) ?: false
+ }
val onQrCodeIconClickListener: (Context) -> Unit = {
it.tryUnwrapContext()?.let { appCompatActivity ->
@@ -56,7 +83,7 @@ internal class EditTextQrCodeItemViewHolderFactory(
}
}
- itemView.findViewById(R.id.text_input_layout).apply {
+ textInputLayout.apply {
setEndIconOnClickListener { onQrCodeIconClickListener.invoke(it.context) }
findViewById(R.id.text_input_edit_text).apply {
setOnFocusChangeListener { v, hasFocus ->
@@ -66,8 +93,7 @@ internal class EditTextQrCodeItemViewHolderFactory(
.hideSoftInputFromWindow(v.windowToken, 0)
}
}
- setOnTouchListener { v, event,
- ->
+ setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_UP) {
onQrCodeIconClickListener(v.context)
}
@@ -77,14 +103,33 @@ internal class EditTextQrCodeItemViewHolderFactory(
}
}
+ override fun bind(questionnaireViewItem: QuestionnaireViewItem) {
+ header.bind(questionnaireViewItem)
+ with(textInputLayout) {
+ hint = questionnaireViewItem.enabledDisplayItems.localizedFlyoverSpanned
+ helperText = getRequiredOrOptionalText(questionnaireViewItem, context)
+ }
+ updateValidationTextUI(questionnaireViewItem, textInputLayout)
+
+ if (!textInputEditText.isFocused) {
+ textInputEditText.removeTextChangedListener(textWatcher)
+ updateInputTextUI(questionnaireViewItem, textInputEditText)
+ textWatcher =
+ textInputEditText.doAfterTextChanged { editable: Editable? ->
+ context.lifecycleScope.launch { handleInput(editable!!, questionnaireViewItem) }
+ }
+ }
+ }
+
override fun setReadOnly(isReadOnly: Boolean) {
val questionnaireItemHasAnswer = questionnaireViewItem.answers.any { !it.value.isEmpty }
val readOnly =
questionnaireItemHasAnswer && (isReadOnly || questionnaireViewItem.isSetOnceReadOnly)
- super.setReadOnly(readOnly)
+ textInputLayout.isEnabled = !readOnly
+ textInputEditText.isEnabled = !readOnly
}
- override suspend fun handleInput(
+ private suspend fun handleInput(
editable: Editable,
questionnaireViewItem: QuestionnaireViewItem,
) {
@@ -104,7 +149,7 @@ internal class EditTextQrCodeItemViewHolderFactory(
)
}
- override fun updateInputTextUI(
+ private fun updateInputTextUI(
questionnaireViewItem: QuestionnaireViewItem,
textInputEditText: TextInputEditText,
) {
@@ -115,7 +160,7 @@ internal class EditTextQrCodeItemViewHolderFactory(
}
}
- override fun updateValidationTextUI(
+ private fun updateValidationTextUI(
questionnaireViewItem: QuestionnaireViewItem,
textInputLayout: TextInputLayout,
) {
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeViewHolderFactory.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeViewHolderFactory.kt
index 3bac623fb09..7dc13a93324 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeViewHolderFactory.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeViewHolderFactory.kt
@@ -25,9 +25,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.fhir.datacapture.views.QuestionnaireViewItem
+import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemAndroidViewHolderDelegate
+import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemAndroidViewHolderFactory
import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolder
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolderDelegate
-import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolderFactory
import org.hl7.fhir.r4.model.BooleanType
import org.hl7.fhir.r4.model.Questionnaire
import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent
@@ -35,9 +35,10 @@ import org.hl7.fhir.r4.model.StringType
import org.smartregister.fhircore.quest.R
object EditTextQrCodeViewHolderFactory :
- QuestionnaireItemViewHolderFactory(R.layout.edit_text_qr_code_view) {
- override fun getQuestionnaireItemViewHolderDelegate(): QuestionnaireItemViewHolderDelegate =
- object : QuestionnaireItemViewHolderDelegate {
+ QuestionnaireItemAndroidViewHolderFactory(R.layout.edit_text_qr_code_view) {
+ override fun getQuestionnaireItemViewHolderDelegate():
+ QuestionnaireItemAndroidViewHolderDelegate =
+ object : QuestionnaireItemAndroidViewHolderDelegate {
override lateinit var questionnaireViewItem: QuestionnaireViewItem
private val canHaveMultipleAnswers
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/ActionableButton.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/ActionableButton.kt
index e20439ed362..67ab1c37eb8 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/ActionableButton.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/shared/components/ActionableButton.kt
@@ -181,7 +181,7 @@ fun ActionableButton(
} else {
if (colorOpacity == 0f) DefaultColor else statusColor.copy(alpha = colorOpacity)
}
- if (buttonProperties.startIcon != null) {
+ if (buttonProperties.startIcon != null && status != ServiceStatus.COMPLETED.name) {
Image(
imageProperties =
ImageProperties(
@@ -219,7 +219,7 @@ fun ActionableButton(
color =
if (isButtonEnabled) {
when (status) {
- ServiceStatus.COMPLETED.name -> DefaultColor.copy(0.9f)
+ ServiceStatus.COMPLETED.name -> SuccessColor
else -> statusColor
}
} else {
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt
index 44636d522c8..153ad0bcbc6 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserInsightScreenFragment.kt
@@ -54,6 +54,7 @@ class UserInsightScreenFragment : Fragment() {
location = userSettingViewModel.practitionerLocation(),
appVersionCode = userSettingViewModel.appVersionCode.toString(),
appVersion = userSettingViewModel.appVersionName,
+ appBuildType = userSettingViewModel.appBuildType,
buildDate = userSettingViewModel.getBuildDate(),
unsyncedResourcesFlow = userSettingViewModel.unsyncedResourcesMutableSharedFlow,
navController = findNavController(),
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt
index aa21a5beca5..e3922a559f7 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingInsightScreen.kt
@@ -93,6 +93,7 @@ fun UserSettingInsightScreen(
location: String?,
appVersionCode: String,
appVersion: String,
+ appBuildType: String,
buildDate: String,
dividerColor: Color = DividerColor,
unsyncedResourcesFlow: MutableSharedFlow>>,
@@ -246,6 +247,7 @@ fun UserSettingInsightScreen(
stringResource(R.string.app_versions) to appVersion,
stringResource(R.string.app_version_code) to appVersionCode,
stringResource(R.string.build_date) to buildDate,
+ stringResource(R.string.app_build_type) to appBuildType,
)
InsightInfoView(
title = stringResource(id = R.string.app_info),
@@ -265,10 +267,9 @@ fun UserSettingInsightScreen(
(if (Build.MANUFACTURER.isNullOrEmpty()) "-" else Build.MANUFACTURER),
stringResource(R.string.device) to
(if (Build.DEVICE.isNullOrEmpty()) "-" else Build.DEVICE),
- stringResource(R.string.os_version) to
- (if (Build.VERSION.BASE_OS.isNullOrEmpty()) "-" else Build.VERSION.BASE_OS),
+ stringResource(R.string.os_version) to Build.VERSION.RELEASE,
stringResource(R.string.device_date) to
- (formatDate(Build.TIME, desireFormat = dateFormat).ifEmpty { "-" }),
+ (formatDate(System.currentTimeMillis(), desireFormat = dateFormat).ifEmpty { "-" }),
)
InsightInfoView(
title = stringResource(id = R.string.device_info),
@@ -394,6 +395,7 @@ fun UserSettingInsightScreenPreview() {
location = "location",
appVersionCode = "v2.3.4",
appVersion = "119",
+ appBuildType = "debug",
buildDate = "29 Jan 2023",
unsyncedResourcesFlow = MutableSharedFlow(),
navController = rememberNavController(),
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt
index 4dcf180010b..37eeadffacc 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/usersetting/UserSettingViewModel.kt
@@ -105,6 +105,7 @@ constructor(
val appVersionCode = BuildConfig.VERSION_CODE
val appVersionName = BuildConfig.VERSION_NAME
+ val appBuildType = BuildConfig.BUILD_TYPE
fun retrieveUsername(): String? = secureSharedPreference.retrieveSessionUsername()
diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensions.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensions.kt
index a4577ad3d8e..5acece2961f 100644
--- a/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensions.kt
+++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensions.kt
@@ -24,6 +24,10 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import org.smartregister.fhircore.engine.domain.model.ToolBarHomeNavigation
+
+fun ToolBarHomeNavigation.shouldEnableDrawerGestures(isDrawerOpen: Boolean): Boolean =
+ this == ToolBarHomeNavigation.OPEN_DRAWER || isDrawerOpen
/**
* Apply [Modifier] conditionally. If the condition is met the [ifTrue] block will be called
diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensionsTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensionsTest.kt
index 10cb93bae0b..cdc3d7716eb 100644
--- a/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensionsTest.kt
+++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/util/extensions/ComposeExtensionsTest.kt
@@ -21,7 +21,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import io.mockk.spyk
import io.mockk.verify
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
import org.junit.Test
+import org.smartregister.fhircore.engine.domain.model.ToolBarHomeNavigation
class ComposeExtensionsTest {
@@ -33,4 +36,29 @@ class ComposeExtensionsTest {
modifier.conditional(false, { fillMaxWidth() }) { fillMaxHeight() }
verify { modifier.fillMaxHeight() }
}
+
+ @Test
+ fun testShouldEnableDrawerGesturesEnabledOnOpenDrawerScreenWhenDrawerClosed() {
+ // On OPEN_DRAWER screens the edge swipe must open the drawer even while it is closed.
+ assertTrue(ToolBarHomeNavigation.OPEN_DRAWER.shouldEnableDrawerGestures(isDrawerOpen = false))
+ }
+
+ @Test
+ fun testShouldEnableDrawerGesturesEnabledOnOpenDrawerScreenWhenDrawerOpen() {
+ assertTrue(ToolBarHomeNavigation.OPEN_DRAWER.shouldEnableDrawerGestures(isDrawerOpen = true))
+ }
+
+ @Test
+ fun testShouldEnableDrawerGesturesDisabledOnNavigateBackScreenWhenDrawerClosed() {
+ // On NAVIGATE_BACK screens the edge swipe must not open the drawer.
+ assertFalse(
+ ToolBarHomeNavigation.NAVIGATE_BACK.shouldEnableDrawerGestures(isDrawerOpen = false),
+ )
+ }
+
+ @Test
+ fun testShouldEnableDrawerGesturesEnabledOnNavigateBackScreenWhenDrawerOpen() {
+ // An already open drawer can still be swiped closed regardless of the home navigation.
+ assertTrue(ToolBarHomeNavigation.NAVIGATE_BACK.shouldEnableDrawerGestures(isDrawerOpen = true))
+ }
}