Skip to content

Commit

Permalink
Merge branch 'qrscan-rotate-fix-rc' into release-v4.46.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Beerosagos committed Nov 13, 2024
2 parents 797e083 + bc386dc commit 91e4ed7
Showing 1 changed file with 64 additions and 43 deletions.
107 changes: 64 additions & 43 deletions frontends/web/src/hooks/qrcodescanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,61 +34,82 @@ export const useQRScanner = (
const { t } = useTranslation();
const [initErrorMessage, setInitErrorMessage] = useState();
const scanner = useRef<QrScanner | null>(null);

useEffect(() => {
if (videoRef.current && !scanner.current) {
scanner.current = new QrScanner(
videoRef.current,
result => {
scanner.current?.stop();
onResult(result);
}, {
onDecodeError: err => {
const errorString = err.toString();
if (err && !errorString.includes('No QR code found')) {
onError(err);
}
},
highlightScanRegion: true,
highlightCodeOutline: true,
calculateScanRegion: (v) => {
const videoWidth = v.videoWidth;
const videoHeight = v.videoHeight;
const factor = 0.5;
const size = Math.floor(Math.min(videoWidth, videoHeight) * factor);
return {
x: (videoWidth - size) / 2,
y: (videoHeight - size) / 2,
width: size,
height: size
};
}
}
);
}
return () => {
scanner.current?.stop();
scanner.current?.destroy();
scanner.current = null;
};
}, [onError, onResult, videoRef]);
// loading is set to true while the scanner is being created/started/stopped/destroyed,
// this allows to sync across re-renders.
const loading = useRef<boolean>(false);

useEffect(() => {
(async () => {
if (!videoRef.current) {
return;
}

while (loading.current) {
await new Promise(r => setTimeout(r, 100));
}
try {
await new Promise(r => setTimeout(r, 300));
if (scanner.current) {
await scanner.current.start();
if (onStart) {
onStart();
loading.current = true;
scanner.current = new QrScanner(
videoRef.current,
result => {
scanner.current?.stop();
onResult(result);
}, {
onDecodeError: err => {
const errorString = err.toString();
if (err && !errorString.includes('No QR code found')) {
onError(err);
}
},
highlightScanRegion: true,
highlightCodeOutline: true,
calculateScanRegion: (v) => {
const videoWidth = v.videoWidth;
const videoHeight = v.videoHeight;
const factor = 0.5;
const size = Math.floor(Math.min(videoWidth, videoHeight) * factor);
return {
x: (videoWidth - size) / 2,
y: (videoHeight - size) / 2,
width: size,
height: size
};
}
}
);
// Somehow, the new QrScanner may return before it is ready to be started.
// We don't have a way to know when it is ready, but this 300ms wait seems
// to work well enough.
await new Promise(r => setTimeout(r, 300));
await scanner.current?.start();
loading.current = false;
if (onStart) {
onStart();
}
} catch (error: any) {
const stringifiedError = error.toString();
loading.current = false;
const cameraNotFound = stringifiedError === 'Camera not found.';
setInitErrorMessage(cameraNotFound ? t('send.scanQRNoCameraMessage') : stringifiedError);
onError(error);
}
})();

return () => {
(async() => {
while (loading.current) {
await new Promise(r => setTimeout(r, 100));
}
if (scanner.current) {
loading.current = true;
await scanner.current?.pause(true);
await scanner.current?.stop();
await scanner.current?.destroy();
scanner.current = null;
loading.current = false;
}
})();
};
}, [videoRef, onStart, onResult, onError, t]);

return { initErrorMessage };
Expand Down

0 comments on commit 91e4ed7

Please sign in to comment.