2022-01-05 17:59:59 +00:00
|
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
import type { ReactElement } from 'react';
|
2022-01-14 16:45:05 +00:00
|
|
|
import React, { useMemo, useRef } from 'react';
|
2022-01-05 17:59:59 +00:00
|
|
|
import qrcode from 'qrcode-generator';
|
2022-01-10 19:32:32 +00:00
|
|
|
import { getEnvironment, Environment } from '../environment';
|
2022-01-05 17:59:59 +00:00
|
|
|
|
|
|
|
const AUTODETECT_TYPE_NUMBER = 0;
|
2022-01-06 00:08:28 +00:00
|
|
|
const ERROR_CORRECTION_LEVEL = 'L';
|
2022-01-05 17:59:59 +00:00
|
|
|
|
|
|
|
type PropsType = Readonly<{
|
2022-01-14 16:45:05 +00:00
|
|
|
alt: string;
|
2022-01-05 17:59:59 +00:00
|
|
|
className?: string;
|
2023-07-13 19:06:42 +00:00
|
|
|
data: string | Uint8Array;
|
2022-01-05 17:59:59 +00:00
|
|
|
}>;
|
|
|
|
|
|
|
|
export function QrCode(props: PropsType): ReactElement {
|
2022-01-14 16:45:05 +00:00
|
|
|
const { alt, className, data } = props;
|
2022-01-05 17:59:59 +00:00
|
|
|
|
2022-01-14 16:45:05 +00:00
|
|
|
const elRef = useRef<null | HTMLImageElement>(null);
|
2022-01-05 17:59:59 +00:00
|
|
|
|
2022-01-14 16:45:05 +00:00
|
|
|
const src = useMemo(() => {
|
|
|
|
const qrCode = qrcode(AUTODETECT_TYPE_NUMBER, ERROR_CORRECTION_LEVEL);
|
|
|
|
qrCode.addData(data);
|
|
|
|
qrCode.make();
|
2022-01-05 17:59:59 +00:00
|
|
|
|
2022-01-14 16:45:05 +00:00
|
|
|
const svgData = qrCode.createSvgTag({ cellSize: 1, margin: 0 });
|
|
|
|
return `data:image/svg+xml;utf8,${svgData}`;
|
|
|
|
}, [data]);
|
2022-01-05 17:59:59 +00:00
|
|
|
|
2022-01-10 19:32:32 +00:00
|
|
|
// Add a development-only feature to copy a QR code to the clipboard by double-clicking.
|
|
|
|
// This can be used to quickly inspect the code, or to link this Desktop with an iOS
|
|
|
|
// simulator primary, which has a debug-only option to paste the linking URL instead of
|
|
|
|
// scanning it. (By the time you read this comment Android may have a similar feature.)
|
|
|
|
const onDoubleClick = () => {
|
|
|
|
if (getEnvironment() === Environment.Production) {
|
|
|
|
return;
|
|
|
|
}
|
2023-07-13 19:06:42 +00:00
|
|
|
if (data instanceof Uint8Array) {
|
|
|
|
return;
|
|
|
|
}
|
2022-01-10 19:32:32 +00:00
|
|
|
|
2022-12-21 18:41:48 +00:00
|
|
|
void navigator.clipboard.writeText(data);
|
2022-01-10 19:32:32 +00:00
|
|
|
|
2022-01-14 16:45:05 +00:00
|
|
|
const el = elRef.current;
|
|
|
|
if (!el) {
|
2022-01-10 19:32:32 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-01-14 16:45:05 +00:00
|
|
|
el.style.filter = 'brightness(50%)';
|
2022-01-10 19:32:32 +00:00
|
|
|
window.setTimeout(() => {
|
2022-01-14 16:45:05 +00:00
|
|
|
el.style.filter = '';
|
2022-01-10 19:32:32 +00:00
|
|
|
}, 150);
|
|
|
|
};
|
|
|
|
|
2022-01-05 17:59:59 +00:00
|
|
|
return (
|
2022-01-14 16:45:05 +00:00
|
|
|
<img
|
|
|
|
alt={alt}
|
2022-01-05 17:59:59 +00:00
|
|
|
className={className}
|
2022-01-10 19:32:32 +00:00
|
|
|
onDoubleClick={onDoubleClick}
|
2022-01-14 16:45:05 +00:00
|
|
|
ref={elRef}
|
|
|
|
src={src}
|
2022-01-05 17:59:59 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|