diff --git a/apps/mobile-app/app/(tabs)/settings/qr-confirm.tsx b/apps/mobile-app/app/(tabs)/settings/qr-confirm.tsx
index 86dfb05a3..f855dca27 100644
--- a/apps/mobile-app/app/(tabs)/settings/qr-confirm.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/qr-confirm.tsx
@@ -11,6 +11,7 @@ import { ThemedButton } from '@/components/themed/ThemedButton';
import { ThemedContainer } from '@/components/themed/ThemedContainer';
import { ThemedScrollView } from '@/components/themed/ThemedScrollView';
import { ThemedText } from '@/components/themed/ThemedText';
+import { UsernameDisplay } from '@/components/ui/UsernameDisplay';
import { useApp } from '@/context/AppContext';
import { useWebApi } from '@/context/WebApiContext';
import NativeVaultManager from '@/specs/NativeVaultManager';
@@ -70,15 +71,13 @@ export default function QRConfirmScreen() : React.ReactNode {
});
} catch (error) {
console.error('Mobile unlock error:', error);
- let errorMsg = t('settings.qrScanner.mobileUnlock.genericError');
+ let errorMsg = t('common.errors.unknownErrorTryAgain');
if (error instanceof Error) {
- if (error.message.includes('ENCRYPTION_ERROR')) {
- errorMsg = t('settings.qrScanner.mobileUnlock.vaultLocked');
- } else if (error.message.includes('404')) {
+ if (error.message.includes('404')) {
errorMsg = t('settings.qrScanner.mobileUnlock.requestExpired');
- } else if (error.message.includes('401') || error.message.includes('403')) {
- errorMsg = t('settings.qrScanner.mobileUnlock.unauthorized');
+ } else {
+ errorMsg = t('common.errors.unknownErrorTryAgain');
}
}
@@ -186,9 +185,13 @@ export default function QRConfirmScreen() : React.ReactNode {
confirmationText: {
fontSize: 16,
lineHeight: 24,
- marginBottom: 12,
+ marginBottom: 16,
textAlign: 'center',
},
+ usernameDisplayContainer: {
+ marginBottom: 12,
+ width: '100%',
+ },
buttonContainer: {
gap: 12,
marginTop: 20,
@@ -223,8 +226,11 @@ export default function QRConfirmScreen() : React.ReactNode {
{t('settings.qrScanner.mobileUnlock.confirmTitle')}
- {t('settings.qrScanner.mobileUnlock.confirmMessage', { username })}
+ {t('settings.qrScanner.mobileUnlock.confirmMessage')}
+
+
+
diff --git a/apps/mobile-app/app/(tabs)/settings/qr-result.tsx b/apps/mobile-app/app/(tabs)/settings/qr-result.tsx
index cd4128515..c2c1eafe0 100644
--- a/apps/mobile-app/app/(tabs)/settings/qr-result.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/qr-result.tsx
@@ -94,7 +94,7 @@ export default function QRResultScreen() : React.ReactNode {
{message || (isSuccess
? t('settings.qrScanner.mobileUnlock.successDescription')
- : t('settings.qrScanner.mobileUnlock.genericError'))}
+ : t('common.errors.unknownErrorTryAgain'))}
diff --git a/apps/mobile-app/app/(tabs)/settings/qr-scanner.tsx b/apps/mobile-app/app/(tabs)/settings/qr-scanner.tsx
index 73d3c3660..2d08de66c 100644
--- a/apps/mobile-app/app/(tabs)/settings/qr-scanner.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/qr-scanner.tsx
@@ -118,13 +118,13 @@ export default function QRScannerScreen() : React.ReactNode {
setIsLoadingAfterScan(false);
console.error('QR validation error:', error);
- let errorMsg = t('settings.qrScanner.mobileUnlock.genericError');
+ let errorMsg = t('common.errors.unknownErrorTryAgain');
if (error instanceof Error) {
if (error.message.includes('404')) {
errorMsg = t('settings.qrScanner.mobileUnlock.requestExpired');
- } else if (error.message.includes('401') || error.message.includes('403')) {
- errorMsg = t('settings.qrScanner.mobileUnlock.unauthorized');
+ } else {
+ errorMsg = t('common.errors.unknownErrorTryAgain');
}
}
@@ -138,6 +138,7 @@ export default function QRScannerScreen() : React.ReactNode {
/**
* Handle barcode scanned - validate request and navigate to confirmation.
+ * Only processes AliasVault QR codes, silently ignores others.
*/
const handleBarcodeScanned = useCallback(({ data }: { data: string }) : void => {
// Prevent multiple scans
@@ -148,21 +149,14 @@ export default function QRScannerScreen() : React.ReactNode {
// Parse the QR code to determine its type
const parsedData = parseQRCode(data);
+ // Silently ignore non-AliasVault QR codes
if (!parsedData.type) {
- Alert.alert(
- t('settings.qrScanner.invalidQrCode'),
- t('settings.qrScanner.notAliasVaultQr'),
- [{ text: t('common.ok'), /**
- * Go back to the settings tab.
- */
- onPress: (): void => router.back() }]
- );
return;
}
// Validate the request and navigate (with min 500ms loading)
validateAndNavigate(parsedData);
- }, [isLoadingAfterScan, t, validateAndNavigate]);
+ }, [isLoadingAfterScan, validateAndNavigate]);
// Handle QR code URL passed from deep link (e.g., from native camera)
useEffect(() => {
diff --git a/apps/mobile-app/i18n/locales/en.json b/apps/mobile-app/i18n/locales/en.json
index ce58baca9..e48868374 100644
--- a/apps/mobile-app/i18n/locales/en.json
+++ b/apps/mobile-app/i18n/locales/en.json
@@ -8,7 +8,7 @@
"no": "No",
"ok": "OK",
"continue": "Continue",
- "loading": "Loading...",
+ "loading": "Loading",
"error": "Error",
"success": "Success",
"never": "Never",
@@ -395,6 +395,23 @@
"failedToDelete": "Failed to delete account. Please try again.",
"usernameNotFound": "Username not found. Please login again."
}
+ },
+ "qrScanner": {
+ "title": "QR Code Scanner",
+ "scanningMessage": "Point your camera at the QR code",
+ "invalidQrCode": "Invalid QR Code",
+ "notAliasVaultQr": "This is not a valid AliasVault QR code. Please scan a QR code generated by AliasVault.",
+ "cameraPermissionTitle": "Camera Permission Required",
+ "cameraPermissionMessage": "Please allow camera access to scan QR codes.",
+ "mobileUnlock": {
+ "confirmTitle": "Confirm Login",
+ "confirmMessage": "You are about to log in on a remote device with your account. This other device will have full access to your vault. Only proceed if you trust this device.",
+ "successTitle": "Device Unlocked",
+ "successDescription": "The remote device has been successfully unlocked.",
+ "requestExpired": "This unlock request has expired. Please generate a new QR code.",
+ "authenticationFailed": "Authentication failed. Please try again.",
+ "authenticationRequired": "Authentication required to confirm this action."
+ }
}
},
"navigation": {