From 70ceb206a7a454b4692ea86a29ef76b31bcea5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=E2=89=A1ZRS?= <12814349+LZRS@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:59:06 +0300 Subject: [PATCH] Update QR Code Scanning UI (#3438) * Update qr code scan to use bottomsheetdialog ui * Fix failing QrCodeCameraPermissionsDialogFragment tests * Update tests for QR code scanning * Update documentation on support for qr_code-widget extension --------- Co-authored-by: Allan Onchuru <16164649+allan-on@users.noreply.github.com> --- android/gradle/libs.versions.toml | 11 +- android/quest/build.gradle.kts | 7 +- ....kt => CameraPermissionsDialogFragment.kt} | 48 +---- .../scan/QRCodeScannerDialogFragment.kt | 188 ++++++++++++++++++ .../fhircore/quest/util/QrCodeScanUtils.kt | 8 +- .../drawable-hdpi/ic_scan_qr_viewfinder.png | Bin 0 -> 9983 bytes .../drawable-mdpi/ic_scan_qr_viewfinder.png | Bin 0 -> 6665 bytes .../drawable-xhdpi/ic_scan_qr_viewfinder.png | Bin 0 -> 13670 bytes .../drawable-xxhdpi/ic_scan_qr_viewfinder.png | Bin 0 -> 23077 bytes .../ic_scan_qr_viewfinder.png | Bin 0 -> 34734 bytes .../main/res/layout/fragment_qr_code_scan.xml | 80 ++++++++ android/quest/src/main/res/values/strings.xml | 2 + .../CameraPermissionsDialogFragmentTest.kt | 87 ++++++++ ...EditTextQrCodeItemViewHolderFactoryTest.kt | 11 +- .../qrCode/QrCodeCameraDialogFragmentTest.kt | 139 ------------- .../scan/QRCodeScannerDialogFragmentTest.kt | 146 ++++++++++++++ .../quest/util/QrCodeScanUtilsTest.kt | 12 +- .../config-types/forms/questionnaire.mdx | 17 +- 18 files changed, 553 insertions(+), 203 deletions(-) rename android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/{QrCodeCameraDialogFragment.kt => CameraPermissionsDialogFragment.kt} (53%) create mode 100644 android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragment.kt create mode 100644 android/quest/src/main/res/drawable-hdpi/ic_scan_qr_viewfinder.png create mode 100644 android/quest/src/main/res/drawable-mdpi/ic_scan_qr_viewfinder.png create mode 100644 android/quest/src/main/res/drawable-xhdpi/ic_scan_qr_viewfinder.png create mode 100644 android/quest/src/main/res/drawable-xxhdpi/ic_scan_qr_viewfinder.png create mode 100644 android/quest/src/main/res/drawable-xxxhdpi/ic_scan_qr_viewfinder.png create mode 100644 android/quest/src/main/res/layout/fragment_qr_code_scan.xml create mode 100644 android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragmentTest.kt delete mode 100644 android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragmentTest.kt create mode 100644 android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragmentTest.kt diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index fceec7641e..101fe3833f 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -2,8 +2,9 @@ accompanist = "0.23.1" activity-compose = "1.8.2" androidJunit5 = "1.8.2.1" +androidx-camera = "1.4.0-rc01" androidx-paging = "3.3.0" -androidx-test= "1.6.1" +androidx-test = "1.6.1" appcompat = "1.7.0" benchmark-junit = "1.2.4" cardview = "1.0.0" @@ -56,6 +57,7 @@ leakcanary-android = "2.10" lifecycle= "2.8.3" mapbox-sdk-turf = "4.8.0" material = "1.12.0" +mlkit-barcode-scanning = "17.3.0" mockk = "1.13.8" mockk-android = "1.13.8" msg-simple = "1.2" @@ -88,6 +90,11 @@ xercesImpl = "2.12.2" accompanist-flowlayout = { group = "com.google.accompanist", name = "accompanist-flowlayout", version.ref = "accompanist" } accompanist-placeholder = { group = "com.google.accompanist", name = "accompanist-placeholder", version.ref = "accompanist" } activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" } +androidx-camera-camera2 = { group = "androidx.camera", name = "camera-camera2", version.ref = "androidx-camera"} +androidx-camera-extensions = { group = "androidx.camera", name = "camera-extensions", version.ref = "androidx-camera"} +androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "androidx-camera"} +androidx-camera-mlkit-vision = {group = "androidx.camera", name = "camera-mlkit-vision", version.ref = "androidx-camera"} +androidx-camera-view = {group = "androidx.camera", name = "camera-view", version.ref = "androidx-camera"} activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activity-compose" } appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } benchmark-junit = { group = "androidx.benchmark", name = "benchmark-junit4", version.ref = "benchmark-junit" } @@ -154,6 +161,7 @@ lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle- lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" } mapbox-sdk-turf = { group = "com.mapbox.mapboxsdk", name = "mapbox-sdk-turf", version.ref = "mapbox-sdk-turf" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } +mlkit-barcode-scanning = { group = "com.google.mlkit", name = "barcode-scanning", version.ref = "mlkit-barcode-scanning"} mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } mockk-android = { group = "io.mockk", name = "mockk-android", version.ref = "mockk-android" } msg-simple = { group = "com.github.java-json-tools", name = "msg-simple", version.ref = "msg-simple" } @@ -206,6 +214,7 @@ org-owasp-dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "o [bundles] accompanist = ["accompanist-placeholder", "accompanist-flowlayout"] +cameraX = ["androidx-camera-camera2", "androidx-camera-extensions", "androidx-camera-lifecycle", "androidx-camera-mlkit-vision", "androidx-camera-view"] compose = ["activity-compose","activity-ktx", "ui", "ui-tooling-preview", "constraintlayout-compose", "foundation","runtime-livedata"] compose-ui-test = ["ui-test-junit4","ui-test-manifest"] coroutines = ["kotlinx-coroutines-core", "kotlinx-coroutines-android"] diff --git a/android/quest/build.gradle.kts b/android/quest/build.gradle.kts index 6e64030d03..bf7ca9de70 100644 --- a/android/quest/build.gradle.kts +++ b/android/quest/build.gradle.kts @@ -11,7 +11,7 @@ import org.json.JSONObject plugins { `jacoco-report` `project-properties` - `ktlint` + ktlint id("com.android.application") id("kotlin-android") id("kotlin-kapt") @@ -27,7 +27,7 @@ plugins { sonar { properties { property("sonar.projectKey", "fhircore") - property("sonar.kotlin.source.version", libs.kotlin) + property("sonar.kotlin.source.version", libs.versions.kotlin) property( "sonar.androidLint.reportPaths", "${project.layout.buildDirectory.get()}/reports/lint-results-opensrpDebug.xml", @@ -429,6 +429,9 @@ dependencies { implementation(libs.dagger.hilt.android) implementation(libs.hilt.work) implementation(libs.gms.play.services.location) + implementation(libs.mlkit.barcode.scanning) + + implementation(libs.bundles.cameraX) // Annotation processors kapt(libs.hilt.compiler) diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragment.kt similarity index 53% rename from android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragment.kt rename to android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragment.kt index 5a08e6c1cf..0202c11c72 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragment.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragment.kt @@ -17,29 +17,26 @@ package org.smartregister.fhircore.quest.ui.sdc.qrCode import android.Manifest -import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.VisibleForTesting import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment -import com.google.android.fhir.datacapture.contrib.views.barcode.mlkit.md.LiveBarcodeScanningFragment import org.smartregister.fhircore.engine.util.location.PermissionUtils import org.smartregister.fhircore.quest.R -class QrCodeCameraDialogFragment : DialogFragment(R.layout.fragment_camera_permission) { +class CameraPermissionsDialogFragment : DialogFragment(R.layout.fragment_camera_permission) { @VisibleForTesting val cameraPermissionRequest = registerForActivityResult(ActivityResultContracts.RequestPermission()) { permissionGranted -> + parentFragmentManager.setFragmentResult( + CAMERA_PERMISSION_REQUEST_RESULT_KEY, + bundleOf(CAMERA_PERMISSION_REQUEST_RESULT_KEY to permissionGranted), + ) + if (permissionGranted) { - showQrCodeScanner() + dismiss() } else { - Toast.makeText( - requireContext(), - requireContext().getString(R.string.barcode_camera_permission_denied), - Toast.LENGTH_SHORT, - ) - .show() dismiss() } } @@ -49,7 +46,7 @@ class QrCodeCameraDialogFragment : DialogFragment(R.layout.fragment_camera_permi when { PermissionUtils.checkPermissions(requireContext(), listOf(Manifest.permission.CAMERA)) -> { - showQrCodeScanner() + dismiss() } else -> { cameraPermissionRequest.launch(Manifest.permission.CAMERA) @@ -57,33 +54,8 @@ class QrCodeCameraDialogFragment : DialogFragment(R.layout.fragment_camera_permi } } - private fun showQrCodeScanner() = - parentFragmentManager.apply { - setFragmentResultListener( - LiveBarcodeScanningFragment.RESULT_REQUEST_KEY, - requireActivity(), - ) { _, result -> - val qrCode = result.getString(LiveBarcodeScanningFragment.RESULT_REQUEST_KEY)?.trim() - this.setFragmentResult( - RESULT_REQUEST_KEY, - bundleOf(RESULT_REQUEST_KEY to qrCode), - ) - } - - val qrCodeScannerFragment = this.findFragmentByTag(QR_CODE_SCANNER_FRAGMENT_TAG) - if (qrCodeScannerFragment == null) { - LiveBarcodeScanningFragment() - .show( - this@apply, - QR_CODE_SCANNER_FRAGMENT_TAG, - ) - } - - dismiss() - } - companion object { - const val RESULT_REQUEST_KEY = "qr-code-result" - const val QR_CODE_SCANNER_FRAGMENT_TAG = "QrCodeCameraDialogFragment" + const val CAMERA_PERMISSION_REQUEST_RESULT_KEY = + "quest.ui.sdc.qrCode.CameraPermissionsDialogFragment" } } diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragment.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragment.kt new file mode 100644 index 0000000000..1f675c1a52 --- /dev/null +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragment.kt @@ -0,0 +1,188 @@ +/* + * Copyright 2021-2024 Ona Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.smartregister.fhircore.quest.ui.sdc.qrCode.scan + +import android.content.res.Resources +import android.graphics.RectF +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.annotation.VisibleForTesting +import androidx.camera.core.ImageAnalysis.COORDINATE_SYSTEM_VIEW_REFERENCED +import androidx.camera.mlkit.vision.MlKitAnalyzer +import androidx.camera.view.LifecycleCameraController +import androidx.camera.view.PreviewView +import androidx.core.content.ContextCompat +import androidx.core.graphics.toRect +import androidx.core.os.bundleOf +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.google.mlkit.vision.barcode.BarcodeScanner +import com.google.mlkit.vision.barcode.BarcodeScannerOptions +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.barcode.common.Barcode +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import org.smartregister.fhircore.engine.util.location.PermissionUtils +import org.smartregister.fhircore.quest.R +import org.smartregister.fhircore.quest.ui.sdc.qrCode.CameraPermissionsDialogFragment + +internal class QRCodeScannerDialogFragment : + BottomSheetDialogFragment(R.layout.fragment_qr_code_scan) { + + private lateinit var cameraExecutor: ExecutorService + private lateinit var cameraController: LifecycleCameraController + private lateinit var mlKitImageAnalyzer: MlKitAnalyzer + private val barcodeScanner: BarcodeScanner by lazy { + val options = BarcodeScannerOptions.Builder().setBarcodeFormats(Barcode.FORMAT_QR_CODE).build() + BarcodeScanning.getClient(options) + } + + private lateinit var previewView: PreviewView + private lateinit var cancelScanButton: ImageButton + private lateinit var viewFinderImageView: ImageView + private lateinit var placeQrCodeScanTextView: TextView + + @VisibleForTesting + val viewFinderBounds: RectF + get() { + val viewFinderImageViewHeight = viewFinderImageView.height + val viewFinderImageViewWidth = viewFinderImageView.width + return RectF( + viewFinderImageView.x, + viewFinderImageView.y, + viewFinderImageView.x + viewFinderImageViewWidth + 10, + viewFinderImageView.y + viewFinderImageViewHeight + 10, + ) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + previewView = view.findViewById(R.id.previewView) + viewFinderImageView = view.findViewById(R.id.viewFinderImageView) + placeQrCodeScanTextView = view.findViewById(R.id.placeQrCodeScanTextView) + cancelScanButton = view.findViewById(R.id.cancelImageButton) + cancelScanButton.setOnClickListener { dismiss() } + + val parent = view.parent as View + val behavior = BottomSheetBehavior.from(parent) + val layoutParams = parent.layoutParams + layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT + parent.layoutParams = layoutParams + behavior.maxHeight = (0.8 * Resources.getSystem().displayMetrics.heightPixels).toInt() + behavior.peekHeight = (0.8 * Resources.getSystem().displayMetrics.heightPixels).toInt() + behavior.state = BottomSheetBehavior.STATE_EXPANDED + behavior.isDraggable = false + + cameraExecutor = Executors.newSingleThreadExecutor() + cameraController = LifecycleCameraController(requireContext()) + mlKitImageAnalyzer = + MlKitAnalyzer( + listOf(barcodeScanner), + COORDINATE_SYSTEM_VIEW_REFERENCED, + ContextCompat.getMainExecutor(requireActivity()), + ) { result: MlKitAnalyzer.Result? -> + val barcodeResults = result?.getValue(barcodeScanner) + if ( + (barcodeResults == null) || (barcodeResults.size == 0) || (barcodeResults.first() == null) + ) { + return@MlKitAnalyzer + } + + onQrCodeDetected(barcodeResults[0]) + } + + cameraController.setImageAnalysisAnalyzer( + ContextCompat.getMainExecutor(requireActivity()), + mlKitImageAnalyzer, + ) + + parentFragmentManager.setFragmentResultListener( + CameraPermissionsDialogFragment.CAMERA_PERMISSION_REQUEST_RESULT_KEY, + this, + ) { _, result -> + val permissionGranted = + result.getBoolean(CameraPermissionsDialogFragment.CAMERA_PERMISSION_REQUEST_RESULT_KEY) + if (!permissionGranted) { + Toast.makeText( + requireActivity(), + requireContext().getString(R.string.barcode_camera_permission_denied), + Toast.LENGTH_SHORT, + ) + .show() + dismiss() + } + } + } + + override fun onResume() { + super.onResume() + + if ( + !PermissionUtils.checkPermissions( + requireContext(), + listOf(android.Manifest.permission.CAMERA), + ) + ) { + requestCameraPermissions() + } else { + bindCamera() + } + } + + private fun requestCameraPermissions() { + CameraPermissionsDialogFragment().show(parentFragmentManager, TAG) + } + + private fun bindCamera() { + cameraController.bindToLifecycle(this) + previewView.controller = cameraController + } + + private fun isBarcodeWithinExpectedBounds(barcode: Barcode): Boolean { + return barcode.boundingBox?.let { viewFinderBounds.toRect().contains(it) } ?: false + } + + @VisibleForTesting + fun onQrCodeDetected(barcode: Barcode) { + if (isBarcodeWithinExpectedBounds(barcode)) { + parentFragmentManager.setFragmentResult( + RESULT_REQUEST_KEY, + bundleOf(RESULT_REQUEST_KEY to barcode.rawValue), + ) + dismiss() + } else { + placeQrCodeScanTextView.visibility = View.VISIBLE + } + } + + override fun onDestroyView() { + super.onDestroyView() + cameraExecutor.shutdown() + barcodeScanner.close() + } + + companion object { + private const val TAG = "QRCodeScannerDialogFragment" + const val RESULT_REQUEST_KEY = "quest.ui.sdc.qrCode.scan.QRCodeScannerDialogFragment" + } +} diff --git a/android/quest/src/main/java/org/smartregister/fhircore/quest/util/QrCodeScanUtils.kt b/android/quest/src/main/java/org/smartregister/fhircore/quest/util/QrCodeScanUtils.kt index 2ad380b4e6..62de1fb396 100644 --- a/android/quest/src/main/java/org/smartregister/fhircore/quest/util/QrCodeScanUtils.kt +++ b/android/quest/src/main/java/org/smartregister/fhircore/quest/util/QrCodeScanUtils.kt @@ -17,7 +17,7 @@ package org.smartregister.fhircore.quest.util import androidx.fragment.app.FragmentActivity -import org.smartregister.fhircore.quest.ui.sdc.qrCode.QrCodeCameraDialogFragment +import org.smartregister.fhircore.quest.ui.sdc.qrCode.scan.QRCodeScannerDialogFragment object QrCodeScanUtils { @@ -26,14 +26,14 @@ object QrCodeScanUtils { fun scanQrCode(lifecycleOwner: FragmentActivity, onQrCodeScanResult: (String?) -> Unit) { lifecycleOwner.supportFragmentManager.apply { setFragmentResultListener( - QrCodeCameraDialogFragment.RESULT_REQUEST_KEY, + QRCodeScannerDialogFragment.RESULT_REQUEST_KEY, lifecycleOwner, ) { _, result -> - val barcode = result.getString(QrCodeCameraDialogFragment.RESULT_REQUEST_KEY) + val barcode = result.getString(QRCodeScannerDialogFragment.RESULT_REQUEST_KEY) onQrCodeScanResult.invoke(barcode) } - QrCodeCameraDialogFragment().show(this@apply, QR_CODE_SCAN_UTILS_TAG) + QRCodeScannerDialogFragment().show(this@apply, QR_CODE_SCAN_UTILS_TAG) } } } diff --git a/android/quest/src/main/res/drawable-hdpi/ic_scan_qr_viewfinder.png b/android/quest/src/main/res/drawable-hdpi/ic_scan_qr_viewfinder.png new file mode 100644 index 0000000000000000000000000000000000000000..063c1f5f487e7917e590c8e2be58b9eeb80e1466 GIT binary patch literal 9983 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 literal 0 HcmV?d00001 diff --git a/android/quest/src/main/res/drawable-mdpi/ic_scan_qr_viewfinder.png b/android/quest/src/main/res/drawable-mdpi/ic_scan_qr_viewfinder.png new file mode 100644 index 0000000000000000000000000000000000000000..d76359263b013b2f184e8ee68d17edd1cbc610ab GIT binary patch literal 6665 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 z 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 c{?7UT0hLNxzb{llrptQ&B)# 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 F_#czEKAr#o literal 0 HcmV?d00001 diff --git a/android/quest/src/main/res/layout/fragment_qr_code_scan.xml b/android/quest/src/main/res/layout/fragment_qr_code_scan.xml new file mode 100644 index 0000000000..1e5d2e3ded --- /dev/null +++ b/android/quest/src/main/res/layout/fragment_qr_code_scan.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/android/quest/src/main/res/values/strings.xml b/android/quest/src/main/res/values/strings.xml index 91402fb480..50fde9a582 100644 --- a/android/quest/src/main/res/values/strings.xml +++ b/android/quest/src/main/res/values/strings.xml @@ -129,4 +129,6 @@ Camera permission request denied. Barcode may not work as expected Place your camera over the QR Code to start scanning Add QR code + Scan QR Code + Place your camera over the entire QR Code to start scanning diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragmentTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragmentTest.kt new file mode 100644 index 0000000000..d56dfa7494 --- /dev/null +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/CameraPermissionsDialogFragmentTest.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2021-2024 Ona Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.smartregister.fhircore.quest.ui.sdc.qrCode + +import android.Manifest +import android.app.Application +import androidx.fragment.app.commitNow +import androidx.test.core.app.ApplicationProvider +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest +import io.mockk.spyk +import io.mockk.verify +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.robolectric.Shadows.shadowOf +import org.robolectric.util.ReflectionHelpers +import org.smartregister.fhircore.quest.hiltActivityForTestScenario +import org.smartregister.fhircore.quest.robolectric.RobolectricTest + +@HiltAndroidTest +class CameraPermissionsDialogFragmentTest : RobolectricTest() { + @get:Rule(order = 0) var hiltAndroidRule = HiltAndroidRule(this) + + private val applicationContext = ApplicationProvider.getApplicationContext() + + @Before + fun setUp() { + hiltAndroidRule.inject() + } + + @Test + fun onResumeShouldNotLaunchCameraPermissionRequestWhenCameraPermissionGranted() { + shadowOf(applicationContext).grantPermissions(Manifest.permission.CAMERA) + hiltActivityForTestScenario().use { scenario -> + scenario.onActivity { activity -> + val qrCodeFragment = CameraPermissionsDialogFragment() + val cameraPermissionRequestSpy = spyk(qrCodeFragment.cameraPermissionRequest) + ReflectionHelpers.setField( + qrCodeFragment, + "cameraPermissionRequest", + cameraPermissionRequestSpy, + ) + + activity.supportFragmentManager.commitNow { + add(qrCodeFragment, CameraPermissionsDialogFragmentTest::class.java.simpleName) + } + verify(exactly = 0) { cameraPermissionRequestSpy.launch(Manifest.permission.CAMERA) } + } + } + } + + @Test + fun onResumeShouldLaunchCameraPermissionRequestWhenPermissionDenied() { + shadowOf(applicationContext).denyPermissions(Manifest.permission.CAMERA) + hiltActivityForTestScenario().use { scenario -> + scenario.onActivity { activity -> + val qrCodeFragment = CameraPermissionsDialogFragment() + val cameraPermissionRequestSpy = spyk(qrCodeFragment.cameraPermissionRequest) + ReflectionHelpers.setField( + qrCodeFragment, + "cameraPermissionRequest", + cameraPermissionRequestSpy, + ) + + activity.supportFragmentManager.commitNow { + add(qrCodeFragment, CameraPermissionsDialogFragmentTest::class.java.simpleName) + } + verify { cameraPermissionRequestSpy.launch(Manifest.permission.CAMERA) } + } + } + } +} diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactoryTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactoryTest.kt index d04814f58a..7edddb6eca 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactoryTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeItemViewHolderFactoryTest.kt @@ -45,6 +45,7 @@ import org.robolectric.Robolectric import org.smartregister.fhircore.quest.R import org.smartregister.fhircore.quest.hiltActivityForTestScenario import org.smartregister.fhircore.quest.robolectric.RobolectricTest +import org.smartregister.fhircore.quest.ui.sdc.qrCode.scan.QRCodeScannerDialogFragment import org.smartregister.fhircore.quest.util.QrCodeScanUtils @HiltAndroidTest @@ -71,7 +72,7 @@ class EditTextQrCodeItemViewHolderFactoryTest : RobolectricTest() { @Test fun shouldUpdateTextCorrectlyWhenScanQrCodeReceived() { - mockkConstructor(QrCodeCameraDialogFragment::class) + mockkConstructor(QRCodeScannerDialogFragment::class) val sampleQrCode = "d84fbd12-4f22-423a-8645-5525504e1bcb" /** * Using style 'com.google.android.material.R.style.Theme_Material3_DayNight' to prevent @@ -90,13 +91,13 @@ class EditTextQrCodeItemViewHolderFactoryTest : RobolectricTest() { textInputLayout.findViewById(R.id.text_input_edit_text) Assert.assertNotNull(textInputEditText) every { - anyConstructed() + anyConstructed() .show(any(), QrCodeScanUtils.QR_CODE_SCAN_UTILS_TAG) } answers { activity.supportFragmentManager.setFragmentResult( - QrCodeCameraDialogFragment.RESULT_REQUEST_KEY, - bundleOf(QrCodeCameraDialogFragment.RESULT_REQUEST_KEY to sampleQrCode), + QRCodeScannerDialogFragment.RESULT_REQUEST_KEY, + bundleOf(QRCodeScannerDialogFragment.RESULT_REQUEST_KEY to sampleQrCode), ) } @@ -106,7 +107,7 @@ class EditTextQrCodeItemViewHolderFactoryTest : RobolectricTest() { Assert.assertEquals(sampleQrCode, textInputEditText.text.toString()) } } - unmockkConstructor(QrCodeCameraDialogFragment::class) + unmockkConstructor(QRCodeScannerDialogFragment::class) } @Test diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragmentTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragmentTest.kt deleted file mode 100644 index c8c891eb9e..0000000000 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/QrCodeCameraDialogFragmentTest.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2021-2024 Ona Systems, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.smartregister.fhircore.quest.ui.sdc.qrCode - -import android.Manifest -import android.app.Application -import android.widget.Toast -import androidx.core.os.bundleOf -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.commitNow -import androidx.test.core.app.ApplicationProvider -import com.google.android.fhir.datacapture.contrib.views.barcode.mlkit.md.LiveBarcodeScanningFragment -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import io.mockk.every -import io.mockk.just -import io.mockk.mockkConstructor -import io.mockk.runs -import io.mockk.spyk -import io.mockk.unmockkConstructor -import io.mockk.unmockkStatic -import io.mockk.verify -import org.junit.Assert -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.robolectric.Shadows.shadowOf -import org.robolectric.util.ReflectionHelpers -import org.smartregister.fhircore.quest.hiltActivityForTestScenario -import org.smartregister.fhircore.quest.launchFragmentInHiltContainer -import org.smartregister.fhircore.quest.robolectric.RobolectricTest -import org.smartregister.fhircore.quest.ui.sdc.qrCode.QrCodeCameraDialogFragment.Companion.QR_CODE_SCANNER_FRAGMENT_TAG - -@HiltAndroidTest -class QrCodeCameraDialogFragmentTest : RobolectricTest() { - @get:Rule(order = 0) var hiltAndroidRule = HiltAndroidRule(this) - - private val applicationContext = ApplicationProvider.getApplicationContext() - - @Before - fun setUp() { - hiltAndroidRule.inject() - } - - @Test - fun onResumeShouldShowQrCodeScannerWhenCameraPermissionGranted() { - shadowOf(applicationContext).grantPermissions(Manifest.permission.CAMERA) - mockkConstructor(LiveBarcodeScanningFragment::class) - every { - anyConstructed().show(any(), any()) - } just runs - launchFragmentInHiltContainer { - verify { - anyConstructed() - .show( - this@launchFragmentInHiltContainer.parentFragmentManager, - QR_CODE_SCANNER_FRAGMENT_TAG, - ) - } - } - unmockkConstructor(LiveBarcodeScanningFragment::class) - } - - @Test - fun onResumeShouldReturnCorrectCodeReceivedFromQrCodeScanningWhenPermissionGranted() { - shadowOf(applicationContext).grantPermissions(Manifest.permission.CAMERA) - mockkConstructor(LiveBarcodeScanningFragment::class) - val sampleBarcodeResult = "13462889" - var receivedCode: String? = null - - hiltActivityForTestScenario().use { scenario -> - scenario.onActivity { activity -> - val activityFragmentManager = activity.supportFragmentManager - every { - anyConstructed().show(any(), any()) - } answers - { - activityFragmentManager.setFragmentResult( - LiveBarcodeScanningFragment.RESULT_REQUEST_KEY, - bundleOf(LiveBarcodeScanningFragment.RESULT_REQUEST_KEY to sampleBarcodeResult), - ) - } - activityFragmentManager.setFragmentResultListener( - QrCodeCameraDialogFragment.RESULT_REQUEST_KEY, - activity, - ) { _, result -> - val code = result.getString(QrCodeCameraDialogFragment.RESULT_REQUEST_KEY) - Assert.assertEquals(sampleBarcodeResult, code) - receivedCode = code - } - - activityFragmentManager.commitNow { - add(QrCodeCameraDialogFragment(), QrCodeCameraDialogFragmentTest::class.java.simpleName) - } - - Assert.assertNotNull(receivedCode) - Assert.assertEquals(sampleBarcodeResult, receivedCode) - } - } - - unmockkConstructor(LiveBarcodeScanningFragment::class) - } - - @Test - fun onResumeShouldLaunchCameraPermissionRequestWhenPermissionDenied() { - shadowOf(applicationContext).denyPermissions(Manifest.permission.CAMERA) - hiltActivityForTestScenario().use { scenario -> - scenario.onActivity { activity -> - val qrCodeFragment = QrCodeCameraDialogFragment() - val cameraPermissionRequestSpy = spyk(qrCodeFragment.cameraPermissionRequest) - ReflectionHelpers.setField( - qrCodeFragment, - "cameraPermissionRequest", - cameraPermissionRequestSpy, - ) - - activity.supportFragmentManager.commitNow { - add(qrCodeFragment, QrCodeCameraDialogFragmentTest::class.java.simpleName) - } - verify { cameraPermissionRequestSpy.launch(Manifest.permission.CAMERA) } - } - } - unmockkStatic(Toast::class) - } -} diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragmentTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragmentTest.kt new file mode 100644 index 0000000000..efc3203659 --- /dev/null +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/scan/QRCodeScannerDialogFragmentTest.kt @@ -0,0 +1,146 @@ +/* + * Copyright 2021-2024 Ona Systems, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.smartregister.fhircore.quest.ui.sdc.qrCode.scan + +import android.Manifest +import android.app.Application +import androidx.core.graphics.toRect +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks +import androidx.test.core.app.ApplicationProvider +import com.google.mlkit.vision.barcode.BarcodeScanner +import com.google.mlkit.vision.barcode.BarcodeScannerOptions +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.barcode.common.Barcode +import com.google.mlkit.vision.interfaces.Detector +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkConstructor +import io.mockk.mockkStatic +import io.mockk.runs +import io.mockk.unmockkConstructor +import io.mockk.unmockkStatic +import io.mockk.verify +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.robolectric.Shadows.shadowOf +import org.smartregister.fhircore.quest.hiltActivityForTestScenario +import org.smartregister.fhircore.quest.robolectric.RobolectricTest +import org.smartregister.fhircore.quest.ui.sdc.qrCode.CameraPermissionsDialogFragment + +@HiltAndroidTest +class QRCodeScannerDialogFragmentTest : RobolectricTest() { + @get:Rule(order = 0) var hiltAndroidRule = HiltAndroidRule(this) + + private val application = ApplicationProvider.getApplicationContext() + + @Before + fun setUp() { + hiltAndroidRule.inject() + } + + @Before + fun setUpQRCodeScannerDialogFragmentMocks() { + val barcodeScanner = + mockk() { + every { detectorType } returns Detector.TYPE_BARCODE_SCANNING + every { close() } just runs + } + mockkStatic(BarcodeScanning::class) + every { BarcodeScanning.getClient(any()) } returns barcodeScanner + mockkConstructor(CameraPermissionsDialogFragment::class) + every { + anyConstructed().show(any(), any()) + } just runs + } + + @After + fun unSetUpQRCodeScannerDialogFragmentMocks() { + unmockkConstructor(CameraPermissionsDialogFragment::class) + unmockkStatic(BarcodeScanning::class) + } + + @Test + fun shouldShowQrCodeCameraPermissionsDialogWhenNoPermission() { + shadowOf(application).denyPermissions(Manifest.permission.CAMERA) + + hiltActivityForTestScenario().use { scenario -> + scenario.onActivity { activity -> + QRCodeScannerDialogFragment() + .show( + activity.supportFragmentManager, + "shouldShowQrCodeCameraPermissionsDialogWhenNoPermission", + ) + } + } + + verify { + anyConstructed().show(any(), any()) + } + } + + @Test + fun shouldSetFragmentWhenBarCodeDetectedWithinBounds() { + shadowOf(application).grantPermissions(Manifest.permission.CAMERA) + + var barcodeValueResult: String? = null + hiltActivityForTestScenario().use { scenario -> + scenario.onActivity { activity -> + QRCodeScannerDialogFragment() + .show( + activity.supportFragmentManager, + "shouldShowQrCodeCameraPermissionsDialogWhenNoPermission", + ) + activity.supportFragmentManager.setFragmentResultListener( + QRCodeScannerDialogFragment.RESULT_REQUEST_KEY, + activity, + ) { _, result -> + barcodeValueResult = result.getString(QRCodeScannerDialogFragment.RESULT_REQUEST_KEY)!! + } + + activity.supportFragmentManager.registerFragmentLifecycleCallbacks( + object : FragmentLifecycleCallbacks() { + override fun onFragmentResumed(fm: FragmentManager, f: Fragment) { + super.onFragmentResumed(fm, f) + if (f is QRCodeScannerDialogFragment) { + val sampleBarcodeWithinBounds = mockk() + every { sampleBarcodeWithinBounds.boundingBox } returns + f.viewFinderBounds.toRect().apply { + bottom -= 20 + right -= 20 + } + every { sampleBarcodeWithinBounds.rawValue } returns + "ad2ae0df-01dd-4e65-a3ee-01e3174b5744" + + f.onQrCodeDetected(sampleBarcodeWithinBounds) + } + } + }, + false, + ) + } + } + Assert.assertEquals("ad2ae0df-01dd-4e65-a3ee-01e3174b5744", barcodeValueResult) + } +} diff --git a/android/quest/src/test/java/org/smartregister/fhircore/quest/util/QrCodeScanUtilsTest.kt b/android/quest/src/test/java/org/smartregister/fhircore/quest/util/QrCodeScanUtilsTest.kt index 1787e9d8aa..38a7e6eb74 100644 --- a/android/quest/src/test/java/org/smartregister/fhircore/quest/util/QrCodeScanUtilsTest.kt +++ b/android/quest/src/test/java/org/smartregister/fhircore/quest/util/QrCodeScanUtilsTest.kt @@ -30,7 +30,7 @@ import org.junit.Rule import org.junit.Test import org.smartregister.fhircore.quest.hiltActivityForTestScenario import org.smartregister.fhircore.quest.robolectric.RobolectricTest -import org.smartregister.fhircore.quest.ui.sdc.qrCode.QrCodeCameraDialogFragment +import org.smartregister.fhircore.quest.ui.sdc.qrCode.scan.QRCodeScannerDialogFragment @HiltAndroidTest class QrCodeScanUtilsTest : RobolectricTest() { @@ -39,13 +39,13 @@ class QrCodeScanUtilsTest : RobolectricTest() { @Before fun setUp() { hiltAndroidRule.inject() - mockkConstructor(QrCodeCameraDialogFragment::class) + mockkConstructor(QRCodeScannerDialogFragment::class) } @After override fun tearDown() { super.tearDown() - unmockkConstructor(QrCodeCameraDialogFragment::class) + unmockkConstructor(QRCodeScannerDialogFragment::class) } @Test @@ -57,13 +57,13 @@ class QrCodeScanUtilsTest : RobolectricTest() { scenario.onActivity { activity -> val sampleQrCode = "d84fbd12-4f22-423a-8645-5525504e1bcb" every { - anyConstructed() + anyConstructed() .show(any(), QrCodeScanUtils.QR_CODE_SCAN_UTILS_TAG) } answers { activity.supportFragmentManager.setFragmentResult( - QrCodeCameraDialogFragment.RESULT_REQUEST_KEY, - bundleOf(QrCodeCameraDialogFragment.RESULT_REQUEST_KEY to sampleQrCode), + QRCodeScannerDialogFragment.RESULT_REQUEST_KEY, + bundleOf(QRCodeScannerDialogFragment.RESULT_REQUEST_KEY to sampleQrCode), ) } QrCodeScanUtils.scanQrCode(activity, onQrCodeScanListener) diff --git a/docs/engineering/app/configuring/config-types/forms/questionnaire.mdx b/docs/engineering/app/configuring/config-types/forms/questionnaire.mdx index c71464ab21..225be946ae 100644 --- a/docs/engineering/app/configuring/config-types/forms/questionnaire.mdx +++ b/docs/engineering/app/configuring/config-types/forms/questionnaire.mdx @@ -552,7 +552,7 @@ Below is the specific extension for this. The extension is validated in this cla ## QR Code Support -QR Code widget can be set up for a Questionnaire by adding `qr_code-widget` extension to a QuestionnaireItem +QR Code widget can be set up for a Questionnaire by adding `qr_code-widget` extension, with url `https://github.com/opensrp/android-fhir/StructureDefinition/qr-code-widget`, to a QuestionnaireItem ```json { @@ -560,22 +560,22 @@ QR Code widget can be set up for a Questionnaire by adding `qr_code-widget` exte "extension": [] } ``` -The QR Code widget can also be configured to allow only setting the QR code and then have the field as readOnly by using `qr-code-entry-mode` extension +The QR Code widget extension can be configured to take another extension with url `set-only-readonly` that takes in a value `Boolean`, which when set to `true`, the QR code widget only allows set QR code once and thereafter the field would behave as `readOnly` ```json { "url": "https://github.com/opensrp/android-fhir/StructureDefinition/qr-code-widget", "extension": [ { - "url": "qr-code-entry-mode", - "valueString": "set-only-readonly" + "url": "set-only-readonly", + "valueBoolean": true } ] } ``` -Other option for the `qr-code-entry-mode` extension is `"normal"` whereby the widget would allow a new scan to repopulate the field +Normal behaviour of the `qr_code-widget` extension or if the `set-only-readonly` extension has a value of `false`, would be to allow setting QR code multiple times whereby subsequent QR codes would replace current -The QR code widget supports adding an arbitrary number of QR codes by setting QuestionnaireItem to `"repeats": true` +The QR code widget supports adding an arbitrary number of QR codes, implemented by showing `+Add QR Code` button. This can be configured by setting QuestionnaireItem with the `qr_code-widget` extension to `"repeats": true` ```json "repeats": true, @@ -584,11 +584,12 @@ The QR code widget supports adding an arbitrary number of QR codes by setting Qu "url": "https://github.com/opensrp/android-fhir/StructureDefinition/qr-code-widget", "extension": [ { - "url": "qr-code-entry-mode", - "valueString": "set-only-readonly" + "url": "set-only-readonly", + "valueBoolean": true } ] } ] } ``` +The extension's implementation can be found [here](https://github.com/opensrp/fhircore/blob/main/android/quest/src/main/java/org/smartregister/fhircore/quest/ui/sdc/qrCode/EditTextQrCodeViewHolderFactory.kt) \ No newline at end of file