Skip to content

Commit

Permalink
Merge pull request #179 from sourcery-ai/ben/sou-1442-feat-copyinsert…
Browse files Browse the repository at this point in the history
…-buttons-on-markdown-chat-blocks

feat: add a copy button to each code block in a chat assistant message
  • Loading branch information
bm424 authored Jul 3, 2023
2 parents ddd7b89 + 8201e91 commit 0500afd
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 34 deletions.
45 changes: 37 additions & 8 deletions media/chat.css
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
}

.sidebar__chat-assistant--chat-bubble-text {
margin: 0;
margin: var(--spacing-sm);
color: var(--vscode-settings-textInputForeground);
}

Expand All @@ -105,7 +105,7 @@
background: transparent;
}

.sidebar__chat-assistant--chat-bubble-text *:not(:last-child) {
.sidebar__chat-assistant--chat-bubble-text > *:not(:last-child) {
margin-bottom: var(--spacing-sm);
}

Expand All @@ -127,25 +127,54 @@
/*padding-left: 1.5em;*/
}

.sidebar__chat-assistant--chat-bubble-text *:not(:last-child) {
margin-bottom: var(--spacing-sm);
}

.sidebar__chat-assistant--chat-bubble-text code {
font-family: var(--vscode-editor-font-family);
font-size: var(--vscode-sidebar-font-size);
}

.sidebar__chat-assistant--chat-bubble-text pre {
margin: 0;
overflow-x: auto;
width: 100%;
background-color: var(--vscode-editor-background);
border: 1px solid var(--vscode-panel-border);
border-radius: var(--spacing-xs);
position: relative;
}

.sidebar__chat-assistant--chat-bubble-text pre code {
button.sidebar__chat-assistant--chat-bubble-text--code-copy-button {
visibility: hidden;
background: var(--vscode-button-secondaryBackground);
border: 1px solid var(--vscode-panel-border);
border-radius: var(--spacing-xxs);
position: absolute;
display: block;
top: var(--spacing-sm);
right: var(--spacing-sm);
color: var(--vscode-settings-textInputForeground);
padding: var(--spacing-md);
fill: var(--vscode-button-secondaryForeground);
margin: 0;
width: var(--spacing-lg);
height: var(--spacing-lg);
outline: none;
}

.sidebar__chat-assistant--code-block-action-button-icon {
height: var(--spacing-lg);
width: var(--spacing-lg);
position: absolute;
left: var(--spacing-xxs);
top: var(--spacing-xxs);
}

button.sidebar__chat-assistant--chat-bubble-text--code-copy-button:hover {
background-color: var(--vscode-button-secondaryHoverBackground);
}

.sidebar__chat-assistant--chat-bubble-text
pre:hover
button.sidebar__chat-assistant--chat-bubble-text--code-copy-button {
visibility: visible;
}

.sidebar__chat-assistant--code-block {
Expand Down
52 changes: 26 additions & 26 deletions src/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,32 +252,32 @@ export class ChatProvider implements vscode.WebviewViewProvider {
</head>
<body class="sidebar__chat-assistant-body">
<section id="message-container" class="sidebar__section-container active" data-section="chat-assistant">
<ul class="sidebar__chat-assistant--dialogue-container">
<li id="anchor"></li>
</ul>
</section>
<footer class="sidebar__chat-assistant--footer">
<section class="sidebar__chat-assistant--textarea-container">
<button id="cancel-button" class="sidebar__chat-assistant--cancel-button" disabled>
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" class="sidebar__chat-assistant--regenerate-button-icon">
<path d="m464 256a208 208 0 1 0 -416 0 208 208 0 1 0 416 0zm-464 0a256 256 0 1 1 512 0 256 256 0 1 1 -512 0zm224-72v144c0 13.3-10.7 24-24 24s-24-10.7-24-24v-144c0-13.3 10.7-24 24-24s24 10.7 24 24zm112 0v144c0 13.3-10.7 24-24 24s-24-10.7-24-24v-144c0-13.3 10.7-24 24-24s24 10.7 24 24z"></path>
</svg>
<span>Cancel</span>
</button>
<textarea class="sidebar__chat-assistant--textarea" placeholder="Type your message here!"
id="user-prompt"></textarea>
<button class="sidebar__chat-assistant--textarea-send-button sidebar__textarea-send-button--disabled"
id="send-button">
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"
class="sidebar__chat-assistant--textarea-send-icon">
<path
d="m498.1 5.6c10.1 7 15.4 19.1 13.5 31.2l-64 416c-1.5 9.7-7.4 18.2-16 23s-18.9 5.4-28 1.6l-119.6-49.7-68.5 74.1c-8.9 9.7-22.9 12.9-35.2 8.1s-20.3-16.7-20.3-29.9v-83.6c0-4 1.5-7.8 4.2-10.7l167.6-182.9c5.8-6.3 5.6-16-.4-22s-15.7-6.4-22-.7l-203.4 180.7-88.3-44.2c-10.6-5.3-17.4-15.9-17.7-27.7s5.9-22.8 16.1-28.7l448-256c10.7-6.1 23.9-5.5 34 1.4z" />
</svg>
</button>
</section>
</footer>
<section id="message-container" class="sidebar__section-container active" data-section="chat-assistant">
<ul class="sidebar__chat-assistant--dialogue-container">
<li id="anchor"></li>
</ul>
</section>
<footer class="sidebar__chat-assistant--footer">
<section class="sidebar__chat-assistant--textarea-container">
<button id="cancel-button" class="sidebar__chat-assistant--cancel-button" disabled>
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" class="sidebar__chat-assistant--regenerate-button-icon">
<path d="m464 256a208 208 0 1 0 -416 0 208 208 0 1 0 416 0zm-464 0a256 256 0 1 1 512 0 256 256 0 1 1 -512 0zm224-72v144c0 13.3-10.7 24-24 24s-24-10.7-24-24v-144c0-13.3 10.7-24 24-24s24 10.7 24 24zm112 0v144c0 13.3-10.7 24-24 24s-24-10.7-24-24v-144c0-13.3 10.7-24 24-24s24 10.7 24 24z"></path>
</svg>
<span>Cancel</span>
</button>
<textarea class="sidebar__chat-assistant--textarea" placeholder="Type your message here!"
id="user-prompt"></textarea>
<button class="sidebar__chat-assistant--textarea-send-button sidebar__textarea-send-button--disabled"
id="send-button">
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"
class="sidebar__chat-assistant--textarea-send-icon">
<path
d="m498.1 5.6c10.1 7 15.4 19.1 13.5 31.2l-64 416c-1.5 9.7-7.4 18.2-16 23s-18.9 5.4-28 1.6l-119.6-49.7-68.5 74.1c-8.9 9.7-22.9 12.9-35.2 8.1s-20.3-16.7-20.3-29.9v-83.6c0-4 1.5-7.8 4.2-10.7l167.6-182.9c5.8-6.3 5.6-16-.4-22s-15.7-6.4-22-.7l-203.4 180.7-88.3-44.2c-10.6-5.3-17.4-15.9-17.7-27.7s5.9-22.8 16.1-28.7l448-256c10.7-6.1 23.9-5.5 34 1.4z" />
</svg>
</button>
</section>
</footer>
</body>
<script nonce="${nonce}" src="${scriptUri}"></script>
</html>`;
Expand Down
39 changes: 39 additions & 0 deletions src/webview/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,42 @@ const LINE_HEIGHT = 36;
}
}

const setupCopyButton = (block) => {
if (navigator.clipboard) {
let text = block.querySelector("code").innerText;
let button = document.createElement("button");
button.innerHTML = `
<svg
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
class="sidebar__chat-assistant--code-block-action-button-icon"
>
<path d="m272 0h124.1c12.7 0 24.9 5.1 33.9 14.1l67.9 67.9c9 9 14.1 21.2 14.1 33.9v220.1c0 26.5-21.5 48-48 48h-192c-26.5 0-48-21.5-48-48v-288c0-26.5 21.5-48 48-48zm-224 128h144v64h-128v256h192v-32h64v48c0 26.5-21.5 48-48 48h-224c-26.5 0-48-21.5-48-48v-288c0-26.5 21.5-48 48-48z" />
</svg>
`;
button.title = "Copy to Clipboard";
button.classList.add(
"sidebar__chat-assistant--chat-bubble-text--code-copy-button"
);
block.appendChild(button);
button.onclick = async () => {
await navigator.clipboard.writeText(text);
button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="sidebar__chat-assistant--code-block-action-button-icon"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>`;
};
button.onblur = async () => {
button.innerHTML = `
<svg
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
class="sidebar__chat-assistant--code-block-action-button-icon"
>
<path d="m272 0h124.1c12.7 0 24.9 5.1 33.9 14.1l67.9 67.9c9 9 14.1 21.2 14.1 33.9v220.1c0 26.5-21.5 48-48 48h-192c-26.5 0-48-21.5-48-48v-288c0-26.5 21.5-48 48-48zm-224 128h144v64h-128v256h192v-32h64v48c0 26.5-21.5 48-48 48h-224c-26.5 0-48-21.5-48-48v-288c0-26.5 21.5-48 48-48z" />
</svg>
`;
};
}
};

// Function to add an assistant message or add to the existing one
function addAssistantMessageToUI(message) {
cancelButton.disabled = false;
Expand All @@ -152,6 +188,9 @@ const LINE_HEIGHT = 36;

const replaceCurrentAssistantMessage = () => {
currentAssistantMessage.innerHTML = message.textContent;

let blocks = currentAssistantMessage.querySelectorAll("pre");
blocks.forEach(setupCopyButton);
};

if (currentAssistantMessage != null && message.outcome !== "error") {
Expand Down

0 comments on commit 0500afd

Please sign in to comment.