Skip to content

Commit

Permalink
Styling message toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
urmauur committed Nov 27, 2023
1 parent d74698a commit 9bf39cb
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 62 deletions.
5 changes: 4 additions & 1 deletion web/screens/Chat/ChatItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import SimpleTextMessage from '../SimpleTextMessage'
type Ref = HTMLDivElement

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} />
</div>
))
Expand Down
118 changes: 62 additions & 56 deletions web/screens/Chat/MessageToolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,63 +35,69 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
}
return (
<div className="flex flex-row items-center">
{message.status === MessageStatus.Pending && (
<StopCircle
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
size={20}
onClick={() => stopInference()}
/>
)}
{message.status !== MessageStatus.Pending &&
message.id === messages[0]?.id && (
<RefreshCcw
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
size={20}
onClick={() => {
const messageRequest: MessageRequest = {
id: message.id ?? '',
messages: messages
.slice(1, messages.length)
.reverse()
.map((e) => {
return {
content: e.content,
role: e.role,
} as ChatCompletionMessage
}),
threadId: message.threadId ?? '',
}
if (message.role === ChatCompletionRole.Assistant) {
deleteAMessage(message.id ?? '')
}
events.emit(EventName.OnNewMessageRequest, messageRequest)
}}
/>
<div className="flex overflow-hidden rounded-md border border-border bg-background/20">
{message.status === MessageStatus.Pending && (
<div
className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
onClick={() => stopInference()}
>
<StopCircle size={14} />
</div>
)}
<ClipboardCopy
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
size={20}
onClick={() => {
navigator.clipboard.writeText(message.content ?? '')
toaster({
title: 'Copied to clipboard',
})
}}
/>
<Trash2Icon
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
size={20}
onClick={async () => {
deleteAMessage(message.id ?? '')
if (thread)
await pluginManager
.get<ConversationalPlugin>(PluginType.Conversational)
?.saveConversation({
...thread,
messages: messages.filter((e) => e.id !== message.id),
})
}}
/>
{message.status !== MessageStatus.Pending &&
message.id === messages[0]?.id && (
<div
className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
onClick={() => {
const messageRequest: MessageRequest = {
id: message.id ?? '',
messages: messages
.slice(1, messages.length)
.reverse()
.map((e) => {
return {
content: e.content,
role: e.role,
} as ChatCompletionMessage
}),
threadId: message.threadId ?? '',
}
if (message.role === ChatCompletionRole.Assistant) {
deleteAMessage(message.id ?? '')
}
events.emit(EventName.OnNewMessageRequest, messageRequest)
}}
>
<RefreshCcw size={14} />
</div>
)}
<div
className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
onClick={() => {
navigator.clipboard.writeText(message.content ?? '')
toaster({
title: 'Copied to clipboard',
})
}}
>
<ClipboardCopy size={14} />
</div>
<div
className="cursor-pointer px-2 py-2 hover:bg-background/80"
onClick={async () => {
deleteAMessage(message.id ?? '')
if (thread)
await pluginManager
.get<ConversationalPlugin>(PluginType.Conversational)
?.saveConversation({
...thread,
messages: messages.filter((e) => e.id !== message.id),
})
}}
>
<Trash2Icon size={14} />
</div>
</div>
</div>
)
}
Expand Down
21 changes: 16 additions & 5 deletions web/screens/Chat/SimpleTextMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ChatCompletionRole, MessageStatus, ThreadMessage } from '@janhq/core'

import hljs from 'highlight.js'

import { useAtomValue } from 'jotai'
import { Marked } from 'marked'

import { markedHighlight } from 'marked-highlight'
Expand All @@ -21,6 +22,8 @@ import { displayDate } from '@/utils/datetime'

import MessageToolbar from '../MessageToolbar'

import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'

const marked = new Marked(
markedHighlight({
langPrefix: 'hljs',
Expand Down Expand Up @@ -55,6 +58,7 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {

const [lastTimestamp, setLastTimestamp] = useState<number | undefined>()
const [tokenSpeed, setTokenSpeed] = useState(0)
const messages = useAtomValue(getCurrentChatMessagesAtom)

useEffect(() => {
if (props.status === MessageStatus.Ready || !experimentalFeatureEnabed) {
Expand All @@ -73,22 +77,29 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {

setTokenSpeed(averageTokenSpeed)
setTokenCount(totalTokenCount)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.content])

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
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 && !isSystem && <LogoMark width={20} />}
<div className="text-sm font-extrabold capitalize">{props.role}</div>
<p className="text-xs font-medium">{displayDate(props.createdAt)}</p>

{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} />
</div>
)}
Expand All @@ -113,7 +124,7 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
</div>
{experimentalFeatureEnabed &&
(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
</p>
)}
Expand Down

0 comments on commit 9bf39cb

Please sign in to comment.