Skip to content

Commit

Permalink
searching for permissions before request
Browse files Browse the repository at this point in the history
  • Loading branch information
Darguima committed Feb 22, 2024
1 parent 64faf41 commit 5c66d2c
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 60 deletions.
16 changes: 11 additions & 5 deletions components/QRScanner/BarebonesQRScanner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { useRef, useState, useEffect, MutableRefObject } from "react";
import {
useRef,
useState,
useEffect,
MutableRefObject,
ReactNode,
} from "react";
import { FEEDBACK, FeedbackType } from "@components/QRScanner";
import useWebcamPermissions from "./useWebcamPermissions";
import useWebcamPermissions from "./useWebcam";
import useQRScanner from "./useQRScanner";

interface Props {
Expand All @@ -17,7 +23,7 @@ const BarebonesQRScanner: React.FC<Props> = ({
setScanFeedback = (_) => {},
}) => {
const [successReadingCode, setSuccessReadingCode] = useState(false);
const [camMessage, setCamMessage] = useState<string>("");
const [camMessage, setCamMessage] = useState<ReactNode>("");
const [isCamReady, setIsCamReady] = useState(false);

const videoRef = useRef<HTMLVideoElement>(null);
Expand Down Expand Up @@ -81,8 +87,8 @@ const BarebonesQRScanner: React.FC<Props> = ({
className="absolute h-full w-full rounded-2xl object-cover"
/>

<div>
<p className="p-16 text-center text-white">{camMessage}</p>
<div className="absolute flex h-full w-full items-center justify-center">
<div className="p-16 text-center text-white">{camMessage}</div>
</div>
</div>
);
Expand Down
1 change: 0 additions & 1 deletion components/QRScanner/BarebonesQRScanner/useQRScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const useQRScanner = ({
handleQRCode,
setSuccessReadingCode,
}: useQRScannerProps) => {

useEffect(() => {
drawQRBoundingBox();
}, [isCamReady]);
Expand Down
94 changes: 94 additions & 0 deletions components/QRScanner/BarebonesQRScanner/useWebcam.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useEffect, ReactNode } from "react";
import Button from "components/Button";

const CAPTURE_OPTIONS = {
audio: false,
video: { facingMode: "environment" },
};

interface useWebcamPermissionsRequestProps {
videoRef: React.RefObject<HTMLVideoElement>;
setCamMessage: React.Dispatch<React.SetStateAction<ReactNode>>;
onPermissionGranted: () => void;
}

const checkWebcamPermissions = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();

const permissions = devices
.filter(({ kind }) => kind === "videoinput")
.filter(({ label }) => label !== "");

return permissions.length > 0;
};

export const requestWebcam = ({
videoRef,
setCamMessage,
onPermissionGranted,
}: useWebcamPermissionsRequestProps) => {
const video = videoRef.current;

if (!video?.srcObject) {
setCamMessage("Grant camera permissions to be able to scan QR codes.");

navigator.mediaDevices
.getUserMedia(CAPTURE_OPTIONS)
.then((stream) => {
if (!video?.srcObject) {
video.srcObject = stream;
video.setAttribute("playsinline", "true"); // required to tell iOS safari we don't want fullscreen
video.play();

setCamMessage("");
onPermissionGranted();
}
})
.catch((err) => {
if (!video?.srcObject && err instanceof DOMException) {
setCamMessage(
"We couldn't access your camera. Check if your camera is being used by another app and if you gave us permission to use it."
);
}
});
}
};

const useWebcam = ({
videoRef,
setCamMessage,
onPermissionGranted,
}: useWebcamPermissionsRequestProps) => {
useEffect(() => {
checkWebcamPermissions()
.then((arePermissionsGranted) => {
if (!arePermissionsGranted) {
setCamMessage(
<Button
title="Click me to open QRScanner!"
onClick={() =>
requestWebcam({ videoRef, setCamMessage, onPermissionGranted })
}
/>
);
} else {
requestWebcam({ videoRef, setCamMessage, onPermissionGranted });
}
})
.catch(() => {
requestWebcam({ videoRef, setCamMessage, onPermissionGranted });
});

const video = videoRef.current;

return () => {
if (video && video.srcObject) {
(video.srcObject as MediaStream).getTracks().forEach((track) => {
track.stop();
});
}
};
}, []);
};

export default useWebcam;
54 changes: 0 additions & 54 deletions components/QRScanner/BarebonesQRScanner/useWebcamPermissions.ts

This file was deleted.

0 comments on commit 5c66d2c

Please sign in to comment.