From fe1775ab5af804772a5c50b07a7e10c94bc5a4c5 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 30 Jul 2026 12:36:21 +0530 Subject: [PATCH 01/10] fix: replaced the existing barcode mask library with new one --- .../barcode-scanner-native/package.json | 2 +- .../src/BarcodeScanner.tsx | 105 ++++++++++++++---- pnpm-lock.yaml | 26 +++-- 3 files changed, 103 insertions(+), 30 deletions(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/package.json b/packages/pluggableWidgets/barcode-scanner-native/package.json index 7fda1b4a8..3510ffb45 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/package.json +++ b/packages/pluggableWidgets/barcode-scanner-native/package.json @@ -19,9 +19,9 @@ "version": "pnpm release" }, "dependencies": { + "@meksiabdou/react-native-barcode-mask": "^2.0.3", "@mendix/piw-native-utils-internal": "*", "@mendix/piw-utils-internal": "*", - "react-native-barcode-mask": "^1.2.4", "react-native-vision-camera": "4.7.3" }, "devDependencies": { diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx index 779849238..783292996 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx @@ -1,9 +1,9 @@ import { flattenStyles } from "@mendix/piw-native-utils-internal"; import { ValueStatus } from "mendix"; -import { ReactElement, useCallback, useMemo, useRef } from "react"; -import { View } from "react-native"; -import { Camera, useCodeScanner, Code, useCameraDevice } from "react-native-vision-camera"; -import BarcodeMask from "react-native-barcode-mask"; +import { ReactElement, useCallback, useMemo, useRef, useState } from "react"; +import { View, LayoutChangeEvent } from "react-native"; +import { Camera, useCodeScanner, Code, useCameraDevice, CodeScannerFrame } from "react-native-vision-camera"; +import BarcodeMask from "@meksiabdou/react-native-barcode-mask"; import { BarcodeScannerProps } from "../typings/BarcodeScannerProps"; import { BarcodeScannerStyle, defaultBarcodeScannerStyle } from "./ui/styles"; @@ -19,18 +19,78 @@ export function BarcodeScanner(props: Props): ReactElement { // Ref to track the lock state const isLockedRef = useRef(false); + // State to track camera view dimensions + const [cameraViewDimensions, setCameraViewDimensions] = useState<{ width: number; height: number } | null>(null); + + // Mask dimensions - should match the BarcodeMask component props + const maskWidth = 200; + const maskHeight = 200; + + // Helper function to check if a code is within the mask bounds + const isCodeInMaskBounds = useCallback( + (code: Code, scanFrame: CodeScannerFrame): boolean => { + // If mask is not shown, allow all codes + if (!props.showMask) { + return true; + } + + // If we don't have camera view dimensions or code frame, allow it + if (!cameraViewDimensions || !code.frame) { + return true; + } + + const { width: viewWidth, height: viewHeight } = cameraViewDimensions; + const { width: frameWidth, height: frameHeight } = scanFrame; + + // Calculate the mask position (centered in the view) + const maskX = (viewWidth - maskWidth) / 2; + const maskY = (viewHeight - maskHeight) / 2; + + // Scale factor from scan frame to view dimensions + const scaleX = viewWidth / frameWidth; + const scaleY = viewHeight / frameHeight; + + // Convert code frame coordinates from scan frame space to view space + const codeX = code.frame.x * scaleX; + const codeY = code.frame.y * scaleY; + const codeWidth = code.frame.width * scaleX; + const codeHeight = code.frame.height * scaleY; + + // Calculate the center of the code + const codeCenterX = codeX + codeWidth / 2; + const codeCenterY = codeY + codeHeight / 2; + + // Check if the center of the code is within the mask bounds + const isWithinMask = + codeCenterX >= maskX && + codeCenterX <= maskX + maskWidth && + codeCenterY >= maskY && + codeCenterY <= maskY + maskHeight; + + return isWithinMask; + }, + [props.showMask, cameraViewDimensions, maskWidth, maskHeight] + ); + const onCodeScanned = useCallback( - (codes: Code[]) => { + (codes: Code[], frame: CodeScannerFrame) => { // Block if still in cooldown if (isLockedRef.current) { return; } - if (props.barcode.status !== ValueStatus.Available || codes.length === 0 || !codes[0].value) { + if (props.barcode.status !== ValueStatus.Available || codes.length === 0) { return; } - const { value } = codes[0]; + // Filter codes to only those within the mask bounds + const codesInMask = codes.filter(code => isCodeInMaskBounds(code, frame)); + + if (codesInMask.length === 0 || !codesInMask[0].value) { + return; + } + + const { value } = codesInMask[0]; if (value !== props.barcode.value) { props.barcode.setValue(value); } @@ -43,7 +103,7 @@ export function BarcodeScanner(props: Props): ReactElement { isLockedRef.current = false; }, 2000); }, - [props.barcode, props.onDetect] + [props.barcode, props.onDetect, isCodeInMaskBounds] ); const codeScanner = useCodeScanner({ @@ -65,27 +125,34 @@ export function BarcodeScanner(props: Props): ReactElement { onCodeScanned }); + const handleCameraLayout = useCallback((event: LayoutChangeEvent) => { + const { width, height } = event.nativeEvent.layout; + setCameraViewDimensions({ width, height }); + }, []); + return ( {device && ( - + <> + {props.showMask && ( )} - + )} ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad1e3164e..6f0970cd6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -344,15 +344,15 @@ importers: packages/pluggableWidgets/barcode-scanner-native: dependencies: + '@meksiabdou/react-native-barcode-mask': + specifier: ^2.0.3 + version: 2.0.3(react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) '@mendix/piw-native-utils-internal': specifier: '*' version: link:../../tools/piw-native-utils-internal '@mendix/piw-utils-internal': specifier: '*' version: link:../../tools/piw-utils-internal - react-native-barcode-mask: - specifier: ^1.2.4 - version: 1.2.4 react-native-vision-camera: specifier: 4.7.3 version: 4.7.3(react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) @@ -1922,6 +1922,13 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@meksiabdou/react-native-barcode-mask@2.0.3': + resolution: {integrity: sha512-XOv2mXDHujbQ5SzoPNmks917EeqeWl8uJGx62fAcqF18Q54spTbUNeya5Xn05KaGEYffBp/wtuNpkI/fmpbLvA==} + peerDependencies: + react: 19.2.3 + react-native: 0.84.1 + react-native-reanimated: '*' + '@mendix/pluggable-widgets-tools@11.8.0': resolution: {integrity: sha512-9PyjVF5xsawbw2926WX/wfKTN3UIrnDseTeXv1yOhIhy+hBUynlECm2TKmXUg+WTdiUYME7kg1lGrH+LPIlQOQ==} engines: {node: '>=20'} @@ -5994,9 +6001,6 @@ packages: react-native-animatable@1.4.0: resolution: {integrity: sha512-DZwaDVWm2NBvBxf7I0wXKXLKb/TxDnkV53sWhCvei1pRyTX3MVFpkvdYBknNBqPrxYuAIlPxEp7gJOidIauUkw==} - react-native-barcode-mask@1.2.4: - resolution: {integrity: sha512-Jh3mEs/xUBs/z9mKkj2mM07MMQ2SdtW9mU4FOo5DQyA2kDte6lW87vIYFkWw1nxpzc7sy28ahMsgId8LTtKZsg==} - react-native-blob-util@0.24.7: resolution: {integrity: sha512-3vgn3hblfJh0+LIoqEhYRqCtwKh1xID2LtXHdTrUml3rYh4xj69eN+lvWU235AL0FRbX5uKrS1c4lIYexSgtWQ==} peerDependencies: @@ -8750,6 +8754,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@meksiabdou/react-native-barcode-mask@2.0.3(react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3)': + dependencies: + react: 19.2.3 + react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) + react-native-reanimated: 4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) + '@mendix/pluggable-widgets-tools@11.8.0(patch_hash=560aa323cdb292c24f00971ec20b781ca239273f210aa1fd174e40f9c2dae24f)(@jest/transform@29.7.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.41)(encoding@0.1.13)(jest-util@30.4.1)(picomatch@4.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3)(tslib@2.8.1)': dependencies: '@babel/core': 7.29.7 @@ -13826,10 +13836,6 @@ snapshots: dependencies: prop-types: 15.8.1 - react-native-barcode-mask@1.2.4: - dependencies: - prop-types: 15.8.1 - react-native-blob-util@0.24.7(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3): dependencies: base-64: 0.1.0 From c06b1504b5abdcf4e56c6cf531ae04e47b474c0b Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Thu, 30 Jul 2026 22:06:43 +0530 Subject: [PATCH 02/10] fix: barcode scanner closest to center implementation --- .../src/BarcodeScanner.tsx | 80 ++++++++++++++----- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx index 783292996..9232a1356 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx @@ -11,6 +11,11 @@ import { executeAction } from "@mendix/piw-utils-internal"; export type Props = BarcodeScannerProps; +type CodePositionInfo = { + isWithinMask: boolean; + distanceToMaskCenter: number; +}; + export function BarcodeScanner(props: Props): ReactElement { const device = useCameraDevice("back"); @@ -23,51 +28,72 @@ export function BarcodeScanner(props: Props): ReactElement { const [cameraViewDimensions, setCameraViewDimensions] = useState<{ width: number; height: number } | null>(null); // Mask dimensions - should match the BarcodeMask component props - const maskWidth = 200; - const maskHeight = 200; - - // Helper function to check if a code is within the mask bounds - const isCodeInMaskBounds = useCallback( - (code: Code, scanFrame: CodeScannerFrame): boolean => { - // If mask is not shown, allow all codes + const maskWidth = styles.mask.width || 280; + const maskHeight = styles.mask.height || 260; + + /** + * Calculates: + * - Whether the code center lies inside the mask + * - Distance of the code center from the mask center + */ + const getCodePositionInfo = useCallback( + (code: Code, scanFrame: CodeScannerFrame): CodePositionInfo => { + // Preserve existing behavior: + // If mask is hidden, allow all codes. if (!props.showMask) { - return true; + return { + isWithinMask: true, + distanceToMaskCenter: 0 + }; } - // If we don't have camera view dimensions or code frame, allow it + // Preserve existing behavior: + // If layout/frame data is unavailable, allow the code. if (!cameraViewDimensions || !code.frame) { - return true; + return { + isWithinMask: true, + distanceToMaskCenter: Number.MAX_SAFE_INTEGER + }; } const { width: viewWidth, height: viewHeight } = cameraViewDimensions; const { width: frameWidth, height: frameHeight } = scanFrame; - // Calculate the mask position (centered in the view) + // Mask position (centered in camera view) const maskX = (viewWidth - maskWidth) / 2; const maskY = (viewHeight - maskHeight) / 2; - // Scale factor from scan frame to view dimensions + const maskCenterX = maskX + maskWidth / 2; + const maskCenterY = maskY + maskHeight / 2; + + // Scale factor from scanner frame space to view space const scaleX = viewWidth / frameWidth; const scaleY = viewHeight / frameHeight; - // Convert code frame coordinates from scan frame space to view space + // Convert code frame coordinates into view coordinates const codeX = code.frame.x * scaleX; const codeY = code.frame.y * scaleY; const codeWidth = code.frame.width * scaleX; const codeHeight = code.frame.height * scaleY; - // Calculate the center of the code + // Code center const codeCenterX = codeX + codeWidth / 2; const codeCenterY = codeY + codeHeight / 2; - // Check if the center of the code is within the mask bounds const isWithinMask = codeCenterX >= maskX && codeCenterX <= maskX + maskWidth && codeCenterY >= maskY && codeCenterY <= maskY + maskHeight; - return isWithinMask; + // Squared distance (no need for Math.sqrt since we only compare values) + const distanceToMaskCenter = + Math.pow(codeCenterX - maskCenterX, 2) + Math.pow(codeCenterY - maskCenterY, 2); + + return { + isWithinMask, + distanceToMaskCenter + }; }, [props.showMask, cameraViewDimensions, maskWidth, maskHeight] ); @@ -83,14 +109,26 @@ export function BarcodeScanner(props: Props): ReactElement { return; } - // Filter codes to only those within the mask bounds - const codesInMask = codes.filter(code => isCodeInMaskBounds(code, frame)); + const candidates = codes + .map(code => ({ + code, + ...getCodePositionInfo(code, frame) + })) + .filter(item => item.isWithinMask); - if (codesInMask.length === 0 || !codesInMask[0].value) { + if (candidates.length === 0) { return; } - const { value } = codesInMask[0]; + // Prefer the code closest to the center of the mask + const selectedCode = candidates.sort((a, b) => a.distanceToMaskCenter - b.distanceToMaskCenter)[0].code; + + if (!selectedCode.value) { + return; + } + + const { value } = selectedCode; + if (value !== props.barcode.value) { props.barcode.setValue(value); } @@ -103,7 +141,7 @@ export function BarcodeScanner(props: Props): ReactElement { isLockedRef.current = false; }, 2000); }, - [props.barcode, props.onDetect, isCodeInMaskBounds] + [props.barcode, props.onDetect, getCodePositionInfo] ); const codeScanner = useCodeScanner({ From a8ed274e1255fc043abcbb54558000d799b1f6f0 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Mon, 3 Aug 2026 20:27:21 +0530 Subject: [PATCH 03/10] fix: qr scan inside barcode mask functionality implementation --- .../src/BarcodeScanner.tsx | 200 ++++++++++++++---- 1 file changed, 157 insertions(+), 43 deletions(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx index 9232a1356..418e49803 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx @@ -1,7 +1,7 @@ import { flattenStyles } from "@mendix/piw-native-utils-internal"; import { ValueStatus } from "mendix"; import { ReactElement, useCallback, useMemo, useRef, useState } from "react"; -import { View, LayoutChangeEvent } from "react-native"; +import { View, LayoutChangeEvent, Platform } from "react-native"; import { Camera, useCodeScanner, Code, useCameraDevice, CodeScannerFrame } from "react-native-vision-camera"; import BarcodeMask from "@meksiabdou/react-native-barcode-mask"; @@ -13,86 +13,200 @@ export type Props = BarcodeScannerProps; type CodePositionInfo = { isWithinMask: boolean; - distanceToMaskCenter: number; + distanceToMaskCenterSquared: number; + overlapArea: number; + overlapPercentage: number; }; +type TransformedCoordinates = { + codeX: number; + codeY: number; + codeWidth: number; + codeHeight: number; +}; + +type OverlapInfo = { + overlapArea: number; + overlapPercentage: number; +}; + +type CandidateCode = { + code: Code; + isWithinMask: boolean; + distanceToMaskCenterSquared: number; + overlapArea: number; + overlapPercentage: number; +}; + +/** + * Transforms barcode coordinates from camera sensor space to screen view space. + * Handles platform-specific coordinate systems (iOS sensor landscape vs Android ML Kit rotated) + * and applies appropriate scaling based on device orientation. + */ +function transformCodeCoordinates( + codeFrame: { x: number; y: number; width: number; height: number }, + scanFrame: CodeScannerFrame, + viewWidth: number, + viewHeight: number +): TransformedCoordinates { + const { width: frameWidth, height: frameHeight } = scanFrame; + const isPortrait = viewHeight > viewWidth; + + let codeX: number, codeY: number, codeWidth: number, codeHeight: number; + + if (isPortrait && Platform.OS === "ios") { + // iOS: code.frame coordinates are in the sensor's native landscape space, + // so we need a 90° rotation to map to portrait view coordinates. + const scaleX = viewWidth / frameHeight; + const scaleY = viewHeight / frameWidth; + + codeX = (frameHeight - codeFrame.y - codeFrame.height) * scaleX; + codeY = codeFrame.x * scaleY; + codeWidth = codeFrame.height * scaleX; + codeHeight = codeFrame.width * scaleY; + } else if (isPortrait && Platform.OS === "android") { + // Android: ML Kit already rotates code.frame coordinates to match device orientation, + // but CodeScannerFrame still reports sensor landscape dimensions (e.g. 1920x1080). + // Scale using the shorter dimension for X and longer for Y. + const scaleX = viewWidth / Math.min(frameWidth, frameHeight); + const scaleY = viewHeight / Math.max(frameWidth, frameHeight); + + codeX = codeFrame.x * scaleX; + codeY = codeFrame.y * scaleY; + codeWidth = codeFrame.width * scaleX; + codeHeight = codeFrame.height * scaleY; + } else { + const scaleX = viewWidth / frameWidth; + const scaleY = viewHeight / frameHeight; + + codeX = codeFrame.x * scaleX; + codeY = codeFrame.y * scaleY; + codeWidth = codeFrame.width * scaleX; + codeHeight = codeFrame.height * scaleY; + } + + return { codeX, codeY, codeWidth, codeHeight }; +} + +/** + * Calculates the overlap between a barcode and the mask region. + * Returns both the absolute overlap area and the percentage of the barcode that overlaps with the mask. + */ +function calculateOverlap( + codeX: number, + codeY: number, + codeWidth: number, + codeHeight: number, + maskX: number, + maskY: number, + maskWidth: number, + maskHeight: number +): OverlapInfo { + const overlapLeft = Math.max(codeX, maskX); + const overlapTop = Math.max(codeY, maskY); + const overlapRight = Math.min(codeX + codeWidth, maskX + maskWidth); + const overlapBottom = Math.min(codeY + codeHeight, maskY + maskHeight); + + const overlapWidth = Math.max(0, overlapRight - overlapLeft); + const overlapHeight = Math.max(0, overlapBottom - overlapTop); + + const overlapArea = overlapWidth * overlapHeight; + const barcodeArea = codeWidth * codeHeight; + const overlapPercentage = barcodeArea > 0 ? overlapArea / barcodeArea : 0; + + return { overlapArea, overlapPercentage }; +} + +/** + * Comparator function to select the best barcode when multiple codes are detected. + * Priority: overlap percentage > overlap area > distance to mask center (squared). + */ +function compareCodesByPriority(a: CandidateCode, b: CandidateCode): number { + if (b.overlapPercentage !== a.overlapPercentage) { + return b.overlapPercentage - a.overlapPercentage; + } + + if (b.overlapArea !== a.overlapArea) { + return b.overlapArea - a.overlapArea; + } + + return a.distanceToMaskCenterSquared - b.distanceToMaskCenterSquared; +} + export function BarcodeScanner(props: Props): ReactElement { const device = useCameraDevice("back"); const styles = useMemo(() => flattenStyles(defaultBarcodeScannerStyle, props.style), [props.style]); - // Ref to track the lock state const isLockedRef = useRef(false); - // State to track camera view dimensions const [cameraViewDimensions, setCameraViewDimensions] = useState<{ width: number; height: number } | null>(null); - // Mask dimensions - should match the BarcodeMask component props const maskWidth = styles.mask.width || 280; const maskHeight = styles.mask.height || 260; - /** - * Calculates: - * - Whether the code center lies inside the mask - * - Distance of the code center from the mask center - */ const getCodePositionInfo = useCallback( (code: Code, scanFrame: CodeScannerFrame): CodePositionInfo => { - // Preserve existing behavior: - // If mask is hidden, allow all codes. if (!props.showMask) { return { isWithinMask: true, - distanceToMaskCenter: 0 + distanceToMaskCenterSquared: 0, + overlapArea: Number.MAX_SAFE_INTEGER, + overlapPercentage: 1 }; } - // Preserve existing behavior: - // If layout/frame data is unavailable, allow the code. if (!cameraViewDimensions || !code.frame) { return { - isWithinMask: true, - distanceToMaskCenter: Number.MAX_SAFE_INTEGER + isWithinMask: false, + distanceToMaskCenterSquared: Number.MAX_SAFE_INTEGER, + overlapArea: 0, + overlapPercentage: 0 }; } const { width: viewWidth, height: viewHeight } = cameraViewDimensions; - const { width: frameWidth, height: frameHeight } = scanFrame; - // Mask position (centered in camera view) const maskX = (viewWidth - maskWidth) / 2; const maskY = (viewHeight - maskHeight) / 2; - const maskCenterX = maskX + maskWidth / 2; const maskCenterY = maskY + maskHeight / 2; - // Scale factor from scanner frame space to view space - const scaleX = viewWidth / frameWidth; - const scaleY = viewHeight / frameHeight; - - // Convert code frame coordinates into view coordinates - const codeX = code.frame.x * scaleX; - const codeY = code.frame.y * scaleY; - const codeWidth = code.frame.width * scaleX; - const codeHeight = code.frame.height * scaleY; + const { codeX, codeY, codeWidth, codeHeight } = transformCodeCoordinates( + code.frame, + scanFrame, + viewWidth, + viewHeight + ); - // Code center const codeCenterX = codeX + codeWidth / 2; const codeCenterY = codeY + codeHeight / 2; + const distanceToMaskCenterSquared = + Math.pow(codeCenterX - maskCenterX, 2) + Math.pow(codeCenterY - maskCenterY, 2); + + const { overlapArea, overlapPercentage } = calculateOverlap( + codeX, + codeY, + codeWidth, + codeHeight, + maskX, + maskY, + maskWidth, + maskHeight + ); + const isWithinMask = codeCenterX >= maskX && codeCenterX <= maskX + maskWidth && codeCenterY >= maskY && codeCenterY <= maskY + maskHeight; - // Squared distance (no need for Math.sqrt since we only compare values) - const distanceToMaskCenter = - Math.pow(codeCenterX - maskCenterX, 2) + Math.pow(codeCenterY - maskCenterY, 2); - return { isWithinMask, - distanceToMaskCenter + distanceToMaskCenterSquared, + overlapArea, + overlapPercentage }; }, [props.showMask, cameraViewDimensions, maskWidth, maskHeight] @@ -100,7 +214,6 @@ export function BarcodeScanner(props: Props): ReactElement { const onCodeScanned = useCallback( (codes: Code[], frame: CodeScannerFrame) => { - // Block if still in cooldown if (isLockedRef.current) { return; } @@ -110,18 +223,20 @@ export function BarcodeScanner(props: Props): ReactElement { } const candidates = codes - .map(code => ({ - code, - ...getCodePositionInfo(code, frame) - })) + .map(code => { + const positionInfo = getCodePositionInfo(code, frame); + return { + code, + ...positionInfo + }; + }) .filter(item => item.isWithinMask); if (candidates.length === 0) { return; } - // Prefer the code closest to the center of the mask - const selectedCode = candidates.sort((a, b) => a.distanceToMaskCenter - b.distanceToMaskCenter)[0].code; + const selectedCode = candidates.sort(compareCodesByPriority)[0].code; if (!selectedCode.value) { return; @@ -135,7 +250,6 @@ export function BarcodeScanner(props: Props): ReactElement { executeAction(props.onDetect); - // Lock further scans for 2 seconds isLockedRef.current = true; setTimeout(() => { isLockedRef.current = false; From 61523537e8c9bdbddccd05b44491dced37ff928b Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 10:31:26 +0530 Subject: [PATCH 04/10] fix: add comment for better explanation of code --- .../barcode-scanner-native/src/BarcodeScanner.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx index 418e49803..2604f9d57 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx @@ -138,6 +138,7 @@ export function BarcodeScanner(props: Props): ReactElement { const styles = useMemo(() => flattenStyles(defaultBarcodeScannerStyle, props.style), [props.style]); + // Ref to track the lock state const isLockedRef = useRef(false); const [cameraViewDimensions, setCameraViewDimensions] = useState<{ width: number; height: number } | null>(null); @@ -167,11 +168,13 @@ export function BarcodeScanner(props: Props): ReactElement { const { width: viewWidth, height: viewHeight } = cameraViewDimensions; + // Barcode mask coordinates in view space const maskX = (viewWidth - maskWidth) / 2; const maskY = (viewHeight - maskHeight) / 2; const maskCenterX = maskX + maskWidth / 2; const maskCenterY = maskY + maskHeight / 2; + // Transform Qr barcode coordinates from camera sensor space to view space const { codeX, codeY, codeWidth, codeHeight } = transformCodeCoordinates( code.frame, scanFrame, @@ -214,6 +217,7 @@ export function BarcodeScanner(props: Props): ReactElement { const onCodeScanned = useCallback( (codes: Code[], frame: CodeScannerFrame) => { + // Block if still in cooldown if (isLockedRef.current) { return; } @@ -250,6 +254,7 @@ export function BarcodeScanner(props: Props): ReactElement { executeAction(props.onDetect); + // Lock further scans for 2 seconds isLockedRef.current = true; setTimeout(() => { isLockedRef.current = false; From 04d396be4822710fd3e37ec301991b0f8aacce5e Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 10:36:34 +0530 Subject: [PATCH 05/10] fix: update changelog,pakage files --- packages/pluggableWidgets/barcode-scanner-native/CHANGELOG.md | 1 + packages/pluggableWidgets/barcode-scanner-native/package.json | 2 +- .../pluggableWidgets/barcode-scanner-native/src/package.xml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/CHANGELOG.md b/packages/pluggableWidgets/barcode-scanner-native/CHANGELOG.md index 6264d826b..1ec105dc9 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/CHANGELOG.md +++ b/packages/pluggableWidgets/barcode-scanner-native/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] - We added support for QR of available remaining types including pdf417 in barcode scanner functinality. +- We fixed the barcode mask not visible issue and selection logic of QR code. ## [4.2.2] - 2025-12-23 diff --git a/packages/pluggableWidgets/barcode-scanner-native/package.json b/packages/pluggableWidgets/barcode-scanner-native/package.json index 3510ffb45..b38c5c891 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/package.json +++ b/packages/pluggableWidgets/barcode-scanner-native/package.json @@ -1,7 +1,7 @@ { "name": "barcode-scanner-native", "widgetName": "BarcodeScanner", - "version": "4.4.0", + "version": "4.4.1", "license": "Apache-2.0", "repository": { "type": "git", diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/package.xml b/packages/pluggableWidgets/barcode-scanner-native/src/package.xml index 679718e6c..fdda5ba78 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/package.xml +++ b/packages/pluggableWidgets/barcode-scanner-native/src/package.xml @@ -1,6 +1,6 @@ - + From 751abcc41baddf49a1380e95dbe4cc0b39623457 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 10:42:52 +0530 Subject: [PATCH 06/10] fix: updated testcases --- .../src/__tests__/BarcodeScanner.spec.tsx | 2 +- .../BarcodeScanner.spec.tsx.snap | 33 +++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx index dbf475a34..5cf543df7 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx @@ -15,7 +15,7 @@ jest.mock("react-native-vision-camera", () => ({ } })); -jest.mock("react-native-barcode-mask", () => "BarcodeMask"); +jest.mock("@meksiabdou/react-native-barcode-mask", () => "BarcodeMask"); describe("BarcodeScanner", () => { let defaultProps: Props; diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/__snapshots__/BarcodeScanner.spec.tsx.snap b/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/__snapshots__/BarcodeScanner.spec.tsx.snap index 479e716ac..f533bae22 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/__snapshots__/BarcodeScanner.spec.tsx.snap +++ b/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/__snapshots__/BarcodeScanner.spec.tsx.snap @@ -15,6 +15,7 @@ exports[`BarcodeScanner renders 1`] = ` codeScanner="mockCodeScanner" device="mock-device" isActive={true} + onLayout={[Function]} style={ { "alignItems": "center", @@ -42,6 +43,7 @@ exports[`BarcodeScanner renders with mask 1`] = ` codeScanner="mockCodeScanner" device="mock-device" isActive={true} + onLayout={[Function]} style={ { "alignItems": "center", @@ -50,13 +52,14 @@ exports[`BarcodeScanner renders with mask 1`] = ` } } testID="barcode-scanner-test" - > - - + /> + `; @@ -75,6 +78,7 @@ exports[`BarcodeScanner renders with mask with animated line 1`] = ` codeScanner="mockCodeScanner" device="mock-device" isActive={true} + onLayout={[Function]} style={ { "alignItems": "center", @@ -83,12 +87,13 @@ exports[`BarcodeScanner renders with mask with animated line 1`] = ` } } testID="barcode-scanner-test" - > - - + /> + `; From 6ba625db9d6d74880ed834c00b4b346c38671406 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 11:27:38 +0530 Subject: [PATCH 07/10] fix: linting error fix --- .../barcode-scanner-native/src/BarcodeScanner.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx index 2604f9d57..b36664283 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx @@ -52,7 +52,10 @@ function transformCodeCoordinates( const { width: frameWidth, height: frameHeight } = scanFrame; const isPortrait = viewHeight > viewWidth; - let codeX: number, codeY: number, codeWidth: number, codeHeight: number; + let codeX: number; + let codeY: number; + let codeWidth: number; + let codeHeight: number; if (isPortrait && Platform.OS === "ios") { // iOS: code.frame coordinates are in the sensor's native landscape space, From 4e3c0a09435dcba7abe8007b2026c3d25e170fcd Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 16:59:42 +0530 Subject: [PATCH 08/10] fix: custom component implementation for barcode mask --- .../barcode-scanner-native/package.json | 2 +- .../src/BarcodeScanner.tsx | 2 +- .../src/components/BarcodeMask.tsx | 139 ++++++++++++++++++ .../barcode-scanner-native/src/ui/styles.tsx | 30 +++- pnpm-lock.yaml | 19 +-- 5 files changed, 173 insertions(+), 19 deletions(-) create mode 100644 packages/pluggableWidgets/barcode-scanner-native/src/components/BarcodeMask.tsx diff --git a/packages/pluggableWidgets/barcode-scanner-native/package.json b/packages/pluggableWidgets/barcode-scanner-native/package.json index b38c5c891..7b6da7ef7 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/package.json +++ b/packages/pluggableWidgets/barcode-scanner-native/package.json @@ -19,9 +19,9 @@ "version": "pnpm release" }, "dependencies": { - "@meksiabdou/react-native-barcode-mask": "^2.0.3", "@mendix/piw-native-utils-internal": "*", "@mendix/piw-utils-internal": "*", + "react-native-svg": "^15.15.4", "react-native-vision-camera": "4.7.3" }, "devDependencies": { diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx index b36664283..a48767b4b 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/BarcodeScanner.tsx @@ -3,7 +3,7 @@ import { ValueStatus } from "mendix"; import { ReactElement, useCallback, useMemo, useRef, useState } from "react"; import { View, LayoutChangeEvent, Platform } from "react-native"; import { Camera, useCodeScanner, Code, useCameraDevice, CodeScannerFrame } from "react-native-vision-camera"; -import BarcodeMask from "@meksiabdou/react-native-barcode-mask"; +import BarcodeMask from "./components/BarcodeMask"; import { BarcodeScannerProps } from "../typings/BarcodeScannerProps"; import { BarcodeScannerStyle, defaultBarcodeScannerStyle } from "./ui/styles"; diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/components/BarcodeMask.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/components/BarcodeMask.tsx new file mode 100644 index 000000000..075d6eaa6 --- /dev/null +++ b/packages/pluggableWidgets/barcode-scanner-native/src/components/BarcodeMask.tsx @@ -0,0 +1,139 @@ +import { ReactElement, useEffect, useRef } from "react"; +import { Animated, View } from "react-native"; +import Svg, { Line, Path } from "react-native-svg"; +import { barcodeMaskStyles as styles } from "../ui/styles"; + +const AnimatedLine = Animated.createAnimatedComponent(Line); + +export type BarcodeMaskSvgProps = { + edgeColor?: string; + width?: number; + height?: number; + showAnimatedLine?: boolean; + backgroundColor?: string; +}; + +const EDGE_WIDTH = 25; +const EDGE_HEIGHT = 25; +const EDGE_BORDER_WIDTH = 4; +const ANIMATED_LINE_COLOR = "#fff"; +const ANIMATED_LINE_THICKNESS = 3; +const LINE_ANIMATION_DURATION = 2000; + +export const BarcodeMask = (props: BarcodeMaskSvgProps): ReactElement => { + const { + edgeColor = "#fff", + width = 280, + height = 260, + showAnimatedLine = true, + backgroundColor = "rgba(0, 0, 0, 0.6)" + } = props; + + const lineY = useRef(new Animated.Value(0)).current; + const lineStrokeWidth = useRef(new Animated.Value(0)).current; + + useEffect(() => { + lineY.setValue(0); + lineStrokeWidth.setValue(0); + + Animated.spring(lineStrokeWidth, { + toValue: ANIMATED_LINE_THICKNESS, + damping: 15, + stiffness: 100, + mass: 0.5, + useNativeDriver: false + }).start(); + + Animated.loop( + Animated.sequence([ + Animated.timing(lineY, { + toValue: height, + duration: LINE_ANIMATION_DURATION, + useNativeDriver: false + }), + Animated.timing(lineY, { + toValue: 0, + duration: LINE_ANIMATION_DURATION, + useNativeDriver: false + }) + ]) + ).start(); + }, [height, lineY, lineStrokeWidth]); + + const strokeOffset = EDGE_BORDER_WIDTH / 2; + const maskLeft = strokeOffset; + const maskTop = strokeOffset; + const maskRight = width - strokeOffset; + const maskBottom = height - strokeOffset; + + return ( + + + + + + + + + + + + + + + {showAnimatedLine && ( + + )} + + + + + + + ); +}; + +export default BarcodeMask; diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/ui/styles.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/ui/styles.tsx index 6ad1c7b94..57d71ebe5 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/ui/styles.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/ui/styles.tsx @@ -1,5 +1,5 @@ import { Style } from "@mendix/piw-native-utils-internal"; -import { ViewStyle } from "react-native"; +import { StyleSheet, ViewStyle } from "react-native"; export interface BarcodeScannerStyle extends Style { container: ViewStyle; @@ -22,3 +22,31 @@ export const defaultBarcodeScannerStyle: BarcodeScannerStyle = { backgroundColor: "rgba(0, 0, 0, 0.6)" } }; + +export const barcodeMaskStyles = StyleSheet.create({ + container: { + flex: 1, + display: "flex", + alignItems: "center", + justifyContent: "space-around", + position: "absolute", + height: "100%", + width: "100%" + }, + maskCenter: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-around" + }, + mask: { + position: "relative", + maxHeight: "100%", + maxWidth: "100%", + zIndex: 99 + }, + svg: { + position: "absolute", + top: 0, + left: 0 + } +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f0970cd6..8e97bbc84 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -344,15 +344,15 @@ importers: packages/pluggableWidgets/barcode-scanner-native: dependencies: - '@meksiabdou/react-native-barcode-mask': - specifier: ^2.0.3 - version: 2.0.3(react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) '@mendix/piw-native-utils-internal': specifier: '*' version: link:../../tools/piw-native-utils-internal '@mendix/piw-utils-internal': specifier: '*' version: link:../../tools/piw-utils-internal + react-native-svg: + specifier: ^15.15.4 + version: 15.15.4(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) react-native-vision-camera: specifier: 4.7.3 version: 4.7.3(react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) @@ -1922,13 +1922,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@meksiabdou/react-native-barcode-mask@2.0.3': - resolution: {integrity: sha512-XOv2mXDHujbQ5SzoPNmks917EeqeWl8uJGx62fAcqF18Q54spTbUNeya5Xn05KaGEYffBp/wtuNpkI/fmpbLvA==} - peerDependencies: - react: 19.2.3 - react-native: 0.84.1 - react-native-reanimated: '*' - '@mendix/pluggable-widgets-tools@11.8.0': resolution: {integrity: sha512-9PyjVF5xsawbw2926WX/wfKTN3UIrnDseTeXv1yOhIhy+hBUynlECm2TKmXUg+WTdiUYME7kg1lGrH+LPIlQOQ==} engines: {node: '>=20'} @@ -8754,12 +8747,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@meksiabdou/react-native-barcode-mask@2.0.3(react-native-reanimated@4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3)': - dependencies: - react: 19.2.3 - react-native: 0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3) - react-native-reanimated: 4.3.1(react-native-worklets@0.8.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) - '@mendix/pluggable-widgets-tools@11.8.0(patch_hash=560aa323cdb292c24f00971ec20b781ca239273f210aa1fd174e40f9c2dae24f)(@jest/transform@29.7.0)(@jest/types@30.4.1)(@types/babel__core@7.20.5)(@types/node@20.19.41)(encoding@0.1.13)(jest-util@30.4.1)(picomatch@4.0.4)(react-dom@19.2.3(react@19.2.3))(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3)(tslib@2.8.1)': dependencies: '@babel/core': 7.29.7 From b3756af8c855f96616bdf82b606f7ef8d3756e86 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 17:03:09 +0530 Subject: [PATCH 09/10] fix: update testcases --- .../src/__tests__/BarcodeScanner.spec.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx b/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx index 5cf543df7..4774fd46e 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx +++ b/packages/pluggableWidgets/barcode-scanner-native/src/__tests__/BarcodeScanner.spec.tsx @@ -15,7 +15,7 @@ jest.mock("react-native-vision-camera", () => ({ } })); -jest.mock("@meksiabdou/react-native-barcode-mask", () => "BarcodeMask"); +jest.mock("../components/BarcodeMask", () => "BarcodeMask"); describe("BarcodeScanner", () => { let defaultProps: Props; From 3a46403f56e39433e293336a15c7512b22327e25 Mon Sep 17 00:00:00 2001 From: Saurabh Chavan Date: Tue, 4 Aug 2026 17:43:09 +0530 Subject: [PATCH 10/10] fix: react svg version update --- packages/pluggableWidgets/barcode-scanner-native/package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pluggableWidgets/barcode-scanner-native/package.json b/packages/pluggableWidgets/barcode-scanner-native/package.json index 7b6da7ef7..33c62cfc7 100644 --- a/packages/pluggableWidgets/barcode-scanner-native/package.json +++ b/packages/pluggableWidgets/barcode-scanner-native/package.json @@ -21,7 +21,7 @@ "dependencies": { "@mendix/piw-native-utils-internal": "*", "@mendix/piw-utils-internal": "*", - "react-native-svg": "^15.15.4", + "react-native-svg": "15.15.4", "react-native-vision-camera": "4.7.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e97bbc84..a7afd4b73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -351,7 +351,7 @@ importers: specifier: '*' version: link:../../tools/piw-utils-internal react-native-svg: - specifier: ^15.15.4 + specifier: 15.15.4 version: 15.15.4(react-native@0.84.1(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7))(@types/react@19.2.16)(react@19.2.3))(react@19.2.3) react-native-vision-camera: specifier: 4.7.3