diff --git a/packages/core/src/common/message-service-protocol.ts b/packages/core/src/common/message-service-protocol.ts index 26ba6d2bbb2f5..0be44e5a501ff 100644 --- a/packages/core/src/common/message-service-protocol.ts +++ b/packages/core/src/common/message-service-protocol.ts @@ -67,8 +67,13 @@ export interface Progress { } export interface ProgressUpdate { - readonly value?: string; - readonly increment?: number; + readonly message?: string; + readonly progressRate?: ProgressRate; +} + +export interface ProgressRate { + done: number; + total: number; } @injectable() @@ -103,7 +108,7 @@ export class MessageClient { * * To be implemented by an extension, e.g. by the messages extension. */ - reportProgress(progressId: string, update: ProgressUpdate): Promise { + reportProgress(progressId: string, update: ProgressUpdate, message: ProgressMessage, cancellationToken: CancellationToken): Promise { return Promise.resolve(undefined); } } @@ -125,9 +130,9 @@ export class DispatchingMessageClient extends MessageClient { )); } - reportProgress(progressId: string, update: ProgressUpdate): Promise { + reportProgress(progressId: string, update: ProgressUpdate, message: ProgressMessage, cancellationToken: CancellationToken): Promise { return Promise.race([...this.clients].map(client => - client.reportProgress(progressId, update) + client.reportProgress(progressId, update, message, cancellationToken) )); } diff --git a/packages/core/src/common/message-service.ts b/packages/core/src/common/message-service.ts index b8b92f94eeca9..d8687b7a586be 100644 --- a/packages/core/src/common/message-service.ts +++ b/packages/core/src/common/message-service.ts @@ -77,7 +77,7 @@ export class MessageService { const id = this.newProgressId(); const cancellationSource = new CancellationTokenSource(); const report = (update: ProgressUpdate) => { - this.client.reportProgress(id, update); + this.client.reportProgress(id, update, message, cancellationSource.token); }; let clientMessage = message; if (ProgressMessage.isCancelable(message)) { diff --git a/packages/messages/src/browser/notifications-message-client.ts b/packages/messages/src/browser/notifications-message-client.ts index 9b92789ef748e..2c2ae8332fe0e 100644 --- a/packages/messages/src/browser/notifications-message-client.ts +++ b/packages/messages/src/browser/notifications-message-client.ts @@ -36,7 +36,7 @@ export class NotificationsMessageClient extends MessageClient { return this.show(message); } - showProgress(progressId: string, message: ProgressMessage, cancellationToken: CancellationToken): Promise { + showProgress(progressId: string, message: ProgressMessage, cancellationToken: CancellationToken, update?: ProgressUpdate): Promise { const messageArguments = { ...message, type: MessageType.Progress, options: { ...(message.options || {}), timeout: 0 } }; if (this.visibleProgressNotifications.has(progressId)) { throw new Error('Cannot show new progress with already existing id.'); @@ -48,6 +48,9 @@ export class NotificationsMessageClient extends MessageClient { })); this.visibleProgressNotifications.set(progressId, progressNotification); progressNotification.show(); + if (update) { + progressNotification.update(update); + } const cancel = () => { if (message.options && message.options.cancelable) { resolve(ProgressMessage.Cancel); @@ -62,10 +65,12 @@ export class NotificationsMessageClient extends MessageClient { }); } - async reportProgress(progressId: string, update: ProgressUpdate): Promise { + async reportProgress(progressId: string, update: ProgressUpdate, message: ProgressMessage, cancellationToken: CancellationToken): Promise { const notification = this.visibleProgressNotifications.get(progressId); if (notification) { - notification.update({ message: update.value, increment: update.increment }); + notification.update({ message: update.message, progressRate: update.progressRate }); + } else { + this.showProgress(progressId, message, cancellationToken, { message: update.message, progressRate: update.progressRate }); } } diff --git a/packages/messages/src/browser/notifications.ts b/packages/messages/src/browser/notifications.ts index 379db296006cf..9c2c7afe008ab 100644 --- a/packages/messages/src/browser/notifications.ts +++ b/packages/messages/src/browser/notifications.ts @@ -13,6 +13,7 @@ * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import { ProgressRate } from '@theia/core/src/common'; export const NOTIFICATIONS_CONTAINER = 'theia-NotificationsContainer'; export const NOTIFICATION = 'theia-Notification'; @@ -42,7 +43,7 @@ export interface Notification { export interface ProgressNotification { show(): void; close(): void; - update(item: { message?: string, increment?: number }): void; + update(item: { message?: string, progressRate?: ProgressRate }): void; } export class Notifications { @@ -134,7 +135,6 @@ export class Notifications { } class ProgressNotificationImpl implements ProgressNotification { - private increment: number = 0; private readonly node: Node; private readonly container: Element; private readonly properties: NotificationProperties; @@ -167,16 +167,14 @@ class ProgressNotificationImpl implements ProgressNotification { } } - update(item: { message?: string, increment?: number }): void { + update(item: { message?: string, progressRate?: ProgressRate }): void { const textElement = document.getElementById('notification-text-' + this.properties.id); if (textElement) { - if (item.increment) { - this.increment = this.increment + item.increment; - this.increment = this.increment > 100 ? 100 : this.increment; - + if (item.progressRate) { const progressElement = document.getElementById('notification-progress-' + this.properties.id); if (progressElement) { - progressElement.innerText = this.increment + '%'; + const progressRate = item.progressRate; + progressElement.innerText = `${Math.floor(progressRate.done / progressRate.total * 100)}%`; } } textElement.innerText = this.properties.text + (item.message ? ': ' + item.message : ''); diff --git a/packages/plugin-ext/src/main/browser/notification-main.ts b/packages/plugin-ext/src/main/browser/notification-main.ts index de36726d661ca..6f50cdcf9321a 100644 --- a/packages/plugin-ext/src/main/browser/notification-main.ts +++ b/packages/plugin-ext/src/main/browser/notification-main.ts @@ -24,7 +24,8 @@ export class NotificationMainImpl implements NotificationMain { private readonly proxy: NotificationExt; private readonly messageService: MessageService; - private readonly progress = new Map(); + private readonly progressMap = new Map(); + private readonly incrementMap = new Map(); constructor(rpc: RPCProtocol, container: interfaces.Container) { this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.NOTIFICATION_EXT); @@ -36,21 +37,33 @@ export class NotificationMainImpl implements NotificationMain { const onDidClose = async () => this.proxy.$onCancel(await deferredId.promise); const progress = await this.messageService.showProgress({ text: message, options: { cancelable: true } }, onDidClose); deferredId.resolve(progress.id); - this.progress.set(progress.id, progress); + this.progressMap.set(progress.id, progress); + this.incrementMap.set(progress.id, 0); return progress.id; } $stopProgress(id: string): void { - const progress = this.progress.get(id); + const progress = this.progressMap.get(id); if (progress) { progress.cancel(); + this.progressMap.delete(id); + this.incrementMap.delete(id); } } $updateProgress(id: string, item: { message?: string, increment?: number }): void { - const progress = this.progress.get(id); + const progress = this.progressMap.get(id); + let done: number | undefined; + if (item.increment) { + const increment = this.incrementMap.get(id); + if (increment !== undefined) { + done = increment + item.increment; + done = done > 100 ? 100 : done; + this.incrementMap.set(id, done); + } + } if (progress) { - progress.report({ value: item.message, increment: item.increment }); + progress.report({ message: item.message, progressRate: done ? { done, total: 100 } : undefined }); } } }