* feat: adding create bot functionality Signed-off-by: James <james@jan.ai> * update the temperature progress bar Signed-off-by: James <james@jan.ai> * WIP baselayout * Mapping plugins with available preferences * Added loader component * WIP working another screen * Cleanup types and avoid import one by one * Prepare bottom bar * Add css variables colors to enable user select the accent * Enable change accent color * Seperate css variable * Fix conflict * Add blank state of my model empty * Restyle explore models page * Enable user config left sidebar * Restyle my models page * WIP styling chat page * Restyling chat message * Fix conflict * Adde form preferences setting plugins * Fixed form bot info * Sidebar bot chat * Showing rightbar for both setting when user created bot * Fix style bot info * Using overflow auto intead of scroll * Remove script built UI from root package * Fix missig import * Resolve error linter * fix e2e tests Signed-off-by: James <james@jan.ai> --------- Signed-off-by: James <james@jan.ai> Co-authored-by: James <james@jan.ai>
86 lines
2.1 KiB
TypeScript
86 lines
2.1 KiB
TypeScript
import React from 'react'
|
|
import { displayDate } from '@utils/datetime'
|
|
import Image from 'next/image'
|
|
|
|
import LoadingIndicator from '../LoadingIndicator'
|
|
import { Marked } from 'marked'
|
|
import { markedHighlight } from 'marked-highlight'
|
|
import hljs from 'highlight.js'
|
|
import { MessageSenderType } from '@models/ChatMessage'
|
|
|
|
type Props = {
|
|
avatarUrl: string
|
|
senderName: string
|
|
createdAt: number
|
|
senderType: MessageSenderType
|
|
text?: string
|
|
}
|
|
|
|
const marked = new Marked(
|
|
markedHighlight({
|
|
langPrefix: 'hljs',
|
|
highlight(code, lang) {
|
|
if (lang === undefined || lang === '') {
|
|
return hljs.highlightAuto(code).value
|
|
}
|
|
return hljs.highlight(code, { language: lang }).value
|
|
},
|
|
}),
|
|
{
|
|
renderer: {
|
|
code(code, lang, escaped) {
|
|
return `<pre class="hljs"><code class="language-${escape(
|
|
lang ?? ''
|
|
)}">${escaped ? code : escape(code)}</code></pre>`
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
const SimpleTextMessage: React.FC<Props> = ({
|
|
senderName,
|
|
createdAt,
|
|
senderType,
|
|
avatarUrl = '',
|
|
text = '',
|
|
}) => {
|
|
const backgroundColor =
|
|
senderType === MessageSenderType.User ? '' : 'bg-gray-100'
|
|
|
|
const parsedText = marked.parse(text)
|
|
|
|
return (
|
|
<div
|
|
className={`border-border/50 flex items-start gap-x-4 gap-y-2 border-b px-4 py-5 last:border-none`}
|
|
>
|
|
<Image
|
|
className="rounded-full"
|
|
src={avatarUrl}
|
|
width={32}
|
|
height={32}
|
|
alt=""
|
|
/>
|
|
<div className="flex w-full flex-col gap-1">
|
|
<div className="flex items-baseline justify-start gap-1">
|
|
<div className="text-sm font-extrabold leading-[15.2px] ">
|
|
{senderName}
|
|
</div>
|
|
<div className="text-xs font-medium leading-[13.2px]">
|
|
{displayDate(createdAt)}
|
|
</div>
|
|
</div>
|
|
{text === '' ? (
|
|
<LoadingIndicator />
|
|
) : (
|
|
<span
|
|
className="text-muted-foreground text-xs font-normal leading-loose"
|
|
dangerouslySetInnerHTML={{ __html: parsedText }}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default React.memo(SimpleTextMessage)
|