feat: display notification on plugin updates

This commit is contained in:
Carl-Robert Linnupuu 2023-12-02 00:54:57 +02:00
parent 10b090e2d2
commit 1392775940
8 changed files with 125 additions and 4 deletions

View file

@ -5,11 +5,15 @@ import static java.util.Objects.requireNonNull;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import ee.carlrobert.codegpt.telemetry.core.util.Directories;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
public final class CodeGPTPlugin {
@ -46,4 +50,18 @@ public final class CodeGPTPlugin {
public static @NotNull String getProjectIndexStorePath(@NotNull Project project) {
return getIndexStorePath() + File.separator + project.getName();
}
public static Optional<PluginDownloader> tryFindAvailableUpdate(
@NotNull ProgressIndicator indicator) {
return findAvailableUpdates(indicator).stream()
.filter((update) -> CODEGPT_ID.equals(update.getId()))
.findFirst();
}
private static @NotNull Collection<PluginDownloader> findAvailableUpdates(
@NotNull ProgressIndicator indicator) {
return UpdateChecker.getInternalPluginUpdates(null, indicator)
.getPluginUpdates()
.getAllEnabled();
}
}

View file

@ -0,0 +1,68 @@
package ee.carlrobert.codegpt;
import com.intellij.notification.NotificationAction;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.util.concurrency.AppExecutorUtil;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationState;
import ee.carlrobert.codegpt.util.OverlayUtil;
import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.NotNull;
public class CodeGPTUpdateStartupActivity implements StartupActivity.Background {
@Override
public void runActivity(@NotNull Project project) {
schedulePluginUpdateChecks(project);
}
private void schedulePluginUpdateChecks(Project project) {
AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay(() -> {
if (project != null && ConfigurationState.getInstance().isCheckForPluginUpdates()) {
new CheckForUpdatesTask(project).queue();
}
}, 0, 4L, TimeUnit.HOURS);
}
private static class CheckForUpdatesTask extends Task.Backgroundable {
public CheckForUpdatesTask(@NotNull Project project) {
super(project, CodeGPTBundle.get("checkForUpdatesTask.title"), true);
}
private static void installCodeGPTUpdate(Project project) {
var settingsCopy = new UpdateSettings();
var settingsState = settingsCopy.getState();
settingsState.copyFrom(UpdateSettings.getInstance().getState());
settingsState.setCheckNeeded(true);
settingsState.setPluginsCheckNeeded(true);
settingsState.setShowWhatsNewEditor(true);
settingsState.setThirdPartyPluginsAllowed(true);
UpdateChecker.updateAndShowResult(project, settingsCopy);
}
public void run(@NotNull ProgressIndicator indicator) {
if (!myProject.isDisposed()) {
CodeGPTPlugin.tryFindAvailableUpdate(indicator)
.ifPresent((update) -> OverlayUtil.getDefaultNotification(
CodeGPTBundle.get("checkForUpdatesTask.notification.message"),
NotificationType.IDE_UPDATE)
.addAction(NotificationAction.createSimpleExpiring(
CodeGPTBundle.get("checkForUpdatesTask.notification.installButton"),
() -> ApplicationManager.getApplication()
.executeOnPooledThread(() -> installCodeGPTUpdate(myProject))))
.addAction(NotificationAction.createSimpleExpiring(
CodeGPTBundle.get("checkForUpdatesTask.notification.hideButton"),
() -> ConfigurationState.getInstance().setCheckForPluginUpdates(false)))
.notify(myProject));
}
}
}
}

View file

@ -41,6 +41,7 @@ public class ConfigurationComponent {
private final JPanel mainPanel;
private final JBTable table;
private final JBCheckBox checkForPluginUpdatesCheckBox;
private final JBCheckBox openNewTabCheckBox;
private final JBCheckBox methodNameGenerationCheckBox;
private final JBCheckBox autoFormattingCheckBox;
@ -99,6 +100,9 @@ public class ConfigurationComponent {
systemPromptTextArea.setColumns(60);
systemPromptTextArea.setRows(3);
checkForPluginUpdatesCheckBox = new JBCheckBox(
CodeGPTBundle.get("configurationConfigurable.checkForPluginUpdates.label"),
configuration.isCheckForPluginUpdates());
openNewTabCheckBox = new JBCheckBox(
CodeGPTBundle.get("configurationConfigurable.openNewTabCheckBox.label"),
configuration.isCreateNewChatOnEachAction());
@ -112,6 +116,7 @@ public class ConfigurationComponent {
mainPanel = FormBuilder.createFormBuilder()
.addComponent(tablePanel)
.addVerticalGap(4)
.addComponent(checkForPluginUpdatesCheckBox)
.addComponent(openNewTabCheckBox)
.addComponent(methodNameGenerationCheckBox)
.addComponent(autoFormattingCheckBox)
@ -256,6 +261,14 @@ public class ConfigurationComponent {
maxTokensField.setValue(maxTokens);
}
public boolean isCheckForPluginUpdates() {
return checkForPluginUpdatesCheckBox.isSelected();
}
public void setCheckForPluginUpdates(boolean checkForUpdates) {
checkForPluginUpdatesCheckBox.setSelected(checkForUpdates);
}
public boolean isCreateNewChatOnEachAction() {
return openNewTabCheckBox.isSelected();
}

View file

@ -37,6 +37,8 @@ public class ConfigurationConfigurable implements Configurable {
|| configurationComponent.getMaxTokens() != configuration.getMaxTokens()
|| configurationComponent.getTemperature() != configuration.getTemperature()
|| !configurationComponent.getSystemPrompt().equals(configuration.getSystemPrompt())
|| configurationComponent.isCheckForPluginUpdates()
!= configuration.isCheckForPluginUpdates()
|| configurationComponent.isCreateNewChatOnEachAction()
!= configuration.isCreateNewChatOnEachAction()
|| configurationComponent.isMethodNameGenerationEnabled()
@ -52,6 +54,7 @@ public class ConfigurationConfigurable implements Configurable {
configuration.setMaxTokens(configurationComponent.getMaxTokens());
configuration.setTemperature(configurationComponent.getTemperature());
configuration.setSystemPrompt(configurationComponent.getSystemPrompt());
configuration.setCheckForPluginUpdates(configurationComponent.isCheckForPluginUpdates());
configuration.setCreateNewChatOnEachAction(
configurationComponent.isCreateNewChatOnEachAction());
configuration.setMethodNameGenerationEnabled(
@ -67,6 +70,7 @@ public class ConfigurationConfigurable implements Configurable {
configurationComponent.setMaxTokens(configuration.getMaxTokens());
configurationComponent.setTemperature(configuration.getTemperature());
configurationComponent.setSystemPrompt(configuration.getSystemPrompt());
configurationComponent.setCheckForPluginUpdates(configuration.isCheckForPluginUpdates());
configurationComponent.setCreateNewChatOnEachAction(
configuration.isCreateNewChatOnEachAction());
configurationComponent.setDisableMethodNameGeneration(

View file

@ -20,6 +20,7 @@ public class ConfigurationState implements PersistentStateComponent<Configuratio
private String systemPrompt = COMPLETION_SYSTEM_PROMPT;
private int maxTokens = 1000;
private double temperature = 0.1;
private boolean checkForPluginUpdates = true;
private boolean createNewChatOnEachAction;
private boolean ignoreGitCommitTokenLimit;
private boolean methodNameGenerationEnabled = true;
@ -81,6 +82,14 @@ public class ConfigurationState implements PersistentStateComponent<Configuratio
this.tableData = tableData;
}
public boolean isCheckForPluginUpdates() {
return checkForPluginUpdates;
}
public void setCheckForPluginUpdates(boolean checkForPluginUpdates) {
this.checkForPluginUpdates = checkForPluginUpdates;
}
public boolean isIgnoreGitCommitTokenLimit() {
return ignoreGitCommitTokenLimit;
}

View file

@ -35,9 +35,12 @@ import org.jetbrains.annotations.NotNull;
public class OverlayUtil {
public static Notification getDefaultNotification(String content, NotificationType type) {
return new Notification("CodeGPT Notification Group", "CodeGPT", content, type);
}
public static void showNotification(String content, NotificationType type) {
Notifications.Bus.notify(
new Notification("CodeGPT Notification Group", "CodeGPT", content, type));
Notifications.Bus.notify(getDefaultNotification(content, type));
}
public static int showFileStructureDialog(