Skip to content

Commit

Permalink
Allow wrappers sdks to capture face images separately v10 [React vs F…
Browse files Browse the repository at this point in the history
…lutter] (#66)

* feat: selfie capture standalone

* feat: selfie and doc capture complete

* feat: ios update

* fix: custom result with absolute file paths

* feat: bump android sdk

* feat: remove config.json

* feat: make ios and android params work the same

* feat: bump ios to 10.2.12

* feat: document capture ios same file paths with selfie
  • Loading branch information
JNdhlovu authored Oct 4, 2024
1 parent f44ce03 commit dfba999
Show file tree
Hide file tree
Showing 29 changed files with 1,044 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Release Notes

## 10.1.12
* Added selfie capture screens
* Added document capture screens
* Bump android to 10.3.1 (https://github.com/smileidentity/android/releases/tag/v10.3.1)
* Bump iOS to 10.2.12 (https://github.com/smileidentity/ios/releases/tag/v10.2.12)

## 10.1.11
* Fix config issues on iOS

Expand Down
8 changes: 4 additions & 4 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,17 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core"
implementation "com.smileidentity:android-sdk:$smile_id_sdk_version"
implementation "com.google.mlkit:object-detection:17.0.2"
implementation "com.jakewharton.timber:timber"
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("androidx.navigation:navigation-compose:2.8.1")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.6")

testImplementation 'junit:junit:4.13.2'

androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation platform('androidx.compose:compose-bom:2024.06.00')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
androidTestImplementation platform('androidx.compose:compose-bom:2024.06.00')
androidTestImplementation platform('androidx.compose:compose-bom:2024.09.02')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'

debugImplementation 'androidx.compose.ui:ui-tooling'
Expand Down
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ SmileId_minSdkVersion=21
SmileId_targetSdkVersion=34
SmileId_compileSdkVersion=34
SmileId_ndkversion=21.4.7075529
SmileId_androidVersion=10.2.5
SmileId_androidVersion=10.3.1
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager
import com.smileidentity.react.viewmanagers.SmileIDBiometricKYCViewManager
import com.smileidentity.react.viewmanagers.SmileIDConsentViewManager
import com.smileidentity.react.viewmanagers.SmileIDDocumentCaptureViewManager
import com.smileidentity.react.viewmanagers.SmileIDDocumentVerificationViewManager
import com.smileidentity.react.viewmanagers.SmileIDEnhancedDocumentVerificationViewManager
import com.smileidentity.react.viewmanagers.SmileIDSmartSelfieAuthenticationViewManager
import com.smileidentity.react.viewmanagers.SmileIDSmartSelfieCaptureViewManager
import com.smileidentity.react.viewmanagers.SmileIDSmartSelfieEnrollmentViewManager
import com.smileidentity.react.views.SmileIDDocumentCaptureView

class SmileIdPackage : TurboReactPackage() {

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
listOf(
SmileIDSmartSelfieCaptureViewManager(reactContext),
SmileIDDocumentCaptureViewManager(reactContext),
SmileIDSmartSelfieEnrollmentViewManager(reactContext),
SmileIDSmartSelfieAuthenticationViewManager(reactContext),
SmileIDDocumentVerificationViewManager(reactContext),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.smileidentity.react.utils

import com.smileidentity.react.views.DocumentCaptureResult
import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import java.io.File
import java.lang.reflect.Type

class DocumentCaptureResultAdapter : JsonAdapter<DocumentCaptureResult>() {

@FromJson
override fun fromJson(reader: JsonReader): DocumentCaptureResult {
reader.beginObject()
var frontFile: File? = null
var backFile: File? = null
while (reader.hasNext()) {
when (reader.nextName()) {
"documentFrontFile" -> frontFile = reader.nextString()?.let { File(it) }
"documentBackFile" -> backFile = reader.nextString()?.let { File(it) }
else -> reader.skipValue()
}
}
reader.endObject()
return DocumentCaptureResult(frontFile, backFile)
}

@ToJson
override fun toJson(writer: JsonWriter, value: DocumentCaptureResult?) {
if (value == null) {
writer.nullValue()
return
}
writer.beginObject()
writer.name("documentFrontFile").value(value.documentFrontFile?.absolutePath)
writer.name("documentBackFile").value(value.documentBackFile?.absolutePath)
writer.endObject()
}

companion object {
val FACTORY = object : Factory {
override fun create(
type: Type,
annotations: Set<Annotation>,
moshi: Moshi
): JsonAdapter<*>? {
return if (type == DocumentCaptureResult::class.java) DocumentCaptureResultAdapter() else null
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.smileidentity.react.utils

import com.smileidentity.react.views.SmartSelfieCaptureResult
import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import java.io.File
import java.lang.reflect.Type

class SelfieCaptureResultAdapter : JsonAdapter<SmartSelfieCaptureResult>() {

@FromJson
override fun fromJson(reader: JsonReader): SmartSelfieCaptureResult {
reader.beginObject()
var selfieFile: File? = null
var livenessFiles: List<File>? = null
while (reader.hasNext()) {
when (reader.nextName()) {
"selfieFile" -> selfieFile = reader.nextString()?.let { File(it) }
"livenessFiles" -> {
reader.beginArray()
val files = mutableListOf<File>()
while (reader.hasNext()) {
reader.nextString()?.let { files.add(File(it)) }
}
reader.endArray()
livenessFiles = files
}
else -> reader.skipValue()
}
}
reader.endObject()
return SmartSelfieCaptureResult(selfieFile, livenessFiles)
}

@ToJson
override fun toJson(writer: JsonWriter, value: SmartSelfieCaptureResult?) {
if (value == null) {
writer.nullValue()
return
}
writer.beginObject()
writer.name("selfieFile").value(value.selfieFile?.absolutePath)
writer.name("livenessFiles")
writer.beginArray()
value.livenessFiles?.forEach { file ->
writer.value(file.absolutePath)
}
writer.endArray()
writer.endObject()
}

companion object {
val FACTORY = object : Factory {
override fun create(
type: Type,
annotations: Set<Annotation>,
moshi: Moshi
): JsonAdapter<*>? {
return if (type == SmartSelfieCaptureResult::class.java) SelfieCaptureResultAdapter() else null
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.smileidentity.react.viewmanagers

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.smileidentity.react.utils.getBoolOrDefault
import com.smileidentity.react.utils.getStringOrDefault
import com.smileidentity.react.views.SmileIDDocumentCaptureView

@ReactModule(name = SmileIDDocumentCaptureViewManager.NAME)
class SmileIDDocumentCaptureViewManager(
private val reactApplicationContext: ReactApplicationContext
) : SimpleViewManager<SmileIDDocumentCaptureView>() {
override fun getName(): String = NAME

override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
return mapOf(
"onSmileResult" to mapOf(
"phasedRegistrationNames" to mapOf(
"bubbled" to "onResult"
)
)
)
}

override fun getCommandsMap(): Map<String, Int> {
return mapOf("setParams" to COMMAND_SET_PARAMS)
}

override fun receiveCommand(
view: SmileIDDocumentCaptureView,
commandId: String?,
args: ReadableArray?
) {
super.receiveCommand(view, commandId, args)
when (commandId?.toInt()) {
COMMAND_SET_PARAMS -> {
// Extract params from args and apply to view
val params = args?.getMap(0)
params?.let {
view.userId = params.getStringOrDefault("userId")
view.jobId = params.getStringOrDefault("jobId")
view.allowAgentMode = params.getBoolOrDefault("allowAgentMode", true)
view.showAttribution = params.getBoolOrDefault("showAttribution", true)
view.showInstructions = params.getBoolOrDefault("showInstructions", true)
view.showConfirmation = params.getBoolOrDefault("showConfirmation", true)
view.allowGalleryUpload = params.getBoolOrDefault("allowGalleryUpload", false)
view.front = params.getBoolOrDefault("isDocumentFrontSide", true)
view.renderContent()
}
}
}
}

override fun createViewInstance(p0: ThemedReactContext): SmileIDDocumentCaptureView {
return SmileIDDocumentCaptureView(reactApplicationContext)
}

companion object {
const val NAME = "SmileIDDocumentCaptureView"
const val COMMAND_SET_PARAMS = 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.smileidentity.react.viewmanagers

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.SimpleViewManager
import com.facebook.react.uimanager.ThemedReactContext
import com.smileidentity.react.utils.getBoolOrDefault
import com.smileidentity.react.utils.getStringOrDefault
import com.smileidentity.react.views.SmileIDSmartSelfieCaptureView

@ReactModule(name = SmileIDSmartSelfieCaptureViewManager.NAME)
class SmileIDSmartSelfieCaptureViewManager(
private val reactApplicationContext: ReactApplicationContext
) : SimpleViewManager<SmileIDSmartSelfieCaptureView>() {
override fun getName(): String = NAME

override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
return mapOf(
"onSmileResult" to mapOf(
"phasedRegistrationNames" to mapOf(
"bubbled" to "onResult"
)
)
)
}

override fun getCommandsMap(): Map<String, Int> {
return mapOf("setParams" to COMMAND_SET_PARAMS)
}

override fun receiveCommand(
view: SmileIDSmartSelfieCaptureView,
commandId: String?,
args: ReadableArray?
) {
super.receiveCommand(view, commandId, args)
when (commandId?.toInt()) {
COMMAND_SET_PARAMS -> {
// Extract params from args and apply to view
val params = args?.getMap(0)
params?.let {
view.userId = params.getStringOrDefault("userId")
view.jobId = params.getStringOrDefault("jobId")
view.allowAgentMode = params.getBoolOrDefault("allowAgentMode", false)
view.showAttribution = params.getBoolOrDefault("showAttribution", true)
view.showInstructions = params.getBoolOrDefault("showInstructions", true)
view.showConfirmation = params.getBoolOrDefault("showConfirmation", true)
view.renderContent()
}
}
}
}

override fun createViewInstance(p0: ThemedReactContext): SmileIDSmartSelfieCaptureView {
return SmileIDSmartSelfieCaptureView(reactApplicationContext)
}

companion object {
const val NAME = "SmileIDSmartSelfieCaptureView"
const val COMMAND_SET_PARAMS = 1
}
}
Loading

0 comments on commit dfba999

Please sign in to comment.