feat: [closes #12] add qr code support (#63)

* Add initial QRCode implementation
This commit is contained in:
krayste 2022-11-06 12:41:24 +11:00 committed by GitHub
parent 237fc0e6df
commit d4e565815c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 155 additions and 23 deletions

43
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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 (
<Dialog
open={isOpen}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
Room QR Code
<IconButton
aria-label="close"
onClick={handleClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
}}
>
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent>
<QRCode
value={url}
size={QR_CODE_SIZE}
logoImage={'/logo512.png'}
logoWidth={QR_CODE_SIZE}
logoHeight={QR_CODE_SIZE}
logoOpacity={QR_IMAGE_OPACITY}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} autoFocus>
Dismiss
</Button>
</DialogActions>
</Dialog>
)
}

View File

@ -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<AlertColor>('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 (
<ShellContext.Provider value={shellContextValue}>
<ThemeProvider theme={theme}>
@ -186,6 +194,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
numberOfPeers={numberOfPeers}
title={title}
onPeerListClick={handlePeerListClick}
setIsQRCodeDialogOpen={setIsQRCodeDialogOpen}
/>
<Drawer
isDrawerOpen={isDrawerOpen}
@ -210,6 +219,10 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
peerList={peerList}
audioState={audioState}
/>
<QRCodeDialog
isOpen={isQRCodeDialogOpen}
handleClose={handleQRCodeDialogClose}
/>
</Box>
</ThemeProvider>
</ShellContext.Provider>

View File

@ -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 (
<AppBar
position="fixed"
@ -95,30 +99,40 @@ export const ShellAppBar = ({
>
{title}
</Typography>
<Tooltip title="Copy current URL">
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="Copy current URL"
sx={{ ml: 'auto' }}
onClick={onLinkButtonClick}
>
<LinkIcon />
</IconButton>
</Tooltip>
{doShowPeers ? (
<Tooltip title="Click to show peer list">
<IconButton
size="large"
edge="end"
color="inherit"
aria-label="Peer list"
onClick={onPeerListClick}
>
<StepIcon icon={numberOfPeers} />
</IconButton>
</Tooltip>
<>
<Tooltip title="Show QR Code">
<IconButton
size="large"
color="inherit"
aria-label="Show QR Code"
onClick={handleQRCodeClick}
>
<QrCode2Icon />
</IconButton>
</Tooltip>
<Tooltip title="Copy current URL">
<IconButton
size="large"
color="inherit"
aria-label="Copy current URL"
onClick={onLinkButtonClick}
>
<LinkIcon />
</IconButton>
</Tooltip>
<Tooltip title="Click to show peer list">
<IconButton
size="large"
edge="end"
color="inherit"
aria-label="Peer list"
onClick={onPeerListClick}
>
<StepIcon icon={numberOfPeers} />
</IconButton>
</Tooltip>
</>
) : null}
</Toolbar>
</AppBar>