diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index f5174a7b15..8427272ecc 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.DependencyConstraint import org.gradle.kotlin.dsl.exclude object Dependencies { @@ -42,34 +43,53 @@ object Dependencies { } object HapiFhir { - const val fhirBase = "ca.uhn.hapi.fhir:hapi-fhir-base:${Versions.hapiFhir}" - const val fhirClient = "ca.uhn.hapi.fhir:hapi-fhir-client:${Versions.hapiFhir}" - const val structuresDstu2 = "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2:${Versions.hapiFhir}" - const val structuresDstu3 = "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3:${Versions.hapiFhir}" - const val structuresR4 = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4:${Versions.hapiFhir}" - const val structuresR4b = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4b:${Versions.hapiFhir}" - const val structuresR5 = "ca.uhn.hapi.fhir:hapi-fhir-structures-r5:${Versions.hapiFhir}" - - const val validation = "ca.uhn.hapi.fhir:hapi-fhir-validation:${Versions.hapiFhir}" - const val validationDstu3 = - "ca.uhn.hapi.fhir:hapi-fhir-validation-resources-dstu3:${Versions.hapiFhir}" - const val validationR4 = - "ca.uhn.hapi.fhir:hapi-fhir-validation-resources-r4:${Versions.hapiFhir}" - const val validationR5 = - "ca.uhn.hapi.fhir:hapi-fhir-validation-resources-r5:${Versions.hapiFhir}" - - const val fhirCoreDstu2 = "ca.uhn.hapi.fhir:org.hl7.fhir.dstu2:${Versions.hapiFhirCore}" - const val fhirCoreDstu2016 = - "ca.uhn.hapi.fhir:org.hl7.fhir.dstu2016may:${Versions.hapiFhirCore}" - const val fhirCoreDstu3 = "ca.uhn.hapi.fhir:org.hl7.fhir.dstu3:${Versions.hapiFhirCore}" - const val fhirCoreR4 = "ca.uhn.hapi.fhir:org.hl7.fhir.r4:${Versions.hapiFhirCore}" - const val fhirCoreR4b = "ca.uhn.hapi.fhir:org.hl7.fhir.r4b:${Versions.hapiFhirCore}" - const val fhirCoreR5 = "ca.uhn.hapi.fhir:org.hl7.fhir.r5:${Versions.hapiFhirCore}" - const val fhirCoreUtils = "ca.uhn.hapi.fhir:org.hl7.fhir.utilities:${Versions.hapiFhirCore}" - const val fhirCoreConvertors = - "ca.uhn.hapi.fhir:org.hl7.fhir.convertors:${Versions.hapiFhirCore}" - - const val guavaCaching = "ca.uhn.hapi.fhir:hapi-fhir-caching-guava:${Versions.hapiFhir}" + const val fhirBaseModule = "ca.uhn.hapi.fhir:hapi-fhir-base" + const val fhirClientModule = "ca.uhn.hapi.fhir:hapi-fhir-client" + const val structuresDstu2Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2" + const val structuresDstu3Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3" + const val structuresR4Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4" + const val structuresR4bModule = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4b" + const val structuresR5Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-r5" + + const val validationModule = "ca.uhn.hapi.fhir:hapi-fhir-validation" + const val validationDstu3Module = "ca.uhn.hapi.fhir:hapi-fhir-validation-resources-dstu3" + const val validationR4Module = "ca.uhn.hapi.fhir:hapi-fhir-validation-resources-r4" + const val validationR5Module = "ca.uhn.hapi.fhir:hapi-fhir-validation-resources-r5" + + const val fhirCoreDstu2Module = "ca.uhn.hapi.fhir:org.hl7.fhir.dstu2" + const val fhirCoreDstu2016Module = "ca.uhn.hapi.fhir:org.hl7.fhir.dstu2016may" + const val fhirCoreDstu3Module = "ca.uhn.hapi.fhir:org.hl7.fhir.dstu3" + const val fhirCoreR4Module = "ca.uhn.hapi.fhir:org.hl7.fhir.r4" + const val fhirCoreR4bModule = "ca.uhn.hapi.fhir:org.hl7.fhir.r4b" + const val fhirCoreR5Module = "ca.uhn.hapi.fhir:org.hl7.fhir.r5" + const val fhirCoreUtilsModule = "ca.uhn.hapi.fhir:org.hl7.fhir.utilities" + const val fhirCoreConvertorsModule = "ca.uhn.hapi.fhir:org.hl7.fhir.convertors" + + const val guavaCachingModule = "ca.uhn.hapi.fhir:hapi-fhir-caching-guava" + + const val fhirBase = "$fhirBaseModule:${Versions.hapiFhir}" + const val fhirClient = "$fhirClientModule:${Versions.hapiFhir}" + const val structuresDstu2 = "$structuresDstu2Module:${Versions.hapiFhir}" + const val structuresDstu3 = "$structuresDstu3Module:${Versions.hapiFhir}" + const val structuresR4 = "$structuresR4Module:${Versions.hapiFhir}" + const val structuresR4b = "$structuresR4bModule:${Versions.hapiFhir}" + const val structuresR5 = "$structuresR5Module:${Versions.hapiFhir}" + + const val validation = "$validationModule:${Versions.hapiFhir}" + const val validationDstu3 = "$validationDstu3Module:${Versions.hapiFhir}" + const val validationR4 = "$validationR4Module:${Versions.hapiFhir}" + const val validationR5 = "$validationR5Module:${Versions.hapiFhir}" + + const val fhirCoreDstu2 = "$fhirCoreDstu2Module:${Versions.hapiFhirCore}" + const val fhirCoreDstu2016 = "$fhirCoreDstu2016Module:${Versions.hapiFhirCore}" + const val fhirCoreDstu3 = "$fhirCoreDstu3Module:${Versions.hapiFhirCore}" + const val fhirCoreR4 = "$fhirCoreR4Module:${Versions.hapiFhirCore}" + const val fhirCoreR4b = "$fhirCoreR4bModule:${Versions.hapiFhirCore}" + const val fhirCoreR5 = "$fhirCoreR5Module:${Versions.hapiFhirCore}" + const val fhirCoreUtils = "$fhirCoreUtilsModule:${Versions.hapiFhirCore}" + const val fhirCoreConvertors = "$fhirCoreConvertorsModule:${Versions.hapiFhirCore}" + + const val guavaCaching = "$guavaCachingModule:${Versions.hapiFhir}" } object Jackson { @@ -79,13 +99,14 @@ object Dependencies { private const val datatypeGroup = "$mainGroup.datatype" private const val moduleGroup = "$mainGroup.module" - const val annotations = "$coreGroup:jackson-annotations:${Versions.jackson}" - const val bom = "$mainGroup:jackson-bom:${Versions.jackson}" - const val core = "$coreGroup:jackson-core:${Versions.jacksonCore}" - const val databind = "$coreGroup:jackson-databind:${Versions.jackson}" - const val dataformatXml = "$dataformatGroup:jackson-dataformat-xml:${Versions.jackson}" - const val jaxbAnnotations = "$moduleGroup:jackson-module-jaxb-annotations:${Versions.jackson}" - const val jsr310 = "$datatypeGroup:jackson-datatype-jsr310:${Versions.jackson}" + const val annotationsBase = "$coreGroup:jackson-annotations:${Versions.jackson}" + const val bomBase = "$mainGroup:jackson-bom:${Versions.jackson}" + const val coreBase = "$coreGroup:jackson-core:${Versions.jacksonCore}" + const val databindBase = "$coreGroup:jackson-databind:${Versions.jackson}" + const val dataformatXmlBase = "$dataformatGroup:jackson-dataformat-xml:${Versions.jackson}" + const val jaxbAnnotationsBase = + "$moduleGroup:jackson-module-jaxb-annotations:${Versions.jackson}" + const val jsr310Base = "$datatypeGroup:jackson-datatype-jsr310:${Versions.jackson}" } object Kotlin { @@ -148,7 +169,10 @@ object Dependencies { const val desugarJdkLibs = "com.android.tools:desugar_jdk_libs:${Versions.desugarJdkLibs}" const val fhirUcum = "org.fhir:ucum:${Versions.fhirUcum}" const val gson = "com.google.code.gson:gson:${Versions.gson}" - const val guava = "com.google.guava:guava:${Versions.guava}" + + const val guavaModule = "com.google.guava:guava" + const val guava = "$guavaModule:${Versions.guava}" + const val httpInterceptor = "com.squareup.okhttp3:logging-interceptor:${Versions.http}" const val http = "com.squareup.okhttp3:okhttp:${Versions.http}" const val mockWebServer = "com.squareup.okhttp3:mockwebserver:${Versions.http}" @@ -231,7 +255,7 @@ object Dependencies { const val caffeine = "2.9.1" const val fhirUcum = "1.0.3" const val gson = "2.9.1" - const val guava = "32.1.2-android" + const val guava = "32.1.3-android" const val hapiFhir = "6.8.0" const val hapiFhirCore = "6.0.22" @@ -294,57 +318,38 @@ object Dependencies { exclude(group = "org.apache.httpcomponents") exclude(group = "org.antlr", module = "antlr4") exclude(group = "org.eclipse.persistence", module = "org.eclipse.persistence.moxy") - } - - fun Configuration.forceGuava() { - // Removes caffeine exclude(module = "hapi-fhir-caching-caffeine") exclude(group = "com.github.ben-manes.caffeine", module = "caffeine") - - resolutionStrategy { - force(guava) - force(HapiFhir.guavaCaching) - } } - fun Configuration.forceHapiVersion() { - // Removes newer versions of caffeine and manually imports 2.9 - // Removes newer versions of hapi and keeps on 6.0.1 - // (newer versions don't work on Android) - resolutionStrategy { - force(HapiFhir.fhirBase) - force(HapiFhir.fhirClient) - force(HapiFhir.fhirCoreConvertors) - - force(HapiFhir.fhirCoreDstu2) - force(HapiFhir.fhirCoreDstu2016) - force(HapiFhir.fhirCoreDstu3) - force(HapiFhir.fhirCoreR4) - force(HapiFhir.fhirCoreR4b) - force(HapiFhir.fhirCoreR5) - force(HapiFhir.fhirCoreUtils) - - force(HapiFhir.structuresDstu2) - force(HapiFhir.structuresDstu3) - force(HapiFhir.structuresR4) - force(HapiFhir.structuresR5) - - force(HapiFhir.validation) - force(HapiFhir.validationDstu3) - force(HapiFhir.validationR4) - force(HapiFhir.validationR5) - } - } - - fun Configuration.forceJacksonVersion() { - resolutionStrategy { - force(Jackson.annotations) - force(Jackson.bom) - force(Jackson.core) - force(Jackson.databind) - force(Jackson.jaxbAnnotations) - force(Jackson.jsr310) - force(Jackson.dataformatXml) - } + fun hapiFhirConstraints(): Map Unit> { + return mutableMapOf Unit>( + guavaModule to { version { strictly(Versions.guava) } }, + HapiFhir.fhirBaseModule to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.fhirClientModule to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.fhirCoreConvertorsModule to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreDstu2Module to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreDstu2016Module to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreDstu3Module to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreR4Module to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreR4bModule to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreR5Module to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.fhirCoreUtilsModule to { version { strictly(Versions.hapiFhirCore) } }, + HapiFhir.structuresDstu2Module to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.structuresDstu3Module to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.structuresR4Module to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.structuresR5Module to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.validationModule to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.validationDstu3Module to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.validationR4Module to { version { strictly(Versions.hapiFhir) } }, + HapiFhir.validationR5Module to { version { strictly(Versions.hapiFhir) } }, + Jackson.annotationsBase to { version { strictly(Versions.jackson) } }, + Jackson.bomBase to { version { strictly(Versions.jackson) } }, + Jackson.coreBase to { version { strictly(Versions.jacksonCore) } }, + Jackson.databindBase to { version { strictly(Versions.jackson) } }, + Jackson.jaxbAnnotationsBase to { version { strictly(Versions.jackson) } }, + Jackson.jsr310Base to { version { strictly(Versions.jackson) } }, + Jackson.dataformatXmlBase to { version { strictly(Versions.jackson) } }, + ) } } diff --git a/buildSrc/src/main/kotlin/Releases.kt b/buildSrc/src/main/kotlin/Releases.kt index 38cb8d700c..e53da77fd7 100644 --- a/buildSrc/src/main/kotlin/Releases.kt +++ b/buildSrc/src/main/kotlin/Releases.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ object Releases { object DataCapture : LibraryArtifact { override val artifactId = "data-capture" - override val version = "1.0.0" + override val version = "1.1.0" override val name = "Android FHIR Structured Data Capture Library" } diff --git a/catalog/build.gradle.kts b/catalog/build.gradle.kts index d137d0a320..e4bb7a4373 100644 --- a/catalog/build.gradle.kts +++ b/catalog/build.gradle.kts @@ -1,5 +1,3 @@ -import Dependencies.forceGuava - plugins { id(Plugins.BuildPlugins.application) id(Plugins.BuildPlugins.kotlinAndroid) @@ -42,8 +40,6 @@ android { kotlin { jvmToolchain(11) } } -configurations { all { forceGuava() } } - dependencies { androidTestImplementation(Dependencies.AndroidxTest.extJunit) androidTestImplementation(Dependencies.Espresso.espressoCore) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 548e463c07..7f53725c3e 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,3 +1,5 @@ +import Dependencies.removeIncompatibleDependencies + plugins { id(Plugins.BuildPlugins.androidLib) id(Plugins.BuildPlugins.kotlinAndroid) @@ -17,20 +19,10 @@ android { kotlin { jvmToolchain(11) } } -configurations { - all { - exclude(module = "xpp3") - exclude(module = "hapi-fhir-caching-caffeine") - exclude(group = "com.github.ben-manes.caffeine", module = "caffeine") - - resolutionStrategy { force("com.google.guava:guava:32.1.3-android") } - } -} +configurations { all { removeIncompatibleDependencies() } } dependencies { - // REVERT to DEPENDENCIES LATER - api("ca.uhn.hapi.fhir:hapi-fhir-structures-r4:6.10.0") - api("ca.uhn.hapi.fhir:hapi-fhir-caching-guava:6.10.0") + api(Dependencies.HapiFhir.structuresR4) implementation(Dependencies.fhirUcum) @@ -39,4 +31,10 @@ dependencies { testImplementation(Dependencies.junit) testImplementation(Dependencies.robolectric) testImplementation(Dependencies.truth) + + constraints { + Dependencies.hapiFhirConstraints().forEach { (libName, constraints) -> + api(libName, constraints) + } + } } diff --git a/contrib/barcode/build.gradle.kts b/contrib/barcode/build.gradle.kts index 2f847d9456..69790d9f7e 100644 --- a/contrib/barcode/build.gradle.kts +++ b/contrib/barcode/build.gradle.kts @@ -1,4 +1,4 @@ -import Dependencies.forceGuava +import Dependencies.removeIncompatibleDependencies plugins { id(Plugins.BuildPlugins.androidLib) @@ -46,12 +46,7 @@ android { kotlin { jvmToolchain(11) } } -configurations { - all { - exclude(module = "xpp3") - forceGuava() - } -} +configurations { all { removeIncompatibleDependencies() } } dependencies { androidTestImplementation(Dependencies.AndroidxTest.core) diff --git a/datacapture/build.gradle.kts b/datacapture/build.gradle.kts index 0e829e662d..d261f17e98 100644 --- a/datacapture/build.gradle.kts +++ b/datacapture/build.gradle.kts @@ -1,6 +1,4 @@ -import Dependencies.forceGuava -import Dependencies.forceHapiVersion -import Dependencies.forceJacksonVersion +import Dependencies.removeIncompatibleDependencies import java.net.URL plugins { @@ -59,9 +57,7 @@ configurations { all { exclude(module = "xpp3") exclude(group = "net.sf.saxon", module = "Saxon-HE") - forceGuava() - forceHapiVersion() - forceJacksonVersion() + removeIncompatibleDependencies() } } @@ -108,6 +104,13 @@ dependencies { testImplementation(Dependencies.mockitoKotlin) testImplementation(Dependencies.robolectric) testImplementation(Dependencies.truth) + + constraints { + Dependencies.hapiFhirConstraints().forEach { (libName, constraints) -> + api(libName, constraints) + implementation(libName, constraints) + } + } } tasks.dokkaHtml.configure { diff --git a/datacapture/sampledata/layout_paginated.json b/datacapture/sampledata/layout_paginated.json new file mode 100644 index 0000000000..cf27bca894 --- /dev/null +++ b/datacapture/sampledata/layout_paginated.json @@ -0,0 +1,60 @@ +{ + "resourceType": "Questionnaire", + "item": [ + { + "linkId": "1", + "type": "group", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "page", + "display": "Page" + } + ], + "text": "Page" + } + } + ], + "item": [ + { + "linkId": "1.1", + "type": "display", + "text": "Personal information", + "prefix": "1." + } + ] + }, + { + "linkId": "2", + "type": "group", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "page", + "display": "Page" + } + ], + "text": "Page" + } + } + ], + "item": [ + { + "linkId": "2.1", + "type": "date", + "text": "Date of birth", + "prefix": "2.", + "required": true + } + ] + } + ] +} diff --git a/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt b/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt index 96b75cba10..e5ee755f80 100644 --- a/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt +++ b/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/test/QuestionnaireUiEspressoTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -105,6 +105,30 @@ class QuestionnaireUiEspressoTest { ) } + @Test + fun shouldHideNextButtonIfDisabled() { + buildFragmentFromQuestionnaire("/layout_paginated.json", true) + + clickOnText("Next") + + onView(withId(R.id.pagination_next_button)) + .check( + ViewAssertions.matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)), + ) + } + + @Test + fun shouldDisplayNextButtonIfEnabled() { + buildFragmentFromQuestionnaire("/layout_paginated.json", true) + + onView(withId(R.id.pagination_next_button)) + .check( + ViewAssertions.matches( + ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), + ), + ) + } + @Test fun integerTextEdit_inputOutOfRange_shouldShowError() { buildFragmentFromQuestionnaire("/text_questionnaire_integer.json") @@ -503,6 +527,7 @@ class QuestionnaireUiEspressoTest { val questionnaireFragment = QuestionnaireFragment.builder() .setQuestionnaire(questionnaireJsonString) + .setShowCancelButton(true) .showReviewPageBeforeSubmit(isReviewMode) .build() activityScenarioRule.scenario.onActivity { activity -> diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt index 70cc0b86b8..83841800c7 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -190,10 +190,10 @@ class QuestionnaireFragment : Fragment() { reviewModeEditButton.visibility = View.GONE if (displayMode.pagination.isPaginated) { - paginationPreviousButton.visibility = View.VISIBLE - paginationPreviousButton.isEnabled = displayMode.pagination.hasPreviousPage - paginationNextButton.visibility = View.VISIBLE - paginationNextButton.isEnabled = displayMode.pagination.hasNextPage + paginationPreviousButton.visibility = + if (displayMode.pagination.hasPreviousPage) View.VISIBLE else View.GONE + paginationNextButton.visibility = + if (displayMode.pagination.hasNextPage) View.VISIBLE else View.GONE } else { paginationPreviousButton.visibility = View.GONE paginationNextButton.visibility = View.GONE diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt index 31a5058c53..a4fb8d2443 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextDecimalViewHolderFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,16 +47,17 @@ internal object EditTextDecimalViewHolderFactory : ) { val questionnaireItemViewItemDecimalAnswer = questionnaireViewItem.answers.singleOrNull()?.valueDecimalType?.value?.toString() - val draftAnswer = questionnaireViewItem.draftAnswer?.toString() - val decimalStringToDisplay = questionnaireItemViewItemDecimalAnswer ?: draftAnswer - - if ( - decimalStringToDisplay?.toDoubleOrNull() != + if (questionnaireItemViewItemDecimalAnswer.isNullOrEmpty() && draftAnswer.isNullOrEmpty()) { + textInputEditText.setText("") + } else if ( + questionnaireItemViewItemDecimalAnswer?.toDoubleOrNull() != textInputEditText.text.toString().toDoubleOrNull() ) { - textInputEditText.setText(decimalStringToDisplay) + textInputEditText.setText(questionnaireItemViewItemDecimalAnswer) + } else if (draftAnswer != null && draftAnswer != textInputEditText.text.toString()) { + textInputEditText.setText(draftAnswer) } // Update error message if draft answer present if (draftAnswer != null) { diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt index bb87204486..b9da83ca2b 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/EditTextIntegerViewHolderFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,14 +64,16 @@ internal object EditTextIntegerViewHolderFactory : questionnaireViewItem.answers.singleOrNull()?.valueIntegerType?.value?.toString() val draftAnswer = questionnaireViewItem.draftAnswer?.toString() - val text = answer ?: draftAnswer - // Update the text on the UI only if the value of the saved answer or draft answer // is different from what the user is typing. We compare the two fields as integers to // avoid shifting focus if the text values are different, but their integer representation // is the same (e.g. "001" compared to "1") - if ((text?.toIntOrNull() != textInputEditText.text.toString().toIntOrNull())) { - textInputEditText.setText(text) + if (answer.isNullOrEmpty() && draftAnswer.isNullOrEmpty()) { + textInputEditText.setText("") + } else if (answer?.toIntOrNull() != textInputEditText.text.toString().toIntOrNull()) { + textInputEditText.setText(answer) + } else if (draftAnswer != null && draftAnswer != textInputEditText.text.toString()) { + textInputEditText.setText(draftAnswer) } // Update error message if draft answer present diff --git a/datacapture/src/main/res/values/styles.xml b/datacapture/src/main/res/values/styles.xml index 4fe62672e7..750f97cd7a 100644 --- a/datacapture/src/main/res/values/styles.xml +++ b/datacapture/src/main/res/values/styles.xml @@ -400,7 +400,7 @@