Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0852d88

Browse files
authored
impl: report progress while handling URI (#180)
Up until now there was no progress while downloading CLI, setting up thecli and the ssh config while handling URIs. This PR reworks the urihandler and the connection screen to be able to reuse the later part inthe URI handler. This should improve the experience because the user isno longer left in the dark for a good couple of seconds.
1 parentacd0578 commit0852d88

File tree

8 files changed

+91
-79
lines changed

8 files changed

+91
-79
lines changed

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
##Unreleased
44

5+
###Added
6+
7+
- progress reporting while handling URIs
8+
59
###Changed
610

711
- workspaces status is now refresh every time Coder Toolbox becomes visible

‎src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt‎

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import com.coder.toolbox.sdk.ex.APIResponseException
77
importcom.coder.toolbox.sdk.v2.models.WorkspaceStatus
88
importcom.coder.toolbox.util.CoderProtocolHandler
99
importcom.coder.toolbox.util.DialogUi
10+
importcom.coder.toolbox.util.toURL
1011
importcom.coder.toolbox.util.waitForTrue
1112
importcom.coder.toolbox.util.withPath
1213
importcom.coder.toolbox.views.Action
1314
importcom.coder.toolbox.views.CoderCliSetupWizardPage
1415
importcom.coder.toolbox.views.CoderSettingsPage
1516
importcom.coder.toolbox.views.NewEnvironmentPage
17+
importcom.coder.toolbox.views.state.CoderCliSetupContext
1618
importcom.coder.toolbox.views.state.CoderCliSetupWizardState
1719
importcom.coder.toolbox.views.state.WizardStep
1820
importcom.jetbrains.toolbox.api.core.ui.icons.SvgIcon
@@ -35,7 +37,6 @@ import kotlinx.coroutines.launch
3537
importkotlinx.coroutines.selects.onTimeout
3638
importkotlinx.coroutines.selects.select
3739
importjava.net.URI
38-
importjava.util.UUID
3940
importkotlin.coroutines.cancellation.CancellationException
4041
importkotlin.time.Duration.Companion.seconds
4142
importkotlin.time.TimeSource
@@ -66,19 +67,18 @@ class CoderRemoteProvider(
6667
privatevar firstRun=true
6768
privateval isInitialized:MutableStateFlow<Boolean>=MutableStateFlow(false)
6869
privateval coderHeaderPage=NewEnvironmentPage(context.i18n.pnotr(context.deploymentUrl.toString()))
69-
privateval linkHandler=CoderProtocolHandler(context, dialogUi, isInitialized)
70-
71-
overrideval loadingEnvironmentsDescription:LocalizableString= context.i18n.ptrl("Loading workspaces...")
72-
overrideval environments:MutableStateFlow<LoadableState<List<CoderRemoteEnvironment>>>=MutableStateFlow(
73-
LoadableState.Loading
74-
)
75-
7670
privateval visibilityState=MutableStateFlow(
7771
ProviderVisibilityState(
7872
applicationVisible=false,
7973
providerVisible=false
8074
)
8175
)
76+
privateval linkHandler=CoderProtocolHandler(context, dialogUi, settingsPage, visibilityState, isInitialized)
77+
78+
overrideval loadingEnvironmentsDescription:LocalizableString= context.i18n.ptrl("Loading workspaces...")
79+
overrideval environments:MutableStateFlow<LoadableState<List<CoderRemoteEnvironment>>>=MutableStateFlow(
80+
LoadableState.Loading
81+
)
8282

8383
privateval errorBuffer= mutableListOf<Throwable>()
8484

@@ -311,17 +311,8 @@ class CoderRemoteProvider(
311311
overridesuspendfunhandleUri(uri:URI) {
312312
try {
313313
linkHandler.handle(
314-
uri, shouldDoAutoSetup(),
315-
{
316-
coderHeaderPage.isBusyCreatingNewEnvironment.update {
317-
true
318-
}
319-
},
320-
{
321-
coderHeaderPage.isBusyCreatingNewEnvironment.update {
322-
false
323-
}
324-
}
314+
uri,
315+
shouldDoAutoSetup()
325316
) { restClient, cli->
326317
// stop polling and de-initialize resources
327318
close()
@@ -337,23 +328,16 @@ class CoderRemoteProvider(
337328
isInitialized.waitForTrue()
338329
}
339330
}catch (ex:Exception) {
340-
context.logger.error(ex,"")
341331
val textError=if (exisAPIResponseException) {
342332
if (!ex.reason.isNullOrBlank()) {
343333
ex.reason
344334
}else ex.message
345335
}else ex.message
346-
347-
context.ui.showSnackbar(
348-
UUID.randomUUID().toString(),
349-
context.i18n.ptrl("Error encountered while handling Coder URI"),
350-
context.i18n.pnotr(textError?:""),
351-
context.i18n.ptrl("Dismiss")
336+
context.logAndShowError(
337+
"Error encountered while handling Coder URI",
338+
textError?:""
352339
)
353-
}finally {
354-
coderHeaderPage.isBusyCreatingNewEnvironment.update {
355-
false
356-
}
340+
context.envPageManager.showPluginEnvironmentsPage()
357341
}
358342
}
359343

@@ -369,8 +353,17 @@ class CoderRemoteProvider(
369353
// When coming back to the application, initializeSession immediately.
370354
if (shouldDoAutoSetup()) {
371355
try {
356+
CoderCliSetupContext.apply {
357+
url= context.secrets.lastDeploymentURL.toURL()
358+
token= context.secrets.lastToken
359+
}
372360
CoderCliSetupWizardState.goToStep(WizardStep.CONNECT)
373-
returnCoderCliSetupWizardPage(context, settingsPage, visibilityState,true, ::onConnect)
361+
returnCoderCliSetupWizardPage(
362+
context, settingsPage, visibilityState,
363+
initialAutoSetup=true,
364+
jumpToMainPageOnError=false,
365+
onConnect= ::onConnect
366+
)
374367
}catch (ex:Exception) {
375368
errorBuffer.add(ex)
376369
}finally {

‎src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,9 @@ data class CoderToolboxContext(
8888
i18n.ptrl("OK")
8989
)
9090
}
91+
92+
funpopupPluginMainPage() {
93+
this.ui.showWindow()
94+
this.envPageManager.showPluginEnvironmentsPage(true)
95+
}
9196
}

‎src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt‎

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@ import com.coder.toolbox.sdk.v2.models.Workspace
1010
importcom.coder.toolbox.sdk.v2.models.WorkspaceAgent
1111
importcom.coder.toolbox.sdk.v2.models.WorkspaceStatus
1212
importcom.coder.toolbox.util.WebUrlValidationResult.Invalid
13+
importcom.coder.toolbox.views.CoderCliSetupWizardPage
14+
importcom.coder.toolbox.views.CoderSettingsPage
15+
importcom.coder.toolbox.views.state.CoderCliSetupContext
16+
importcom.coder.toolbox.views.state.CoderCliSetupWizardState
17+
importcom.coder.toolbox.views.state.WizardStep
18+
importcom.jetbrains.toolbox.api.remoteDev.ProviderVisibilityState
1319
importcom.jetbrains.toolbox.api.remoteDev.connection.RemoteToolsHelper
1420
importkotlinx.coroutines.Job
1521
importkotlinx.coroutines.TimeoutCancellationException
1622
importkotlinx.coroutines.delay
23+
importkotlinx.coroutines.flow.MutableStateFlow
1724
importkotlinx.coroutines.flow.StateFlow
1825
importkotlinx.coroutines.launch
1926
importkotlinx.coroutines.time.withTimeout
@@ -25,12 +32,13 @@ import kotlin.time.Duration.Companion.seconds
2532
importkotlin.time.toJavaDuration
2633

2734
privateconstvalCAN_T_HANDLE_URI_TITLE="Can't handle URI"
28-
privateval noOpTextProgress: (String)->Unit= { _-> }
2935

3036
@Suppress("UnstableApiUsage")
3137
openclassCoderProtocolHandler(
3238
privatevalcontext:CoderToolboxContext,
3339
privatevaldialogUi:DialogUi,
40+
privatevalsettingsPage:CoderSettingsPage,
41+
privatevalvisibilityState:MutableStateFlow<ProviderVisibilityState>,
3442
privatevalisInitialized:StateFlow<Boolean>,
3543
) {
3644
privateval settings= context.settingsStore.readOnly()
@@ -45,8 +53,6 @@ open class CoderProtocolHandler(
4553
suspendfunhandle(
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,53 @@ open class CoderProtocolHandler(
6772
val deploymentURL= resolveDeploymentUrl(params)?:return
6873
val token=if (!context.settingsStore.requireTokenAuth)nullelse 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+
suspendfunonConnect(
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+
valagent: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()
104+
105+
if (!productCode.isNullOrBlank()&&!buildNumber.isNullOrBlank()) {
106+
launchIde(environmentId, productCode, buildNumber, projectFolder)
107+
}
108+
}
99109

100-
if (!productCode.isNullOrBlank()&&!buildNumber.isNullOrBlank()) {
101-
launchIde(environmentId, productCode, buildNumber, projectFolder)
110+
CoderCliSetupContext.apply {
111+
url= deploymentURL.toURL()
112+
CoderCliSetupContext.token= token
102113
}
114+
CoderCliSetupWizardState.goToStep(WizardStep.CONNECT)
115+
context.ui.showUiPage(
116+
CoderCliSetupWizardPage(
117+
context, settingsPage, visibilityState,true,
118+
jumpToMainPageOnError=true,
119+
onConnect= ::onConnect
120+
)
121+
)
103122
}
104123

105124
privatesuspendfunresolveDeploymentUrl(params:Map<String,String>):String? {
@@ -308,13 +327,14 @@ open class CoderProtocolHandler(
308327

309328
privatesuspendfunconfigureCli(
310329
deploymentURL:String,
311-
restClient:CoderRestClient
330+
restClient:CoderRestClient,
331+
progressReporter: (String)->Unit
312332
):CoderCLIManager {
313333
val cli= ensureCLI(
314334
context,
315335
deploymentURL.toURL(),
316336
restClient.buildInfo().version,
317-
noOpTextProgress
337+
progressReporter
318338
)
319339

320340
// We only need to log in if we are using token-based auth.
@@ -455,12 +475,6 @@ open class CoderProtocolHandler(
455475
}
456476
}
457477

458-
459-
privatefun CoderToolboxContext.popupPluginMainPage() {
460-
this.ui.showWindow()
461-
this.envPageManager.showPluginEnvironmentsPage(true)
462-
}
463-
464478
privatesuspendfun CoderToolboxContext.showEnvironmentPage(envId:String) {
465479
this.ui.showWindow()
466480
this.envPageManager.showEnvironmentPage(envId,false)

‎src/main/kotlin/com/coder/toolbox/views/CoderCliSetupWizardPage.kt‎

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import com.coder.toolbox.CoderToolboxContext
44
importcom.coder.toolbox.cli.CoderCLIManager
55
importcom.coder.toolbox.sdk.CoderRestClient
66
importcom.coder.toolbox.sdk.ex.APIResponseException
7-
importcom.coder.toolbox.util.toURL
8-
importcom.coder.toolbox.views.state.CoderCliSetupContext
97
importcom.coder.toolbox.views.state.CoderCliSetupWizardState
108
importcom.coder.toolbox.views.state.WizardStep
119
importcom.jetbrains.toolbox.api.remoteDev.ProviderVisibilityState
@@ -21,6 +19,7 @@ class CoderCliSetupWizardPage(
2119
privatevalsettingsPage:CoderSettingsPage,
2220
privatevalvisibilityState:MutableStateFlow<ProviderVisibilityState>,
2321
initialAutoSetup:Boolean =false,
22+
jumpToMainPageOnError:Boolean =false,
2423
onConnect:suspend (
2524
client:CoderRestClient,
2625
cli:CoderCLIManager,
@@ -35,7 +34,8 @@ class CoderCliSetupWizardPage(
3534
privateval tokenStep=TokenStep(context)
3635
privateval connectStep=ConnectStep(
3736
context,
38-
shouldAutoSetup,
37+
shouldAutoLogin= shouldAutoSetup,
38+
jumpToMainPageOnError,
3939
this::notify,
4040
this::displaySteps,
4141
onConnect
@@ -49,13 +49,6 @@ class CoderCliSetupWizardPage(
4949

5050
privateval errorBuffer= mutableListOf<Throwable>()
5151

52-
init {
53-
if (shouldAutoSetup.value) {
54-
CoderCliSetupContext.url= context.secrets.lastDeploymentURL.toURL()
55-
CoderCliSetupContext.token= context.secrets.lastToken
56-
}
57-
}
58-
5952
overridefunbeforeShow() {
6053
displaySteps()
6154
if (errorBuffer.isNotEmpty()&& visibilityState.value.applicationVisible) {

‎src/main/kotlin/com/coder/toolbox/views/CoderPage.kt‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
packagecom.coder.toolbox.views
22

3-
importcom.coder.toolbox.CoderToolboxContext
43
importcom.jetbrains.toolbox.api.core.ui.icons.SvgIcon
54
importcom.jetbrains.toolbox.api.core.ui.icons.SvgIcon.IconType
65
importcom.jetbrains.toolbox.api.localization.LocalizableString
@@ -43,12 +42,6 @@ abstract class CoderPage(
4342
}else {
4443
SvgIcon(byteArrayOf(), type=IconType.Masked)
4544
}
46-
47-
overrideval isBusyCreatingNewEnvironment:MutableStateFlow<Boolean>=MutableStateFlow(false)
48-
49-
companionobject {
50-
funemptyPage(ctx:CoderToolboxContext):UiPage=UiPage(ctx.i18n.pnotr(""))
51-
}
5245
}
5346

5447
/**

‎src/main/kotlin/com/coder/toolbox/views/ConnectStep.kt‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ private const val USER_HIT_THE_BACK_BUTTON = "User hit the back button"
2525
classConnectStep(
2626
privatevalcontext:CoderToolboxContext,
2727
privatevalshouldAutoLogin:StateFlow<Boolean>,
28+
privatevaljumpToMainPageOnError:Boolean,
2829
privatevalnotify: (String,Throwable)->Unit,
2930
privatevalrefreshWizard: ()->Unit,
3031
privatevalonConnect:suspend (
@@ -127,7 +128,11 @@ class ConnectStep(
127128
}finally {
128129
if (shouldAutoLogin.value) {
129130
CoderCliSetupContext.reset()
130-
CoderCliSetupWizardState.goToFirstStep()
131+
if (jumpToMainPageOnError) {
132+
context.popupPluginMainPage()
133+
}else {
134+
CoderCliSetupWizardState.goToFirstStep()
135+
}
131136
}else {
132137
if (context.settingsStore.requireTokenAuth) {
133138
CoderCliSetupWizardState.goToPreviousStep()

‎src/test/kotlin/com/coder/toolbox/util/CoderProtocolHandlerTest.kt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import com.coder.toolbox.sdk.DataGen
55
importcom.coder.toolbox.settings.Environment
66
importcom.coder.toolbox.store.CoderSecretsStore
77
importcom.coder.toolbox.store.CoderSettingsStore
8+
importcom.coder.toolbox.views.CoderSettingsPage
89
importcom.jetbrains.toolbox.api.core.diagnostics.Logger
910
importcom.jetbrains.toolbox.api.core.os.LocalDesktopManager
1011
importcom.jetbrains.toolbox.api.localization.LocalizableStringFactory
12+
importcom.jetbrains.toolbox.api.remoteDev.ProviderVisibilityState
1113
importcom.jetbrains.toolbox.api.remoteDev.connection.ClientHelper
1214
importcom.jetbrains.toolbox.api.remoteDev.connection.RemoteToolsHelper
1315
importcom.jetbrains.toolbox.api.remoteDev.connection.ToolboxProxySettings
@@ -16,6 +18,7 @@ import com.jetbrains.toolbox.api.remoteDev.ui.EnvironmentUiPageManager
1618
importcom.jetbrains.toolbox.api.ui.ToolboxUi
1719
importio.mockk.mockk
1820
importkotlinx.coroutines.CoroutineScope
21+
importkotlinx.coroutines.channels.Channel
1922
importkotlinx.coroutines.flow.MutableStateFlow
2023
importkotlinx.coroutines.runBlocking
2124
importorg.junit.jupiter.api.DisplayName
@@ -43,6 +46,8 @@ internal class CoderProtocolHandlerTest {
4346
privateval protocolHandler=CoderProtocolHandler(
4447
context,
4548
DialogUi(context),
49+
CoderSettingsPage(context,Channel(Channel.CONFLATED)),
50+
MutableStateFlow(ProviderVisibilityState(applicationVisible=true, providerVisible=true)),
4651
MutableStateFlow(false)
4752
)
4853

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp