From 14fe29c03aeb6f737811055064803f71f3f731cd Mon Sep 17 00:00:00 2001 From: Jack Wu Date: Sun, 26 Mar 2023 00:28:08 -0400 Subject: [PATCH] feat: Message copy button (#171) * Add copy button * Fix copy button not copying the entire message * fix style * remove prewrap --------- Co-authored-by: Mckay Wrigley --- components/Chat/ChatMessage.tsx | 97 ++++++++++++++++++++------------- components/Chat/CopyButton.tsx | 24 ++++++++ 2 files changed, 84 insertions(+), 37 deletions(-) create mode 100644 components/Chat/CopyButton.tsx diff --git a/components/Chat/ChatMessage.tsx b/components/Chat/ChatMessage.tsx index c087f9d..126e31b 100644 --- a/components/Chat/ChatMessage.tsx +++ b/components/Chat/ChatMessage.tsx @@ -1,10 +1,11 @@ import { Message } from "@/types"; import { IconEdit } from "@tabler/icons-react"; -import { FC, useEffect, useRef, useState } from "react"; import { useTranslation } from "next-i18next"; +import { FC, useEffect, useRef, useState } from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { CodeBlock } from "../Markdown/CodeBlock"; +import { CopyButton } from "./CopyButton"; interface Props { message: Message; @@ -14,10 +15,11 @@ interface Props { } export const ChatMessage: FC = ({ message, messageIndex, lightMode, onEditMessage }) => { - const { t } = useTranslation('chat'); + const { t } = useTranslation("chat"); const [isEditing, setIsEditing] = useState(false); const [isHovering, setIsHovering] = useState(false); const [messageContent, setMessageContent] = useState(message.content); + const [messagedCopied, setMessageCopied] = useState(false); const textareaRef = useRef(null); @@ -47,6 +49,17 @@ export const ChatMessage: FC = ({ message, messageIndex, lightMode, onEdi } }; + const copyOnClick = () => { + if (!navigator.clipboard) return; + + navigator.clipboard.writeText(message.content).then(() => { + setMessageCopied(true); + setTimeout(() => { + setMessageCopied(false); + }, 2000); + }); + }; + useEffect(() => { if (textareaRef.current) { textareaRef.current.style.height = "inherit"; @@ -119,41 +132,51 @@ export const ChatMessage: FC = ({ message, messageIndex, lightMode, onEdi )} ) : ( - - ) : ( - - {children} - - ); - }, - table({ children }) { - return {children}
; - }, - th({ children }) { - return {children}; - }, - td({ children }) { - return {children}; - } - }} - > - {message.content} -
+ <> + + ) : ( + + {children} + + ); + }, + table({ children }) { + return {children}
; + }, + th({ children }) { + return {children}; + }, + td({ children }) { + return {children}; + } + }} + > + {message.content} +
+ + {(isHovering || window.innerWidth < 640) && ( + + )} + )} diff --git a/components/Chat/CopyButton.tsx b/components/Chat/CopyButton.tsx new file mode 100644 index 0000000..554bfb6 --- /dev/null +++ b/components/Chat/CopyButton.tsx @@ -0,0 +1,24 @@ +import { IconCheck, IconCopy } from "@tabler/icons-react"; +import { FC } from "react"; + +type Props = { + messagedCopied: boolean; + copyOnClick: () => void; +}; + +export const CopyButton: FC = ({ messagedCopied, copyOnClick }) => ( + +);