Skip to content

Commit d748b70

Browse files
committed
[explorer] fix #5959: report busy progress in view container location
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
1 parent 697a47d commit d748b70

File tree

4 files changed

+44
-6
lines changed

4 files changed

+44
-6
lines changed

packages/core/src/common/progress-service.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,7 @@ export class ProgressService {
7474
async withProgress<T>(text: string, locationId: string, task: () => Promise<T>): Promise<T> {
7575
const progress = await this.showProgress({ text, options: { cancelable: true, location: locationId } });
7676
try {
77-
const result = task();
78-
return result;
79-
} catch (error) {
80-
throw error;
77+
return await task();
8178
} finally {
8279
progress.cancel();
8380
}

packages/navigator/src/browser/navigator-frontend-module.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ export default new ContainerModule(bind => {
5656
bind(WidgetFactory).toDynamicValue(({ container }) => ({
5757
id: EXPLORER_VIEW_CONTAINER_ID,
5858
createWidget: async () => {
59-
const viewContainer = container.get<ViewContainer.Factory>(ViewContainer.Factory)({ id: EXPLORER_VIEW_CONTAINER_ID });
59+
const viewContainer = container.get<ViewContainer.Factory>(ViewContainer.Factory)({
60+
id: EXPLORER_VIEW_CONTAINER_ID,
61+
progressLocationId: 'explorer'
62+
});
6063
viewContainer.setTitleOptions(EXPLORER_VIEW_CONTAINER_TITLE_OPTIONS);
6164
const widget = await container.get(WidgetManager).getOrCreateWidget(FILE_NAVIGATOR_ID);
6265
viewContainer.addWidget(widget, {

packages/navigator/src/browser/navigator-model.spec.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
1818
let disableJSDOM = enableJSDOM();
1919

2020
import { Container } from 'inversify';
21-
import { Emitter, ILogger, Logger } from '@theia/core';
21+
import { Event, Emitter, ILogger, Logger } from '@theia/core';
2222
import {
2323
CompositeTreeNode, DefaultOpenerService, ExpandableTreeNode, LabelProvider, OpenerService,
2424
Tree, TreeNode, TreeSelectionService, TreeExpansionService, TreeExpansionServiceImpl,
@@ -37,6 +37,7 @@ import { expect } from 'chai';
3737
import URI from '@theia/core/lib/common/uri';
3838
import * as sinon from 'sinon';
3939
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
40+
import { ProgressService } from '@theia/core/lib/common/progress-service';
4041

4142
disableJSDOM();
4243

@@ -113,6 +114,7 @@ const setup = () => {
113114
});
114115
};
115116

117+
// TODO rewrite as integration tests instead of testing mocks
116118
describe('FileNavigatorModel', () => {
117119
let testContainer: Container;
118120

@@ -177,12 +179,16 @@ describe('FileNavigatorModel', () => {
177179
testContainer.bind(TreeSearch).toConstantValue(mockTreeSearch);
178180
testContainer.bind(CorePreferences).toConstantValue(mockPreferences);
179181
testContainer.bind(FrontendApplicationStateService).toConstantValue(mockApplicationStateService);
182+
testContainer.bind(ProgressService).toConstantValue(<ProgressService>{
183+
withProgress: (_, __, task) => task()
184+
});
180185

181186
sinon.stub(mockWorkspaceService, 'onWorkspaceChanged').value(mockWorkspaceServiceEmitter.event);
182187
sinon.stub(mockWorkspaceService, 'onWorkspaceLocationChanged').value(mockWorkspaceOnLocationChangeEmitter.event);
183188
sinon.stub(mockFileSystemWatcher, 'onFilesChanged').value(mockFileChangeEmitter.event);
184189
sinon.stub(mockFileSystemWatcher, 'onDidMove').value(mockFileMoveEmitter.event);
185190
sinon.stub(mockFileNavigatorTree, 'onChanged').value(mockTreeChangeEmitter.event);
191+
sinon.stub(mockFileNavigatorTree, 'onDidChangeBusy').value(Event.None);
186192
sinon.stub(mockTreeExpansionService, 'onExpansionChanged').value(mockExpansionChangeEmitter.event);
187193

188194
setup();

packages/navigator/src/browser/navigator-model.ts

+32
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import { OpenerService, open, TreeNode, ExpandableTreeNode, CompositeTreeNode, S
2121
import { FileNavigatorTree, WorkspaceRootNode, WorkspaceNode } from './navigator-tree';
2222
import { WorkspaceService } from '@theia/workspace/lib/browser';
2323
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
24+
import { ProgressService } from '@theia/core/lib/common/progress-service';
25+
import { Deferred } from '@theia/core/lib/common/promise-util';
26+
import { Disposable } from '@theia/core/lib/common/disposable';
2427

2528
@injectable()
2629
export class FileNavigatorModel extends FileTreeModel {
@@ -30,12 +33,41 @@ export class FileNavigatorModel extends FileTreeModel {
3033
@inject(WorkspaceService) protected readonly workspaceService: WorkspaceService;
3134
@inject(FrontendApplicationStateService) protected readonly applicationState: FrontendApplicationStateService;
3235

36+
@inject(ProgressService)
37+
protected readonly progressService: ProgressService;
38+
3339
@postConstruct()
3440
protected init(): void {
3541
super.init();
42+
this.reportBusyProgress();
3643
this.initializeRoot();
3744
}
3845

46+
protected readonly pendingBusyProgress = new Map<string, Deferred<void>>();
47+
protected reportBusyProgress(): void {
48+
this.toDispose.push(this.onDidChangeBusy(node => {
49+
const pending = this.pendingBusyProgress.get(node.id);
50+
if (pending) {
51+
if (!node.busy) {
52+
pending.resolve();
53+
this.pendingBusyProgress.delete(node.id);
54+
}
55+
return;
56+
}
57+
if (node.busy) {
58+
const progress = new Deferred<void>();
59+
this.pendingBusyProgress.set(node.id, progress);
60+
this.progressService.withProgress('', 'explorer', () => progress.promise);
61+
}
62+
}));
63+
this.toDispose.push(Disposable.create(() => {
64+
for (const pending of this.pendingBusyProgress.values()) {
65+
pending.resolve();
66+
}
67+
this.pendingBusyProgress.clear();
68+
}));
69+
}
70+
3971
protected async initializeRoot(): Promise<void> {
4072
await Promise.all([
4173
this.applicationState.reachedState('initialized_layout'),

0 commit comments

Comments
 (0)