From 6637482752f2e85e2b8940e825c7d336a2200c33 Mon Sep 17 00:00:00 2001 From: Andre Dietisheim Date: Fri, 12 Sep 2025 16:51:04 +0200 Subject: [PATCH 1/4] replaced custom progress dialog with platform means (#23547) Signed-off-by: Andre Dietisheim --- .../devtools/gateway/DevSpacesConnection.kt | 10 +- .../gateway/DevSpacesConnectionProvider.kt | 298 +++++++----------- ...DevSpacesRemoteServerConnectionStepView.kt | 146 ++++----- .../devtools/gateway/view/ui/Dialogs.kt | 7 +- 4 files changed, 180 insertions(+), 281 deletions(-) diff --git a/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt b/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt index 76e3221..b6c5919 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt @@ -34,7 +34,7 @@ class DevSpacesConnection(private val devSpacesContext: DevSpacesContext) { devSpacesContext.isConnected = true try { - return doConnection(onConnected, onDevWorkspaceStopped, onDisconnected) + return doConnect(onConnected, onDevWorkspaceStopped, onDisconnected) } catch (e: Exception) { devSpacesContext.isConnected = false throw e @@ -43,7 +43,7 @@ class DevSpacesConnection(private val devSpacesContext: DevSpacesContext) { @Throws(Exception::class) @Suppress("UnstableApiUsage") - private fun doConnection( + private fun doConnect( onConnected: () -> Unit, onDevWorkspaceStopped: () -> Unit, onDisconnected: () -> Unit @@ -102,11 +102,7 @@ class DevSpacesConnection(private val devSpacesContext: DevSpacesContext) { DevWorkspaces.RUNNING_TIMEOUT ) ) throw IOException( - String.format( - "DevWorkspace '%s' is not running after %d seconds", - devSpacesContext.devWorkspace.metadata.name, - DevWorkspaces.RUNNING_TIMEOUT - ) + "DevWorkspace '${devSpacesContext.devWorkspace.metadata.name}' is not running after ${DevWorkspaces.RUNNING_TIMEOUT} seconds" ) } } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnectionProvider.kt b/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnectionProvider.kt index 177501d..7157707 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnectionProvider.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnectionProvider.kt @@ -12,16 +12,11 @@ package com.redhat.devtools.gateway import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.EDT -import com.intellij.openapi.application.ModalityState import com.intellij.openapi.diagnostic.thisLogger -import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.ui.DialogWrapper -import com.intellij.openapi.ui.Messages +import com.intellij.openapi.progress.ProgressManager import com.intellij.ui.dsl.builder.Align.Companion.CENTER import com.intellij.ui.dsl.builder.panel -import com.intellij.util.ui.JBUI import com.jetbrains.gateway.api.ConnectionRequestor import com.jetbrains.gateway.api.GatewayConnectionHandle import com.jetbrains.gateway.api.GatewayConnectionProvider @@ -34,18 +29,12 @@ import com.redhat.devtools.gateway.util.messageWithoutPrefix import com.redhat.devtools.gateway.view.ui.Dialogs import io.kubernetes.client.openapi.ApiException import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.awt.BorderLayout -import java.awt.Dimension -import javax.swing.Action -import javax.swing.Box -import javax.swing.BoxLayout +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.suspendCancellableCoroutine import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel -import javax.swing.JProgressBar import javax.swing.Timer +import kotlin.coroutines.resume private const val DW_NAMESPACE = "dwNamespace" private const val DW_NAME = "dwName" @@ -57,107 +46,115 @@ private const val DW_NAME = "dwName" */ class DevSpacesConnectionProvider : GatewayConnectionProvider { + @OptIn(ExperimentalCoroutinesApi::class) @Suppress("UnstableApiUsage") override suspend fun connect( parameters: Map, requestor: ConnectionRequestor ): GatewayConnectionHandle? { - val indicator = StartupProgressIndicator("Connecting to Remote IDE...") - ApplicationManager.getApplication().invokeAndWait { indicator.show() } - - return withContext(Dispatchers.IO) { - try { - indicator.setText("Connecting to DevSpace...") - indicator.setIndeterminate(true) - - val handle = doConnect(parameters, indicator) - - val thinClient = handle.clientHandle - ?: throw RuntimeException("Failed to obtain ThinClientHandle") - - indicator.setText("Waiting for remote IDE to start...") - indicator.setText2("Launching environment and initializing IDE window…") - - // Observe signals on thinClient to detect ready/error - val readyDeferred = CompletableDeferred() - - thinClient.onClientPresenceChanged.advise(thinClient.lifetime, - onClientPresenceChanged(readyDeferred, indicator, handle)) - thinClient.clientFailedToOpenProject.advise(thinClient.lifetime, - onClientFailedToOpenProject(readyDeferred, indicator)) - thinClient.clientClosed.advise(thinClient.lifetime, - onClientClosed(readyDeferred, indicator)) + return suspendCancellableCoroutine { cont -> + ProgressManager.getInstance().runProcessWithProgressSynchronously( + { + val indicator = ProgressManager.getInstance().progressIndicator + try { + indicator.isIndeterminate = true + indicator.text = "Connecting to DevSpace..." + + val handle = doConnect(parameters, indicator) + val thinClient = handle.clientHandle + ?: throw RuntimeException("Failed to obtain ThinClientHandle") + + indicator.text = "Waiting for remote IDE to start..." + + val ready = CompletableDeferred() + + thinClient.onClientPresenceChanged.advise(thinClient.lifetime, + onClientPresenceChanged(ready, indicator, handle) + ) + thinClient.clientFailedToOpenProject.advise(thinClient.lifetime, + onClientFailedToOpenProject(ready, indicator) + ) + thinClient.clientClosed.advise(thinClient.lifetime, + onClientClosed(ready, indicator) + ) + ready.invokeOnCompletion { error -> + if (error == null) { + cont.resume(ready.getCompleted()) + } else { + cont.resumeWith(Result.failure(error)) + } + } + } catch (e: ApiException) { + indicator.text = "Connection failed" + runDelayed(2000, { indicator.stop() }) + if (!(handleUnauthorizedError(e) || handleNotFoundError(e))) { + // Dialogs.error is suspend — use a blocking non-suspending dialog instead + Dialogs.error( + e.messageWithoutPrefix() ?: "Could not connect to workspace.", + "Connection Error" + ) + } - readyDeferred.await() - } catch (e: ApiException) { - indicator.setText("Connection failed") - delayedClose(indicator) - if (!(handleUnauthorizedError(e) || handleNotFoundError(e))) { - Dialogs.error(e.messageWithoutPrefix() ?: "Could not connect to workspace.", "Connection Error") - } - null - } catch (e: Exception) { - indicator.setText("Unexpected error: ${e.message}") - delayedClose(indicator) - Dialogs.error(e.messageWithoutPrefix() ?: "Could not connect to workspace.", "Connection Error") + if (cont.isActive) cont.resume(null) + } catch (e: Exception) { + runDelayed(2000) { indicator.stop() } + Dialogs.error( + e.message ?: "Could not connect to workspace.", + "Connection Error" + ) + cont.resume(null) + } + }, + "Connecting to Remote IDE...", + true, null - } finally { - withContext(Dispatchers.EDT) { - if (indicator.isShowing) indicator.close(DialogWrapper.OK_EXIT_CODE) - } - } + ) } } - private fun delayedClose(indicator: StartupProgressIndicator) { - Timer(2000) { - indicator.close(DialogWrapper.CANCEL_EXIT_CODE) - }.start() - } - private fun onClientPresenceChanged( - readyDeferred: CompletableDeferred, - indicator: StartupProgressIndicator, + ready: CompletableDeferred, + indicator: ProgressIndicator, handle: GatewayConnectionHandle ): (Unit) -> Unit = { ApplicationManager.getApplication().invokeLater { - if (!readyDeferred.isCompleted) { - indicator.setText("Remote IDE has started successfully") - indicator.setText2("Opening project window…") - Timer(3000) { - indicator.close(DialogWrapper.OK_EXIT_CODE) - readyDeferred.complete(handle) - }.start() + if (!ready.isCompleted) { + indicator.text = "Remote IDE has started successfully" + indicator.text2 = "Opening project window…" + runDelayed(3000) { + indicator.stop() + ready.complete(handle) + } } } } private fun onClientFailedToOpenProject( - readyDeferred: CompletableDeferred, - indicator: StartupProgressIndicator + ready: CompletableDeferred, + indicator: ProgressIndicator ): (Int) -> Unit = { errorCode -> ApplicationManager.getApplication().invokeLater { - if (!readyDeferred.isCompleted) { - indicator.setText("Failed to open remote project (code: $errorCode)") - Timer(2000) { - indicator.close(DialogWrapper.CANCEL_EXIT_CODE) - readyDeferred.complete(null) - }.start() + if (!ready.isCompleted) { + indicator.text = "Failed to open remote project (code: $errorCode)" + runDelayed(2000) { + indicator.stop() + ready.complete(null) + } } } } private fun onClientClosed( - readyDeferred: CompletableDeferred, - indicator: StartupProgressIndicator + ready: CompletableDeferred, + indicator: ProgressIndicator ): (Unit) -> Unit = { ApplicationManager.getApplication().invokeLater { - if (!readyDeferred.isCompleted) { - indicator.setText("Remote IDE closed unexpectedly.") - Timer(2000) { - indicator.close(DialogWrapper.CANCEL_EXIT_CODE) - readyDeferred.complete(null) - }.start() + if (!ready.isCompleted) { + indicator.text = "Remote IDE closed unexpectedly." + runDelayed(2000) { + indicator.stop() + ready.complete(null) + } } } } @@ -166,11 +163,11 @@ class DevSpacesConnectionProvider : GatewayConnectionProvider { @Throws(IllegalArgumentException::class) private fun doConnect( parameters: Map, - indicator: ProgressIndicator? = null + indicator: ProgressIndicator ): GatewayConnectionHandle { thisLogger().debug("Launched Dev Spaces connection provider", parameters) - indicator?.text2 = "Preparing connection environment…" + indicator.text2 = "Preparing connection environment…" val dwNamespace = parameters[DW_NAMESPACE] if (dwNamespace.isNullOrBlank()) { @@ -184,18 +181,24 @@ class DevSpacesConnectionProvider : GatewayConnectionProvider { throw IllegalArgumentException("Query parameter \"$DW_NAME\" is missing") } - indicator?.text2 = "Initializing Kubernetes connection…" val ctx = DevSpacesContext() + + indicator.text2 = "Initializing Kubernetes connection…" ctx.client = OpenShiftClientFactory().create() - indicator?.text2 = "Fetching DevWorkspace “$dwName” from namespace “$dwNamespace”…" + indicator.text2 = "Fetching DevWorkspace “$dwName” from namespace “$dwNamespace”…" ctx.devWorkspace = DevWorkspaces(ctx.client).get(dwNamespace, dwName) - indicator?.text2 = "Establishing remote IDE connection…" - val thinClient = DevSpacesConnection(ctx).connect({}, {}, {}) + indicator.text2 = "Establishing remote IDE connection…" + val thinClient = DevSpacesConnection(ctx) + .connect({}, {}, {}) - indicator?.text2 = "Connection established successfully." - return DevSpacesConnectionHandle(thinClient.lifetime, thinClient, { createComponent(dwName) }, dwName) + indicator.text2 = "Connection established successfully." + return DevSpacesConnectionHandle( + thinClient.lifetime, + thinClient, + { createComponent(dwName) }, + dwName) } override fun isApplicable(parameters: Map): Boolean { @@ -220,7 +223,7 @@ class DevSpacesConnectionProvider : GatewayConnectionProvider { } } - private suspend fun handleUnauthorizedError(err: ApiException): Boolean { + private fun handleUnauthorizedError(err: ApiException): Boolean { if (!err.isUnauthorized()) return false val tokenNote = if (KubeConfigBuilder.isTokenAuthUsed()) @@ -234,7 +237,7 @@ class DevSpacesConnectionProvider : GatewayConnectionProvider { return true } - private suspend fun handleNotFoundError(err: ApiException): Boolean { + private fun handleNotFoundError(err: ApiException): Boolean { if (!err.isNotFound()) return false val message = """ @@ -248,97 +251,10 @@ class DevSpacesConnectionProvider : GatewayConnectionProvider { return true } - // Common progress dialog to monitor the connection and the renote IDE readiness - private class StartupProgressIndicator ( - initialTitle: String = "Progress Indicator" - ) : DialogWrapper(false), ProgressIndicator { - private val progressBar = JProgressBar().apply { isIndeterminate = true } - private val mainTextLabel = JLabel("Initializing...") - private val subTextLabel = JLabel("") - - @Volatile - private var canceled = false - - init { - title = initialTitle - isModal = false - isResizable = true - init() - } - - fun setIndeterminateValue(indeterminate: Boolean) = ApplicationManager.getApplication().invokeLater { - progressBar.isIndeterminate = indeterminate - } - - fun setFractionValue(fraction: Double) = ApplicationManager.getApplication().invokeLater { - progressBar.isIndeterminate = false - progressBar.value = (fraction * 100).toInt() - } - - override fun createCenterPanel(): JComponent = JPanel(BorderLayout(5, 5)).apply { - border = JBUI.Borders.empty(10) - layout = BoxLayout(this, BoxLayout.Y_AXIS) - add(mainTextLabel) - add(Box.createVerticalStrut(4)) - add(subTextLabel) - add(Box.createVerticalStrut(8)) - add(progressBar) - } - - override fun createActions(): Array = emptyArray() - override fun getPreferredFocusedComponent() = mainTextLabel - override fun getPreferredSize(): Dimension = Dimension(400, 120) - override fun getText(): String = mainTextLabel.text - override fun getText2(): String = subTextLabel.text - - override fun setText(text: String?) = ApplicationManager.getApplication().invokeLater { - mainTextLabel.text = shortenMessage(text ?: "") - subTextLabel.text = "" - } - - override fun setText2(text: String?) = ApplicationManager.getApplication().invokeLater { - subTextLabel.text = shortenMessage(text ?: "") - } - - override fun setIndeterminate(indeterminate: Boolean) = setIndeterminateValue(indeterminate) - override fun isIndeterminate(): Boolean = progressBar.isIndeterminate - - override fun setFraction(fraction: Double) = setFractionValue(fraction) - override fun getFraction(): Double = progressBar.value / 100.0 - - override fun cancel() { - canceled = true - close(CANCEL_EXIT_CODE) - } - - override fun isCanceled(): Boolean = canceled - - override fun start() {} - override fun stop() {} - override fun isRunning(): Boolean = isShowing - override fun pushState() {} - override fun popState() {} - - override fun getModalityState(): ModalityState { - return if (isShowing) ModalityState.current() else ModalityState.nonModal() - } - - override fun setModalityProgress(progressIndicator: ProgressIndicator?) {} - - override fun checkCanceled() { - if (isCanceled) throw ProcessCanceledException() - } - - override fun isPopupWasShown(): Boolean { - return isShowing - } - - private fun shortenMessage(message: String, maxLength: Int = 100): String { - if (message.length <= maxLength) return message - - val head = message.take(maxLength / 2 - 3) - val tail = message.takeLast(maxLength / 2 - 3) - return "$head…$tail" - } + private fun runDelayed(delay: Int, runnable: () -> Unit) { + Timer(delay) { + runnable.invoke() + }.start() } + } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt index 2f04680..58ac65b 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt @@ -11,18 +11,8 @@ */ package com.redhat.devtools.gateway.view.steps -import com.intellij.notification.Notifications -import com.redhat.devtools.gateway.DevSpacesBundle -import com.redhat.devtools.gateway.DevSpacesConnection -import com.redhat.devtools.gateway.DevSpacesContext -import com.redhat.devtools.gateway.openshift.DevWorkspace -import com.redhat.devtools.gateway.openshift.DevWorkspaces -import com.redhat.devtools.gateway.openshift.Projects -import com.redhat.devtools.gateway.openshift.Utils -import com.redhat.devtools.gateway.view.InformationDialog -import com.redhat.devtools.gateway.view.LoaderDialog -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.diagnostic.thisLogger +import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBList @@ -32,15 +22,17 @@ import com.intellij.ui.dsl.builder.RightGap import com.intellij.ui.dsl.builder.panel import com.intellij.util.ui.JBFont import com.intellij.util.ui.JBUI +import com.redhat.devtools.gateway.DevSpacesBundle +import com.redhat.devtools.gateway.DevSpacesConnection +import com.redhat.devtools.gateway.DevSpacesContext +import com.redhat.devtools.gateway.openshift.DevWorkspace +import com.redhat.devtools.gateway.openshift.DevWorkspaces +import com.redhat.devtools.gateway.openshift.Projects +import com.redhat.devtools.gateway.openshift.Utils import com.redhat.devtools.gateway.util.messageWithoutPrefix +import com.redhat.devtools.gateway.view.InformationDialog import com.redhat.devtools.gateway.view.ui.Dialogs -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.internal.notify -import org.jetbrains.concurrency.runAsync import java.awt.Component -import java.awt.EventQueue import javax.swing.DefaultListModel import javax.swing.JButton import javax.swing.JList @@ -81,7 +73,7 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS DevSpacesBundle.message("connector.wizard_step.remote_server_connection.button.refresh") ) { refreshAllDevWorkspaces() - refreshStopButton() + enableStopButton() }.gap(RightGap.SMALL).align(AlignX.RIGHT) } }.apply { @@ -94,7 +86,7 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS listDevWorkspaces.cellRenderer = DevWorkspaceListRenderer() listDevWorkspaces.setEmptyText(DevSpacesBundle.message("connector.wizard_step.remote_server_connection.list.empty_text")) refreshAllDevWorkspaces() - refreshStopButton() + enableStopButton() } override fun onPrevious(): Boolean { @@ -109,19 +101,18 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS } private fun refreshAllDevWorkspaces() { - val d = LoaderDialog( + ProgressManager.getInstance().runProcessWithProgressSynchronously( + { + try { + doRefreshAllDevWorkspaces() + } catch (e: Exception) { + Dialogs.error("Could not refresh workspaces: " + e.messageWithoutPrefix(), "Error Refreshing") + } + }, DevSpacesBundle.message("connector.loader.devspaces.fetching.text"), - component + true, + null ) - ApplicationManager.getApplication().invokeLaterOnWriteThread { d.show() } - - Thread { - try { - doRefreshAllDevWorkspaces() - } finally { - EventQueue.invokeLater { d.hide() } - } - }.start() } private fun refreshDevWorkspace(namespace: String, name: String) { @@ -168,16 +159,20 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS it.metadata.namespace, it.metadata.name ) - - Thread { - if (waitDevWorkspaceStopped(it)) { - refreshDevWorkspace( - it.metadata.namespace, - it.metadata.name - ) - refreshStopButton() - } - }.start() + ProgressManager.getInstance().runProcessWithProgressSynchronously( + { + if (waitDevWorkspaceStopped(it)) { + refreshDevWorkspace( + it.metadata.namespace, + it.metadata.name + ) + enableStopButton() + } + }, + "Refreshing Workspace", + true, + null + ) } } } @@ -201,47 +196,42 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS devSpacesContext.devWorkspace = it } - val loaderDialog = - LoaderDialog( - DevSpacesBundle.message("connector.loader.devspaces.connecting.text"), - component - ) - ApplicationManager.getApplication().invokeLaterOnWriteThread { loaderDialog.show() } - - CoroutineScope(Dispatchers.IO).launch { - try { - DevSpacesConnection(devSpacesContext).connect( - { - EventQueue.invokeLater { loaderDialog.hide() } - refreshDevWorkspace( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name - ) - refreshStopButton() - }, - { - }, - { - if (waitDevWorkspaceStopped(devSpacesContext.devWorkspace)) { + ProgressManager.getInstance().runProcessWithProgressSynchronously( + { + try { + DevSpacesConnection(devSpacesContext).connect( + { refreshDevWorkspace( devSpacesContext.devWorkspace.metadata.namespace, devSpacesContext.devWorkspace.metadata.name ) - refreshStopButton() + enableStopButton() + }, + {}, + { + if (waitDevWorkspaceStopped(devSpacesContext.devWorkspace)) { + refreshDevWorkspace( + devSpacesContext.devWorkspace.metadata.namespace, + devSpacesContext.devWorkspace.metadata.name + ) + enableStopButton() + } } - } - ) - } catch (e: Exception) { - EventQueue.invokeLater { loaderDialog.hide() } - refreshDevWorkspace( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name - ) - refreshStopButton() - thisLogger().error("Remote server connection failed.", e) - Dialogs.error(e.messageWithoutPrefix() ?: "Could not connect to workspace", "Connection Error") - } - } + ) + } catch (e: Exception) { + refreshDevWorkspace( + devSpacesContext.devWorkspace.metadata.namespace, + devSpacesContext.devWorkspace.metadata.name + ) + enableStopButton() + thisLogger().error("Remote server connection failed.", e) + Dialogs.error(e.messageWithoutPrefix() ?: "Could not connect to workspace", "Connection Error") + } + }, + DevSpacesBundle.message("connector.loader.devspaces.connecting.text"), + true, + null + ) } private fun waitDevWorkspaceStopped(devWorkspace: DevWorkspace): Boolean { @@ -254,7 +244,7 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS ) } - private fun refreshStopButton() { + private fun enableStopButton() { stopDevWorkspaceButton.isEnabled = !listDevWorkspaces.isSelectionEmpty && listDWDataModel.get(listDevWorkspaces.minSelectionIndex).spec.started @@ -283,7 +273,7 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS inner class DevWorkspaceSelection : ListSelectionListener { override fun valueChanged(e: ListSelectionEvent) { - refreshStopButton() + enableStopButton() } } } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/ui/Dialogs.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/ui/Dialogs.kt index e6755d5..8a773c7 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/ui/Dialogs.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/ui/Dialogs.kt @@ -2,13 +2,11 @@ package com.redhat.devtools.gateway.view.ui import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.ui.Messages -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext object Dialogs { - suspend fun error(message: String, title: String) { - withContext(Dispatchers.Main) { + fun error(message: String, title: String) { + ApplicationManager.getApplication().invokeLater { Messages.showMessageDialog( message, title, @@ -16,5 +14,4 @@ object Dialogs { ) } } - } \ No newline at end of file From 60eaf3edce270d9110ee75a01b857acd3bffa8c7 Mon Sep 17 00:00:00 2001 From: Andre Dietisheim Date: Mon, 15 Sep 2025 22:50:41 +0200 Subject: [PATCH 2/4] provided getter for DevWorkspace properties Signed-off-by: Andre Dietisheim --- .../devtools/gateway/DevSpacesConnection.kt | 18 +++++----- .../gateway/openshift/DevWorkspace.kt | 34 +++++++++++++++++-- .../gateway/openshift/DevWorkspaces.kt | 2 +- .../gateway/server/RemoteIDEServer.kt | 6 ++-- ...DevSpacesRemoteServerConnectionStepView.kt | 34 +++++++++---------- 5 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt b/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt index b6c5919..e57b2bf 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/DevSpacesConnection.kt @@ -30,7 +30,7 @@ class DevSpacesConnection(private val devSpacesContext: DevSpacesContext) { onDevWorkspaceStopped: () -> Unit, ): ThinClientHandle { if (devSpacesContext.isConnected) - throw IOException(String.format("Already connected to %s", devSpacesContext.devWorkspace.metadata.name)) + throw IOException(String.format("Already connected to %s", devSpacesContext.devWorkspace.name)) devSpacesContext.isConnected = true try { @@ -72,8 +72,8 @@ class DevSpacesConnection(private val devSpacesContext: DevSpacesContext) { if (remoteIdeServer.waitServerTerminated()) DevWorkspaces(devSpacesContext.client) .stop( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.namespace, + devSpacesContext.devWorkspace.name ) .also { onDevWorkspaceStopped() } } @@ -86,23 +86,23 @@ class DevSpacesConnection(private val devSpacesContext: DevSpacesContext) { @Throws(IOException::class, ApiException::class) private fun startAndWaitDevWorkspace() { - if (!devSpacesContext.devWorkspace.spec.started) { + if (!devSpacesContext.devWorkspace.started) { DevWorkspaces(devSpacesContext.client) .start( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.namespace, + devSpacesContext.devWorkspace.name ) } if (!DevWorkspaces(devSpacesContext.client) .waitPhase( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name, + devSpacesContext.devWorkspace.namespace, + devSpacesContext.devWorkspace.name, DevWorkspaces.RUNNING, DevWorkspaces.RUNNING_TIMEOUT ) ) throw IOException( - "DevWorkspace '${devSpacesContext.devWorkspace.metadata.name}' is not running after ${DevWorkspaces.RUNNING_TIMEOUT} seconds" + "DevWorkspace '${devSpacesContext.devWorkspace.name}' is not running after ${DevWorkspaces.RUNNING_TIMEOUT} seconds" ) } } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspace.kt b/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspace.kt index d05b5ef..748895f 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspace.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspace.kt @@ -14,10 +14,31 @@ package com.redhat.devtools.gateway.openshift import java.util.Collections.emptyMap data class DevWorkspace( - val metadata: DevWorkspaceObjectMeta, - val spec: DevWorkspaceSpec, - val status: DevWorkspaceStatus + private val metadata: DevWorkspaceObjectMeta, + private val spec: DevWorkspaceSpec, + private val status: DevWorkspaceStatus ) { + val namespace: String + get() { + return metadata.namespace + } + + val name: String + get() { + return metadata.name + } + + val started: Boolean + get() { + return spec.started + } + + val phase: String + get() { + return status.phase + } + + companion object { fun from(map: Any?) = object { val metadata = Utils.getValue(map, arrayOf("metadata")) ?: emptyMap() @@ -43,6 +64,13 @@ data class DevWorkspace( return true } + + override fun hashCode(): Int { + var result = metadata.hashCode() + result = 31 * result + spec.hashCode() + result = 31 * result + status.hashCode() + return result + } } data class DevWorkspaceObjectMeta( diff --git a/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspaces.kt b/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspaces.kt index 82ce68c..17dd52b 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspaces.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/openshift/DevWorkspaces.kt @@ -107,7 +107,7 @@ class DevWorkspaces(private val client: ApiClient) { try { for (item in watcher) { val devWorkspace = DevWorkspace.from(item.`object`) - if (desiredPhase == devWorkspace.status.phase) { + if (desiredPhase == devWorkspace.phase) { phaseIsDesiredState = true break } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/server/RemoteIDEServer.kt b/src/main/kotlin/com/redhat/devtools/gateway/server/RemoteIDEServer.kt index 9a49f2d..2f2e5f4 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/server/RemoteIDEServer.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/server/RemoteIDEServer.kt @@ -101,17 +101,17 @@ class RemoteIDEServer(private val devSpacesContext: DevSpacesContext) { val selector = String.format( "controller.devfile.io/devworkspace_name=%s", - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.name ) return Pods(devSpacesContext.client) .findFirst( - devSpacesContext.devWorkspace.metadata.namespace, + devSpacesContext.devWorkspace.namespace, selector ) ?: throw IOException( String.format( "DevWorkspace '%s' is not running.", - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.name ) ) } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt index 58ac65b..60d6e6e 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt @@ -156,15 +156,15 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS .also { DevWorkspaces(devSpacesContext.client) .stop( - it.metadata.namespace, - it.metadata.name + it.namespace, + it.name ) ProgressManager.getInstance().runProcessWithProgressSynchronously( { if (waitDevWorkspaceStopped(it)) { refreshDevWorkspace( - it.metadata.namespace, - it.metadata.name + it.namespace, + it.name ) enableStopButton() } @@ -183,7 +183,7 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS "Connection failed", String.format( "Already connected to %s", - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.name ), component ).show() @@ -202,8 +202,8 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS DevSpacesConnection(devSpacesContext).connect( { refreshDevWorkspace( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.namespace, + devSpacesContext.devWorkspace.name ) enableStopButton() }, @@ -211,8 +211,8 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS { if (waitDevWorkspaceStopped(devSpacesContext.devWorkspace)) { refreshDevWorkspace( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.namespace, + devSpacesContext.devWorkspace.name ) enableStopButton() } @@ -220,8 +220,8 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS ) } catch (e: Exception) { refreshDevWorkspace( - devSpacesContext.devWorkspace.metadata.namespace, - devSpacesContext.devWorkspace.metadata.name + devSpacesContext.devWorkspace.namespace, + devSpacesContext.devWorkspace.name ) enableStopButton() thisLogger().error("Remote server connection failed.", e) @@ -237,8 +237,8 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS private fun waitDevWorkspaceStopped(devWorkspace: DevWorkspace): Boolean { return DevWorkspaces(devSpacesContext.client) .waitPhase( - devWorkspace.metadata.namespace, - devWorkspace.metadata.name, + devWorkspace.namespace, + devWorkspace.name, DevWorkspaces.STOPPED, 30 ) @@ -247,7 +247,7 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS private fun enableStopButton() { stopDevWorkspaceButton.isEnabled = !listDevWorkspaces.isSelectionEmpty - && listDWDataModel.get(listDevWorkspaces.minSelectionIndex).spec.started + && listDWDataModel.get(listDevWorkspaces.minSelectionIndex).started } inner class DevWorkspaceListRenderer : ListCellRenderer { @@ -261,9 +261,9 @@ class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevS return JBLabel( String.format( "[%s] %s %s", - devWorkspace.status.phase, - if (!multipleNamespaces) "" else (devWorkspace.metadata.namespace + " /"), - devWorkspace.metadata.name + devWorkspace.phase, + if (!multipleNamespaces) "" else (devWorkspace.namespace + " /"), + devWorkspace.name ) ).also { it.font = JBFont.h4().asPlain() From a939ae6cbbba87e4f42e4793c9d9f6f0f895a0cd Mon Sep 17 00:00:00 2001 From: Andre Dietisheim Date: Tue, 16 Sep 2025 11:24:19 +0200 Subject: [PATCH 3/4] renamed wizard steps to better reflect function Signed-off-by: Andre Dietisheim --- .../devtools/gateway/view/DevSpacesWizardView.kt | 12 ++++++------ ...nectionStepView.kt => DevSpacesServerStepView.kt} | 2 +- ...ionStepView.kt => DevSpacesWorkspacesStepView.kt} | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename src/main/kotlin/com/redhat/devtools/gateway/view/steps/{DevSpacesOpenShiftConnectionStepView.kt => DevSpacesServerStepView.kt} (98%) rename src/main/kotlin/com/redhat/devtools/gateway/view/steps/{DevSpacesRemoteServerConnectionStepView.kt => DevSpacesWorkspacesStepView.kt} (98%) diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/DevSpacesWizardView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/DevSpacesWizardView.kt index b942243..b559ff9 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/DevSpacesWizardView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/DevSpacesWizardView.kt @@ -12,8 +12,8 @@ package com.redhat.devtools.gateway.view import com.redhat.devtools.gateway.DevSpacesContext -import com.redhat.devtools.gateway.view.steps.DevSpacesRemoteServerConnectionStepView -import com.redhat.devtools.gateway.view.steps.DevSpacesOpenShiftConnectionStepView +import com.redhat.devtools.gateway.view.steps.DevSpacesWorkspacesStepView +import com.redhat.devtools.gateway.view.steps.DevSpacesServerStepView import com.redhat.devtools.gateway.view.steps.DevSpacesWizardStep import com.intellij.openapi.Disposable import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager @@ -34,8 +34,8 @@ class DevSpacesWizardView(devSpacesContext: DevSpacesContext) : BorderLayoutPane private var nextButton = JButton() init { - steps.add(DevSpacesOpenShiftConnectionStepView(devSpacesContext)) - steps.add(DevSpacesRemoteServerConnectionStepView(devSpacesContext)) + steps.add(DevSpacesServerStepView(devSpacesContext)) + steps.add(DevSpacesWorkspacesStepView(devSpacesContext)) addToBottom(createButtons()) applyStep(0) @@ -99,7 +99,7 @@ class DevSpacesWizardView(devSpacesContext: DevSpacesContext) : BorderLayoutPane // If this is the RemoteServerConnection step, watch for changes val remoteStep = steps[currentStep] - if (remoteStep is DevSpacesRemoteServerConnectionStepView) { + if (remoteStep is DevSpacesWorkspacesStepView) { val listField = remoteStep.javaClass.getDeclaredField("listDevWorkspaces") listField.isAccessible = true val list = listField.get(remoteStep) as javax.swing.JList<*> @@ -113,7 +113,7 @@ class DevSpacesWizardView(devSpacesContext: DevSpacesContext) : BorderLayoutPane private fun refreshNextButtonState() { val step = steps[currentStep] nextButton.isEnabled = when (step) { - is DevSpacesRemoteServerConnectionStepView -> { + is DevSpacesWorkspacesStepView -> { val listField = step.javaClass.getDeclaredField("listDevWorkspaces") listField.isAccessible = true val list = listField.get(step) as javax.swing.JList<*> diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesOpenShiftConnectionStepView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt similarity index 98% rename from src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesOpenShiftConnectionStepView.kt rename to src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt index 2653f5b..0be85a3 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesOpenShiftConnectionStepView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt @@ -38,7 +38,7 @@ import javax.swing.JComboBox import javax.swing.JTextField -class DevSpacesOpenShiftConnectionStepView(private var devSpacesContext: DevSpacesContext) : DevSpacesWizardStep { +class DevSpacesServerStepView(private var devSpacesContext: DevSpacesContext) : DevSpacesWizardStep { private val allServers = KubeConfigBuilder.getServers() private var tfToken = JBTextField() diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt similarity index 98% rename from src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt rename to src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt index 60d6e6e..9f3b881 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesRemoteServerConnectionStepView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt @@ -40,7 +40,7 @@ import javax.swing.ListCellRenderer import javax.swing.event.ListSelectionEvent import javax.swing.event.ListSelectionListener -class DevSpacesRemoteServerConnectionStepView(private var devSpacesContext: DevSpacesContext) : DevSpacesWizardStep { +class DevSpacesWorkspacesStepView(private var devSpacesContext: DevSpacesContext) : DevSpacesWizardStep { override val nextActionText = DevSpacesBundle.message("connector.wizard_step.remote_server_connection.button.next") override val previousActionText = DevSpacesBundle.message("connector.wizard_step.remote_server_connection.button.previous") From 071c344e90c98732b07655ba9ef588a663dedbbb Mon Sep 17 00:00:00 2001 From: Andre Dietisheim Date: Tue, 16 Sep 2025 18:23:25 +0200 Subject: [PATCH 4/4] replaced InformationDialog by Messages.showMessageDialog Signed-off-by: Andre Dietisheim --- .../devtools/gateway/util/ExceptionUtils.kt | 24 +++++++- .../gateway/view/InformationDialog.kt | 57 ------------------- .../view/steps/DevSpacesServerStepView.kt | 30 +--------- .../view/steps/DevSpacesWorkspacesStepView.kt | 10 +--- 4 files changed, 27 insertions(+), 94 deletions(-) delete mode 100644 src/main/kotlin/com/redhat/devtools/gateway/view/InformationDialog.kt diff --git a/src/main/kotlin/com/redhat/devtools/gateway/util/ExceptionUtils.kt b/src/main/kotlin/com/redhat/devtools/gateway/util/ExceptionUtils.kt index bc60930..8acb7c7 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/util/ExceptionUtils.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/util/ExceptionUtils.kt @@ -11,6 +11,9 @@ */ package com.redhat.devtools.gateway.util +import com.google.gson.Gson +import io.kubernetes.client.openapi.ApiException + fun Throwable.rootMessage(): String { var cause: Throwable? = this @@ -25,4 +28,23 @@ fun Throwable.rootMessage(): String { fun Throwable.messageWithoutPrefix(): String? { return message?.trim() ?: message?.substringAfter(":")?.trim() -} \ No newline at end of file +} + +fun Throwable.message(): String { + return if (this is ApiException) { + message() + } else { + message.orEmpty() + } +} + +fun ApiException.message(): String { + val response = Gson().fromJson(responseBody, Map::class.java) + val msg = try { + response["message"]?.toString() + } catch (e: Exception) { + e.rootMessage() + } + return "Reason: $msg" +} + diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/InformationDialog.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/InformationDialog.kt deleted file mode 100644 index 0a5a861..0000000 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/InformationDialog.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package com.redhat.devtools.gateway.view - -import com.intellij.openapi.ui.DialogWrapper -import com.intellij.ui.components.JBLabel -import com.intellij.ui.dsl.builder.AlignX -import com.intellij.ui.dsl.builder.panel -import com.intellij.util.ui.JBUI -import java.awt.Component -import java.awt.Dimension -import javax.swing.Action -import javax.swing.JComponent -class InformationDialog(title: String, private var text: String, parent: Component) : DialogWrapper(parent, false) { - init { - super.init() - this.title = title - } - - override fun createActions(): Array { - return arrayOf(this.okAction) - } - - override fun createCenterPanel(): JComponent { - return panel { - row { - cell(JBLabel(text)).resizableColumn().align(AlignX.FILL) - } - } - } - - override fun getInitialSize(): Dimension { - // Get FontMetrics for the title bar font (uses Label font as a proxy) - val fontMetrics = JBLabel().getFontMetrics(JBUI.Fonts.label()) - - // Measure title string width in pixels - val titleWidth = fontMetrics.stringWidth(title) - - // Get the preferred height from the center panel - val contentSize = createCenterPanel().preferredSize - - // Add some padding for window borders and buttons - val extraWidth = JBUI.scale(100) - - return Dimension(titleWidth + extraWidth, contentSize.height + extraWidth) - } - -} diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt index 0be85a3..5f611d5 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesServerStepView.kt @@ -11,8 +11,6 @@ */ package com.redhat.devtools.gateway.view.steps -import com.google.gson.Gson -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager @@ -27,11 +25,10 @@ import com.redhat.devtools.gateway.openshift.OpenShiftClientFactory import com.redhat.devtools.gateway.openshift.Projects import com.redhat.devtools.gateway.openshift.kube.KubeConfigBuilder import com.redhat.devtools.gateway.settings.DevSpacesSettings -import com.redhat.devtools.gateway.util.rootMessage -import com.redhat.devtools.gateway.view.InformationDialog +import com.redhat.devtools.gateway.util.message +import com.redhat.devtools.gateway.view.ui.Dialogs import com.redhat.devtools.gateway.view.ui.FilteringComboBox import com.redhat.devtools.gateway.view.ui.PasteClipboardMenu -import io.kubernetes.client.openapi.ApiException import io.kubernetes.client.openapi.auth.ApiKeyAuth import io.kubernetes.client.util.Config import javax.swing.JComboBox @@ -91,10 +88,7 @@ class DevSpacesServerStepView(private var devSpacesContext: DevSpacesContext) : Projects(client).list() success = true } catch (e: Exception) { - val errorMsg = getMessage(e) - ApplicationManager.getApplication().invokeLater { - InformationDialog("Connection failed", errorMsg, component).show() - } + Dialogs.error(e.message(), "Connection failed") throw e } }, @@ -111,24 +105,6 @@ class DevSpacesServerStepView(private var devSpacesContext: DevSpacesContext) : return success } - private fun getMessage(e: Exception): String { - return if (e is ApiException) { - getMessage(e) - } else { - e.message.orEmpty() - } - } - - private fun getMessage(e: ApiException): String { - val response = Gson().fromJson(e.responseBody, Map::class.java) - val msg = try { - response["message"]?.toString() - } catch (e: Exception) { - e.rootMessage() - } - return String.format("Reason: %s", msg) - } - private fun loadOpenShiftConnectionSettings() { tfServer.removeAllItems() allServers.forEach { tfServer.addItem(it) } diff --git a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt index 9f3b881..14c09de 100644 --- a/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt +++ b/src/main/kotlin/com/redhat/devtools/gateway/view/steps/DevSpacesWorkspacesStepView.kt @@ -30,7 +30,6 @@ import com.redhat.devtools.gateway.openshift.DevWorkspaces import com.redhat.devtools.gateway.openshift.Projects import com.redhat.devtools.gateway.openshift.Utils import com.redhat.devtools.gateway.util.messageWithoutPrefix -import com.redhat.devtools.gateway.view.InformationDialog import com.redhat.devtools.gateway.view.ui.Dialogs import java.awt.Component import javax.swing.DefaultListModel @@ -179,14 +178,7 @@ class DevSpacesWorkspacesStepView(private var devSpacesContext: DevSpacesContext private fun connect() { if (devSpacesContext.isConnected) { - InformationDialog( - "Connection failed", - String.format( - "Already connected to %s", - devSpacesContext.devWorkspace.name - ), - component - ).show() + Dialogs.error("Already connected to ${devSpacesContext.devWorkspace.name}", "Connection failed") return }