Skip to content

Commit

Permalink
fixup! fixes #2802 Introduce 'window.withProgress' API endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Vinokur <ivinokur@redhat.com>
  • Loading branch information
vinokurig committed Oct 26, 2018
1 parent 5b0fe0c commit 87d7332
Show file tree
Hide file tree
Showing 14 changed files with 695 additions and 24 deletions.
52 changes: 51 additions & 1 deletion packages/core/src/common/message-service-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@

import { injectable, inject } from 'inversify';
import { ILogger } from './logger';
import { Event } from '../common';

export const messageServicePath = '/services/messageService';

export enum MessageType {
Error = 1,
Warning = 2,
Info = 3,
Log = 4
Log = 4,
Progress = 5
}

export interface Message {
Expand All @@ -33,6 +35,11 @@ export interface Message {
options?: MessageOptions;
}

export interface ProgressMessageArguments {
text: string;
actions?: string[];
}

export interface MessageOptions {
timeout?: number;
}
Expand All @@ -53,6 +60,40 @@ export class MessageClient {
this.logger.info(message.text);
return Promise.resolve(undefined);
}

/**
* Show progress message with possible actions to user.
*
* To be implemented by an extension, e.g. by the messages extension.
*/
newProgress(message: ProgressMessageArguments): Promise<ProgressToken| undefined> {
return Promise.resolve(undefined);
}

/**
* Hide progress message.
*
* To be implemented by an extension, e.g. by the messages extension.
*/
stopProgress(progress: ProgressToken): Promise<void> {
return Promise.resolve(undefined);
}

/**
* Update started progress message.
*
* To be implemented by an extension, e.g. by the messages extension.
*/
reportProgress(progress: ProgressToken, update: ProgressUpdate): Promise<void> {
return Promise.resolve(undefined);
}

/**
* Event that fires when a progress message is canceled.
*
* To be implemented by an extension, e.g. by the messages extension.
*/
onProgressCanceled: Event<string>;
}

@injectable()
Expand All @@ -67,3 +108,12 @@ export class DispatchingMessageClient extends MessageClient {
}

}

export interface ProgressToken {
id: string;
}

export interface ProgressUpdate {
value?: string;
increment?: number;
}
22 changes: 21 additions & 1 deletion packages/core/src/common/message-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@
********************************************************************************/

import { injectable, inject } from 'inversify';
import { MessageClient, MessageType, MessageOptions } from './message-service-protocol';
import { Event } from '../common';
import {
MessageClient,
MessageType,
MessageOptions,
ProgressToken,
ProgressUpdate, ProgressMessageArguments
} from './message-service-protocol';

@injectable()
export class MessageService {
Expand Down Expand Up @@ -65,4 +72,17 @@ export class MessageService {
return this.client.showMessage({ type, text });
}

newProgress(message: ProgressMessageArguments): Promise<ProgressToken | undefined> {
return this.client.newProgress(message);
}

stopProgress(progress: ProgressToken): Promise<void> {
return this.client.stopProgress(progress);
}

reportProgress(progress: ProgressToken, update: ProgressUpdate): Promise<void> {
return this.client.reportProgress(progress, update);
}

onProgressCanceled: Event<string> = this.client.onProgressCanceled;
}
67 changes: 54 additions & 13 deletions packages/messages/src/browser/notifications-message-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,82 @@ import { injectable, inject } from 'inversify';
import {
MessageClient,
MessageType,
Message
Message,
Emitter,
ProgressMessageArguments,
ProgressToken,
ProgressUpdate
} from '@theia/core/lib/common';
import { Notifications, NotificationAction } from './notifications';
import { Notifications, NotificationAction, NotificationProperties, ProgressNotification} from './notifications';
import { NotificationPreferences } from './notification-preferences';

@injectable()
export class NotificationsMessageClient extends MessageClient {

private readonly onProgressCanceledEmitter: Emitter<string> = new Emitter();
readonly onProgressCanceled = this.onProgressCanceledEmitter.event;
protected notifications: Notifications = new Notifications();
@inject(NotificationPreferences) protected preferences: NotificationPreferences;

showMessage(message: Message): Promise<string | undefined> {
return this.show(message);
}

newProgress(message: ProgressMessageArguments): Promise<ProgressToken | undefined> {
const messageArguments = { type: MessageType.Progress, text: message.text, options: { timeout: 0 }, actions: message.actions };
const key = this.getKey(messageArguments);
if (this.visibleProgressNotifications.has(key)) {
return Promise.resolve({ id: key });
}
const progressNotification = this.notifications.create(this.getNotificationProperties(
key,
messageArguments,
() => {
this.onProgressCanceledEmitter.fire(key);
this.visibleProgressNotifications.delete(key);
}));
this.visibleProgressNotifications.set(key, progressNotification);
progressNotification.show();
return Promise.resolve({ id: key });
}

stopProgress(progress: ProgressToken): Promise<void> {
const progressMessage = this.visibleProgressNotifications.get(progress.id);
if (progressMessage) {
progressMessage.close();
}
return Promise.resolve(undefined);
}

reportProgress(progress: ProgressToken, update: ProgressUpdate): Promise<void> {
const notification = this.visibleProgressNotifications.get(progress.id);
if (notification) {
notification.update({ message: update.value, increment: update.increment });
}
return Promise.resolve(undefined);
}

protected visibleMessages = new Set<string>();
protected visibleProgressNotifications = new Map<string, ProgressNotification>();
protected show(message: Message): Promise<string | undefined> {
const key = this.getKey(message);
if (this.visibleMessages.has(key)) {
return Promise.resolve(undefined);
}
this.visibleMessages.add(key);
return new Promise(resolve => {
this.showToast(message, a => {
this.notifications.show(this.getNotificationProperties(key, message, a => {
this.visibleMessages.delete(key);
resolve(a);
});
}));
});
}

protected getKey(m: Message): string {
return `${m.type}-${m.text}-${m.actions ? m.actions.join('|') : '|'}`;
}

protected showToast(message: Message, onCloseFn: (action: string | undefined) => void): void {
protected getNotificationProperties(id: string, message: Message, onCloseFn: (action: string | undefined) => void): NotificationProperties {
const icon = this.iconFor(message.type);
const text = message.text;
const actions = (message.actions || []).map(action => <NotificationAction>{
Expand All @@ -69,22 +110,22 @@ export class NotificationsMessageClient extends MessageClient {
label: 'Close',
fn: element => onCloseFn(undefined)
});
this.notifications.show({
return {
id,
icon,
text,
actions,
timeout,
onTimeout: () => onCloseFn(undefined)
});
};
}

protected iconFor(type: MessageType): string {
if (type === MessageType.Error) {
return 'error';
}
if (type === MessageType.Warning) {
return 'warning';
switch (type) {
case MessageType.Error: return 'error';
case MessageType.Warning: return 'warning';
case MessageType.Progress: return 'progress';
default: return 'info';
}
return 'info';
}
}
Loading

0 comments on commit 87d7332

Please sign in to comment.