diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 7fc3ec8..3a91d6e 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -20,7 +20,6 @@ if (!process.env.OPENAI_API_KEY) { export const POST = auth(async function POST(req: Request) { const json = await req.json() // @ts-ignore - console.log(req.auth) // todo fix types const messages = json.messages.map((m: any) => ({ content: m.content, role: m.role diff --git a/components/chat-message-actions.tsx b/components/chat-message-actions.tsx new file mode 100644 index 0000000..6593ae9 --- /dev/null +++ b/components/chat-message-actions.tsx @@ -0,0 +1,38 @@ +'use client' + +import { Button } from '@/components/ui/button' +import { IconCheck, IconCopy } from '@/components/ui/icons' +import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard' +import { cn } from '@/lib/utils' +import { type Message } from 'ai-connector' + +interface ChatMessageActionsProps extends React.ComponentProps<'div'> { + message: Message +} + +export function ChatMessageActions({ + message, + className, + ...props +}: ChatMessageActionsProps) { + const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }) + + return ( +
+ +
+ ) +} diff --git a/components/chat-message.tsx b/components/chat-message.tsx index f3c6635..7ea122f 100644 --- a/components/chat-message.tsx +++ b/components/chat-message.tsx @@ -6,6 +6,7 @@ import { cn } from '@/lib/utils' import { CodeBlock } from '@/components/ui/codeblock' import { MemoizedReactMarkdown } from '@/components/markdown' import { IconOpenAI, IconUser } from '@/components/ui/icons' +import { ChatMessageActions } from '@/components/chat-message-actions' export interface ChatMessageProps { message: Message @@ -13,7 +14,10 @@ export interface ChatMessageProps { export function ChatMessage({ message, ...props }: ChatMessageProps) { return ( -
+
{message.role === 'user' ? : }
-
- {children}

- }, - code({ node, inline, className, children, ...props }) { - if (children.length) { - if (children[0] == '▍') { - return ( - - ) +
+
+ {children}

+ }, + code({ node, inline, className, children, ...props }) { + if (children.length) { + if (children[0] == '▍') { + return ( + + ▍ + + ) + } + + children[0] = (children[0] as string).replace('`▍`', '▍') } - children[0] = (children[0] as string).replace('`▍`', '▍') + const match = /language-(\w+)/.exec(className || '') + + return !inline ? ( + + ) : ( + + {children} + + ) } - - const match = /language-(\w+)/.exec(className || '') - - return !inline ? ( - - ) : ( - - {children} - - ) - } - }} - > - {message.content} -
+ }} + > + {message.content} + +
+
) diff --git a/components/ui/codeblock.tsx b/components/ui/codeblock.tsx index 694bd1d..cfa98d0 100644 --- a/components/ui/codeblock.tsx +++ b/components/ui/codeblock.tsx @@ -4,7 +4,7 @@ import { FC, memo } from 'react' import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' import { coldarkDark } from 'react-syntax-highlighter/dist/cjs/styles/prism' -import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-cliipboard' +import { useCopyToClipboard } from '@/lib/hooks/use-copy-to-clipboard' import { IconCheck, IconCopy, IconDownload } from '@/components/ui/icons' interface Props { diff --git a/lib/hooks/use-copy-to-cliipboard.tsx b/lib/hooks/use-copy-to-clipboard.tsx similarity index 85% rename from lib/hooks/use-copy-to-cliipboard.tsx rename to lib/hooks/use-copy-to-clipboard.tsx index 748a9bc..9f9b8e3 100644 --- a/lib/hooks/use-copy-to-cliipboard.tsx +++ b/lib/hooks/use-copy-to-clipboard.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState } from 'react' +import * as React from 'react' export interface useCopyToClipboardProps { timeout?: number @@ -9,7 +9,7 @@ export interface useCopyToClipboardProps { export function useCopyToClipboard({ timeout = 2000 }: useCopyToClipboardProps) { - const [isCopied, setIsCopied] = useState(false) + const [isCopied, setIsCopied] = React.useState(false) const copyToClipboard = (value: string) => { if (