diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java index 1ee1b392..bdedddaf 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java @@ -22,13 +22,14 @@ import ee.carlrobert.codegpt.conversations.Conversation; import ee.carlrobert.codegpt.conversations.ConversationService; import ee.carlrobert.codegpt.conversations.message.Message; import ee.carlrobert.codegpt.telemetry.TelemetryAction; +import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.CopyAction; import ee.carlrobert.codegpt.toolwindow.chat.ui.ChatMessageResponseBody; import ee.carlrobert.codegpt.toolwindow.chat.ui.ChatToolWindowScrollablePanel; -import ee.carlrobert.codegpt.toolwindow.chat.ui.ResponsePanel; -import ee.carlrobert.codegpt.toolwindow.chat.ui.UserMessagePanel; import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.TotalTokensDetails; import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.TotalTokensPanel; import ee.carlrobert.codegpt.toolwindow.ui.ChatToolWindowLandingPanel; +import ee.carlrobert.codegpt.toolwindow.ui.ResponseMessagePanel; +import ee.carlrobert.codegpt.toolwindow.ui.UserMessagePanel; import ee.carlrobert.codegpt.ui.OverlayUtil; import ee.carlrobert.codegpt.ui.textarea.AppliedActionInlay; import ee.carlrobert.codegpt.ui.textarea.UserInputPanel; @@ -174,12 +175,14 @@ public class ChatToolWindowTabPanel implements Disposable { totalTokensPanel.updateReferencedFilesTokens(callParameters.getReferencedFiles()); } - var responsePanel = createResponsePanel(callParameters); - var messagePanel = toolWindowScrollablePanel.addMessage(message.getId()); - messagePanel.add(new UserMessagePanel(project, message, this)); - messagePanel.add(responsePanel); + var userMessagePanel = createUserMessagePanel(message, callParameters); + var responseMessagePanel = createResponseMessagePanel(callParameters); - call(callParameters, responsePanel); + var messagePanel = toolWindowScrollablePanel.addMessage(message.getId()); + messagePanel.add(userMessagePanel); + messagePanel.add(responseMessagePanel); + + call(callParameters, responseMessagePanel, userMessagePanel); }); } @@ -193,29 +196,39 @@ public class ChatToolWindowTabPanel implements Disposable { it -> it.getReferencedFilePaths() != null && !it.getReferencedFilePaths().isEmpty()); } - private ResponsePanel createResponsePanel(ChatCompletionParameters callParameters) { + private UserMessagePanel createUserMessagePanel( + Message message, + ChatCompletionParameters callParameters) { + var panel = new UserMessagePanel(project, message, this); + panel.addCopyAction(() -> CopyAction.copyToClipboard(message.getPrompt())); + panel.addReloadAction(() -> reloadMessage(callParameters, panel)); + panel.addDeleteAction(() -> removeMessage(message.getId(), conversation)); + return panel; + } + + private ResponseMessagePanel createResponseMessagePanel(ChatCompletionParameters callParameters) { var message = callParameters.getMessage(); var fileContextIncluded = hasReferencedFilePaths(message) || hasReferencedFilePaths(conversation); - return new ResponsePanel() - .withReloadAction(() -> reloadMessage(callParameters)) - .withDeleteAction(() -> removeMessage(message.getId(), conversation)) - .addContent( - new ChatMessageResponseBody( - project, - true, - false, - message.isWebSearchIncluded(), - fileContextIncluded || message.getDocumentationDetails() != null, - this)); + var panel = new ResponseMessagePanel(); + panel.addCopyAction(() -> CopyAction.copyToClipboard(message.getResponse())); + panel.addContent(new ChatMessageResponseBody( + project, + true, + false, + message.isWebSearchIncluded(), + fileContextIncluded || message.getDocumentationDetails() != null, + this)); + return panel; } - private void reloadMessage(ChatCompletionParameters prevParameters) { + private void reloadMessage(ChatCompletionParameters prevParameters, + UserMessagePanel userMessagePanel) { var prevMessage = prevParameters.getMessage(); - ResponsePanel responsePanel = null; + ResponseMessagePanel responsePanel = null; try { - responsePanel = toolWindowScrollablePanel.getMessageResponsePanel(prevMessage.getId()); + responsePanel = toolWindowScrollablePanel.getResponseMessagePanel(prevMessage.getId()); ((ChatMessageResponseBody) responsePanel.getContent()).clear(); toolWindowScrollablePanel.update(); } catch (Exception e) { @@ -226,7 +239,7 @@ public class ChatToolWindowTabPanel implements Disposable { if (responsePanel != null) { prevMessage.setResponse(""); conversationService.saveMessage(conversation, prevMessage); - call(prevParameters.toBuilder().retry(true).build(), responsePanel); + call(prevParameters.toBuilder().retry(true).build(), responsePanel, userMessagePanel); } totalTokensPanel.updateConversationTokens(conversation); @@ -253,8 +266,11 @@ public class ChatToolWindowTabPanel implements Disposable { totalTokensPanel.updateConversationTokens(conversation); } - private void call(ChatCompletionParameters callParameters, ResponsePanel responsePanel) { - var responseContainer = (ChatMessageResponseBody) responsePanel.getContent(); + private void call( + ChatCompletionParameters callParameters, + ResponseMessagePanel responseMessagePanel, + UserMessagePanel userMessagePanel) { + var responseContainer = (ChatMessageResponseBody) responseMessagePanel.getContent(); if (!CompletionRequestService.isRequestAllowed()) { responseContainer.displayMissingCredential(); @@ -264,15 +280,18 @@ public class ChatToolWindowTabPanel implements Disposable { requestHandler = new ToolwindowChatCompletionRequestHandler( new ToolWindowCompletionResponseEventListener( conversationService, - responsePanel, + userMessagePanel, + responseMessagePanel, totalTokensPanel, userInputPanel) { @Override public void handleTokensExceededPolicyAccepted() { - call(callParameters, responsePanel); + call(callParameters, responseMessagePanel, userMessagePanel); } }); userInputPanel.setSubmitEnabled(false); + userMessagePanel.disableActions(List.of("RELOAD", "DELETE")); + responseMessagePanel.disableActions(List.of("COPY")); requestHandler.call(callParameters); } @@ -337,30 +356,41 @@ public class ChatToolWindowTabPanel implements Disposable { private void displayConversation() { clearWindow(); conversation.getMessages().forEach(message -> { - var response = message.getResponse() == null ? "" : message.getResponse(); - var messageResponseBody = - new ChatMessageResponseBody(project, this).withResponse(response); - - messageResponseBody.hideCaret(); - - var userMessagePanel = new UserMessagePanel(project, message, this); - var imageFilePath = message.getImageFilePath(); - if (imageFilePath != null && !imageFilePath.isEmpty()) { - userMessagePanel.displayImage(imageFilePath); - } - var messagePanel = toolWindowScrollablePanel.addMessage(message.getId()); - messagePanel.add(userMessagePanel); - messagePanel.add(new ResponsePanel() - .withReloadAction(() -> reloadMessage( - ChatCompletionParameters.builder(conversation, message) - .conversationType(ConversationType.DEFAULT) - .build())) - .withDeleteAction(() -> removeMessage(message.getId(), conversation)) - .addContent(messageResponseBody)); + messagePanel.add(getUserMessagePanel(message)); + messagePanel.add(getResponseMessagePanel(message)); }); } + private UserMessagePanel getUserMessagePanel(Message message) { + var userMessagePanel = new UserMessagePanel(project, message, this); + userMessagePanel.addCopyAction(() -> CopyAction.copyToClipboard(message.getPrompt())); + userMessagePanel.addReloadAction(() -> reloadMessage( + ChatCompletionParameters.builder(conversation, message) + .conversationType(ConversationType.DEFAULT) + .build(), + userMessagePanel)); + userMessagePanel.addDeleteAction(() -> removeMessage(message.getId(), conversation)); + var imageFilePath = message.getImageFilePath(); + if (imageFilePath != null && !imageFilePath.isEmpty()) { + userMessagePanel.displayImage(imageFilePath); + } + return userMessagePanel; + } + + private ResponseMessagePanel getResponseMessagePanel(Message message) { + var response = message.getResponse() == null ? "" : message.getResponse(); + var messageResponseBody = + new ChatMessageResponseBody(project, this).withResponse(response); + + messageResponseBody.hideCaret(); + + var responseMessagePanel = new ResponseMessagePanel(); + responseMessagePanel.addContent(messageResponseBody); + responseMessagePanel.addCopyAction(() -> CopyAction.copyToClipboard(message.getResponse())); + return responseMessagePanel; + } + private JPanel createRootPanel() { var rootPanel = new JPanel(new BorderLayout()); rootPanel.add(createScrollPaneWithSmartScroller(toolWindowScrollablePanel), diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ResponseNodeRenderer.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ResponseNodeRenderer.java index 45c2b071..d3c1eaf3 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ResponseNodeRenderer.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ResponseNodeRenderer.java @@ -37,9 +37,7 @@ public class ResponseNodeRenderer implements NodeRenderer { } private void renderHeading(Heading node, NodeRendererContext context, HtmlWriter html) { - if (node.getLevel() == 3) { - html.attr("style", "margin-top: 4px; margin-bottom: 4px;"); - } + html.attr("style", "margin-top: 8px; margin-bottom: 4px;"); context.delegateRender(); } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ToolWindowCompletionResponseEventListener.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ToolWindowCompletionResponseEventListener.java index ad9207e1..bd04e055 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ToolWindowCompletionResponseEventListener.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ToolWindowCompletionResponseEventListener.java @@ -13,8 +13,9 @@ import ee.carlrobert.codegpt.conversations.message.Message; import ee.carlrobert.codegpt.events.CodeGPTEvent; import ee.carlrobert.codegpt.telemetry.TelemetryAction; import ee.carlrobert.codegpt.toolwindow.chat.ui.ChatMessageResponseBody; -import ee.carlrobert.codegpt.toolwindow.chat.ui.ResponsePanel; import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.TotalTokensPanel; +import ee.carlrobert.codegpt.toolwindow.ui.ResponseMessagePanel; +import ee.carlrobert.codegpt.toolwindow.ui.UserMessagePanel; import ee.carlrobert.codegpt.ui.OverlayUtil; import ee.carlrobert.codegpt.ui.textarea.UserInputPanel; import ee.carlrobert.llm.client.openai.completion.ErrorDetails; @@ -31,7 +32,8 @@ abstract class ToolWindowCompletionResponseEventListener implements private final StringBuilder messageBuilder = new StringBuilder(); private final EncodingManager encodingManager; private final ConversationService conversationService; - private final ResponsePanel responsePanel; + private final ResponseMessagePanel responsePanel; + private final UserMessagePanel userMessagePanel; private final ChatMessageResponseBody responseContainer; private final TotalTokensPanel totalTokensPanel; private final UserInputPanel textArea; @@ -43,11 +45,13 @@ abstract class ToolWindowCompletionResponseEventListener implements public ToolWindowCompletionResponseEventListener( ConversationService conversationService, - ResponsePanel responsePanel, + UserMessagePanel userMessagePanel, + ResponseMessagePanel responsePanel, TotalTokensPanel totalTokensPanel, UserInputPanel textArea) { this.encodingManager = EncodingManager.getInstance(); this.conversationService = conversationService; + this.userMessagePanel = userMessagePanel; this.responsePanel = responsePanel; this.responseContainer = (ChatMessageResponseBody) responsePanel.getContent(); this.totalTokensPanel = totalTokensPanel; @@ -89,7 +93,7 @@ abstract class ToolWindowCompletionResponseEventListener implements } } finally { LOG.error(error.getMessage(), ex); - responsePanel.enableActions(); + responsePanel.enableAllActions(true); stopStreaming(responseContainer); } }); @@ -119,7 +123,7 @@ abstract class ToolWindowCompletionResponseEventListener implements ApplicationManager.getApplication().invokeLater(() -> { try { - responsePanel.enableActions(); + responsePanel.enableAllActions(true); if (!streamResponseReceived && !fullMessage.isEmpty()) { responseContainer.withResponse(fullMessage); } @@ -156,6 +160,8 @@ abstract class ToolWindowCompletionResponseEventListener implements private void stopStreaming(ChatMessageResponseBody responseContainer) { stopped = true; textArea.setSubmitEnabled(true); + userMessagePanel.enableAllActions(true); + responsePanel.enableAllActions(true); responseContainer.hideCaret(); } } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/CopyAction.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/CopyAction.java index 15618a32..b82059f8 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/CopyAction.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/editor/actions/CopyAction.java @@ -8,7 +8,6 @@ import ee.carlrobert.codegpt.actions.ActionType; import ee.carlrobert.codegpt.actions.TrackableAction; import ee.carlrobert.codegpt.ui.OverlayUtil; import java.awt.Toolkit; -import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.StringSelection; import java.awt.event.MouseEvent; import org.jetbrains.annotations.NotNull; @@ -19,8 +18,8 @@ public class CopyAction extends TrackableAction { public CopyAction(@NotNull Editor toolwindowEditor) { super( - CodeGPTBundle.get("shared.copy"), - CodeGPTBundle.get("toolwindow.chat.editor.action.copy.description"), + CodeGPTBundle.get("shared.copyCode"), + CodeGPTBundle.get("shared.copyToClipboard"), Actions.Copy, ActionType.COPY_CODE); this.toolwindowEditor = toolwindowEditor; @@ -28,17 +27,24 @@ public class CopyAction extends TrackableAction { @Override public void handleAction(@NotNull AnActionEvent event) { - StringSelection stringSelection = new StringSelection(toolwindowEditor.getDocument().getText()); - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - clipboard.setContents(stringSelection, null); + copyToClipboard(toolwindowEditor.getDocument().getText()); + showCopyBalloon(event); + } + public static void copyToClipboard(String text) { + Toolkit.getDefaultToolkit() + .getSystemClipboard() + .setContents(new StringSelection(text), null); + } + + public static void showCopyBalloon(AnActionEvent event) { var mouseEvent = (MouseEvent) event.getInputEvent(); if (mouseEvent != null) { var locationOnScreen = mouseEvent.getLocationOnScreen(); locationOnScreen.y = locationOnScreen.y - 16; OverlayUtil.showInfoBalloon( - CodeGPTBundle.get("toolwindow.chat.editor.action.copy.success"), + CodeGPTBundle.get("shared.copiedToClipboard"), locationOnScreen); } } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java index a001c8b7..53065f5a 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java @@ -9,6 +9,7 @@ import com.intellij.icons.AllIcons; import com.intellij.icons.AllIcons.General; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionPlaces; +import com.intellij.openapi.actionSystem.ActionUpdateThread; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; @@ -37,12 +38,15 @@ import ee.carlrobert.codegpt.settings.GeneralSettingsConfigurable; import ee.carlrobert.codegpt.telemetry.TelemetryAction; import ee.carlrobert.codegpt.toolwindow.chat.StreamParser; import ee.carlrobert.codegpt.toolwindow.chat.editor.ResponseEditorPanel; +import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.CopyAction; import ee.carlrobert.codegpt.toolwindow.ui.ResponseBodyProgressPanel; import ee.carlrobert.codegpt.toolwindow.ui.WebpageList; +import ee.carlrobert.codegpt.ui.OverlayUtil; import ee.carlrobert.codegpt.ui.UIUtil; import ee.carlrobert.codegpt.util.EditorUtil; import ee.carlrobert.codegpt.util.MarkdownUtil; import java.awt.BorderLayout; +import java.awt.event.MouseEvent; import java.util.Objects; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; @@ -331,9 +335,16 @@ public class ChatMessageResponseBody extends JPanel { CodeGPTBundle.get("shared.copy"), CodeGPTBundle.get("shared.copyToClipboard"), AllIcons.Actions.Copy) { + @Override - public void actionPerformed(@NotNull AnActionEvent e) { + public @NotNull ActionUpdateThread getActionUpdateThread() { + return ActionUpdateThread.EDT; + } + + @Override + public void actionPerformed(@NotNull AnActionEvent event) { textPane.copy(); + CopyAction.showCopyBalloon(event); } @Override diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatToolWindowScrollablePanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatToolWindowScrollablePanel.java index 81108fdd..ca017608 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatToolWindowScrollablePanel.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatToolWindowScrollablePanel.java @@ -12,6 +12,7 @@ import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey; import ee.carlrobert.codegpt.settings.GeneralSettings; import ee.carlrobert.codegpt.settings.service.ServiceType; import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTServiceConfigurable; +import ee.carlrobert.codegpt.toolwindow.ui.ResponseMessagePanel; import ee.carlrobert.codegpt.ui.UIUtil; import ee.carlrobert.codegpt.util.ApplicationUtil; import java.util.Arrays; @@ -36,35 +37,35 @@ public class ChatToolWindowScrollablePanel extends ScrollablePanel { if (GeneralSettings.isSelected(ServiceType.CODEGPT) && !CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.CODEGPT_API_KEY)) { - var panel = new ResponsePanel() - .addContent(UIUtil.createTextPane(""" - -
- It looks like you haven't configured your API key yet. Visit CodeGPT settings to do so. -
-- Don't have an account? Sign up to get the most out of CodeGPT. -
- """, - false, - event -> { - if (ACTIVATED.equals(event.getEventType()) - && "#OPEN_SETTINGS".equals(event.getDescription())) { - ShowSettingsUtil.getInstance().showSettingsDialog( - ApplicationUtil.findCurrentProject(), - CodeGPTServiceConfigurable.class); - } else { - UIUtil.handleHyperlinkClicked(event); - } - })); + var panel = new ResponseMessagePanel(); + panel.addContent(UIUtil.createTextPane(""" + ++ It looks like you haven't configured your API key yet. Visit CodeGPT settings to do so. +
++ Don't have an account? Sign up to get the most out of CodeGPT. +
+ """, + false, + event -> { + if (ACTIVATED.equals(event.getEventType()) + && "#OPEN_SETTINGS".equals(event.getDescription())) { + ShowSettingsUtil.getInstance().showSettingsDialog( + ApplicationUtil.findCurrentProject(), + CodeGPTServiceConfigurable.class); + } else { + UIUtil.handleHyperlinkClicked(event); + } + })); panel.setBorder(JBUI.Borders.customLine(JBColor.border(), 1, 0, 0, 0)); add(panel); } } - public ResponsePanel getMessageResponsePanel(UUID messageId) { - return (ResponsePanel) Arrays.stream(visibleMessagePanels.get(messageId).getComponents()) - .filter(ResponsePanel.class::isInstance) + public ResponseMessagePanel getResponseMessagePanel(UUID messageId) { + return (ResponseMessagePanel) Arrays.stream(visibleMessagePanels.get(messageId).getComponents()) + .filter(ResponseMessagePanel.class::isInstance) .findFirst().orElseThrow(); } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ResponsePanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ResponsePanel.java deleted file mode 100644 index 235ec7d8..00000000 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ResponsePanel.java +++ /dev/null @@ -1,150 +0,0 @@ -package ee.carlrobert.codegpt.toolwindow.chat.ui; - -import com.intellij.icons.AllIcons.Actions; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.components.JBLabel; -import com.intellij.util.ui.JBFont; -import com.intellij.util.ui.JBUI; -import ee.carlrobert.codegpt.CodeGPTBundle; -import ee.carlrobert.codegpt.Icons; -import ee.carlrobert.codegpt.ui.IconActionButton; -import java.awt.BorderLayout; -import java.awt.FlowLayout; -import javax.swing.Box; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class ResponsePanel extends JPanel { - - private final Header header; - private final Body body; - - public ResponsePanel() { - super(new BorderLayout()); - header = new Header(); - body = new Body(); - add(header, BorderLayout.NORTH); - add(body, BorderLayout.CENTER); - } - - public void enableActions() { - header.enableActions(true); - } - - public ResponsePanel withReloadAction(Runnable onReload) { - header.addReloadAction(onReload); - return this; - } - - public ResponsePanel withDeleteAction(Runnable onDelete) { - header.addDeleteAction(onDelete); - return this; - } - - public ResponsePanel addContent(JComponent content) { - body.addContent(content); - return this; - } - - public void updateContent(JComponent content) { - body.updateContent(content); - } - - public JComponent getContent() { - return body.getContent(); - } - - static class Header extends JPanel { - - private final JPanel iconsWrapper; - - Header() { - super(new BorderLayout()); - setBorder(JBUI.Borders.empty(12, 8, 4, 8)); - add(getIconLabel(), BorderLayout.LINE_START); - - iconsWrapper = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0)); - iconsWrapper.setBackground(getBackground()); - add(iconsWrapper, BorderLayout.LINE_END); - } - - public void enableActions(boolean enabled) { - for (var iconButton : iconsWrapper.getComponents()) { - iconButton.setEnabled(enabled); - } - } - - public void addReloadAction(Runnable onReload) { - addIconActionButton(new IconActionButton( - new AnAction( - CodeGPTBundle.get("toolwindow.chat.response.action.reloadResponse.text"), - CodeGPTBundle.get("toolwindow.chat.response.action.reloadResponse.description"), - Actions.Refresh) { - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - enableActions(false); - onReload.run(); - } - })); - } - - public void addDeleteAction(Runnable onDelete) { - addIconActionButton(new IconActionButton( - new AnAction( - CodeGPTBundle.get("toolwindow.chat.response.action.deleteResponse.text"), - CodeGPTBundle.get("toolwindow.chat.response.action.deleteResponse.description"), - Actions.GC) { - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - onDelete.run(); - } - })); - } - - private void addIconActionButton(IconActionButton iconActionButton) { - if (iconsWrapper.getComponents() != null && iconsWrapper.getComponents().length > 0) { - iconsWrapper.add(Box.createHorizontalStrut(8)); - } - iconsWrapper.add(iconActionButton); - } - - private JBLabel getIconLabel() { - return new JBLabel( - CodeGPTBundle.get("project.label"), - Icons.Default, - SwingConstants.LEADING) - .setAllowAutoWrapping(true) - .withFont(JBFont.label().asBold()); - } - } - - static class Body extends JPanel { - - private @Nullable JComponent content; - - Body() { - super(new BorderLayout()); - setBorder(JBUI.Borders.empty(4, 8)); - } - - public void addContent(JComponent content) { - this.content = content; - add(content); - } - - public void updateContent(JComponent content) { - removeAll(); - revalidate(); - repaint(); - addContent(content); - } - - public @Nullable JComponent getContent() { - return content; - } - } -} diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/UserMessagePanel.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/UserMessagePanel.java deleted file mode 100644 index 1e019f8a..00000000 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/UserMessagePanel.java +++ /dev/null @@ -1,127 +0,0 @@ -package ee.carlrobert.codegpt.toolwindow.chat.ui; - -import com.intellij.icons.AllIcons.General; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.project.Project; -import com.intellij.ui.ColorUtil; -import com.intellij.ui.JBColor; -import com.intellij.ui.components.JBLabel; -import com.intellij.util.ui.JBFont; -import com.intellij.util.ui.JBUI; -import ee.carlrobert.codegpt.CodeGPTBundle; -import ee.carlrobert.codegpt.CodeGPTKeys; -import ee.carlrobert.codegpt.Icons; -import ee.carlrobert.codegpt.conversations.message.Message; -import ee.carlrobert.codegpt.events.WebSearchEventDetails; -import ee.carlrobert.codegpt.settings.GeneralSettings; -import ee.carlrobert.codegpt.toolwindow.ui.WebpageList; -import java.awt.BorderLayout; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.UUID; -import javax.swing.DefaultListModel; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import org.jetbrains.annotations.Nullable; - -public class UserMessagePanel extends JPanel { - - public UserMessagePanel(Project project, Message message, Disposable parentDisposable) { - super(new BorderLayout()); - var headerPanel = new JPanel(new BorderLayout()); - headerPanel.setOpaque(false); - headerPanel.add(createDisplayNameLabel(), BorderLayout.LINE_START); - setBorder(JBUI.Borders.compound( - JBUI.Borders.customLine(JBColor.border(), 1, 0, 1, 0), - JBUI.Borders.empty(12, 8, 8, 8))); - setBackground(ColorUtil.brighter(getBackground(), 2)); - add(headerPanel, BorderLayout.NORTH); - - var additionalContextPanel = getAdditionalContextPanel(project, message); - if (additionalContextPanel != null) { - add(additionalContextPanel, BorderLayout.CENTER); - } - - if (message.getImageFilePath() != null && !message.getImageFilePath().isEmpty()) { - displayImage(message.getImageFilePath()); - } - - add(createResponseBody( - project, - message.getPrompt(), - parentDisposable), BorderLayout.SOUTH); - } - - public @Nullable JPanel getAdditionalContextPanel(Project project, Message message) { - var addedDocumentation = CodeGPTKeys.ADDED_DOCUMENTATION.get(project); - var referencedFilePaths = message.getReferencedFilePaths(); - if (addedDocumentation == null - && (referencedFilePaths == null - || referencedFilePaths.isEmpty())) { - return null; - } - - var panel = new JPanel(new BorderLayout()); - panel.setOpaque(false); - if (addedDocumentation != null) { - var listModel = new DefaultListModel