Merge branch 'main' into docs/label-api-reference

This commit is contained in:
Hieu 2023-11-28 07:54:42 +09:00 committed by GitHub
commit 5b64ddbe73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 62 deletions

View File

@ -7,7 +7,10 @@ import SimpleTextMessage from '../SimpleTextMessage'
type Ref = HTMLDivElement type Ref = HTMLDivElement
const ChatItem = forwardRef<Ref, ThreadMessage>((message, ref) => ( const ChatItem = forwardRef<Ref, ThreadMessage>((message, ref) => (
<div ref={ref} className="py-4 even:bg-secondary dark:even:bg-secondary/20"> <div
ref={ref}
className="relative py-4 first:pb-14 even:bg-secondary dark:even:bg-secondary/20"
>
<SimpleTextMessage {...message} /> <SimpleTextMessage {...message} />
</div> </div>
)) ))

View File

@ -35,18 +35,19 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
} }
return ( return (
<div className="flex flex-row items-center"> <div className="flex flex-row items-center">
<div className="flex overflow-hidden rounded-md border border-border bg-background/20">
{message.status === MessageStatus.Pending && ( {message.status === MessageStatus.Pending && (
<StopCircle <div
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]" className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
size={20}
onClick={() => stopInference()} onClick={() => stopInference()}
/> >
<StopCircle size={14} />
</div>
)} )}
{message.status !== MessageStatus.Pending && {message.status !== MessageStatus.Pending &&
message.id === messages[0]?.id && ( message.id === messages[0]?.id && (
<RefreshCcw <div
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]" className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
size={20}
onClick={() => { onClick={() => {
const messageRequest: MessageRequest = { const messageRequest: MessageRequest = {
id: message.id ?? '', id: message.id ?? '',
@ -66,21 +67,23 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
} }
events.emit(EventName.OnNewMessageRequest, messageRequest) events.emit(EventName.OnNewMessageRequest, messageRequest)
}} }}
/> >
<RefreshCcw size={14} />
</div>
)} )}
<ClipboardCopy <div
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]" className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
size={20}
onClick={() => { onClick={() => {
navigator.clipboard.writeText(message.content ?? '') navigator.clipboard.writeText(message.content ?? '')
toaster({ toaster({
title: 'Copied to clipboard', title: 'Copied to clipboard',
}) })
}} }}
/> >
<Trash2Icon <ClipboardCopy size={14} />
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]" </div>
size={20} <div
className="cursor-pointer px-2 py-2 hover:bg-background/80"
onClick={async () => { onClick={async () => {
deleteAMessage(message.id ?? '') deleteAMessage(message.id ?? '')
if (thread) if (thread)
@ -91,7 +94,10 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
messages: messages.filter((e) => e.id !== message.id), messages: messages.filter((e) => e.id !== message.id),
}) })
}} }}
/> >
<Trash2Icon size={14} />
</div>
</div>
</div> </div>
) )
} }

View File

@ -5,6 +5,7 @@ import { ChatCompletionRole, MessageStatus, ThreadMessage } from '@janhq/core'
import hljs from 'highlight.js' import hljs from 'highlight.js'
import { useAtomValue } from 'jotai'
import { Marked } from 'marked' import { Marked } from 'marked'
import { markedHighlight } from 'marked-highlight' import { markedHighlight } from 'marked-highlight'
@ -21,6 +22,8 @@ import { displayDate } from '@/utils/datetime'
import MessageToolbar from '../MessageToolbar' import MessageToolbar from '../MessageToolbar'
import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
const marked = new Marked( const marked = new Marked(
markedHighlight({ markedHighlight({
langPrefix: 'hljs', langPrefix: 'hljs',
@ -55,6 +58,7 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
const [lastTimestamp, setLastTimestamp] = useState<number | undefined>() const [lastTimestamp, setLastTimestamp] = useState<number | undefined>()
const [tokenSpeed, setTokenSpeed] = useState(0) const [tokenSpeed, setTokenSpeed] = useState(0)
const messages = useAtomValue(getCurrentChatMessagesAtom)
useEffect(() => { useEffect(() => {
if (props.status === MessageStatus.Ready || !experimentalFeatureEnabed) { if (props.status === MessageStatus.Ready || !experimentalFeatureEnabed) {
@ -73,22 +77,29 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
setTokenSpeed(averageTokenSpeed) setTokenSpeed(averageTokenSpeed)
setTokenCount(totalTokenCount) setTokenCount(totalTokenCount)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.content]) }, [props.content])
return ( return (
<div className="group mx-auto rounded-xl px-4 lg:w-3/4"> <div className="group relative mx-auto rounded-xl px-4 lg:w-3/4">
<div <div
className={twMerge( className={twMerge(
'mb-1 flex items-center justify-start gap-2', 'mb-2 flex items-center justify-start gap-x-2',
!isUser && 'mt-2' !isUser && 'mt-2'
)} )}
> >
{!isUser && !isSystem && <LogoMark width={20} />} {!isUser && !isSystem && <LogoMark width={20} />}
<div className="text-sm font-extrabold capitalize">{props.role}</div> <div className="text-sm font-extrabold capitalize">{props.role}</div>
<p className="text-xs font-medium">{displayDate(props.createdAt)}</p> <p className="text-xs font-medium">{displayDate(props.createdAt)}</p>
{experimentalFeatureEnabed && ( {experimentalFeatureEnabed && (
<div className="hidden cursor-pointer group-hover:flex"> <div
className={twMerge(
'absolute right-0 cursor-pointer transition-all',
messages[0].id === props.id
? 'absolute -bottom-10 left-4'
: 'hidden group-hover:flex'
)}
>
<MessageToolbar message={props} /> <MessageToolbar message={props} />
</div> </div>
)} )}
@ -113,7 +124,7 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
</div> </div>
{experimentalFeatureEnabed && {experimentalFeatureEnabed &&
(props.status === MessageStatus.Pending || tokenSpeed > 0) && ( (props.status === MessageStatus.Pending || tokenSpeed > 0) && (
<p className="mt-1 text-xs font-medium text-white"> <p className="mt-2 text-xs font-medium text-foreground">
Token Speed: {Number(tokenSpeed).toFixed(2)}/s Token Speed: {Number(tokenSpeed).toFixed(2)}/s
</p> </p>
)} )}