Added Qr scann on mobile Funtionalites
This commit is contained in:
parent
4fbce4ec31
commit
374c76540f
|
|
@ -0,0 +1,419 @@
|
|||
// import React, { useRef, useState, useEffect } from "react";
|
||||
// import { BarcodeScanner } from "@capacitor-mlkit/barcode-scanning";
|
||||
// import { BsUpcScan } from "react-icons/bs";
|
||||
// import { BrowserMultiFormatReader } from "@zxing/library";
|
||||
// import { Capacitor } from "@capacitor/core";
|
||||
// import { DefaultModal } from "../Components/Modal/DefaultModal";
|
||||
|
||||
// export default function BarCodeScan({ onScan }) {
|
||||
// const isMobileApp = Capacitor.getPlatform() !== "web";
|
||||
// const [scanning, setScanning] = useState(false);
|
||||
// const [modalOpen, setModalOpen] = useState(false);
|
||||
// const videoRef = useRef(null);
|
||||
// const codeReaderRef = useRef(null);
|
||||
// const streamRef = useRef(null);
|
||||
|
||||
// const startScan = async () => {
|
||||
// if (scanning) return;
|
||||
// setScanning(true);
|
||||
|
||||
// if (isMobileApp) {
|
||||
// // Mobile: MLKit scanner
|
||||
// try {
|
||||
// const perm = await BarcodeScanner.requestPermissions();
|
||||
// if (perm.camera !== "granted") {
|
||||
// alert("Camera permission not granted");
|
||||
// setScanning(false);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const { barcodes } = await BarcodeScanner.scan();
|
||||
// if (barcodes && barcodes.length > 0) {
|
||||
// onScan(barcodes[0].rawValue);
|
||||
// }
|
||||
// } catch (err) {
|
||||
// alert("Error scanning barcode: " + err.message);
|
||||
// } finally {
|
||||
// setScanning(false);
|
||||
// }
|
||||
// } else {
|
||||
// // Web: open modal and start camera
|
||||
// setModalOpen(true);
|
||||
// setTimeout(() => startWebScan(), 50); // wait for modal DOM
|
||||
// }
|
||||
// };
|
||||
|
||||
// const startWebScan = async () => {
|
||||
// try {
|
||||
// codeReaderRef.current = new BrowserMultiFormatReader();
|
||||
// streamRef.current = await navigator.mediaDevices.getUserMedia({
|
||||
// video: { facingMode: "environment" },
|
||||
// });
|
||||
// if (videoRef.current) {
|
||||
// videoRef.current.srcObject = streamRef.current;
|
||||
// videoRef.current.play();
|
||||
// }
|
||||
|
||||
// codeReaderRef.current.decodeFromVideoDevice(
|
||||
// null,
|
||||
// videoRef.current,
|
||||
// (result) => {
|
||||
// if (result) {
|
||||
// onScan(result.getText());
|
||||
// stopWebScan();
|
||||
// setModalOpen(false);
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// } catch (err) {
|
||||
// alert("Error accessing camera: " + err.message);
|
||||
// setScanning(false);
|
||||
// setModalOpen(false);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const stopWebScan = () => {
|
||||
// if (streamRef.current) {
|
||||
// streamRef.current.getTracks().forEach((track) => track.stop());
|
||||
// streamRef.current = null;
|
||||
// }
|
||||
// if (codeReaderRef.current) {
|
||||
// codeReaderRef.current.reset();
|
||||
// codeReaderRef.current = null;
|
||||
// }
|
||||
// setScanning(false);
|
||||
// };
|
||||
|
||||
// const closeModal = () => {
|
||||
// stopWebScan();
|
||||
// setModalOpen(false);
|
||||
// };
|
||||
|
||||
// // Stop camera if component unmounts
|
||||
// useEffect(() => () => stopWebScan(), []);
|
||||
|
||||
// return (
|
||||
// <div style={{ display: "flex", justifyContent: "center", padding: 20 }}>
|
||||
// {!scanning && (
|
||||
// <BsUpcScan
|
||||
// onClick={startScan}
|
||||
// style={{ fontSize: 32, color: "#007bff", cursor: "pointer" }}
|
||||
// />
|
||||
// )}
|
||||
|
||||
// <DefaultModal
|
||||
// title="Barcode Reader"
|
||||
// width={500}
|
||||
// open={modalOpen}
|
||||
// footer={false}
|
||||
// handleCancel={() => {
|
||||
// closeModal();
|
||||
// }}
|
||||
// >
|
||||
// <div
|
||||
// style={{
|
||||
// display: "flex",
|
||||
// flexDirection: "column",
|
||||
// alignItems: "center",
|
||||
// justifyContent: "center",
|
||||
// }}
|
||||
// >
|
||||
// <video
|
||||
// ref={videoRef}
|
||||
// style={{
|
||||
// width: "100%",
|
||||
// maxWidth: 400,
|
||||
// borderRadius: 8,
|
||||
// border: "2px solid #000",
|
||||
// }}
|
||||
// />
|
||||
|
||||
// <button
|
||||
// onClick={closeModal}
|
||||
// style={{
|
||||
// marginTop: 20,
|
||||
// padding: "10px 20px",
|
||||
// fontSize: 16,
|
||||
// borderRadius: 8,
|
||||
// border: "none",
|
||||
// cursor: "pointer",
|
||||
// }}
|
||||
// >
|
||||
// Close
|
||||
// </button>
|
||||
// </div>
|
||||
// </DefaultModal>
|
||||
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
import React, { useRef, useState, useEffect } from "react";
|
||||
import { BarcodeScanner } from "@capacitor-mlkit/barcode-scanning";
|
||||
import { BsUpcScan } from "react-icons/bs";
|
||||
import { Capacitor } from "@capacitor/core";
|
||||
import { DefaultModal } from "../Components/Modal/DefaultModal";
|
||||
import QrScanner from "qr-scanner/qr-scanner.min.js";
|
||||
import {
|
||||
BrowserMultiFormatReader,
|
||||
BarcodeFormat,
|
||||
} from "@zxing/library";
|
||||
|
||||
QrScanner.WORKER_PATH = new URL(
|
||||
"qr-scanner/qr-scanner-worker.min.js",
|
||||
import.meta.url
|
||||
).toString();
|
||||
|
||||
export default function BarCodeScan({ onScan }) {
|
||||
const isMobileApp = Capacitor.getPlatform() !== "web";
|
||||
const [scanning, setScanning] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
const videoRef = useRef(null);
|
||||
const qrScannerRef = useRef(null);
|
||||
const barcodeReaderRef = useRef(null);
|
||||
|
||||
// -------------------------
|
||||
// START SCAN
|
||||
// -------------------------
|
||||
const startScan = async () => {
|
||||
if (scanning) return;
|
||||
setScanning(true);
|
||||
|
||||
if (isMobileApp) {
|
||||
try {
|
||||
const perm = await BarcodeScanner.requestPermissions();
|
||||
if (perm.camera !== "granted") {
|
||||
alert("Camera permission not granted");
|
||||
setScanning(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const { barcodes } = await BarcodeScanner.scan();
|
||||
if (barcodes?.length > 0) {
|
||||
onScan(barcodes[0].rawValue);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
setScanning(false);
|
||||
}
|
||||
} else {
|
||||
setModalOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------
|
||||
// START WEB SCAN (HYBRID)
|
||||
// -------------------------
|
||||
const startWebScan = async () => {
|
||||
if (!videoRef.current) return;
|
||||
|
||||
// Start QR scanner (fast)
|
||||
qrScannerRef.current = new QrScanner(
|
||||
videoRef.current,
|
||||
(result) => {
|
||||
stopWebScan();
|
||||
onScan(result.data);
|
||||
setModalOpen(false);
|
||||
},
|
||||
{
|
||||
maxScansPerSecond: 25,
|
||||
}
|
||||
);
|
||||
|
||||
await qrScannerRef.current.start();
|
||||
|
||||
// Start Barcode scanner (ZXing)
|
||||
barcodeReaderRef.current = new BrowserMultiFormatReader(undefined, {
|
||||
possibleFormats: [
|
||||
BarcodeFormat.CODE_128,
|
||||
BarcodeFormat.EAN_13,
|
||||
BarcodeFormat.UPC_A,
|
||||
BarcodeFormat.UPC_E,
|
||||
],
|
||||
});
|
||||
|
||||
barcodeReaderRef.current.timeBetweenDecodingAttempts = 50;
|
||||
|
||||
barcodeReaderRef.current.decodeFromVideoDevice(
|
||||
null,
|
||||
videoRef.current,
|
||||
(result) => {
|
||||
if (result) {
|
||||
stopWebScan();
|
||||
onScan(result.getText());
|
||||
setModalOpen(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const stopWebScan = () => {
|
||||
if (qrScannerRef.current) {
|
||||
qrScannerRef.current.stop();
|
||||
qrScannerRef.current.destroy();
|
||||
qrScannerRef.current = null;
|
||||
}
|
||||
|
||||
if (barcodeReaderRef.current) {
|
||||
barcodeReaderRef.current.reset();
|
||||
barcodeReaderRef.current = null;
|
||||
}
|
||||
|
||||
setScanning(false);
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
stopWebScan();
|
||||
setModalOpen(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (modalOpen) {
|
||||
startWebScan();
|
||||
}
|
||||
}, [modalOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => stopWebScan();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", justifyContent: "center", padding: 20 }}>
|
||||
{!scanning && (
|
||||
<BsUpcScan
|
||||
onClick={startScan}
|
||||
style={{
|
||||
fontSize: 32,
|
||||
color: "#007bff",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* <DefaultModal
|
||||
title="QR / Barcode Reader"
|
||||
width={500}
|
||||
open={modalOpen}
|
||||
footer={false}
|
||||
handleCancel={closeModal}
|
||||
>
|
||||
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||
<video
|
||||
ref={videoRef}
|
||||
style={{
|
||||
width: "100%",
|
||||
maxWidth: 400,
|
||||
borderRadius: 8,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={closeModal}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
padding: "10px 20px",
|
||||
fontSize: 16,
|
||||
borderRadius: 8,
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</DefaultModal> */}
|
||||
<DefaultModal
|
||||
title="QR / Barcode Reader"
|
||||
width={500}
|
||||
open={modalOpen}
|
||||
footer={false}
|
||||
handleCancel={closeModal}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
maxWidth: 400,
|
||||
margin: "auto",
|
||||
}}
|
||||
>
|
||||
{/* VIDEO */}
|
||||
<video
|
||||
ref={videoRef}
|
||||
style={{
|
||||
width: "100%",
|
||||
borderRadius: 8,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* DARK OVERLAY */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
background: "rgba(0,0,0,0.5)",
|
||||
borderRadius: 8,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* SCAN BOX */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
width: "70%",
|
||||
height: "60%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
border: "3px solid #00ff00",
|
||||
borderRadius: 12,
|
||||
boxShadow: "0 0 0 2000px rgba(0,0,0,0.4)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* SCAN LINE */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: "15%",
|
||||
width: "70%",
|
||||
height: 2,
|
||||
background: "red",
|
||||
animation: "scanAnimation 2s infinite linear",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={closeModal}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
padding: "10px 20px",
|
||||
fontSize: 16,
|
||||
borderRadius: 8,
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
|
||||
{/* Animation */}
|
||||
<style>
|
||||
{`
|
||||
@keyframes scanAnimation {
|
||||
0% { top: 25%; }
|
||||
50% { top: 70%; }
|
||||
100% { top: 25%; }
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</DefaultModal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue