@@ -3,15 +3,14 @@ package com.coder.toolbox
33import com.coder.toolbox.cli.CoderCLIManager
44import com.coder.toolbox.sdk.CoderRestClient
55import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
6- import com.coder.toolbox.settings.SettingSource
76import com.coder.toolbox.util.CoderProtocolHandler
87import com.coder.toolbox.util.DialogUi
98import com.coder.toolbox.views.Action
9+ import com.coder.toolbox.views.AuthWizardPage
1010import com.coder.toolbox.views.CoderSettingsPage
11- import com.coder.toolbox.views.ConnectPage
1211import 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
1514import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon
1615import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon.IconType
1716import com.jetbrains.toolbox.api.core.util.LoadableState
@@ -32,7 +31,6 @@ import kotlinx.coroutines.selects.onTimeout
3231import kotlinx.coroutines.selects.select
3332import java.net.SocketTimeoutException
3433import java.net.URI
35- import java.net.URL
3634import kotlin.coroutines.cancellation.CancellationException
3735import kotlin.time.Duration.Companion.seconds
3836import kotlin.time.TimeSource
@@ -67,7 +65,7 @@ class CoderRemoteProvider(
6765 // On the first load, automatically log in if we can.
6866 private var firstRun = true
6967 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 ? : " " ))
7169 private val linkHandler = CoderProtocolHandler (context, dialogUi, isInitialized)
7270 override val environments: MutableStateFlow <LoadableState <List <RemoteProviderEnvironment >>> = MutableStateFlow (
7371 LoadableState .Value (emptyList())
@@ -177,7 +175,7 @@ class CoderRemoteProvider(
177175 private fun logout () {
178176 // Keep the URL and token to make it easy to log back in, but set
179177 // rememberMe to false so we do not try to automatically log in.
180- context.secrets.rememberMe = " false"
178+ context.secrets.rememberMe = false
181179 close()
182180 }
183181
@@ -189,7 +187,7 @@ class CoderRemoteProvider(
189187 if (username != null ) {
190188 return dropDownFactory(context.i18n.pnotr(username)) {
191189 logout()
192- context.ui.showUiPage(getOverrideUiPage() !! )
190+ context.envPageManager.showPluginEnvironmentsPage( )
193191 }
194192 }
195193 return null
@@ -215,6 +213,7 @@ class CoderRemoteProvider(
215213 environments.value = LoadableState .Value (emptyList())
216214 isInitialized.update { false }
217215 client = null
216+ AuthWizardState .resetSteps()
218217 }
219218
220219 override val svgIcon: SvgIcon =
@@ -293,7 +292,7 @@ class CoderRemoteProvider(
293292 /* *
294293 * Return the sign-in page if we do not have a valid client.
295294
296- * Otherwise return null, which causes Toolbox to display the environment
295+ * Otherwise, return null, which causes Toolbox to display the environment
297296 * list.
298297 */
299298 override fun getOverrideUiPage (): UiPage ? {
@@ -306,7 +305,8 @@ class CoderRemoteProvider(
306305 context.secrets.lastDeploymentURL.let { lastDeploymentURL ->
307306 if (autologin && lastDeploymentURL.isNotBlank() && (lastToken.isNotBlank() || ! settings.requireTokenAuth)) {
308307 try {
309- return createConnectPage(URL (lastDeploymentURL), lastToken)
308+ AuthWizardState .goToStep(WizardStep .LOGIN )
309+ return AuthWizardPage (context, true , ::onConnect)
310310 } catch (ex: Exception ) {
311311 autologinEx = ex
312312 }
@@ -316,84 +316,29 @@ class CoderRemoteProvider(
316316 firstRun = false
317317
318318 // 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)
332320 // 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) }
334322 // 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) }
336324
337- return signInPage
325+ return authWizard
338326 }
339327 return null
340328 }
341329
342- private fun shouldDoAutoLogin (): Boolean = firstRun && context.secrets.rememberMe == " true"
330+ private fun shouldDoAutoLogin (): Boolean = firstRun && context.secrets.rememberMe == true
343331
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 ) {
353333 // Store the URL and token for use next time.
354334 context.secrets.lastDeploymentURL = client.url.toString()
355335 context.secrets.lastToken = client.token ? : " "
356336 // Currently we always remember, but this could be made an option.
357- context.secrets.rememberMe = " true"
337+ context.secrets.rememberMe = true
358338 this .client = client
359339 pollError = null
360340 pollJob?.cancel()
361341 pollJob = poll(client, cli)
362342 goToEnvironmentsPage()
363343 }
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- }
399344}
0 commit comments