From 00cd5112fb85d0051d5caf61170f3088cf79b083 Mon Sep 17 00:00:00 2001 From: Juma Allan Date: Mon, 19 Aug 2024 12:21:50 +0300 Subject: [PATCH 1/2] temporarily force the light mode even if the user is in dark mode (#219) --- .../SmileID/Classes/Consent/OrchestratedConsentScreen.swift | 4 ++-- .../Classes/DocumentVerification/View/CaptureButton.swift | 1 + .../View/DocumentCaptureInstructionsScreen.swift | 1 + .../DocumentVerification/View/DocumentCaptureScreen.swift | 1 + .../DocumentVerification/View/DocumentShapedBoundingBox.swift | 2 +- Sources/SmileID/Classes/Navigation/NavigationBar.swift | 1 + .../SelfieCapture/View/FaceShapedProgressIndicator.swift | 1 + .../Classes/SelfieCapture/View/InfiniteProgressBar.swift | 1 + .../Classes/SelfieCapture/View/SelfieCaptureScreen.swift | 1 + .../SelfieCapture/View/SmartSelfieInstructionsScreen.swift | 1 + Sources/SmileID/Classes/SelfieCapture/View/SmileButton.swift | 1 + .../Classes/Views/ImageCaptureConfirmationDialog.swift | 1 + Sources/SmileID/Classes/Views/ProcessingScreen.swift | 3 +++ Sources/SmileID/Classes/Views/RadioGroupSelector.swift | 1 + .../SmileID/Classes/Views/SearchableDropdownSelector.swift | 2 +- 15 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Sources/SmileID/Classes/Consent/OrchestratedConsentScreen.swift b/Sources/SmileID/Classes/Consent/OrchestratedConsentScreen.swift index 85fafb2bc..9224c27d9 100644 --- a/Sources/SmileID/Classes/Consent/OrchestratedConsentScreen.swift +++ b/Sources/SmileID/Classes/Consent/OrchestratedConsentScreen.swift @@ -149,7 +149,7 @@ public struct ConsentScreen: View { Image(uiImage: SmileIDResourcesHelper.SmileEmblem) } } - } + }.preferredColorScheme(.light) } } @@ -208,6 +208,6 @@ public struct ConsentDeniedScreen: View { if showAttribution { Image(uiImage: SmileIDResourcesHelper.SmileEmblem) } - } + }.preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/DocumentVerification/View/CaptureButton.swift b/Sources/SmileID/Classes/DocumentVerification/View/CaptureButton.swift index ac0521ac1..2b7aacb11 100644 --- a/Sources/SmileID/Classes/DocumentVerification/View/CaptureButton.swift +++ b/Sources/SmileID/Classes/DocumentVerification/View/CaptureButton.swift @@ -8,6 +8,7 @@ struct CaptureButton: View { label: { Image(uiImage: SmileIDResourcesHelper.Capture) } ) .frame(width: 70, height: 70, alignment: .center) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureInstructionsScreen.swift b/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureInstructionsScreen.swift index 2d4b08724..efbed632a 100644 --- a/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureInstructionsScreen.swift +++ b/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureInstructionsScreen.swift @@ -107,5 +107,6 @@ public struct DocumentCaptureInstructionsScreen: View { } } .padding(.horizontal, 16) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureScreen.swift b/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureScreen.swift index 2903a06f6..a78970778 100644 --- a/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureScreen.swift +++ b/Sources/SmileID/Classes/DocumentVerification/View/DocumentCaptureScreen.swift @@ -160,5 +160,6 @@ struct CaptureScreenContent: View { Spacer() } .frame(maxWidth: .infinity, maxHeight: .infinity) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/DocumentVerification/View/DocumentShapedBoundingBox.swift b/Sources/SmileID/Classes/DocumentVerification/View/DocumentShapedBoundingBox.swift index 4e0dc281a..009da1ee1 100644 --- a/Sources/SmileID/Classes/DocumentVerification/View/DocumentShapedBoundingBox.swift +++ b/Sources/SmileID/Classes/DocumentVerification/View/DocumentShapedBoundingBox.swift @@ -22,6 +22,6 @@ struct DocumentShapedBoundingBox: View { // issues on iOS 14 devices .cutout(cutoutShape) .overlay(cutoutShape.stroke(borderColor, lineWidth: 4)) - } + }.preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/Navigation/NavigationBar.swift b/Sources/SmileID/Classes/Navigation/NavigationBar.swift index 752248ee3..4b635a53d 100644 --- a/Sources/SmileID/Classes/Navigation/NavigationBar.swift +++ b/Sources/SmileID/Classes/Navigation/NavigationBar.swift @@ -12,6 +12,7 @@ struct NavigationBar: View { } .frame(height: 50) .frame(maxHeight: .infinity, alignment: .top) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/SelfieCapture/View/FaceShapedProgressIndicator.swift b/Sources/SmileID/Classes/SelfieCapture/View/FaceShapedProgressIndicator.swift index 2068f396a..f139dda96 100644 --- a/Sources/SmileID/Classes/SelfieCapture/View/FaceShapedProgressIndicator.swift +++ b/Sources/SmileID/Classes/SelfieCapture/View/FaceShapedProgressIndicator.swift @@ -21,5 +21,6 @@ struct FaceShapedProgressIndicator: View { .animation(.easeInOut, value: progress) ) .edgesIgnoringSafeArea(.all) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/SelfieCapture/View/InfiniteProgressBar.swift b/Sources/SmileID/Classes/SelfieCapture/View/InfiniteProgressBar.swift index d020c7f0b..051c27b0c 100644 --- a/Sources/SmileID/Classes/SelfieCapture/View/InfiniteProgressBar.swift +++ b/Sources/SmileID/Classes/SelfieCapture/View/InfiniteProgressBar.swift @@ -18,6 +18,7 @@ struct InfiniteProgressBar: View { overlayRect(in: geo.frame(in: .global)) }) .clipped() + .preferredColorScheme(.light) } private func overlayRect(in rect: CGRect) -> some View { diff --git a/Sources/SmileID/Classes/SelfieCapture/View/SelfieCaptureScreen.swift b/Sources/SmileID/Classes/SelfieCapture/View/SelfieCaptureScreen.swift index ad53c486b..11c8bfad8 100644 --- a/Sources/SmileID/Classes/SelfieCapture/View/SelfieCaptureScreen.swift +++ b/Sources/SmileID/Classes/SelfieCapture/View/SelfieCaptureScreen.swift @@ -50,6 +50,7 @@ public struct SelfieCaptureScreen: View { } .padding(24) } + .preferredColorScheme(.light) .alert(item: $viewModel.unauthorizedAlert) { alert in Alert( title: Text(alert.title), diff --git a/Sources/SmileID/Classes/SelfieCapture/View/SmartSelfieInstructionsScreen.swift b/Sources/SmileID/Classes/SelfieCapture/View/SmartSelfieInstructionsScreen.swift index 03555f652..9ef22041c 100644 --- a/Sources/SmileID/Classes/SelfieCapture/View/SmartSelfieInstructionsScreen.swift +++ b/Sources/SmileID/Classes/SelfieCapture/View/SmartSelfieInstructionsScreen.swift @@ -103,5 +103,6 @@ public struct SmartSelfieInstructionsScreen: View { } } .padding(.horizontal, 16) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/SelfieCapture/View/SmileButton.swift b/Sources/SmileID/Classes/SelfieCapture/View/SmileButton.swift index f8c63b1fc..3e986c54b 100644 --- a/Sources/SmileID/Classes/SelfieCapture/View/SmileButton.swift +++ b/Sources/SmileID/Classes/SelfieCapture/View/SmileButton.swift @@ -74,6 +74,7 @@ public struct SmileButton: View { .cornerRadius(cornerRadius) .frame(maxWidth: .infinity) .disabled(isDisabled) + .preferredColorScheme(.light) } } } diff --git a/Sources/SmileID/Classes/Views/ImageCaptureConfirmationDialog.swift b/Sources/SmileID/Classes/Views/ImageCaptureConfirmationDialog.swift index 0b313bf58..3144056cf 100644 --- a/Sources/SmileID/Classes/Views/ImageCaptureConfirmationDialog.swift +++ b/Sources/SmileID/Classes/Views/ImageCaptureConfirmationDialog.swift @@ -74,5 +74,6 @@ public struct ImageCaptureConfirmationDialog: View { .cornerRadius(24) .shadow(radius: 16) .padding(32) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/Views/ProcessingScreen.swift b/Sources/SmileID/Classes/Views/ProcessingScreen.swift index 3717d3e4e..c59b3d7ed 100644 --- a/Sources/SmileID/Classes/Views/ProcessingScreen.swift +++ b/Sources/SmileID/Classes/Views/ProcessingScreen.swift @@ -136,6 +136,7 @@ public struct ProcessingInProgressScreen: View { .cornerRadius(24) .shadow(radius: 16) .padding(32) + .preferredColorScheme(.light) } } @@ -177,6 +178,7 @@ private struct ProcessingSuccessScreen: View { .cornerRadius(24) .shadow(radius: 16) .padding(32) + .preferredColorScheme(.light) } } @@ -230,5 +232,6 @@ public struct ProcessingErrorScreen: View { .cornerRadius(24) .shadow(radius: 16) .padding(32) + .preferredColorScheme(.light) } } diff --git a/Sources/SmileID/Classes/Views/RadioGroupSelector.swift b/Sources/SmileID/Classes/Views/RadioGroupSelector.swift index 580671f2c..35f415816 100644 --- a/Sources/SmileID/Classes/Views/RadioGroupSelector.swift +++ b/Sources/SmileID/Classes/Views/RadioGroupSelector.swift @@ -69,6 +69,7 @@ public struct RadioGroupSelector: View where T: Identifiable & Equatable { .cornerRadius(60) .frame(maxWidth: .infinity) .padding() + .preferredColorScheme(.light) } } } diff --git a/Sources/SmileID/Classes/Views/SearchableDropdownSelector.swift b/Sources/SmileID/Classes/Views/SearchableDropdownSelector.swift index 3c9c50e11..4e8ae8b83 100644 --- a/Sources/SmileID/Classes/Views/SearchableDropdownSelector.swift +++ b/Sources/SmileID/Classes/Views/SearchableDropdownSelector.swift @@ -70,7 +70,7 @@ public struct SearchableDropdownSelector: View { ) } } - } + }.preferredColorScheme(.light) } } From 473f0679a64ee28adb1a42ecd4c108491f8f2317 Mon Sep 17 00:00:00 2001 From: Juma Allan Date: Mon, 19 Aug 2024 16:09:29 +0300 Subject: [PATCH 2/2] Fix Ambiguous File paths (#212) * change to relative path for file response * fixed file handling * Update Sources/SmileID/Classes/BiometricKYC/OrchestratedBiometricKycViewModel.swift Co-authored-by: JNdhlovu * Update Sources/SmileID/Classes/BiometricKYC/OrchestratedBiometricKycViewModel.swift Co-authored-by: JNdhlovu * Update OrchestratedDocumentVerificationViewModel.swift * Update OrchestratedBiometricKycViewModel.swift * removed trailing whitespaces * remove force unwrapping --------- Co-authored-by: JNdhlovu --- .../OrchestratedBiometricKycViewModel.swift | 97 ++++++++----------- ...stratedDocumentVerificationViewModel.swift | 76 +++++++++------ Sources/SmileID/Classes/Util.swift | 16 +++ 3 files changed, 107 insertions(+), 82 deletions(-) diff --git a/Sources/SmileID/Classes/BiometricKYC/OrchestratedBiometricKycViewModel.swift b/Sources/SmileID/Classes/BiometricKYC/OrchestratedBiometricKycViewModel.swift index ad1b76827..22dbd90b7 100644 --- a/Sources/SmileID/Classes/BiometricKYC/OrchestratedBiometricKycViewModel.swift +++ b/Sources/SmileID/Classes/BiometricKYC/OrchestratedBiometricKycViewModel.swift @@ -17,8 +17,9 @@ internal class OrchestratedBiometricKycViewModel: ObservableObject { // MARK: - Other Properties + internal var selfieFile: URL? + internal var livenessFiles: [URL]? private var error: Error? - private var selfieCaptureResultStore: SelfieCaptureResultStore? private var didSubmitBiometricJob: Bool = false // MARK: - UI Properties @@ -45,18 +46,21 @@ internal class OrchestratedBiometricKycViewModel: ObservableObject { } func onRetry() { - if selfieCaptureResultStore == nil { - DispatchQueue.main.async { self.step = .selfie } + if let selfieFile { + submitJob() } else { - submitJob(selfieCaptureResultStore: selfieCaptureResultStore!) + DispatchQueue.main.async { self.step = .selfie } } } func onFinished(delegate: BiometricKycResultDelegate) { - if let selfieCaptureResultStore { + if let selfieFile = selfieFile, + let livenessFiles = livenessFiles, + let selfiePath = getRelativePath(from: selfieFile) + { delegate.didSucceed( - selfieImage: selfieCaptureResultStore.selfie, - livenessImages: selfieCaptureResultStore.livenessImages, + selfieImage: selfiePath, + livenessImages: livenessFiles.compactMap { getRelativePath(from: $0) }, didSubmitBiometricJob: didSubmitBiometricJob ) } else if let error { @@ -66,21 +70,39 @@ internal class OrchestratedBiometricKycViewModel: ObservableObject { } } - func submitJob(selfieCaptureResultStore: SelfieCaptureResultStore) { + func submitJob() { DispatchQueue.main.async { self.step = .processing(.inProgress) } Task { do { - let livenessImages = selfieCaptureResultStore.livenessImages - let selfieImage = selfieCaptureResultStore.selfie + selfieFile = try LocalStorage.getFileByType( + jobId: jobId, + fileType: FileType.selfie + ) + + livenessFiles = try LocalStorage.getFilesByType( + jobId: jobId, + fileType: FileType.liveness + ) + + guard let selfieFile else { + // Set step to .selfieCapture so that the Retry button goes back to this step + DispatchQueue.main.async { self.step = .selfie } + error = SmileIDError.unknown("Error capturing selfie") + return + } + + var allFiles = [URL]() let infoJson = try LocalStorage.createInfoJsonFile( jobId: jobId, idInfo: idInfo.copy(entered: true), - selfie: selfieImage, - livenessImages: livenessImages - ) - let zipData = try LocalStorage.zipFiles( - at: livenessImages + [selfieImage] + [infoJson] + selfie: selfieFile, + livenessImages: livenessFiles ) + allFiles.append(contentsOf: [selfieFile, infoJson]) + if let livenessFiles { + allFiles.append(contentsOf: livenessFiles) + } + let zipData = try LocalStorage.zipFiles(at: allFiles) let authRequest = AuthenticationRequest( jobType: .biometricKyc, enrollment: false, @@ -128,18 +150,6 @@ internal class OrchestratedBiometricKycViewModel: ObservableObject { didSubmitBiometricJob = true do { try LocalStorage.moveToSubmittedJobs(jobId: self.jobId) - self.selfieCaptureResultStore = SelfieCaptureResultStore( - selfie: try LocalStorage.getFileByType( - jobId: jobId, - fileType: FileType.selfie, - submitted: true - ) ?? selfieCaptureResultStore.selfie, - livenessImages: try LocalStorage.getFilesByType( - jobId: jobId, - fileType: FileType.liveness, - submitted: true - ) ?? selfieCaptureResultStore.livenessImages - ) } catch { print("Error moving job to submitted directory: \(error)") self.error = error @@ -149,24 +159,10 @@ internal class OrchestratedBiometricKycViewModel: ObservableObject { DispatchQueue.main.async { self.step = .processing(.success) } } catch let error as SmileIDError { do { - let didMove = try LocalStorage.handleOfflineJobFailure( + _ = try LocalStorage.handleOfflineJobFailure( jobId: self.jobId, error: error ) - if didMove { - self.selfieCaptureResultStore = SelfieCaptureResultStore( - selfie: try LocalStorage.getFileByType( - jobId: jobId, - fileType: FileType.selfie, - submitted: true - ) ?? selfieCaptureResultStore.selfie, - livenessImages: try LocalStorage.getFilesByType( - jobId: jobId, - fileType: FileType.liveness, - submitted: true - ) ?? selfieCaptureResultStore.livenessImages - ) - } } catch { print("Error moving job to submitted directory: \(error)") self.error = error @@ -199,24 +195,15 @@ internal class OrchestratedBiometricKycViewModel: ObservableObject { extension OrchestratedBiometricKycViewModel: SmartSelfieResultDelegate { func didSucceed( - selfieImage: URL, - livenessImages: [URL], + selfieImage _: URL, + livenessImages _: [URL], apiResponse _: SmartSelfieResponse? ) { - selfieCaptureResultStore = SelfieCaptureResultStore( - selfie: selfieImage, - livenessImages: livenessImages - ) - if let selfieCaptureResultStore { - submitJob(selfieCaptureResultStore: selfieCaptureResultStore) - } else { - error = SmileIDError.unknown("Failed to save selfie capture result") - DispatchQueue.main.async { self.step = .processing(.error) } - } + submitJob() } func didError(error _: Error) { - error = SmileIDError.unknown("Failed to capture selfie") + error = SmileIDError.unknown("Error capturing selfie") DispatchQueue.main.async { self.step = .processing(.error) } } } diff --git a/Sources/SmileID/Classes/DocumentVerification/Model/OrchestratedDocumentVerificationViewModel.swift b/Sources/SmileID/Classes/DocumentVerification/Model/OrchestratedDocumentVerificationViewModel.swift index 93d605648..c3310b982 100644 --- a/Sources/SmileID/Classes/DocumentVerification/Model/OrchestratedDocumentVerificationViewModel.swift +++ b/Sources/SmileID/Classes/DocumentVerification/Model/OrchestratedDocumentVerificationViewModel.swift @@ -107,24 +107,36 @@ internal class IOrchestratedDocumentVerificationViewModel: Obse } func submitJob() { - guard let documentFrontFile else { - // Set step to .frontDocumentCapture so that the Retry button goes back to this step - step = .frontDocumentCapture - onError(error: SmileIDError.unknown("Error getting document front file")) - return - } - guard let selfieFile else { - // Set step to .selfieCapture so that the Retry button goes back to this step - step = .selfieCapture - onError(error: SmileIDError.unknown("Error getting selfie file")) - return - } - DispatchQueue.main.async { - self.step = .processing(.inProgress) - } Task { - let zip: Data do { + guard let documentFrontFile else { + // Set step to .frontDocumentCapture so that the Retry button goes back to this step + step = .frontDocumentCapture + onError(error: SmileIDError.unknown("Error getting document front file")) + return + } + + selfieFile = try LocalStorage.getFileByType( + jobId: jobId, + fileType: FileType.selfie + ) + + livenessFiles = try LocalStorage.getFilesByType( + jobId: jobId, + fileType: FileType.liveness + ) + + guard let selfieFile else { + // Set step to .selfieCapture so that the Retry button goes back to this step + step = .selfieCapture + onError(error: SmileIDError.unknown("Error getting selfie file")) + return + } + + DispatchQueue.main.async { + self.step = .processing(.inProgress) + } + var allFiles = [URL]() let frontDocumentUrl = try LocalStorage.createDocumentFile( jobId: jobId, @@ -286,9 +298,11 @@ internal class IOrchestratedDocumentVerificationViewModel: Obse } extension IOrchestratedDocumentVerificationViewModel: SmartSelfieResultDelegate { - func didSucceed(selfieImage: URL, livenessImages: [URL], apiResponse _: SmartSelfieResponse?) { - selfieFile = selfieImage - livenessFiles = livenessImages + func didSucceed( + selfieImage _: URL, + livenessImages _: [URL], + apiResponse _: SmartSelfieResponse? + ) { submitJob() } @@ -302,11 +316,15 @@ internal class OrchestratedDocumentVerificationViewModel: IOrchestratedDocumentVerificationViewModel { override func onFinished(delegate: DocumentVerificationResultDelegate) { - if let savedFiles { + if let savedFiles, + let selfiePath = getRelativePath(from: selfieFile), + let documentFrontPath = getRelativePath(from: savedFiles.documentFront), + let documentBackPath = getRelativePath(from: savedFiles.documentBack) + { delegate.didSucceed( - selfie: savedFiles.selfie, - documentFrontImage: savedFiles.documentFront, - documentBackImage: savedFiles.documentBack, + selfie: selfiePath, + documentFrontImage: documentFrontPath, + documentBackImage: documentBackPath, didSubmitDocumentVerificationJob: didSubmitJob ) } else if let error { @@ -325,11 +343,15 @@ internal class OrchestratedEnhancedDocumentVerificationViewModel: IOrchestratedDocumentVerificationViewModel { override func onFinished(delegate: EnhancedDocumentVerificationResultDelegate) { - if let savedFiles { + if let savedFiles, + let selfiePath = getRelativePath(from: selfieFile), + let documentFrontPath = getRelativePath(from: savedFiles.documentFront), + let documentBackPath = getRelativePath(from: savedFiles.documentBack) + { delegate.didSucceed( - selfie: savedFiles.selfie, - documentFrontImage: savedFiles.documentFront, - documentBackImage: savedFiles.documentBack, + selfie: selfiePath, + documentFrontImage: documentFrontPath, + documentBackImage: documentBackPath, didSubmitEnhancedDocVJob: didSubmitJob ) } else if let error { diff --git a/Sources/SmileID/Classes/Util.swift b/Sources/SmileID/Classes/Util.swift index 3054e2f9c..3e0e6e2f9 100644 --- a/Sources/SmileID/Classes/Util.swift +++ b/Sources/SmileID/Classes/Util.swift @@ -74,3 +74,19 @@ func getErrorSubtitle(errorMessageRes: String?, errorMessage: String?) -> String return SmileIDResourcesHelper.localizedString(for: "Confirmation.FailureReason") } } + +func getRelativePath(from absoluteURL: URL?) -> URL? { + guard let absoluteURL = absoluteURL else { + return nil + } + + let relativeComponents = absoluteURL.pathComponents + .drop(while: { $0 != "SmileID" }) + .dropFirst() + + if relativeComponents.isEmpty { + return absoluteURL + } else { + return URL(string: relativeComponents.joined(separator: "/")) + } +}