From eba8d8d4b8db665520e693e40f79b58b8d2d1f3a Mon Sep 17 00:00:00 2001
From: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com>
Date: Fri, 14 Jan 2022 10:45:05 -0600
Subject: [PATCH] Render QR code with SVG, not canvas
---
ts/components/QrCode.stories.tsx | 3 +-
ts/components/QrCode.tsx | 62 ++++++-------------
.../InstallScreenQrCodeNotScannedStep.tsx | 5 +-
ts/util/lint/exceptions.json | 4 +-
4 files changed, 24 insertions(+), 50 deletions(-)
diff --git a/ts/components/QrCode.stories.tsx b/ts/components/QrCode.stories.tsx
index 118c02bb91..88ce6f458e 100644
--- a/ts/components/QrCode.stories.tsx
+++ b/ts/components/QrCode.stories.tsx
@@ -10,8 +10,7 @@ const story = storiesOf('Components/QrCode', module);
story.add('Default', () => (
));
diff --git a/ts/components/QrCode.tsx b/ts/components/QrCode.tsx
index 173e659988..aeb7304eb0 100644
--- a/ts/components/QrCode.tsx
+++ b/ts/components/QrCode.tsx
@@ -2,53 +2,33 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { ReactElement } from 'react';
-import React, { useEffect, useMemo, useRef } from 'react';
+import React, { useMemo, useRef } from 'react';
import qrcode from 'qrcode-generator';
import { getEnvironment, Environment } from '../environment';
-import { strictAssert } from '../util/assert';
-import { useDevicePixelRatio } from '../hooks/useDevicePixelRatio';
const AUTODETECT_TYPE_NUMBER = 0;
const ERROR_CORRECTION_LEVEL = 'L';
type PropsType = Readonly<{
- 'aria-label': string;
+ alt: string;
className?: string;
data: string;
- size: number;
}>;
export function QrCode(props: PropsType): ReactElement {
- // I don't think it's possible to destructure this.
- // eslint-disable-next-line react/destructuring-assignment
- const ariaLabel = props['aria-label'];
- const { className, data, size } = props;
+ const { alt, className, data } = props;
- const qrCode = useMemo(() => {
- const result = qrcode(AUTODETECT_TYPE_NUMBER, ERROR_CORRECTION_LEVEL);
- result.addData(data);
- result.make();
- return result;
+ const elRef = useRef(null);
+
+ const src = useMemo(() => {
+ const qrCode = qrcode(AUTODETECT_TYPE_NUMBER, ERROR_CORRECTION_LEVEL);
+ qrCode.addData(data);
+ qrCode.make();
+
+ const svgData = qrCode.createSvgTag({ cellSize: 1, margin: 0 });
+ return `data:image/svg+xml;utf8,${svgData}`;
}, [data]);
- const canvasRef = useRef(null);
- const dpi = useDevicePixelRatio();
- const canvasSize = size * dpi;
-
- useEffect(() => {
- const canvas = canvasRef.current;
- if (!canvas) {
- return;
- }
-
- const context = canvas.getContext('2d');
- strictAssert(context, 'Expected a canvas context');
-
- const cellSize = canvasSize / qrCode.getModuleCount();
- context.clearRect(0, 0, canvasSize, canvasSize);
- qrCode.renderTo2dContext(context, cellSize);
- }, [canvasSize, qrCode]);
-
// 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
@@ -60,25 +40,23 @@ export function QrCode(props: PropsType): ReactElement {
navigator.clipboard.writeText(data);
- const canvas = canvasRef.current;
- if (!canvas) {
+ const el = elRef.current;
+ if (!el) {
return;
}
- canvas.style.filter = 'brightness(50%)';
+ el.style.filter = 'brightness(50%)';
window.setTimeout(() => {
- canvas.style.filter = '';
+ el.style.filter = '';
}, 150);
};
return (
-
);
}
diff --git a/ts/components/installScreen/InstallScreenQrCodeNotScannedStep.tsx b/ts/components/installScreen/InstallScreenQrCodeNotScannedStep.tsx
index 84ddd9a939..360a19e97b 100644
--- a/ts/components/installScreen/InstallScreenQrCodeNotScannedStep.tsx
+++ b/ts/components/installScreen/InstallScreenQrCodeNotScannedStep.tsx
@@ -25,8 +25,6 @@ type PropsType = {
provisioningUrl: Loadable;
};
-// This should match the size in the CSS.
-const QR_CODE_SIZE = 256;
const QR_CODE_FAILED_LINK =
'https://support.signal.org/hc/articles/360007320451#desktop_multiple_device';
@@ -113,10 +111,9 @@ function InstallScreenQrCode(
case LoadingState.Loaded:
contents = (
);
break;
diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json
index b5bcd92745..c1a1f5cf76 100644
--- a/ts/util/lint/exceptions.json
+++ b/ts/util/lint/exceptions.json
@@ -7527,10 +7527,10 @@
{
"rule": "React-useRef",
"path": "ts/components/QrCode.tsx",
- "line": " const canvasRef = useRef(null);",
+ "line": " const elRef = useRef(null);",
"reasonCategory": "usageTrusted",
"updated": "2022-01-04T21:43:17.517Z",
- "reasonDetail": "Used to draw on the canvas."
+ "reasonDetail": "Used to change the style in non-production builds."
},
{
"rule": "React-createRef",