@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
83 lines (76 loc) • 3.38 kB
text/typescript
// *****************************************************************************
// Copyright (C) 2019 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
import { injectable, inject } from 'inversify';
import {
Progress,
ProgressUpdate,
ProgressMessage
} from './message-service-protocol';
import { CancellationTokenSource } from './cancellation';
import { ProgressClient } from './progress-service-protocol';
import { MessageService } from './message-service';
()
export class ProgressService {
(ProgressClient) protected readonly client: ProgressClient;
(MessageService) protected readonly messageService: MessageService;
async showProgress(message: ProgressMessage, onDidCancel?: () => void): Promise<Progress> {
if (this.shouldDelegate(message)) {
return this.messageService.showProgress(message, onDidCancel);
}
const id = this.newProgressId();
const cancellationSource = new CancellationTokenSource();
const report = (update: ProgressUpdate) => {
this.client.reportProgress(id, update, message, cancellationSource.token);
};
const actions = new Set<string>(message.actions);
if (ProgressMessage.isCancelable(message)) {
actions.delete(ProgressMessage.Cancel);
actions.add(ProgressMessage.Cancel);
}
const clientMessage = { ...message, actions: Array.from(actions) };
const result = this.client.showProgress(id, clientMessage, cancellationSource.token);
if (ProgressMessage.isCancelable(message) && typeof onDidCancel === 'function') {
result.then(value => {
if (value === ProgressMessage.Cancel) {
onDidCancel();
}
});
}
return {
id,
cancel: () => cancellationSource.cancel(),
result,
report
};
}
protected shouldDelegate(message: ProgressMessage): boolean {
const location = message.options && message.options.location;
return location === 'notification';
}
private progressIdPrefix = Math.random().toString(36).substring(5);
private counter = 0;
protected newProgressId(): string {
return `${this.progressIdPrefix}-${++this.counter}`;
}
async withProgress<T>(text: string, locationId: string, task: () => Promise<T>, onDidCancel?: () => void): Promise<T> {
const progress = await this.showProgress({ text, options: { cancelable: true, location: locationId } }, onDidCancel);
try {
return await task();
} finally {
progress.cancel();
}
}
}