From 5a9c93f7ee32f3e334562baf94717ce5ea748b8b Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Tue, 11 Mar 2025 22:46:43 +0200 Subject: [PATCH 1/7] fix: Start button is active when template is outdated - Start button is active even though it doesn't do anything when clicked when the workspace template has updates. - resolves #31 --- src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt index 82256be..f39fc18 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt @@ -68,7 +68,7 @@ class CoderRemoteEnvironment( } } }, - Action(context.i18n.ptrl("Start"), enabled = { wsRawStatus.canStart() }) { + Action(context.i18n.ptrl("Start"), enabled = { wsRawStatus.canStart() && !workspace.outdated }) { val build = client.startWorkspace(workspace) workspace = workspace.copy(latestBuild = build) update(workspace, agent) From 7559cbb8bbe309d8625f9a034a31dad1763f9573 Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Tue, 11 Mar 2025 22:48:19 +0200 Subject: [PATCH 2/7] fix: rename `Update` button - to `Update and start` to reflect that the it also starts the workspace - more consistent with the web client --- src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt index f39fc18..776cb14 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt @@ -78,7 +78,7 @@ class CoderRemoteEnvironment( workspace = workspace.copy(latestBuild = build) update(workspace, agent) }, - Action(context.i18n.ptrl("Update"), enabled = { workspace.outdated }) { + Action(context.i18n.ptrl("Update and start"), enabled = { workspace.outdated }) { val build = client.updateWorkspace(workspace) workspace = workspace.copy(latestBuild = build) update(workspace, agent) From 38bcbba769259e2a7814e7f67664ed9153ec3f6a Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Tue, 11 Mar 2025 23:40:55 +0200 Subject: [PATCH 3/7] impl: icon support for light & dark theme - LAF support in Toolbox is quite primitive, it turns out icon support for light and dark themes is enabled by a masked flag on the icons - the mask flag controls whether the svg colors are inverted in light&dark themes. --- CHANGELOG.md | 3 ++- .../kotlin/com/coder/toolbox/CoderRemoteProvider.kt | 11 +++++++++-- src/main/kotlin/com/coder/toolbox/views/CoderPage.kt | 8 ++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6867b6f..0bb2520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,4 +5,5 @@ ### Added - initial support for JetBrains Toolbox 2.6.0.38311 with the possibility to manage the workspaces - i.e. start, stop, - update and delete actions and also quick shortcuts to templates, web terminal and dashboard. \ No newline at end of file + update and delete actions and also quick shortcuts to templates, web terminal and dashboard. +- support for light & dark themes \ No newline at end of file diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt index a449c39..a30d3fb 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt @@ -17,6 +17,7 @@ import com.coder.toolbox.views.NewEnvironmentPage import com.coder.toolbox.views.SignInPage import com.coder.toolbox.views.TokenPage import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon +import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon.IconType import com.jetbrains.toolbox.api.core.util.LoadableState import com.jetbrains.toolbox.api.remoteDev.ProviderVisibilityState import com.jetbrains.toolbox.api.remoteDev.RemoteProvider @@ -181,10 +182,16 @@ class CoderRemoteProvider( } override val svgIcon: SvgIcon = - SvgIcon(this::class.java.getResourceAsStream("/icon.svg")?.readAllBytes() ?: byteArrayOf()) + SvgIcon( + this::class.java.getResourceAsStream("/icon.svg")?.readAllBytes() ?: byteArrayOf(), + type = IconType.Masked + ) override val noEnvironmentsSvgIcon: SvgIcon? = - SvgIcon(this::class.java.getResourceAsStream("/icon.svg")?.readAllBytes() ?: byteArrayOf()) + SvgIcon( + this::class.java.getResourceAsStream("/icon.svg")?.readAllBytes() ?: byteArrayOf(), + type = IconType.Masked + ) /** * TODO@JB: It would be nice to show "loading workspaces" at first but it diff --git a/src/main/kotlin/com/coder/toolbox/views/CoderPage.kt b/src/main/kotlin/com/coder/toolbox/views/CoderPage.kt index 6a1c4e3..53b55ea 100644 --- a/src/main/kotlin/com/coder/toolbox/views/CoderPage.kt +++ b/src/main/kotlin/com/coder/toolbox/views/CoderPage.kt @@ -2,6 +2,7 @@ package com.coder.toolbox.views import com.coder.toolbox.CoderToolboxContext import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon +import com.jetbrains.toolbox.api.core.ui.icons.SvgIcon.IconType import com.jetbrains.toolbox.api.localization.LocalizableString import com.jetbrains.toolbox.api.ui.actions.RunnableActionDescription import com.jetbrains.toolbox.api.ui.components.UiField @@ -46,9 +47,12 @@ abstract class CoderPage( * This seems to only work on the first page. */ override val svgIcon: SvgIcon? = if (showIcon) { - SvgIcon(this::class.java.getResourceAsStream("/icon.svg")?.readAllBytes() ?: byteArrayOf()) + SvgIcon( + this::class.java.getResourceAsStream("/icon.svg")?.readAllBytes() ?: byteArrayOf(), + type = IconType.Masked + ) } else { - SvgIcon(byteArrayOf()) + SvgIcon(byteArrayOf(), type = IconType.Masked) } /** From efea6671259d2a0f52d0bb57401f119a7ef4caa0 Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Tue, 11 Mar 2025 23:53:04 +0200 Subject: [PATCH 4/7] fix: update localization bundle --- src/main/resources/localization/defaultMessages.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/localization/defaultMessages.po b/src/main/resources/localization/defaultMessages.po index 837e2a0..5c86a06 100644 --- a/src/main/resources/localization/defaultMessages.po +++ b/src/main/resources/localization/defaultMessages.po @@ -73,7 +73,7 @@ msgstr "" msgid "Stop" msgstr "" -msgid "Update" +msgid "Update and start" msgstr "" msgid "Settings" From 5f1756211c76ebf09c18f8a5621ee0946cf34c4a Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Wed, 12 Mar 2025 22:10:29 +0200 Subject: [PATCH 5/7] impl: hide unavailable actions - instead of disabling the env actions when they are not available we should hide them instead. - resolves #31 --- .../coder/toolbox/CoderRemoteEnvironment.kt | 78 +++++++++++-------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt index 776cb14..d824898 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt @@ -45,44 +45,54 @@ class CoderRemoteEnvironment( override val actionsList: MutableStateFlow> = MutableStateFlow(getAvailableActions()) - private fun getAvailableActions(): List = listOf( - Action(context.i18n.ptrl("Open web terminal")) { - context.cs.launch { - BrowserUtil.browse(client.url.withPath("/${workspace.ownerName}/$name/terminal").toString()) { - context.ui.showErrorInfoPopup(it) + private fun getAvailableActions(): List { + val actions = mutableListOf( + Action(context.i18n.ptrl("Open web terminal")) { + context.cs.launch { + BrowserUtil.browse(client.url.withPath("/${workspace.ownerName}/$name/terminal").toString()) { + context.ui.showErrorInfoPopup(it) + } } - } - }, - Action(context.i18n.ptrl("Open in dashboard")) { - context.cs.launch { - BrowserUtil.browse(client.url.withPath("/@${workspace.ownerName}/${workspace.name}").toString()) { - context.ui.showErrorInfoPopup(it) + }, + Action(context.i18n.ptrl("Open in dashboard")) { + context.cs.launch { + BrowserUtil.browse(client.url.withPath("/@${workspace.ownerName}/${workspace.name}").toString()) { + context.ui.showErrorInfoPopup(it) + } } - } - }, + }, - Action(context.i18n.ptrl("View template")) { - context.cs.launch { - BrowserUtil.browse(client.url.withPath("/templates/${workspace.templateName}").toString()) { - context.ui.showErrorInfoPopup(it) + Action(context.i18n.ptrl("View template")) { + context.cs.launch { + BrowserUtil.browse(client.url.withPath("/templates/${workspace.templateName}").toString()) { + context.ui.showErrorInfoPopup(it) + } } - } - }, - Action(context.i18n.ptrl("Start"), enabled = { wsRawStatus.canStart() && !workspace.outdated }) { - val build = client.startWorkspace(workspace) - workspace = workspace.copy(latestBuild = build) - update(workspace, agent) - }, - Action(context.i18n.ptrl("Stop"), enabled = { wsRawStatus.canStop() }) { - val build = client.stopWorkspace(workspace) - workspace = workspace.copy(latestBuild = build) - update(workspace, agent) - }, - Action(context.i18n.ptrl("Update and start"), enabled = { workspace.outdated }) { - val build = client.updateWorkspace(workspace) - workspace = workspace.copy(latestBuild = build) - update(workspace, agent) - }) + }) + if (wsRawStatus.canStart() && !workspace.outdated) { + actions.add(Action(context.i18n.ptrl("Start")) { + val build = client.startWorkspace(workspace) + workspace = workspace.copy(latestBuild = build) + update(workspace, agent) + }) + } + if (wsRawStatus.canStop()) { + actions.add(Action(context.i18n.ptrl("Stop")) { + val build = client.stopWorkspace(workspace) + workspace = workspace.copy(latestBuild = build) + update(workspace, agent) + }) + } + if (workspace.outdated) { + actions.add(Action(context.i18n.ptrl("Update and start")) { + val build = client.updateWorkspace(workspace) + workspace = workspace.copy(latestBuild = build) + update(workspace, agent) + }) + } + + return actions + } /** * Update the workspace/agent status to the listeners, if it has changed. From 55446410c11a95e8e61d1d4e6e0c40dfd185b4f7 Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Wed, 12 Mar 2025 22:32:46 +0200 Subject: [PATCH 6/7] refactor: update already assigns the workspace reference --- .../kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt index d824898..810a273 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt @@ -72,22 +72,19 @@ class CoderRemoteEnvironment( if (wsRawStatus.canStart() && !workspace.outdated) { actions.add(Action(context.i18n.ptrl("Start")) { val build = client.startWorkspace(workspace) - workspace = workspace.copy(latestBuild = build) - update(workspace, agent) + update(workspace.copy(latestBuild = build), agent) }) } if (wsRawStatus.canStop()) { actions.add(Action(context.i18n.ptrl("Stop")) { val build = client.stopWorkspace(workspace) - workspace = workspace.copy(latestBuild = build) - update(workspace, agent) + update(workspace.copy(latestBuild = build), agent) }) } if (workspace.outdated) { actions.add(Action(context.i18n.ptrl("Update and start")) { val build = client.updateWorkspace(workspace) - workspace = workspace.copy(latestBuild = build) - update(workspace, agent) + update(workspace.copy(latestBuild = build), agent) }) } From 3285347b2d6c7258c38ba6533ecae0b6ec021d20 Mon Sep 17 00:00:00 2001 From: Faur Ioan-Aurel Date: Wed, 12 Mar 2025 23:58:25 +0200 Subject: [PATCH 7/7] impl: support for `Update and restart` action - when workspace is running and is outdated - resolves #33 --- .../coder/toolbox/CoderRemoteEnvironment.kt | 40 +++++++++++-------- .../resources/localization/defaultMessages.po | 3 ++ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt index 810a273..d9e7d95 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt @@ -69,25 +69,33 @@ class CoderRemoteEnvironment( } } }) - if (wsRawStatus.canStart() && !workspace.outdated) { - actions.add(Action(context.i18n.ptrl("Start")) { - val build = client.startWorkspace(workspace) - update(workspace.copy(latestBuild = build), agent) - }) + + if (wsRawStatus.canStart()) { + if (workspace.outdated) { + actions.add(Action(context.i18n.ptrl("Update and start")) { + val build = client.updateWorkspace(workspace) + update(workspace.copy(latestBuild = build), agent) + }) + } else { + actions.add(Action(context.i18n.ptrl("Start")) { + val build = client.startWorkspace(workspace) + update(workspace.copy(latestBuild = build), agent) + }) + } } if (wsRawStatus.canStop()) { - actions.add(Action(context.i18n.ptrl("Stop")) { - val build = client.stopWorkspace(workspace) - update(workspace.copy(latestBuild = build), agent) - }) - } - if (workspace.outdated) { - actions.add(Action(context.i18n.ptrl("Update and start")) { - val build = client.updateWorkspace(workspace) - update(workspace.copy(latestBuild = build), agent) - }) + if (workspace.outdated) { + actions.add(Action(context.i18n.ptrl("Update and restart")) { + val build = client.updateWorkspace(workspace) + update(workspace.copy(latestBuild = build), agent) + }) + } else { + actions.add(Action(context.i18n.ptrl("Stop")) { + val build = client.stopWorkspace(workspace) + update(workspace.copy(latestBuild = build), agent) + }) + } } - return actions } diff --git a/src/main/resources/localization/defaultMessages.po b/src/main/resources/localization/defaultMessages.po index 5c86a06..aa96e05 100644 --- a/src/main/resources/localization/defaultMessages.po +++ b/src/main/resources/localization/defaultMessages.po @@ -76,6 +76,9 @@ msgstr "" msgid "Update and start" msgstr "" +msgid "Update and restart" +msgstr "" + msgid "Settings" msgstr "" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy