diff --git a/.editorconfig b/.editorconfig index df8aef05..a994c8f8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,5 +3,6 @@ max_line_length=100 [{*.kt,*.kts}] ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^ +ktlint_function_naming_ignore_when_annotated_with = Composable ij_kotlin_allow_trailing_comma_on_call_site=true ij_kotlin_allow_trailing_comma=true \ No newline at end of file diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 34b82ca9..a95fe54c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -40,7 +40,8 @@ jobs: - name: Lint Android uses: musichin/ktlint-check@v3 with: - ktlint-version: "0.49.1" + ktlint-version: "1.1.1" + code-style: android_studio patterns: | **/**.kt !**/generated/** diff --git a/android/build.gradle b/android/build.gradle index f9e27584..732275bc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -10,9 +10,9 @@ buildscript { } dependencies { - classpath "com.android.tools.build:gradle:8.1.2" + classpath "com.android.tools.build:gradle:8.1.4" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jlleitschuh.gradle:ktlint-gradle:11.6.1" + classpath "org.jlleitschuh.gradle:ktlint-gradle:12.1.1" } } @@ -68,7 +68,7 @@ android { implementation "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.6" testImplementation "org.jetbrains.kotlin:kotlin-test" - testImplementation "io.mockk:mockk:1.13.8" + testImplementation "io.mockk:mockk:1.13.11" } } @@ -77,4 +77,4 @@ ktlint { filter { exclude { it.file.path.contains(".g.kt") } } -} +} \ No newline at end of file diff --git a/android/src/main/kotlin/com/smileidentity/flutter/Mapper.kt b/android/src/main/kotlin/com/smileidentity/flutter/Mapper.kt index a7ccc14f..27836933 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/Mapper.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/Mapper.kt @@ -109,332 +109,366 @@ fun convertNonNullMapToNullable(map: Map): Map map.mapKeys { it.key } .mapValues { it.value } -fun FlutterJobType.toRequest() = when (this) { - FlutterJobType.ENHANCEDKYC -> JobType.EnhancedKyc - FlutterJobType.DOCUMENTVERIFICATION -> JobType.DocumentVerification - FlutterJobType.BIOMETRICKYC -> JobType.BiometricKyc - FlutterJobType.ENHANCEDDOCUMENTVERIFICATION -> JobType.EnhancedDocumentVerification - FlutterJobType.SMARTSELFIEENROLLMENT -> JobType.SmartSelfieEnrollment - FlutterJobType.SMARTSELFIEAUTHENTICATION -> JobType.SmartSelfieAuthentication -} - -fun JobType.toResponse() = when (this) { - JobType.EnhancedKyc -> FlutterJobType.ENHANCEDKYC - JobType.DocumentVerification -> FlutterJobType.DOCUMENTVERIFICATION - JobType.BiometricKyc -> FlutterJobType.BIOMETRICKYC - JobType.EnhancedDocumentVerification -> FlutterJobType.ENHANCEDDOCUMENTVERIFICATION - JobType.SmartSelfieEnrollment -> FlutterJobType.SMARTSELFIEENROLLMENT - JobType.SmartSelfieAuthentication -> FlutterJobType.SMARTSELFIEAUTHENTICATION - else -> TODO("Not yet implemented") -} - -fun FlutterJobTypeV2.toRequest() = when (this) { - FlutterJobTypeV2.SMARTSELFIEAUTHENTICATION -> JobTypeV2.SmartSelfieAuthentication - FlutterJobTypeV2.SMARTSELFIEENROLLMENT -> JobTypeV2.SmartSelfieEnrollment -} - -fun JobTypeV2.toResponse() = when (this) { - JobTypeV2.SmartSelfieAuthentication -> FlutterJobTypeV2.SMARTSELFIEAUTHENTICATION - JobTypeV2.SmartSelfieEnrollment -> FlutterJobTypeV2.SMARTSELFIEENROLLMENT - else -> TODO("Not yet implemented") -} - -fun FlutterAuthenticationRequest.toRequest() = AuthenticationRequest( - jobType = jobType.toRequest(), - country = country, - idType = idType, - updateEnrolledImage = updateEnrolledImage, - jobId = jobId, - userId = userId, -) - -fun PartnerParams.toResponse() = FlutterPartnerParams( - jobType = jobType?.toResponse(), - jobId = jobId, - userId = userId, - extras = convertNonNullMapToNullable(extras), -) - -fun FlutterPartnerParams.toRequest() = PartnerParams( - jobType = jobType?.toRequest(), - jobId = jobId, - userId = userId, - extras = convertNullableMapToNonNull(extras), -) - -fun ConsentInfo.toRequest() = FlutterConsentInfo( - canAccess = canAccess, - consentRequired = consentRequired, -) - -fun AuthenticationResponse.toResponse() = FlutterAuthenticationResponse( - success = success, - signature = signature, - timestamp = timestamp, - partnerParams = partnerParams.toResponse(), - callbackUrl = callbackUrl, - consentInfo = consentInfo?.toRequest(), -) - -fun FlutterPrepUploadRequest.toRequest() = PrepUploadRequest( - partnerParams = partnerParams.toRequest(), - callbackUrl = callbackUrl, - allowNewEnroll = allowNewEnroll.toString(), - partnerId = partnerId, - sourceSdk = "android (flutter)", - timestamp = timestamp, - signature = signature, -) - -fun PrepUploadResponse.toResponse() = FlutterPrepUploadResponse( - code = code, - refId = refId, - uploadUrl = uploadUrl, - smileJobId = smileJobId, -) - -fun FlutterUploadRequest.toRequest() = UploadRequest( - images = images.mapNotNull { it?.toRequest() }, - idInfo = idInfo?.toRequest(), -) - -fun FlutterUploadImageInfo.toRequest() = UploadImageInfo( - imageTypeId = imageTypeId.toRequest(), - image = File(imageName), -) - -fun FlutterImageType.toRequest() = when (this) { - FlutterImageType.SELFIEJPGFILE -> ImageType.SelfieJpgFile - FlutterImageType.IDCARDJPGFILE -> ImageType.IdCardJpgFile - FlutterImageType.SELFIEJPGBASE64 -> ImageType.SelfieJpgBase64 - FlutterImageType.IDCARDJPGBASE64 -> ImageType.IdCardJpgBase64 - FlutterImageType.LIVENESSJPGFILE -> ImageType.LivenessJpgFile - FlutterImageType.IDCARDREARJPGFILE -> ImageType.IdCardRearJpgFile - FlutterImageType.LIVENESSJPGBASE64 -> ImageType.LivenessJpgBase64 - FlutterImageType.IDCARDREARJPGBASE64 -> ImageType.IdCardRearJpgBase64 -} - -fun FlutterIdInfo.toRequest() = IdInfo( - country = country, - idType = idType, - idNumber = idNumber, - firstName = firstName, - middleName = middleName, - lastName = lastName, - dob = dob, - bankCode = bankCode, - entered = entered, -) - -fun FlutterEnhancedKycRequest.toRequest() = EnhancedKycRequest( - country = country, - idType = idType, - idNumber = idNumber, - firstName = firstName, - middleName = middleName, - lastName = lastName, - dob = dob, - phoneNumber = phoneNumber, - bankCode = bankCode, - callbackUrl = callbackUrl, - partnerParams = partnerParams.toRequest(), - sourceSdk = "android (flutter)", - timestamp = timestamp, - signature = signature, -) - -fun EnhancedKycResponse.toResponse() = FlutterEnhancedKycResponse( - smileJobId = smileJobId, - partnerParams = partnerParams.toResponse(), - resultText = resultText, - resultCode = resultCode, - actions = actions.toResponse(), - country = country, - idType = idType, - idNumber = idNumber, - fullName = fullName, - expirationDate = expirationDate, - dob = dob, - base64Photo = base64Photo, -) - -fun EnhancedKycAsyncResponse.toResponse() = FlutterEnhancedKycAsyncResponse( - success = success, -) - -fun Actions.toResponse() = FlutterActions( - documentCheck = documentCheck.toResponse(), - humanReviewCompare = humanReviewCompare.toResponse(), - humanReviewDocumentCheck = humanReviewDocumentCheck.toResponse(), - humanReviewLivenessCheck = humanReviewLivenessCheck.toResponse(), - humanReviewSelfieCheck = humanReviewSelfieCheck.toResponse(), - humanReviewUpdateSelfie = humanReviewUpdateSelfie.toResponse(), - livenessCheck = livenessCheck.toResponse(), - registerSelfie = registerSelfie.toResponse(), - returnPersonalInfo = returnPersonalInfo.toResponse(), - selfieCheck = selfieCheck.toResponse(), - selfieProvided = selfieProvided.toResponse(), - selfieToIdAuthorityCompare = selfieToIdAuthorityCompare.toResponse(), - selfieToIdCardCompare = selfieToIdCardCompare.toResponse(), - selfieToRegisteredSelfieCompare = selfieToRegisteredSelfieCompare.toResponse(), - updateRegisteredSelfieOnFile = updateRegisteredSelfieOnFile.toResponse(), - verifyDocument = verifyDocument.toResponse(), - verifyIdNumber = verifyIdNumber.toResponse(), -) - -fun ActionResult.toResponse() = when (this) { - ActionResult.Passed -> FlutterActionResult.PASSED - ActionResult.Completed -> FlutterActionResult.COMPLETED - ActionResult.Approved -> FlutterActionResult.APPROVED - ActionResult.Verified -> FlutterActionResult.VERIFIED - ActionResult.ProvisionallyApproved -> FlutterActionResult.PROVISIONALLYAPPROVED - ActionResult.Returned -> FlutterActionResult.RETURNED - ActionResult.NotReturned -> FlutterActionResult.NOTRETURNED - ActionResult.Failed -> FlutterActionResult.FAILED - ActionResult.Rejected -> FlutterActionResult.REJECTED - ActionResult.UnderReview -> FlutterActionResult.UNDERREVIEW - ActionResult.UnableToDetermine -> FlutterActionResult.UNABLETODETERMINE - ActionResult.NotApplicable -> FlutterActionResult.NOTAPPLICABLE - ActionResult.NotVerified -> FlutterActionResult.NOTVERIFIED - ActionResult.NotDone -> FlutterActionResult.NOTDONE - ActionResult.IssuerUnavailable -> FlutterActionResult.ISSUERUNAVAILABLE - ActionResult.Unknown -> FlutterActionResult.UNKNOWN -} - -fun ImageLinks.toResponse() = FlutterImageLinks( - selfieImageUrl = selfieImageUrl, - error = error, -) - -fun Antifraud.toResponse() = FlutterAntifraud( - suspectUsers = suspectUsers.map { it.toResponse() }, -) - -fun SuspectUser.toResponse() = FlutterSuspectUser( - reason = reason, - userId = userId, -) - -fun FlutterJobStatusRequest.toRequest() = JobStatusRequest( - userId = userId, - jobId = jobId, - includeImageLinks = includeImageLinks, - includeHistory = includeHistory, - partnerId = partnerId, - timestamp = timestamp, - signature = signature, -) - -fun SmartSelfieJobStatusResponse.toResponse() = FlutterSmartSelfieJobStatusResponse( - timestamp = timestamp, - jobComplete = jobComplete, - jobSuccess = jobSuccess, - code = code, - result = result?.toResponse() as? FlutterSmartSelfieJobResult, - resultString = result?.toResponse() as? String, - imageLinks = imageLinks?.toResponse(), -) - -fun SmartSelfieJobResult.toResponse(): Any = when (this) { - is JobResult.Freeform -> this.result - is SmartSelfieJobResult.Entry -> FlutterSmartSelfieJobResult( - actions = actions.toResponse(), - resultCode = resultCode, - resultText = resultText, - smileJobId = smileJobId, +fun FlutterJobType.toRequest() = + when (this) { + FlutterJobType.ENHANCEDKYC -> JobType.EnhancedKyc + FlutterJobType.DOCUMENTVERIFICATION -> JobType.DocumentVerification + FlutterJobType.BIOMETRICKYC -> JobType.BiometricKyc + FlutterJobType.ENHANCEDDOCUMENTVERIFICATION -> JobType.EnhancedDocumentVerification + FlutterJobType.SMARTSELFIEENROLLMENT -> JobType.SmartSelfieEnrollment + FlutterJobType.SMARTSELFIEAUTHENTICATION -> JobType.SmartSelfieAuthentication + } + +fun JobType.toResponse() = + when (this) { + JobType.EnhancedKyc -> FlutterJobType.ENHANCEDKYC + JobType.DocumentVerification -> FlutterJobType.DOCUMENTVERIFICATION + JobType.BiometricKyc -> FlutterJobType.BIOMETRICKYC + JobType.EnhancedDocumentVerification -> FlutterJobType.ENHANCEDDOCUMENTVERIFICATION + JobType.SmartSelfieEnrollment -> FlutterJobType.SMARTSELFIEENROLLMENT + JobType.SmartSelfieAuthentication -> FlutterJobType.SMARTSELFIEAUTHENTICATION + else -> TODO("Not yet implemented") + } + +fun FlutterJobTypeV2.toRequest() = + when (this) { + FlutterJobTypeV2.SMARTSELFIEAUTHENTICATION -> JobTypeV2.SmartSelfieAuthentication + FlutterJobTypeV2.SMARTSELFIEENROLLMENT -> JobTypeV2.SmartSelfieEnrollment + } + +fun JobTypeV2.toResponse() = + when (this) { + JobTypeV2.SmartSelfieAuthentication -> FlutterJobTypeV2.SMARTSELFIEAUTHENTICATION + JobTypeV2.SmartSelfieEnrollment -> FlutterJobTypeV2.SMARTSELFIEENROLLMENT + else -> TODO("Not yet implemented") + } + +fun FlutterAuthenticationRequest.toRequest() = + AuthenticationRequest( + jobType = jobType.toRequest(), + country = country, + idType = idType, + updateEnrolledImage = updateEnrolledImage, + jobId = jobId, + userId = userId, + ) + +fun PartnerParams.toResponse() = + FlutterPartnerParams( + jobType = jobType?.toResponse(), + jobId = jobId, + userId = userId, + extras = convertNonNullMapToNullable(extras), + ) + +fun FlutterPartnerParams.toRequest() = + PartnerParams( + jobType = jobType?.toRequest(), + jobId = jobId, + userId = userId, + extras = convertNullableMapToNonNull(extras), + ) + +fun ConsentInfo.toRequest() = + FlutterConsentInfo( + canAccess = canAccess, + consentRequired = consentRequired, + ) + +fun AuthenticationResponse.toResponse() = + FlutterAuthenticationResponse( + success = success, + signature = signature, + timestamp = timestamp, partnerParams = partnerParams.toResponse(), - confidence = confidence, - ) -} - -fun SmartSelfieStatus.toResponse() = when (this) { - SmartSelfieStatus.Approved -> FlutterSmartSelfieStatus.APPROVED - SmartSelfieStatus.Pending -> FlutterSmartSelfieStatus.PENDING - SmartSelfieStatus.Rejected -> FlutterSmartSelfieStatus.REJECTED - SmartSelfieStatus.Unknown -> FlutterSmartSelfieStatus.UNKNOWN -} - -fun SmartSelfieResponse.toResponse() = FlutterSmartSelfieResponse( - code = code, - createdAt = createdAt, - jobId = jobId, - jobType = jobType.toResponse(), - message = message, - partnerId = partnerId, - partnerParams = convertNonNullMapToNullable(partnerParams), - status = status.toResponse(), - updatedAt = updatedAt, - userId = userId, -) + callbackUrl = callbackUrl, + consentInfo = consentInfo?.toRequest(), + ) -fun DocumentVerificationJobStatusResponse.toResponse() = - FlutterDocumentVerificationJobStatusResponse( +fun FlutterPrepUploadRequest.toRequest() = + PrepUploadRequest( + partnerParams = partnerParams.toRequest(), + callbackUrl = callbackUrl, + allowNewEnroll = allowNewEnroll.toString(), + partnerId = partnerId, + sourceSdk = "android (flutter)", timestamp = timestamp, - jobComplete = jobComplete, - jobSuccess = jobSuccess, - code = code, - result = result?.toResponse() as? FlutterDocumentVerificationJobResult, - resultString = result?.toResponse() as? String, - imageLinks = imageLinks?.toResponse(), + signature = signature, ) -fun DocumentVerificationJobResult.toResponse(): Any = when (this) { - is JobResult.Freeform -> this.result - is DocumentVerificationJobResult.Entry -> FlutterDocumentVerificationJobResult( - actions = actions.toResponse(), - resultCode = resultCode, - resultText = resultText, +fun PrepUploadResponse.toResponse() = + FlutterPrepUploadResponse( + code = code, + refId = refId, + uploadUrl = uploadUrl, smileJobId = smileJobId, - partnerParams = partnerParams.toResponse(), + ) + +fun FlutterUploadRequest.toRequest() = + UploadRequest( + images = images.mapNotNull { it?.toRequest() }, + idInfo = idInfo?.toRequest(), + ) + +fun FlutterUploadImageInfo.toRequest() = + UploadImageInfo( + imageTypeId = imageTypeId.toRequest(), + image = File(imageName), + ) + +fun FlutterImageType.toRequest() = + when (this) { + FlutterImageType.SELFIEJPGFILE -> ImageType.SelfieJpgFile + FlutterImageType.IDCARDJPGFILE -> ImageType.IdCardJpgFile + FlutterImageType.SELFIEJPGBASE64 -> ImageType.SelfieJpgBase64 + FlutterImageType.IDCARDJPGBASE64 -> ImageType.IdCardJpgBase64 + FlutterImageType.LIVENESSJPGFILE -> ImageType.LivenessJpgFile + FlutterImageType.IDCARDREARJPGFILE -> ImageType.IdCardRearJpgFile + FlutterImageType.LIVENESSJPGBASE64 -> ImageType.LivenessJpgBase64 + FlutterImageType.IDCARDREARJPGBASE64 -> ImageType.IdCardRearJpgBase64 + } + +fun FlutterIdInfo.toRequest() = + IdInfo( country = country, idType = idType, - fullName = fullName, idNumber = idNumber, + firstName = firstName, + middleName = middleName, + lastName = lastName, + dob = dob, + bankCode = bankCode, + entered = entered, + ) + +fun FlutterEnhancedKycRequest.toRequest() = + EnhancedKycRequest( + country = country, + idType = idType, + idNumber = idNumber, + firstName = firstName, + middleName = middleName, + lastName = lastName, dob = dob, - gender = gender, - expirationDate = expirationDate, - documentImageBase64 = documentImageBase64, phoneNumber = phoneNumber, - phoneNumber2 = phoneNumber2, - address = address, - ) -} - -fun BiometricKycJobStatusResponse.toResponse() = FlutterBiometricKycJobStatusResponse( - timestamp = timestamp, - jobComplete = jobComplete, - jobSuccess = jobSuccess, - code = code, - result = result?.toResponse() as? FlutterBiometricKycJobResult, - resultString = result?.toResponse() as? String, - imageLinks = imageLinks?.toResponse(), -) - -fun BiometricKycJobResult.toResponse(): Any = when (this) { - is JobResult.Freeform -> this.result - is BiometricKycJobResult.Entry -> FlutterBiometricKycJobResult( - actions = actions.toResponse(), - resultCode = resultCode, - resultText = resultText, - resultType = resultType, + bankCode = bankCode, + callbackUrl = callbackUrl, + partnerParams = partnerParams.toRequest(), + sourceSdk = "android (flutter)", + timestamp = timestamp, + signature = signature, + ) + +fun EnhancedKycResponse.toResponse() = + FlutterEnhancedKycResponse( smileJobId = smileJobId, partnerParams = partnerParams.toResponse(), - antifraud = antifraud?.toResponse(), - dob = dob, - photoBase64 = photoBase64, - gender = gender, - idType = idType, - address = address, + resultText = resultText, + resultCode = resultCode, + actions = actions.toResponse(), country = country, - documentImageBase64 = documentImageBase64, - fullData = fullData?.mapKeys { it.key }, - fullName = fullName, + idType = idType, idNumber = idNumber, - phoneNumber = phoneNumber, - phoneNumber2 = phoneNumber2, + fullName = fullName, expirationDate = expirationDate, + dob = dob, + base64Photo = base64Photo, + ) + +fun EnhancedKycAsyncResponse.toResponse() = + FlutterEnhancedKycAsyncResponse( + success = success, + ) + +fun Actions.toResponse() = + FlutterActions( + documentCheck = documentCheck.toResponse(), + humanReviewCompare = humanReviewCompare.toResponse(), + humanReviewDocumentCheck = humanReviewDocumentCheck.toResponse(), + humanReviewLivenessCheck = humanReviewLivenessCheck.toResponse(), + humanReviewSelfieCheck = humanReviewSelfieCheck.toResponse(), + humanReviewUpdateSelfie = humanReviewUpdateSelfie.toResponse(), + livenessCheck = livenessCheck.toResponse(), + registerSelfie = registerSelfie.toResponse(), + returnPersonalInfo = returnPersonalInfo.toResponse(), + selfieCheck = selfieCheck.toResponse(), + selfieProvided = selfieProvided.toResponse(), + selfieToIdAuthorityCompare = selfieToIdAuthorityCompare.toResponse(), + selfieToIdCardCompare = selfieToIdCardCompare.toResponse(), + selfieToRegisteredSelfieCompare = selfieToRegisteredSelfieCompare.toResponse(), + updateRegisteredSelfieOnFile = updateRegisteredSelfieOnFile.toResponse(), + verifyDocument = verifyDocument.toResponse(), + verifyIdNumber = verifyIdNumber.toResponse(), ) -} + +fun ActionResult.toResponse() = + when (this) { + ActionResult.Passed -> FlutterActionResult.PASSED + ActionResult.Completed -> FlutterActionResult.COMPLETED + ActionResult.Approved -> FlutterActionResult.APPROVED + ActionResult.Verified -> FlutterActionResult.VERIFIED + ActionResult.ProvisionallyApproved -> FlutterActionResult.PROVISIONALLYAPPROVED + ActionResult.Returned -> FlutterActionResult.RETURNED + ActionResult.NotReturned -> FlutterActionResult.NOTRETURNED + ActionResult.Failed -> FlutterActionResult.FAILED + ActionResult.Rejected -> FlutterActionResult.REJECTED + ActionResult.UnderReview -> FlutterActionResult.UNDERREVIEW + ActionResult.UnableToDetermine -> FlutterActionResult.UNABLETODETERMINE + ActionResult.NotApplicable -> FlutterActionResult.NOTAPPLICABLE + ActionResult.NotVerified -> FlutterActionResult.NOTVERIFIED + ActionResult.NotDone -> FlutterActionResult.NOTDONE + ActionResult.IssuerUnavailable -> FlutterActionResult.ISSUERUNAVAILABLE + ActionResult.Unknown -> FlutterActionResult.UNKNOWN + } + +fun ImageLinks.toResponse() = + FlutterImageLinks( + selfieImageUrl = selfieImageUrl, + error = error, + ) + +fun Antifraud.toResponse() = + FlutterAntifraud( + suspectUsers = suspectUsers.map { it.toResponse() }, + ) + +fun SuspectUser.toResponse() = + FlutterSuspectUser( + reason = reason, + userId = userId, + ) + +fun FlutterJobStatusRequest.toRequest() = + JobStatusRequest( + userId = userId, + jobId = jobId, + includeImageLinks = includeImageLinks, + includeHistory = includeHistory, + partnerId = partnerId, + timestamp = timestamp, + signature = signature, + ) + +fun SmartSelfieJobStatusResponse.toResponse() = + FlutterSmartSelfieJobStatusResponse( + timestamp = timestamp, + jobComplete = jobComplete, + jobSuccess = jobSuccess, + code = code, + result = result?.toResponse() as? FlutterSmartSelfieJobResult, + resultString = result?.toResponse() as? String, + imageLinks = imageLinks?.toResponse(), + ) + +fun SmartSelfieJobResult.toResponse(): Any = + when (this) { + is JobResult.Freeform -> this.result + is SmartSelfieJobResult.Entry -> + FlutterSmartSelfieJobResult( + actions = actions.toResponse(), + resultCode = resultCode, + resultText = resultText, + smileJobId = smileJobId, + partnerParams = partnerParams.toResponse(), + confidence = confidence, + ) + } + +fun SmartSelfieStatus.toResponse() = + when (this) { + SmartSelfieStatus.Approved -> FlutterSmartSelfieStatus.APPROVED + SmartSelfieStatus.Pending -> FlutterSmartSelfieStatus.PENDING + SmartSelfieStatus.Rejected -> FlutterSmartSelfieStatus.REJECTED + SmartSelfieStatus.Unknown -> FlutterSmartSelfieStatus.UNKNOWN + } + +fun SmartSelfieResponse.toResponse() = + FlutterSmartSelfieResponse( + code = code, + createdAt = createdAt, + jobId = jobId, + jobType = jobType.toResponse(), + message = message, + partnerId = partnerId, + partnerParams = convertNonNullMapToNullable(partnerParams), + status = status.toResponse(), + updatedAt = updatedAt, + userId = userId, + ) + +fun DocumentVerificationJobStatusResponse.toResponse() = + FlutterDocumentVerificationJobStatusResponse( + timestamp = timestamp, + jobComplete = jobComplete, + jobSuccess = jobSuccess, + code = code, + result = result?.toResponse() as? FlutterDocumentVerificationJobResult, + resultString = result?.toResponse() as? String, + imageLinks = imageLinks?.toResponse(), + ) + +fun DocumentVerificationJobResult.toResponse(): Any = + when (this) { + is JobResult.Freeform -> this.result + is DocumentVerificationJobResult.Entry -> + FlutterDocumentVerificationJobResult( + actions = actions.toResponse(), + resultCode = resultCode, + resultText = resultText, + smileJobId = smileJobId, + partnerParams = partnerParams.toResponse(), + country = country, + idType = idType, + fullName = fullName, + idNumber = idNumber, + dob = dob, + gender = gender, + expirationDate = expirationDate, + documentImageBase64 = documentImageBase64, + phoneNumber = phoneNumber, + phoneNumber2 = phoneNumber2, + address = address, + ) + } + +fun BiometricKycJobStatusResponse.toResponse() = + FlutterBiometricKycJobStatusResponse( + timestamp = timestamp, + jobComplete = jobComplete, + jobSuccess = jobSuccess, + code = code, + result = result?.toResponse() as? FlutterBiometricKycJobResult, + resultString = result?.toResponse() as? String, + imageLinks = imageLinks?.toResponse(), + ) + +fun BiometricKycJobResult.toResponse(): Any = + when (this) { + is JobResult.Freeform -> this.result + is BiometricKycJobResult.Entry -> + FlutterBiometricKycJobResult( + actions = actions.toResponse(), + resultCode = resultCode, + resultText = resultText, + resultType = resultType, + smileJobId = smileJobId, + partnerParams = partnerParams.toResponse(), + antifraud = antifraud?.toResponse(), + dob = dob, + photoBase64 = photoBase64, + gender = gender, + idType = idType, + address = address, + country = country, + documentImageBase64 = documentImageBase64, + fullData = fullData?.mapKeys { it.key }, + fullName = fullName, + idNumber = idNumber, + phoneNumber = phoneNumber, + phoneNumber2 = phoneNumber2, + expirationDate = expirationDate, + ) + } fun EnhancedDocumentVerificationJobStatusResponse.toResponse() = FlutterEnhancedDocumentVerificationJobStatusResponse( @@ -447,106 +481,125 @@ fun EnhancedDocumentVerificationJobStatusResponse.toResponse() = imageLinks = imageLinks?.toResponse(), ) -fun EnhancedDocumentVerificationJobResult.toResponse(): Any = when (this) { - is JobResult.Freeform -> this.result - is EnhancedDocumentVerificationJobResult.Entry -> FlutterEnhancedDocumentVerificationJobResult( - actions = actions.toResponse(), - resultCode = resultCode, - resultText = resultText, - smileJobId = smileJobId, - resultType = resultType, - partnerParams = partnerParams.toResponse(), - antifraud = antifraud?.toResponse(), - dob = dob, - photoBase64 = photoBase64, - gender = gender, - idType = idType, - address = address, - country = country, - documentImageBase64 = documentImageBase64, - fullData = fullData?.mapKeys { it.key }, - fullName = fullName, - idNumber = idNumber, - phoneNumber = phoneNumber, - phoneNumber2 = phoneNumber2, - expirationDate = expirationDate, +fun EnhancedDocumentVerificationJobResult.toResponse(): Any = + when (this) { + is JobResult.Freeform -> this.result + is EnhancedDocumentVerificationJobResult.Entry -> + FlutterEnhancedDocumentVerificationJobResult( + actions = actions.toResponse(), + resultCode = resultCode, + resultText = resultText, + smileJobId = smileJobId, + resultType = resultType, + partnerParams = partnerParams.toResponse(), + antifraud = antifraud?.toResponse(), + dob = dob, + photoBase64 = photoBase64, + gender = gender, + idType = idType, + address = address, + country = country, + documentImageBase64 = documentImageBase64, + fullData = fullData?.mapKeys { it.key }, + fullName = fullName, + idNumber = idNumber, + phoneNumber = phoneNumber, + phoneNumber2 = phoneNumber2, + expirationDate = expirationDate, + ) + } + +fun FlutterProductsConfigRequest.toRequest() = + ProductsConfigRequest( + partnerId = partnerId, + timestamp = timestamp, + signature = signature, + ) + +fun ProductsConfigResponse.toResponse() = + FlutterProductsConfigResponse( + consentRequired = consentRequired.mapKeys { it.key }, + idSelection = idSelection.toResponse(), + ) + +fun IdSelection.toResponse() = + FlutterIdSelection( + basicKyc = basicKyc.mapKeys { it.key }, + biometricKyc = biometricKyc.mapKeys { it.key }, + enhancedKyc = enhancedKyc.mapKeys { it.key }, + documentVerification = documentVerification.mapKeys { it.key }, + ) + +fun ValidDocumentsResponse.toResponse() = + FlutterValidDocumentsResponse( + validDocuments = validDocuments.map { it.toResponse() }, + ) + +fun ValidDocument.toResponse() = + FlutterValidDocument( + country = country.toResponse(), + idTypes = idTypes.map { it.toResponse() }, + ) + +fun Country.toResponse() = + FlutterCountry( + name = name, + code = code, + continent = continent, + ) + +fun IdType.toResponse() = + FlutterIdType( + name = name, + code = code, + example = example.map { it }, + hasBack = hasBack, + ) + +fun ServicesResponse.toResponse() = + FlutterServicesResponse( + bankCodes = bankCodes.map { it.toResponse() }, + hostedWeb = hostedWeb.toResponse(), + ) + +fun BankCode.toResponse() = + FlutterBankCode( + name = name, + code = code, + ) + +fun HostedWeb.toResponse() = + FlutterHostedWeb( + basicKyc = basicKyc.groupBy { it.countryCode }.mapValues { it.value.first().toResponse() }, + biometricKyc = + biometricKyc.groupBy { it.countryCode } + .mapValues { it.value.first().toResponse() }, + enhancedKyc = + enhancedKyc.groupBy { it.countryCode } + .mapValues { it.value.first().toResponse() }, + documentVerification = + docVerification.groupBy { it.countryCode } + .mapValues { it.value.first().toResponse() }, + enhancedKycSmartSelfie = + enhancedKycSmartSelfie.groupBy { it.countryCode } + .mapValues { it.value.first().toResponse() }, + enhancedDocumentVerification = + enhancedDocumentVerification.groupBy { it.countryCode } + .mapValues { it.value.first().toResponse() }, + ) + +fun CountryInfo.toResponse() = + FlutterCountryInfo( + countryCode = countryCode, + name = name, + availableIdTypes = availableIdTypes.map { it.toResponse() }, + ) + +fun AvailableIdType.toResponse() = + FlutterAvailableIdType( + idTypeKey = idTypeKey, + label = label, + requiredFields = requiredFields.map { it.name }, + testData = testData, + idNumberRegex = idNumberRegex, ) -} - -fun FlutterProductsConfigRequest.toRequest() = ProductsConfigRequest( - partnerId = partnerId, - timestamp = timestamp, - signature = signature, -) - -fun ProductsConfigResponse.toResponse() = FlutterProductsConfigResponse( - consentRequired = consentRequired.mapKeys { it.key }, - idSelection = idSelection.toResponse(), -) - -fun IdSelection.toResponse() = FlutterIdSelection( - basicKyc = basicKyc.mapKeys { it.key }, - biometricKyc = biometricKyc.mapKeys { it.key }, - enhancedKyc = enhancedKyc.mapKeys { it.key }, - documentVerification = documentVerification.mapKeys { it.key }, -) - -fun ValidDocumentsResponse.toResponse() = FlutterValidDocumentsResponse( - validDocuments = validDocuments.map { it.toResponse() }, -) - -fun ValidDocument.toResponse() = FlutterValidDocument( - country = country.toResponse(), - idTypes = idTypes.map { it.toResponse() }, -) - -fun Country.toResponse() = FlutterCountry( - name = name, - code = code, - continent = continent, -) - -fun IdType.toResponse() = FlutterIdType( - name = name, - code = code, - example = example.map { it }, - hasBack = hasBack, -) - -fun ServicesResponse.toResponse() = FlutterServicesResponse( - bankCodes = bankCodes.map { it.toResponse() }, - hostedWeb = hostedWeb.toResponse(), -) - -fun BankCode.toResponse() = FlutterBankCode( - name = name, - code = code, -) - -fun HostedWeb.toResponse() = FlutterHostedWeb( - basicKyc = basicKyc.groupBy { it.countryCode }.mapValues { it.value.first().toResponse() }, - biometricKyc = biometricKyc.groupBy { it.countryCode } - .mapValues { it.value.first().toResponse() }, - enhancedKyc = enhancedKyc.groupBy { it.countryCode } - .mapValues { it.value.first().toResponse() }, - documentVerification = docVerification.groupBy { it.countryCode } - .mapValues { it.value.first().toResponse() }, - enhancedKycSmartSelfie = enhancedKycSmartSelfie.groupBy { it.countryCode } - .mapValues { it.value.first().toResponse() }, - enhancedDocumentVerification = enhancedDocumentVerification.groupBy { it.countryCode } - .mapValues { it.value.first().toResponse() }, -) - -fun CountryInfo.toResponse() = FlutterCountryInfo( - countryCode = countryCode, - name = name, - availableIdTypes = availableIdTypes.map { it.toResponse() }, -) - -fun AvailableIdType.toResponse() = FlutterAvailableIdType( - idTypeKey = idTypeKey, - label = label, - requiredFields = requiredFields.map { it.name }, - testData = testData, - idNumberRegex = idNumberRegex, -) diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileComposablePlatformView.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileComposablePlatformView.kt index 9f45ce55..3c8f5528 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileComposablePlatformView.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileComposablePlatformView.kt @@ -25,7 +25,6 @@ internal abstract class SmileComposablePlatformView( messenger: BinaryMessenger, args: Map, ) : PlatformView { - private val methodChannel = MethodChannel(messenger, "${viewTypeId}_$viewId") /** @@ -34,17 +33,19 @@ internal abstract class SmileComposablePlatformView( * Activity level and since we don't have a full Compose app or nav graph, the same viewModel * ends up getting re-used */ - private val viewModelStoreOwner = object : ViewModelStoreOwner { - override val viewModelStore = ViewModelStore() - } + private val viewModelStoreOwner = + object : ViewModelStoreOwner { + override val viewModelStore = ViewModelStore() + } - private var view: ComposeView? = ComposeView(context).apply { - setContent { - CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - Content(args) + private var view: ComposeView? = + ComposeView(context).apply { + setContent { + CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { + Content(args) + } } } - } /** * Implement this method to provide the actual Composable content for the view @@ -67,15 +68,16 @@ internal abstract class SmileComposablePlatformView( // possibility of the JSON serializing erroring for whatever reason -- if such a thing // happens, we still want to tell the caller that the overall operation was successful. // However, we just may not be able to provide the result JSON. - val json = try { - SmileID.moshi - .adapter(T::class.java) - .toJson(result) - } catch (e: Exception) { - Log.e("SmileComposablePlatformView", "Error serializing result", e) - Log.v("SmileComposablePlatformView", "Result is: $result") - "null" - } + val json = + try { + SmileID.moshi + .adapter(T::class.java) + .toJson(result) + } catch (e: Exception) { + Log.e("SmileComposablePlatformView", "Error serializing result", e) + Log.v("SmileComposablePlatformView", "Result is: $result") + "null" + } methodChannel.invokeMethod("onSuccess", json) } diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDBiometricKYC.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDBiometricKYC.kt index 6dc1e3b1..df891bb9 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDBiometricKYC.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDBiometricKYC.kt @@ -28,17 +28,18 @@ internal class SmileIDBiometricKYC private constructor( override fun Content(args: Map) { val extraPartnerParams = args["extraPartnerParams"] as? Map ?: emptyMap() SmileID.BiometricKYC( - idInfo = IdInfo( - country = args["country"] as? String ?: "", - idType = args["idType"] as? String?, - idNumber = args["idNumber"] as? String?, - firstName = args["firstName"] as? String?, - middleName = args["middleName"] as? String?, - lastName = args["lastName"] as? String?, - dob = args["dob"] as? String?, - bankCode = args["bankCode"] as? String?, - entered = args["entered"] as? Boolean?, - ), + idInfo = + IdInfo( + country = args["country"] as? String ?: "", + idType = args["idType"] as? String?, + idNumber = args["idNumber"] as? String?, + firstName = args["firstName"] as? String?, + middleName = args["middleName"] as? String?, + lastName = args["lastName"] as? String?, + dob = args["dob"] as? String?, + bankCode = args["bankCode"] as? String?, + entered = args["entered"] as? Boolean?, + ), userId = args["userId"] as? String ?: randomUserId(), jobId = args["jobId"] as? String ?: randomJobId(), allowNewEnroll = args["allowNewEnroll"] as? Boolean ?: false, @@ -57,7 +58,11 @@ internal class SmileIDBiometricKYC private constructor( class Factory( private val messenger: BinaryMessenger, ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + override fun create( + context: Context, + viewId: Int, + args: Any?, + ): PlatformView { @Suppress("UNCHECKED_CAST") return SmileIDBiometricKYC( context, diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDDocumentVerification.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDDocumentVerification.kt index ea502024..88c77eb5 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDDocumentVerification.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDDocumentVerification.kt @@ -33,7 +33,7 @@ internal class SmileIDDocumentVerification private constructor( idAspectRatio = (args["idAspectRatio"] as Double?)?.toFloat(), captureBothSides = args["captureBothSides"] as? Boolean ?: true, bypassSelfieCaptureWithFile = - (args["bypassSelfieCaptureWithFile"] as? String)?.let { File(it) }, + (args["bypassSelfieCaptureWithFile"] as? String)?.let { File(it) }, userId = args["userId"] as? String ?: randomUserId(), jobId = args["jobId"] as? String ?: randomJobId(), allowNewEnroll = args["allowNewEnroll"] as? Boolean ?: false, @@ -53,7 +53,11 @@ internal class SmileIDDocumentVerification private constructor( class Factory( private val messenger: BinaryMessenger, ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + override fun create( + context: Context, + viewId: Int, + args: Any?, + ): PlatformView { @Suppress("UNCHECKED_CAST") return SmileIDDocumentVerification( context, diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDEnhancedDocumentVerification.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDEnhancedDocumentVerification.kt index 4022a4ae..27506b34 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDEnhancedDocumentVerification.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDEnhancedDocumentVerification.kt @@ -50,7 +50,11 @@ internal class SmileIDEnhancedDocumentVerification private constructor( class Factory( private val messenger: BinaryMessenger, ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + override fun create( + context: Context, + viewId: Int, + args: Any?, + ): PlatformView { @Suppress("UNCHECKED_CAST") return SmileIDEnhancedDocumentVerification( context, diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDPlugin.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDPlugin.kt index 0199efde..a8d9d08c 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDPlugin.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDPlugin.kt @@ -111,7 +111,10 @@ class SmileIDPlugin : FlutterPlugin, SmileIDApi, ActivityAware { SmileID.cleanup(jobIds = jobIds) } - override fun submitJob(jobId: String, deleteFilesOnSuccess: Boolean) { + override fun submitJob( + jobId: String, + deleteFilesOnSuccess: Boolean, + ) { scope.launch { SmileID.submitJob(jobId = jobId, deleteFilesOnSuccess = deleteFilesOnSuccess) } @@ -182,16 +185,18 @@ class SmileIDPlugin : FlutterPlugin, SmileIDApi, ActivityAware { work = { SmileID.api.doSmartSelfieEnrollment( userId = userId, - selfieImage = File(selfieImage).asFormDataPart( - partName = "selfie_image", - mediaType = "image/jpeg", - ), - livenessImages = livenessImages.map { + selfieImage = File(selfieImage).asFormDataPart( - partName = "liveness_images", + partName = "selfie_image", mediaType = "image/jpeg", - ) - }, + ), + livenessImages = + livenessImages.map { + File(selfieImage).asFormDataPart( + partName = "liveness_images", + mediaType = "image/jpeg", + ) + }, partnerParams = convertNullableMapToNonNull(partnerParams), callbackUrl = callbackUrl, sandboxResult = sandboxResult?.toInt(), @@ -216,16 +221,18 @@ class SmileIDPlugin : FlutterPlugin, SmileIDApi, ActivityAware { work = { SmileID.api.doSmartSelfieAuthentication( userId = userId, - selfieImage = File(selfieImage).asFormDataPart( - partName = "selfie_image", - mediaType = "image/jpeg", - ), - livenessImages = livenessImages.map { + selfieImage = File(selfieImage).asFormDataPart( - partName = "liveness_images", + partName = "selfie_image", mediaType = "image/jpeg", - ) - }, + ), + livenessImages = + livenessImages.map { + File(selfieImage).asFormDataPart( + partName = "liveness_images", + mediaType = "image/jpeg", + ) + }, partnerParams = convertNullableMapToNonNull(partnerParams), callbackUrl = callbackUrl, sandboxResult = sandboxResult?.toInt(), diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieAuthentication.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieAuthentication.kt index bfa84718..5322b302 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieAuthentication.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieAuthentication.kt @@ -45,7 +45,11 @@ internal class SmileIDSmartSelfieAuthentication private constructor( class Factory( private val messenger: BinaryMessenger, ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + override fun create( + context: Context, + viewId: Int, + args: Any?, + ): PlatformView { @Suppress("UNCHECKED_CAST") return SmileIDSmartSelfieAuthentication( context, diff --git a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieEnrollment.kt b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieEnrollment.kt index c9f7653e..eabee3c2 100644 --- a/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieEnrollment.kt +++ b/android/src/main/kotlin/com/smileidentity/flutter/SmileIDSmartSelfieEnrollment.kt @@ -45,7 +45,11 @@ internal class SmileIDSmartSelfieEnrollment private constructor( class Factory( private val messenger: BinaryMessenger, ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + override fun create( + context: Context, + viewId: Int, + args: Any?, + ): PlatformView { @Suppress("UNCHECKED_CAST") return SmileIDSmartSelfieEnrollment( context, diff --git a/android/src/test/kotlin/com/smileidentity/flutter/SmileIDPluginTest.kt b/android/src/test/kotlin/com/smileidentity/flutter/SmileIDPluginTest.kt index 845de642..ce5035a9 100644 --- a/android/src/test/kotlin/com/smileidentity/flutter/SmileIDPluginTest.kt +++ b/android/src/test/kotlin/com/smileidentity/flutter/SmileIDPluginTest.kt @@ -47,9 +47,8 @@ internal class SmileIDPluginTest { confirmVerified(api) } - // ktlint-disable max-line-length @Test - fun `when we call doEnhancedKycAsync and pass a request object, we get a successful callback`() { + fun `when we call doEnhancedKycAsync with a request object, we get a successful callback`() { val request = mockk() val callback = mockk<(Result) -> Unit>() val api = mockk() diff --git a/example/android/build.gradle b/example/android/build.gradle index 3d287a58..dbe2aea0 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -7,9 +7,9 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.1.2' + classpath 'com.android.tools.build:gradle:8.1.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jlleitschuh.gradle:ktlint-gradle:11.6.1" + classpath "org.jlleitschuh.gradle:ktlint-gradle:12.1.1" } } @@ -21,13 +21,15 @@ allprojects { } rootProject.buildDir = "../build" + subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } + subprojects { project.evaluationDependsOn(":app") } tasks.register("clean", Delete) { delete rootProject.buildDir -} +} \ No newline at end of file