Skip to content

Commit 9dd25a8

Browse files
committed
feat: add debouncing to workspace search for better user experience
- Add 150ms debounce delay to prevent excessive search operations - Implement immediate clear functionality without debouncing - Add proper cleanup for debounce timers to prevent memory leaks - Improve search responsiveness, especially for users with many workspaces
1 parent 3e340bf commit 9dd25a8

File tree

3 files changed

+35
-13
lines changed

3 files changed

+35
-13
lines changed

src/commands.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -724,13 +724,6 @@ export class Commands {
724724
quickPick.show();
725725
}
726726

727-
/**
728-
* Clear the workspace search filter.
729-
*/
730-
public clearWorkspaceSearch(): void {
731-
vscode.commands.executeCommand("coder.setWorkspaceSearchFilter", "");
732-
}
733-
734727
/**
735728
* Return agents from the workspace.
736729
*

src/extension.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,9 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
303303
vscode.commands.registerCommand("coder.getWorkspaceSearchFilter", () => {
304304
return allWorkspacesProvider.getSearchFilter();
305305
});
306-
vscode.commands.registerCommand(
307-
"coder.clearWorkspaceSearch",
308-
commands.clearWorkspaceSearch.bind(commands),
309-
);
306+
vscode.commands.registerCommand("coder.clearWorkspaceSearch", () => {
307+
allWorkspacesProvider.clearSearchFilter();
308+
});
310309

311310
// Since the "onResolveRemoteAuthority:ssh-remote" activation event exists
312311
// in package.json we're able to perform actions before the authority is

src/workspacesProvider.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export class WorkspaceProvider
4444
private visible = false;
4545
private searchFilter = "";
4646
private metadataCache: Record<string, string> = {};
47+
private searchDebounceTimer: NodeJS.Timeout | undefined;
4748

4849
constructor(
4950
private readonly getWorkspacesQuery: WorkspaceQuery,
@@ -59,14 +60,38 @@ export class WorkspaceProvider
5960
if (filter.length > 200) {
6061
filter = filter.substring(0, 200);
6162
}
62-
this.searchFilter = filter;
63-
this.refresh(undefined);
63+
64+
// Clear any existing debounce timer
65+
if (this.searchDebounceTimer) {
66+
clearTimeout(this.searchDebounceTimer);
67+
}
68+
69+
// Debounce the search operation to improve performance
70+
this.searchDebounceTimer = setTimeout(() => {
71+
this.searchFilter = filter;
72+
this.refresh(undefined);
73+
this.searchDebounceTimer = undefined;
74+
}, 150); // 150ms debounce delay - good balance between responsiveness and performance
6475
}
6576

6677
getSearchFilter(): string {
6778
return this.searchFilter;
6879
}
6980

81+
/**
82+
* Clear the search filter immediately without debouncing.
83+
* Use this when the user explicitly clears the search.
84+
*/
85+
clearSearchFilter(): void {
86+
// Clear any pending debounce timer
87+
if (this.searchDebounceTimer) {
88+
clearTimeout(this.searchDebounceTimer);
89+
this.searchDebounceTimer = undefined;
90+
}
91+
this.searchFilter = "";
92+
this.refresh(undefined);
93+
}
94+
7095
// fetchAndRefresh fetches new workspaces, re-renders the entire tree, then
7196
// keeps refreshing (if a timer length was provided) as long as the user is
7297
// still logged in and no errors were encountered fetching workspaces.
@@ -219,6 +244,11 @@ export class WorkspaceProvider
219244
clearTimeout(this.timeout);
220245
this.timeout = undefined;
221246
}
247+
// clear search debounce timer
248+
if (this.searchDebounceTimer) {
249+
clearTimeout(this.searchDebounceTimer);
250+
this.searchDebounceTimer = undefined;
251+
}
222252
}
223253

224254
/**

0 commit comments

Comments
 (0)