@@ -10,10 +10,17 @@ import com.coder.toolbox.sdk.v2.models.Workspace
1010import com.coder.toolbox.sdk.v2.models.WorkspaceAgent
1111import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
1212import com.coder.toolbox.util.WebUrlValidationResult.Invalid
13+ import com.coder.toolbox.views.CoderCliSetupWizardPage
14+ import com.coder.toolbox.views.CoderSettingsPage
15+ import com.coder.toolbox.views.state.CoderCliSetupContext
16+ import com.coder.toolbox.views.state.CoderCliSetupWizardState
17+ import com.coder.toolbox.views.state.WizardStep
18+ import com.jetbrains.toolbox.api.remoteDev.ProviderVisibilityState
1319import com.jetbrains.toolbox.api.remoteDev.connection.RemoteToolsHelper
1420import kotlinx.coroutines.Job
1521import kotlinx.coroutines.TimeoutCancellationException
1622import kotlinx.coroutines.delay
23+ import kotlinx.coroutines.flow.MutableStateFlow
1724import kotlinx.coroutines.flow.StateFlow
1825import kotlinx.coroutines.launch
1926import kotlinx.coroutines.time.withTimeout
@@ -25,12 +32,13 @@ import kotlin.time.Duration.Companion.seconds
2532import kotlin.time.toJavaDuration
2633
2734private const val CAN_T_HANDLE_URI_TITLE = " Can't handle URI"
28- private val noOpTextProgress: (String ) -> Unit = { _ -> }
2935
3036@Suppress(" UnstableApiUsage" )
3137open class CoderProtocolHandler (
3238 private val context : CoderToolboxContext ,
3339 private val dialogUi : DialogUi ,
40+ private val settingsPage : CoderSettingsPage ,
41+ private val visibilityState : MutableStateFlow <ProviderVisibilityState >,
3442 private val isInitialized : StateFlow <Boolean >,
3543) {
3644 private val settings = context.settingsStore.readOnly()
@@ -45,8 +53,6 @@ open class CoderProtocolHandler(
4553 suspend fun handle (
4654 uri : URI ,
4755 shouldWaitForAutoLogin : Boolean ,
48- markAsBusy : () -> Unit ,
49- unmarkAsBusy : () -> Unit ,
5056 reInitialize : suspend (CoderRestClient , CoderCLIManager ) -> Unit
5157 ) {
5258 val params = uri.toQueryParameters()
@@ -58,7 +64,6 @@ open class CoderProtocolHandler(
5864 // this switches to the main plugin screen, even
5965 // if last opened provider was not Coder
6066 context.envPageManager.showPluginEnvironmentsPage()
61- markAsBusy()
6267 if (shouldWaitForAutoLogin) {
6368 isInitialized.waitForTrue()
6469 }
@@ -67,39 +72,47 @@ open class CoderProtocolHandler(
6772 val deploymentURL = resolveDeploymentUrl(params) ? : return
6873 val token = if (! context.settingsStore.requireTokenAuth) null else resolveToken(params) ? : return
6974 val workspaceName = resolveWorkspaceName(params) ? : return
70- val restClient = buildRestClient(deploymentURL, token) ? : return
71- val workspace = restClient.workspaces().matchName(workspaceName, deploymentURL) ? : return
7275
73- val cli = configureCli(deploymentURL, restClient)
74-
75- var agent: WorkspaceAgent
76- try {
76+ suspend fun onConnect (
77+ restClient : CoderRestClient ,
78+ cli : CoderCLIManager
79+ ) {
80+ val workspace = restClient.workspaces().matchName(workspaceName, deploymentURL)
81+ if (workspace == null ) {
82+ context.envPageManager.showPluginEnvironmentsPage()
83+ return
84+ }
7785 reInitialize(restClient, cli)
7886 context.envPageManager.showPluginEnvironmentsPage()
7987 if (! prepareWorkspace(workspace, restClient, workspaceName, deploymentURL)) return
8088 // we resolve the agent after the workspace is started otherwise we can get misleading
8189 // errors like: no agent available while workspace is starting or stopping
8290 // we also need to retrieve the workspace again to have the latest resources (ex: agent)
8391 // attached to the workspace.
84- agent = resolveAgent(
92+ val agent: WorkspaceAgent = resolveAgent(
8593 params,
8694 restClient.workspace(workspace.id)
8795 ) ? : return
8896 if (! ensureAgentIsReady(workspace, agent)) return
89- } finally {
90- unmarkAsBusy()
91- }
92- delay(2 .seconds)
93- val environmentId = " ${workspace.name} .${agent.name} "
94- context.showEnvironmentPage(environmentId)
97+ delay(2 .seconds)
98+ val environmentId = " ${workspace.name} .${agent.name} "
99+ context.showEnvironmentPage(environmentId)
95100
96- val productCode = params.ideProductCode()
97- val buildNumber = params.ideBuildNumber()
98- val projectFolder = params.projectFolder()
101+ val productCode = params.ideProductCode()
102+ val buildNumber = params.ideBuildNumber()
103+ val projectFolder = params.projectFolder()
99104
100- if (! productCode.isNullOrBlank() && ! buildNumber.isNullOrBlank()) {
101- launchIde(environmentId, productCode, buildNumber, projectFolder)
105+ if (! productCode.isNullOrBlank() && ! buildNumber.isNullOrBlank()) {
106+ launchIde(environmentId, productCode, buildNumber, projectFolder)
107+ }
108+ }
109+
110+ CoderCliSetupContext .apply {
111+ url = deploymentURL.toURL()
112+ CoderCliSetupContext .token = token
102113 }
114+ CoderCliSetupWizardState .goToStep(WizardStep .CONNECT )
115+ context.ui.showUiPage(CoderCliSetupWizardPage (context, settingsPage, visibilityState, true , ::onConnect))
103116 }
104117
105118 private suspend fun resolveDeploymentUrl (params : Map <String , String >): String? {
@@ -308,13 +321,14 @@ open class CoderProtocolHandler(
308321
309322 private suspend fun configureCli (
310323 deploymentURL : String ,
311- restClient : CoderRestClient
324+ restClient : CoderRestClient ,
325+ progressReporter : (String ) -> Unit
312326 ): CoderCLIManager {
313327 val cli = ensureCLI(
314328 context,
315329 deploymentURL.toURL(),
316330 restClient.buildInfo().version,
317- noOpTextProgress
331+ progressReporter
318332 )
319333
320334 // We only need to log in if we are using token-based auth.
0 commit comments