diff --git a/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties b/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties
index 79ecca81754..c4eaa3ec9fd 100644
--- a/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties
+++ b/plugins/amazonq/shared/jetbrains-community/resources/software/aws/toolkits/resources/AmazonQBundle.properties
@@ -1,4 +1,3 @@
-action.q.hello.description=Hello description
amazonqInlineChat.hint.edit = Edit
amazonqInlineChat.popup.accept=Accept \u23CE
amazonqInlineChat.popup.cancel=Cancel \u238B
@@ -10,9 +9,9 @@ amazonqInlineChat.popup.title=Enter Instructions for Q
amazonq.refresh.panel=Refresh Chat Session
amazonq.title=Amazon Q
amazonq.workspace.settings.open.prompt=Workspace index is now enabled. You can disable it from Amazon Q settings.
-action.q.profile.usage.text=You changed profile
-action.q.profile.usage=You're using the '{0}' profile for Amazon Q.
-action.q.switchProfiles.text=Change profile
+action.q.profile.usage.text=You changed your profile
+action.q.profile.usage=You''re using the ''{0}'' profile for Amazon Q.
+action.q.switchProfiles.text=Change Profile
action.q.switchProfiles.dialog.text=Amazon Q Developer Profile
action.q.switchProfiles.dialog.account.label=Account: {0}
action.q.switchProfiles.dialog.panel.text=Change your Q Developer profile
diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/actions/QSwitchProfilesAction.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/actions/QSwitchProfilesAction.kt
index 2e8949d0f66..4735d748a62 100644
--- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/actions/QSwitchProfilesAction.kt
+++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/actions/QSwitchProfilesAction.kt
@@ -7,17 +7,10 @@ import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.DumbAware
-import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
-import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
-import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
-import software.aws.toolkits.jetbrains.services.amazonq.profile.QProfileSwitchIntent
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileDialog
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
import software.aws.toolkits.resources.AmazonQBundle.message
-import software.aws.toolkits.telemetry.MetricResult
-import software.aws.toolkits.telemetry.Telemetry
class QSwitchProfilesAction : AnAction(message("action.q.switchProfiles.text")), DumbAware {
@@ -29,30 +22,9 @@ class QSwitchProfilesAction : AnAction(message("action.q.switchProfiles.text")),
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
- ApplicationManager.getApplication().executeOnPooledThread {
- val profiles = try {
- QRegionProfileManager.getInstance().listRegionProfiles(project)
- } catch (e: Exception) {
- val conn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) as? AwsBearerTokenConnection
- Telemetry.amazonq.didSelectProfile.use { span ->
- span.source(QProfileSwitchIntent.User.value)
- .amazonQProfileRegion(QRegionProfileManager.getInstance().activeProfile(project)?.region ?: "not-set")
- .ssoRegion(conn?.region)
- .credentialStartUrl(conn?.startUrl)
- .result(MetricResult.Failed)
- .reason(e.message)
- }
- throw e
- }
- ?: error("Attempted to fetch profiles while there does not exist")
- val selectedProfile = QRegionProfileManager.getInstance().activeProfile(project) ?: profiles[0]
- ApplicationManager.getApplication().invokeLater {
- QRegionProfileDialog(
- project,
- profiles = profiles,
- selectedProfile = selectedProfile
- ).show()
- }
- }
+ QRegionProfileDialog(
+ project,
+ selectedProfile = QRegionProfileManager.getInstance().activeProfile(project)
+ ).show()
}
}
diff --git a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileDialog.kt b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileDialog.kt
index ead6ab5aca3..c0921f3362f 100644
--- a/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileDialog.kt
+++ b/plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/profile/QRegionProfileDialog.kt
@@ -7,24 +7,61 @@ import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.DialogWrapper
+import com.intellij.ui.ColoredListCellRenderer
+import com.intellij.ui.SimpleTextAttributes
+import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.BottomGap
-import com.intellij.ui.dsl.builder.bind
+import com.intellij.ui.dsl.builder.bindItem
import com.intellij.ui.dsl.builder.panel
+import com.intellij.ui.dsl.builder.toNullableProperty
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
import software.aws.toolkits.jetbrains.core.help.HelpIds
+import software.aws.toolkits.jetbrains.ui.AsyncComboBox
+import software.aws.toolkits.jetbrains.utils.ui.selected
import software.aws.toolkits.resources.AmazonQBundle.message
+import software.aws.toolkits.resources.AwsCoreBundle
import software.aws.toolkits.telemetry.MetricResult
import software.aws.toolkits.telemetry.Telemetry
import javax.swing.JComponent
+import javax.swing.JList
+
+data class QRegionProfileDialogState(
+ var selectedProfile: QRegionProfile? = null,
+)
class QRegionProfileDialog(
private var project: Project,
- private var profiles: List,
- private var selectedProfile: QRegionProfile, // default
+ val state: QRegionProfileDialogState = QRegionProfileDialogState(),
+ private var selectedProfile: QRegionProfile?,
) : DialogWrapper(project) {
+ private val renderer = object : ColoredListCellRenderer() {
+ override fun customizeCellRenderer(
+ list: JList,
+ value: QRegionProfile?,
+ index: Int,
+ selected: Boolean,
+ hasFocus: Boolean,
+ ) {
+ value?.let {
+ append(
+ if (it == selectedProfile) {
+ "${it.profileName} - ${it.region} (connected)"
+ } else {
+ "${it.profileName} - ${it.region}"
+ },
+ SimpleTextAttributes.REGULAR_ATTRIBUTES
+ )
+
+ append(" " + message("action.q.switchProfiles.dialog.account.label", it.accountId), SimpleTextAttributes.GRAY_SMALL_ATTRIBUTES)
+ }
+ }
+ }
+
+ private val combo = AsyncComboBox(customRenderer = renderer)
+
private val panel: DialogPanel by lazy {
panel {
row { label(message("action.q.switchProfiles.dialog.panel.text")).bold() }
@@ -36,32 +73,40 @@ class QRegionProfileDialog(
}
separator().bottomGap(BottomGap.MEDIUM)
- buttonsGroup {
- profiles.forEach { profile ->
- row {
- radioButton("", profile)
-
- panel {
- val regionDisplay = if (profile == selectedProfile) {
- "${profile.profileName} - ${profile.region} (connected)"
- } else {
- "${profile.profileName} - ${profile.region}"
- }
- row { label(regionDisplay) }
- row {
- label(message("action.q.switchProfiles.dialog.account.label", profile.accountId)).applyToComponent {
- font = font.deriveFont(font.size2D - 2.0f)
- }
- }
- }
- }.bottomGap(BottomGap.MEDIUM)
+ combo.proposeModelUpdate { model ->
+ try {
+ QRegionProfileManager.getInstance().listRegionProfiles(project)?.forEach {
+ model.addElement(it)
+ } ?: error("Attempted to fetch profiles while there does not exist")
+
+ model.selectedItem = selectedProfile
+ } catch (e: Exception) {
+ val conn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) as? AwsBearerTokenConnection
+ Telemetry.amazonq.didSelectProfile.use { span ->
+ span.source(QProfileSwitchIntent.User.value)
+ .amazonQProfileRegion(QRegionProfileManager.getInstance().activeProfile(project)?.region ?: "not-set")
+ .ssoRegion(conn?.region)
+ .credentialStartUrl(conn?.startUrl)
+ .result(MetricResult.Failed)
+ .reason(e.message)
+ }
+ throw e
}
- }.bind({ selectedOption }, { selectedOption = it })
+ }
+
+ row {
+ cell(combo)
+ .align(AlignX.FILL)
+ .errorOnApply(AwsCoreBundle.message("gettingstarted.setup.error.not_selected")) { it.selected() == null }
+ .bindItem(state::selectedProfile.toNullableProperty())
+ }
separator().bottomGap(BottomGap.MEDIUM)
}
}
- private var selectedOption: QRegionProfile = selectedProfile // user selected
+
+ private val selectedOption
+ get() = state.selectedProfile // user selected
init {
title = message("action.q.switchProfiles.dialog.text")
@@ -87,7 +132,7 @@ class QRegionProfileDialog(
Telemetry.amazonq.didSelectProfile.use { span ->
span.source(QProfileSwitchIntent.User.value)
.amazonQProfileRegion(profileManager.activeProfile(project)?.region ?: "not-set")
- .profileCount(profiles.size)
+ .profileCount(combo.model.size)
.ssoRegion(conn?.region)
.credentialStartUrl(conn?.startUrl)
.result(MetricResult.Cancelled)