Skip to content

Commit

Permalink
Add API documentation for 'MessageService'
Browse files Browse the repository at this point in the history
Document 'MessageService' and related message interfaces.

Signed-off-by: Stefan Dirix <sdirix@eclipsesource.com>
Contributed on behalf of STMicroelectronics
  • Loading branch information
sdirix committed Oct 29, 2020
1 parent fb3694b commit 63d26a5
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
34 changes: 34 additions & 0 deletions packages/core/src/common/message-service-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,21 @@ export enum MessageType {
}

export interface Message {
/**
* Type of the message, i.e. error, warning, info, etc.
*/
readonly type?: MessageType;
/**
* Message text.
*/
readonly text: string;
/**
* Actions offered to the user in the context of the message.
*/
readonly actions?: string[];
/**
* Additional options.
*/
readonly options?: MessageOptions;
readonly source?: string;
}
Expand Down Expand Up @@ -66,14 +78,36 @@ export interface ProgressMessageOptions extends MessageOptions {
}

export interface Progress {
/**
* Unique progress id.
*/
readonly id: string;
/**
* Update the current progress.
*
* @param update the data to update.
*/
readonly report: (update: ProgressUpdate) => void;
/**
* Cancel or complete the current progress.
*/
readonly cancel: () => void;
/**
* Result of the progress.
*
* @returns a promise which resolves to either 'Cancel', an alternative action or `undefined`.
*/
readonly result: Promise<string | undefined>;
}

export interface ProgressUpdate {
/**
* Updated message for the progress.
*/
readonly message?: string;
/**
* Updated ratio between steps done so far and total number of steps.
*/
readonly work?: { done: number, total: number };
}

Expand Down
116 changes: 116 additions & 0 deletions packages/core/src/common/message-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,114 @@ import {
} from './message-service-protocol';
import { CancellationTokenSource } from './cancellation';

/**
* Service to log and categorize messages, show progress information and offer actions.
*
* The messages are processed by this service and forwarded to an injected {@link MessageClient}.
* Usually this is the {@link NotificationManager} contributed by "@theia/messages" rendering
* messages as notifications in the frontend.
*
* ### Example usage
*
* ```typescript
* @inject(MessageService)
* protected readonly messageService: MessageService;
*
* messageService.warn("Typings not available");
*
* messageService.error("Could not restore state", ["Rollback", "Ignore"])
* .then(action => action === "Rollback" && rollback());
* ```
*/
@injectable()
export class MessageService {

constructor(
@inject(MessageClient) protected readonly client: MessageClient
) { }

/**
* Logs the message and, if given, offers actions to act on it.
* @param message the message to log.
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
log<T extends string>(message: string, ...actions: T[]): Promise<T | undefined>;
/**
* Logs the message and, if given, offers actions to act on it.
* @param message the message to log.
* @param options additional options. Can be omitted
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
log<T extends string>(message: string, options?: MessageOptions, ...actions: T[]): Promise<T | undefined>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
log(message: string, ...args: any[]): Promise<string | undefined> {
return this.processMessage(MessageType.Log, message, args);
}

/**
* Logs the message as "info" and, if given, offers actions to act on it.
* @param message the message to log.
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
info<T extends string>(message: string, ...actions: T[]): Promise<T | undefined>;
/**
* Logs the message as "info" and, if given, offers actions to act on it.
* @param message the message to log.
* @param options additional options. Can be omitted
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
info<T extends string>(message: string, options?: MessageOptions, ...actions: T[]): Promise<T | undefined>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
info(message: string, ...args: any[]): Promise<string | undefined> {
return this.processMessage(MessageType.Info, message, args);
}

/**
* Logs the message as "warning" and, if given, offers actions to act on it.
* @param message the message to log.
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
warn<T extends string>(message: string, ...actions: T[]): Promise<T | undefined>;
/**
* Logs the message as "warning" and, if given, offers actions to act on it.
* @param message the message to log.
* @param options additional options. Can be omitted
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
warn<T extends string>(message: string, options?: MessageOptions, ...actions: T[]): Promise<T | undefined>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
warn(message: string, ...args: any[]): Promise<string | undefined> {
return this.processMessage(MessageType.Warning, message, args);
}

/**
* Logs the message as "error" and, if given, offers actions to act on it.
* @param message the message to log.
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
error<T extends string>(message: string, ...actions: T[]): Promise<T | undefined>;
/**
* Logs the message as "error" and, if given, offers actions to act on it.
* @param message the message to log.
* @param options additional options. Can be omitted
* @param actions the actions to offer. Can be omitted.
*
* @returns the selected action if there is any, `undefined` when there was no action or none was selected.
*/
error<T extends string>(message: string, options?: MessageOptions, ...actions: T[]): Promise<T | undefined>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
error(message: string, ...args: any[]): Promise<string | undefined> {
Expand All @@ -73,6 +152,43 @@ export class MessageService {
return this.client.showMessage({ type, text });
}

/**
* Shows the given message as a progress.
*
* @param message the message to show for the progress. If not specified otherwise the message will be cancelable.
* @param onDidCancel an optional callback which will be invoked if the progress indicator was indeed canceled.
*
* @returns a promise resolving to a {@link Progress} object with which the progress can be updated.
*
* ### Example usage
*
* ```typescript
* @inject(MessageService)
* protected readonly messageService: MessageService;
*
* // this will show "Progress" as a cancelable message
* this.messageService.showProgress({text: 'Progress'});
*
* // this will show "Rolling back" with "Cancel" and an additional "Skip" action
* this.messageService.showProgress({
* text: `Rolling back`,
* actions: ["Skip"],
* },
* () => console.log("canceled"))
* .then((progress) => {
* // register if interested in the result (only necessary for custom actions)
* progress.result.then((result) => {
* // will be 'Cancel', 'Skip' or `undefined`
* console.log("result is", result);
* });
* progress.report({message: "Cleaning references", work: {done: 10, total: 100}});
* progress.report({message: "Restoring previous state", work: {done: 80, total: 100}});
* progress.report({message: "Complete", work: {done: 100, total: 100}});
* // we are done so we can cancel the progress message, note that this will also invoke `onDidCancel`
* progress.cancel();
* });
* ```
*/
async showProgress(message: ProgressMessage, onDidCancel?: () => void): Promise<Progress> {
const id = this.newProgressId();
const cancellationSource = new CancellationTokenSource();
Expand Down

0 comments on commit 63d26a5

Please sign in to comment.