Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leverage notification progress support for progress API #45958

Merged
merged 7 commits into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/vs/platform/progress/common/progress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,16 @@ export enum ProgressLocation {
Explorer = 1,
Scm = 3,
Extensions = 5,
Window = 10
Window = 10,
Notification = 15
}

export interface IProgressOptions {
location: ProgressLocation;
title?: string;
tooltip?: string;
source?: string;
total?: number;
cancellable?: boolean;
}

export interface IProgressStep {
Expand All @@ -86,5 +89,5 @@ export interface IProgressService2 {

_serviceBrand: any;

withProgress<P extends Thenable<R>, R=any>(options: IProgressOptions, task: (progress: IProgress<IProgressStep>) => P): P;
withProgress<P extends Thenable<R>, R=any>(options: IProgressOptions, task: (progress: IProgress<IProgressStep>) => P, onDidCancel?: () => void): P;
}
30 changes: 26 additions & 4 deletions src/vs/vscode.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5154,9 +5154,18 @@ declare module 'vscode' {
*
* @param task A callback returning a promise. Progress state can be reported with
* the provided [progress](#Progress)-object.
*
* To report discrete progress, use `percentage` to indicate how much work has been completed. Each call with
* a `percentage` value will be summed up and reflected as overall progress until 100% is reached. Note that
* currently only `ProgressLocation.Notification` is capable of showing discrete progress.
*
* To monitor if the operation has been cancelled by the user, use the provided [`CancellationToken`](#CancellationToken).
* Note that currently only `ProgressLocation.Notification` is supporting to show a cancel button to cancel the
* long running operation.
*
* @return The thenable the task-callback returned.
*/
export function withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; }>) => Thenable<R>): Thenable<R>;
export function withProgress<R>(options: ProgressOptions, task: (progress: Progress<{ message?: string; percentage?: number }>, token: CancellationToken) => Thenable<R>): Thenable<R>;

/**
* Creates a status bar [item](#StatusBarItem).
Expand Down Expand Up @@ -5355,14 +5364,19 @@ declare module 'vscode' {

/**
* Show progress for the source control viewlet, as overlay for the icon and as progress bar
* inside the viewlet (when visible).
* inside the viewlet (when visible). Neither supports cancellation nor discrete progress.
*/
SourceControl = 1,

/**
* Show progress in the status bar of the editor.
* Show progress in the status bar of the editor. Neither supports cancellation nor discrete progress.
*/
Window = 10
Window = 10,

/**
* Show progress as notifiation with an optional cancel button. Supports to show infinite and discrete progress.
*/
Notification = 15
}

/**
Expand All @@ -5380,6 +5394,14 @@ declare module 'vscode' {
* operation.
*/
title?: string;

/**
* Controls if a cancel button should show to allow the user to
* cancel the long running operation. Note that currently only
* `ProgressLocation.Notification` is supporting to show a cancel
* button.
*/
cancellable?: boolean;
}

/**
Expand Down
7 changes: 5 additions & 2 deletions src/vs/workbench/api/electron-browser/mainThreadProgress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@
'use strict';

import { IProgressService2, IProgress, IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import { MainThreadProgressShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { MainThreadProgressShape, MainContext, IExtHostContext, ExtHostProgressShape, ExtHostContext } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';

@extHostNamedCustomer(MainContext.MainThreadProgress)
export class MainThreadProgress implements MainThreadProgressShape {

private _progressService: IProgressService2;
private _progress = new Map<number, { resolve: Function, progress: IProgress<IProgressStep> }>();
private _proxy: ExtHostProgressShape;

constructor(
extHostContext: IExtHostContext,
@IProgressService2 progressService: IProgressService2
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostProgress);
this._progressService = progressService;
}

Expand All @@ -28,7 +30,8 @@ export class MainThreadProgress implements MainThreadProgressShape {

$startProgress(handle: number, options: IProgressOptions): void {
const task = this._createTask(handle);
this._progressService.withProgress(options, task);

this._progressService.withProgress(options, task, () => this._proxy.$acceptProgressCanceled(handle));
}

$progressReport(handle: number, message: IProgressStep): void {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/node/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export function createApiFactory(
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));

// Check that no named customers are missing
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
Expand All @@ -127,7 +128,6 @@ export function createApiFactory(
const extHostMessageService = new ExtHostMessageService(rpcProtocol);
const extHostDialogs = new ExtHostDialogs(rpcProtocol);
const extHostStatusBar = new ExtHostStatusBar(rpcProtocol);
const extHostProgress = new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress));
const extHostOutputService = new ExtHostOutputService(rpcProtocol);
const extHostLanguages = new ExtHostLanguages(rpcProtocol);

Expand Down Expand Up @@ -391,7 +391,7 @@ export function createApiFactory(
console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
},
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable<R>) {
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) {
return extHostProgress.withProgress(extension, options, task);
},
createOutputChannel(name: string): vscode.OutputChannel {
Expand Down
7 changes: 6 additions & 1 deletion src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,10 @@ export interface ExtHostLogServiceShape {
$setLevel(level: LogLevel);
}

export interface ExtHostProgressShape {
$acceptProgressCanceled(handle: number): void;
}

// --- proxy identifiers

export const MainContext = {
Expand Down Expand Up @@ -863,5 +867,6 @@ export const ExtHostContext = {
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews')
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress')
};
45 changes: 35 additions & 10 deletions src/vs/workbench/api/node/extHostProgress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,72 @@
*--------------------------------------------------------------------------------------------*/
'use strict';

import { Progress, ProgressOptions, CancellationToken } from 'vscode';
import { MainThreadProgressShape } from './extHost.protocol';
import { Progress, ProgressOptions } from 'vscode';
import { MainThreadProgressShape, ExtHostProgressShape } from './extHost.protocol';
import { ProgressLocation } from './extHostTypeConverters';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressStep } from 'vs/platform/progress/common/progress';
import { localize } from 'vs/nls';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';

export class ExtHostProgress {
export class ExtHostProgress implements ExtHostProgressShape {

private _proxy: MainThreadProgressShape;
private _handles: number = 0;
private _mapHandleToCancellationSource: Map<number, CancellationTokenSource> = new Map();

constructor(proxy: MainThreadProgressShape) {
this._proxy = proxy;
}

withProgress<R>(extension: IExtensionDescription, options: ProgressOptions, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> {
const handle = this._handles++;
const { title, location } = options;
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, tooltip: extension.name });
return this._withProgress(handle, task);
const { title, location, cancellable } = options;
const source = localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name);
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, source, cancellable });
return this._withProgress(handle, task, cancellable);
}

private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> {
private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>, cancellable: boolean): Thenable<R> {
let source: CancellationTokenSource;
if (cancellable) {
source = new CancellationTokenSource();
this._mapHandleToCancellationSource.set(handle, source);
}

const progress = {
report: (p: IProgressStep) => {
this._proxy.$progressReport(handle, p);
}
};

const progressEnd = (handle: number): void => {
this._proxy.$progressEnd(handle);
this._mapHandleToCancellationSource.delete(handle);
if (source) {
source.dispose();
}
};

let p: Thenable<R>;

try {
p = task(progress, null);
p = task(progress, cancellable ? source.token : CancellationToken.None);
} catch (err) {
this._proxy.$progressEnd(handle);
progressEnd(handle);
throw err;
}

p.then(result => this._proxy.$progressEnd(handle), err => this._proxy.$progressEnd(handle));
p.then(result => progressEnd(handle), err => progressEnd(handle));
return p;
}

public $acceptProgressCanceled(handle: number): void {
const source = this._mapHandleToCancellationSource.get(handle);
if (source) {
source.cancel();
this._mapHandleToCancellationSource.delete(handle);
}
}
}

1 change: 1 addition & 0 deletions src/vs/workbench/api/node/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ export namespace ProgressLocation {
switch (loc) {
case types.ProgressLocation.SourceControl: return MainProgressLocation.Scm;
case types.ProgressLocation.Window: return MainProgressLocation.Window;
case types.ProgressLocation.Notification: return MainProgressLocation.Notification;
}
return undefined;
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/node/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,7 @@ export class Task implements vscode.Task {
export enum ProgressLocation {
SourceControl = 1,
Window = 10,
Notification = 15
}

export class TreeItem {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
return this.progressService.withProgress({
location: ProgressLocation.Extensions,
title: nls.localize('installingVSIXExtension', 'Installing extension from VSIX...'),
tooltip: `${extension}`
source: `${extension}`
}, () => this.extensionService.install(extension).then(() => null));
}

Expand All @@ -610,7 +610,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
return this.progressService.withProgress({
location: ProgressLocation.Extensions,
title: nls.localize('installingMarketPlaceExtension', 'Installing extension from Marketplace....'),
tooltip: `${extension.id}`
source: `${extension.id}`
}, () => this.extensionService.installFromGallery(gallery).then(() => null));
}

Expand Down Expand Up @@ -651,7 +651,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
return this.progressService.withProgress({
location: ProgressLocation.Extensions,
title: nls.localize('uninstallingExtension', 'Uninstalling extension....'),
tooltip: `${local.identifier.id}`
source: `${local.identifier.id}`
}, () => this.extensionService.uninstall(local));
}

Expand All @@ -669,7 +669,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {

return this.progressService.withProgress({
location: ProgressLocation.Extensions,
tooltip: `${local.identifier.id}`
source: `${local.identifier.id}`
}, () => this.extensionService.reinstallFromGallery(local).then(() => null));
}

Expand Down
Loading