Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import com.intellij.openapi.project.DumbAwareAction
import com.intellij.util.messages.Topic
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindow
import software.aws.toolkits.resources.AmazonQBundle
import software.aws.toolkits.resources.message
import java.util.EventListener

class QRefreshPanelAction : DumbAwareAction(AmazonQBundle.message("amazonq.refresh.panel"), null, AllIcons.Actions.Refresh) {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
// recreate chat browser
AmazonQToolWindow.getInstance(project).disposeAndRecreate()
AmazonQToolWindow.getInstance(project).recreatePanel()
// recreate signin browser
QWebviewPanel.getInstance(project).disposeAndRecreate()
RefreshQChatPanelButtonPressedListener.notifyRefresh()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.wm.ToolWindowManager
import kotlinx.coroutines.CoroutineScope
import software.aws.toolkits.jetbrains.services.amazonq.onboarding.OnboardingPageInteraction
Expand All @@ -25,8 +24,7 @@ class AmazonQToolWindow private constructor(
val component
get() = chatPanel.component

fun disposeAndRecreate() {
Disposer.dispose(chatPanel)
Copy link
Contributor

@Will-ShaoHua Will-ShaoHua May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what will happen if we keep creating new panel and they are never disposed, will it cause memory leak (but idk how to test it..)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes we would need to dispose if we are creating new panels

fun recreatePanel() {
chatPanel = AmazonQPanel(project, scope)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manodnyab will it help if we assign the new panel first then dispose the stale one?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe not, just tested

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#5729 would fix the crash issue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this part, if 5729 fixes the crash

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
object : BearerTokenProviderListener {
override fun onChange(providerId: String, newScopes: List<String>?) {
if (ToolkitConnectionManager.getInstance(project).connectionStateForFeature(QConnection.getInstance()) == BearerTokenAuthState.AUTHORIZED) {
AmazonQToolWindow.getInstance(project).disposeAndRecreate()
AmazonQToolWindow.getInstance(project).recreatePanel()
prepareChatContent(project, qPanel)
}
}
Expand All @@ -98,7 +98,7 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
// note we name myProject intentionally ow it will shadow the "project" provided by the IDE
override fun onProfileSelected(myProject: Project, profile: QRegionProfile?) {
if (project.isDisposed) return
AmazonQToolWindow.getInstance(project).disposeAndRecreate()
AmazonQToolWindow.getInstance(project).recreatePanel()
prepareChatContent(project, qPanel)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.CHAT_
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ErrorParams
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.GetSerializedChatResult
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.SEND_CHAT_COMMAND_PROMPT
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileDialog
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileManager
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSelectedListener
import java.util.UUID
Expand Down Expand Up @@ -140,19 +141,30 @@ class ChatCommunicationManager(private val cs: CoroutineScope) {
val incomingType = params.authFollowupType
val connectionManager = ToolkitConnectionManager.getInstance(project)
try {
connectionManager.activeConnectionForFeature(QConnection.getInstance())?.let {
reauthConnectionIfNeeded(project, it, isReAuth = true)
}

when (incomingType) {
AuthFollowupType.USE_SUPPORTED_AUTH -> {
project.messageBus.syncPublisher(QRegionProfileSelectedListener.TOPIC)
.onProfileSelected(project, QRegionProfileManager.getInstance().activeProfile(project))
val activeProfile = QRegionProfileManager.getInstance().activeProfile(project)
if(activeProfile != null) {
project.messageBus.syncPublisher(QRegionProfileSelectedListener.TOPIC)
.onProfileSelected(project, QRegionProfileManager.getInstance().activeProfile(project))
} else {
QRegionProfileDialog(
project,
selectedProfile = null
).show()
}


return
}
AuthFollowupType.RE_AUTH,
AuthFollowupType.MISSING_SCOPES,
AuthFollowupType.FULL_AUTH,
-> {
connectionManager.activeConnectionForFeature(QConnection.getInstance())?.let {
reauthConnectionIfNeeded(project, it, isReAuth = true)
}
return
}
else -> {
Expand Down
Loading