diff --git a/src/message.tsx b/src/components/MessageBubble.tsx similarity index 72% rename from src/message.tsx rename to src/components/MessageBubble.tsx index 2784854..d99bd38 100644 --- a/src/message.tsx +++ b/src/components/MessageBubble.tsx @@ -1,15 +1,11 @@ import { XMarkIcon } from "@heroicons/react/24/outline"; import Markdown from "react-markdown"; import { useContext, useState } from "react"; +import { ChatStoreMessage } from "@/types/chatstore"; -import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate"; -import { ChatStore, ChatStoreMessage } from "@/types/chatstore"; -import { calculate_token_length, getMessageText } from "@/chatgpt"; +import { Tr } from "@/translate"; +import { getMessageText } from "@/chatgpt"; import TTSButton, { TTSPlay } from "@/tts"; -import { MessageHide } from "@/messageHide"; -import { MessageDetail } from "@/messageDetail"; -import { MessageToolCall } from "@/messageToolCall"; -import { MessageToolResp } from "@/messageToolResp"; import { EditMessage } from "@/editMessage"; import logprobToColor from "@/utils/logprob"; import { @@ -18,6 +14,7 @@ import { ChatBubbleAction, ChatBubbleActionWrapper, } from "@/components/ui/chat/chat-bubble"; +import { Badge } from "@/components/ui/badge"; import { useToast } from "@/hooks/use-toast"; import { ClipboardIcon, @@ -25,16 +22,126 @@ import { MessageSquareOffIcon, MessageSquarePlusIcon, } from "lucide-react"; -import { AppContext } from "./pages/App"; +import { AppContext } from "@/pages/App"; -export const isVailedJSON = (str: string): boolean => { - try { - JSON.parse(str); - } catch (e) { - return false; +interface HideMessageProps { + chat: ChatStoreMessage; +} + +function MessageHide({ chat }: HideMessageProps) { + return ( + <> +
+ {getMessageText(chat).split("\n")[0].slice(0, 28)} ... +
+
+ Removed from context +
+ + ); +} + +interface MessageDetailProps { + chat: ChatStoreMessage; + renderMarkdown: boolean; +} +function MessageDetail({ chat, renderMarkdown }: MessageDetailProps) { + if (typeof chat.content === "string") { + return
; } - return true; -}; + return ( +
+ {chat.content.map((mdt) => + mdt.type === "text" ? ( + chat.hide ? ( + mdt.text?.split("\n")[0].slice(0, 16) + " ..." + ) : renderMarkdown ? ( + {mdt.text} + ) : ( + mdt.text + ) + ) : ( + { + window.open(mdt.image_url?.url, "_blank"); + }} + /> + ) + )} +
+ ); +} + +interface ToolCallMessageProps { + chat: ChatStoreMessage; + copyToClipboard: (text: string) => void; +} +function MessageToolCall({ chat, copyToClipboard }: ToolCallMessageProps) { + return ( +
+ {chat.tool_calls?.map((tool_call) => ( +
+ + Tool Call ID:{" "} + copyToClipboard(String(tool_call.id))} + > + {tool_call?.id} + + +

Type: {tool_call?.type}

+

+ Function: + copyToClipboard(tool_call.function.name)} + > + {tool_call.function.name} + +

+

+ Arguments: + copyToClipboard(tool_call.function.arguments)} + > + {tool_call.function.arguments} + +

+
+ ))} + {/* [TODO] */} + {chat.content as string} +
+ ); +} + +interface ToolRespondMessageProps { + chat: ChatStoreMessage; + copyToClipboard: (text: string) => void; +} +function MessageToolResp({ chat, copyToClipboard }: ToolRespondMessageProps) { + return ( +
+
+ + Tool Response ID:{" "} + copyToClipboard(String(chat.tool_call_id))} + > + {chat.tool_call_id} + + + {/* [TODO] */} +

{chat.content as string}

+
+
+ ); +} export default function Message(props: { messageIndex: number }) { const ctx = useContext(AppContext); @@ -44,7 +151,6 @@ export default function Message(props: { messageIndex: number }) { const chat = chatStore.history[messageIndex]; const [showEdit, setShowEdit] = useState(false); - const [showCopiedHint, setShowCopiedHint] = useState(false); const [renderMarkdown, setRenderWorkdown] = useState(false); const [renderColor, setRenderColor] = useState(false); const DeleteIcon = () => ( diff --git a/src/messageDetail.tsx b/src/messageDetail.tsx deleted file mode 100644 index 63d7cd9..0000000 --- a/src/messageDetail.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { ChatStoreMessage } from "@/types/chatstore"; -import Markdown from "react-markdown"; - -interface Props { - chat: ChatStoreMessage; - renderMarkdown: boolean; -} -export function MessageDetail({ chat, renderMarkdown }: Props) { - if (typeof chat.content === "string") { - return
; - } - return ( -
- {chat.content.map((mdt) => - mdt.type === "text" ? ( - chat.hide ? ( - mdt.text?.split("\n")[0].slice(0, 16) + " ..." - ) : renderMarkdown ? ( - {mdt.text} - ) : ( - mdt.text - ) - ) : ( - { - window.open(mdt.image_url?.url, "_blank"); - }} - /> - ) - )} -
- ); -} diff --git a/src/messageHide.tsx b/src/messageHide.tsx deleted file mode 100644 index 82b2ac4..0000000 --- a/src/messageHide.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { ChatStoreMessage } from "@/types/chatstore"; -import { getMessageText } from "@/chatgpt"; -import { Badge } from "./components/ui/badge"; - -interface Props { - chat: ChatStoreMessage; -} - -export function MessageHide({ chat }: Props) { - return ( - <> -
- {getMessageText(chat).split("\n")[0].slice(0, 28)} ... -
-
- Removed from context -
- - ); -} diff --git a/src/messageToolCall.tsx b/src/messageToolCall.tsx deleted file mode 100644 index 7957f21..0000000 --- a/src/messageToolCall.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { ChatStoreMessage } from "@/types/chatstore"; - -interface Props { - chat: ChatStoreMessage; - copyToClipboard: (text: string) => void; -} -export function MessageToolCall({ chat, copyToClipboard }: Props) { - return ( -
- {chat.tool_calls?.map((tool_call) => ( -
- - Tool Call ID:{" "} - copyToClipboard(String(tool_call.id))} - > - {tool_call?.id} - - -

Type: {tool_call?.type}

-

- Function: - copyToClipboard(tool_call.function.name)} - > - {tool_call.function.name} - -

-

- Arguments: - copyToClipboard(tool_call.function.arguments)} - > - {tool_call.function.arguments} - -

-
- ))} - {/* [TODO] */} - {chat.content as string} -
- ); -} diff --git a/src/messageToolResp.tsx b/src/messageToolResp.tsx deleted file mode 100644 index 2968d03..0000000 --- a/src/messageToolResp.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { ChatStoreMessage } from "@/types/chatstore"; - -interface Props { - chat: ChatStoreMessage; - copyToClipboard: (text: string) => void; -} -export function MessageToolResp({ chat, copyToClipboard }: Props) { - return ( -
-
- - Tool Response ID:{" "} - copyToClipboard(String(chat.tool_call_id))} - > - {chat.tool_call_id} - - - {/* [TODO] */} -

{chat.content as string}

-
-
- ); -} diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 6a7cf7a..b4e7d20 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -215,6 +215,10 @@ export function App() { const newKey = await (await db).add(STORAGE_NAME, newChatStore(chatStore)); setSelectedChatIndex(newKey as number); setAllChatStoreIndexes(await (await db).getAllKeys(STORAGE_NAME)); + toast({ + title: "New chat session created", + description: `A new chat session (ID. ${newKey}) has been created.`, + }); }; const handleNewChatStore = async () => { return handleNewChatStoreWithOldOne(chatStore); diff --git a/src/pages/Chatbox.tsx b/src/pages/Chatbox.tsx index f8d2b5f..a06175f 100644 --- a/src/pages/Chatbox.tsx +++ b/src/pages/Chatbox.tsx @@ -12,7 +12,7 @@ import ChatGPT, { Usage, } from "@/chatgpt"; import { ChatStoreMessage } from "../types/chatstore"; -import Message from "@/message"; +import Message from "@/components/MessageBubble"; import { models } from "@/types/models"; import { AddImage } from "@/addImage"; import { ListAPIs } from "@/listAPIs";