@smile_identity/react-native 10.1.11 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +4 -4
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/smileidentity/react/SmileIdPackage.kt +5 -0
- package/android/src/main/java/com/smileidentity/react/results/DocumentCaptureResult.kt +12 -0
- package/android/src/main/java/com/smileidentity/react/results/SmartSelfieCaptureResult.kt +11 -0
- package/android/src/main/java/com/smileidentity/react/utils/DocumentCaptureResultAdapter.kt +98 -0
- package/android/src/main/java/com/smileidentity/react/utils/SelfieCaptureResultAdapter.kt +78 -0
- package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDDocumentCaptureViewManager.kt +65 -0
- package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDSmartSelfieCaptureViewManager.kt +63 -0
- package/android/src/main/java/com/smileidentity/react/views/SmileIDBiometricKYCView.kt +26 -15
- package/android/src/main/java/com/smileidentity/react/views/SmileIDDocumentCaptureView.kt +102 -0
- package/android/src/main/java/com/smileidentity/react/views/SmileIDDocumentVerificationView.kt +28 -15
- package/android/src/main/java/com/smileidentity/react/views/SmileIDEnhancedDocumentVerificationView.kt +28 -15
- package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieAuthenticationView.kt +26 -16
- package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieCaptureView.kt +209 -0
- package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieEnrollmentView.kt +26 -16
- package/android/src/main/java/com/smileidentity/react/views/SmileIDView.kt +7 -2
- package/ios/RNSmileID.swift +1 -1
- package/ios/SmileId.xcodeproj/xcuserdata/japhetndhlovu.xcuserdatad/xcschemes/SmileId.xcscheme +23 -0
- package/ios/SmileId.xcodeproj/xcuserdata/japhetndhlovu.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/ios/Utils/FileUtils.swift +24 -0
- package/ios/View/SmileIDBiometricKYCView.swift +54 -51
- package/ios/View/SmileIDDocumentCaptureView.swift +82 -0
- package/ios/View/SmileIDDocumentVerificationView.swift +50 -47
- package/ios/View/SmileIDEnhancedDocumentVerificationView.swift +49 -47
- package/ios/View/SmileIDSmartSelfieAuthView.swift +35 -33
- package/ios/View/SmileIDSmartSelfieCaptureView.swift +71 -0
- package/ios/View/SmileIDSmartSelfieEnrollmentView.swift +35 -33
- package/ios/ViewManagers/SmileIDDocumentCaptureViewManager.m +7 -0
- package/ios/ViewManagers/SmileIDDocumentCaptureViewManager.swift +29 -0
- package/ios/ViewManagers/SmileIDSmartSelfieCaptureViewManager.m +7 -0
- package/ios/ViewManagers/SmileIDSmartSelfieCaptureViewManager.swift +36 -0
- package/ios/ViewModels/SmileIDProductModel.swift +2 -0
- package/lib/commonjs/SmileIDDocumentCaptureView.js +40 -0
- package/lib/commonjs/SmileIDDocumentCaptureView.js.map +1 -0
- package/lib/commonjs/SmileIDSmartSelfieCaptureView.js +40 -0
- package/lib/commonjs/SmileIDSmartSelfieCaptureView.js.map +1 -0
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/SmileIDDocumentCaptureView.js +30 -0
- package/lib/module/SmileIDDocumentCaptureView.js.map +1 -0
- package/lib/module/SmileIDSmartSelfieCaptureView.js +30 -0
- package/lib/module/SmileIDSmartSelfieCaptureView.js.map +1 -0
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/NativeSmileId.d.ts.map +1 -0
- package/lib/typescript/SmileIDBiometricKYCView.d.ts.map +1 -0
- package/lib/typescript/SmileIDConsentView.d.ts.map +1 -0
- package/lib/typescript/SmileIDDocumentCaptureView.d.ts +8 -0
- package/lib/typescript/SmileIDDocumentCaptureView.d.ts.map +1 -0
- package/lib/typescript/SmileIDDocumentVerificationView.d.ts.map +1 -0
- package/lib/typescript/SmileIDEnhancedDocumentVerificationView.d.ts.map +1 -0
- package/lib/typescript/SmileIDSmartSelfieAuthenticationView.d.ts.map +1 -0
- package/lib/typescript/SmileIDSmartSelfieCaptureView.d.ts +8 -0
- package/lib/typescript/SmileIDSmartSelfieCaptureView.d.ts.map +1 -0
- package/lib/typescript/SmileIDSmartSelfieEnrollmentView.d.ts.map +1 -0
- package/lib/typescript/{src/index.d.ts → index.d.ts} +3 -1
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/{src/types.d.ts → types.d.ts} +13 -2
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +1 -1
- package/react-native-smile-id.podspec +1 -1
- package/src/SmileIDDocumentCaptureView.tsx +44 -0
- package/src/SmileIDSmartSelfieCaptureView.tsx +44 -0
- package/src/index.tsx +4 -0
- package/src/types.ts +21 -2
- package/lib/typescript/src/NativeSmileId.d.ts.map +0 -1
- package/lib/typescript/src/SmileIDBiometricKYCView.d.ts.map +0 -1
- package/lib/typescript/src/SmileIDConsentView.d.ts.map +0 -1
- package/lib/typescript/src/SmileIDDocumentVerificationView.d.ts.map +0 -1
- package/lib/typescript/src/SmileIDEnhancedDocumentVerificationView.d.ts.map +0 -1
- package/lib/typescript/src/SmileIDSmartSelfieAuthenticationView.d.ts.map +0 -1
- package/lib/typescript/src/SmileIDSmartSelfieEnrollmentView.d.ts.map +0 -1
- package/lib/typescript/src/index.d.ts.map +0 -1
- package/lib/typescript/src/types.d.ts.map +0 -1
- /package/lib/typescript/{src/NativeSmileId.d.ts → NativeSmileId.d.ts} +0 -0
- /package/lib/typescript/{src/SmileIDBiometricKYCView.d.ts → SmileIDBiometricKYCView.d.ts} +0 -0
- /package/lib/typescript/{src/SmileIDConsentView.d.ts → SmileIDConsentView.d.ts} +0 -0
- /package/lib/typescript/{src/SmileIDDocumentVerificationView.d.ts → SmileIDDocumentVerificationView.d.ts} +0 -0
- /package/lib/typescript/{src/SmileIDEnhancedDocumentVerificationView.d.ts → SmileIDEnhancedDocumentVerificationView.d.ts} +0 -0
- /package/lib/typescript/{src/SmileIDSmartSelfieAuthenticationView.d.ts → SmileIDSmartSelfieAuthenticationView.d.ts} +0 -0
- /package/lib/typescript/{src/SmileIDSmartSelfieEnrollmentView.d.ts → SmileIDSmartSelfieEnrollmentView.d.ts} +0 -0
|
@@ -6,12 +6,12 @@ import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
|
|
6
6
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
7
|
import com.smileidentity.SmileID
|
|
8
8
|
import com.smileidentity.compose.EnhancedDocumentVerificationScreen
|
|
9
|
-
import com.smileidentity.results.
|
|
9
|
+
import com.smileidentity.react.results.DocumentCaptureResult
|
|
10
|
+
import com.smileidentity.react.utils.DocumentCaptureResultAdapter
|
|
10
11
|
import com.smileidentity.results.SmileIDResult
|
|
11
12
|
import com.smileidentity.util.randomJobId
|
|
12
13
|
import com.smileidentity.util.randomUserId
|
|
13
14
|
import kotlinx.collections.immutable.toImmutableMap
|
|
14
|
-
import timber.log.Timber
|
|
15
15
|
|
|
16
16
|
class SmileIDEnhancedDocumentVerificationView(context: ReactApplicationContext) :
|
|
17
17
|
SmileIDView(context) {
|
|
@@ -44,24 +44,37 @@ class SmileIDEnhancedDocumentVerificationView(context: ReactApplicationContext)
|
|
|
44
44
|
allowGalleryUpload = allowGalleryUpload,
|
|
45
45
|
captureBothSides = captureBothSides,
|
|
46
46
|
extraPartnerParams = (extraPartnerParams ?: mapOf()).toImmutableMap(),
|
|
47
|
-
) {
|
|
48
|
-
when (
|
|
47
|
+
) { res ->
|
|
48
|
+
when (res) {
|
|
49
49
|
is SmileIDResult.Success -> {
|
|
50
|
-
val
|
|
50
|
+
val result =
|
|
51
|
+
DocumentCaptureResult(
|
|
52
|
+
selfieFile = res.data.selfieFile,
|
|
53
|
+
documentFrontFile = res.data.documentFrontFile,
|
|
54
|
+
livenessFiles = res.data.livenessFiles,
|
|
55
|
+
documentBackFile = res.data.documentBackFile,
|
|
56
|
+
didSubmitEnhancedDocVJob = res.data.didSubmitEnhancedDocVJob,
|
|
57
|
+
)
|
|
58
|
+
val newMoshi =
|
|
51
59
|
SmileID.moshi
|
|
52
|
-
.
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
.newBuilder()
|
|
61
|
+
.add(DocumentCaptureResultAdapter.FACTORY)
|
|
62
|
+
.build()
|
|
63
|
+
val json =
|
|
64
|
+
try {
|
|
65
|
+
newMoshi
|
|
66
|
+
.adapter(DocumentCaptureResult::class.java)
|
|
67
|
+
.toJson(result)
|
|
68
|
+
} catch (e: Exception) {
|
|
69
|
+
emitFailure(e)
|
|
70
|
+
return@EnhancedDocumentVerificationScreen
|
|
71
|
+
}
|
|
72
|
+
json?.let { js ->
|
|
73
|
+
emitSuccess(js)
|
|
57
74
|
}
|
|
58
|
-
emitSuccess(json)
|
|
59
75
|
}
|
|
60
76
|
|
|
61
|
-
is SmileIDResult.Error ->
|
|
62
|
-
result.throwable.printStackTrace()
|
|
63
|
-
emitFailure(result.throwable)
|
|
64
|
-
}
|
|
77
|
+
is SmileIDResult.Error -> emitFailure(res.throwable)
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
}
|
package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieAuthenticationView.kt
CHANGED
|
@@ -6,12 +6,12 @@ import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
|
|
6
6
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
7
|
import com.smileidentity.SmileID
|
|
8
8
|
import com.smileidentity.compose.SmartSelfieAuthentication
|
|
9
|
-
import com.smileidentity.results.
|
|
9
|
+
import com.smileidentity.react.results.SmartSelfieCaptureResult
|
|
10
|
+
import com.smileidentity.react.utils.SelfieCaptureResultAdapter
|
|
10
11
|
import com.smileidentity.results.SmileIDResult
|
|
11
12
|
import com.smileidentity.util.randomJobId
|
|
12
13
|
import com.smileidentity.util.randomUserId
|
|
13
14
|
import kotlinx.collections.immutable.toImmutableMap
|
|
14
|
-
import timber.log.Timber
|
|
15
15
|
|
|
16
16
|
class SmileIDSmartSelfieAuthenticationView(context: ReactApplicationContext) :
|
|
17
17
|
SmileIDView(context) {
|
|
@@ -23,30 +23,40 @@ class SmileIDSmartSelfieAuthenticationView(context: ReactApplicationContext) :
|
|
|
23
23
|
CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
|
|
24
24
|
SmileID.SmartSelfieAuthentication(
|
|
25
25
|
userId = userId ?: rememberSaveable { randomUserId() },
|
|
26
|
-
jobId = jobId ?: rememberSaveable { randomJobId() },
|
|
27
26
|
allowAgentMode = allowAgentMode ?: false,
|
|
28
27
|
allowNewEnroll = allowNewEnroll ?: false,
|
|
29
28
|
showAttribution = showAttribution ?: true,
|
|
30
29
|
showInstructions = showInstructions ?: true,
|
|
31
30
|
extraPartnerParams = (extraPartnerParams ?: mapOf()).toImmutableMap(),
|
|
32
|
-
) {
|
|
33
|
-
when (
|
|
31
|
+
) { res ->
|
|
32
|
+
when (res) {
|
|
34
33
|
is SmileIDResult.Success -> {
|
|
35
|
-
val
|
|
34
|
+
val result =
|
|
35
|
+
SmartSelfieCaptureResult(
|
|
36
|
+
selfieFile = res.data.selfieFile,
|
|
37
|
+
livenessFiles = res.data.livenessFiles,
|
|
38
|
+
apiResponse = res.data.apiResponse,
|
|
39
|
+
)
|
|
40
|
+
val newMoshi =
|
|
36
41
|
SmileID.moshi
|
|
37
|
-
.
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
.newBuilder()
|
|
43
|
+
.add(SelfieCaptureResultAdapter.FACTORY)
|
|
44
|
+
.build()
|
|
45
|
+
val json =
|
|
46
|
+
try {
|
|
47
|
+
newMoshi
|
|
48
|
+
.adapter(SmartSelfieCaptureResult::class.java)
|
|
49
|
+
.toJson(result)
|
|
50
|
+
} catch (e: Exception) {
|
|
51
|
+
emitFailure(e)
|
|
52
|
+
return@SmartSelfieAuthentication
|
|
53
|
+
}
|
|
54
|
+
json?.let { js ->
|
|
55
|
+
emitSuccess(js)
|
|
42
56
|
}
|
|
43
|
-
emitSuccess(json)
|
|
44
57
|
}
|
|
45
58
|
|
|
46
|
-
is SmileIDResult.Error ->
|
|
47
|
-
result.throwable.printStackTrace()
|
|
48
|
-
emitFailure(result.throwable)
|
|
49
|
-
}
|
|
59
|
+
is SmileIDResult.Error -> emitFailure(res.throwable)
|
|
50
60
|
}
|
|
51
61
|
}
|
|
52
62
|
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
package com.smileidentity.react.views
|
|
2
|
+
|
|
3
|
+
import android.graphics.BitmapFactory
|
|
4
|
+
import androidx.compose.foundation.background
|
|
5
|
+
import androidx.compose.foundation.layout.Box
|
|
6
|
+
import androidx.compose.foundation.layout.WindowInsets
|
|
7
|
+
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
8
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
9
|
+
import androidx.compose.foundation.layout.statusBars
|
|
10
|
+
import androidx.compose.foundation.layout.windowInsetsPadding
|
|
11
|
+
import androidx.compose.material3.MaterialTheme
|
|
12
|
+
import androidx.compose.material3.Surface
|
|
13
|
+
import androidx.compose.runtime.Composable
|
|
14
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
15
|
+
import androidx.compose.runtime.getValue
|
|
16
|
+
import androidx.compose.runtime.mutableStateOf
|
|
17
|
+
import androidx.compose.runtime.remember
|
|
18
|
+
import androidx.compose.runtime.saveable.rememberSaveable
|
|
19
|
+
import androidx.compose.runtime.setValue
|
|
20
|
+
import androidx.compose.runtime.toMutableStateList
|
|
21
|
+
import androidx.compose.ui.Modifier
|
|
22
|
+
import androidx.compose.ui.graphics.Color
|
|
23
|
+
import androidx.compose.ui.graphics.asImageBitmap
|
|
24
|
+
import androidx.compose.ui.graphics.painter.BitmapPainter
|
|
25
|
+
import androidx.compose.ui.res.stringResource
|
|
26
|
+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
27
|
+
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
|
28
|
+
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
29
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
30
|
+
import com.smileidentity.R
|
|
31
|
+
import com.smileidentity.SmileID
|
|
32
|
+
import com.smileidentity.SmileIDOptIn
|
|
33
|
+
import com.smileidentity.compose.components.ImageCaptureConfirmationDialog
|
|
34
|
+
import com.smileidentity.compose.components.LocalMetadata
|
|
35
|
+
import com.smileidentity.compose.selfie.SelfieCaptureScreen
|
|
36
|
+
import com.smileidentity.compose.selfie.SmartSelfieInstructionsScreen
|
|
37
|
+
import com.smileidentity.compose.theme.colorScheme
|
|
38
|
+
import com.smileidentity.compose.theme.typography
|
|
39
|
+
import com.smileidentity.models.v2.Metadata
|
|
40
|
+
import com.smileidentity.react.results.SmartSelfieCaptureResult
|
|
41
|
+
import com.smileidentity.react.utils.SelfieCaptureResultAdapter
|
|
42
|
+
import com.smileidentity.results.SmileIDResult
|
|
43
|
+
import com.smileidentity.util.randomJobId
|
|
44
|
+
import com.smileidentity.util.randomUserId
|
|
45
|
+
import com.smileidentity.viewmodel.SelfieUiState
|
|
46
|
+
import com.smileidentity.viewmodel.SelfieViewModel
|
|
47
|
+
import com.smileidentity.viewmodel.viewModelFactory
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@OptIn(SmileIDOptIn::class)
|
|
51
|
+
class SmileIDSmartSelfieCaptureView(context: ReactApplicationContext) : SmileIDView(context) {
|
|
52
|
+
var showConfirmation: Boolean = true
|
|
53
|
+
|
|
54
|
+
override fun renderContent() {
|
|
55
|
+
composeView.apply {
|
|
56
|
+
val customViewModelStoreOwner = CustomViewModelStoreOwner()
|
|
57
|
+
setContent {
|
|
58
|
+
CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
|
|
59
|
+
RenderSmartSelfieCaptureContent()
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Composable
|
|
66
|
+
private fun RenderSmartSelfieCaptureContent() {
|
|
67
|
+
val userId = randomUserId()
|
|
68
|
+
val jobId = randomJobId()
|
|
69
|
+
val metadata = LocalMetadata.current
|
|
70
|
+
val viewModel: SelfieViewModel =
|
|
71
|
+
viewModel(
|
|
72
|
+
factory =
|
|
73
|
+
viewModelFactory {
|
|
74
|
+
SelfieViewModel(
|
|
75
|
+
isEnroll = false,
|
|
76
|
+
userId = userId,
|
|
77
|
+
jobId = jobId,
|
|
78
|
+
allowNewEnroll = false,
|
|
79
|
+
skipApiSubmission = true,
|
|
80
|
+
metadata = metadata,
|
|
81
|
+
)
|
|
82
|
+
},
|
|
83
|
+
)
|
|
84
|
+
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
|
|
85
|
+
var acknowledgedInstructions by rememberSaveable { mutableStateOf(false) }
|
|
86
|
+
CompositionLocalProvider(
|
|
87
|
+
LocalMetadata provides remember { Metadata.default().items.toMutableStateList() },
|
|
88
|
+
) {
|
|
89
|
+
MaterialTheme(colorScheme = SmileID.colorScheme, typography = SmileID.typography) {
|
|
90
|
+
Surface(content = {
|
|
91
|
+
when {
|
|
92
|
+
showInstructions && !acknowledgedInstructions -> SmartSelfieInstructionsScreen(
|
|
93
|
+
showAttribution = showAttribution,
|
|
94
|
+
) {
|
|
95
|
+
acknowledgedInstructions = true
|
|
96
|
+
}
|
|
97
|
+
uiState.processingState != null -> HandleProcessingState(viewModel)
|
|
98
|
+
uiState.selfieToConfirm != null ->
|
|
99
|
+
HandleSelfieConfirmation(
|
|
100
|
+
showConfirmation,
|
|
101
|
+
uiState,
|
|
102
|
+
viewModel,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
else -> RenderSelfieCaptureScreen(userId, jobId, allowAgentMode ?: true, viewModel)
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Composable
|
|
113
|
+
private fun RenderSelfieCaptureScreen(
|
|
114
|
+
userId: String,
|
|
115
|
+
jobId: String,
|
|
116
|
+
allowAgentMode: Boolean,
|
|
117
|
+
viewModel: SelfieViewModel,
|
|
118
|
+
) {
|
|
119
|
+
Box(
|
|
120
|
+
modifier =
|
|
121
|
+
Modifier
|
|
122
|
+
.background(color = Color.White)
|
|
123
|
+
.windowInsetsPadding(WindowInsets.statusBars)
|
|
124
|
+
.consumeWindowInsets(WindowInsets.statusBars)
|
|
125
|
+
.fillMaxSize(),
|
|
126
|
+
) {
|
|
127
|
+
SelfieCaptureScreen(
|
|
128
|
+
userId = userId,
|
|
129
|
+
jobId = jobId,
|
|
130
|
+
allowAgentMode = allowAgentMode,
|
|
131
|
+
allowNewEnroll = false,
|
|
132
|
+
skipApiSubmission = true,
|
|
133
|
+
viewModel = viewModel,
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@Composable
|
|
139
|
+
private fun HandleSelfieConfirmation(
|
|
140
|
+
showConfirmation: Boolean,
|
|
141
|
+
uiState: SelfieUiState,
|
|
142
|
+
viewModel: SelfieViewModel,
|
|
143
|
+
) {
|
|
144
|
+
if (showConfirmation) {
|
|
145
|
+
ImageCaptureConfirmationDialog(
|
|
146
|
+
titleText = stringResource(R.string.si_smart_selfie_confirmation_dialog_title),
|
|
147
|
+
subtitleText =
|
|
148
|
+
stringResource(
|
|
149
|
+
R.string.si_smart_selfie_confirmation_dialog_subtitle,
|
|
150
|
+
),
|
|
151
|
+
painter =
|
|
152
|
+
BitmapPainter(
|
|
153
|
+
BitmapFactory
|
|
154
|
+
.decodeFile(uiState.selfieToConfirm!!.absolutePath)
|
|
155
|
+
.asImageBitmap(),
|
|
156
|
+
),
|
|
157
|
+
confirmButtonText =
|
|
158
|
+
stringResource(
|
|
159
|
+
R.string.si_smart_selfie_confirmation_dialog_confirm_button,
|
|
160
|
+
),
|
|
161
|
+
onConfirm = {
|
|
162
|
+
viewModel.submitJob()
|
|
163
|
+
},
|
|
164
|
+
retakeButtonText =
|
|
165
|
+
stringResource(
|
|
166
|
+
R.string.si_smart_selfie_confirmation_dialog_retake_button,
|
|
167
|
+
),
|
|
168
|
+
onRetake = viewModel::onSelfieRejected,
|
|
169
|
+
scaleFactor = 1.25f,
|
|
170
|
+
)
|
|
171
|
+
} else {
|
|
172
|
+
viewModel.submitJob()
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Composable
|
|
177
|
+
private fun HandleProcessingState(viewModel: SelfieViewModel) {
|
|
178
|
+
viewModel.onFinished { res ->
|
|
179
|
+
when (res) {
|
|
180
|
+
is SmileIDResult.Success -> {
|
|
181
|
+
val result =
|
|
182
|
+
SmartSelfieCaptureResult(
|
|
183
|
+
selfieFile = res.data.selfieFile,
|
|
184
|
+
livenessFiles = res.data.livenessFiles,
|
|
185
|
+
)
|
|
186
|
+
val newMoshi =
|
|
187
|
+
SmileID.moshi
|
|
188
|
+
.newBuilder()
|
|
189
|
+
.add(SelfieCaptureResultAdapter.FACTORY)
|
|
190
|
+
.build()
|
|
191
|
+
val json =
|
|
192
|
+
try {
|
|
193
|
+
newMoshi
|
|
194
|
+
.adapter(SmartSelfieCaptureResult::class.java)
|
|
195
|
+
.toJson(result)
|
|
196
|
+
} catch (e: Exception) {
|
|
197
|
+
emitFailure(e)
|
|
198
|
+
return@onFinished
|
|
199
|
+
}
|
|
200
|
+
json?.let { js ->
|
|
201
|
+
emitSuccess(js)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
is SmileIDResult.Error -> emitFailure(res.throwable)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieEnrollmentView.kt
CHANGED
|
@@ -6,12 +6,12 @@ import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
|
|
6
6
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
7
|
import com.smileidentity.SmileID
|
|
8
8
|
import com.smileidentity.compose.SmartSelfieEnrollment
|
|
9
|
-
import com.smileidentity.results.
|
|
9
|
+
import com.smileidentity.react.results.SmartSelfieCaptureResult
|
|
10
|
+
import com.smileidentity.react.utils.SelfieCaptureResultAdapter
|
|
10
11
|
import com.smileidentity.results.SmileIDResult
|
|
11
12
|
import com.smileidentity.util.randomJobId
|
|
12
13
|
import com.smileidentity.util.randomUserId
|
|
13
14
|
import kotlinx.collections.immutable.toImmutableMap
|
|
14
|
-
import timber.log.Timber
|
|
15
15
|
|
|
16
16
|
class SmileIDSmartSelfieEnrollmentView(context: ReactApplicationContext) : SmileIDView(context) {
|
|
17
17
|
|
|
@@ -22,30 +22,40 @@ class SmileIDSmartSelfieEnrollmentView(context: ReactApplicationContext) : Smile
|
|
|
22
22
|
CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
|
|
23
23
|
SmileID.SmartSelfieEnrollment(
|
|
24
24
|
userId = userId ?: rememberSaveable { randomUserId() },
|
|
25
|
-
jobId = jobId ?: rememberSaveable { randomJobId() },
|
|
26
25
|
allowAgentMode = allowAgentMode ?: false,
|
|
27
26
|
allowNewEnroll = allowNewEnroll ?: false,
|
|
28
27
|
showAttribution = showAttribution ?: true,
|
|
29
28
|
showInstructions = showInstructions ?: true,
|
|
30
29
|
extraPartnerParams = (extraPartnerParams ?: mapOf()).toImmutableMap(),
|
|
31
|
-
) {
|
|
32
|
-
when (
|
|
30
|
+
) { res ->
|
|
31
|
+
when (res) {
|
|
33
32
|
is SmileIDResult.Success -> {
|
|
34
|
-
val
|
|
33
|
+
val result =
|
|
34
|
+
SmartSelfieCaptureResult(
|
|
35
|
+
selfieFile = res.data.selfieFile,
|
|
36
|
+
livenessFiles = res.data.livenessFiles,
|
|
37
|
+
apiResponse = res.data.apiResponse,
|
|
38
|
+
)
|
|
39
|
+
val newMoshi =
|
|
35
40
|
SmileID.moshi
|
|
36
|
-
.
|
|
37
|
-
.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
.newBuilder()
|
|
42
|
+
.add(SelfieCaptureResultAdapter.FACTORY)
|
|
43
|
+
.build()
|
|
44
|
+
val json =
|
|
45
|
+
try {
|
|
46
|
+
newMoshi
|
|
47
|
+
.adapter(SmartSelfieCaptureResult::class.java)
|
|
48
|
+
.toJson(result)
|
|
49
|
+
} catch (e: Exception) {
|
|
50
|
+
emitFailure(e)
|
|
51
|
+
return@SmartSelfieEnrollment
|
|
52
|
+
}
|
|
53
|
+
json?.let { js ->
|
|
54
|
+
emitSuccess(js)
|
|
41
55
|
}
|
|
42
|
-
emitSuccess(json)
|
|
43
56
|
}
|
|
44
57
|
|
|
45
|
-
is SmileIDResult.Error ->
|
|
46
|
-
result.throwable.printStackTrace()
|
|
47
|
-
emitFailure(result.throwable)
|
|
48
|
-
}
|
|
58
|
+
is SmileIDResult.Error -> emitFailure(res.throwable)
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
61
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.smileidentity.react.views
|
|
2
2
|
|
|
3
|
+
import android.annotation.SuppressLint
|
|
3
4
|
import android.view.Choreographer
|
|
4
5
|
import android.view.ViewGroup
|
|
5
6
|
import android.widget.LinearLayout
|
|
@@ -10,9 +11,12 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
10
11
|
import com.facebook.react.bridge.ReactContext
|
|
11
12
|
import com.facebook.react.bridge.WritableMap
|
|
12
13
|
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
14
|
+
import com.smileidentity.SmileID
|
|
13
15
|
import com.smileidentity.models.JobType
|
|
16
|
+
import com.smileidentity.react.utils.DocumentCaptureResultAdapter
|
|
14
17
|
import timber.log.Timber
|
|
15
18
|
|
|
19
|
+
@SuppressLint("CheckResult")
|
|
16
20
|
abstract class SmileIDView(context: ReactApplicationContext) : LinearLayout(context) {
|
|
17
21
|
lateinit var composeView: ComposeView
|
|
18
22
|
var userId: String? = null
|
|
@@ -20,8 +24,8 @@ abstract class SmileIDView(context: ReactApplicationContext) : LinearLayout(cont
|
|
|
20
24
|
private var jobType: JobType? = null
|
|
21
25
|
var allowAgentMode: Boolean? = false
|
|
22
26
|
var allowNewEnroll: Boolean? = false
|
|
23
|
-
var showInstructions: Boolean
|
|
24
|
-
var showAttribution: Boolean
|
|
27
|
+
var showInstructions: Boolean = true
|
|
28
|
+
var showAttribution: Boolean = true
|
|
25
29
|
var extraPartnerParams: Map<String, String>? = null
|
|
26
30
|
private var eventEmitter: RCTEventEmitter
|
|
27
31
|
private var productThrowable: Throwable? = null
|
|
@@ -31,6 +35,7 @@ abstract class SmileIDView(context: ReactApplicationContext) : LinearLayout(cont
|
|
|
31
35
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
32
36
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
33
37
|
)
|
|
38
|
+
|
|
34
39
|
eventEmitter = (context as ReactContext).getJSModule(RCTEventEmitter::class.java);
|
|
35
40
|
setLayoutParams(layoutParams)
|
|
36
41
|
orientation = VERTICAL
|
package/ios/RNSmileID.swift
CHANGED
|
@@ -33,7 +33,7 @@ class RNSmileID: NSObject {
|
|
|
33
33
|
)
|
|
34
34
|
resolve(nil)
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
@objc(initialize:withResolver:withRejecter:)
|
|
38
38
|
func initialize(useSandBox: Bool, resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
|
|
39
39
|
SmileID.initialize(useSandbox: useSandBox)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<Scheme
|
|
3
|
+
version = "1.3">
|
|
4
|
+
<BuildAction>
|
|
5
|
+
<BuildActionEntries>
|
|
6
|
+
<BuildActionEntry
|
|
7
|
+
buildForRunning = "YES">
|
|
8
|
+
<BuildableReference
|
|
9
|
+
BuildableIdentifier = "primary"
|
|
10
|
+
BlueprintIdentifier = "58B511DA1A9E6C8500147676"
|
|
11
|
+
BuildableName = "libSmileId.a"
|
|
12
|
+
BlueprintName = "SmileId"
|
|
13
|
+
ReferencedContainer = "container:SmileId.xcodeproj">
|
|
14
|
+
</BuildableReference>
|
|
15
|
+
</BuildActionEntry>
|
|
16
|
+
</BuildActionEntries>
|
|
17
|
+
</BuildAction>
|
|
18
|
+
<LaunchAction
|
|
19
|
+
useCustomWorkingDirectory = "NO"
|
|
20
|
+
buildConfiguration = "Debug"
|
|
21
|
+
allowLocationSimulation = "YES">
|
|
22
|
+
</LaunchAction>
|
|
23
|
+
</Scheme>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>SmileId.xcscheme</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>0</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
</dict>
|
|
14
|
+
</plist>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
protocol SmileIDFileUtilsProtocol {
|
|
2
|
+
var fileManager: FileManager { get set }
|
|
3
|
+
func getFilePath(fileName: String) -> String?
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
extension SmileIDFileUtilsProtocol {
|
|
7
|
+
func getSmileIDDirectory() -> String? {
|
|
8
|
+
guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
|
9
|
+
print("Unable to access documents directory")
|
|
10
|
+
return nil
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let smileIDDirectory = documentsDirectory.appendingPathComponent("SmileID")
|
|
14
|
+
return smileIDDirectory.absoluteURL.absoluteString
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func getFilePath(fileName: String) -> String? {
|
|
18
|
+
guard let smileIDDirectory = getSmileIDDirectory() else {
|
|
19
|
+
return nil
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (smileIDDirectory as NSString).appendingPathComponent(fileName)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -2,59 +2,62 @@ import Foundation
|
|
|
2
2
|
import SmileID
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
|
-
struct SmileIDBiometricKYCView: View {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
5
|
+
struct SmileIDBiometricKYCView: View ,SmileIDFileUtilsProtocol {
|
|
6
|
+
var fileManager: FileManager = Foundation.FileManager.default
|
|
7
|
+
@ObservedObject var product : SmileIDProductModel
|
|
8
|
+
var body: some View{
|
|
9
|
+
NavigationView {
|
|
10
|
+
if let idInfo = product.idInfo {
|
|
11
|
+
SmileID.biometricKycScreen(
|
|
12
|
+
idInfo: idInfo, // already validated in the SmileIDBiometricKYCViewManager
|
|
13
|
+
userId: product.userId ?? generateUserId(),
|
|
14
|
+
jobId: product.jobId ?? generateJobId(),
|
|
15
|
+
allowNewEnroll: product.allowNewEnroll,
|
|
16
|
+
allowAgentMode: product.allowAgentMode,
|
|
17
|
+
showAttribution: product.showAttribution,
|
|
18
|
+
showInstructions: product.showInstructions,
|
|
19
|
+
extraPartnerParams: product.extraPartnerParams as [String: String],
|
|
20
|
+
delegate: self
|
|
21
|
+
)
|
|
22
|
+
} else {
|
|
23
|
+
// This exists for debugging purposes and will show in extreme cases
|
|
24
|
+
// when the params were not set NB: setParams in the viewmanager will always
|
|
25
|
+
// return an error if the required data is missing
|
|
26
|
+
Text("An error has occured")
|
|
27
|
+
}
|
|
28
|
+
}.navigationViewStyle(StackNavigationViewStyle())
|
|
29
|
+
}
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
extension SmileIDBiometricKYCView: BiometricKycResultDelegate {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
func didSucceed(
|
|
48
|
-
selfieImage _: URL,
|
|
49
|
-
livenessImages _: [URL],
|
|
50
|
-
jobStatusResponse: BiometricKycJobStatusResponse
|
|
51
|
-
) {
|
|
52
|
-
let encoder = JSONEncoder()
|
|
53
|
-
let jsonData = try! encoder.encode(jobStatusResponse)
|
|
54
|
-
product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
func didError(error: Error) {
|
|
58
|
-
product.onResult?(["error": error.localizedDescription])
|
|
33
|
+
func didSucceed(selfieImage: URL, livenessImages: [URL], didSubmitBiometricJob: Bool) {
|
|
34
|
+
|
|
35
|
+
let params: [String: Any] = [
|
|
36
|
+
"selfieFile": getFilePath(fileName: selfieImage.absoluteString),
|
|
37
|
+
"livenessFiles": livenessImages.map {
|
|
38
|
+
getFilePath(fileName: $0.absoluteString)
|
|
39
|
+
},
|
|
40
|
+
"didSubmitBiometricKycJob": didSubmitBiometricJob,
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
guard let jsonData = try? JSONSerialization.data(withJSONObject: params.toJSONCompatibleDictionary(), options: .prettyPrinted) else {
|
|
44
|
+
product.onResult?(["error": SmileIDError.unknown("SmileIDBiometricKYCView encoding error")])
|
|
45
|
+
return
|
|
59
46
|
}
|
|
47
|
+
product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func didSucceed(
|
|
51
|
+
selfieImage _: URL,
|
|
52
|
+
livenessImages _: [URL],
|
|
53
|
+
jobStatusResponse: BiometricKycJobStatusResponse
|
|
54
|
+
) {
|
|
55
|
+
let encoder = JSONEncoder()
|
|
56
|
+
let jsonData = try! encoder.encode(jobStatusResponse)
|
|
57
|
+
product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func didError(error: Error) {
|
|
61
|
+
product.onResult?(["error": error.localizedDescription])
|
|
62
|
+
}
|
|
60
63
|
}
|