Skip to content

Commit

Permalink
[explorer] fix #5959: report busy progress in view container location
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Mar 2, 2020
1 parent f2932fe commit e48b9b5
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/browser/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export interface TreeNode {
*/
readonly nextSibling?: TreeNode;
/**
* Whether this node is busy. Greater than 0 than busy; otherwise not.
* Whether this node is busy. Greater than 0 then busy; otherwise not.
*/
readonly busy?: number;
}
Expand Down
5 changes: 1 addition & 4 deletions packages/core/src/common/progress-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,7 @@ export class ProgressService {
async withProgress<T>(text: string, locationId: string, task: () => Promise<T>): Promise<T> {
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();
}
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/common/promise-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export class Deferred<T> {
});
}

/**
* @returns resolves after a specified number of milliseconds
* @throws cancelled if a given token is cancelled before a specified number of milliseconds
*/
export function timeout(ms: number, token = CancellationToken.None): Promise<void> {
const deferred = new Deferred<void>();
const handle = setTimeout(() => deferred.resolve(), ms);
Expand Down
5 changes: 4 additions & 1 deletion packages/navigator/src/browser/navigator-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>(ViewContainer.Factory)({ id: EXPLORER_VIEW_CONTAINER_ID });
const viewContainer = container.get<ViewContainer.Factory>(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, {
Expand Down
8 changes: 7 additions & 1 deletion packages/navigator/src/browser/navigator-model.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
let disableJSDOM = enableJSDOM();

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

disableJSDOM();

Expand Down Expand Up @@ -113,6 +114,7 @@ const setup = () => {
});
};

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

Expand Down Expand Up @@ -177,12 +179,16 @@ describe('FileNavigatorModel', () => {
testContainer.bind(TreeSearch).toConstantValue(mockTreeSearch);
testContainer.bind(CorePreferences).toConstantValue(mockPreferences);
testContainer.bind(FrontendApplicationStateService).toConstantValue(mockApplicationStateService);
testContainer.bind(ProgressService).toConstantValue(<ProgressService>{
withProgress: (_, __, task) => task()
});

sinon.stub(mockWorkspaceService, 'onWorkspaceChanged').value(mockWorkspaceServiceEmitter.event);
sinon.stub(mockWorkspaceService, 'onWorkspaceLocationChanged').value(mockWorkspaceOnLocationChangeEmitter.event);
sinon.stub(mockFileSystemWatcher, 'onFilesChanged').value(mockFileChangeEmitter.event);
sinon.stub(mockFileSystemWatcher, 'onDidMove').value(mockFileMoveEmitter.event);
sinon.stub(mockFileNavigatorTree, 'onChanged').value(mockTreeChangeEmitter.event);
sinon.stub(mockFileNavigatorTree, 'onDidChangeBusy').value(Event.None);
sinon.stub(mockTreeExpansionService, 'onExpansionChanged').value(mockExpansionChangeEmitter.event);

setup();
Expand Down
32 changes: 32 additions & 0 deletions packages/navigator/src/browser/navigator-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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<string, Deferred<void>>();
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<void>();
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<void> {
await Promise.all([
this.applicationState.reachedState('initialized_layout'),
Expand Down

0 comments on commit e48b9b5

Please sign in to comment.