import {saveAs} from 'file-saver'; import React, {FormEvent, useEffect, useRef, useState} from "react"; import {BrowserQRCodeReader, IScannerControls} from "@zxing/browser"; import {Result} from "@zxing/library"; import {useTranslation} from 'next-i18next'; import Link from 'next/link'; import Card from "./Card"; import Alert from "./Alert"; import Check from './Check'; import {PayloadBody} from "../src/payload"; import {getPayloadBodyFromFile, getPayloadBodyFromQR} from "../src/process"; import {PassData} from "../src/pass"; import {COLORS} from "../src/colors"; import Colors from './Colors'; import Button from './Button'; function Form(): JSX.Element { const {t} = useTranslation(['index', 'errors', 'common']); // Whether camera is open or not const [isCameraOpen, setIsCameraOpen] = useState(false); // Currently selected color const [selectedColor, setSelectedColor] = useState(COLORS.WHITE); // Global camera controls const [globalControls, setGlobalControls] = useState(undefined); // Currently selected QR Code / File. Only one of them is set. const [qrCode, setQrCode] = useState(undefined); const [file, setFile] = useState(undefined); const [errorMessage, _setErrorMessage] = useState(undefined); const [loading, setLoading] = useState(false); // Check if there is a translation and replace message accordingly const setErrorMessage = (message: string) => { if (message == undefined) { _setErrorMessage(undefined); return; } const translation = t('errors:'.concat(message)); _setErrorMessage(translation !== message ? translation : message); }; // File Input ref const inputFile = useRef(undefined) // Add event listener to listen for file change events useEffect(() => { if (inputFile && inputFile.current) { inputFile.current.addEventListener('input', () => { let selectedFile = inputFile.current.files[0]; if (selectedFile !== undefined) { setQrCode(undefined); setFile(selectedFile); } }); } }, [inputFile]) // Whether Safari is used or not let [isSafari, setIsSafari] = useState(true); // Check if Safari is used useEffect(() => { const navigator = window.navigator; setIsSafari( navigator.vendor && navigator.vendor.indexOf('Apple') > -1 && navigator.userAgent && navigator.userAgent.indexOf('CriOS') == -1 && navigator.userAgent.indexOf('FxiOS') == -1 ) }, [isSafari]); // Whether Safari is used or not let [isShareDialogAvailable, setIsShareDialogAvailable] = useState(false); // Check if share dialog is available useEffect(() => { setIsShareDialogAvailable(window.navigator && window.navigator.share !== undefined); }, [isShareDialogAvailable]); // Open share dialog async function showShareDialog() { const shareData = { title: document.title, text: t('common:title') + ' – ' + t('common:subtitle'), url: window.location.protocol + "//" + window.location.host, }; try { await window.navigator.share(shareData); } catch(error) { console.log(error); } } // Show file Dialog async function showFileDialog() { inputFile.current.click(); } // Hide camera view async function hideCameraView() { if (globalControls !== undefined) { globalControls.stop(); } setIsCameraOpen(false); } // Show camera view async function showCameraView() { // Create new QR Code Reader const codeReader = new BrowserQRCodeReader(); // Needs to be called before any camera can be accessed let deviceList: MediaDeviceInfo[]; try { deviceList = await BrowserQRCodeReader.listVideoInputDevices(); } catch (e) { setErrorMessage('noCameraAccess'); return; } // Check if camera device is present if (deviceList.length == 0) { setErrorMessage("noCameraFound"); return; } // Get preview Element to show camera stream const previewElem: HTMLVideoElement = document.querySelector('#cameraPreview'); // Set Global controls setGlobalControls( // Start decoding from video device await codeReader.decodeFromVideoDevice(undefined, previewElem, (result, _error, controls) => { if (result !== undefined) { setQrCode(result); setFile(undefined); controls.stop(); // Reset setGlobalControls(undefined); setIsCameraOpen(false); } } ) ); setIsCameraOpen(true); } // Add Pass to wallet async function addToWallet(event: FormEvent) { event.preventDefault(); setLoading(true); if (navigator.userAgent.match('CriOS')) { setErrorMessage('safariSupportOnly'); setLoading(false); return; } if (!file && !qrCode) { setErrorMessage('noFileOrQrCode') setLoading(false); return; } const color = selectedColor; let payloadBody: PayloadBody; try { if (file) { payloadBody = await getPayloadBodyFromFile(file, color); } else { payloadBody = await getPayloadBodyFromQR(qrCode, color); } let pass = await PassData.generatePass(payloadBody); const passBlob = new Blob([pass], {type: "application/vnd.apple.pkpass"}); saveAs(passBlob, 'covid.pkpass'); setLoading(false); var scrollingElement = (document.scrollingElement || document.body); scrollingElement.scrollTop = scrollingElement.scrollHeight; } catch (e) { setErrorMessage(e.message); setLoading(false); } } return (
{ !isSafari && {}}/> }

{t('index:selectCertificateDescription')}

}/>

{t('index:pickColorDescription')}

}/>

{t('index:dataPrivacyDescription')} {t('index:privacyPolicy')} .

}/> { errorMessage && setErrorMessage(undefined)}/> } { isShareDialogAvailable &&