diff --git a/package.json b/package.json index 92d228a812..dda4a5a897 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/res/css/_components.scss b/res/css/_components.scss index 428a28ac3a..c05e2cabc6 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -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"; diff --git a/res/css/views/dialogs/_ShareDialog.scss b/res/css/views/dialogs/_ShareDialog.scss index 9a2f67dea3..e08469ec6d 100644 --- a/res/css/views/dialogs/_ShareDialog.scss +++ b/res/css/views/dialogs/_ShareDialog.scss @@ -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; diff --git a/res/css/views/elements/_QRCode.scss b/res/css/views/elements/_QRCode.scss new file mode 100644 index 0000000000..96d9114b54 --- /dev/null +++ b/res/css/views/elements/_QRCode.scss @@ -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; + } +} diff --git a/src/components/views/dialogs/ShareDialog.tsx b/src/components/views/dialogs/ShareDialog.tsx index 375cb65b5f..271f754fd2 100644 --- a/src/components/views/dialogs/ShareDialog.tsx +++ b/src/components/views/dialogs/ShareDialog.tsx @@ -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 {
- +
{ socials.map((social) => ( diff --git a/src/components/views/elements/QRCode.tsx b/src/components/views/elements/QRCode.tsx new file mode 100644 index 0000000000..f70ab48fa3 --- /dev/null +++ b/src/components/views/elements/QRCode.tsx @@ -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 = ({data, className, ...options}) => { + const [dataUri, setUri] = React.useState(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
+ { dataUri ? {_t("QR : } +
; +}; + +export default QRCode; diff --git a/src/components/views/elements/crypto/VerificationQRCode.js b/src/components/views/elements/crypto/VerificationQRCode.js index 08cd0c772e..3bbfb004c6 100644 --- a/src/components/views/elements/crypto/VerificationQRCode.js +++ b/src/components/views/elements/crypto/VerificationQRCode.js @@ -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
; - } - - return ; + return ( + + ); } } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 82b2a752ea..088c2c4940 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -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.", "In reply to ": "In reply to ", "Room alias": "Room alias", diff --git a/yarn.lock b/yarn.lock index 520e976b17..b0d3816dc4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"