Skip to content

Commit ee07b8d

Browse files
committed
impl: support uri handling (1)
- reacts to uris like: jetbrains://gateway/com.coder.toolbox?url=https%3A%2F%2Fdev.coder.com&token=....&workspace=bobiverse-bill - the handling still does not work correctly when Toolbox is already running.
1 parent 2b18fe4 commit ee07b8d

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

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

+6-8
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import com.coder.toolbox.services.CoderSecretsService
77
import com.coder.toolbox.services.CoderSettingsService
88
import com.coder.toolbox.settings.CoderSettings
99
import com.coder.toolbox.settings.Source
10+
import com.coder.toolbox.util.CoderProtocolHandler
1011
import com.coder.toolbox.util.DialogUi
11-
import com.coder.toolbox.util.LinkHandler
1212
import com.coder.toolbox.util.toQueryParameters
1313
import com.coder.toolbox.views.Action
1414
import com.coder.toolbox.views.CoderSettingsPage
@@ -47,13 +47,15 @@ class CoderRemoteProvider(
4747
private var pollJob: Job? = null
4848
private var lastEnvironments: Set<CoderRemoteEnvironment>? = null
4949

50+
private val isInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
51+
5052
// Create our services from the Toolbox ones.
5153
private val settingsService = CoderSettingsService(context.settingsStore)
5254
private val settings: CoderSettings = CoderSettings(settingsService, context.logger)
5355
private val secrets: CoderSecretsService = CoderSecretsService(context.secretsStore)
5456
private val settingsPage: CoderSettingsPage = CoderSettingsPage(context, settingsService)
5557
private val dialogUi = DialogUi(context, settings)
56-
private val linkHandler = LinkHandler(context, settings, httpClient, dialogUi)
58+
private val linkHandler = CoderProtocolHandler(context, settings, httpClient, dialogUi, isInitialized)
5759

5860
// The REST client, if we are signed in
5961
private var client: CoderRestClient? = null
@@ -65,7 +67,6 @@ class CoderRemoteProvider(
6567

6668
// On the first load, automatically log in if we can.
6769
private var firstRun = true
68-
6970
override val environments: MutableStateFlow<LoadableState<List<RemoteProviderEnvironment>>> = MutableStateFlow(
7071
LoadableState.Value(emptyList())
7172
)
@@ -234,11 +235,7 @@ class CoderRemoteProvider(
234235
*/
235236
override suspend fun handleUri(uri: URI) {
236237
val params = uri.toQueryParameters()
237-
context.cs.launch {
238-
val name = linkHandler.handle(params)
239-
// TODO@JB: Now what? How do we actually connect this workspace?
240-
context.logger.debug("External request for $name: $uri")
241-
}
238+
linkHandler.handle(params)
242239
}
243240

244241
/**
@@ -323,6 +320,7 @@ class CoderRemoteProvider(
323320
pollJob?.cancel()
324321
pollJob = poll(client, cli)
325322
goToEnvironmentsPage()
323+
isInitialized.update { true }
326324
}
327325

328326
/**

src/main/kotlin/com/coder/toolbox/util/LinkHandler.kt renamed to src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt

+21-6
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@ import com.coder.toolbox.sdk.v2.models.WorkspaceAgent
1111
import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
1212
import com.coder.toolbox.settings.CoderSettings
1313
import com.coder.toolbox.settings.Source
14+
import kotlinx.coroutines.flow.StateFlow
15+
import kotlinx.coroutines.flow.filter
16+
import kotlinx.coroutines.launch
17+
import kotlinx.coroutines.yield
1418
import okhttp3.OkHttpClient
1519
import java.net.HttpURLConnection
1620
import java.net.URL
1721

18-
open class LinkHandler(
22+
open class CoderProtocolHandler(
1923
private val context: CoderToolboxContext,
2024
private val settings: CoderSettings,
2125
private val httpClient: OkHttpClient?,
2226
private val dialogUi: DialogUi,
27+
private val isInitialized: StateFlow<Boolean>,
2328
) {
2429
/**
2530
* Given a set of URL parameters, prepare the CLI then return a workspace to
@@ -31,7 +36,7 @@ open class LinkHandler(
3136
suspend fun handle(
3237
parameters: Map<String, String>,
3338
indicator: ((t: String) -> Unit)? = null,
34-
): String {
39+
) {
3540
val deploymentURL =
3641
parameters.url() ?: dialogUi.ask(
3742
context.i18n.ptrl("Deployment URL"),
@@ -129,10 +134,16 @@ open class LinkHandler(
129134
indicator?.invoke("Configuring Coder CLI...")
130135
cli.configSsh(client.agentNames(workspaces))
131136

132-
val name = "${workspace.name}.${agent.name}"
133-
// TODO@JB: Can we ask for the IDE and project path or how does
134-
// this work?
135-
return name
137+
isInitialized.waitForTrue()
138+
context.cs.launch {
139+
context.ui.showWindow()
140+
yield()
141+
context.envPageManager.showEnvironmentPage("${workspace.name}.${agent.name}", false)
142+
// without a yield or a delay(0) the env page does not show up. My assumption is that
143+
// the coroutine is finishing too fast without giving enough time to compose main thread
144+
// to catch the state change. Yielding gives other coroutines the chance to run
145+
yield()
146+
}
136147
}
137148

138149
/**
@@ -332,4 +343,8 @@ internal fun getMatchingAgent(
332343
return agent
333344
}
334345

346+
fun StateFlow<Boolean>.waitForTrue() {
347+
this.filter { it }
348+
}
349+
335350
class MissingArgumentException(message: String, ex: Throwable? = null) : IllegalArgumentException(message, ex)

0 commit comments

Comments
 (0)