diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd94a5..81eaad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 9315e03..9d82255 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -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) @@ -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 diff --git a/ios/Classes/FileUtils.swift b/ios/Classes/FileUtils.swift index 092a300..33fa308 100644 --- a/ios/Classes/FileUtils.swift +++ b/ios/Classes/FileUtils.swift @@ -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 } diff --git a/ios/Classes/FlutterPlatformView+EmbedSwiftUIView.swift b/ios/Classes/FlutterPlatformView+EmbedSwiftUIView.swift index f3a34e7..5af93df 100644 --- a/ios/Classes/FlutterPlatformView+EmbedSwiftUIView.swift +++ b/ios/Classes/FlutterPlatformView+EmbedSwiftUIView.swift @@ -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` @@ -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() diff --git a/ios/Classes/SmileIDPlugin.swift b/ios/Classes/SmileIDPlugin.swift index 3a04c89..d8e9844 100644 --- a/ios/Classes/SmileIDPlugin.swift +++ b/ios/Classes/SmileIDPlugin.swift @@ -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() diff --git a/ios/Classes/SmileIDSmartSelfieAuthentication.swift b/ios/Classes/SmileIDSmartSelfieAuthentication.swift index bba18fe..e2e876b 100644 --- a/ios/Classes/SmileIDSmartSelfieAuthentication.swift +++ b/ios/Classes/SmileIDSmartSelfieAuthentication.swift @@ -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) } } diff --git a/ios/Classes/SmileIDSmartSelfieAuthenticationEnhanced.swift b/ios/Classes/SmileIDSmartSelfieAuthenticationEnhanced.swift index 695741f..5a84d53 100644 --- a/ios/Classes/SmileIDSmartSelfieAuthenticationEnhanced.swift +++ b/ios/Classes/SmileIDSmartSelfieAuthenticationEnhanced.swift @@ -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, @@ -41,7 +41,17 @@ 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) { @@ -49,7 +59,6 @@ class SmileIDSmartSelfieAuthenticationEnhanced : NSObject, FlutterPlatformView, _channel.invokeMethod("onError", arguments: error.localizedDescription) } - class Factory : NSObject, FlutterPlatformViewFactory { private var messenger: FlutterBinaryMessenger init(messenger: FlutterBinaryMessenger) { @@ -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 + ) + } + } +} diff --git a/ios/Classes/SmileIDSmartSelfieCaptureView.swift b/ios/Classes/SmileIDSmartSelfieCaptureView.swift index 17a4f5b..a41243d 100644 --- a/ios/Classes/SmileIDSmartSelfieCaptureView.swift +++ b/ios/Classes/SmileIDSmartSelfieCaptureView.swift @@ -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) + } + } + } } diff --git a/ios/Classes/SmileIDSmartSelfieEnrollment.swift b/ios/Classes/SmileIDSmartSelfieEnrollment.swift index 0b3b224..c5412a8 100644 --- a/ios/Classes/SmileIDSmartSelfieEnrollment.swift +++ b/ios/Classes/SmileIDSmartSelfieEnrollment.swift @@ -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) } } diff --git a/ios/Classes/SmileIDSmartSelfieEnrollmentEnhanced.swift b/ios/Classes/SmileIDSmartSelfieEnrollmentEnhanced.swift index 4cebf1d..e7972e4 100644 --- a/ios/Classes/SmileIDSmartSelfieEnrollmentEnhanced.swift +++ b/ios/Classes/SmileIDSmartSelfieEnrollmentEnhanced.swift @@ -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, @@ -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) { @@ -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 + ) + } + } +} diff --git a/ios/smile_id.podspec b/ios/smile_id.podspec index 82354d3..461c410 100644 --- a/ios/smile_id.podspec +++ b/ios/smile_id.podspec @@ -4,7 +4,7 @@ Pod::Spec.new do |s| s.name = 'smile_id' # NB! Keep this version in sync with the Native iOS SDK version - s.version = '10.3.1' + s.version = '10.3.2' s.summary = 'Official Smile ID SDK for Flutter' s.description = <<-DESC A new Flutter project. @@ -15,7 +15,7 @@ A new Flutter project. s.source_files = 'Classes/**/*' s.dependency 'Flutter' # NB! Update the s.version above when changing this version - s.dependency 'SmileID', '10.3.1' + s.dependency 'SmileID', '10.3.2' s.platform = :ios, '13.0' # Flutter.framework does not contain a i386 slice. diff --git a/pubspec.yaml b/pubspec.yaml index 4de680e..9118924 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: smile_id description: The Official Smile ID Flutter SDK -version: 10.3.0 +version: 10.3.1 homepage: "https://usesmileid.com" environment: