Skip to content

Commit

Permalink
Fix iOS Issues (#131)
Browse files Browse the repository at this point in the history
* fix padding issue with selfie capture view.

* run pod install.

* code formatting.

* uncomment factory methods for enhanced selfie enrolment and authentication.
provide a navigation view container for the selfie capture screens to fix navigation issue.

* bump up iOS version

* version bump and updated changelog

* run pod install

* fix parameter for selfie capture initializer

* refactor how the json data from did succeed is encoded for on success event.

* run pod install

---------

Co-authored-by: Juma Allan <allanjuma@gmail.com>
  • Loading branch information
tobitech and jumaallan authored Dec 16, 2024
1 parent 07cda05 commit 65351ab
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 109 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## 10.3.1

* Fixed Moshi configuration to only use FileAdapter which uses absolute path
* Fixed iOS navigation setup
* Bump iOS to 10.3.2 (https://github.com/smileidentity/ios/releases/tag/v10.3.2)

## 10.3.0

Expand Down
10 changes: 5 additions & 5 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ PODS:
- integration_test (0.0.1):
- Flutter
- lottie-ios (4.4.3)
- smile_id (10.3.1):
- smile_id (10.3.2):
- Flutter
- SmileID (= 10.3.1)
- SmileID (10.3.1):
- SmileID (= 10.3.2)
- SmileID (10.3.2):
- FingerprintJS
- lottie-ios (~> 4.4.2)
- ZIPFoundation (~> 0.9)
Expand Down Expand Up @@ -42,8 +42,8 @@ SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
lottie-ios: fcb5e73e17ba4c983140b7d21095c834b3087418
smile_id: 0dda462b0a99ae72bb96f37cacfc8b6d36d61957
SmileID: ec46d9db430ffafc69831914b15f4058912ea083
smile_id: bac1ccef93d28805bf906ee8aa8cc61ef5b52366
SmileID: 650b97c8786e4d79851b08bb5a12ae149ea78f38
ZIPFoundation: b8c29ea7ae353b309bc810586181fd073cb3312c

PODFILE CHECKSUM: 929954fb8941cef06249e96bd1516fd2a22ed7a5
Expand Down
4 changes: 3 additions & 1 deletion ios/Classes/FileUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ protocol SmileIDFileUtilsProtocol {

extension SmileIDFileUtilsProtocol {
func getSmileIDDirectory() -> String? {
guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
guard let documentsDirectory = fileManager.urls(
for: .documentDirectory, in: .userDomainMask
).first else {
print("Unable to access documents directory")
return nil
}
Expand Down
12 changes: 7 additions & 5 deletions ios/Classes/FlutterPlatformView+EmbedSwiftUIView.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Flutter
import UIKit
import SwiftUI
import UIKit

extension FlutterPlatformView {
/// Embeds a SwiftUI view into a UIKit view hierarchy for a view class that conforms to `FlutterPlatformView`
Expand All @@ -25,13 +25,15 @@ extension FlutterPlatformView {
frame: CGRect
) -> UIViewController {
let hostingController = UIHostingController(rootView: swiftUIView)

hostingController.view.frame = frame
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
parentView.addSubview(hostingController.view)

if let navigationController = UIApplication.shared.windows.first?.rootViewController as? UINavigationController,
let flutterViewController = navigationController.viewControllers.first as? FlutterViewController {

if let navigationController = UIApplication.shared.windows.first?.rootViewController
as? UINavigationController,
let flutterViewController = navigationController.viewControllers.first
as? FlutterViewController {
flutterViewController.addChild(hostingController)
parentView.addSubview(hostingController.view)
hostingController.view.setNeedsLayout()
Expand Down
30 changes: 15 additions & 15 deletions ios/Classes/SmileIDPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,21 @@ public class SmileIDPlugin: NSObject, FlutterPlugin, SmileIDApi {
withId: SmileIDSmartSelfieAuthentication.VIEW_TYPE_ID
)

// let smartSelfieEnrollmentEnhancedFactory = SmileIDSmartSelfieEnrollmentEnhanced.Factory(
// messenger: registrar.messenger()
// )
// registrar.register(
// smartSelfieEnrollmentEnhancedFactory,
// withId: SmileIDSmartSelfieEnrollmentEnhanced.VIEW_TYPE_ID
// )
//
// let smartSelfieAuthenticationEnhancedFactory = SmileIDSmartSelfieAuthenticationEnhanced.Factory(
// messenger: registrar.messenger()
// )
// registrar.register(
// smartSelfieAuthenticationEnhancedFactory,
// withId: SmileIDSmartSelfieAuthenticationEnhanced.VIEW_TYPE_ID
// )
let smartSelfieEnrollmentEnhancedFactory = SmileIDSmartSelfieEnrollmentEnhanced.Factory(
messenger: registrar.messenger()
)
registrar.register(
smartSelfieEnrollmentEnhancedFactory,
withId: SmileIDSmartSelfieEnrollmentEnhanced.VIEW_TYPE_ID
)

let smartSelfieAuthenticationEnhancedFactory = SmileIDSmartSelfieAuthenticationEnhanced.Factory(
messenger: registrar.messenger()
)
registrar.register(
smartSelfieAuthenticationEnhancedFactory,
withId: SmileIDSmartSelfieAuthenticationEnhanced.VIEW_TYPE_ID
)

let biometricKYCFactory = SmileIDBiometricKYC.Factory(
messenger: registrar.messenger()
Expand Down
29 changes: 9 additions & 20 deletions ios/Classes/SmileIDSmartSelfieAuthentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,16 @@ class SmileIDSmartSelfieAuthentication : NSObject, FlutterPlatformView, SmartSel

func didSucceed(selfieImage: URL, livenessImages: [URL], apiResponse: SmartSelfieResponse?) {
_childViewController?.removeFromParent()
var arguments: [String: Any] = [
"selfieFile": getFilePath(fileName: selfieImage.absoluteString),
"livenessFiles": livenessImages.map {
getFilePath(fileName: $0.absoluteString)
let successData = SmartSelfieSuccessData(
selfieFile: getFilePath(fileName: selfieImage.absoluteString),
livenessFiles: livenessImages.map {
getFilePath(fileName: $0.absoluteString)
},
]
if let apiResponse = apiResponse {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
if let jsonData = try? encoder.encode(apiResponse),
let jsonString = String(data: jsonData, encoding: .utf8) {
arguments["apiResponse"] = jsonString
}
}
do {
let jsonData = try JSONSerialization.data(withJSONObject: arguments, options: [])
if let jsonString = String(data: jsonData, encoding: .utf8) {
_channel.invokeMethod("onSuccess", arguments: jsonString)
}
} catch {
didError(error: error)
apiResponse: apiResponse
)

if let jsonString = successData.toJSONString() {
_channel.invokeMethod("onSuccess", arguments: jsonString)
}
}

Expand Down
37 changes: 34 additions & 3 deletions ios/Classes/SmileIDSmartSelfieAuthenticationEnhanced.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class SmileIDSmartSelfieAuthenticationEnhanced : NSObject, FlutterPlatformView,
)
_childViewController = nil
super.init()
let screen = SmileID.smartSelfieAuthenticationScreenEnhanced(
let screen = EnhancedSelfieAuthenticationRootView(
userId: args["userId"] as? String ?? "user-\(UUID().uuidString)",
allowNewEnroll: args["allowNewEnroll"] as? Bool ?? false,
showAttribution: args["showAttribution"] as? Bool ?? true,
Expand All @@ -41,15 +41,24 @@ class SmileIDSmartSelfieAuthenticationEnhanced : NSObject, FlutterPlatformView,

func didSucceed(selfieImage: URL, livenessImages: [URL], apiResponse: SmartSelfieResponse?) {
_childViewController?.removeFromParent()
// todo
let successData = SmartSelfieSuccessData(
selfieFile: getFilePath(fileName: selfieImage.absoluteString),
livenessFiles: livenessImages.map {
getFilePath(fileName: $0.absoluteString)
},
apiResponse: apiResponse
)

if let jsonString = successData.toJSONString() {
_channel.invokeMethod("onSuccess", arguments: jsonString)
}
}

func didError(error: Error) {
print("[Smile ID] An error occurred - \(error.localizedDescription)")
_channel.invokeMethod("onError", arguments: error.localizedDescription)
}


class Factory : NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
Expand All @@ -75,3 +84,25 @@ class SmileIDSmartSelfieAuthenticationEnhanced : NSObject, FlutterPlatformView,
}
}
}

struct EnhancedSelfieAuthenticationRootView: View {
let userId: String
let allowNewEnroll: Bool
let showAttribution: Bool
let showInstructions: Bool
let extraPartnerParams: [String: String]
let delegate: SmartSelfieResultDelegate

var body: some View {
NavigationView {
SmileID.smartSelfieAuthenticationScreenEnhanced(
userId: userId,
allowNewEnroll: allowNewEnroll,
showAttribution: showAttribution,
showInstructions: showInstructions,
extraPartnerParams: extraPartnerParams,
delegate: delegate
)
}
}
}
68 changes: 34 additions & 34 deletions ios/Classes/SmileIDSmartSelfieCaptureView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,40 +75,40 @@ struct SmileIDRootView: View {

var body: some View {
NavigationView {
// Group {
// if showInstructions, !acknowledgedInstructions {
// SmartSelfieInstructionsScreen(showAttribution: showAttribution) {
// acknowledgedInstructions = true
// }
// } else if viewModel.processingState != nil {
// Color.clear.onAppear {
// self.viewModel.onFinished(callback: self)
// }
// } else if let selfieToConfirm = viewModel.selfieToConfirm{
// if(showConfirmationDialog){
// ImageCaptureConfirmationDialog(
// title: SmileIDResourcesHelper.localizedString(for: "Confirmation.GoodSelfie"),
// subtitle: SmileIDResourcesHelper.localizedString(for: "Confirmation.FaceClear"),
// image: UIImage(data: selfieToConfirm)!,
// confirmationButtonText: SmileIDResourcesHelper.localizedString(for: "Confirmation.YesUse"),
// onConfirm: viewModel.submitJob,
// retakeButtonText: SmileIDResourcesHelper.localizedString(for: "Confirmation.Retake"),
// onRetake: viewModel.onSelfieRejected,
// scaleFactor: 1.25
// ).preferredColorScheme(.light)
// }else{
// Color.clear.onAppear {
// self.viewModel.submitJob()
// }
// }
// } else {
// SelfieCaptureScreen(
// allowAgentMode: allowAgentMode,
// viewModel: viewModel
// ).preferredColorScheme(.light)
// }
// }
}.padding()
Group {
if showInstructions, !acknowledgedInstructions {
SmartSelfieInstructionsScreen(showAttribution: showAttribution) {
acknowledgedInstructions = true
}
.padding()
} else if viewModel.processingState != nil {
Color.clear.onAppear {
self.viewModel.onFinished(callback: self)
}
} else if let selfieToConfirm = viewModel.selfieToConfirm{
if(showConfirmationDialog){
ImageCaptureConfirmationDialog(
title: SmileIDResourcesHelper.localizedString(for: "Confirmation.GoodSelfie"),
subtitle: SmileIDResourcesHelper.localizedString(for: "Confirmation.FaceClear"),
image: UIImage(data: selfieToConfirm)!,
confirmationButtonText: SmileIDResourcesHelper.localizedString(for: "Confirmation.YesUse"),
onConfirm: viewModel.submitJob,
retakeButtonText: SmileIDResourcesHelper.localizedString(for: "Confirmation.Retake"),
onRetake: viewModel.onSelfieRejected,
scaleFactor: 1.25
).preferredColorScheme(.light)
}else{
Color.clear.onAppear {
self.viewModel.submitJob()
}
}
} else {
SelfieCaptureScreen(
viewModel: viewModel, allowAgentMode: allowAgentMode
).preferredColorScheme(.light)
}
}
}
}


Expand Down
31 changes: 10 additions & 21 deletions ios/Classes/SmileIDSmartSelfieEnrollment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,16 @@ class SmileIDSmartSelfieEnrollment : NSObject, FlutterPlatformView, SmartSelfieR

func didSucceed(selfieImage: URL, livenessImages: [URL], apiResponse: SmartSelfieResponse?) {
_childViewController?.removeFromParent()
var arguments: [String: Any] = [
"selfieFile": getFilePath(fileName: selfieImage.absoluteString),
"livenessFiles": livenessImages.map {
getFilePath(fileName: $0.absoluteString)
}
]
if let apiResponse = apiResponse {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
if let jsonData = try? encoder.encode(apiResponse),
let jsonString = String(data: jsonData, encoding: .utf8) {
arguments["apiResponse"] = jsonString
}
}
do {
let jsonData = try JSONSerialization.data(withJSONObject: arguments, options: [])
if let jsonString = String(data: jsonData, encoding: .utf8) {
_channel.invokeMethod("onSuccess", arguments: jsonString)
}
} catch {
didError(error: error)
let successData = SmartSelfieSuccessData(
selfieFile: getFilePath(fileName: selfieImage.absoluteString),
livenessFiles: livenessImages.map {
getFilePath(fileName: $0.absoluteString)
},
apiResponse: apiResponse
)

if let jsonString = successData.toJSONString() {
_channel.invokeMethod("onSuccess", arguments: jsonString)
}
}

Expand Down
53 changes: 51 additions & 2 deletions ios/Classes/SmileIDSmartSelfieEnrollmentEnhanced.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class SmileIDSmartSelfieEnrollmentEnhanced : NSObject, FlutterPlatformView, Smar
)
_childViewController = nil
super.init()
let screen = SmileID.smartSelfieEnrollmentScreenEnhanced(
let screen = EnhancedSelfieEnrollmentRootView.init(
userId: args["userId"] as? String ?? "user-\(UUID().uuidString)",
allowNewEnroll: args["allowNewEnroll"] as? Bool ?? false,
showAttribution: args["showAttribution"] as? Bool ?? true,
Expand All @@ -41,7 +41,17 @@ class SmileIDSmartSelfieEnrollmentEnhanced : NSObject, FlutterPlatformView, Smar

func didSucceed(selfieImage: URL, livenessImages: [URL], apiResponse: SmartSelfieResponse?) {
_childViewController?.removeFromParent()
// todo
let successData = SmartSelfieSuccessData(
selfieFile: getFilePath(fileName: selfieImage.absoluteString),
livenessFiles: livenessImages.map {
getFilePath(fileName: $0.absoluteString)
},
apiResponse: apiResponse
)

if let jsonString = successData.toJSONString() {
_channel.invokeMethod("onSuccess", arguments: jsonString)
}
}

func didError(error: Error) {
Expand Down Expand Up @@ -74,3 +84,42 @@ class SmileIDSmartSelfieEnrollmentEnhanced : NSObject, FlutterPlatformView, Smar
}
}
}

struct SmartSelfieSuccessData: Encodable {
let selfieFile: String
let livenessFiles: [String]
let apiResponse: SmartSelfieResponse?

func toJSONString() -> String? {
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .withoutEscapingSlashes
let json = try? jsonEncoder.encode(self)
guard let data = json,
let jsonString = String(data: data, encoding: .utf8) else {
return nil
}
return jsonString
}
}

struct EnhancedSelfieEnrollmentRootView: View {
let userId: String
let allowNewEnroll: Bool
let showAttribution: Bool
let showInstructions: Bool
let extraPartnerParams: [String: String]
let delegate: SmartSelfieResultDelegate

var body: some View {
NavigationView {
SmileID.smartSelfieEnrollmentScreenEnhanced(
userId: userId,
allowNewEnroll: allowNewEnroll,
showAttribution: showAttribution,
showInstructions: showInstructions,
extraPartnerParams: extraPartnerParams,
delegate: delegate
)
}
}
}
Loading

0 comments on commit 65351ab

Please sign in to comment.