Merge pull request #227 from devchat-ai/70-implement-a-feature-to-display-a-message-at-the-top-of-the-chat-history-when-scrolled-to-the-top
70 implement a feature to display a message at the top of the chat history when scrolled to the top
@ -1,108 +0,0 @@
|
||||
|
||||
|
||||
|
||||
function processMessageUI(message) {
|
||||
addMessageToUI('user', message);
|
||||
messageUtil.sendMessage({
|
||||
command: 'sendMessage',
|
||||
text: message});
|
||||
}
|
||||
|
||||
function userMessageActions(messageItem, onCancel, onSend, onEdit) {
|
||||
const buttonGroup = document.createElement('div');
|
||||
buttonGroup.classList.add('button-group');
|
||||
|
||||
const cancelButton = document.createElement('button');
|
||||
cancelButton.classList.add('cancel-button');
|
||||
cancelButton.innerText = 'Cancel';
|
||||
buttonGroup.appendChild(cancelButton);
|
||||
|
||||
const sendButton = document.createElement('button');
|
||||
sendButton.classList.add('send-button');
|
||||
sendButton.innerText = 'Send';
|
||||
buttonGroup.appendChild(sendButton);
|
||||
|
||||
const editButton = document.createElement('button');
|
||||
editButton.classList.add('edit-button');
|
||||
editButton.innerHTML = '<i class="fas fa-edit"></i>';
|
||||
buttonGroup.appendChild(editButton);
|
||||
|
||||
messageItem.appendChild(buttonGroup);
|
||||
|
||||
// Initially hide the cancel and send buttons
|
||||
cancelButton.style.display = 'none';
|
||||
sendButton.style.display = 'none';
|
||||
|
||||
// Add a click listener to the edit button
|
||||
editButton.addEventListener('click', () => {
|
||||
// Hide the edit button and show the cancel and send buttons
|
||||
editButton.style.display = 'none';
|
||||
cancelButton.style.display = 'inline-block';
|
||||
sendButton.style.display = 'inline-block';
|
||||
|
||||
// Add your existing edit button functionality here
|
||||
onEdit();
|
||||
});
|
||||
|
||||
// Add an event listener for the cancel button
|
||||
cancelButton.addEventListener('click', () => {
|
||||
// Hide the cancel and send buttons and show the edit button
|
||||
cancelButton.style.display = 'none';
|
||||
sendButton.style.display = 'none';
|
||||
editButton.style.display = 'inline-block';
|
||||
|
||||
// Add your existing cancel button functionality here
|
||||
onCancel();
|
||||
});
|
||||
|
||||
// Add an event listener for the send button
|
||||
sendButton.addEventListener('click', () => {
|
||||
// Hide the cancel and send buttons and show the edit button
|
||||
cancelButton.style.display = 'none';
|
||||
sendButton.style.display = 'none';
|
||||
editButton.style.display = 'inline-block';
|
||||
|
||||
// Add your existing save button functionality here
|
||||
onSend();
|
||||
});
|
||||
}
|
||||
|
||||
function messageItemActions(messageItem, messageContent, role) {
|
||||
if (role === 'user') {
|
||||
userMessageActions(messageItem, () => { // onCancel
|
||||
const textArea = messageItem.querySelector('.edit-textarea');
|
||||
textArea.replaceWith(messageContent)
|
||||
// Remove the text area, save button, and cancel button
|
||||
textArea.remove();
|
||||
}, () => { // onSend
|
||||
const textArea = messageItem.querySelector('.edit-textarea');
|
||||
const newMessage = textArea.value.trim();
|
||||
if (newMessage !== '') {
|
||||
textArea.replaceWith(messageContent)
|
||||
// Remove the text area, save button, and cancel button
|
||||
textArea.remove();
|
||||
|
||||
// Process and send the new message to the extension
|
||||
processMessageUI(newMessage);
|
||||
}
|
||||
}, () => { // onEdit
|
||||
// Create a new text area element with the same size as the message content
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.classList.add('edit-textarea');
|
||||
textArea.style.width = `${messageContent.offsetWidth}px`;
|
||||
textArea.style.height = `${messageContent.offsetHeight}px`;
|
||||
textArea.value = messageContent.textContent.trim();
|
||||
messageContent.replaceWith(textArea);
|
||||
|
||||
// Focus on the text area
|
||||
textArea.focus();
|
||||
});
|
||||
} else {
|
||||
// TODO
|
||||
// currently there is no action for the bot message
|
||||
//
|
||||
// const actionIcon = document.createElement('i');
|
||||
// actionIcon.className = 'fas fa-check-circle';
|
||||
// messageItem.appendChild(actionIcon);
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 115 KiB |
@ -1,215 +0,0 @@
|
||||
:root {
|
||||
--vscode-background: var(--vscode-editor-background);
|
||||
--vscode-foreground: var(--vscode-editor-foreground);
|
||||
--vscode-border: var(--vscode-editorWidget-border);
|
||||
--vscode-button-bg: var(--vscode-button-background);
|
||||
--vscode-button-fg: var(--vscode-button-foreground);
|
||||
--vscode-button-hover-bg: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: var(--vscode-background);
|
||||
color: var(--vscode-foreground);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f1f1f1;
|
||||
overflow: auto;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#chat-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background-color: #f1f1f1;
|
||||
color: #000000;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
overflow-y: auto;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
background-color: #f1f1f1;
|
||||
border-radius: 5px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
position: absolute;
|
||||
display: none;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
padding: 8px;
|
||||
z-index: 10;
|
||||
}
|
||||
.context-menu-item {
|
||||
cursor: pointer;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.context-menu-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
background-color: #007acc;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
background-color: #005b8e;
|
||||
}
|
||||
|
||||
|
||||
#messages-container {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin: 20px 0;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
border-bottom: 1px solid var(--vscode-border);
|
||||
}
|
||||
|
||||
.message-item.user-message {
|
||||
background-color: #007acc;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
margin-left: 30px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.message-item .message-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.new-message-textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.message-item .message-content code {
|
||||
background-color: #ddd;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.message-item .sender-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.message-item .action-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.input-resize-handle {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
cursor: ns-resize;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
#message-input {
|
||||
flex-grow: 1;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
padding: 5px;
|
||||
outline: none;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
#send-button {
|
||||
margin-top: 10px;
|
||||
background-color: var(--vscode-button-bg);
|
||||
color: var(--vscode-button-fg);
|
||||
border: 1px solid var(--vscode-border);
|
||||
border-radius: 4px;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#send-button:hover {
|
||||
background-color: var(--vscode-button-hover-bg);
|
||||
}
|
||||
|
||||
.popup-context-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #f9f9f9;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
padding: 12px 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
.popup-context-menu a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
.popup-context-menu a:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.popup-command-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #f9f9f9;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
padding: 12px 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
.popup-command-menu a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
.popup-command-menu a:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<!-- Meta tags for responsiveness and charset -->
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<title>Chat Panel</title>
|
||||
|
||||
<!-- Font Awesome icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.0/css/all.min.css" />
|
||||
<link rel="stylesheet" href="<vscode-resource:/assets/chatPanel.css>" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/prism.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="chat-container">
|
||||
<div id="messages-container">
|
||||
<!-- Chat messages will be added here dynamically -->
|
||||
</div>
|
||||
<div id="input-resize-handle" class="input-resize-handle"></div>
|
||||
<div id="input-container">
|
||||
<textarea id="message-input" placeholder="Type your message..."></textarea>
|
||||
<button id="add-context-button">+</button>
|
||||
<div id="popupContextMenu" class="popup-context-menu"></div><button id="add-command-button">Commands</button>
|
||||
<div id="popupCommandMenu" class="popup-command-menu"></div><button id="send-button">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="context-menu" id="context-menu">
|
||||
<div class="context-menu-item" id="menu-item-1">Insert Code</div>
|
||||
</div>
|
||||
|
||||
<!-- Load the chatPanel.js file -->
|
||||
<script src="<vscode-resource:/assets/messageUtil.js>"></script>
|
||||
<script src="<vscode-resource:/assets/codeBlock.js>"></script>
|
||||
<script src="<vscode-resource:/assets/markdown.js>"></script>
|
||||
<script src="<vscode-resource:/assets/contextMenu.js>"></script>
|
||||
<script src="<vscode-resource:/assets/inputContainer.js>"></script>
|
||||
<script src="<vscode-resource:/assets/messageContainer.js>"></script>
|
||||
<script src="<vscode-resource:/assets/actionButton.js>"></script>
|
||||
<script src="<vscode-resource:/assets/chatUI.js>"></script>
|
||||
<script src="<vscode-resource:/assets/resizeInput.js>"></script>
|
||||
<script src="<vscode-resource:/assets/clipboard.js>"></script>
|
||||
<script src="<vscode-resource:/assets/main.js>"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
Prism.highlightAll();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,95 +0,0 @@
|
||||
// chatUI.js
|
||||
|
||||
|
||||
function getLastBotMessageItem(messagesContainer) {
|
||||
const lastMessage = messagesContainer.lastElementChild;
|
||||
|
||||
if (lastMessage && lastMessage.classList.contains('message-item')) {
|
||||
const lastMessageIcon = lastMessage.querySelector('i');
|
||||
if (lastMessageIcon && lastMessageIcon.classList.contains('fa-robot')) {
|
||||
return lastMessage;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function botMessageUpdate(role, content, partial) {
|
||||
// Create a MarkdownIt instance for rendering markdown content
|
||||
const messagesContainer = document.getElementById('messages-container');
|
||||
let lastBotMessage = getLastBotMessageItem(messagesContainer);
|
||||
|
||||
if (lastBotMessage == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Render the markdown content inside the message content container
|
||||
const renderedContent = markdownRender(content);
|
||||
const lastMessageContent = lastBotMessage.querySelector('.message-content');
|
||||
lastMessageContent.innerHTML = renderedContent;
|
||||
|
||||
if (!partial) {
|
||||
// Find any code blocks in the rendered content and add a class to style them
|
||||
const codeBlocks = lastMessageContent.querySelectorAll('pre > code');
|
||||
|
||||
// Initialize the Apply Patch functionality
|
||||
initButtonForCodeBlock(codeBlocks);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function addSenderIcon(messageItem, role) {
|
||||
// Create a sender icon element and add the appropriate class based on the role (user or bot)
|
||||
const senderIcon = document.createElement('i');
|
||||
const iconClasses = role === 'user' ? ['fas', 'fa-user-circle'] : ['fas', 'fa-robot'];
|
||||
senderIcon.classList.add(...iconClasses);
|
||||
messageItem.appendChild(senderIcon);
|
||||
}
|
||||
|
||||
function addMessageContent(messageItem, renderedContent, role) {
|
||||
// Create a container for the message content
|
||||
const messageContent = document.createElement('div');
|
||||
messageContent.classList.add('message-content');
|
||||
messageContent.innerHTML = renderedContent;
|
||||
|
||||
// Find any code blocks in the rendered content and add a class to style them
|
||||
const codeBlocks = messageContent.querySelectorAll('pre > code');
|
||||
|
||||
// Initialize the Apply Patch functionality
|
||||
if (role != "user") {
|
||||
initButtonForCodeBlock(codeBlocks);
|
||||
}
|
||||
messageItem.appendChild(messageContent);
|
||||
messageItemActions(messageItem, messageContent, role);
|
||||
}
|
||||
|
||||
function addMessageItem(messagesContainer, content, role) {
|
||||
// Render the markdown content inside the message content container
|
||||
let renderedContent = markdownRender(content);
|
||||
if (role == "user") {
|
||||
renderedContent = markdownRender("\`\`\`\n" + content);
|
||||
}
|
||||
|
||||
const messageItem = document.createElement('div');
|
||||
messageItem.classList.add('message-item');
|
||||
|
||||
addSenderIcon(messageItem, role);
|
||||
addMessageContent(messageItem, renderedContent, role);
|
||||
|
||||
messagesContainer.appendChild(messageItem);
|
||||
}
|
||||
|
||||
function addMessageToUI(role, content, partial = false) {
|
||||
// Create a MarkdownIt instance for rendering markdown content
|
||||
const messagesContainer = document.getElementById('messages-container');
|
||||
|
||||
if (role == "bot" && botMessageUpdate(role, content, partial)) {
|
||||
return
|
||||
}
|
||||
|
||||
addMessageItem(messagesContainer, content, role);
|
||||
// Scroll the messages container to the bottom to display the latest message
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
@ -1,62 +0,0 @@
|
||||
// clipboard.js
|
||||
|
||||
|
||||
function initClipboard(codeBlocks, onApplyButtonClick, onApplyCodeButtonClick, onApplyCodeFileButtonClick) {
|
||||
codeBlocks.forEach(block => {
|
||||
const contentSpan = document.createElement('span');
|
||||
contentSpan.innerHTML = block.innerHTML;
|
||||
block.innerHTML = '';
|
||||
block.appendChild(contentSpan);
|
||||
|
||||
const copyButton = document.createElement('button');
|
||||
copyButton.classList.add('copy-button');
|
||||
copyButton.innerText = 'Copy';
|
||||
block.appendChild(copyButton);
|
||||
|
||||
copyButton.addEventListener('click', () => {
|
||||
// Copy the message text to the clipboard
|
||||
navigator.clipboard.writeText(contentSpan.textContent);
|
||||
|
||||
// Change the button text temporarily to show that the text has been copied
|
||||
copyButton.textContent = 'Copied!';
|
||||
|
||||
// Reset the button text after a short delay
|
||||
setTimeout(() => {
|
||||
copyButton.textContent = '';
|
||||
const copyIcon = document.createElement('i');
|
||||
copyIcon.classList.add('fas', 'fa-copy');
|
||||
copyButton.appendChild(copyIcon);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
// Add 'Apply' button
|
||||
const applyButton = document.createElement('button');
|
||||
applyButton.classList.add('apply-button');
|
||||
applyButton.innerText = 'Show Diff';
|
||||
block.appendChild(applyButton);
|
||||
|
||||
applyButton.addEventListener('click', () => {
|
||||
onApplyButtonClick(contentSpan.textContent);
|
||||
});
|
||||
|
||||
// Add 'Apply' button
|
||||
const applyCodeButton = document.createElement('button');
|
||||
applyCodeButton.classList.add('apply-button');
|
||||
applyCodeButton.innerText = 'Insert Code';
|
||||
block.appendChild(applyCodeButton);
|
||||
|
||||
applyCodeButton.addEventListener('click', () => {
|
||||
onApplyCodeButtonClick(contentSpan.textContent);
|
||||
});
|
||||
|
||||
// Add 'Apply' button
|
||||
const applyCodeFileButton = document.createElement('button');
|
||||
applyCodeFileButton.classList.add('apply-button');
|
||||
applyCodeFileButton.innerText = 'Relace File';
|
||||
block.appendChild(applyCodeFileButton);
|
||||
|
||||
applyCodeFileButton.addEventListener('click', () => {
|
||||
onApplyCodeFileButtonClick(contentSpan.textContent);
|
||||
});
|
||||
});
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
|
||||
function initButtonForCodeBlock(codeBlocks) {
|
||||
codeBlocks.forEach(block => {
|
||||
block.classList.add('code-block');
|
||||
});
|
||||
|
||||
initClipboard(codeBlocks, (patchContent) => {
|
||||
messageUtil.sendMessage({
|
||||
command: 'block_apply',
|
||||
content: patchContent,
|
||||
});
|
||||
}, (codeContent) => {
|
||||
messageUtil.sendMessage({
|
||||
command: 'code_apply',
|
||||
content: codeContent,
|
||||
});
|
||||
}, (codeContent) => {
|
||||
messageUtil.sendMessage({
|
||||
command: 'code_file_apply',
|
||||
content: codeContent,
|
||||
});
|
||||
});
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
|
||||
function initContextMenu() {
|
||||
const messagesContainer = document.getElementById('messages-container');
|
||||
const contextMenu = document.getElementById('context-menu');
|
||||
const menuItem1 = document.getElementById('menu-item-1');
|
||||
let selectedText = '';
|
||||
|
||||
function hideContextMenu() {
|
||||
contextMenu.style.display = 'none';
|
||||
}
|
||||
|
||||
function getSelectedText() {
|
||||
const selection = window.getSelection();
|
||||
return selection.toString();
|
||||
}
|
||||
|
||||
messagesContainer.addEventListener('contextmenu', (event) => {
|
||||
event.preventDefault();
|
||||
selectedText = getSelectedText();
|
||||
contextMenu.style.display = 'block';
|
||||
contextMenu.style.left = event.pageX + 'px';
|
||||
contextMenu.style.top = event.pageY + 'px';
|
||||
});
|
||||
|
||||
document.addEventListener('click', hideContextMenu);
|
||||
|
||||
menuItem1.addEventListener('click', () => {
|
||||
messageUtil.sendMessage('code_apply', { content: selectedText });
|
||||
hideContextMenu();
|
||||
});
|
||||
}
|
Before Width: | Height: | Size: 4.7 KiB |
@ -1,4 +0,0 @@
|
||||
<svg width="240" height="240" viewBox="0 0 240 240" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M163 200.375L188.4 226L230 184" stroke="#E8471C" stroke-width="19" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.2577 175.031C45.7672 177.204 42.3402 179.693 39.0398 182.511C32.0335 188.468 25.5467 195.87 19.9848 204.71C17.66 198.72 16.3804 192.195 16.3804 185.367V161.123C16.3804 140.684 27.8336 122.979 44.5636 114.261C35.2832 93.6736 19.1803 55.2645 19.5414 37.3591C20.0038 14.3278 38.3873 5.32676 48.3265 3.70837C58.1707 1.56128 78.5052 3.18611 87.1268 24.4894C94.1457 41.8403 92.3086 86.8197 90.9276 108.491H117.73C116.349 86.8262 114.512 41.8403 121.531 24.4894C130.146 3.19256 150.481 1.56128 160.325 3.70837C170.258 5.32676 188.641 14.3278 189.11 37.3591C189.471 55.2645 173.374 93.6608 164.094 114.248C173.127 118.955 180.621 126.286 185.6 135.255C178.113 141.11 170.669 143.863 162.257 144.714C155.916 136.538 146.091 131.29 135.055 131.29H73.5958C54.4649 131.29 38.9511 147.08 38.9511 166.552V171.511C38.9511 172.542 39.7999 173.348 40.8071 173.31C43.5311 173.206 46.217 173.232 48.8586 173.387C49.7075 173.439 49.9862 174.58 49.2577 175.031ZM148.327 20.3758C142.873 21.6718 139.388 25.2374 136.76 30.8662L136.766 30.8598C134.91 34.8316 134.2 39.7254 134.2 39.7254C134.2 39.7254 150.126 35.2572 156.448 46.8308C161.579 56.2252 143.037 108.491 143.037 108.491C143.037 108.491 146.338 108.574 148.276 109.071C151.089 102.855 154.738 94.557 158.348 85.672C171.011 54.5359 172.747 42.2465 172.652 37.6944C172.525 31.4659 170.22 26.8751 165.595 23.6577C161.889 21.085 157.987 20.3113 157.582 20.2339L157.157 20.1759L156.999 20.1243C156.492 20.0276 152.634 19.3506 148.327 20.3758ZM61.0847 44.4194C70.289 52.6338 69.1995 108.491 69.1995 108.491H74.394C74.8374 101.495 75.3695 91.5008 75.6039 80.862C76.3387 47.1726 73.5958 35.0766 71.8917 30.8662C69.5605 25.102 65.7787 21.6718 60.3245 20.3758C55.9472 19.3377 52.0323 20.0534 51.6332 20.1308L51.2215 20.2404H51.0568C50.55 20.3371 46.7111 21.1237 43.0623 23.6641C38.4379 26.8751 36.1321 31.4723 36.0054 37.7008C35.9801 39.2419 36.1574 41.0214 36.8923 44.7482C36.8923 44.7482 48.4732 33.8323 61.0847 44.4194ZM169.611 163.98C176.617 158.022 183.104 150.62 188.665 141.78C190.99 147.77 192.27 154.295 192.27 161.124V185.367C192.27 188.925 191.923 192.401 191.262 195.762L169.049 173.549L169.026 173.571C168.703 173.312 168.288 173.164 167.843 173.181C165.119 173.284 162.433 173.258 159.792 173.103C158.943 173.058 158.664 171.911 159.393 171.459C162.883 169.286 166.31 166.798 169.611 163.98ZM144.011 214.011C141.154 214.787 138.152 215.201 135.055 215.201H73.5948C62.5597 215.201 52.7345 209.952 46.3934 201.777C37.9808 202.628 30.5375 205.381 23.0498 211.235C31.9248 227.213 48.7689 238 68.0899 238H140.559C148.547 238 156.111 236.156 162.865 232.865L144.011 214.011ZM75.5146 189.571C82.4488 189.571 88.0701 182.262 88.0701 173.245C88.0701 164.229 82.4488 156.92 75.5146 156.92C68.5804 156.92 62.9592 164.229 62.9592 173.245C62.9592 182.262 68.5804 189.571 75.5146 189.571ZM145.697 173.245C145.697 182.262 140.076 189.571 133.142 189.571C126.208 189.571 120.587 182.262 120.587 173.245C120.587 164.229 126.208 156.92 133.142 156.92C140.076 156.92 145.697 164.229 145.697 173.245Z" fill="#E8471C"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.2 KiB |
@ -1,6 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.13976 17.8052C6.45142 17.5415 6.77505 17.3085 7.10466 17.105C7.17345 17.0628 7.14713 16.956 7.06697 16.9511C6.81752 16.9366 6.56388 16.9342 6.30666 16.9439C6.21154 16.9475 6.13139 16.872 6.13139 16.7755V16.3113C6.13139 14.4884 7.59638 13.0101 9.40294 13.0101H15.2067C16.2487 13.0101 17.1765 13.5014 17.7753 14.2668C18.5698 14.1872 19.2726 13.9294 19.9797 13.3813C19.5095 12.5417 18.8019 11.8554 17.9488 11.4147C18.8252 9.48739 20.3452 5.89284 20.3111 4.2166C20.2668 2.06047 18.5309 1.21782 17.5929 1.06632C16.6633 0.865311 14.7431 1.01803 13.9295 3.01178C13.2667 4.63611 13.4402 8.84755 13.5706 10.8757H11.0396C11.17 8.84695 11.3435 4.63611 10.6807 3.01178C9.86654 1.01742 7.94632 0.865311 7.01672 1.06632C6.07815 1.21782 4.34217 2.06047 4.2985 4.2166C4.2644 5.89284 5.78503 9.4886 6.66139 11.4159C5.08155 12.232 4 13.8896 4 15.803V18.0726C4 18.7119 4.12084 19.3227 4.34038 19.8835C4.86559 19.0559 5.47815 18.363 6.13976 17.8052ZM15.3676 3.60875C15.6158 3.0818 15.9449 2.748 16.4599 2.62667C16.8667 2.53069 17.231 2.59407 17.2788 2.60313L17.2938 2.60796L17.3339 2.61339C17.3722 2.62063 17.7406 2.69307 18.0906 2.93391C18.5273 3.23511 18.745 3.66489 18.757 4.24799C18.766 4.67414 18.6021 5.82463 17.4063 8.73951C17.0653 9.57129 16.7207 10.3481 16.4551 10.93C16.2721 10.8836 15.9604 10.8757 15.9604 10.8757C15.9604 10.8757 17.7113 5.98278 17.2268 5.10331C16.6298 4.01982 15.1259 4.43812 15.1259 4.43812C15.1259 4.43812 15.1929 3.97998 15.3682 3.60815L15.3676 3.60875ZM8.98779 10.8757C8.98779 10.8757 9.09068 5.64657 8.2215 4.87756C7.03057 3.88643 5.93697 4.90834 5.93697 4.90834C5.86758 4.55945 5.85083 4.39285 5.85322 4.24859C5.86519 3.66549 6.08293 3.23511 6.51962 2.93451C6.86418 2.69669 7.22669 2.62305 7.27455 2.61399H7.2901L7.32898 2.60373C7.36667 2.59649 7.73636 2.52949 8.14971 2.62667C8.66476 2.748 9.02189 3.06912 9.24202 3.60875C9.40294 4.00292 9.66196 5.1353 9.59257 8.28921C9.57044 9.28518 9.52019 10.2208 9.47831 10.8757H8.98779Z" fill="black"/>
|
||||
<path d="M20.2692 13.9922C19.744 14.8198 19.1314 15.5127 18.4698 16.0705C18.1581 16.3342 17.8345 16.5672 17.5049 16.7707C17.4361 16.8129 17.4624 16.9204 17.5426 16.9246C17.792 16.9391 18.0457 16.9415 18.3029 16.9318C18.398 16.9282 18.4782 17.0037 18.4782 17.1002V17.5644C18.4782 19.3873 17.0132 20.8656 15.2066 20.8656H9.40289C8.36082 20.8656 7.43302 20.3743 6.83422 19.6089C6.03981 19.6886 5.33692 19.9463 4.62985 20.4944C5.46793 21.9901 7.05854 23 8.88305 23H15.7265C18.4231 23 20.6096 20.7938 20.6096 18.0727V15.8031C20.6096 15.1638 20.4887 14.553 20.2692 13.9922Z" fill="black"/>
|
||||
<path d="M9.58414 18.4662C10.2389 18.4662 10.7698 17.782 10.7698 16.9379C10.7698 16.0938 10.2389 15.4095 9.58414 15.4095C8.92933 15.4095 8.39851 16.0938 8.39851 16.9379C8.39851 17.782 8.92933 18.4662 9.58414 18.4662Z" fill="black"/>
|
||||
<path d="M15.026 18.4662C15.6808 18.4662 16.2116 17.782 16.2116 16.9379C16.2116 16.0938 15.6808 15.4095 15.026 15.4095C14.3712 15.4095 13.8403 16.0938 13.8403 16.9379C13.8403 17.782 14.3712 18.4662 15.026 18.4662Z" fill="black"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.0 KiB |
@ -1,165 +0,0 @@
|
||||
|
||||
const messageInput = document.getElementById('message-input');
|
||||
const inputContainer = document.getElementById('input-container');
|
||||
|
||||
const defaultHeight = 16;
|
||||
|
||||
function autoResizeTextarea() {
|
||||
const lineCount = (messageInput.value.match(/\n/g) || []).length + 1;
|
||||
messageInput.style.height = 'auto';
|
||||
messageInput.style.height = (lineCount <= 1 ? defaultHeight : messageInput.scrollHeight) + 'px';
|
||||
inputContainer.style.height = 'auto';
|
||||
inputContainer.style.height = messageInput.style.height + 25;
|
||||
}
|
||||
|
||||
messageInput.addEventListener('input', autoResizeTextarea);
|
||||
|
||||
autoResizeTextarea();
|
||||
|
||||
function initInputContainer() {
|
||||
const messageInput = document.getElementById('message-input');
|
||||
const sendButton = document.getElementById('send-button');
|
||||
const addContextButton = document.getElementById('add-context-button');
|
||||
const addCommandButton = document.getElementById('add-command-button');
|
||||
const popupContextMenu = document.getElementById('popupContextMenu');
|
||||
const popupCommandMenu = document.getElementById('popupCommandMenu');
|
||||
|
||||
let contextList = [];
|
||||
let commandList = [];
|
||||
|
||||
messageInput.addEventListener('keypress', function (e) {
|
||||
if (e.key === 'Enter') {
|
||||
if (e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
const message = messageInput.value.trim();
|
||||
if (message !== '') {
|
||||
sendButton.click();
|
||||
}
|
||||
} else if (!e.shiftKey) {
|
||||
e.preventDefault();
|
||||
messageInput.setRangeText('\n', messageInput.selectionStart, messageInput.selectionEnd, 'end');
|
||||
autoResizeTextarea();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sendButton.addEventListener('click', () => {
|
||||
const message = messageInput.value;
|
||||
if (message) {
|
||||
// Add the user's message to the chat UI
|
||||
addMessageToUI('user', message);
|
||||
|
||||
// Clear the input field
|
||||
messageInput.value = '';
|
||||
|
||||
// Process and send the message to the extension
|
||||
messageUtil.sendMessage({
|
||||
command: 'sendMessage',
|
||||
text: message
|
||||
});
|
||||
autoResizeTextarea();
|
||||
}
|
||||
});
|
||||
|
||||
addContextButton.addEventListener('click', (event) => {
|
||||
popupContextMenu.style.display = popupContextMenu.style.display === 'block' ? 'none' : 'block';
|
||||
// 设置弹出菜单的位置
|
||||
popupContextMenu.style.left = event.pageX + 'px';
|
||||
popupContextMenu.style.top = event.pageY + 'px';
|
||||
});
|
||||
|
||||
addCommandButton.addEventListener('click', (event) => {
|
||||
popupCommandMenu.style.display = popupCommandMenu.style.display === 'block' ? 'none' : 'block';
|
||||
// 设置弹出菜单的位置
|
||||
popupCommandMenu.style.left = event.pageX + 'px';
|
||||
popupCommandMenu.style.top = event.pageY + 'px';
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('file_select', (message) => {
|
||||
addFileToMessageInput(message.filePath);
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('code_select', (message) => {
|
||||
addCodeToMessageInput(message.codeBlock);
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('appendContext', (message) => {
|
||||
addCodeToMessageInput(message.context);
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('regContextList', (message) => {
|
||||
contextList = message.result;
|
||||
|
||||
const menuItems = [];
|
||||
for (let i = 0; i < contextList.length; i++) {
|
||||
menuItems.push({
|
||||
text: contextList[i].name,
|
||||
href: contextList[i].name
|
||||
});
|
||||
}
|
||||
|
||||
menuItems.forEach(item => {
|
||||
const menuItem = document.createElement('a');
|
||||
menuItem.textContent = 'add ' + item.text;
|
||||
menuItem.href = item.text;
|
||||
|
||||
popupContextMenu.appendChild(menuItem);
|
||||
|
||||
// 为每个菜单项添加点击事件监听器
|
||||
menuItem.addEventListener('click', (event) => {
|
||||
// 阻止<a>标签的默认行为(例如导航到链接)
|
||||
event.preventDefault();
|
||||
// 在此处定义点击处理逻辑
|
||||
messageUtil.sendMessage({ command: 'addContext', selected: item.href })
|
||||
// 隐藏弹出菜单
|
||||
popupContextMenu.style.display = 'none';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('regCommandList', (message) => {
|
||||
commandList = message.result;
|
||||
|
||||
const menuItems = [];
|
||||
for (let i = 0; i < commandList.length; i++) {
|
||||
menuItems.push({
|
||||
text: commandList[i].pattern,
|
||||
href: commandList[i].pattern
|
||||
});
|
||||
}
|
||||
|
||||
menuItems.forEach(item => {
|
||||
const menuItem = document.createElement('a');
|
||||
menuItem.textContent = item.text;
|
||||
menuItem.href = item.href;
|
||||
|
||||
popupCommandMenu.appendChild(menuItem);
|
||||
|
||||
// 为每个菜单项添加点击事件监听器
|
||||
menuItem.addEventListener('click', (event) => {
|
||||
// 阻止<a>标签的默认行为(例如导航到链接)
|
||||
event.preventDefault();
|
||||
// 在此处定义点击处理逻辑
|
||||
addCodeToMessageInput("/" + item.href);
|
||||
// 隐藏弹出菜单
|
||||
popupCommandMenu.style.display = 'none';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
messageUtil.sendMessage({ command: 'regContextList' });
|
||||
messageUtil.sendMessage({ command: 'regCommandList' });
|
||||
}
|
||||
|
||||
function addFileToMessageInput(filePath) {
|
||||
const messageInput = document.getElementById('message-input');
|
||||
const formattedPath = `[context|${filePath}] `;
|
||||
messageInput.value = formattedPath + messageInput.value;
|
||||
messageInput.focus();
|
||||
}
|
||||
|
||||
function addCodeToMessageInput(codeBlock) {
|
||||
const messageInput = document.getElementById('message-input');
|
||||
messageInput.value += "\n" + codeBlock + "\n";
|
||||
messageInput.focus();
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// main.js
|
||||
|
||||
(function () {
|
||||
initMessageContainer();
|
||||
initInputContainer();
|
||||
initContextMenu();
|
||||
|
||||
window.addEventListener('message', (event) => {
|
||||
const message = event.data;
|
||||
messageUtil.handleMessage(message)
|
||||
});
|
||||
})();
|
||||
|
@ -1,5 +0,0 @@
|
||||
|
||||
function markdownRender(content) {
|
||||
const md = new markdownit();
|
||||
return md.render(content);
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
|
||||
function requestHistoryMessages() {
|
||||
// Send a message to the extension with the 'historyMessages' command
|
||||
messageUtil.sendMessage({
|
||||
command: 'historyMessages',
|
||||
});
|
||||
}
|
||||
|
||||
function loadHistoryMessages(entries) {
|
||||
entries.forEach((entry) => {
|
||||
addMessageToUI('user', entry.message);
|
||||
addMessageToUI('bot', entry.response);
|
||||
});
|
||||
}
|
||||
|
||||
function initMessageContainer() {
|
||||
// Register message handlers for receiving messages from the extension
|
||||
messageUtil.registerHandler('receiveMessage', (message) => {
|
||||
// Add the received message to the chat UI as a bot message
|
||||
addMessageToUI('bot', message.text);
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('receiveMessagePartial', (message) => {
|
||||
// Add the received message to the chat UI as a bot message
|
||||
addMessageToUI('bot', message.text, true);
|
||||
});
|
||||
|
||||
messageUtil.registerHandler('loadHistoryMessages', (message) => {
|
||||
loadHistoryMessages(message.entries);
|
||||
});
|
||||
|
||||
// Request history messages when the web view is created and shown
|
||||
requestHistoryMessages();
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
|
||||
const vscode_api = acquireVsCodeApi();
|
||||
|
||||
class MessageUtil {
|
||||
constructor() {
|
||||
this.handlers = {};
|
||||
}
|
||||
|
||||
// Register a message handler for a specific message type
|
||||
registerHandler(messageType, handler) {
|
||||
if (!this.handlers[messageType]) {
|
||||
this.handlers[messageType] = [];
|
||||
}
|
||||
this.handlers[messageType].push(handler);
|
||||
}
|
||||
|
||||
// Unregister a message handler for a specific message type
|
||||
unregisterHandler(messageType, handler) {
|
||||
if (this.handlers[messageType]) {
|
||||
this.handlers[messageType] = this.handlers[messageType].filter(
|
||||
(h) => h !== handler
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle a received message
|
||||
handleMessage(message) {
|
||||
console.log("handleMessage", message)
|
||||
const handlers = this.handlers[message.command];
|
||||
if (handlers) {
|
||||
handlers.forEach((handler) => handler(message));
|
||||
}
|
||||
}
|
||||
|
||||
// Send a message to the VSCode API
|
||||
sendMessage(message) {
|
||||
console.log("sendMessage", message)
|
||||
vscode_api.postMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
// Export the MessageUtil class as a module
|
||||
const messageUtil = new MessageUtil();
|
@ -1,26 +0,0 @@
|
||||
function initInputResizing() {
|
||||
// Create a handle for resizing the input container
|
||||
const inputContainer = document.getElementById('input-container')
|
||||
const inputResizeHandle = document.getElementById('input-resize-handle')
|
||||
|
||||
// Add an event listener for mouse down on the resize handle
|
||||
inputResizeHandle.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const startY = e.clientY;
|
||||
const startHeight = inputContainer.style.height ? parseInt(inputContainer.style.height) : parseInt(getComputedStyle(inputContainer).height);
|
||||
|
||||
window.addEventListener('mousemove', resizeInput);
|
||||
window.addEventListener('mouseup', stopResizeInput);
|
||||
|
||||
function resizeInput(e) {
|
||||
const delta = startY - e.clientY;
|
||||
inputContainer.style.height = `${startHeight + delta}px`;
|
||||
}
|
||||
|
||||
function stopResizeInput() {
|
||||
window.removeEventListener('mousemove', resizeInput);
|
||||
window.removeEventListener('mouseup', stopResizeInput);
|
||||
}
|
||||
});
|
||||
}
|
Before Width: | Height: | Size: 3.3 KiB |
@ -4,7 +4,7 @@ import { createRoot } from 'react-dom/client';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import { Provider } from 'react-redux';
|
||||
import App from '@/views/App';
|
||||
import { store } from '@/views/store';
|
||||
import { store } from '@/views/reducers/store';
|
||||
|
||||
const container = document.getElementById('app')!;
|
||||
const root = createRoot(container); // createRoot(container!) if you use TypeScript
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
AppShell,
|
||||
useMantineTheme,
|
||||
} from '@mantine/core';
|
||||
import ChatPanel from '@/views/ChatPanel';
|
||||
import ChatPanel from '@/views/pages/ChatPanel';
|
||||
|
||||
export default function App() {
|
||||
const theme = useMantineTheme();
|
||||
|
@ -3,7 +3,7 @@ import React from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { okaidia } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||
import CodeButtons from "@/views/CodeButtons";
|
||||
import CodeButtons from "./CodeButtons";
|
||||
|
||||
const CodeBlock = (props: any) => {
|
||||
const { messageText, messageType } = props;
|
@ -3,7 +3,7 @@ import React, { useEffect } from "react";
|
||||
import { keyframes } from "@emotion/react";
|
||||
import { Container, Text } from "@mantine/core";
|
||||
import { useAppDispatch, useAppSelector } from '@/views/hooks';
|
||||
import CodeBlock from "@/views/CodeBlock";
|
||||
import CodeBlock from "@/views/components/CodeBlock";
|
||||
|
||||
import {
|
||||
newMessage,
|
||||
@ -12,7 +12,7 @@ import {
|
||||
selectCurrentMessage,
|
||||
selecLastMessage,
|
||||
selectResponsed,
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
const MessageBlink = () => {
|
||||
const responsed = useAppSelector(selectResponsed);
|
@ -6,7 +6,7 @@ import { useAppDispatch, useAppSelector } from '@/views/hooks';
|
||||
import {
|
||||
selectContexts,
|
||||
removeContext,
|
||||
} from './inputSlice';
|
||||
} from '@/views/reducers/inputSlice';
|
||||
|
||||
const InputContexts = () => {
|
||||
const dispatch = useAppDispatch();
|
@ -2,10 +2,10 @@ import { useMantineTheme, Flex, Stack, Accordion, Box, ActionIcon, ScrollArea, C
|
||||
import { useListState, useResizeObserver } from "@mantine/hooks";
|
||||
import { IconGitBranch, IconBook, IconX, IconSquareRoundedPlus, IconSend } from "@tabler/icons-react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IconGitBranchChecked, IconShellCommand, IconMouseRightClick } from "./Icons";
|
||||
import { IconGitBranchChecked, IconShellCommand, IconMouseRightClick } from "@/views/components/ChatIcons";
|
||||
import messageUtil from '@/util/MessageUtil';
|
||||
import { useAppDispatch, useAppSelector } from '@/views/hooks';
|
||||
import InputContexts from '@/views/InputContexts';
|
||||
import InputContexts from './InputContexts';
|
||||
|
||||
import {
|
||||
setValue,
|
||||
@ -23,12 +23,12 @@ import {
|
||||
closeMenu,
|
||||
fetchContextMenus,
|
||||
fetchCommandMenus,
|
||||
} from './inputSlice';
|
||||
} from '@/views/reducers/inputSlice';
|
||||
import {
|
||||
selectGenerating,
|
||||
newMessage,
|
||||
startGenerating,
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
const InputMessage = (props: any) => {
|
||||
const { width } = props;
|
@ -1,13 +1,13 @@
|
||||
|
||||
import { Center, Text, Accordion, Box, Stack, Container, Divider } from "@mantine/core";
|
||||
import React from "react";
|
||||
import CodeBlock from "@/views/CodeBlock";
|
||||
import MessageHeader from "@/views/MessageHeader";
|
||||
import CodeBlock from "@/views/components/CodeBlock";
|
||||
import MessageHeader from "@/views/components/MessageHeader";
|
||||
|
||||
import { useAppSelector } from '@/views/hooks';
|
||||
import {
|
||||
selectMessages,
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
|
||||
const MessageContext = (props: any) => {
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
@ -2,9 +2,9 @@ import React from "react";
|
||||
import { Text, Flex, Avatar, ActionIcon, Tooltip, CopyButton, SimpleGrid } from "@mantine/core";
|
||||
|
||||
// @ts-ignore
|
||||
import SvgAvatarDevChat from '@/views/avatar_devchat.svg';
|
||||
import SvgAvatarDevChat from './avatar_devchat.svg';
|
||||
// @ts-ignore
|
||||
import SvgAvatarUser from '@/views/avatar_spaceman.png';
|
||||
import SvgAvatarUser from './avatar_spaceman.png';
|
||||
import { IconCheck, IconCopy, Icon360, IconEdit, IconTrash } from "@tabler/icons-react";
|
||||
|
||||
import { useAppDispatch } from '@/views/hooks';
|
||||
@ -12,12 +12,12 @@ import { useAppDispatch } from '@/views/hooks';
|
||||
import {
|
||||
setContexts,
|
||||
setValue,
|
||||
} from './inputSlice';
|
||||
} from '@/views/reducers/inputSlice';
|
||||
|
||||
import {
|
||||
deleteMessage,
|
||||
popMessage
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
const MessageHeader = (props: any) => {
|
||||
const { item, showEdit = false, showDelete = true } = props;
|
@ -6,7 +6,7 @@ import { useAppDispatch } from '@/views/hooks';
|
||||
|
||||
import {
|
||||
reGenerating,
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
const RegenerationButton = () => {
|
||||
const dispatch = useAppDispatch();
|
@ -6,7 +6,7 @@ import { useAppDispatch } from '@/views/hooks';
|
||||
|
||||
import {
|
||||
stopGenerating,
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
const StopButton = () => {
|
||||
const dispatch = useAppDispatch();
|
@ -1,5 +1,5 @@
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
import type { RootState, AppDispatch } from '@/views/store';
|
||||
import type { RootState, AppDispatch } from '@/views/reducers/store';
|
||||
|
||||
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
@ -1,13 +1,13 @@
|
||||
import * as React from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Alert, Center, Container, Stack, px } from '@mantine/core';
|
||||
import { ActionIcon, Alert, Center, Container, Stack, px } from '@mantine/core';
|
||||
import { ScrollArea } from '@mantine/core';
|
||||
import { useResizeObserver, useTimeout, useViewportSize } from '@mantine/hooks';
|
||||
import messageUtil from '@/util/MessageUtil';
|
||||
import { useAppDispatch, useAppSelector } from '@/views/hooks';
|
||||
import CurrentMessage from "@/views/CurrentMessage";
|
||||
import StopButton from '@/views/StopButton';
|
||||
import RegenerationButton from '@/views/RegenerationButton';
|
||||
import CurrentMessage from "@/views/components/CurrentMessage";
|
||||
import StopButton from '@/views/components/StopButton';
|
||||
import RegenerationButton from '@/views/components/RegenerationButton';
|
||||
|
||||
import {
|
||||
stopGenerating,
|
||||
@ -23,11 +23,12 @@ import {
|
||||
fetchHistoryMessages,
|
||||
newMessage,
|
||||
startSystemMessage,
|
||||
} from './chatSlice';
|
||||
} from '@/views/reducers/chatSlice';
|
||||
|
||||
import InputMessage from './InputMessage';
|
||||
import MessageContainer from './MessageContainer';
|
||||
import { clearContexts, setValue } from './inputSlice';
|
||||
import InputMessage from '@/views/components/InputMessage';
|
||||
import MessageContainer from '../components/MessageContainer';
|
||||
import { clearContexts, setValue } from '@/views/reducers/inputSlice';
|
||||
import { IconCircleArrowDown, IconCircleArrowDownFilled } from '@tabler/icons-react';
|
||||
|
||||
|
||||
const chatPanel = () => {
|
||||
@ -108,8 +109,13 @@ const chatPanel = () => {
|
||||
color: 'var(--vscode-editor-foreground)',
|
||||
minWidth: 240
|
||||
}}>
|
||||
{!isBottom && <ActionIcon
|
||||
onClick={() => { scrollToBottom() }}
|
||||
title='Bottom'
|
||||
variant='transparent' sx={{ position: "absolute", bottom: 60, right: 20, zIndex: 999 }}>
|
||||
<IconCircleArrowDownFilled size="1.125rem" />
|
||||
</ActionIcon>}
|
||||
<ScrollArea
|
||||
type="never"
|
||||
sx={{
|
||||
height: generating ? height - px('8rem') : height - px('5rem'),
|
||||
width: chatContainerRect.width,
|
@ -1,6 +1,6 @@
|
||||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import messageUtil from '@/util/MessageUtil';
|
||||
import type { RootState } from '@/views/store';
|
||||
import type { RootState } from '@/views/reducers/store';
|
||||
|
||||
export const fetchHistoryMessages = createAsyncThunk<{ pageIndex: number, entries: [] }, { pageIndex: number }>('input/fetchHistoryMessages', async (params) => {
|
||||
const { pageIndex } = params;
|
@ -1,5 +1,5 @@
|
||||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import type { RootState } from '@/views/store';
|
||||
import type { RootState } from '@/views/reducers/store';
|
||||
import messageUtil from '@/util/MessageUtil';
|
||||
|
||||
export const fetchContextMenus = createAsyncThunk('input/fetchContextMenus', async () => {
|
@ -1,6 +1,6 @@
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
import inputReducer from '@/views/inputSlice';
|
||||
import chatReducer from '@/views/chatSlice';
|
||||
import inputReducer from '@/views/reducers/inputSlice';
|
||||
import chatReducer from '@/views/reducers/chatSlice';
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
@ -168,11 +168,6 @@ const webviewConfig = {
|
||||
filename: 'welcome.html',
|
||||
chunks: ['welcome']
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{ from: 'assets', to: 'assets' },
|
||||
],
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
|