diff --git a/app/android/app/build.gradle b/app/android/app/build.gradle index 0f03a8735..4ee023496 100644 --- a/app/android/app/build.gradle +++ b/app/android/app/build.gradle @@ -134,8 +134,8 @@ android { applicationId "com.proofofpassportapp" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 136 - versionName "2.9.13" + versionCode 139 + versionName "2.9.14" manifestPlaceholders = [appAuthRedirectScheme: 'com.proofofpassportapp'] externalNativeBuild { cmake { diff --git a/app/package.json b/app/package.json index afa292d1a..f7e753f1f 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "@selfxyz/mobile-app", - "version": "2.9.13", + "version": "2.9.14", "private": true, "type": "module", "scripts": { diff --git a/app/scripts/setup-private-modules.cjs b/app/scripts/setup-private-modules.cjs index 39ded4be9..3f016998e 100644 --- a/app/scripts/setup-private-modules.cjs +++ b/app/scripts/setup-private-modules.cjs @@ -24,6 +24,7 @@ const PRIVATE_MODULES = [ repoName: 'react-native-passport-reader', localPath: path.join(ANDROID_DIR, 'react-native-passport-reader'), validationFiles: ['android/build.gradle'], + commit: '99122a8', }, ]; @@ -146,7 +147,7 @@ function usingHTTPSGitAuth() { } } -function clonePrivateRepo(repoName, localPath) { +function clonePrivateRepo(repoName, localPath, commit) { log(`Setting up ${repoName}...`, 'info'); let cloneUrl; @@ -181,7 +182,16 @@ function clonePrivateRepo(repoName, localPath) { const isCredentialedUrl = isCI && (appToken || repoToken); const quietFlag = isCredentialedUrl ? '--quiet' : ''; const targetDir = path.basename(localPath); - const cloneCommand = `git clone --branch ${BRANCH} --single-branch --depth 1 ${quietFlag} "${cloneUrl}" "${targetDir}"`; + + // If commit is specified, clone without branch restriction and checkout commit + // Otherwise, clone the branch as before + let cloneCommand; + if (commit) { + log(`Using specific commit: ${commit}`, 'info'); + cloneCommand = `git clone ${quietFlag} "${cloneUrl}" "${targetDir}"`; + } else { + cloneCommand = `git clone --branch ${BRANCH} --single-branch --depth 1 ${quietFlag} "${cloneUrl}" "${targetDir}"`; + } try { if (isCredentialedUrl) { @@ -190,6 +200,18 @@ function clonePrivateRepo(repoName, localPath) { } else { runCommand(cloneCommand); } + + // If commit is specified, checkout that commit + if (commit) { + const checkoutCommand = `cd "${targetDir}" && git checkout ${commit}`; + if (isCredentialedUrl) { + runCommand(checkoutCommand, { stdio: 'pipe' }); + } else { + runCommand(checkoutCommand); + } + log(`Checked out commit ${commit}`, 'success'); + } + log(`Successfully cloned ${repoName}`, 'success'); return true; // Return true to indicate successful clone } catch (error) { @@ -220,14 +242,14 @@ function validateSetup(modulePath, validationFiles, repoName) { } function setupPrivateModule(module) { - const { repoName, localPath, validationFiles } = module; + const { repoName, localPath, validationFiles, commit } = module; log(`Starting setup of ${repoName}...`, 'info'); // Remove existing module removeExistingModule(localPath, repoName); // Clone the private repository - const cloneSuccessful = clonePrivateRepo(repoName, localPath); + const cloneSuccessful = clonePrivateRepo(repoName, localPath, commit); // If clone was skipped (e.g., in forked PRs), exit gracefully if (cloneSuccessful === false) { diff --git a/app/src/integrations/nfc/nfcScanner.ts b/app/src/integrations/nfc/nfcScanner.ts index e356d5392..83459d09c 100644 --- a/app/src/integrations/nfc/nfcScanner.ts +++ b/app/src/integrations/nfc/nfcScanner.ts @@ -93,6 +93,7 @@ const scanAndroid = async ( useCan: inputs.useCan ?? false, sessionId: inputs.sessionId, skipReselect: inputs.skipReselect ?? false, + skipPACE: inputs.skipPACE ?? false, }); }; diff --git a/app/src/integrations/nfc/passportReader.ts b/app/src/integrations/nfc/passportReader.ts index d78733414..20d7b3732 100644 --- a/app/src/integrations/nfc/passportReader.ts +++ b/app/src/integrations/nfc/passportReader.ts @@ -93,6 +93,7 @@ if (Platform.OS === 'android') { useCan = false, quality = 1, skipReselect = false, + skipPACE = false, sessionId, } = options; @@ -104,6 +105,7 @@ if (Platform.OS === 'android') { useCan, quality, skipReselect, + skipPACE, sessionId, }); }; diff --git a/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx b/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx index f72acbc7d..fb7368013 100644 --- a/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentNFCMethodSelectionScreen.tsx @@ -54,16 +54,6 @@ const NFC_METHODS = [ platform: ['ios'], params: { usePacePolling: true }, }, - { - // We try PACE first, but if it fails, we try BAC authentication. - // Some chips will invalidate the session if PACE fails. - key: 'skipPACE', - label: 'Skip PACE', - description: - 'Skip PACE protocol during NFC scan. Useful if your passport does not support PACE.', - platform: ['ios'], - params: { skipPACE: true }, - }, { key: 'can', label: 'CAN Authentication', @@ -107,6 +97,7 @@ const DocumentNFCMethodSelectionScreen: React.FC = () => { const [selectedMethod, setSelectedMethod] = useState('standard'); const [canValue, setCanValue] = useState(''); const [error, setError] = useState(''); + const [skipPACE, setSkipPACE] = useState(false); const selfClient = useSelfClient(); const { useMRZStore } = selfClient; @@ -147,6 +138,10 @@ const DocumentNFCMethodSelectionScreen: React.FC = () => { if (selectedMethod === 'can') { params.canNumber = canValue; } + + if (skipPACE) { + params.skipPACE = true; + } // Type assertion needed because static navigation doesn't infer optional params navigation.navigate('DocumentNFCScan', params as never); }; @@ -158,6 +153,28 @@ const DocumentNFCMethodSelectionScreen: React.FC = () => { Choose NFC Scan Method + + Skip PACE + + + + +