diff --git a/packages/core/src/common/progress-service.ts b/packages/core/src/common/progress-service.ts index ad6383f440e5c..a7ecfeb67a8a0 100644 --- a/packages/core/src/common/progress-service.ts +++ b/packages/core/src/common/progress-service.ts @@ -74,10 +74,7 @@ export class ProgressService { async withProgress(text: string, locationId: string, task: () => Promise): Promise { const progress = await this.showProgress({ text, options: { cancelable: true, location: locationId } }); try { - const result = task(); - return result; - } catch (error) { - throw error; + return await task(); } finally { progress.cancel(); } diff --git a/packages/navigator/src/browser/navigator-frontend-module.ts b/packages/navigator/src/browser/navigator-frontend-module.ts index bee418be321f2..b47290469edcd 100644 --- a/packages/navigator/src/browser/navigator-frontend-module.ts +++ b/packages/navigator/src/browser/navigator-frontend-module.ts @@ -56,7 +56,10 @@ export default new ContainerModule(bind => { bind(WidgetFactory).toDynamicValue(({ container }) => ({ id: EXPLORER_VIEW_CONTAINER_ID, createWidget: async () => { - const viewContainer = container.get(ViewContainer.Factory)({ id: EXPLORER_VIEW_CONTAINER_ID }); + const viewContainer = container.get(ViewContainer.Factory)({ + id: EXPLORER_VIEW_CONTAINER_ID, + progressLocationId: 'explorer' + }); viewContainer.setTitleOptions(EXPLORER_VIEW_CONTAINER_TITLE_OPTIONS); const widget = await container.get(WidgetManager).getOrCreateWidget(FILE_NAVIGATOR_ID); viewContainer.addWidget(widget, { diff --git a/packages/navigator/src/browser/navigator-model.ts b/packages/navigator/src/browser/navigator-model.ts index d1e0f5b0ecb15..bbe6aa8975a4c 100644 --- a/packages/navigator/src/browser/navigator-model.ts +++ b/packages/navigator/src/browser/navigator-model.ts @@ -21,6 +21,9 @@ import { OpenerService, open, TreeNode, ExpandableTreeNode, CompositeTreeNode, S import { FileNavigatorTree, WorkspaceRootNode, WorkspaceNode } from './navigator-tree'; import { WorkspaceService } from '@theia/workspace/lib/browser'; import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; +import { ProgressService } from '@theia/core/lib/common/progress-service'; +import { Deferred } from '@theia/core/lib/common/promise-util'; +import { Disposable } from '@theia/core/lib/common/disposable'; @injectable() export class FileNavigatorModel extends FileTreeModel { @@ -30,12 +33,41 @@ export class FileNavigatorModel extends FileTreeModel { @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService; @inject(FrontendApplicationStateService) protected readonly applicationState: FrontendApplicationStateService; + @inject(ProgressService) + protected readonly progressService: ProgressService; + @postConstruct() protected init(): void { super.init(); + this.reportBusyProgress(); this.initializeRoot(); } + protected readonly pendingBusyProgress = new Map>(); + protected reportBusyProgress(): void { + this.toDispose.push(this.onDidChangeBusy(node => { + const pending = this.pendingBusyProgress.get(node.id); + if (pending) { + if (!node.busy) { + pending.resolve(); + this.pendingBusyProgress.delete(node.id); + } + return; + } + if (node.busy) { + const progress = new Deferred(); + this.pendingBusyProgress.set(node.id, progress); + this.progressService.withProgress('', 'explorer', () => progress.promise); + } + })); + this.toDispose.push(Disposable.create(() => { + for (const pending of this.pendingBusyProgress.values()) { + pending.resolve(); + } + this.pendingBusyProgress.clear(); + })); + } + protected async initializeRoot(): Promise { await Promise.all([ this.applicationState.reachedState('initialized_layout'),