@@ -3,15 +3,14 @@ package com.coder.toolbox
3
3
import com.coder.toolbox.cli.CoderCLIManager
4
4
import com.coder.toolbox.sdk.CoderRestClient
5
5
import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
6
- import com.coder.toolbox.settings.SettingSource
7
6
import com.coder.toolbox.util.CoderProtocolHandler
8
7
import com.coder.toolbox.util.DialogUi
9
8
import com.coder.toolbox.views.Action
9
+ import com.coder.toolbox.views.AuthWizardPage
10
10
import com.coder.toolbox.views.CoderSettingsPage
11
- import com.coder.toolbox.views.ConnectPage
12
11
import com.coder.toolbox.views.NewEnvironmentPage
13
- import com.coder.toolbox.views.SignInPage
14
- import com.coder.toolbox.views.TokenPage
12
+ import com.coder.toolbox.views.state.AuthWizardState
13
+ import com.coder.toolbox.views.state.WizardStep
15
14
import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon
16
15
import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon.IconType
17
16
import com.jetbrains.toolbox.api.core.util.LoadableState
@@ -32,7 +31,6 @@ import kotlinx.coroutines.selects.onTimeout
32
31
import kotlinx.coroutines.selects.select
33
32
import java.net.SocketTimeoutException
34
33
import java.net.URI
35
- import java.net.URL
36
34
import kotlin.coroutines.cancellation.CancellationException
37
35
import kotlin.time.Duration.Companion.seconds
38
36
import kotlin.time.TimeSource
@@ -67,7 +65,7 @@ class CoderRemoteProvider(
67
65
// On the first load, automatically log in if we can.
68
66
private var firstRun = true
69
67
private val isInitialized: MutableStateFlow <Boolean > = MutableStateFlow (false )
70
- private var coderHeaderPage = NewEnvironmentPage (context, context.i18n.pnotr(getDeploymentURL() ?.first ? : " " ))
68
+ private var coderHeaderPage = NewEnvironmentPage (context, context.i18n.pnotr(context.deploymentUrl ?.first ? : " " ))
71
69
private val linkHandler = CoderProtocolHandler (context, dialogUi, isInitialized)
72
70
override val environments: MutableStateFlow <LoadableState <List <RemoteProviderEnvironment >>> = MutableStateFlow (
73
71
LoadableState .Value (emptyList())
@@ -177,7 +175,7 @@ class CoderRemoteProvider(
177
175
private fun logout () {
178
176
// Keep the URL and token to make it easy to log back in, but set
179
177
// rememberMe to false so we do not try to automatically log in.
180
- context.secrets.rememberMe = " false"
178
+ context.secrets.rememberMe = false
181
179
close()
182
180
}
183
181
@@ -189,7 +187,7 @@ class CoderRemoteProvider(
189
187
if (username != null ) {
190
188
return dropDownFactory(context.i18n.pnotr(username)) {
191
189
logout()
192
- context.ui.showUiPage(getOverrideUiPage() !! )
190
+ context.envPageManager.showPluginEnvironmentsPage( )
193
191
}
194
192
}
195
193
return null
@@ -215,6 +213,7 @@ class CoderRemoteProvider(
215
213
environments.value = LoadableState .Value (emptyList())
216
214
isInitialized.update { false }
217
215
client = null
216
+ AuthWizardState .resetSteps()
218
217
}
219
218
220
219
override val svgIcon: SvgIcon =
@@ -293,7 +292,7 @@ class CoderRemoteProvider(
293
292
/* *
294
293
* Return the sign-in page if we do not have a valid client.
295
294
296
- * Otherwise return null, which causes Toolbox to display the environment
295
+ * Otherwise, return null, which causes Toolbox to display the environment
297
296
* list.
298
297
*/
299
298
override fun getOverrideUiPage (): UiPage ? {
@@ -306,7 +305,8 @@ class CoderRemoteProvider(
306
305
context.secrets.lastDeploymentURL.let { lastDeploymentURL ->
307
306
if (autologin && lastDeploymentURL.isNotBlank() && (lastToken.isNotBlank() || ! settings.requireTokenAuth)) {
308
307
try {
309
- return createConnectPage(URL (lastDeploymentURL), lastToken)
308
+ AuthWizardState .goToStep(WizardStep .LOGIN )
309
+ return AuthWizardPage (context, true , ::onConnect)
310
310
} catch (ex: Exception ) {
311
311
autologinEx = ex
312
312
}
@@ -316,84 +316,29 @@ class CoderRemoteProvider(
316
316
firstRun = false
317
317
318
318
// Login flow.
319
- val signInPage =
320
- SignInPage (context, getDeploymentURL()) { deploymentURL ->
321
- context.ui.showUiPage(
322
- TokenPage (
323
- context,
324
- deploymentURL,
325
- getToken(deploymentURL)
326
- ) { selectedToken ->
327
- context.ui.showUiPage(createConnectPage(deploymentURL, selectedToken))
328
- },
329
- )
330
- }
331
-
319
+ val authWizard = AuthWizardPage (context, false , ::onConnect)
332
320
// We might have tried and failed to automatically log in.
333
- autologinEx?.let { signInPage .notify(" Error logging in" , it) }
321
+ autologinEx?.let { authWizard .notify(" Error logging in" , it) }
334
322
// We might have navigated here due to a polling error.
335
- pollError?.let { signInPage .notify(" Error fetching workspaces" , it) }
323
+ pollError?.let { authWizard .notify(" Error fetching workspaces" , it) }
336
324
337
- return signInPage
325
+ return authWizard
338
326
}
339
327
return null
340
328
}
341
329
342
- private fun shouldDoAutoLogin (): Boolean = firstRun && context.secrets.rememberMe == " true"
330
+ private fun shouldDoAutoLogin (): Boolean = firstRun && context.secrets.rememberMe == true
343
331
344
- /* *
345
- * Create a connect page that starts polling and resets the UI on success.
346
- */
347
- private fun createConnectPage (deploymentURL : URL , token : String? ): ConnectPage = ConnectPage (
348
- context,
349
- deploymentURL,
350
- token,
351
- ::goToEnvironmentsPage,
352
- ) { client, cli ->
332
+ private fun onConnect (client : CoderRestClient , cli : CoderCLIManager ) {
353
333
// Store the URL and token for use next time.
354
334
context.secrets.lastDeploymentURL = client.url.toString()
355
335
context.secrets.lastToken = client.token ? : " "
356
336
// Currently we always remember, but this could be made an option.
357
- context.secrets.rememberMe = " true"
337
+ context.secrets.rememberMe = true
358
338
this .client = client
359
339
pollError = null
360
340
pollJob?.cancel()
361
341
pollJob = poll(client, cli)
362
342
goToEnvironmentsPage()
363
343
}
364
-
365
- /* *
366
- * Try to find a token.
367
- *
368
- * Order of preference:
369
- *
370
- * 1. Last used token, if it was for this deployment.
371
- * 2. Token on disk for this deployment.
372
- * 3. Global token for Coder, if it matches the deployment.
373
- */
374
- private fun getToken (deploymentURL : URL ): Pair <String , SettingSource >? = context.secrets.lastToken.let {
375
- if (it.isNotBlank() && context.secrets.lastDeploymentURL == deploymentURL.toString()) {
376
- it to SettingSource .LAST_USED
377
- } else {
378
- settings.token(deploymentURL)
379
- }
380
- }
381
-
382
- /* *
383
- * Try to find a URL.
384
- *
385
- * In order of preference:
386
- *
387
- * 1. Last used URL.
388
- * 2. URL in settings.
389
- * 3. CODER_URL.
390
- * 4. URL in global cli config.
391
- */
392
- private fun getDeploymentURL (): Pair <String , SettingSource >? = context.secrets.lastDeploymentURL.let {
393
- if (it.isNotBlank()) {
394
- it to SettingSource .LAST_USED
395
- } else {
396
- context.settingsStore.defaultURL()
397
- }
398
- }
399
344
}
0 commit comments