Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save SmartSelfie Enrollment userId on job completion #83

Merged
merged 1 commit into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions Example/SmileID/EnterUserIDView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ import SmileID

struct EnterUserIDView: View {
let onContinue: (_ userId: String) -> Void
@State private var userId: String = ""
@State private var userId: String

init(
initialUserId: String? = nil,
initialUserId: String = "",
onContinue: @escaping (String) -> Void
) {
self.onContinue = onContinue
if let initialUserId = initialUserId {
userId = initialUserId
}
userId = initialUserId
}

var body: some View {
Expand Down
49 changes: 45 additions & 4 deletions Example/SmileID/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ struct HomeView: View {
let partner = SmileID.configuration.partnerId
let version = SmileID.version
let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"
@State private var smartSelfieEnrollmentUserId: String = ""
@ObservedObject var viewModel = HomeViewModel()

var body: some View {
Expand All @@ -20,17 +21,30 @@ struct HomeView: View {
ProductCell(
image: "userauth",
name: "SmartSelfie™ Enrollment",
onClick: { smartSelfieEnrollmentUserId = generateUserId() },
content: SmileID.smartSelfieEnrollmentScreen(
userId: generateUserId(),
userId: smartSelfieEnrollmentUserId,
allowAgentMode: true,
delegate: viewModel
delegate: SmartSelfieEnrollmentDelegate(
userId: smartSelfieEnrollmentUserId,
onEnrollmentSuccess: {
userId, selfieFile, livenessImages, jobStatusResponse in
viewModel.onSmartSelfieEnrollment(
userId: userId,
selfieImage: selfieFile,
livenessImages: livenessImages,
jobStatusResponse: jobStatusResponse
)
},
onError: viewModel.didError
)
)
),
ProductCell(
image: "userauth",
name: "SmartSelfie™ Authentication",
content: SmartSelfieAuthWithUserIdEntry(
initialUserId: viewModel.returnedUserID,
initialUserId: smartSelfieEnrollmentUserId,
delegate: viewModel
)
),
Expand Down Expand Up @@ -67,8 +81,35 @@ struct HomeView: View {
}
}

// We need to define a separate proxy delegate because it's the same protocol for both Enrollment
// and Authentication. However, since the result is still processing, the result parameter is not
// yet populated (which is what contains the jobType). On Enroll, we need to perform a different
// action (namely, save userId to clipboard)
struct SmartSelfieEnrollmentDelegate: SmartSelfieResultDelegate {
let userId: String
let onEnrollmentSuccess: (
_ userId: String,
_ selfieFile: URL,
_ livenessImages: [URL],
_ jobStatusResponse: SmartSelfieJobStatusResponse
) -> Void
let onError: (Error) -> Void

func didSucceed(
selfieImage: URL,
livenessImages: [URL],
jobStatusResponse: SmartSelfieJobStatusResponse
) {
onEnrollmentSuccess(userId, selfieImage, livenessImages, jobStatusResponse)
}

func didError(error: Error) {
onError(error)
}
}

private struct SmartSelfieAuthWithUserIdEntry: View {
let initialUserId: String?
let initialUserId: String
let delegate: SmartSelfieResultDelegate
@State private var userId: String?

Expand Down
62 changes: 34 additions & 28 deletions Example/SmileID/HomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,48 +8,48 @@ class HomeViewModel: ObservableObject,
DocumentVerificationResultDelegate,
EnhancedDocumentVerificationResultDelegate {

// MARK: - UI Properties
@Published var dismissed = false
@Published var toastMessage = ""
@Published var showToast = false

var returnedUserID: String?

@objc func didError(error: Error) {
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
// Called for SmartSelfie Enrollment by a proxy delegate in HomeView
func onSmartSelfieEnrollment(
userId: String,
selfieImage: URL,
livenessImages: [URL],
jobStatusResponse: JobStatusResponse<SmartSelfieJobResult>
) {
showToast = true
toastMessage = error.localizedDescription
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
UIPasteboard.general.string = userId
toastMessage = jobResultMessageBuilder(
jobName: "SmartSelfie Enrollment",
jobComplete: jobStatusResponse.jobComplete,
jobSuccess: jobStatusResponse.jobSuccess,
code: jobStatusResponse.code,
resultCode: jobStatusResponse.result?.resultCode,
resultText: jobStatusResponse.result?.resultText,
suffix: "The User ID has been copied to your clipboard"
)
}

// Called only for SmartSelfie Authentication
func didSucceed(
selfieImage: URL,
livenessImages: [URL],
jobStatusResponse: JobStatusResponse<SmartSelfieJobResult>
) {
showToast = true
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
let partnerParams = jobStatusResponse.result?.partnerParams
if partnerParams?.jobType == .smartSelfieEnrollment {
returnedUserID = partnerParams?.userId
UIPasteboard.general.string = returnedUserID
toastMessage = jobResultMessageBuilder(
jobName: "SmartSelfie Enrollment",
jobComplete: jobStatusResponse.jobComplete,
jobSuccess: jobStatusResponse.jobSuccess,
code: jobStatusResponse.code,
resultCode: jobStatusResponse.result?.resultCode,
resultText: jobStatusResponse.result?.resultText,
suffix: "The User ID has been copied to your clipboard"
)
} else {
toastMessage = jobResultMessageBuilder(
jobName: "SmartSelfie Authentication",
jobComplete: jobStatusResponse.jobComplete,
jobSuccess: jobStatusResponse.jobSuccess,
code: jobStatusResponse.code,
resultCode: jobStatusResponse.result?.resultCode,
resultText: jobStatusResponse.result?.resultText
)
}
toastMessage = jobResultMessageBuilder(
jobName: "SmartSelfie Authentication",
jobComplete: jobStatusResponse.jobComplete,
jobSuccess: jobStatusResponse.jobSuccess,
code: jobStatusResponse.code,
resultCode: jobStatusResponse.result?.resultCode,
resultText: jobStatusResponse.result?.resultText
)
}

func didSucceed(
Expand Down Expand Up @@ -87,4 +87,10 @@ class HomeViewModel: ObservableObject,
resultText: jobStatusResponse.result?.resultText
)
}

@objc func didError(error: Error) {
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
showToast = true
toastMessage = error.localizedDescription
}
}
14 changes: 12 additions & 2 deletions Example/SmileID/ProductCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@ import SmileID
struct ProductCell: View {
let image: String
let name: String
let onClick: (() -> Void)?
let content: any View
@State private var isPresented: Bool = false

init(image: String, name: String, content: any View) {
init(
image: String,
name: String,
onClick: (() -> Void)? = nil,
content: any View
) {
self.image = image
self.name = name
self.onClick = onClick
self.content = content
}

public var body: some View {
Button(
action: { isPresented = true },
action: {
onClick?()
isPresented = true
},
label: {
VStack(spacing: 24) {
Image(image)
Expand Down
1 change: 1 addition & 0 deletions Example/SmileID/SmileTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct SmileTextField: View {
.font(SmileID.theme.button)
.padding()
.background(RoundedRectangle(cornerRadius: 10).fill(backgroundColor))
.textFieldStyle(.roundedBorder)
.foregroundColor(textColor)
.padding()
}
Expand Down
Loading