diff --git a/src/components/QrCodeScanner/QrCodeScanner.tsx b/src/components/QrCodeScanner/QrCodeScanner.tsx index b95ee1c..fd285e0 100644 --- a/src/components/QrCodeScanner/QrCodeScanner.tsx +++ b/src/components/QrCodeScanner/QrCodeScanner.tsx @@ -1,8 +1,12 @@ -import { Button, Card, CardContent, Grid, Modal, ModalProps, Stack, SxProps, Typography } from "@mui/material"; -import { Html5Qrcode, Html5QrcodeCameraScanConfig, Html5QrcodeFullConfig, Html5QrcodeResult, Html5QrcodeScanner, QrcodeErrorCallback, QrcodeSuccessCallback } from "html5-qrcode"; +import { Autocomplete, Box, Button, Card, CardContent, Grid, Modal, ModalProps, Stack, SxProps, TextField, Typography } from "@mui/material"; +import { CameraDevice, Html5Qrcode, Html5QrcodeCameraScanConfig, Html5QrcodeFullConfig, Html5QrcodeResult, Html5QrcodeScanner, Html5QrcodeScannerState, QrcodeErrorCallback, QrcodeSuccessCallback } from "html5-qrcode"; import { Html5QrcodeError } from "html5-qrcode/esm/core"; import { Html5QrcodeScannerConfig } from "html5-qrcode/esm/html5-qrcode-scanner"; import React, { RefObject, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import QrCodeScannerIcon from '@mui/icons-material/QrCodeScanner'; +import StopCircleOutlinedIcon from '@mui/icons-material/StopCircleOutlined'; +import CloseOutlinedIcon from '@mui/icons-material/CloseOutlined'; const scannerSx: React.CSSProperties = { position: "absolute", @@ -15,28 +19,36 @@ const scannerSx: React.CSSProperties = { }; type QrCodeScannerProps = { + title?: string, onScanSuccess: (result: string) => void, onScanError?: (error: string) => void, - isOpen: boolean + isOpen: boolean, + onClose: () => void } const QrCodeScanner: React.FC = ({ + title, onScanSuccess, onScanError, - isOpen + isOpen, + onClose }) => { - + const { t } = useTranslation() const [isScanned, setIsScanned] = useState(false) const [scanner, setScanner] = useState(null) + const [cameraList, setCameraList] = useState([]) + const [selectedCameraId, setSelectedCameraId] = useState(null) + const stringList = ["ABC: abc", "123:123", "ABC: abc", "123:123", "ABC: abc", "123:123"] + const scannerConfig: Html5QrcodeFullConfig = { verbose: false } const cameraConfig: Html5QrcodeCameraScanConfig = { fps: 10, - qrbox: { width: 400, height: 400 }, + qrbox: { width: 250, height: 250 }, // aspectRatio: cardRef.current ? (cardRef.current.offsetWidth / cardRef.current.offsetHeight) : 1.78, - aspectRatio: 2.5 + aspectRatio: (window.innerWidth / window.innerHeight) * 1.5 // can be better }; // MediaTrackConstraintSet @@ -44,26 +56,56 @@ const QrCodeScanner: React.FC = ({ facingMode: "environment" } - useEffect(() => { - setScanner(new Html5Qrcode( - "qr-reader", - scannerConfig - )) + const handleScanStart = useCallback(() => { + if (scanner && selectedCameraId) { + if (scanner.getState() === Html5QrcodeScannerState.SCANNING) { + console.log("first") + scanner.stop() + } + + scanner.start( + selectedCameraId, + cameraConfig, + handleScanSuccess, + handleScanError + ) + } + + }, [selectedCameraId, scanner]) + + const handleCameraList = useCallback(async () => { + const cameras = await Html5Qrcode.getCameras() + setCameraList(cameras) + if (cameras.length > 0) { + handleCameraChange(cameras[0].id) + } + }, []) + + const handleCameraChange = useCallback((id: string) => { + setSelectedCameraId(id) }, []) - const handleStartScan = useCallback(() => { + const switchScanStatus = useCallback(() => { if (scanner) { - setIsScanned(false) - scanner.resume(); + console.log(isScanned) + switch (isScanned) { + case true: + setIsScanned(false); + scanner.resume(); + break; + case false: + setIsScanned(true); + scanner.pause(true); + break; + } } - }, [scanner]) + }, [scanner, isScanned]) const handleScanSuccess = useCallback((decodedText, result) => { if (scanner) { console.log(`Decoded text: ${decodedText}`); // Handle the decoded text as needed - setIsScanned(true) - scanner.pause(); + switchScanStatus() onScanSuccess(decodedText) } }, [scanner, onScanSuccess]) @@ -76,55 +118,99 @@ const QrCodeScanner: React.FC = ({ } }, [scanner, onScanError]) - const handleScanClose = useCallback(async () => { + + + const handleScanCloseButton = useCallback(async () => { if (scanner) { console.log("Cleaning up scanner..."); await scanner.stop() await scanner.clear() + onClose() } }, [scanner]) + // close modal without using Cancel Button + const handleScanClose = useCallback(async () => { + if (scanner && !isOpen) { + handleScanCloseButton() + } + }, [scanner, isOpen, handleScanCloseButton]) + + // -------------------------------------------------------// useEffect(() => { - if (scanner) { - console.log("Scanner Instance:", scanner); + setScanner(new Html5Qrcode( + "qr-reader", + scannerConfig + )) - scanner.start( - mediaTrackConstraintSet, - cameraConfig, - handleScanSuccess, - handleScanError - ) + handleCameraList() + }, []) - return () => { - handleScanClose() - }; - } - }, [scanner]); + useEffect(() => { + handleScanStart() + }, [scanner, selectedCameraId]); + + useEffect(() => { + handleScanClose() + }, [isOpen]) return ( <> - + {title ? {"Title"} - - - -