@@ -14,34 +14,53 @@ export enum WorkspaceQuery {
1414export 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