@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.
Files changed (84) hide show
  1. package/android/build.gradle +4 -4
  2. package/android/gradle.properties +1 -1
  3. package/android/src/main/java/com/smileidentity/react/SmileIdPackage.kt +5 -0
  4. package/android/src/main/java/com/smileidentity/react/results/DocumentCaptureResult.kt +12 -0
  5. package/android/src/main/java/com/smileidentity/react/results/SmartSelfieCaptureResult.kt +11 -0
  6. package/android/src/main/java/com/smileidentity/react/utils/DocumentCaptureResultAdapter.kt +98 -0
  7. package/android/src/main/java/com/smileidentity/react/utils/SelfieCaptureResultAdapter.kt +78 -0
  8. package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDDocumentCaptureViewManager.kt +65 -0
  9. package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDSmartSelfieCaptureViewManager.kt +63 -0
  10. package/android/src/main/java/com/smileidentity/react/views/SmileIDBiometricKYCView.kt +26 -15
  11. package/android/src/main/java/com/smileidentity/react/views/SmileIDDocumentCaptureView.kt +102 -0
  12. package/android/src/main/java/com/smileidentity/react/views/SmileIDDocumentVerificationView.kt +28 -15
  13. package/android/src/main/java/com/smileidentity/react/views/SmileIDEnhancedDocumentVerificationView.kt +28 -15
  14. package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieAuthenticationView.kt +26 -16
  15. package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieCaptureView.kt +209 -0
  16. package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieEnrollmentView.kt +26 -16
  17. package/android/src/main/java/com/smileidentity/react/views/SmileIDView.kt +7 -2
  18. package/ios/RNSmileID.swift +1 -1
  19. package/ios/SmileId.xcodeproj/xcuserdata/japhetndhlovu.xcuserdatad/xcschemes/SmileId.xcscheme +23 -0
  20. package/ios/SmileId.xcodeproj/xcuserdata/japhetndhlovu.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  21. package/ios/Utils/FileUtils.swift +24 -0
  22. package/ios/View/SmileIDBiometricKYCView.swift +54 -51
  23. package/ios/View/SmileIDDocumentCaptureView.swift +82 -0
  24. package/ios/View/SmileIDDocumentVerificationView.swift +50 -47
  25. package/ios/View/SmileIDEnhancedDocumentVerificationView.swift +49 -47
  26. package/ios/View/SmileIDSmartSelfieAuthView.swift +35 -33
  27. package/ios/View/SmileIDSmartSelfieCaptureView.swift +71 -0
  28. package/ios/View/SmileIDSmartSelfieEnrollmentView.swift +35 -33
  29. package/ios/ViewManagers/SmileIDDocumentCaptureViewManager.m +7 -0
  30. package/ios/ViewManagers/SmileIDDocumentCaptureViewManager.swift +29 -0
  31. package/ios/ViewManagers/SmileIDSmartSelfieCaptureViewManager.m +7 -0
  32. package/ios/ViewManagers/SmileIDSmartSelfieCaptureViewManager.swift +36 -0
  33. package/ios/ViewModels/SmileIDProductModel.swift +2 -0
  34. package/lib/commonjs/SmileIDDocumentCaptureView.js +40 -0
  35. package/lib/commonjs/SmileIDDocumentCaptureView.js.map +1 -0
  36. package/lib/commonjs/SmileIDSmartSelfieCaptureView.js +40 -0
  37. package/lib/commonjs/SmileIDSmartSelfieCaptureView.js.map +1 -0
  38. package/lib/commonjs/index.js +14 -0
  39. package/lib/commonjs/index.js.map +1 -1
  40. package/lib/commonjs/types.js.map +1 -1
  41. package/lib/module/SmileIDDocumentCaptureView.js +30 -0
  42. package/lib/module/SmileIDDocumentCaptureView.js.map +1 -0
  43. package/lib/module/SmileIDSmartSelfieCaptureView.js +30 -0
  44. package/lib/module/SmileIDSmartSelfieCaptureView.js.map +1 -0
  45. package/lib/module/index.js +3 -1
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/types.js.map +1 -1
  48. package/lib/typescript/NativeSmileId.d.ts.map +1 -0
  49. package/lib/typescript/SmileIDBiometricKYCView.d.ts.map +1 -0
  50. package/lib/typescript/SmileIDConsentView.d.ts.map +1 -0
  51. package/lib/typescript/SmileIDDocumentCaptureView.d.ts +8 -0
  52. package/lib/typescript/SmileIDDocumentCaptureView.d.ts.map +1 -0
  53. package/lib/typescript/SmileIDDocumentVerificationView.d.ts.map +1 -0
  54. package/lib/typescript/SmileIDEnhancedDocumentVerificationView.d.ts.map +1 -0
  55. package/lib/typescript/SmileIDSmartSelfieAuthenticationView.d.ts.map +1 -0
  56. package/lib/typescript/SmileIDSmartSelfieCaptureView.d.ts +8 -0
  57. package/lib/typescript/SmileIDSmartSelfieCaptureView.d.ts.map +1 -0
  58. package/lib/typescript/SmileIDSmartSelfieEnrollmentView.d.ts.map +1 -0
  59. package/lib/typescript/{src/index.d.ts → index.d.ts} +3 -1
  60. package/lib/typescript/index.d.ts.map +1 -0
  61. package/lib/typescript/{src/types.d.ts → types.d.ts} +13 -2
  62. package/lib/typescript/types.d.ts.map +1 -0
  63. package/package.json +1 -1
  64. package/react-native-smile-id.podspec +1 -1
  65. package/src/SmileIDDocumentCaptureView.tsx +44 -0
  66. package/src/SmileIDSmartSelfieCaptureView.tsx +44 -0
  67. package/src/index.tsx +4 -0
  68. package/src/types.ts +21 -2
  69. package/lib/typescript/src/NativeSmileId.d.ts.map +0 -1
  70. package/lib/typescript/src/SmileIDBiometricKYCView.d.ts.map +0 -1
  71. package/lib/typescript/src/SmileIDConsentView.d.ts.map +0 -1
  72. package/lib/typescript/src/SmileIDDocumentVerificationView.d.ts.map +0 -1
  73. package/lib/typescript/src/SmileIDEnhancedDocumentVerificationView.d.ts.map +0 -1
  74. package/lib/typescript/src/SmileIDSmartSelfieAuthenticationView.d.ts.map +0 -1
  75. package/lib/typescript/src/SmileIDSmartSelfieEnrollmentView.d.ts.map +0 -1
  76. package/lib/typescript/src/index.d.ts.map +0 -1
  77. package/lib/typescript/src/types.d.ts.map +0 -1
  78. /package/lib/typescript/{src/NativeSmileId.d.ts → NativeSmileId.d.ts} +0 -0
  79. /package/lib/typescript/{src/SmileIDBiometricKYCView.d.ts → SmileIDBiometricKYCView.d.ts} +0 -0
  80. /package/lib/typescript/{src/SmileIDConsentView.d.ts → SmileIDConsentView.d.ts} +0 -0
  81. /package/lib/typescript/{src/SmileIDDocumentVerificationView.d.ts → SmileIDDocumentVerificationView.d.ts} +0 -0
  82. /package/lib/typescript/{src/SmileIDEnhancedDocumentVerificationView.d.ts → SmileIDEnhancedDocumentVerificationView.d.ts} +0 -0
  83. /package/lib/typescript/{src/SmileIDSmartSelfieAuthenticationView.d.ts → SmileIDSmartSelfieAuthenticationView.d.ts} +0 -0
  84. /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.EnhancedDocumentVerificationResult
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
- ) { result ->
48
- when (result) {
47
+ ) { res ->
48
+ when (res) {
49
49
  is SmileIDResult.Success -> {
50
- val json = try {
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
- .adapter(EnhancedDocumentVerificationResult::class.java)
53
- .toJson(result.data)
54
- } catch (e: Exception) {
55
- Timber.w(e)
56
- "null"
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
  }
@@ -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.SmartSelfieResult
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
- ) { result ->
33
- when (result) {
31
+ ) { res ->
32
+ when (res) {
34
33
  is SmileIDResult.Success -> {
35
- val json = try {
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
- .adapter(SmartSelfieResult::class.java)
38
- .toJson(result.data)
39
- } catch (e: Exception) {
40
- Timber.w(e)
41
- "null"
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
+ }
@@ -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.SmartSelfieResult
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
- ) { result ->
32
- when (result) {
30
+ ) { res ->
31
+ when (res) {
33
32
  is SmileIDResult.Success -> {
34
- val json = try {
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
- .adapter(SmartSelfieResult::class.java)
37
- .toJson(result.data)
38
- } catch (e: Exception) {
39
- Timber.w(e)
40
- "null"
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? = true
24
- var showAttribution: Boolean? = true
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
@@ -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
- @ObservedObject var product : SmileIDProductModel
7
- var body: some View{
8
- NavigationView {
9
- if let idInfo = product.idInfo {
10
- SmileID.biometricKycScreen(
11
- idInfo: idInfo, // already validated in the SmileIDBiometricKYCViewManager
12
- userId: product.userId ?? generateUserId(),
13
- jobId: product.jobId ?? generateJobId(),
14
- allowNewEnroll: product.allowNewEnroll,
15
- allowAgentMode: product.allowAgentMode,
16
- showAttribution: product.showAttribution,
17
- showInstructions: product.showInstructions,
18
- extraPartnerParams: product.extraPartnerParams as [String: String],
19
- delegate: self
20
- )
21
- } else {
22
- // This exists for debugging purposes and will show in extreme cases
23
- // when the params were not set NB: setParams in the viewmanager will always
24
- // return an error if the required data is missing
25
- Text("An error has occured")
26
- }
27
- }.navigationViewStyle(StackNavigationViewStyle())
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
- func didSucceed(selfieImage: URL, livenessImages: [URL], didSubmitBiometricJob: Bool) {
33
-
34
- let params: [String: Any] = [
35
- "selfieFile": selfieImage.absoluteString,
36
- "livenessFiles": livenessImages,
37
- "didSubmitBiometricKycJob": didSubmitBiometricJob,
38
- ]
39
-
40
- guard let jsonData = try? JSONSerialization.data(withJSONObject: params.toJSONCompatibleDictionary(), options: .prettyPrinted) else {
41
- product.onResult?(["error": SmileIDError.unknown("SmileIDBiometricKYCView encoding error")])
42
- return
43
- }
44
- product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
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
  }