Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API documentation for 'MessageService' #13

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}.
* For example "@theia/messages" provides such a client, 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.
* @param onDidCancel an optional callback which will be invoked if the progress indicator was 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