Skip to content
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
4 changes: 1 addition & 3 deletions formulus/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,8 @@ android {
targetSdk = rootProject.ext.targetSdkVersion
versionCode = 2
versionName = "1.0.1"

// Enable VisionCamera code scanner

buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", (findProperty("newArchEnabled") ?: "false").toString()
buildConfigField "boolean", "VISION_CAMERA_ENABLE_CODE_SCANNER", "true"
}

signingConfigs {
Expand Down
2 changes: 1 addition & 1 deletion formulus/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<uses-permission android:name="android.permission.INTERNET" />

<!-- Camera permission for react-native-vision-camera -->
<!-- Camera permission for QR scanning (react-native-camera-kit-no-google) -->
<uses-permission android:name="android.permission.CAMERA" />

<!-- Storage permissions for react-native-image-picker -->
Expand Down
2 changes: 0 additions & 2 deletions formulus/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,3 @@ org.gradle.daemon=true
org.gradle.parallel=false
org.gradle.workers.max=2

# Enable VisionCamera code scanner
VisionCamera_enableCodeScanner=true
39 changes: 14 additions & 25 deletions formulus/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion formulus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"lucide-react-native": "^0.577.0",
"react": "19.2.4",
"react-native": "0.83.1",
"react-native-camera-kit-no-google": "^17.0.1",
"react-native-device-info": "^15.0.1",
"react-native-fs": "^2.20.0",
"react-native-geolocation-service": "^5.3.1",
Expand All @@ -53,7 +54,6 @@
"react-native-signature-canvas": "^5.0.2",
"react-native-svg": "^15.11.2",
"react-native-url-polyfill": "^3.0.0",
"react-native-vision-camera": "^4.7.3",
"react-native-webview": "^13.16.0",
"react-native-zip-archive": "^7.0.2"
},
Expand Down
96 changes: 55 additions & 41 deletions formulus/src/components/QRScannerModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import React, { Component, ErrorInfo } from 'react';
import { Modal, View, Text, StyleSheet } from 'react-native';
import {
Modal,
View,
Text,
StyleSheet,
ScrollView,
NativeModules,
TurboModuleRegistry,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { colors } from '../theme/colors';
import Button from './common/Button';

class VisionCameraErrorBoundary extends Component<
/** Native module is registered as RNCameraKitModule (not CameraKit). See react-native-camera-kit-no-google. */
function isCameraKitNativeLinked(): boolean {
if (NativeModules.RNCameraKitModule != null) return true;
if (NativeModules.CameraKit != null) return true;
return TurboModuleRegistry.get('RNCameraKitModule') != null;
}

class QRScannerErrorBoundary extends Component<
{ children: React.ReactNode; fallback: React.ReactNode },
{ hasError: boolean }
> {
Expand All @@ -12,7 +28,7 @@ class VisionCameraErrorBoundary extends Component<
static getDerivedStateFromError = () => ({ hasError: true });

componentDidCatch(error: Error, info: ErrorInfo) {
console.warn('QRScannerModal: VisionCamera error', error, info);
console.warn('QRScannerModal: camera kit error', error, info);
}

render() {
Expand Down Expand Up @@ -40,40 +56,46 @@ interface QRScannerModalProps {
onResult?: (result: ScannerModalResults) => void;
}

// Only load QRScannerModalImpl if VisionCamera native module is linked
// Only load QRScannerModalImpl if react-native-camera-kit-no-google is linked
let QRScannerModalImpl: React.ComponentType<QRScannerModalProps> | null = null;
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { NativeModules } = require('react-native');
if (NativeModules.CameraView) {
if (isCameraKitNativeLinked()) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
QRScannerModalImpl = require('./QRScannerModalImpl').default;
}
} catch (e) {
console.warn('QRScannerModal: VisionCamera not linked, using fallback', e);
console.warn('QRScannerModal: CameraKit not linked, using fallback', e);
}

const FallbackContent: React.FC<{ onClose: () => void }> = ({ onClose }) => (
<View style={styles.container}>
<View style={styles.fallbackContainer}>
<SafeAreaView
style={styles.container}
edges={['top', 'bottom', 'left', 'right']}>
<ScrollView
style={styles.fallbackScrollView}
contentContainerStyle={styles.fallbackScrollContent}
keyboardShouldPersistTaps="handled">
<Text style={styles.fallbackText}>
QR scanner not available. Camera module (react-native-vision-camera) is
not linked. Re-enable it in react-native.config.js and rebuild.
QR scanner not available. Camera module
(react-native-camera-kit-no-google) is not linked. Rebuild the native
app after installing the dependency.
</Text>
<Button
title="Close"
onPress={onClose}
variant="secondary"
size="medium"
/>
</View>
</View>
<View style={styles.fallbackButtonWrap}>
<Button
title="Close"
onPress={onClose}
variant="secondary"
size="medium"
/>
</View>
</ScrollView>
</SafeAreaView>
);

const QRScannerModal: React.FC<QRScannerModalProps> = props => {
if (QRScannerModalImpl) {
return (
<VisionCameraErrorBoundary
<QRScannerErrorBoundary
fallback={
props.visible ? (
<Modal visible animationType="slide" statusBarTranslucent>
Expand All @@ -82,45 +104,37 @@ const QRScannerModal: React.FC<QRScannerModalProps> = props => {
) : null
}>
<QRScannerModalImpl {...props} />
</VisionCameraErrorBoundary>
</QRScannerErrorBoundary>
);
}

if (!props.visible) return null;

return (
<Modal visible={props.visible} animationType="slide" statusBarTranslucent>
<View style={styles.container}>
<View style={styles.fallbackContainer}>
<Text style={styles.fallbackText}>
QR scanner not available. Camera module (react-native-vision-camera)
is not linked. Re-enable it in react-native.config.js and rebuild.
</Text>
<Button
title="Close"
onPress={props.onClose}
variant="secondary"
size="medium"
/>
</View>
</View>
<FallbackContent onClose={props.onClose} />
</Modal>
);
};

const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: colors.neutral.black },
fallbackContainer: {
flex: 1,
fallbackScrollView: { flex: 1 },
fallbackScrollContent: {
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 40,
paddingHorizontal: 24,
paddingVertical: 24,
},
fallbackText: {
color: colors.neutral.white,
fontSize: 16,
textAlign: 'center',
marginBottom: 24,
marginBottom: 20,
},
fallbackButtonWrap: {
alignSelf: 'center',
maxWidth: '100%',
},
});

Expand Down
Loading
Loading