-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[INJIVER-127] Update QR code scanning and upload libraries (#136)
* [DSD-5765] Updated pom.xml Signed-off-by: Rakshith B <[email protected]> Signed-off-by: srikanth716 <[email protected]> * [DSD-5765] added browserstack-web.yml Signed-off-by: Rakshith B <[email protected]> Signed-off-by: srikanth716 <[email protected]> * [DSD-5765] Updated browserstack-web.yml Signed-off-by: Rakshith B <[email protected]> Signed-off-by: srikanth716 <[email protected]> * [INJIVER-127]: integrate HTML5 QRcode to scan upload qr Signed-off-by: srikanth716 <[email protected]> * [INJIVER-127]: integrate HTML5 library for both upload and scan Signed-off-by: srikanth716 <[email protected]> * [INJIVER-127]: injiver-durian-integration-testing Signed-off-by: srikanth716 <[email protected]> * revert ovp qr header config Signed-off-by: srikanth716 <[email protected]> * [INJIVER-444]: update readme file and added fictious assets (#130) * [INJIVER-444]: update readme file and added fictious assets Signed-off-by: srikanth716 <[email protected]> * [INJIVER-444]: Organized fictitious assets by placing them in the directory Signed-off-by: srikanth716 <[email protected]> * [INJIVER-444]: updated readme with available tags,release branches and active branches Signed-off-by: srikanth716 <[email protected]> --------- Signed-off-by: srikanth716 <[email protected]> * Update browserstack-web.yml Signed-off-by: Mohan E <[email protected]> Signed-off-by: srikanth716 <[email protected]> * [DSD-6004] Updated browserstack-web.yml to push artifacts to s3 bucket. Signed-off-by: Mohan E <[email protected]> Signed-off-by: srikanth716 <[email protected]> * [DSD-6004] Updated browserstack-web.yml Signed-off-by: Mohan E <[email protected]> Signed-off-by: srikanth716 <[email protected]> * [DSD-6004] Updated browserstack-web.yml Signed-off-by: Mohan E <[email protected]> Signed-off-by: srikanth716 <[email protected]> * handeling durian changes from inji web (#135) Signed-off-by: srikanth716 <[email protected]> * [INJIVER-127] chore: Update QR code scanning and upload libraries Signed-off-by: srikanth716 <[email protected]> * [INJIVER-127] remove old libraries Signed-off-by: srikanth716 <[email protected]> --------- Signed-off-by: Rakshith B <[email protected]> Signed-off-by: srikanth716 <[email protected]> Signed-off-by: Mohan E <[email protected]> Co-authored-by: Rakshith B <[email protected]> Co-authored-by: Mohan E <[email protected]>
- Loading branch information
1 parent
3d6a465
commit eb27f0b
Showing
7 changed files
with
244 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
INTERNET_CONNECTIVITY_CHECK_ENDPOINT=https://dns.google/ | ||
INTERNET_CONNECTIVITY_CHECK_TIMEOUT=10000 | ||
OVP_CLIENT_ID=https://injiverify.dev1.mosip.net | ||
OVP_QR_HEADER=INJI_OVP://payload= | ||
OVP_QR_HEADER=INJI_OVP:// |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
163 changes: 72 additions & 91 deletions
163
inji-verify/src/components/Home/VerificationSection/QrScanner.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,105 +1,86 @@ | ||
import React, {useEffect, useRef, useState} from 'react'; | ||
import {Scanner} from '@yudiel/react-qr-scanner'; | ||
import React, { useEffect, useRef, useState } from "react"; | ||
import CameraAccessDenied from "./CameraAccessDenied"; | ||
import {ScanSessionExpiryTime} from "../../../utils/config"; | ||
import {useAppDispatch} from "../../../redux/hooks"; | ||
import {goHomeScreen, verificationInit} from "../../../redux/features/verification/verification.slice"; | ||
import {raiseAlert} from "../../../redux/features/alerts/alerts.slice"; | ||
import { ScanSessionExpiryTime } from "../../../utils/config"; | ||
import { useAppDispatch } from "../../../redux/hooks"; | ||
import { | ||
goHomeScreen, | ||
verificationInit, | ||
} from "../../../redux/features/verification/verification.slice"; | ||
import { raiseAlert } from "../../../redux/features/alerts/alerts.slice"; | ||
import "./ScanningLine.css"; | ||
import { initiateQrScanning, terminateScanning } from "../../../utils/qr-utils"; | ||
|
||
let timer: NodeJS.Timeout; | ||
|
||
function QrScanner() { | ||
const dispatch = useAppDispatch(); | ||
const [isCameraBlocked, setIsCameraBlocked] = useState(false); | ||
const dispatch = useAppDispatch(); | ||
const [isCameraBlocked, setIsCameraBlocked] = useState(false); | ||
|
||
const scannerRef = useRef<HTMLDivElement>(null); | ||
const scannerRef = useRef<HTMLDivElement>(null); | ||
|
||
useEffect(() => { | ||
timer = setTimeout(() => { | ||
dispatch(goHomeScreen({})); | ||
dispatch(raiseAlert({ | ||
open: true, | ||
message: "The scan session has expired due to inactivity. Please initiate a new scan.", | ||
severity: "error" | ||
})) | ||
}, ScanSessionExpiryTime); | ||
return () => { | ||
console.log('Clearing timeout'); | ||
clearTimeout(timer) | ||
}; | ||
}, [dispatch]); | ||
const onSuccess = (decodedText: any) => { | ||
dispatch( | ||
verificationInit({ | ||
qrReadResult: { qrData: decodedText, status: "SUCCESS" }, | ||
flow: "SCAN", | ||
}) | ||
); | ||
clearTimeout(timer); | ||
}; | ||
|
||
useEffect(() => { | ||
timer = setTimeout(() => { | ||
dispatch(goHomeScreen({})); | ||
dispatch( | ||
raiseAlert({ | ||
open: true, | ||
message: | ||
"The scan session has expired due to inactivity. Please initiate a new scan.", | ||
severity: "error", | ||
}) | ||
); | ||
terminateScanning(); | ||
}, ScanSessionExpiryTime); | ||
initiateQrScanning(timer, onSuccess); | ||
return () => { | ||
console.log("Clearing timeout"); | ||
clearTimeout(timer); | ||
}; | ||
}, [dispatch]); | ||
|
||
useEffect(() => { | ||
// Disable inbuilt border around the video | ||
if (scannerRef?.current) { | ||
let svgElements = scannerRef?.current?.getElementsByTagName('svg'); | ||
if (svgElements.length === 1) { | ||
svgElements[0].style.display = 'none'; | ||
} | ||
} | ||
}, [scannerRef]); | ||
useEffect(() => { | ||
// Disable inbuilt border around the video | ||
if (scannerRef?.current) { | ||
let svgElements = scannerRef?.current?.getElementsByTagName("svg"); | ||
if (svgElements.length === 1) { | ||
svgElements[0].style.display = "none"; | ||
} | ||
} | ||
}, [scannerRef]); | ||
|
||
return ( | ||
<div ref={scannerRef} className="relative"> | ||
{ | ||
!isCameraBlocked && ( | ||
<div | ||
className="absolute top-[-15px] left-[-15px] h-[280px] w-[280px] lg:top-[-12px] lg:left-[-12px] lg:h-[340px] lg:w-[340px] flex items-center justify-center"> | ||
<div id="scanning-line" className="scanning-line"></div> | ||
</div> | ||
) | ||
} | ||
<Scanner | ||
onResult={(text, result) => { | ||
console.log(text, result); | ||
dispatch(verificationInit({qrReadResult: {qrData: text, status: "SUCCESS"}, flow: "SCAN"})); | ||
}} | ||
onError={(error) => { | ||
console.log('Clearing timeout - camera blocked'); | ||
clearTimeout(timer); | ||
setIsCameraBlocked(true); | ||
}} | ||
components={{ | ||
torch: false | ||
}} | ||
options={{ | ||
constraints: { | ||
"width": { | ||
"min": 640, | ||
"ideal": 720, | ||
"max": 1920 | ||
}, | ||
"height": { | ||
"min": 640, | ||
"ideal": 720, | ||
"max": 1080 | ||
}, | ||
facingMode: "environment" | ||
}, | ||
delayBetweenScanSuccess: 1000000 // Scan once | ||
}} | ||
styles={{ | ||
container: { | ||
width: window.innerWidth < 1024 ? "250px" : "316px", | ||
placeContent: "center", | ||
display: "grid", | ||
placeItems: "center", | ||
borderRadius: "12px" | ||
}, | ||
video: { | ||
objectFit: "cover", | ||
objectPosition: "center" | ||
} | ||
}} | ||
/> | ||
<CameraAccessDenied open={isCameraBlocked} handleClose={() => { | ||
console.log("closing camera"); | ||
dispatch(goHomeScreen({})); | ||
setIsCameraBlocked(false) | ||
}}/> | ||
return ( | ||
<div ref={scannerRef} className="relative"> | ||
{!isCameraBlocked && ( | ||
<div className="absolute top-[-15px] left-[-15px] h-[280px] w-[280px] lg:top-[-12px] lg:left-[-12px] lg:h-[340px] lg:w-[340px] flex items-center justify-center"> | ||
<div id="scanning-line" className="scanning-line"></div> | ||
</div> | ||
); | ||
)} | ||
|
||
<div | ||
className="none absolute h-[250px] w-[250px] lg:h-[316px] lg:w-[316px] rounded-lg overflow-hidden flex items-center justify-center" | ||
id="reader" | ||
/> | ||
|
||
<CameraAccessDenied | ||
open={isCameraBlocked} | ||
handleClose={() => { | ||
console.log("closing camera"); | ||
dispatch(goHomeScreen({})); | ||
setIsCameraBlocked(false); | ||
}} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
export default QrScanner; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 41 additions & 35 deletions
76
inji-verify/src/components/Home/VerificationSection/Verification.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,49 @@ | ||
import React from 'react'; | ||
import React from "react"; | ||
import scanQr from "../../../assets/scanner-ouline.svg"; | ||
import Loader from "../../commons/Loader"; | ||
import QrScanner from "./QrScanner"; | ||
import StyledButton from "./commons/StyledButton"; | ||
import {useAppDispatch} from "../../../redux/hooks"; | ||
import {goHomeScreen} from "../../../redux/features/verification/verification.slice"; | ||
import {VerificationSteps} from "../../../utils/config"; | ||
import {useVerificationFlowSelector} from "../../../redux/features/verification/verification.selector"; | ||
import { useAppDispatch } from "../../../redux/hooks"; | ||
import { goHomeScreen } from "../../../redux/features/verification/verification.slice"; | ||
import { VerificationSteps } from "../../../utils/config"; | ||
import { useVerificationFlowSelector } from "../../../redux/features/verification/verification.selector"; | ||
import { terminateScanning } from "../../../utils/qr-utils"; | ||
|
||
const Verification = () => { | ||
const dispatch = useAppDispatch(); | ||
const {activeScreen, method} = useVerificationFlowSelector(state => ({activeScreen: state.activeScreen, method: state.method})); | ||
console.log({activeScreen}); | ||
return ( | ||
<div | ||
className="grid grid-cols-12 mx-auto pt-1 pb-[100px] px-[16px] lg:py-[42px] lg:px-[104px] text-center content-center justify-center"> | ||
<div | ||
className="col-start-1 col-end-13 grid w-[100%] lg:w-[350px] aspect-square max-w-[280px] lg:max-w-none bg-cover content-center justify-center m-auto" | ||
style={{ | ||
backgroundImage: `url(${scanQr})` | ||
}}> | ||
{ | ||
activeScreen === VerificationSteps[method].Verifying | ||
? (<Loader/>) | ||
: (<QrScanner/>) | ||
} | ||
</div> | ||
<div className="col-span-12"> | ||
<StyledButton | ||
id="verification-back-button" | ||
className="w-[100%] lg:w-[350px] max-w-[280px] lg:max-w-none mt-[18px]" | ||
onClick={() => { | ||
dispatch(goHomeScreen({})) | ||
}}> | ||
Back | ||
</StyledButton> | ||
</div> | ||
</div> | ||
); | ||
} | ||
const dispatch = useAppDispatch(); | ||
const { activeScreen, method } = useVerificationFlowSelector((state) => ({ | ||
activeScreen: state.activeScreen, | ||
method: state.method, | ||
})); | ||
console.log({ activeScreen }); | ||
return ( | ||
<div className="grid grid-cols-12 mx-auto pt-1 pb-[100px] px-[16px] lg:py-[42px] lg:px-[104px] text-center content-center justify-center"> | ||
<div | ||
className="col-start-1 col-end-13 grid w-[100%] lg:w-[350px] aspect-square max-w-[280px] lg:max-w-none bg-cover content-center justify-center m-auto" | ||
style={{ | ||
backgroundImage: `url(${scanQr})`, | ||
}} | ||
> | ||
{activeScreen === VerificationSteps[method].Verifying ? ( | ||
<Loader /> | ||
) : ( | ||
<QrScanner /> | ||
)} | ||
</div> | ||
<div className="col-span-12"> | ||
<StyledButton | ||
id="verification-back-button" | ||
className="w-[100%] lg:w-[350px] max-w-[280px] lg:max-w-none mt-[18px]" | ||
onClick={() => { | ||
terminateScanning(); | ||
dispatch(goHomeScreen({})); | ||
}} | ||
> | ||
Back | ||
</StyledButton> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Verification; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import * as pdfjsLib from "pdfjs-dist/webpack"; | ||
import jsQR from "jsqr"; | ||
|
||
const decodeQrCode = (imageDataUrl) => { | ||
return new Promise((resolve, reject) => { | ||
const img = new Image(); | ||
img.onload = () => { | ||
const canvas = document.createElement("canvas"); | ||
canvas.width = img.width; | ||
canvas.height = img.height; | ||
const ctx = canvas.getContext("2d"); | ||
ctx.drawImage(img, 0, 0); | ||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
const decoded = jsQR(imageData.data, canvas.width, canvas.height); | ||
if (decoded) { | ||
resolve(decoded.data); | ||
} else { | ||
resolve(null); | ||
} | ||
}; | ||
img.onerror = () => reject("Error loading image"); | ||
img.src = imageDataUrl; | ||
}); | ||
}; | ||
|
||
export const pdfToQrData = async (file) => { | ||
try { | ||
const pdfData = await file.arrayBuffer(); | ||
const pdf = await pdfjsLib.getDocument({ data: pdfData }).promise; | ||
let qrData; | ||
|
||
for (let i = 1; i <= pdf.numPages; i++) { | ||
const page = await pdf.getPage(i); | ||
const viewport = page.getViewport({ scale: 2.0 }); | ||
const canvas = document.createElement("canvas"); | ||
const context = canvas.getContext("2d"); | ||
canvas.height = viewport.height; | ||
canvas.width = viewport.width; | ||
const renderContext = { | ||
canvasContext: context, | ||
viewport: viewport, | ||
}; | ||
await page.render(renderContext).promise; | ||
const dataURL = canvas.toDataURL("image/png"); | ||
qrData = await decodeQrCode(dataURL); | ||
|
||
if (qrData) { | ||
break; // Exit loop if QR code is found | ||
} | ||
} | ||
|
||
return qrData; | ||
} catch (err) { | ||
console.error("Error processing PDF:", err); | ||
throw new Error("Failed to process PDF file."); | ||
} | ||
}; |
Oops, something went wrong.