@@ -3,6 +3,7 @@ package com.coder.gateway.views.steps
3
3
import com.coder.gateway.CoderGatewayBundle
4
4
import com.coder.gateway.icons.CoderIcons
5
5
import com.coder.gateway.models.CoderWorkspacesWizardModel
6
+ import com.coder.gateway.models.WorkspaceAgentModel
6
7
import com.coder.gateway.sdk.Arch
7
8
import com.coder.gateway.sdk.CoderRestClientService
8
9
import com.coder.gateway.sdk.OS
@@ -38,10 +39,13 @@ import com.jetbrains.gateway.ssh.HighLevelHostAccessor
38
39
import com.jetbrains.gateway.ssh.IdeStatus
39
40
import com.jetbrains.gateway.ssh.IdeWithStatus
40
41
import com.jetbrains.gateway.ssh.IntelliJPlatformProduct
42
+ import kotlinx.coroutines.CancellationException
41
43
import kotlinx.coroutines.CoroutineScope
42
44
import kotlinx.coroutines.Dispatchers
45
+ import kotlinx.coroutines.Job
43
46
import kotlinx.coroutines.async
44
47
import kotlinx.coroutines.cancel
48
+ import kotlinx.coroutines.cancelAndJoin
45
49
import kotlinx.coroutines.launch
46
50
import kotlinx.coroutines.withContext
47
51
import java.awt.Component
@@ -67,6 +71,8 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
67
71
private lateinit var tfProject: JBTextField
68
72
private lateinit var terminalLink: LazyBrowserLink
69
73
74
+ private lateinit var ideResolvingJob: Job
75
+
70
76
override val component = panel {
71
77
indent {
72
78
row {
@@ -107,6 +113,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
107
113
override val nextActionText = CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.next.text" )
108
114
109
115
override fun onInit (wizardModel : CoderWorkspacesWizardModel ) {
116
+ ideComboBoxModel.removeAllElements()
110
117
wizard = wizardModel
111
118
val selectedWorkspace = wizardModel.selectedWorkspace
112
119
if (selectedWorkspace == null ) {
@@ -118,61 +125,73 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
118
125
titleLabel.text = CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.choose.text" , selectedWorkspace.name)
119
126
terminalLink.url = " ${coderClient.coderURL} /@${coderClient.me.username} /${selectedWorkspace.name} /terminal"
120
127
121
- cs.launch {
122
- logger.info(" Retrieving available IDE's for ${selectedWorkspace.name} workspace..." )
123
- val hostAccessor = HighLevelHostAccessor .create(
124
- RemoteCredentialsHolder ().apply {
125
- setHost(" coder.${selectedWorkspace.name} " )
126
- userName = " coder"
127
- authType = AuthType .OPEN_SSH
128
- },
129
- true
130
- )
131
- val workspaceOS = if (selectedWorkspace.agentOS != null && selectedWorkspace.agentArch != null ) toDeployedOS(selectedWorkspace.agentOS, selectedWorkspace.agentArch) else withContext(Dispatchers .IO ) {
132
- try {
133
- hostAccessor.guessOs()
134
- } catch (e: Exception ) {
135
- logger.error(" Could not resolve any IDE for workspace ${selectedWorkspace.name} . Reason: $e " )
136
- null
137
- }
138
- }
139
- if (workspaceOS == null ) {
140
- disableNextAction()
141
- cbIDE.renderer = object : ColoredListCellRenderer <IdeWithStatus >() {
142
- override fun customizeCellRenderer (list : JList <out IdeWithStatus >, value : IdeWithStatus ? , index : Int , isSelected : Boolean , cellHasFocus : Boolean ) {
143
- background = UIUtil .getListBackground(isSelected, cellHasFocus)
144
- icon = UIUtil .getBalloonErrorIcon()
145
- append(CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.ide.error.text" , selectedWorkspace.name))
128
+ ideResolvingJob = cs.launch {
129
+ try {
130
+ retrieveIDES(selectedWorkspace)
131
+ } catch (e: Exception ) {
132
+ when (e) {
133
+ is InterruptedException -> Unit
134
+ is CancellationException -> Unit
135
+ else -> {
136
+ logger.error(" Could not resolve any IDE for workspace ${selectedWorkspace.name} . Reason: $e " )
137
+ withContext(Dispatchers .Main ) {
138
+ disableNextAction()
139
+ cbIDE.renderer = object : ColoredListCellRenderer <IdeWithStatus >() {
140
+ override fun customizeCellRenderer (list : JList <out IdeWithStatus >, value : IdeWithStatus ? , index : Int , isSelected : Boolean , cellHasFocus : Boolean ) {
141
+ background = UIUtil .getListBackground(isSelected, cellHasFocus)
142
+ icon = UIUtil .getBalloonErrorIcon()
143
+ append(CoderGatewayBundle .message(" gateway.connector.view.coder.remoteproject.ide.error.text" , selectedWorkspace.name))
144
+ }
145
+ }
146
+ }
146
147
}
147
148
}
148
- } else {
149
- logger.info(" Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS " )
150
- val installedIdesJob = async(Dispatchers .IO ) {
151
- hostAccessor.getInstalledIDEs().map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .ALREADY_INSTALLED , null , ide.pathToIde, ide.presentableVersion, ide.remoteDevType) }
152
- }
153
- val idesWithStatusJob = async(Dispatchers .IO ) {
154
- IntelliJPlatformProduct .values()
155
- .filter { it.showInGateway }
156
- .flatMap { CachingProductsJsonWrapper .getInstance().getAvailableIdes(it, workspaceOS) }
157
- .map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .DOWNLOAD , ide.download, null , ide.presentableVersion, ide.remoteDevType) }
158
- }
149
+ }
150
+ }
151
+ }
159
152
160
- val installedIdes = installedIdesJob.await()
161
- val idesWithStatus = idesWithStatusJob.await()
162
- if (installedIdes.isEmpty()) {
163
- logger.info(" No IDE is installed in workspace ${selectedWorkspace.name} " )
164
- } else {
165
- ideComboBoxModel.addAll(installedIdes)
166
- cbIDE.selectedIndex = 0
167
- }
153
+ private suspend fun retrieveIDES (selectedWorkspace : WorkspaceAgentModel ) {
154
+ logger.info(" Retrieving available IDE's for ${selectedWorkspace.name} workspace..." )
155
+ val hostAccessor = HighLevelHostAccessor .create(
156
+ RemoteCredentialsHolder ().apply {
157
+ setHost(" coder.${selectedWorkspace.name} " )
158
+ userName = " coder"
159
+ authType = AuthType .OPEN_SSH
160
+ },
161
+ true
162
+ )
163
+ val workspaceOS = if (selectedWorkspace.agentOS != null && selectedWorkspace.agentArch != null ) toDeployedOS(selectedWorkspace.agentOS, selectedWorkspace.agentArch) else withContext(Dispatchers .IO ) {
164
+ hostAccessor.guessOs()
165
+ }
168
166
169
- if (idesWithStatus.isEmpty()) {
170
- logger.warn(" Could not resolve any IDE for workspace ${selectedWorkspace.name} , probably $workspaceOS is not supported by Gateway" )
171
- } else {
167
+ logger.info(" Resolved OS and Arch for ${selectedWorkspace.name} is: $workspaceOS " )
168
+ val installedIdesJob = cs.async(Dispatchers .IO ) {
169
+ hostAccessor.getInstalledIDEs().map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .ALREADY_INSTALLED , null , ide.pathToIde, ide.presentableVersion, ide.remoteDevType) }
170
+ }
171
+ val idesWithStatusJob = cs.async(Dispatchers .IO ) {
172
+ IntelliJPlatformProduct .values()
173
+ .filter { it.showInGateway }
174
+ .flatMap { CachingProductsJsonWrapper .getInstance().getAvailableIdes(it, workspaceOS) }
175
+ .map { ide -> IdeWithStatus (ide.product, ide.buildNumber, IdeStatus .DOWNLOAD , ide.download, null , ide.presentableVersion, ide.remoteDevType) }
176
+ }
172
177
173
- ideComboBoxModel.addAll(idesWithStatus)
174
- cbIDE.selectedIndex = 0
175
- }
178
+ val installedIdes = installedIdesJob.await()
179
+ val idesWithStatus = idesWithStatusJob.await()
180
+ if (installedIdes.isEmpty()) {
181
+ logger.info(" No IDE is installed in workspace ${selectedWorkspace.name} " )
182
+ } else {
183
+ withContext(Dispatchers .Main ) {
184
+ ideComboBoxModel.addAll(installedIdes)
185
+ cbIDE.selectedIndex = 0
186
+ }
187
+ }
188
+
189
+ if (idesWithStatus.isEmpty()) {
190
+ logger.warn(" Could not resolve any IDE for workspace ${selectedWorkspace.name} , probably $workspaceOS is not supported by Gateway" )
191
+ } else {
192
+ withContext(Dispatchers .Main ) {
193
+ ideComboBoxModel.addAll(idesWithStatus)
194
+ cbIDE.selectedIndex = 0
176
195
}
177
196
}
178
197
}
@@ -201,6 +220,7 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
201
220
202
221
override fun onNext (wizardModel : CoderWorkspacesWizardModel ): Boolean {
203
222
val selectedIDE = cbIDE.selectedItem ? : return false
223
+ logger.info(" Going to launch the IDE" )
204
224
cs.launch {
205
225
GatewayUI .getInstance().connect(
206
226
selectedIDE
@@ -213,12 +233,16 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
213
233
return true
214
234
}
215
235
216
- override fun dispose () {
217
- cs.cancel()
236
+ override fun onPrevious () {
237
+ super .onPrevious()
238
+ logger.info(" Going back to Workspace view" )
239
+ cs.launch {
240
+ ideResolvingJob.cancelAndJoin()
241
+ }
218
242
}
219
243
220
- companion object {
221
- val logger = Logger .getInstance( CoderLocateRemoteProjectStepView :: class .java.simpleName )
244
+ override fun dispose () {
245
+ cs.cancel( )
222
246
}
223
247
224
248
private class IDEComboBox (model : ComboBoxModel <IdeWithStatus >) : ComboBox<IdeWithStatus>(model) {
@@ -258,4 +282,8 @@ class CoderLocateRemoteProjectStepView(private val disableNextAction: () -> Unit
258
282
}
259
283
}
260
284
}
285
+
286
+ companion object {
287
+ val logger = Logger .getInstance(CoderLocateRemoteProjectStepView ::class .java.simpleName)
288
+ }
261
289
}
0 commit comments