feat(ui): add copy button to message items
Add a Copy button that allows users to copy raw message contents (text and reasoning parts) to clipboard. The button appears on all messages - alongside Revert/Fork for user messages, and standalone for assistant messages.
This commit is contained in:
committed by
Shantur Rathore
parent
ff5c698131
commit
997d4f4129
@@ -1,4 +1,4 @@
|
|||||||
import { For, Show } from "solid-js"
|
import { For, Show, createSignal } from "solid-js"
|
||||||
import type { MessageInfo, ClientPart } from "../types/message"
|
import type { MessageInfo, ClientPart } from "../types/message"
|
||||||
import { partHasRenderableText } from "../types/message"
|
import { partHasRenderableText } from "../types/message"
|
||||||
import type { MessageRecord } from "../stores/message-v2/types"
|
import type { MessageRecord } from "../stores/message-v2/types"
|
||||||
@@ -18,6 +18,7 @@ interface MessageItemProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function MessageItem(props: MessageItemProps) {
|
export default function MessageItem(props: MessageItemProps) {
|
||||||
|
const [copied, setCopied] = createSignal(false)
|
||||||
|
|
||||||
const isUser = () => props.record.role === "user"
|
const isUser = () => props.record.role === "user"
|
||||||
const createdTimestamp = () => props.messageInfo?.time?.created ?? props.record.createdAt
|
const createdTimestamp = () => props.messageInfo?.time?.created ?? props.record.createdAt
|
||||||
@@ -143,6 +144,22 @@ interface MessageItemProps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getRawContent = () => {
|
||||||
|
return props.parts
|
||||||
|
.filter(part => part.type === "text" || part.type === "reasoning")
|
||||||
|
.map(part => (part as { text?: string }).text || "")
|
||||||
|
.filter(text => text.trim().length > 0)
|
||||||
|
.join("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCopy = async () => {
|
||||||
|
const content = getRawContent()
|
||||||
|
if (!content) return
|
||||||
|
await navigator.clipboard.writeText(content)
|
||||||
|
setCopied(true)
|
||||||
|
setTimeout(() => setCopied(false), 2000)
|
||||||
|
}
|
||||||
|
|
||||||
if (!isUser() && !hasContent()) {
|
if (!isUser() && !hasContent()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -218,8 +235,30 @@ interface MessageItemProps {
|
|||||||
Fork
|
Fork
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
|
<button
|
||||||
|
class="message-action-button"
|
||||||
|
onClick={handleCopy}
|
||||||
|
title="Copy message"
|
||||||
|
aria-label="Copy message"
|
||||||
|
>
|
||||||
|
<Show when={copied()} fallback="Copy">
|
||||||
|
Copied!
|
||||||
|
</Show>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={!isUser()}>
|
||||||
|
<button
|
||||||
|
class="message-action-button"
|
||||||
|
onClick={handleCopy}
|
||||||
|
title="Copy message"
|
||||||
|
aria-label="Copy message"
|
||||||
|
>
|
||||||
|
<Show when={copied()} fallback="Copy">
|
||||||
|
Copied!
|
||||||
|
</Show>
|
||||||
|
</button>
|
||||||
|
</Show>
|
||||||
<time class="message-timestamp" dateTime={timestampIso()}>{timestamp()}</time>
|
<time class="message-timestamp" dateTime={timestampIso()}>{timestamp()}</time>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user