Skip to content

Commit 0c132ee

Browse files
committed
feature: option to copy chat message in search component
1 parent 686181b commit 0c132ee

File tree

4 files changed

+68
-29
lines changed

4 files changed

+68
-29
lines changed

clients/search-component/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"import": "./dist/vanilla/index.js"
2020
}
2121
},
22-
"version": "0.2.7",
22+
"version": "0.2.8",
2323
"license": "MIT",
2424
"homepage": "https://github.com/devflowinc/trieve/tree/main/clients/search-component",
2525
"scripts": {

clients/search-component/src/TrieveModal/Chat/ChatMessage.tsx

+41-26
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const Markdown = lazy(() => import("react-markdown"));
33

44
import {
55
AIIcon,
6+
CopyConfirmIcon,
7+
CopyIcon,
68
LoadingIcon,
79
ThumbsDownIcon,
810
ThumbsUpIcon,
@@ -91,6 +93,7 @@ export const Message = ({
9193
}) => {
9294
const { rateChatCompletion } = useChatState();
9395
const [positive, setPositive] = React.useState<boolean | null>(null);
96+
const [copied, setCopied] = React.useState<boolean>(false);
9497
const { props } = useModalState();
9598

9699
const ecommerceItems = message.additional
@@ -115,7 +118,7 @@ export const Message = ({
115118
.filter(
116119
(item, index, array) =>
117120
array.findIndex((arrayItem) => arrayItem.title === item.title) ===
118-
index && item.title,
121+
index && item.title,
119122
)
120123
.map((item, index) => (
121124
<a
@@ -176,37 +179,49 @@ export const Message = ({
176179
<div>
177180
{message.additional
178181
? props.type !== "ecommerce" && (
179-
<div className="additional-links">
180-
{message.additional
181-
.filter(
182-
(chunk) =>
183-
(chunk.metadata.heading ||
184-
chunk.metadata.title ||
185-
chunk.metadata.page_title) &&
186-
chunk.link,
187-
)
188-
.map((chunk) => [
189-
chunk.metadata.heading ||
182+
<div className="additional-links">
183+
{message.additional
184+
.filter(
185+
(chunk) =>
186+
(chunk.metadata.heading ||
190187
chunk.metadata.title ||
191-
chunk.metadata.page_title,
188+
chunk.metadata.page_title) &&
192189
chunk.link,
193-
])
194-
.filter(
195-
(link, index, array) =>
196-
array.findIndex((item) => item[0] === link[0]) ===
197-
index && link[0],
198-
)
199-
.map((link, index) => (
200-
<a key={index} href={link[1] as string} target="_blank">
201-
{link[0]}
202-
</a>
203-
))}
204-
</div>
205-
)
190+
)
191+
.map((chunk) => [
192+
chunk.metadata.heading ||
193+
chunk.metadata.title ||
194+
chunk.metadata.page_title,
195+
chunk.link,
196+
])
197+
.filter(
198+
(link, index, array) =>
199+
array.findIndex((item) => item[0] === link[0]) ===
200+
index && link[0],
201+
)
202+
.map((link, index) => (
203+
<a key={index} href={link[1] as string} target="_blank">
204+
{link[0]}
205+
</a>
206+
))}
207+
</div>
208+
)
206209
: null}
207210
<div className="feedback-wrapper">
208211
<span className="spacer"></span>
209212
<div className="feedback-icons">
213+
{copied ? <CopyConfirmIcon /> :
214+
<button
215+
onClick={() => {
216+
void navigator.clipboard.writeText(message.text).then(() => {
217+
setCopied(true);
218+
setTimeout(() => setCopied(false), 2000);
219+
});
220+
}}
221+
>
222+
<CopyIcon />
223+
</button>
224+
}
210225
<button
211226
className={positive != null && positive ? "icon-darken" : ""}
212227
onClick={() => {

clients/search-component/src/TrieveModal/icons.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,27 @@ export const ChatIcon = () => {
322322
</svg>
323323
);
324324
};
325+
326+
export const CopyIcon = () => {
327+
return (
328+
<svg
329+
className="w-4 h-4"
330+
xmlns="http://www.w3.org/2000/svg"
331+
viewBox="0 0 448 512"
332+
>
333+
<path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l140.1 0L400 115.9 400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-204.1c0-12.7-5.1-24.9-14.1-33.9L366.1 14.1c-9-9-21.2-14.1-33.9-14.1L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-32-48 0 0 32c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l32 0 0-48-32 0z" />
334+
</svg>
335+
);
336+
};
337+
338+
export const CopyConfirmIcon = (props: SVGAttributes<SVGElement>) => (
339+
<svg
340+
className="w-4 h-4"
341+
xmlns="http://www.w3.org/2000/svg"
342+
viewBox="0 0 24 24"
343+
{...props}
344+
>
345+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
346+
<path d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z" />
347+
</svg>
348+
);

server/src/public/page.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<link rel="stylesheet" href="/static/output.css" />
55
<link
66
rel="stylesheet"
7-
href="https://unpkg.com/[email protected].7/dist/index.css"
7+
href="https://unpkg.com/[email protected].8/dist/index.css"
88
/>
99
<link
1010
rel="apple-touch-icon"
@@ -181,7 +181,7 @@
181181
</style>
182182

183183
<script type="module">
184-
import {renderToDiv} from 'https://unpkg.com/[email protected].7/dist/vanilla/index.js';
184+
import {renderToDiv} from 'https://unpkg.com/[email protected].8/dist/vanilla/index.js';
185185
window.addEventListener('load', () => {
186186
const root = document.getElementById('root');
187187
renderToDiv(root, {

0 commit comments

Comments
 (0)