Skip to content
Prev Previous commit
Next Next commit
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
  • Loading branch information
yelnatscoding committed Jul 29, 2025
commit 9dd25a8a9d3856d8842e1ad53c56627d97b5d968
7 changes: 0 additions & 7 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -724,13 +724,6 @@ export class Commands {
quickPick.show();
}

/**
* Clear the workspace search filter.
*/
public clearWorkspaceSearch(): void {
vscode.commands.executeCommand("coder.setWorkspaceSearchFilter", "");
}

/**
* Return agents from the workspace.
*
Expand Down
7 changes: 3 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,9 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
vscode.commands.registerCommand("coder.getWorkspaceSearchFilter", () => {
return allWorkspacesProvider.getSearchFilter();
});
vscode.commands.registerCommand(
"coder.clearWorkspaceSearch",
commands.clearWorkspaceSearch.bind(commands),
);
vscode.commands.registerCommand("coder.clearWorkspaceSearch", () => {
allWorkspacesProvider.clearSearchFilter();
});

// Since the "onResolveRemoteAuthority:ssh-remote" activation event exists
// in package.json we're able to perform actions before the authority is
Expand Down
34 changes: 32 additions & 2 deletions src/workspacesProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export class WorkspaceProvider
private visible = false;
private searchFilter = "";
private metadataCache: Record<string, string> = {};
private searchDebounceTimer: NodeJS.Timeout | undefined;

constructor(
private readonly getWorkspacesQuery: WorkspaceQuery,
Expand All @@ -59,14 +60,38 @@ export class WorkspaceProvider
if (filter.length > 200) {
filter = filter.substring(0, 200);
}
this.searchFilter = filter;
this.refresh(undefined);

// Clear any existing debounce timer
if (this.searchDebounceTimer) {
clearTimeout(this.searchDebounceTimer);
}

// Debounce the search operation to improve performance
this.searchDebounceTimer = setTimeout(() => {
this.searchFilter = filter;
this.refresh(undefined);
this.searchDebounceTimer = undefined;
}, 150); // 150ms debounce delay - good balance between responsiveness and performance
}

getSearchFilter(): string {
return this.searchFilter;
}

/**
* Clear the search filter immediately without debouncing.
* Use this when the user explicitly clears the search.
*/
clearSearchFilter(): void {
// Clear any pending debounce timer
if (this.searchDebounceTimer) {
clearTimeout(this.searchDebounceTimer);
this.searchDebounceTimer = undefined;
}
this.searchFilter = "";
this.refresh(undefined);
}

// fetchAndRefresh fetches new workspaces, re-renders the entire tree, then
// keeps refreshing (if a timer length was provided) as long as the user is
// still logged in and no errors were encountered fetching workspaces.
Expand Down Expand Up @@ -219,6 +244,11 @@ export class WorkspaceProvider
clearTimeout(this.timeout);
this.timeout = undefined;
}
// clear search debounce timer
if (this.searchDebounceTimer) {
clearTimeout(this.searchDebounceTimer);
this.searchDebounceTimer = undefined;
}
}

/**
Expand Down