UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

83 lines (76 loc) 3.38 kB
// ***************************************************************************** // 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'; @injectable() export class ProgressService { @inject(ProgressClient) protected readonly client: ProgressClient; @inject(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(); } } }