code2024/bingo
0
1import remarkGfm from 'remark-gfm'2import remarkMath from 'remark-math'3import supersub from 'remark-supersub'4import remarkBreaks from 'remark-breaks'5import { cn } from '@/lib/utils'6import { CodeBlock } from '@/components/ui/codeblock'7import { MemoizedReactMarkdown } from '@/components/markdown'8import { LearnMore } from './learn-more'9import { ChatMessageModel } from '@/lib/bots/bing/types'10import { useEffect } from 'react'11import { TurnCounter } from './turn-counter'12 13export interface ChatMessageProps {14 message: ChatMessageModel15}16 17export function ChatMessage({ message, ...props }: ChatMessageProps) {18 useEffect(() => {19 if (document.body.scrollHeight - window.innerHeight - window.scrollY - 200 < 0) {20 window.scrollBy(0, 200)21 }22 }, [message.text])23 24 return message.text ? (25 <div26 className={cn('text-message', message.author)}27 {...props}28 >29 <div className="text-message-content">30 <MemoizedReactMarkdown31 linkTarget="_blank"32 className="prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0"33 remarkPlugins={[remarkGfm, remarkMath, supersub, remarkBreaks]}34 components={{35 img(obj) {36 try {37 const uri = new URL(obj.src!)38 const w = uri.searchParams.get('w')39 const h = uri.searchParams.get('h')40 if (w && h) {41 uri.searchParams.delete('w')42 uri.searchParams.delete('h')43 return <a style={{ float: 'left', maxWidth: '50%' }} href={uri.toString()} target="_blank" rel="noopener noreferrer"><img src={obj.src} alt={obj.alt} width={w!} height={h!}/></a>44 }45 } catch (e) {46 }47 return <img src={obj.src} alt={obj.alt} title={obj.title} />48 },49 p({ children }) {50 return <p className="mb-2">{children}</p>51 },52 code({ node, inline, className, children, ...props }) {53 if (children.length) {54 if (children[0] == '▍') {55 return (56 <span className="mt-1 animate-pulse cursor-default">▍</span>57 )58 }59 60 children[0] = (children[0] as string).replace('`▍`', '▍')61 }62 63 const match = /language-(\w+)/.exec(className || '')64 65 if (inline) {66 return (67 <code className={className} {...props}>68 {children}69 </code>70 )71 }72 73 return (74 <CodeBlock75 key={Math.random()}76 language={(match && match[1]) || ''}77 value={String(children).replace(/\n$/, '')}78 {...props}79 />80 )81 }82 }}83 >84 {message.text}85 </MemoizedReactMarkdown>86 </div>87 <div className="text-message-footer">88 {message.author === 'bot' && <LearnMore sourceAttributions={message.sourceAttributions} />}89 {message.author === 'bot' && <TurnCounter throttling={message.throttling} />}90 </div>91 </div>92 ) : null93}94 