Merge pull request #4394 from matrix-org/t3chguy/qrcode

wrap node-qrcode in a React FC and use it for ShareDialog
This commit is contained in:
Michael Telatynski 2020-05-14 17:31:26 +01:00 committed by GitHub
commit 239197a3cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 47 deletions

View file

@ -87,7 +87,6 @@
"project-name-generator": "^2.1.7",
"prop-types": "^15.5.8",
"qrcode": "^1.4.4",
"qrcode-react": "^0.1.16",
"qs": "^6.6.0",
"react": "^16.9.0",
"react-beautiful-dnd": "^4.0.1",
@ -119,6 +118,7 @@
"@peculiar/webcrypto": "^1.0.22",
"@types/classnames": "^2.2.10",
"@types/modernizr": "^3.5.3",
"@types/qrcode": "^1.3.4",
"@types/react": "16.9",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",

View file

@ -108,6 +108,7 @@
@import "./views/elements/_ManageIntegsButton.scss";
@import "./views/elements/_PowerSelector.scss";
@import "./views/elements/_ProgressBar.scss";
@import "./views/elements/_QRCode.scss";
@import "./views/elements/_ReplyThread.scss";
@import "./views/elements/_ResizeHandle.scss";
@import "./views/elements/_RichText.scss";

View file

@ -64,9 +64,6 @@ limitations under the License.
.mx_ShareDialog_qrcode_container {
float: left;
background-color: #ffffff;
padding: 5px; // makes qr code more readable in dark theme
border-radius: 5px;
height: 256px;
width: 256px;
margin-right: 64px;

View file

@ -0,0 +1,21 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_QRCode {
img {
border-radius: 8px;
}
}

View file

@ -24,7 +24,7 @@ import {RoomMember} from "matrix-js-sdk/src/models/room-member";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import QRCode from 'qrcode-react';
import QRCode from "../elements/QRCode";
import {RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink} from "../../../utils/permalinks/Permalinks";
import * as ContextMenu from "../../structures/ContextMenu";
import {toRightOf} from "../../structures/ContextMenu";
@ -221,7 +221,7 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
<div className="mx_ShareDialog_split">
<div className="mx_ShareDialog_qrcode_container">
<QRCode value={matrixToUrl} size={256} logoWidth={48} logo={require("../../../../res/img/matrix-m.svg")} />
<QRCode data={matrixToUrl} width={256} />
</div>
<div className="mx_ShareDialog_social_container">
{ socials.map((social) => (

View file

@ -0,0 +1,51 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import * as React from "react";
import {toDataURL, QRCodeSegment, QRCodeToDataURLOptions} from "qrcode";
import classNames from "classnames";
import {_t} from "../../../languageHandler";
import Spinner from "./Spinner";
interface IProps extends QRCodeToDataURLOptions {
data: string | QRCodeSegment[];
className?: string;
}
const defaultOptions: QRCodeToDataURLOptions = {
errorCorrectionLevel: 'L', // we want it as trivial-looking as possible
};
const QRCode: React.FC<IProps> = ({data, className, ...options}) => {
const [dataUri, setUri] = React.useState<string>(null);
React.useEffect(() => {
let cancelled = false;
toDataURL(data, {...defaultOptions, ...options}).then(uri => {
if (cancelled) return;
setUri(uri);
});
return () => {
cancelled = true;
};
}, [JSON.stringify(data), options]);
return <div className={classNames("mx_QRCode", className)}>
{ dataUri ? <img src={dataUri} className="mx_VerificationQRCode" alt={_t("QR Code")} /> : <Spinner /> }
</div>;
};
export default QRCode;

View file

@ -17,8 +17,7 @@ limitations under the License.
import React from "react";
import PropTypes from "prop-types";
import {replaceableComponent} from "../../../../utils/replaceableComponent";
import Spinner from "../Spinner";
import * as QRCode from "qrcode";
import QRCode from "../QRCode";
@replaceableComponent("views.elements.crypto.VerificationQRCode")
export default class VerificationQRCode extends React.PureComponent {
@ -26,33 +25,12 @@ export default class VerificationQRCode extends React.PureComponent {
qrCodeData: PropTypes.object.isRequired,
};
constructor(props) {
super(props);
this.state = {
dataUri: null,
};
this.generateQrCode();
}
componentDidUpdate(prevProps): void {
if (JSON.stringify(this.props) === JSON.stringify(prevProps)) return; // No prop change
this.generateQRCode();
}
async generateQrCode() {
// Now actually assemble the QR code's data URI
const uri = await QRCode.toDataURL([{data: this.props.qrCodeData.buffer, mode: 'byte'}], {
errorCorrectionLevel: 'L', // we want it as trivial-looking as possible
});
this.setState({dataUri: uri});
}
render() {
if (!this.state.dataUri) {
return <div className='mx_VerificationQRCode'><Spinner /></div>;
}
return <img src={this.state.dataUri} className='mx_VerificationQRCode' />;
return (
<QRCode
data={[{data: this.props.qrCodeData.buffer, mode: 'byte'}]}
className="mx_VerificationQRCode"
width={196} />
);
}
}

View file

@ -1494,6 +1494,7 @@
"%(oneUser)smade no changes %(count)s times|one": "%(oneUser)smade no changes",
"Power level": "Power level",
"Custom level": "Custom level",
"QR Code": "QR Code",
"Unable to load event that was replied to, it either does not exist or you do not have permission to view it.": "Unable to load event that was replied to, it either does not exist or you do not have permission to view it.",
"<a>In reply to</a> <pill>": "<a>In reply to</a> <pill>",
"Room alias": "Room alias",

View file

@ -1272,6 +1272,13 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/qrcode@^1.3.4":
version "1.3.4"
resolved "https://registry.yarnpkg.com/@types/qrcode/-/qrcode-1.3.4.tgz#984d97bb72caa558d470158701081ccb712f616b"
integrity sha512-aILE5yvKaqQXlY0YPMEYwK/KwdD43fwQTyagj0ffBBTQj8h//085Zp8LUrOnZ9FT69x64f5UgDo0EueY4BPAdg==
dependencies:
"@types/node" "*"
"@types/react@16.9":
version "16.9.32"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.32.tgz#f6368625b224604148d1ddf5920e4fefbd98d383"
@ -6851,18 +6858,6 @@ pvutils@latest:
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
qr.js@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
qrcode-react@^0.1.16:
version "0.1.16"
resolved "https://registry.yarnpkg.com/qrcode-react/-/qrcode-react-0.1.16.tgz#d064999d510ffc3e55a9ca3ffcf6c203c69f1517"
integrity sha512-FK+QCfFqCQMSxUE1byzglERJQkwKqXYvYMCS+/Ad2zACJOfoHkHHtRqsQQPji7lfb1y1qCXLvL+3eP1hAfg8Ng==
dependencies:
qr.js "0.0.0"
qrcode@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83"