Skip to content

Commit 30c8ac5

Browse files
committed
Impl: Recent Workspaces search functionality
- it can search by hostname and by project path - it's not case sensitive - re-worked some of the code building the UI. The first part - up to the list of workspaces - is now statically declared and created only once.
1 parent 91dad07 commit 30c8ac5

File tree

1 file changed

+77
-52
lines changed

1 file changed

+77
-52
lines changed

src/main/kotlin/com/coder/gateway/views/CoderGatewayRecentWorkspaceConnectionsView.kt

+77-52
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@ package com.coder.gateway.views
22

33
import com.coder.gateway.CoderGatewayBundle
44
import com.coder.gateway.icons.CoderIcons
5+
import com.coder.gateway.models.RecentWorkspaceConnection
56
import com.coder.gateway.services.CoderRecentWorkspaceConnectionsService
67
import com.intellij.ide.BrowserUtil
78
import com.intellij.openapi.actionSystem.AnActionEvent
89
import com.intellij.openapi.components.service
910
import com.intellij.openapi.project.DumbAwareAction
1011
import com.intellij.openapi.ui.panel.ComponentPanelBuilder
1112
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
13+
import com.intellij.ui.DocumentAdapter
14+
import com.intellij.ui.SearchTextField
1215
import com.intellij.ui.components.ActionLink
1316
import com.intellij.ui.components.JBScrollPane
1417
import com.intellij.ui.dsl.builder.BottomGap
1518
import com.intellij.ui.dsl.builder.RightGap
1619
import com.intellij.ui.dsl.builder.TopGap
1720
import com.intellij.ui.dsl.builder.panel
1821
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
22+
import com.intellij.ui.dsl.gridLayout.VerticalAlign
1923
import com.intellij.util.ui.JBFont
2024
import com.intellij.util.ui.JBUI
2125
import com.jetbrains.gateway.api.GatewayRecentConnections
@@ -25,89 +29,110 @@ import com.jetbrains.rd.util.lifetime.Lifetime
2529
import kotlinx.coroutines.CoroutineScope
2630
import kotlinx.coroutines.Dispatchers
2731
import kotlinx.coroutines.launch
32+
import java.awt.Dimension
2833
import javax.swing.JComponent
34+
import javax.swing.event.DocumentEvent
2935

3036
class CoderGatewayRecentWorkspaceConnectionsView : GatewayRecentConnections {
3137
private val recentConnectionsService = service<CoderRecentWorkspaceConnectionsService>()
3238
private val cs = CoroutineScope(Dispatchers.Main)
3339

34-
private var contentPanel = JBScrollPane()
40+
private val contentPanel = JBScrollPane()
41+
42+
private lateinit var searchBar: SearchTextField
3543

3644
override val id = "CoderGatewayRecentConnections"
3745

3846
override val recentsIcon = CoderIcons.LOGO_16
3947

4048
override fun createRecentsView(lifetime: Lifetime): JComponent {
41-
updateContentView()
42-
return contentPanel
49+
return panel {
50+
indent {
51+
row {
52+
label(CoderGatewayBundle.message("gateway.connector.recentconnections.title")).applyToComponent {
53+
font = JBFont.h3().asBold()
54+
}
55+
searchBar = cell(SearchTextField(false)).applyToComponent {
56+
minimumSize = Dimension(350, -1)
57+
textEditor.border = JBUI.Borders.empty(2, 5, 2, 0)
58+
}.horizontalAlign(HorizontalAlign.RIGHT).component
59+
searchBar.addDocumentListener(object : DocumentAdapter() {
60+
override fun textChanged(e: DocumentEvent) {
61+
val toSearchFor = searchBar.text
62+
val filteredConnections = recentConnectionsService.getAllRecentConnections().filter { it.coderWorkspaceHostname?.toLowerCase()?.contains(toSearchFor) ?: false || it.projectPath?.toLowerCase()?.contains(toSearchFor) ?: false }
63+
updateContentView(filteredConnections.groupBy { it.coderWorkspaceHostname })
64+
}
65+
})
66+
}.bottomGap(BottomGap.MEDIUM)
67+
separator(background = WelcomeScreenUIManager.getSeparatorColor())
68+
row {
69+
resizableRow()
70+
cell(contentPanel).resizableColumn().horizontalAlign(HorizontalAlign.FILL).verticalAlign(VerticalAlign.FILL).component
71+
}
72+
}
73+
}.apply {
74+
background = WelcomeScreenUIManager.getMainAssociatedComponentBackground()
75+
border = JBUI.Borders.empty(12, 0, 0, 12)
76+
}
4377
}
4478

4579
override fun getRecentsTitle() = CoderGatewayBundle.message("gateway.connector.title")
4680

4781
override fun updateRecentView() {
48-
updateContentView()
82+
updateContentView(recentConnectionsService.getAllRecentConnections().groupBy { it.coderWorkspaceHostname })
4983
}
5084

51-
private fun updateContentView() {
52-
val groupedConnections = recentConnectionsService.getAllRecentConnections().groupBy { it.coderWorkspaceHostname }
85+
private fun updateContentView(groupedConnections: Map<String?, List<RecentWorkspaceConnection>>) {
5386
contentPanel.viewport.view = panel {
54-
indent {
87+
groupedConnections.entries.forEach { (hostname, recentConnections) ->
5588
row {
56-
label(CoderGatewayBundle.message("gateway.connector.recentconnections.title")).applyToComponent {
57-
font = JBFont.h3().asBold()
89+
if (hostname != null) {
90+
label(hostname).applyToComponent {
91+
font = JBFont.h3().asBold()
92+
}.horizontalAlign(HorizontalAlign.LEFT).gap(RightGap.SMALL)
93+
actionButton(object : DumbAwareAction("Open SSH Web Terminal", "", CoderIcons.OPEN_TERMINAL) {
94+
override fun actionPerformed(e: AnActionEvent) {
95+
BrowserUtil.browse(recentConnections[0]?.webTerminalLink ?: "")
96+
}
97+
})
5898
}
59-
}.bottomGap(BottomGap.MEDIUM)
60-
groupedConnections.entries.forEach { (hostname, recentConnections) ->
61-
row {
62-
if (hostname != null) {
63-
label(hostname).applyToComponent {
64-
font = JBFont.h3().asBold()
65-
}.horizontalAlign(HorizontalAlign.LEFT).gap(RightGap.SMALL)
66-
actionButton(object : DumbAwareAction("Open SSH Web Terminal", "", CoderIcons.OPEN_TERMINAL) {
67-
override fun actionPerformed(e: AnActionEvent) {
68-
BrowserUtil.browse(recentConnections[0]?.webTerminalLink ?: "")
69-
}
70-
})
71-
}
72-
}.topGap(TopGap.MEDIUM)
99+
}.topGap(TopGap.MEDIUM)
73100

74-
recentConnections.forEach { connectionDetails ->
75-
val product = IntelliJPlatformProduct.fromProductCode(connectionDetails.ideProductCode!!)!!
76-
row {
77-
icon(product.icon)
78-
cell(ActionLink(connectionDetails.projectPath!!) {
79-
cs.launch {
80-
GatewayUI.getInstance().connect(
81-
mapOf(
82-
"type" to "coder",
83-
"coder_workspace_hostname" to "${connectionDetails.coderWorkspaceHostname}",
84-
"project_path" to connectionDetails.projectPath!!,
85-
"ide_product_code" to "${product.productCode}",
86-
"ide_build_number" to "${connectionDetails.ideBuildNumber}",
87-
"ide_download_link" to "${connectionDetails.downloadSource}",
88-
"web_terminal_link" to "${connectionDetails.webTerminalLink}"
89-
)
101+
recentConnections.forEach { connectionDetails ->
102+
val product = IntelliJPlatformProduct.fromProductCode(connectionDetails.ideProductCode!!)!!
103+
row {
104+
icon(product.icon)
105+
cell(ActionLink(connectionDetails.projectPath!!) {
106+
cs.launch {
107+
GatewayUI.getInstance().connect(
108+
mapOf(
109+
"type" to "coder",
110+
"coder_workspace_hostname" to "${connectionDetails.coderWorkspaceHostname}",
111+
"project_path" to connectionDetails.projectPath!!,
112+
"ide_product_code" to "${product.productCode}",
113+
"ide_build_number" to "${connectionDetails.ideBuildNumber}",
114+
"ide_download_link" to "${connectionDetails.downloadSource}"
90115
)
91-
}
92-
})
93-
label("").resizableColumn().horizontalAlign(HorizontalAlign.FILL)
94-
label("Last opened: ${connectionDetails.lastOpened}").applyToComponent {
95-
foreground = JBUI.CurrentTheme.ContextHelp.FOREGROUND
96-
font = ComponentPanelBuilder.getCommentFont(font)
116+
)
97117
}
98-
actionButton(object : DumbAwareAction("Remove", "", CoderIcons.DELETE) {
99-
override fun actionPerformed(e: AnActionEvent) {
100-
recentConnectionsService.removeConnection(connectionDetails)
101-
updateContentView()
102-
}
103-
})
118+
})
119+
label("").resizableColumn().horizontalAlign(HorizontalAlign.FILL)
120+
label("Last opened: ${connectionDetails.lastOpened}").applyToComponent {
121+
foreground = JBUI.CurrentTheme.ContextHelp.FOREGROUND
122+
font = ComponentPanelBuilder.getCommentFont(font)
104123
}
124+
actionButton(object : DumbAwareAction("Remove from Recent Connections", "", CoderIcons.DELETE) {
125+
override fun actionPerformed(e: AnActionEvent) {
126+
recentConnectionsService.removeConnection(connectionDetails)
127+
updateContentView(recentConnectionsService.getAllRecentConnections().groupBy { it.coderWorkspaceHostname })
128+
}
129+
})
105130
}
106131
}
107132
}
108133
}.apply {
109134
background = WelcomeScreenUIManager.getMainAssociatedComponentBackground()
110-
border = JBUI.Borders.empty(0, 0, 0, 12)
135+
border = JBUI.Borders.empty(12, 0, 0, 12)
111136
}
112137
}
113138
}

0 commit comments

Comments
 (0)