From 3d104c8b5a7819fc8aadfc0f97eb7cc209d5d4b2 Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Wed, 22 Mar 2023 23:42:32 +0000 Subject: [PATCH] Add tabs for multiple concurrent conversations (#54) --- .../carlrobert/codegpt/action/AskAction.java | 16 ++++--- .../carlrobert/codegpt/action/BaseAction.java | 19 ++++---- .../codegpt/settings/SettingsComponent.java | 8 ++-- .../toolwindow/ContentManagerService.java | 15 ++++++ .../toolwindow/ProjectToolWindowFactory.java | 47 +++++++++++++++---- .../codegpt/toolwindow/ToolWindowService.java | 39 +++++---------- .../toolwindow/chat/ChatTabbedPane.java | 28 +++++++++++ ...olWindow.form => ChatToolWindowPanel.form} | 2 +- ...olWindow.java => ChatToolWindowPanel.java} | 45 +++++++----------- .../actions/CreateNewConversationAction.java | 12 ++--- .../ConversationsToolWindow.java | 21 ++++++--- 11 files changed, 158 insertions(+), 94 deletions(-) create mode 100644 src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatTabbedPane.java rename src/main/java/ee/carlrobert/codegpt/toolwindow/chat/{ChatGptToolWindow.form => ChatToolWindowPanel.form} (96%) rename src/main/java/ee/carlrobert/codegpt/toolwindow/chat/{ChatGptToolWindow.java => ChatToolWindowPanel.java} (84%) diff --git a/src/main/java/ee/carlrobert/codegpt/action/AskAction.java b/src/main/java/ee/carlrobert/codegpt/action/AskAction.java index 210a32b8..17d549b5 100644 --- a/src/main/java/ee/carlrobert/codegpt/action/AskAction.java +++ b/src/main/java/ee/carlrobert/codegpt/action/AskAction.java @@ -3,9 +3,8 @@ package ee.carlrobert.codegpt.action; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import ee.carlrobert.codegpt.conversations.ConversationsState; import ee.carlrobert.codegpt.toolwindow.ContentManagerService; -import ee.carlrobert.codegpt.toolwindow.ToolWindowService; +import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowPanel; import org.jetbrains.annotations.NotNull; public class AskAction extends AnAction { @@ -23,10 +22,15 @@ public class AskAction extends AnAction { public void actionPerformed(@NotNull AnActionEvent event) { var project = event.getProject(); if (project != null) { - ConversationsState.getInstance().startConversation(); - project.getService(ContentManagerService.class).displayChatTab(project); - var chatToolWindow = project.getService(ToolWindowService.class).getChatToolWindow(); - chatToolWindow.displayLandingView(); + var contentManagerService = project.getService(ContentManagerService.class); + contentManagerService.displayChatTab(project); + contentManagerService.tryFindChatTabbedPane(project) + .ifPresent(tabbedPane -> { + var panel = new ChatToolWindowPanel(project); + panel.displayLandingView(); + tabbedPane.addTab("Chat " + (tabbedPane.getTabCount() + 1), panel); + tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1); + }); } } } diff --git a/src/main/java/ee/carlrobert/codegpt/action/BaseAction.java b/src/main/java/ee/carlrobert/codegpt/action/BaseAction.java index 90be410f..90ea3d6c 100644 --- a/src/main/java/ee/carlrobert/codegpt/action/BaseAction.java +++ b/src/main/java/ee/carlrobert/codegpt/action/BaseAction.java @@ -6,9 +6,8 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsActions; -import ee.carlrobert.codegpt.conversations.ConversationsState; import ee.carlrobert.codegpt.toolwindow.ContentManagerService; -import ee.carlrobert.codegpt.toolwindow.ToolWindowService; +import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowPanel; import javax.swing.Icon; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,11 +46,15 @@ public abstract class BaseAction extends AnAction { } protected void sendMessage(@NotNull Project project, String prompt) { - ConversationsState.getInstance().startConversation(); - project.getService(ContentManagerService.class).displayChatTab(project); - var chatToolWindow = project.getService(ToolWindowService.class).getChatToolWindow(); - chatToolWindow.clearWindow(); - chatToolWindow.displayUserMessage(prompt); - chatToolWindow.sendMessage(prompt, project); + var contentManagerService = project.getService(ContentManagerService.class); + contentManagerService.displayChatTab(project); + contentManagerService.tryFindChatTabbedPane(project) + .ifPresent(tabbedPane -> { + var panel = new ChatToolWindowPanel(project); + panel.displayUserMessage(prompt); + tabbedPane.addTab("Chat " + (tabbedPane.getTabCount() + 1), panel); + tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1); + panel.sendMessage(prompt, project); + }); } } diff --git a/src/main/java/ee/carlrobert/codegpt/settings/SettingsComponent.java b/src/main/java/ee/carlrobert/codegpt/settings/SettingsComponent.java index eb790bd0..082c952f 100644 --- a/src/main/java/ee/carlrobert/codegpt/settings/SettingsComponent.java +++ b/src/main/java/ee/carlrobert/codegpt/settings/SettingsComponent.java @@ -95,16 +95,16 @@ public class SettingsComponent { return (TextCompletionModel) textCompletionBaseModelComboBox.getSelectedItem(); } - public void setTextCompletionBaseModel(String model) { - textCompletionBaseModelComboBox.setSelectedItem(TextCompletionModel.valueOf(model)); + public void setTextCompletionBaseModel(String modelCode) { + textCompletionBaseModelComboBox.setSelectedItem(TextCompletionModel.findByCode(modelCode)); } public ChatCompletionModel getChatCompletionBaseModel() { return (ChatCompletionModel) chatCompletionBaseModelComboBox.getSelectedItem(); } - public void setChatCompletionBaseModel(String model) { - chatCompletionBaseModelComboBox.setSelectedItem(ChatCompletionModel.valueOf(model)); + public void setChatCompletionBaseModel(String modelCode) { + chatCompletionBaseModelComboBox.setSelectedItem(ChatCompletionModel.findByCode(modelCode)); } private JPanel createMainSelectionForm() { diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/ContentManagerService.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/ContentManagerService.java index 54b65c72..6abde1a7 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/ContentManagerService.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/ContentManagerService.java @@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; +import ee.carlrobert.codegpt.toolwindow.chat.ChatTabbedPane; import java.util.Arrays; import java.util.Optional; import org.jetbrains.annotations.NotNull; @@ -33,4 +34,18 @@ public class ContentManagerService { .filter(contentManager::isSelected) .isPresent(); } + + public Optional tryFindChatTabbedPane(@NotNull Project project) { + var toolWindow = requireNonNull(ToolWindowManager.getInstance(project).getToolWindow("CodeGPT")); + var chatTabContent = tryFindChatTabContent(toolWindow.getContentManager()); + if (chatTabContent.isPresent()) { + var tabbedPane = Arrays.stream(chatTabContent.get().getComponent().getComponents()) + .filter(component -> component instanceof ChatTabbedPane) + .findFirst(); + if (tabbedPane.isPresent()) { + return Optional.of((ChatTabbedPane) tabbedPane.get()); + } + } + return Optional.empty(); + } } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/ProjectToolWindowFactory.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/ProjectToolWindowFactory.java index 03b24cce..0b72aca5 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/ProjectToolWindowFactory.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/ProjectToolWindowFactory.java @@ -1,16 +1,23 @@ package ee.carlrobert.codegpt.toolwindow; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.ContentManagerEvent; import com.intellij.ui.content.ContentManagerListener; -import com.intellij.ui.jcef.JBCefBrowser; -import ee.carlrobert.codegpt.client.ClientFactory; import ee.carlrobert.codegpt.account.AccountDetailsState; +import ee.carlrobert.codegpt.client.ClientFactory; import ee.carlrobert.codegpt.conversations.ConversationsState; -import ee.carlrobert.codegpt.toolwindow.chat.ChatGptToolWindow; +import ee.carlrobert.codegpt.toolwindow.chat.ChatTabbedPane; +import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowPanel; +import ee.carlrobert.codegpt.toolwindow.chat.actions.CreateNewConversationAction; +import ee.carlrobert.codegpt.toolwindow.chat.actions.OpenInEditorAction; +import ee.carlrobert.codegpt.toolwindow.chat.actions.UsageToolbarLabelAction; import ee.carlrobert.codegpt.toolwindow.conversations.ConversationsToolWindow; import javax.swing.JComponent; import org.jetbrains.annotations.NotNull; @@ -18,15 +25,18 @@ import org.jetbrains.annotations.NotNull; public class ProjectToolWindowFactory implements ToolWindowFactory, DumbAware { public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { - var chatToolWindow = new ChatGptToolWindow(project); + var chatToolWindow = new ChatToolWindowPanel(project); var conversationsToolWindow = new ConversationsToolWindow(project); - var toolWindowService = project.getService(ToolWindowService.class); - toolWindowService.setChatToolWindow(chatToolWindow); + var toolWindowPanel = new SimpleToolWindowPanel(true); - var contentManagerService = project.getService(ContentManagerService.class); - addContent(toolWindow, chatToolWindow.getContent(), "Chat"); + var chatTabbedPane = new ChatTabbedPane(); + chatTabbedPane.addTab("Chat 1", chatToolWindow); + + toolWindowPanel.setToolbar(createActionToolbar(project, chatTabbedPane, toolWindowPanel).getComponent()); + toolWindowPanel.setContent(chatTabbedPane); + + addContent(toolWindow, toolWindowPanel, "Chat"); addContent(toolWindow, conversationsToolWindow.getContent(), "Conversation History"); - addContent(toolWindow, new JBCefBrowser("https://chat.openai.com/chat").getComponent(), "Browser"); toolWindow.addContentManagerListener(new ContentManagerListener() { public void selectionChanged(@NotNull ContentManagerEvent event) { var content = event.getContent(); @@ -43,6 +53,7 @@ public class ProjectToolWindowFactory implements ToolWindowFactory, DumbAware { } }); + var contentManagerService = project.getService(ContentManagerService.class); if (contentManagerService.isChatTabSelected(toolWindow.getContentManager())) { var conversation = ConversationsState.getCurrentConversation(); if (conversation == null) { @@ -58,4 +69,22 @@ public class ProjectToolWindowFactory implements ToolWindowFactory, DumbAware { var content = contentManager.getFactory().createContent(panel, displayName, false); contentManager.addContent(content); } + + private ActionToolbar createActionToolbar(Project project, ChatTabbedPane tabbedPane, SimpleToolWindowPanel toolWindowPanel) { + var actionGroup = new DefaultActionGroup("TOOLBAR_ACTION_GROUP", false); + actionGroup.add(new CreateNewConversationAction(() -> { + tabbedPane.addTab("Chat " + (tabbedPane.getTabCount() + 1), new ChatToolWindowPanel(project)); + tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1); + toolWindowPanel.repaint(); + toolWindowPanel.revalidate(); + })); + actionGroup.add(new OpenInEditorAction()); + actionGroup.addSeparator(); + actionGroup.add(new UsageToolbarLabelAction()); + + // TODO: Data usage not enabled in stream mode https://community.openai.com/t/usage-info-in-api-responses/18862/11 + // actionGroup.add(new TokenToolbarLabelAction()); + + return ActionManager.getInstance().createActionToolbar("NAVIGATION_BAR_TOOLBAR", actionGroup, false); + } } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/ToolWindowService.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/ToolWindowService.java index f3d90c10..0b6b7887 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/ToolWindowService.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/ToolWindowService.java @@ -1,40 +1,27 @@ package ee.carlrobert.codegpt.toolwindow; -import com.intellij.ide.ui.LafManager; -import com.intellij.ide.ui.LafManagerListener; import com.intellij.openapi.project.Project; import ee.carlrobert.codegpt.client.ClientFactory; import ee.carlrobert.codegpt.client.ClientRequestFactory; import ee.carlrobert.codegpt.client.EventListener; -import ee.carlrobert.codegpt.conversations.ConversationsState; +import ee.carlrobert.codegpt.conversations.Conversation; import ee.carlrobert.codegpt.conversations.message.Message; import ee.carlrobert.codegpt.settings.SettingsState; -import ee.carlrobert.codegpt.toolwindow.chat.ChatGptToolWindow; +import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowPanel; import ee.carlrobert.codegpt.toolwindow.components.SyntaxTextArea; import java.util.List; import javax.swing.SwingWorker; import okhttp3.sse.EventSource; -import org.jetbrains.annotations.NotNull; -public class ToolWindowService implements LafManagerListener { +public class ToolWindowService { - private ChatGptToolWindow chatToolWindow; - - @Override - public void lookAndFeelChanged(@NotNull LafManager source) { - chatToolWindow.changeStyle(); - } - - public void setChatToolWindow(ChatGptToolWindow chatToolWindow) { - this.chatToolWindow = chatToolWindow; - } - - public ChatGptToolWindow getChatToolWindow() { - return chatToolWindow; - } - - public void startRequest(String prompt, SyntaxTextArea textArea, Project project, boolean isRetry) { - var conversation = ConversationsState.getInstance().getOrStartNew(); + public void startRequest( + String prompt, + SyntaxTextArea textArea, + Project project, + boolean isRetry, + ChatToolWindowPanel toolWindow, + Conversation conversation) { var conversationMessage = new Message(prompt); new SwingWorker() { @@ -42,7 +29,7 @@ public class ToolWindowService implements LafManagerListener { var eventListener = new EventListener( conversationMessage, textArea::append, - () -> chatToolWindow.stopGenerating(prompt, textArea, project), + () -> toolWindow.stopGenerating(prompt, textArea, project), isRetry) { public void onMessage(String message) { publish(message); @@ -59,7 +46,7 @@ public class ToolWindowService implements LafManagerListener { call = ClientFactory.getTextCompletionClient().stream( requestFactory.buildTextCompletionRequest(settings), eventListener); } - chatToolWindow.displayGenerateButton(call::cancel); + toolWindow.displayGenerateButton(call::cancel); return null; } @@ -68,7 +55,7 @@ public class ToolWindowService implements LafManagerListener { try { textArea.append(text); conversationMessage.setResponse(textArea.getText()); - chatToolWindow.scrollToBottom(); + toolWindow.scrollToBottom(); } catch (Exception e) { textArea.append("Something went wrong. Please try again later."); throw new RuntimeException(e); diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatTabbedPane.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatTabbedPane.java new file mode 100644 index 00000000..a6355758 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatTabbedPane.java @@ -0,0 +1,28 @@ +package ee.carlrobert.codegpt.toolwindow.chat; + +import com.intellij.ui.components.JBTabbedPane; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class ChatTabbedPane extends JBTabbedPane { + + private final Map activeTabMapping = new HashMap<>(); + + public ChatTabbedPane() { + setTabComponentInsets(null); + } + + public void addTab(String title, ChatToolWindowPanel toolWindowPanel) { + super.addTab(title, toolWindowPanel.getContent()); + activeTabMapping.put(getTabCount() - 1, toolWindowPanel); + } + + public Optional tryFindActiveConversationIndex(UUID conversationId) { + return activeTabMapping.entrySet().stream() + .filter(entry -> conversationId.equals(entry.getValue().getConversationId())) + .findFirst() + .map(Map.Entry::getKey); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatGptToolWindow.form b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowPanel.form similarity index 96% rename from src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatGptToolWindow.form rename to src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowPanel.form index c624e1b7..69bf081a 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatGptToolWindow.form +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowPanel.form @@ -1,5 +1,5 @@ -
+ diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatGptToolWindow.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowPanel.java similarity index 84% rename from src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatGptToolWindow.java rename to src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowPanel.java index d664ecb1..b40ee3c4 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatGptToolWindow.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowPanel.java @@ -6,13 +6,9 @@ import static ee.carlrobert.codegpt.util.SwingUtils.justifyLeft; import static java.lang.String.format; import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionToolbar; -import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel; -import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.ui.JBColor; import com.intellij.ui.components.JBScrollPane; import ee.carlrobert.codegpt.account.AccountDetailsState; @@ -21,9 +17,6 @@ import ee.carlrobert.codegpt.conversations.ConversationsState; import ee.carlrobert.codegpt.settings.SettingsConfigurable; import ee.carlrobert.codegpt.settings.SettingsState; import ee.carlrobert.codegpt.toolwindow.ToolWindowService; -import ee.carlrobert.codegpt.toolwindow.chat.actions.CreateNewConversationAction; -import ee.carlrobert.codegpt.toolwindow.chat.actions.OpenInEditorAction; -import ee.carlrobert.codegpt.toolwindow.chat.actions.UsageToolbarLabelAction; import ee.carlrobert.codegpt.toolwindow.components.GenerateButton; import ee.carlrobert.codegpt.toolwindow.components.LandingView; import ee.carlrobert.codegpt.toolwindow.components.ScrollPane; @@ -36,6 +29,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; @@ -49,7 +43,7 @@ import javax.swing.SwingUtilities; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.jetbrains.annotations.NotNull; -public class ChatGptToolWindow { +public class ChatToolWindowPanel { private static final List textAreas = new ArrayList<>(); private final Project project; @@ -60,33 +54,18 @@ public class ChatGptToolWindow { private JScrollPane textAreaScrollPane; private GenerateButton generateButton; private boolean isLandingViewVisible; + private UUID conversationId; - public ChatGptToolWindow(@NotNull Project project) { + public ChatToolWindowPanel(@NotNull Project project) { this.project = project; } public JPanel getContent() { - SimpleToolWindowPanel panel = new SimpleToolWindowPanel(true); - panel.setContent(chatGptToolWindowContent); - - var actionGroup = new DefaultActionGroup("TOOLBAR_ACTION_GROUP", false); - actionGroup.add(new CreateNewConversationAction()); - actionGroup.add(new OpenInEditorAction()); - actionGroup.addSeparator(); - actionGroup.add(new UsageToolbarLabelAction()); - - // TODO: Data usage not enabled in stream mode https://community.openai.com/t/usage-info-in-api-responses/18862/11 - // actionGroup.add(new TokenToolbarLabelAction()); - - ActionToolbar actionToolbar = ActionManager.getInstance() - .createActionToolbar("NAVIGATION_BAR_TOOLBAR", actionGroup, false); - panel.setToolbar(actionToolbar.getComponent()); - return panel; + return chatGptToolWindowContent; } public void displayUserMessage(String userMessage) { addIconLabel(AllIcons.General.User, AccountDetailsState.getInstance().accountName); - scrollablePanel.add(createTextPane(userMessage)); scrollablePanel.revalidate(); scrollablePanel.repaint(); @@ -113,6 +92,7 @@ public class ChatGptToolWindow { } public void displayConversation(Conversation conversation) { + setConversationId(conversation.getId()); clearWindow(); conversation.getMessages().forEach(message -> { displayUserMessage(message.getPrompt()); @@ -149,8 +129,11 @@ public class ChatGptToolWindow { textArea = new SyntaxTextArea(true, true, SyntaxConstants.SYNTAX_STYLE_MARKDOWN); addTextArea(textArea); } + + var conversation = ConversationsState.getInstance().getOrStartNew(); + setConversationId(conversation.getId()); project.getService(ToolWindowService.class) - .startRequest(prompt, textArea, project, isRetry); + .startRequest(prompt, textArea, project, isRetry, this, conversation); } } @@ -247,4 +230,12 @@ public class ChatGptToolWindow { generateButton = new GenerateButton(); } + + public UUID getConversationId() { + return conversationId; + } + + public void setConversationId(UUID conversationId) { + this.conversationId = conversationId; + } } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/actions/CreateNewConversationAction.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/actions/CreateNewConversationAction.java index ae8a97fb..f2501e9a 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/actions/CreateNewConversationAction.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/actions/CreateNewConversationAction.java @@ -4,13 +4,15 @@ import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import ee.carlrobert.codegpt.conversations.ConversationsState; -import ee.carlrobert.codegpt.toolwindow.ToolWindowService; import org.jetbrains.annotations.NotNull; public class CreateNewConversationAction extends AnAction { - public CreateNewConversationAction() { - super("Create New Conversation", "Create new conversation", AllIcons.General.Add); + private final Runnable onCreate; + + public CreateNewConversationAction(Runnable onCreate) { + super("Create New Chat", "Create new chat", AllIcons.General.Add); + this.onCreate = onCreate; } @Override @@ -18,9 +20,7 @@ public class CreateNewConversationAction extends AnAction { var project = event.getProject(); if (project != null) { ConversationsState.getInstance().startConversation(); - project.getService(ToolWindowService.class) - .getChatToolWindow() - .displayLandingView(); + onCreate.run(); } } } diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/conversations/ConversationsToolWindow.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/conversations/ConversationsToolWindow.java index 5eddedc4..22a82f94 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/conversations/ConversationsToolWindow.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/conversations/ConversationsToolWindow.java @@ -13,7 +13,7 @@ import ee.carlrobert.codegpt.conversations.Conversation; import ee.carlrobert.codegpt.conversations.ConversationsState; import ee.carlrobert.codegpt.settings.SettingsState; import ee.carlrobert.codegpt.toolwindow.ContentManagerService; -import ee.carlrobert.codegpt.toolwindow.ToolWindowService; +import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowPanel; import ee.carlrobert.codegpt.toolwindow.conversations.actions.ClearAllConversationsAction; import ee.carlrobert.codegpt.toolwindow.conversations.actions.DeleteConversationAction; import ee.carlrobert.codegpt.toolwindow.conversations.actions.MoveDownAction; @@ -76,17 +76,24 @@ public class ConversationsToolWindow { var mainPanel = new RootConversationPanel(() -> { ConversationsState.getInstance().setCurrentConversation(conversation); changeSettings(conversation); - project.getService(ContentManagerService.class).displayChatTab(project); - project.getService(ToolWindowService.class) - .getChatToolWindow() - .displayConversation(conversation); + + var contentManagerService = project.getService(ContentManagerService.class); + contentManagerService.displayChatTab(project); + contentManagerService.tryFindChatTabbedPane(project) + .ifPresent(tabbedPane -> tabbedPane.tryFindActiveConversationIndex(conversation.getId()) + .ifPresentOrElse(tabbedPane::setSelectedIndex, () -> { + var panel = new ChatToolWindowPanel(project); + panel.displayConversation(conversation); + + tabbedPane.addTab("Chat " + (tabbedPane.getTabCount() + 1), panel); + tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1); + })); }); - mainPanel.setBackground(conversationsToolWindowContent.getBackground()); var currentConversation = ConversationsState.getCurrentConversation(); var isSelected = currentConversation != null && currentConversation.getId().equals(conversation.getId()); mainPanel.add(new ConversationPanel(conversation, isSelected)); - + mainPanel.setBackground(conversationsToolWindowContent.getBackground()); scrollablePanel.add(mainPanel); }