Merge pull request #353 from RooVetGit/markdown_copy

Add a button to copy markdown out of the chat
This commit is contained in:
Matt Rubens
2025-01-14 12:21:15 -05:00
committed by GitHub
3 changed files with 66 additions and 7 deletions

View File

@@ -0,0 +1,5 @@
---
"roo-cline": patch
---
Add a button to copy markdown out of the chat

View File

@@ -35,6 +35,7 @@ Give it a try and let us know what you think in the reddit: https://www.reddit.c
- Sound effects for feedback
- Option to use browsers of different sizes and adjust screenshot quality
- Quick prompt copying from history
- Copy markdown from chat messages
- OpenRouter compression support
- Includes current time in the system prompt
- Uses a file system watcher to more reliably watch for file system changes

View File

@@ -1,6 +1,6 @@
import { VSCodeBadge, VSCodeButton, VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react"
import deepEqual from "fast-deep-equal"
import React, { memo, useEffect, useMemo, useRef } from "react"
import React, { memo, useEffect, useMemo, useRef, useState } from "react"
import { useSize } from "react-use"
import {
ClineApiReqInfo,
@@ -551,7 +551,7 @@ export const ChatRowContent = ({
case "text":
return (
<div>
<Markdown markdown={message.text} />
<Markdown markdown={message.text} partial={message.partial} />
</div>
)
case "user_feedback":
@@ -703,7 +703,7 @@ export const ChatRowContent = ({
</div>
)}
<div style={{ paddingTop: 10 }}>
<Markdown markdown={message.text} />
<Markdown markdown={message.text} partial={message.partial} />
</div>
</>
)
@@ -876,7 +876,7 @@ export const ChatRowContent = ({
{title}
</div>
<div style={{ color: "var(--vscode-charts-green)", paddingTop: 10 }}>
<Markdown markdown={message.text} />
<Markdown markdown={message.text} partial={message.partial} />
</div>
</div>
)
@@ -918,10 +918,63 @@ export const ProgressIndicator = () => (
</div>
)
const Markdown = memo(({ markdown }: { markdown?: string }) => {
const Markdown = memo(({ markdown, partial }: { markdown?: string; partial?: boolean }) => {
const [isHovering, setIsHovering] = useState(false);
return (
<div style={{ wordBreak: "break-word", overflowWrap: "anywhere", marginBottom: -15, marginTop: -15 }}>
<MarkdownBlock markdown={markdown} />
<div
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
style={{ position: "relative" }}
>
<div style={{ wordBreak: "break-word", overflowWrap: "anywhere", marginBottom: -15, marginTop: -15 }}>
<MarkdownBlock markdown={markdown} />
</div>
{markdown && !partial && isHovering && (
<div
style={{
position: "absolute",
bottom: "-4px",
right: "8px",
opacity: 0,
animation: "fadeIn 0.2s ease-in-out forwards",
borderRadius: "4px"
}}
>
<style>
{`
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1.0; }
}
`}
</style>
<VSCodeButton
className="copy-button"
appearance="icon"
style={{
height: "24px",
border: "none",
background: "var(--vscode-editor-background)",
transition: "background 0.2s ease-in-out"
}}
onClick={() => {
navigator.clipboard.writeText(markdown);
// Flash the button background briefly to indicate success
const button = document.activeElement as HTMLElement;
if (button) {
button.style.background = "var(--vscode-button-background)";
setTimeout(() => {
button.style.background = "";
}, 200);
}
}}
title="Copy as markdown"
>
<span className="codicon codicon-copy"></span>
</VSCodeButton>
</div>
)}
</div>
)
})