diff --git a/src/main/java/ee/carlrobert/codegpt/client/official/CompletionClientEventListener.java b/src/main/java/ee/carlrobert/codegpt/client/official/CompletionClientEventListener.java index fa890f27..3e6107ce 100644 --- a/src/main/java/ee/carlrobert/codegpt/client/official/CompletionClientEventListener.java +++ b/src/main/java/ee/carlrobert/codegpt/client/official/CompletionClientEventListener.java @@ -3,6 +3,7 @@ package ee.carlrobert.codegpt.client.official; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; +import java.net.SocketTimeoutException; import java.util.function.Consumer; import javax.annotation.Nullable; import okhttp3.Call; @@ -11,9 +12,13 @@ import okhttp3.Response; import okhttp3.sse.EventSource; import okhttp3.sse.EventSourceListener; import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class CompletionClientEventListener extends EventSourceListener { + private static final Logger LOG = LoggerFactory.getLogger(CompletionClientEventListener.class); + private static final String DEFAULT_ERROR_MSG = "Something went wrong. Please try again later."; private final OkHttpClient client; @@ -71,6 +76,11 @@ public abstract class CompletionClientEventListener extends EventSourceListener return; } + if (ex instanceof SocketTimeoutException) { + onFailure.accept("Request timed out. This may be due to the server being overloaded."); + return; + } + try { if (response == null) { onFailure.accept(DEFAULT_ERROR_MSG); @@ -83,6 +93,7 @@ public abstract class CompletionClientEventListener extends EventSourceListener onFailure.accept(error.getError().getMessage()); } } catch (IOException e) { + LOG.error("Something went wrong.", ex); onFailure.accept(DEFAULT_ERROR_MSG); } } diff --git a/src/main/java/ee/carlrobert/codegpt/ide/conversations/ConversationsState.java b/src/main/java/ee/carlrobert/codegpt/ide/conversations/ConversationsState.java index 50595603..ed32b762 100644 --- a/src/main/java/ee/carlrobert/codegpt/ide/conversations/ConversationsState.java +++ b/src/main/java/ee/carlrobert/codegpt/ide/conversations/ConversationsState.java @@ -14,7 +14,11 @@ import ee.carlrobert.codegpt.ide.conversations.converter.ConversationsConverter; import ee.carlrobert.codegpt.ide.settings.SettingsState; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,6 +57,16 @@ public class ConversationsState implements PersistentStateComponent getSortedConversations() { + return conversationsContainer + .getConversationsMapping() + .values() + .stream() + .flatMap(List::stream) + .sorted(Comparator.comparing(Conversation::getUpdatedOn).reversed()) + .collect(Collectors.toList()); + } + public Conversation createConversation(ClientCode clientCode) { var settings = SettingsState.getInstance(); var conversation = new Conversation(); @@ -101,4 +115,53 @@ public class ConversationsState implements PersistentStateComponent getNextConversation() { + return tryGetNextOrPreviousConversation(true); + } + + public Optional getPreviousConversation() { + return tryGetNextOrPreviousConversation(false); + } + + private Optional tryGetNextOrPreviousConversation(boolean isNext) { + if (currentConversation != null) { + var sortedConversations = getSortedConversations(); + for (int i = 0; i < sortedConversations.size(); i++) { + var conversation = sortedConversations.get(i); + if (conversation != null && conversation.getId().equals(currentConversation.getId())) { + var nextIndex = isNext ? i + 1 : i - 1; + if (isNext ? nextIndex < sortedConversations.size() : nextIndex != -1) { + return Optional.of(sortedConversations.get(nextIndex)); + } + } + } + } + return Optional.empty(); + } + + public void deleteSelectedConversation() { + var nextConversation = getNextConversation(); + if (nextConversation.isEmpty()) { + nextConversation = getPreviousConversation(); + } + + var iterator = conversationsContainer.getConversationsMapping() + .get(currentConversation.getClientCode()) + .listIterator(); + while (iterator.hasNext()) { + var next = iterator.next(); + if (next.getId().equals(currentConversation.getId())) { + iterator.remove(); + break; + } + } + + nextConversation.ifPresent(this::setCurrentConversation); + } } diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ProjectToolWindowFactory.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ProjectToolWindowFactory.java index ff6a552f..ce35e76f 100644 --- a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ProjectToolWindowFactory.java +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ProjectToolWindowFactory.java @@ -4,11 +4,10 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.ContentManagerEvent; import com.intellij.ui.content.ContentManagerListener; import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import ee.carlrobert.codegpt.ide.toolwindow.chat.ChatGptToolWindow; import ee.carlrobert.codegpt.ide.toolwindow.conversations.ConversationsToolWindow; import javax.swing.JPanel; import org.jetbrains.annotations.NotNull; @@ -44,8 +43,8 @@ public class ProjectToolWindowFactory implements ToolWindowFactory, DumbAware { } public void addContent(ToolWindow toolWindow, JPanel panel, String displayName) { - ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); - Content content = contentFactory.createContent(panel, displayName, false); - toolWindow.getContentManager().addContent(content); + var contentManager = toolWindow.getContentManager(); + var content = contentManager.getFactory().createContent(panel, displayName, false); + contentManager.addContent(content); } } diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ToolWindowService.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ToolWindowService.java index e14532c4..6f2af801 100644 --- a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ToolWindowService.java +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ToolWindowService.java @@ -6,6 +6,7 @@ import com.intellij.openapi.project.Project; import ee.carlrobert.codegpt.client.ClientFactory; import ee.carlrobert.codegpt.ide.conversations.ConversationsState; import ee.carlrobert.codegpt.ide.conversations.message.Message; +import ee.carlrobert.codegpt.ide.toolwindow.chat.ChatGptToolWindow; import ee.carlrobert.codegpt.ide.toolwindow.components.SyntaxTextArea; import java.util.List; import javax.swing.SwingWorker; diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ChatGptToolWindow.form b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/ChatGptToolWindow.form similarity index 96% rename from src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ChatGptToolWindow.form rename to src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/ChatGptToolWindow.form index 23fd9c99..d1d375fd 100644 --- a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ChatGptToolWindow.form +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/ChatGptToolWindow.form @@ -1,5 +1,5 @@ -
+ diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ChatGptToolWindow.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/ChatGptToolWindow.java similarity index 85% rename from src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ChatGptToolWindow.java rename to src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/ChatGptToolWindow.java index 3c508bb1..3a13719c 100644 --- a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/ChatGptToolWindow.java +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/ChatGptToolWindow.java @@ -1,4 +1,4 @@ -package ee.carlrobert.codegpt.ide.toolwindow; +package ee.carlrobert.codegpt.ide.toolwindow.chat; import static ee.carlrobert.codegpt.ide.util.SwingUtils.createIconLabel; import static ee.carlrobert.codegpt.ide.util.SwingUtils.createTextArea; @@ -6,20 +6,27 @@ import static ee.carlrobert.codegpt.ide.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.ide.conversations.Conversation; import ee.carlrobert.codegpt.ide.conversations.ConversationsState; import ee.carlrobert.codegpt.ide.settings.SettingsConfigurable; import ee.carlrobert.codegpt.ide.settings.SettingsState; +import ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService; import ee.carlrobert.codegpt.ide.toolwindow.components.GenerateButton; import ee.carlrobert.codegpt.ide.toolwindow.components.LandingView; import ee.carlrobert.codegpt.ide.toolwindow.components.ScrollPane; import ee.carlrobert.codegpt.ide.toolwindow.components.SyntaxTextArea; import ee.carlrobert.codegpt.ide.toolwindow.components.TextArea; +import ee.carlrobert.codegpt.ide.toolwindow.chat.actions.CreateNewConversationAction; +import ee.carlrobert.codegpt.ide.toolwindow.chat.actions.OpenInEditorAction; import icons.Icons; import java.awt.Cursor; import java.awt.Dimension; @@ -57,7 +64,21 @@ public class ChatGptToolWindow { } public JPanel getContent() { - return chatGptToolWindowContent; + SimpleToolWindowPanel panel = new SimpleToolWindowPanel(true); + panel.setContent(chatGptToolWindowContent); + + var actionGroup = new DefaultActionGroup("TOOLBAR_ACTION_GROUP", false); + actionGroup.add(new CreateNewConversationAction()); + actionGroup.addSeparator(); + actionGroup.add(new OpenInEditorAction()); + + // 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; } public void displayUserMessage(String userMessage) { @@ -205,10 +226,12 @@ public class ChatGptToolWindow { BorderFactory.createEmptyBorder(0, 5, 0, 10))); textArea = new TextArea(this::handleSubmit, textAreaScrollPane); textAreaScrollPane.setViewportView(textArea); + scrollablePanel = new ScrollablePanel(); scrollablePanel.setLayout(new BoxLayout(scrollablePanel, BoxLayout.Y_AXIS)); scrollPane = new ScrollPane(scrollablePanel); + generateButton = new GenerateButton(); - displayLandingView(); + // displayLandingView(); } } diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/CreateNewConversationAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/CreateNewConversationAction.java new file mode 100644 index 00000000..fb6e111a --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/CreateNewConversationAction.java @@ -0,0 +1,26 @@ +package ee.carlrobert.codegpt.ide.toolwindow.chat.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService; +import org.jetbrains.annotations.NotNull; + +public class CreateNewConversationAction extends AnAction { + + public CreateNewConversationAction() { + super("Create New Conversation", "Create new conversation", AllIcons.General.Add); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent event) { + var project = event.getProject(); + if (project != null) { + ConversationsState.getInstance().startConversation(); + project.getService(ToolWindowService.class) + .getChatToolWindow() + .displayLandingView(); + } + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/OpenInEditorAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/OpenInEditorAction.java new file mode 100644 index 00000000..6e8cac6e --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/OpenInEditorAction.java @@ -0,0 +1,49 @@ +package ee.carlrobert.codegpt.ide.toolwindow.chat.actions; + +import static java.util.Objects.requireNonNull; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.testFramework.LightVirtualFile; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import java.time.format.DateTimeFormatter; +import java.util.stream.Collectors; +import org.jetbrains.annotations.NotNull; + +public class OpenInEditorAction extends AnAction { + + public OpenInEditorAction() { + super("Open In Editor", "Open conversation in editor", AllIcons.Actions.SplitVertically); + } + + @Override + public void update(@NotNull AnActionEvent event) { + super.update(event); + var currentConversation = ConversationsState.getCurrentConversation(); + var isEnabled = currentConversation != null && !currentConversation.getMessages().isEmpty(); + event.getPresentation().setEnabled(isEnabled); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + var project = e.getProject(); + var currentConversation = ConversationsState.getCurrentConversation(); + if (project != null && currentConversation != null) { + var dateTimeStamp = currentConversation.getUpdatedOn().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")); + var fileName = String.format("%s_%s.md", currentConversation.getModel().getCode(), dateTimeStamp); + var fileContent = currentConversation + .getMessages() + .stream() + .map(it -> String.format("### User:\n%s\n### ChatGPT:\n%s\n", it.getPrompt(), it.getResponse())) + .collect(Collectors.joining()); + VirtualFile file = new LightVirtualFile(fileName, fileContent); + FileEditorManager.getInstance(project).openFile(file, true); + var toolWindow = requireNonNull(ToolWindowManager.getInstance(project).getToolWindow("CodeGPT")); + toolWindow.hide(); + } + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/TokenToolbarLabelAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/TokenToolbarLabelAction.java new file mode 100644 index 00000000..40e9e795 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/chat/actions/TokenToolbarLabelAction.java @@ -0,0 +1,28 @@ +package ee.carlrobert.codegpt.ide.toolwindow.chat.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.ex.ToolbarLabelAction; +import com.intellij.util.ui.JBUI; +import javax.swing.JComponent; +import org.jetbrains.annotations.NotNull; + +public class TokenToolbarLabelAction extends ToolbarLabelAction { + + @Override + public @NotNull JComponent createCustomComponent( + @NotNull Presentation presentation, + @NotNull String place) { + JComponent component = super.createCustomComponent(presentation, place); + component.setBorder(JBUI.Borders.empty(0, 2)); + return component; + } + + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + Presentation presentation = e.getPresentation(); + presentation.setText("Tokens: 0/0"); + presentation.setVisible(true); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/ConversationsToolWindow.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/ConversationsToolWindow.java index 760a8415..f297c559 100644 --- a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/ConversationsToolWindow.java +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/ConversationsToolWindow.java @@ -1,7 +1,11 @@ package ee.carlrobert.codegpt.ide.toolwindow.conversations; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.actionSystem.DefaultActionGroup; 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.components.JBScrollPane; import ee.carlrobert.codegpt.client.ClientCode; import ee.carlrobert.codegpt.ide.conversations.Conversation; @@ -9,7 +13,10 @@ import ee.carlrobert.codegpt.ide.conversations.ConversationsState; import ee.carlrobert.codegpt.ide.settings.SettingsState; import ee.carlrobert.codegpt.ide.toolwindow.ContentManagerService; import ee.carlrobert.codegpt.ide.toolwindow.ToolWindowService; -import java.util.Comparator; +import ee.carlrobert.codegpt.ide.toolwindow.conversations.actions.ClearAllConversationsAction; +import ee.carlrobert.codegpt.ide.toolwindow.conversations.actions.DeleteConversationAction; +import ee.carlrobert.codegpt.ide.toolwindow.conversations.actions.MoveDownAction; +import ee.carlrobert.codegpt.ide.toolwindow.conversations.actions.MoveUpAction; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.JScrollPane; @@ -29,17 +36,29 @@ public class ConversationsToolWindow { } public JPanel getContent() { - return conversationsToolWindowContent; + SimpleToolWindowPanel panel = new SimpleToolWindowPanel(true); + panel.setContent(conversationsToolWindowContent); + + var actionGroup = new DefaultActionGroup("TOOLBAR_ACTION_GROUP", false); + actionGroup.add(new MoveDownAction(this::refresh)); + actionGroup.add(new MoveUpAction(this::refresh)); + actionGroup.addSeparator(); + actionGroup.add(new DeleteConversationAction(this::refresh)); + actionGroup.add(new ClearAllConversationsAction(this::refresh)); + + ActionToolbar actionToolbar = ActionManager.getInstance() + .createActionToolbar("NAVIGATION_BAR_TOOLBAR", actionGroup, true); + panel.setToolbar(actionToolbar.getComponent()); + return panel; } public void refresh() { scrollablePanel.removeAll(); ConversationsState.getInstance() - .conversationsContainer - .getConversationsMapping() - .forEach((key, value) -> value.stream() - .sorted(Comparator.comparing(Conversation::getUpdatedOn).reversed()) - .forEach(this::addContent)); + .getSortedConversations() + .forEach(this::addContent); + scrollablePanel.revalidate(); + scrollablePanel.repaint(); } private void addContent(Conversation conversation) { diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/ClearAllConversationsAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/ClearAllConversationsAction.java new file mode 100644 index 00000000..ef27abcb --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/ClearAllConversationsAction.java @@ -0,0 +1,23 @@ +package ee.carlrobert.codegpt.ide.toolwindow.conversations.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import org.jetbrains.annotations.NotNull; + +public class ClearAllConversationsAction extends AnAction { + + private final Runnable onRefresh; + + public ClearAllConversationsAction(Runnable onRefresh) { + super("Delete All", "Delete all conversations", AllIcons.Actions.GC); + this.onRefresh = onRefresh; + } + + @Override + public void actionPerformed(@NotNull AnActionEvent event) { + ConversationsState.getInstance().clearAll(); + this.onRefresh.run(); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/DeleteConversationAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/DeleteConversationAction.java new file mode 100644 index 00000000..780d7e6a --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/DeleteConversationAction.java @@ -0,0 +1,23 @@ +package ee.carlrobert.codegpt.ide.toolwindow.conversations.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import org.jetbrains.annotations.NotNull; + +public class DeleteConversationAction extends AnAction { + + private final Runnable onRefresh; + + public DeleteConversationAction(Runnable onRefresh) { + super("Delete Conversation", "Delete single conversation", AllIcons.General.Remove); + this.onRefresh = onRefresh; + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + ConversationsState.getInstance().deleteSelectedConversation(); + onRefresh.run(); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveAction.java new file mode 100644 index 00000000..b3195c00 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveAction.java @@ -0,0 +1,30 @@ +package ee.carlrobert.codegpt.ide.toolwindow.conversations.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import ee.carlrobert.codegpt.ide.conversations.Conversation; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import java.util.Optional; +import javax.swing.Icon; +import org.jetbrains.annotations.NotNull; + +public abstract class MoveAction extends AnAction { + + private final Runnable onRefresh; + + protected abstract Optional getConversation(); + + protected MoveAction(String text, String description, Icon icon, Runnable onRefresh) { + super(text, description, icon); + this.onRefresh = onRefresh; + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + getConversation() + .ifPresent(conversation -> { + ConversationsState.getInstance().setCurrentConversation(conversation); + onRefresh.run(); + }); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveDownAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveDownAction.java new file mode 100644 index 00000000..9fdce0e2 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveDownAction.java @@ -0,0 +1,25 @@ +package ee.carlrobert.codegpt.ide.toolwindow.conversations.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import ee.carlrobert.codegpt.ide.conversations.Conversation; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +public class MoveDownAction extends MoveAction { + + public MoveDownAction(Runnable onRefresh) { + super("Move Down", "Move Down", AllIcons.Actions.MoveDown, onRefresh); + } + + @Override + public void update(@NotNull AnActionEvent event) { + super.update(event); + } + + @Override + protected Optional getConversation() { + return ConversationsState.getInstance().getNextConversation(); + } +} diff --git a/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveUpAction.java b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveUpAction.java new file mode 100644 index 00000000..a26ee480 --- /dev/null +++ b/src/main/java/ee/carlrobert/codegpt/ide/toolwindow/conversations/actions/MoveUpAction.java @@ -0,0 +1,25 @@ +package ee.carlrobert.codegpt.ide.toolwindow.conversations.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import ee.carlrobert.codegpt.ide.conversations.Conversation; +import ee.carlrobert.codegpt.ide.conversations.ConversationsState; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; + +public class MoveUpAction extends MoveAction { + + public MoveUpAction(Runnable onRefresh) { + super("Move Up", "Move up", AllIcons.Actions.MoveUp, onRefresh); + } + + @Override + public void update(@NotNull AnActionEvent event) { + super.update(event); + } + + @Override + protected Optional getConversation() { + return ConversationsState.getInstance().getPreviousConversation(); + } +}