@@ -6,12 +6,14 @@ import androidx.compose.runtime.LaunchedEffect
66import androidx.lifecycle.LifecycleOwner
77import androidx.navigation.NavController
88import com.stripe.android.identity.analytics.IdentityAnalyticsRequestFactory
9+ import com.stripe.android.identity.camera.IdentityAggregator
910import com.stripe.android.identity.camera.IdentityCameraManager
1011import com.stripe.android.identity.ml.FaceDetectorOutput
1112import com.stripe.android.identity.ml.IDDetectorOutput
1213import com.stripe.android.identity.navigation.CouldNotCaptureDestination
1314import com.stripe.android.identity.navigation.navigateTo
1415import com.stripe.android.identity.networking.models.VerificationPage
16+ import com.stripe.android.identity.states.FaceDetectorTransitioner
1517import com.stripe.android.identity.states.IdentityScanState.Companion.isBack
1618import com.stripe.android.identity.states.IdentityScanState.Companion.isFront
1719import com.stripe.android.identity.viewmodel.IdentityScanViewModel
@@ -33,60 +35,26 @@ internal fun LiveCaptureLaunchedEffect(
3335 cameraManager : IdentityCameraManager ? = null
3436) {
3537 LaunchedEffect (scannerState) {
36- if (scannerState is IdentityScanViewModel .State .Scanned ) {
37- val scanResult = scannerState.result
38- // Capture selfie virtual camera flag while camera is still bound
39- if (scanResult.result is FaceDetectorOutput ) {
40- identityViewModel.setSelfieIsVirtualCamera(cameraManager?.isVirtualCamera())
38+ when (scannerState) {
39+ is IdentityScanViewModel .State .Scanned -> {
40+ handleScannedState(
41+ scannerState = scannerState,
42+ identityScanViewModel = identityScanViewModel,
43+ identityViewModel = identityViewModel,
44+ lifecycleOwner = lifecycleOwner,
45+ verificationPage = verificationPage,
46+ navController = navController,
47+ cameraManager = cameraManager
48+ )
4149 }
42- identityScanViewModel.stopScan(lifecycleOwner)
43-
44- // Set camera metadata right before uploading
45- cameraManager?.getCameraLensModel()?.let { identityViewModel.setCameraLensModel(it) }
46- cameraManager?.getExposureIso()?.let { identityViewModel.setCameraExposureIso(it) }
47- cameraManager?.getFocalLength()?.let { identityViewModel.setCameraFocalLength(it) }
48- cameraManager?.getExposureDuration()?.let { identityViewModel.setCameraExposureDuration(it) }
49- cameraManager?.isVirtualCamera()?.let { identityViewModel.setIsVirtualCamera(it) }
50-
51- identityViewModel.uploadScanResult(
52- scanResult,
53- verificationPage
54- )
55- when (val detectorOutput = scanResult.result) {
56- is FaceDetectorOutput -> {
57- identityViewModel.updateAnalyticsState { oldState ->
58- oldState.copy(selfieModelScore = detectorOutput.resultScore)
59- }
60- }
61- is IDDetectorOutput -> {
62- if (scanResult.identityState.type.isFront()) {
63- identityViewModel.updateAnalyticsState { oldState ->
64- oldState.copy(
65- docFrontModelScore = detectorOutput.resultScore,
66- docFrontBlurScore = detectorOutput.blurScore
67- )
68- }
69- } else if (scanResult.identityState.type.isBack()) {
70- identityViewModel.updateAnalyticsState { oldState ->
71- oldState.copy(
72- docBackModelScore = detectorOutput.resultScore,
73- docBackBlurScore = detectorOutput.blurScore
74- )
75- }
76- }
77- }
50+ is IdentityScanViewModel .State .Timeout -> {
51+ handleTimeoutState(
52+ scannerState = scannerState,
53+ identityViewModel = identityViewModel,
54+ navController = navController
55+ )
7856 }
79- } else if (scannerState is IdentityScanViewModel .State .Timeout ) {
80- identityViewModel.screenTracker.screenTransitionStart(
81- identityViewModel.analyticsLastScreenName ? : if (scannerState.fromSelfie) {
82- IdentityAnalyticsRequestFactory .SCREEN_NAME_SELFIE
83- } else {
84- IdentityAnalyticsRequestFactory .SCREEN_NAME_LIVE_CAPTURE
85- }
86- )
87- navController.navigateTo(
88- CouldNotCaptureDestination (fromSelfie = scannerState.fromSelfie)
89- )
57+ else -> Unit
9058 }
9159 }
9260
@@ -96,3 +64,99 @@ internal fun LiveCaptureLaunchedEffect(
9664 }
9765 }
9866}
67+
68+ private suspend fun handleScannedState (
69+ scannerState : IdentityScanViewModel .State .Scanned ,
70+ identityScanViewModel : IdentityScanViewModel ,
71+ identityViewModel : IdentityViewModel ,
72+ lifecycleOwner : LifecycleOwner ,
73+ verificationPage : VerificationPage ,
74+ navController : NavController ,
75+ cameraManager : IdentityCameraManager ?
76+ ) {
77+ val scanResult = scannerState.result
78+ val detectorOutput = scanResult.result
79+ val isSelfieResult = detectorOutput is FaceDetectorOutput
80+
81+ if (isSelfieResult) {
82+ identityViewModel.setSelfieIsVirtualCamera(cameraManager?.isVirtualCamera())
83+ }
84+ identityScanViewModel.stopScan(lifecycleOwner)
85+ identityViewModel.setCameraMetadata(cameraManager)
86+
87+ if (isSelfieResult) {
88+ identityViewModel.clearSelfieUploadedState()
89+ }
90+ identityViewModel.uploadScanResult(scanResult, verificationPage)
91+
92+ when (detectorOutput) {
93+ is FaceDetectorOutput -> {
94+ identityViewModel.handleFaceDetectorOutput(detectorOutput, scanResult, navController)
95+ }
96+ is IDDetectorOutput -> {
97+ identityViewModel.handleIdDetectorOutput(detectorOutput, scanResult)
98+ }
99+ }
100+ }
101+
102+ private fun IdentityViewModel.setCameraMetadata (cameraManager : IdentityCameraManager ? ) {
103+ cameraManager?.getCameraLensModel()?.let { setCameraLensModel(it) }
104+ cameraManager?.getExposureIso()?.let { setCameraExposureIso(it) }
105+ cameraManager?.getFocalLength()?.let { setCameraFocalLength(it) }
106+ cameraManager?.getExposureDuration()?.let { setCameraExposureDuration(it) }
107+ cameraManager?.isVirtualCamera()?.let { setIsVirtualCamera(it) }
108+ }
109+
110+ private suspend fun IdentityViewModel.handleFaceDetectorOutput (
111+ detectorOutput : FaceDetectorOutput ,
112+ scanResult : IdentityAggregator .FinalResult ,
113+ navController : NavController
114+ ) {
115+ updateAnalyticsState { oldState ->
116+ oldState.copy(selfieModelScore = detectorOutput.resultScore)
117+ }
118+ (scanResult.identityState.transitioner as ? FaceDetectorTransitioner )?.let {
119+ collectDataForSelfieScreen(
120+ navController = navController,
121+ faceDetectorTransitioner = it
122+ )
123+ }
124+ }
125+
126+ private fun IdentityViewModel.handleIdDetectorOutput (
127+ detectorOutput : IDDetectorOutput ,
128+ scanResult : IdentityAggregator .FinalResult
129+ ) {
130+ if (scanResult.identityState.type.isFront()) {
131+ updateAnalyticsState { oldState ->
132+ oldState.copy(
133+ docFrontModelScore = detectorOutput.resultScore,
134+ docFrontBlurScore = detectorOutput.blurScore
135+ )
136+ }
137+ } else if (scanResult.identityState.type.isBack()) {
138+ updateAnalyticsState { oldState ->
139+ oldState.copy(
140+ docBackModelScore = detectorOutput.resultScore,
141+ docBackBlurScore = detectorOutput.blurScore
142+ )
143+ }
144+ }
145+ }
146+
147+ private fun handleTimeoutState (
148+ scannerState : IdentityScanViewModel .State .Timeout ,
149+ identityViewModel : IdentityViewModel ,
150+ navController : NavController
151+ ) {
152+ identityViewModel.screenTracker.screenTransitionStart(
153+ identityViewModel.analyticsLastScreenName ? : if (scannerState.fromSelfie) {
154+ IdentityAnalyticsRequestFactory .SCREEN_NAME_SELFIE
155+ } else {
156+ IdentityAnalyticsRequestFactory .SCREEN_NAME_LIVE_CAPTURE
157+ }
158+ )
159+ navController.navigateTo(
160+ CouldNotCaptureDestination (fromSelfie = scannerState.fromSelfie)
161+ )
162+ }
0 commit comments