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

fix: resolve scan process until popup is dismissed #4

Merged
merged 1 commit into from
Nov 20, 2024
Merged
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
68 changes: 41 additions & 27 deletions ios/NFCPassportReader/PassportReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import CoreNFC

@available(iOS 15, *)
public class PassportReader : NSObject {
private var pendingPassportModel: NFCPassportModel? = nil
private typealias NFCCheckedContinuation = CheckedContinuation<NFCPassportModel, Error>
private var nfcContinuation: NFCCheckedContinuation?

Expand Down Expand Up @@ -117,33 +118,51 @@ extension PassportReader : NFCTagReaderSessionDelegate {
}

public func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
// TODO: This delay of 1 second was added to wait popup finish close process before send response to RN side. Be aware in a future API update could do it in a better way
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.handlePostFinishSesion(didInvalidateWithError: error)
}
}

private func handlePostFinishSesion(didInvalidateWithError error: Error) {
// If necessary, you may handle the error. Note session is no longer valid.
// You must create a new session to restart RF polling.
Logger.passportReader.debug( "tagReaderSession:didInvalidateWithError - \(error.localizedDescription)" )
self.readerSession?.invalidate()
self.readerSession = nil

if let readerError = error as? NFCReaderError, readerError.code == NFCReaderError.readerSessionInvalidationErrorUserCanceled
&& self.shouldNotReportNextReaderSessionInvalidationErrorUserCanceled {

self.shouldNotReportNextReaderSessionInvalidationErrorUserCanceled = false
// if pop up dismissed and could scan nfc
if pendingPassportModel != nil {
self.shouldNotReportNextReaderSessionInvalidationErrorUserCanceled = false
nfcContinuation?.resume(returning: pendingPassportModel!)
nfcContinuation = nil
pendingPassportModel = nil
} else {
var userError = NFCPassportReaderError.UnexpectedError
if let readerError = error as? NFCReaderError {
Logger.passportReader.error( "tagReaderSession:didInvalidateWithError - Got NFCReaderError - \(readerError.localizedDescription)" )
switch (readerError.code) {
case NFCReaderError.readerSessionInvalidationErrorUserCanceled:
Logger.passportReader.error( " - User cancelled session" )
userError = NFCPassportReaderError.UserCanceled
default:
Logger.passportReader.error( " - some other error - \(readerError.localizedDescription)" )
userError = NFCPassportReaderError.UnexpectedError
}
// if user press cancel button while scanning nfc or ocurrs error while scanning
if let readerError = error as? NFCReaderError, readerError.code == NFCReaderError.readerSessionInvalidationErrorUserCanceled
&& self.shouldNotReportNextReaderSessionInvalidationErrorUserCanceled {
self.shouldNotReportNextReaderSessionInvalidationErrorUserCanceled = false
let userError = NFCPassportReaderError.UnexpectedError
nfcContinuation?.resume(throwing: userError)
nfcContinuation = nil
// when user press cancel button before start scanning
} else {
Logger.passportReader.error( "tagReaderSession:didInvalidateWithError - Received error - \(error.localizedDescription)" )
var userError = NFCPassportReaderError.UnexpectedError
if let readerError = error as? NFCReaderError {
Logger.passportReader.error( "tagReaderSession:didInvalidateWithError - Got NFCReaderError - \(readerError.localizedDescription)" )
switch (readerError.code) {
case NFCReaderError.readerSessionInvalidationErrorUserCanceled:
Logger.passportReader.error( " - User cancelled session" )
userError = NFCPassportReaderError.UserCanceled
default:
Logger.passportReader.error( " - some other error - \(readerError.localizedDescription)" )
userError = NFCPassportReaderError.UnexpectedError
}
} else {
Logger.passportReader.error( "tagReaderSession:didInvalidateWithError - Received error - \(error.localizedDescription)" )
}
nfcContinuation?.resume(throwing: userError)
nfcContinuation = nil
}
nfcContinuation?.resume(throwing: userError)
nfcContinuation = nil
}
}

Expand Down Expand Up @@ -191,10 +210,7 @@ extension PassportReader : NFCTagReaderSessionDelegate {
}
}

let passportModel = try await self.startReading( tagReader : tagReader)
nfcContinuation?.resume(returning: passportModel)
nfcContinuation = nil

try await self.startReading( tagReader : tagReader)

} catch let error as NFCPassportReaderError {
let errorMessage = NFCViewDisplayMessage.error(error)
Expand All @@ -215,7 +231,7 @@ extension PassportReader : NFCTagReaderSessionDelegate {
@available(iOS 15, *)
extension PassportReader {

func startReading(tagReader : TagReader) async throws -> NFCPassportModel {
func startReading(tagReader : TagReader) async throws -> Void {

if !skipPACE {
do {
Expand Down Expand Up @@ -255,7 +271,7 @@ extension PassportReader {
// If we have a masterlist url set then use that and verify the passport now
self.passport.verifyPassport(masterListURL: self.masterListURL, useCMSVerification: self.passiveAuthenticationUsesOpenSSL)

return self.passport
pendingPassportModel = self.passport
}


Expand Down Expand Up @@ -408,8 +424,6 @@ extension PassportReader {
// session). The real error is reported back with the call to the completed handler
self.shouldNotReportNextReaderSessionInvalidationErrorUserCanceled = true
self.readerSession?.invalidate(errorMessage: self.nfcViewDisplayMessageHandler?(errorMessage) ?? errorMessage.description)
nfcContinuation?.resume(throwing: error)
nfcContinuation = nil
}
}
#endif
Loading