Skip to content

Commit 99b594f

Browse files
authored
Automatically refresh workspaces (#203)
1 parent 08ae6f8 commit 99b594f

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

src/extension.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,19 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
9090
return config
9191
})
9292

93-
const myWorkspacesProvider = new WorkspaceProvider(WorkspaceQuery.Mine, storage)
93+
const myWorkspacesProvider = new WorkspaceProvider(WorkspaceQuery.Mine, storage, 5)
9494
const allWorkspacesProvider = new WorkspaceProvider(WorkspaceQuery.All, storage)
9595

96-
vscode.window.registerTreeDataProvider("myWorkspaces", myWorkspacesProvider)
96+
// createTreeView, unlike registerTreeDataProvider, gives us the tree view API
97+
// (so we can see when it is visible) but otherwise they have the same effect.
98+
const wsTree = vscode.window.createTreeView("myWorkspaces", { treeDataProvider: myWorkspacesProvider })
9799
vscode.window.registerTreeDataProvider("allWorkspaces", allWorkspacesProvider)
98100

101+
myWorkspacesProvider.setVisibility(wsTree.visible)
102+
wsTree.onDidChangeVisibility((event) => {
103+
myWorkspacesProvider.setVisibility(event.visible)
104+
})
105+
99106
const url = storage.getURL()
100107
if (url) {
101108
getAuthenticatedUser()

src/workspacesProvider.ts

+53-3
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,53 @@ export enum WorkspaceQuery {
1414
export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
1515
private workspaces: WorkspaceTreeItem[] = []
1616
private agentWatchers: Record<WorkspaceAgent["id"], { dispose: () => void; metadata?: AgentMetadataEvent[] }> = {}
17+
private timeout: NodeJS.Timeout | undefined
18+
private visible = false
1719
private fetching = false
1820

1921
constructor(
2022
private readonly getWorkspacesQuery: WorkspaceQuery,
2123
private readonly storage: Storage,
24+
private readonly timerSeconds?: number,
2225
) {
2326
this.fetchAndRefresh()
2427
}
2528

26-
// fetchAndRefresh fetches new workspaces then re-renders the entire tree.
27-
// Trying to call this while already refreshing is a no-op and will return
29+
// fetchAndRefresh fetches new workspaces, re-renders the entire tree, then
30+
// keeps refreshing (if a timer length was provided) as long as the user is
31+
// still logged in and no errors were encountered fetching workspaces.
32+
// Calling this while already refreshing is a no-op and will return
2833
// immediately.
2934
async fetchAndRefresh() {
3035
if (this.fetching) {
3136
return
3237
}
3338
this.fetching = true
3439

40+
// TODO: It would be better to reuse these.
3541
Object.values(this.agentWatchers).forEach((watcher) => watcher.dispose())
3642

43+
// It is possible we called fetchAndRefresh() manually (through the button
44+
// for example), in which case we might still have a pending refresh that
45+
// needs to be cleared.
46+
this.cancelPendingRefresh()
47+
48+
let hadError = false
3749
try {
3850
this.workspaces = await this.fetch()
3951
} catch (error) {
52+
hadError = true
4053
this.workspaces = []
4154
}
4255

43-
this.refresh()
4456
this.fetching = false
57+
58+
this.refresh()
59+
60+
// As long as there was no error we can schedule the next refresh.
61+
if (hadError) {
62+
this.maybeScheduleRefresh()
63+
}
4564
}
4665

4766
/**
@@ -82,6 +101,37 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
82101
})
83102
}
84103

104+
/**
105+
* Either start or stop the refresh timer based on visibility.
106+
*/
107+
setVisibility(visible: boolean) {
108+
this.visible = visible
109+
if (!visible) {
110+
this.cancelPendingRefresh()
111+
} else {
112+
this.maybeScheduleRefresh()
113+
}
114+
}
115+
116+
private cancelPendingRefresh() {
117+
if (this.timeout) {
118+
clearTimeout(this.timeout)
119+
this.timeout = undefined
120+
}
121+
}
122+
123+
/**
124+
* Schedule a refresh if one is not already scheduled or underway and a
125+
* timeout length was provided.
126+
*/
127+
private maybeScheduleRefresh() {
128+
if (this.timerSeconds && !this.timeout && !this.fetching) {
129+
this.timeout = setTimeout(() => {
130+
this.fetchAndRefresh()
131+
}, this.timerSeconds * 1000)
132+
}
133+
}
134+
85135
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | null | void> =
86136
new vscode.EventEmitter<vscode.TreeItem | undefined | null | void>()
87137
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | null | void> =

0 commit comments

Comments
 (0)