fix: long-running tasks on EDT when initializing forms

This commit is contained in:
Carl-Robert Linnupuu 2024-05-09 13:03:38 +03:00
parent 7bee59a90e
commit fedbe11fd2
9 changed files with 75 additions and 36 deletions

View file

@ -2,6 +2,7 @@ package ee.carlrobert.codegpt.settings.service.anthropic;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.ANTHROPIC_API_KEY;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.ui.components.JBPasswordField;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
@ -10,6 +11,7 @@ import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.ui.UIUtil;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jetbrains.annotations.Nullable;
public class AnthropicSettingsForm {
@ -21,7 +23,10 @@ public class AnthropicSettingsForm {
public AnthropicSettingsForm(AnthropicSettingsState settings) {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(CredentialsStore.getCredential(ANTHROPIC_API_KEY));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
var apiKey = CredentialsStore.getCredential(ANTHROPIC_API_KEY);
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
});
apiVersionField = new JBTextField(settings.getApiVersion(), 35);
modelField = new JBTextField(settings.getModel(), 35);
}

View file

@ -2,6 +2,7 @@ package ee.carlrobert.codegpt.settings.service.azure;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.ui.TitledSeparator;
import com.intellij.ui.components.JBPasswordField;
import com.intellij.ui.components.JBRadioButton;
@ -15,6 +16,7 @@ import java.util.List;
import java.util.Map;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jetbrains.annotations.Nullable;
public class AzureSettingsForm {
@ -38,15 +40,20 @@ public class AzureSettingsForm {
settings.isUseAzureActiveDirectoryAuthentication());
azureApiKeyField = new JBPasswordField();
azureApiKeyField.setColumns(30);
azureApiKeyField.setText(CredentialsStore.getCredential(CredentialKey.AZURE_OPENAI_API_KEY));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
var apiKey = CredentialsStore.getCredential(CredentialKey.AZURE_OPENAI_API_KEY);
SwingUtilities.invokeLater(() -> azureApiKeyField.setText(apiKey));
});
azureApiKeyFieldPanel = UI.PanelFactory.panel(azureApiKeyField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
.resizeX(false)
.createPanel();
azureActiveDirectoryTokenField = new JBPasswordField();
azureActiveDirectoryTokenField.setColumns(30);
azureActiveDirectoryTokenField.setText(
CredentialsStore.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
var apiKey = CredentialsStore.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN);
SwingUtilities.invokeLater(() -> azureActiveDirectoryTokenField.setText(apiKey));
});
azureActiveDirectoryTokenFieldPanel = UI.PanelFactory.panel(azureActiveDirectoryTokenField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.service.azure.bearerToken.label"))
.resizeX(false)

View file

@ -28,6 +28,7 @@ import ee.carlrobert.codegpt.completions.llama.LlamaServerAgent;
import ee.carlrobert.codegpt.completions.llama.LlamaServerStartupParams;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import ee.carlrobert.codegpt.ui.UIUtil;
@ -40,6 +41,7 @@ import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import org.jetbrains.annotations.Nullable;
public class LlamaServerPreferencesForm {
@ -86,7 +88,10 @@ public class LlamaServerPreferencesForm {
baseHostField = new JBTextField(settings.getBaseHost(), 30);
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(CredentialsStore.getCredential(LLAMA_API_KEY));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
var apiKey = CredentialsStore.getCredential(CredentialKey.LLAMA_API_KEY);
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
});
llamaModelPreferencesForm = new LlamaModelPreferencesForm();
runLocalServerRadioButton = new JBRadioButton("Run local server",
@ -189,17 +194,17 @@ public class LlamaServerPreferencesForm {
createComment("settingsConfigurable.service.llama.threads.comment"))
.addLabeledComponent(
CodeGPTBundle.get("settingsConfigurable.service.llama.additionalParameters.label"),
additionalParametersField)
.addComponentToRightColumn(
createComment(
"settingsConfigurable.service.llama.additionalParameters.comment"))
.addLabeledComponent(
CodeGPTBundle.get(
"settingsConfigurable.service.llama.additionalBuildParameters.label"),
additionalBuildParametersField)
.addComponentToRightColumn(
createComment(
"settingsConfigurable.service.llama.additionalBuildParameters.comment"))
additionalParametersField)
.addComponentToRightColumn(
createComment(
"settingsConfigurable.service.llama.additionalParameters.comment"))
.addLabeledComponent(
CodeGPTBundle.get(
"settingsConfigurable.service.llama.additionalBuildParameters.label"),
additionalBuildParametersField)
.addComponentToRightColumn(
createComment(
"settingsConfigurable.service.llama.additionalBuildParameters.comment"))
.addVerticalGap(4)
.addComponentFillVertically(new JPanel(), 0)
.getPanel()))
@ -354,9 +359,9 @@ public class LlamaServerPreferencesForm {
public List<String> getListOfAdditionalParameters() {
return Arrays.stream(additionalParametersField.getText().split(","))
.map(String::trim)
.filter(s -> !s.isBlank())
.toList();
.map(String::trim)
.filter(s -> !s.isBlank())
.toList();
}
public String getAdditionalBuildParameters() {
@ -365,9 +370,9 @@ public class LlamaServerPreferencesForm {
public List<String> getListOfAdditionalBuildParameters() {
return Arrays.stream(additionalBuildParametersField.getText().split(","))
.map(String::trim)
.filter(s -> !s.isBlank())
.toList();
.map(String::trim)
.filter(s -> !s.isBlank())
.toList();
}
public PromptTemplate getPromptTemplate() {

View file

@ -3,6 +3,7 @@ package ee.carlrobert.codegpt.settings.service.openai;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.ui.EnumComboBoxModel;
import com.intellij.ui.TitledSeparator;
@ -12,10 +13,12 @@ import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.settings.service.CodeCompletionConfigurationForm;
import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jetbrains.annotations.Nullable;
public class OpenAISettingsForm {
@ -28,7 +31,10 @@ public class OpenAISettingsForm {
public OpenAISettingsForm(OpenAISettingsState settings) {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(CredentialsStore.getCredential(OPENAI_API_KEY));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
var apiKey = CredentialsStore.getCredential(CredentialKey.OPENAI_API_KEY);
SwingUtilities.invokeLater(() -> apiKeyField.setText(apiKey));
});
organizationField = new JBTextField(settings.getOrganization(), 30);
completionModelComboBox = new ComboBox<>(
new EnumComboBoxModel<>(OpenAIChatCompletionModel.class));

View file

@ -1,9 +1,9 @@
package ee.carlrobert.codegpt.settings.service.you;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.YOU_ACCOUNT_PASSWORD;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.ComponentValidator;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.text.StringUtil;
@ -53,7 +53,10 @@ public class YouSettingsForm extends JPanel {
passwordField = new JBPasswordField();
passwordField.setColumns(25);
if (!settings.getEmail().isEmpty()) {
passwordField.setText(CredentialsStore.getCredential(YOU_ACCOUNT_PASSWORD));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
var apiKey = CredentialsStore.getCredential(CredentialKey.YOU_ACCOUNT_PASSWORD);
SwingUtilities.invokeLater(() -> passwordField.setText(apiKey));
});
}
signInButton = new JButton(CodeGPTBundle.get("settingsConfigurable.service.you.signIn.label"));
signUpTextPane = createSignUpTextPane();

View file

@ -3,16 +3,18 @@ package ee.carlrobert.codegpt.credentials
import com.intellij.credentialStore.CredentialAttributes
import com.intellij.credentialStore.generateServiceName
import com.intellij.ide.passwordSafe.PasswordSafe
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
object CredentialsStore {
private val credentialsMap = mutableMapOf<CredentialKey, String?>()
@JvmStatic
@RequiresBackgroundThread
fun getCredential(key: CredentialKey): String? = credentialsMap.getOrPut(key) {
PasswordSafe.instance.getPassword(
CredentialAttributes(generateServiceName("CodeGPT", key.name))
)
) ?: ""
}
fun setCredential(key: CredentialKey, password: String?) {

View file

@ -9,7 +9,6 @@ import com.intellij.ui.components.JBPasswordField
import com.intellij.ui.components.fields.IntegerField
import com.intellij.util.ui.FormBuilder
import ee.carlrobert.codegpt.CodeGPTBundle
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CODEGPT_API_KEY
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
import ee.carlrobert.codegpt.credentials.CredentialsStore.setCredential
@ -18,6 +17,8 @@ import ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels
import ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels.AVAILABLE_CHAT_MODELS
import ee.carlrobert.llm.client.codegpt.CodeGPTAvailableModels.AVAILABLE_CODE_MODELS
import ee.carlrobert.llm.client.codegpt.CodeGPTModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.jdesktop.swingx.combobox.ListComboBoxModel
import java.awt.Component
import javax.swing.DefaultListCellRenderer
@ -28,7 +29,6 @@ class CodeGPTServiceForm {
private val apiKeyField = JBPasswordField().apply {
columns = 30
text = getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
}
private val chatCompletionModelComboBox =
@ -56,6 +56,12 @@ class CodeGPTServiceForm {
value = service<CodeGPTServiceSettings>().state.codeCompletionSettings.maxTokens
}
init {
apiKeyField.text = runBlocking(Dispatchers.IO) {
getCredential(CODEGPT_API_KEY)
}
}
fun getForm(): JPanel = FormBuilder.createFormBuilder()
.addComponent(TitledSeparator(CodeGPTBundle.get("shared.configuration")))
.addComponent(

View file

@ -16,6 +16,8 @@ import ee.carlrobert.codegpt.settings.service.custom.CustomServiceCodeCompletion
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings
import ee.carlrobert.codegpt.settings.service.custom.template.CustomServiceTemplate
import ee.carlrobert.codegpt.ui.UIUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import java.awt.FlowLayout
import java.net.MalformedURLException
import java.net.URL
@ -27,7 +29,6 @@ class CustomServiceForm {
private val apiKeyField = JBPasswordField().apply {
columns = 30
text = getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
}
private val templateHelpText = JBLabel(General.ContextHelp)
private val templateComboBox = ComboBox(EnumComboBoxModel(CustomServiceTemplate::class.java))
@ -37,6 +38,9 @@ class CustomServiceForm {
init {
val state = service<CustomServiceSettings>().state
apiKeyField.text = runBlocking(Dispatchers.IO) {
getCredential(CredentialKey.CUSTOM_SERVICE_API_KEY)
}
chatCompletionsForm =
CustomServiceChatCompletionForm(state.chatCompletionSettings, this::getApiKey)
codeCompletionsForm =

View file

@ -8,10 +8,12 @@ import com.intellij.ui.components.JBPasswordField
import com.intellij.util.ui.FormBuilder
import com.intellij.util.ui.UI
import ee.carlrobert.codegpt.CodeGPTBundle
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.GOOGLE_API_KEY
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
import ee.carlrobert.codegpt.ui.UIUtil
import ee.carlrobert.llm.client.google.models.GoogleModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import javax.swing.JPanel
import javax.swing.event.HyperlinkEvent
@ -23,8 +25,9 @@ class GoogleSettingsForm {
init {
val state = service<GoogleSettings>().state
apiKeyField.columns = 30
apiKeyField.text =
getCredential(CredentialKey.GOOGLE_API_KEY)
apiKeyField.text = runBlocking(Dispatchers.IO) {
getCredential(GOOGLE_API_KEY)
}
completionModelComboBox = ComboBox(
EnumComboBoxModel(GoogleModel::class.java)
)
@ -75,13 +78,12 @@ class GoogleSettingsForm {
fun resetForm() {
val state = service<GoogleSettings>().state
apiKeyField.text =
getCredential(CredentialKey.GOOGLE_API_KEY)
apiKeyField.text = getCredential(GOOGLE_API_KEY)
completionModelComboBox.selectedItem = GoogleModel.findByCode(state.model)
}
fun isModified(): Boolean = service<GoogleSettings>().state.run {
model != getModel() || getApiKey() != getCredential(CredentialKey.GOOGLE_API_KEY)
model != getModel() || getApiKey() != getCredential(GOOGLE_API_KEY)
}
fun applyChanges() {
@ -89,5 +91,4 @@ class GoogleSettingsForm {
model = getModel()
}
}
}