import styled from '@emotion/styled'; import { Button, CopyButton, Loader, Textarea } from '@mantine/core'; import { Message } from "../types"; import { share } from '../utils'; import { ElevenLabsReaderButton } from '../tts/elevenlabs'; import { Markdown } from './markdown'; import { useAppContext } from '../context'; import { useCallback, useMemo, useState } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; // hide for everyone but screen readers const SROnly = styled.span` position: fixed; left: -9999px; top: -9999px; `; const Container = styled.div` &.by-user { background: #22232b; } &.by-assistant { background: #292933; } &.by-assistant + &.by-assistant, &.by-user + &.by-user { border-top: 0.2rem dotted rgba(0, 0, 0, 0.1); } &.by-assistant { border-bottom: 0.2rem solid rgba(0, 0, 0, 0.1); } position: relative; padding: 1.618rem; @media (max-width: 40em) { padding: 1rem; } .inner { margin: auto; } .content { font-family: "Open Sans", sans-serif; margin-top: 0rem; max-width: 100%; * { color: white; } p, ol, ul, li, h1, h2, h3, h4, h5, h6, img, blockquote, &>pre { max-width: 50rem; margin-left: auto; margin-right: auto; } img { display: block; max-width: 50rem; @media (max-width: 50rem) { max-width: 100%; } } ol { counter-reset: list-item; li { counter-increment: list-item; } } em, i { font-style: italic; } code { &, * { font-family: "Fira Code", monospace !important; } vertical-align: bottom; } /* Tables */ table { margin-top: 1.618rem; border-spacing: 0px; border-collapse: collapse; border: thin solid rgba(255, 255, 255, 0.1); width: 100%; max-width: 55rem; margin-left: auto; margin-right: auto; } td + td, th + th { border-left: thin solid rgba(255, 255, 255, 0.1); } tr { border-top: thin solid rgba(255, 255, 255, 0.1); } table td, table th { padding: 0.618rem 1rem; } th { font-weight: 600; background: rgba(255, 255, 255, 0.1); } } .metadata { display: flex; flex-wrap: wrap; align-items: center; font-family: "Work Sans", sans-serif; font-size: 0.8rem; font-weight: 400; opacity: 0.6; max-width: 50rem; margin-bottom: 0.0rem; margin-right: -0.5rem; margin-left: auto; margin-right: auto; span + span { margin-left: 1em; } .fa { font-size: 85%; } .fa + span { margin-left: 0.2em; } .mantine-Button-root { color: #ccc; font-size: 0.8rem; font-weight: 400; .mantine-Button-label { display: flex; align-items: center; } } } .fa { margin-right: 0.5em; font-size: 85%; } .buttons { text-align: right; } strong { font-weight: bold; } `; const EndOfChatMarker = styled.div` position: absolute; bottom: calc(-1.618rem - 0.5rem); left: 50%; width: 0.5rem; height: 0.5rem; margin-left: -0.25rem; border-radius: 50%; background: rgba(255, 255, 255, 0.1); `; const Editor = styled.div` max-width: 50rem; margin-left: auto; margin-right: auto; margin-top: 0.5rem; .mantine-Button-root { margin-top: 1rem; } `; function InlineLoader() { return ( ); } export default function MessageComponent(props: { message: Message, last: boolean, share?: boolean }) { const context = useAppContext(); const [editing, setEditing] = useState(false); const [content, setContent] = useState(''); const intl = useIntl(); const getRoleName = useCallback((role: string, share = false) => { switch (role) { case 'user': if (share) { return intl.formatMessage({ id: 'role-user-formal', defaultMessage: 'User' }); } else { return intl.formatMessage({ id: 'role-user', defaultMessage: 'You' }); } break; case 'assistant': return intl.formatMessage({ id: 'role-chatgpt', defaultMessage: 'ChatGPT' }); case 'system': return intl.formatMessage({ id: 'role-system', defaultMessage: 'System' }); default: return role; } }, [intl]); const elem = useMemo(() => { if (props.message.role === 'system') { return null; } return (
{getRoleName(props.message.role, props.share)}: {props.message.role === 'assistant' && props.last && !props.message.done && } {props.message.done && }
{({ copy, copied }) => ( )} {typeof navigator.share !== 'undefined' && ( )} {!context.isShare && props.message.role === 'user' && ( )} {!context.isShare && props.message.role === 'assistant' && ( )}
{!editing && } {editing && (