From d4e565815cfc1af70639f317f6f3f4915ae2915c Mon Sep 17 00:00:00 2001 From: krayste Date: Sun, 6 Nov 2022 12:41:24 +1100 Subject: [PATCH] feat: [closes #12] add qr code support (#63) * Add initial QRCode implementation --- package-lock.json | 43 +++++++++++++++++++ package.json | 1 + src/components/Shell/QRCodeDialog.tsx | 61 +++++++++++++++++++++++++++ src/components/Shell/Shell.tsx | 13 ++++++ src/components/Shell/ShellAppBar.tsx | 60 ++++++++++++++++---------- 5 files changed, 155 insertions(+), 23 deletions(-) create mode 100644 src/components/Shell/QRCodeDialog.tsx diff --git a/package-lock.json b/package-lock.json index 4bb6260..37903c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^8.0.3", + "react-qrcode-logo": "^2.8.0", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", "react-syntax-highlighter": "^15.5.0", @@ -16401,6 +16402,11 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -20353,6 +20359,11 @@ "teleport": ">=0.2.0" } }, + "node_modules/qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, "node_modules/qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -20685,6 +20696,19 @@ "p-defer": "^3.0.0" } }, + "node_modules/react-qrcode-logo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/react-qrcode-logo/-/react-qrcode-logo-2.8.0.tgz", + "integrity": "sha512-dbEgjsg6C4tK6+oGmCRDlJ7urQAWqybaGBLJtp8Z6ZYvVUP302HBXk/F7VRk54yWTwzlHwig3VK6HMKCha2YFw==", + "dependencies": { + "lodash.isequal": "^4.5.0", + "qrcode-generator": "^1.4.1" + }, + "peerDependencies": { + "react": ">=16.4.1", + "react-dom": ">=16.4.1" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -36682,6 +36706,11 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -39300,6 +39329,11 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" }, + "qrcode-generator": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-1.4.4.tgz", + "integrity": "sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==" + }, "qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -39547,6 +39581,15 @@ "p-defer": "^3.0.0" } }, + "react-qrcode-logo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/react-qrcode-logo/-/react-qrcode-logo-2.8.0.tgz", + "integrity": "sha512-dbEgjsg6C4tK6+oGmCRDlJ7urQAWqybaGBLJtp8Z6ZYvVUP302HBXk/F7VRk54yWTwzlHwig3VK6HMKCha2YFw==", + "requires": { + "lodash.isequal": "^4.5.0", + "qrcode-generator": "^1.4.1" + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", diff --git a/package.json b/package.json index a8a0fce..956d447 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^8.0.3", + "react-qrcode-logo": "^2.8.0", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", "react-syntax-highlighter": "^15.5.0", diff --git a/src/components/Shell/QRCodeDialog.tsx b/src/components/Shell/QRCodeDialog.tsx new file mode 100644 index 0000000..2fcb3c8 --- /dev/null +++ b/src/components/Shell/QRCodeDialog.tsx @@ -0,0 +1,61 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, +} from '@mui/material' +import React from 'react' +import CloseIcon from '@mui/icons-material/Close' +import { QRCode } from 'react-qrcode-logo' + +const QR_CODE_SIZE = 256 +const QR_IMAGE_OPACITY = 0.3 + +export interface QRCodeDialogProps { + isOpen: boolean + handleClose: () => void +} + +export function QRCodeDialog({ isOpen, handleClose }: QRCodeDialogProps) { + const url = window.location.href + return ( + + + Room QR Code + + + + + + + + + + + + ) +} diff --git a/src/components/Shell/Shell.tsx b/src/components/Shell/Shell.tsx index 6d667a0..be2a3a7 100644 --- a/src/components/Shell/Shell.tsx +++ b/src/components/Shell/Shell.tsx @@ -24,6 +24,7 @@ import { ShellAppBar } from './ShellAppBar' import { NotificationArea } from './NotificationArea' import { RouteContent } from './RouteContent' import { PeerList } from './PeerList' +import { QRCodeDialog } from './QRCodeDialog' export interface ShellProps extends PropsWithChildren { userPeerId: string @@ -34,6 +35,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => { const settingsContext = useContext(SettingsContext) const [isAlertShowing, setIsAlertShowing] = useState(false) const [isDrawerOpen, setIsDrawerOpen] = useState(false) + const [isQRCodeDialogOpen, setIsQRCodeDialogOpen] = useState(false) const [doShowPeers, setDoShowPeers] = useState(false) const [alertSeverity, setAlertSeverity] = useState('info') const [title, setTitle] = useState('') @@ -61,6 +63,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => { setTitle, showAlert, isPeerListOpen, + setIsQRCodeDialogOpen, setIsPeerListOpen, peerList, setPeerList, @@ -69,6 +72,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => { }), [ isPeerListOpen, + setIsQRCodeDialogOpen, numberOfPeers, peerList, tabHasFocus, @@ -159,6 +163,10 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => { setIsDrawerOpen(false) } + const handleQRCodeDialogClose = () => { + setIsQRCodeDialogOpen(false) + } + return ( @@ -186,6 +194,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => { numberOfPeers={numberOfPeers} title={title} onPeerListClick={handlePeerListClick} + setIsQRCodeDialogOpen={setIsQRCodeDialogOpen} /> { peerList={peerList} audioState={audioState} /> + diff --git a/src/components/Shell/ShellAppBar.tsx b/src/components/Shell/ShellAppBar.tsx index 7c5ff10..cacd9b4 100644 --- a/src/components/Shell/ShellAppBar.tsx +++ b/src/components/Shell/ShellAppBar.tsx @@ -7,6 +7,7 @@ import Tooltip from '@mui/material/Tooltip' import IconButton from '@mui/material/IconButton' import MenuIcon from '@mui/icons-material/Menu' import LinkIcon from '@mui/icons-material/Link' +import QrCode2Icon from '@mui/icons-material/QrCode2' import { drawerWidth } from './Drawer' import { peerListWidth } from './PeerList' @@ -51,6 +52,7 @@ interface ShellAppBarProps { numberOfPeers: number title: string onPeerListClick: () => void + setIsQRCodeDialogOpen: (isOpen: boolean) => void } export const ShellAppBar = ({ @@ -59,10 +61,12 @@ export const ShellAppBar = ({ onLinkButtonClick, isDrawerOpen, isPeerListOpen, + setIsQRCodeDialogOpen, numberOfPeers, title, onPeerListClick, }: ShellAppBarProps) => { + const handleQRCodeClick = () => setIsQRCodeDialogOpen(true) return ( {title} - - - - - {doShowPeers ? ( - - - - - + <> + + + + + + + + + + + + + + + + ) : null}