Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): Add copy button for code #178

Merged
merged 6 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/components/CopyableBlock/CopyableBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Box, { BoxProps } from '@mui/material/Box'
import Tooltip from '@mui/material/Tooltip'
import Fab from '@mui/material/Fab'
import ContentCopy from '@mui/icons-material/ContentCopy'
import { useContext, useRef } from 'react'
import { ShellContext } from 'contexts/ShellContext'

interface CopyableBlockProps extends BoxProps {}

export const CopyableBlock = ({ children }: CopyableBlockProps) => {
const { showAlert } = useContext(ShellContext)
const boxRef = useRef<HTMLDivElement>(null)

const handleCopyClick = async () => {
const div = boxRef?.current

if (!div) return

await navigator.clipboard.writeText(div.innerText)

showAlert('Copied to clipboard', { severity: 'success' })
}

return (
<Box
ref={boxRef}
sx={{
position: 'relative',
'&:hover button': {
opacity: 0.75,
},
}}
>
{children}
<Tooltip title="Copy to clipboard">
<Fab
color="default"
size="small"
onClick={handleCopyClick}
sx={theme => ({
position: 'absolute',
top: '1em',
right: '1em',
opacity: 0,
transition: theme.transitions.create(['opacity', 'transform']),
})}
>
<ContentCopy />
</Fab>
</Tooltip>
</Box>
)
}
1 change: 1 addition & 0 deletions src/components/CopyableBlock/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './CopyableBlock'
22 changes: 13 additions & 9 deletions src/components/Message/Message.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HTMLAttributes } from 'react'
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'
import YouTube from 'react-youtube'
import Box from '@mui/material/Box'
import Tooltip from '@mui/material/Tooltip'
Expand Down Expand Up @@ -27,10 +28,10 @@ import {
isInlineMedia,
} from 'models/chat'
import { PeerNameDisplay } from 'components/PeerNameDisplay'

import { SyntaxHighlighter } from '../../components/SyntaxHighlighter'
import { CopyableBlock } from 'components/CopyableBlock/CopyableBlock'

import { InlineMedia } from './InlineMedia'

import './Message.sass'

export interface MessageProps {
Expand Down Expand Up @@ -65,14 +66,17 @@ const componentMap = {
// https://github.com/remarkjs/react-markdown#use-custom-components-syntax-highlight
code({ node, inline, className, children, style, ...props }: CodeProps) {
const match = /language-(\w+)/.exec(className || '')

return !inline && match ? (
<SyntaxHighlighter
children={String(children).replace(/\n$/, '')}
language={match[1]}
style={materialDark}
PreTag="div"
{...props}
/>
<CopyableBlock>
<SyntaxHighlighter
children={String(children).replace(/\n$/, '')}
language={match[1]}
style={materialDark}
PreTag="div"
{...props}
/>
</CopyableBlock>
) : (
<code className={className} {...props}>
{children}
Expand Down
3 changes: 0 additions & 3 deletions src/components/SyntaxHighlighter/SyntaxHighlighter.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/components/SyntaxHighlighter/index.ts

This file was deleted.

38 changes: 20 additions & 18 deletions src/pages/Home/EmbedCodeDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'
import Button from '@mui/material/Button'
import Dialog from '@mui/material/Dialog'
import { materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import DialogContentText from '@mui/material/DialogContentText'
import DialogTitle from '@mui/material/DialogTitle'

import { SyntaxHighlighter } from '../../components/SyntaxHighlighter'
import { CopyableBlock } from 'components/CopyableBlock/CopyableBlock'

interface EmbedCodeDialogProps {
showEmbedCode: boolean
Expand All @@ -29,22 +29,24 @@ export const EmbedCodeDialog = ({
<Dialog open={showEmbedCode} onClose={handleEmbedCodeWindowClose}>
<DialogTitle>Room embed code</DialogTitle>
<DialogContent>
<SyntaxHighlighter
language="html"
style={materialDark}
PreTag="div"
lineProps={{
style: {
wordBreak: 'break-all',
whiteSpace: 'pre-wrap',
},
}}
wrapLines={true}
>
{`<iframe src="${embedUrl}" allow="${iframeFeatureAllowList.join(
';'
)}" width="800" height="800" />`}
</SyntaxHighlighter>
<CopyableBlock>
<SyntaxHighlighter
language="html"
style={materialDark}
PreTag="div"
lineProps={{
style: {
wordBreak: 'break-all',
whiteSpace: 'pre-wrap',
},
}}
wrapLines={true}
>
{`<iframe src="${embedUrl}" allow="${iframeFeatureAllowList.join(
';'
)}" width="800" height="800" />`}
</SyntaxHighlighter>
</CopyableBlock>
<DialogContentText
sx={{
mb: 2,
Expand Down