101 lines
2.8 KiB
TypeScript
Raw Normal View History

2022-08-27 21:25:38 -05:00
import { HTMLAttributes } from 'react'
import Box from '@mui/material/Box'
import Typography, { TypographyProps } from '@mui/material/Typography'
import Link, { LinkProps } from '@mui/material/Link'
import Markdown from 'react-markdown'
2022-08-28 18:19:14 -05:00
import { CodeProps } from 'react-markdown/lib/ast-to-react'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { materialDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
2022-08-23 21:46:07 -05:00
import { Message as IMessage, isMessageReceived } from 'models/chat'
export interface MessageProps {
message: IMessage
userId: string
}
2022-08-27 21:25:38 -05:00
const typographyFactory =
(overrides: TypographyProps) => (args: HTMLAttributes<HTMLElement>) => {
return <Typography {...args} {...overrides} />
}
const linkFactory =
(overrides: LinkProps) => (args: HTMLAttributes<HTMLElement>) => {
return <Link {...args} {...overrides} />
}
const componentMap = {
h1: typographyFactory({ variant: 'h1' }),
h2: typographyFactory({ variant: 'h2' }),
h3: typographyFactory({ variant: 'h3' }),
h4: typographyFactory({ variant: 'h4' }),
h5: typographyFactory({ variant: 'h5' }),
h6: typographyFactory({ variant: 'h6' }),
p: typographyFactory({ variant: 'body1' }),
a: linkFactory({
variant: 'body1',
underline: 'always',
color: 'primary.light',
}),
2022-08-28 18:19:14 -05:00
// 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}
/>
) : (
<code className={className} {...props}>
{children}
</code>
)
},
2022-08-27 21:25:38 -05:00
}
2022-08-23 21:46:07 -05:00
export const Message = ({ message, userId }: MessageProps) => {
let backgroundColor: string
if (message.authorId === userId) {
backgroundColor = isMessageReceived(message)
? 'primary.dark'
: 'primary.main'
} else {
backgroundColor = 'grey.700'
}
return (
2022-08-27 21:38:08 -05:00
<Box className="Message">
<Typography
2022-08-28 11:45:26 -05:00
variant="caption"
2022-08-27 21:38:08 -05:00
display="block"
2022-08-28 11:45:26 -05:00
color="grey.400"
2022-08-27 21:38:08 -05:00
sx={{
textAlign: message.authorId === userId ? 'right' : 'left',
}}
>
2022-08-28 11:45:26 -05:00
{message.authorId}
2022-08-27 21:38:08 -05:00
</Typography>
2022-08-27 21:25:38 -05:00
<Box
2022-08-23 21:46:07 -05:00
sx={{
backgroundColor,
margin: 0.5,
2022-08-28 11:45:26 -05:00
padding: '0.5em 0.75em',
2022-08-23 21:46:07 -05:00
borderRadius: 6,
float: message.authorId === userId ? 'right' : 'left',
transition: 'background-color 1s',
2022-08-28 11:45:26 -05:00
wordBreak: 'break-word',
2022-08-23 21:46:07 -05:00
}}
2022-08-28 11:45:26 -05:00
maxWidth="85%"
2022-08-23 21:46:07 -05:00
>
2022-08-27 21:25:38 -05:00
<Markdown components={componentMap} linkTarget="_blank">
{message.text}
</Markdown>
</Box>
2022-08-27 21:38:08 -05:00
</Box>
2022-08-23 21:46:07 -05:00
)
}