Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions feature/external-credential/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
12 changes: 12 additions & 0 deletions feature/external-credential/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
id("simprints.feature")
id("kotlin-parcelize")
}

android {
namespace = "com.simprints.feature.externalcredential"
}

dependencies {
implementation(project(":feature:exit-form"))
}
4 changes: 4 additions & 0 deletions feature/external-credential/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.simprints.feature.externalcredential

import com.simprints.core.domain.common.FlowType
import com.simprints.feature.externalcredential.model.ExternalCredentialParams

object ExternalCredentialContract {
val DESTINATION = R.id.externalCredentialControllerFragment

fun getParams(subjectId: String?, flowType: FlowType) = ExternalCredentialParams(subjectId = subjectId, flowType = flowType)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.simprints.feature.externalcredential.model

import androidx.annotation.Keep
import com.simprints.core.domain.common.FlowType
import com.simprints.core.domain.step.StepParams

@Keep
data class ExternalCredentialParams(
val subjectId: String?,
val flowType: FlowType
) : StepParams
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.simprints.feature.externalcredential.screens.controller

import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.simprints.feature.exitform.ExitFormContract
import com.simprints.feature.exitform.ExitFormResult
import com.simprints.feature.externalcredential.GraphExternalCredentialInternalDirections
import com.simprints.feature.externalcredential.R
import com.simprints.infra.uibase.navigation.finishWithResult
import com.simprints.infra.uibase.navigation.handleResult
import com.simprints.infra.uibase.navigation.navigateSafely
import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue

@AndroidEntryPoint
internal class ExternalCredentialControllerFragment : Fragment(R.layout.fragment_external_credential_controller) {
private val args: ExternalCredentialControllerFragmentArgs by navArgs()

private val hostFragment: Fragment?
get() = childFragmentManager.findFragmentById(R.id.external_credential_host_fragment)

private val internalNavController: NavController?
get() = hostFragment?.findNavController()

private val currentlyDisplayedInternalFragment: Fragment?
get() = hostFragment?.childFragmentManager?.fragments?.first()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

findNavController().handleResult<ExitFormResult>(
this,
R.id.externalCredentialControllerFragment,
ExitFormContract.DESTINATION,
) {
val option = it.submittedOption()
if (option != null) {
findNavController().finishWithResult(this, it)
} else {
internalNavController?.navigateSafely(
currentlyDisplayedInternalFragment,
GraphExternalCredentialInternalDirections.actionGlobalExternalCredentialSelect()
)
}
}
internalNavController?.setGraph(R.navigation.graph_external_credential_internal)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.simprints.feature.externalcredential.screens.scanocr

import androidx.fragment.app.Fragment
import com.simprints.feature.externalcredential.R
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
internal class ExternalCredentialScanOcrFragment : Fragment(R.layout.fragment_external_credential_scan_ocr) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.simprints.feature.externalcredential.screens.scanqr

import androidx.fragment.app.Fragment
import com.simprints.feature.externalcredential.R
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
internal class ExternalCredentialScanQrFragment : Fragment(R.layout.fragment_external_credential_scan_qr) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.simprints.feature.externalcredential.screens.search

import androidx.fragment.app.Fragment
import com.simprints.feature.externalcredential.R
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
internal class ExternalCredentialSearchFragment : Fragment(R.layout.fragment_external_credential_search) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.simprints.feature.externalcredential.screens.select

import androidx.fragment.app.Fragment
import com.simprints.feature.externalcredential.R
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
internal class ExternalCredentialSelectFragment : Fragment(R.layout.fragment_external_credential_select) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.simprints.feature.externalcredential.screens.skip

import androidx.fragment.app.Fragment
import com.simprints.feature.externalcredential.R
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class ExternalCredentialSkipFragment : Fragment(R.layout.fragment_external_credential_skip) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>

<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/external_credential_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!--TODO [MS-1127] add content-->
<TextView
android:text="OCR scanner"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--TODO [MS-1127] add content-->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="QR scanner" />

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--TODO [MS-1127] add content-->
<TextView
android:text="Credential Search"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!--TODO [MS-1127] add content-->
<TextView
android:text="Credential Selection fragment"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--TODO [MS-1127] add content-->
<TextView
android:text="Skip Credential scan"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/graph_external_credential"
app:startDestination="@id/externalCredentialControllerFragment">

<fragment
android:id="@+id/externalCredentialControllerFragment"
android:name="com.simprints.feature.externalcredential.screens.controller.ExternalCredentialControllerFragment"
android:label="ExternalCredentialController">
<argument
android:name="externalCredentialParams"
app:argType="com.simprints.feature.externalcredential.model.ExternalCredentialParams" />
</fragment>

<include app:graph="@navigation/graph_exit_form" />
<action
android:id="@+id/action_global_refusalFragment"
app:destination="@+id/graph_exit_form" />
</navigation>
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/graph_external_credential_internal"
app:startDestination="@id/externalCredentialSelectFragment">

<fragment
android:id="@+id/externalCredentialSelectFragment"
android:name="com.simprints.feature.externalcredential.screens.select.ExternalCredentialSelectFragment"
android:label="fragment_external_credential_select"
tools:layout="@layout/fragment_external_credential_select">
<action
android:id="@+id/action_externalCredentialSelectFragment_to_externalCredentialScanQr"
app:destination="@+id/externalCredentialScanQr"
app:popUpTo="@+id/graph_external_credential_internal"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_externalCredentialSelectFragment_to_externalCredentialScanOcr"
app:destination="@+id/externalCredentialScanOcr"
app:popUpTo="@+id/graph_external_credential_internal"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_externalCredentialSelectFragment_to_externalCredentialSkip"
app:destination="@+id/externalCredentialSkip"
app:popUpTo="@+id/graph_external_credential_internal"
app:popUpToInclusive="true" />
</fragment>

<fragment
android:id="@+id/externalCredentialScanQr"
android:name="com.simprints.feature.externalcredential.screens.scanqr.ExternalCredentialScanQrFragment"
android:label="ExternalCredentialScanQrFragment"
tools:layout="@layout/fragment_external_credential_scan_qr">
</fragment>

<fragment
android:id="@+id/externalCredentialSearch"
android:name="com.simprints.feature.externalcredential.screens.search.ExternalCredentialSearchFragment"
android:label="ExternalCredentialSearchFragment"
tools:layout="@layout/fragment_external_credential_search">
</fragment>

<fragment
android:id="@+id/externalCredentialScanOcr"
android:name="com.simprints.feature.externalcredential.screens.scanocr.ExternalCredentialScanOcrFragment"
android:label="ExternalCredentialScanOcrFragment"
tools:layout="@layout/fragment_external_credential_scan_ocr">
</fragment>

<fragment
android:id="@+id/externalCredentialSkip"
android:name="com.simprints.feature.externalcredential.screens.skip.ExternalCredentialSkipFragment"
android:label="ExternalCredentialSkipFragment"
tools:layout="@layout/fragment_external_credential_skip">
</fragment>

<action
android:id="@+id/action_global_external_credential_select"
app:destination="@+id/externalCredentialSelectFragment"
app:popUpTo="@+id/graph_external_credential_internal"
app:popUpToInclusive="true" />

</navigation>
1 change: 1 addition & 0 deletions feature/orchestrator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies {
implementation(project(":feature:matcher"))
implementation(project(":feature:validate-subject-pool"))
implementation(project(":feature:select-subject-age-group"))
implementation(project(":feature:external-credential"))

implementation(project(":face:capture"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import com.simprints.matcher.MatchParams
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.io.Serializable
import java.util.UUID
import javax.inject.Inject

@HiltViewModel
Expand All @@ -61,6 +62,9 @@ internal class OrchestratorViewModel @Inject constructor(
private val mapStepsForLastBiometrics: MapStepsForLastBiometricEnrolUseCase,
) : ViewModel() {
var isRequestProcessed = false

// [MS-1127] MF-ID: during enrolment, the same 'subjectId' needs to be used during the entire workflow
private val enrolmentSubjectId = UUID.randomUUID().toString()
private var modalities = emptySet<GeneralConfiguration.Modality>()
private var steps = emptyList<Step>()
private var actionRequest: ActionRequest? = null
Expand All @@ -83,7 +87,11 @@ internal class OrchestratorViewModel @Inject constructor(
// In case of a follow-up action, we should restore completed steps from cache
// and add new ones to the list. This way all session steps are available throughout
// the app for reference (i.e. have we already captured face in this session?)
steps = cache.steps + stepsBuilder.build(action, projectConfiguration)
steps = cache.steps + stepsBuilder.build(
action = action,
projectConfiguration = projectConfiguration,
enrolmentSubjectId = enrolmentSubjectId
)
Simber.i("Steps to execute: ${steps.joinToString { it.id.toString() }}", tag = ORCHESTRATION)
} catch (_: SubjectAgeNotSupportedException) {
handleErrorResponse(AppErrorResponse(AppErrorReason.AGE_GROUP_NOT_SUPPORTED))
Expand Down Expand Up @@ -115,9 +123,10 @@ internal class OrchestratorViewModel @Inject constructor(

if (result is SelectSubjectAgeGroupResult) {
val captureAndMatchSteps = stepsBuilder.buildCaptureAndMatchStepsForAgeGroup(
actionRequest!!,
projectConfiguration,
result.ageGroup,
action = actionRequest!!,
projectConfiguration = projectConfiguration,
ageGroup = result.ageGroup,
enrolmentSubjectId = enrolmentSubjectId
)
steps = steps + captureAndMatchSteps
}
Expand Down Expand Up @@ -195,10 +204,11 @@ internal class OrchestratorViewModel @Inject constructor(
val projectConfiguration = configManager.getProjectConfiguration()
val project = configManager.getProject(projectConfiguration.projectId)
val appResponse = appResponseBuilder(
projectConfiguration,
actionRequest,
steps.mapNotNull { it.result },
project,
projectConfiguration = projectConfiguration,
request = actionRequest,
results = steps.mapNotNull { it.result },
project = project,
enrolmentSubjectId = enrolmentSubjectId,
)

updateDailyActivity(appResponse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal object StepId {
const val CONFIRM_IDENTITY = STEP_BASE_CORE + 5
const val VALIDATE_ID_POOL = STEP_BASE_CORE + 6
const val SELECT_SUBJECT_AGE = STEP_BASE_CORE + 7
const val EXTERNAL_CREDENTIAL = STEP_BASE_CORE + 8

// Face step ids
private const val STEP_BASE_FINGERPRINT = 300
Expand Down
Loading