Skip to main content
Version: v4

ShortCut Formatter

Overview​

The ShortCutFormatter class extends the CometChatTextFormatter class to provide a mechanism for handling shortcuts within messages. This guide will walk you through the process of using ShortCutFormatter to implement shortcut extensions in your CometChat application.

Image

Usage​

Here are the steps to create a ShortCutFormatter for CometChat using the CometChatTextFormatter:

  1. Firstly, you need to import CometChatTextFormatter from the CometChat UI Kit angular library.
import { CometChatTextFormatter } from "@cometchat/chat-uikit-angular";
  1. Now, extend the CometChatTextFormatter class to create your custom text formatter class. In this case, let's create a HashTagTextFormatter.
class ShortCutFormatter extends CometChatTextFormatter {
...
}
  1. Set up the trackCharacter and define any necessary private fields.
this.setTrackingCharacter("!");
  1. Implement the onKeyDown method to handle key events and trigger actions based on defined shortcuts.
onKeyDown(event: KeyboardEvent) {
// Your implementation
}
  1. Implement any additional methods required for your custom formatter, such as opening and closing dialogs, handling button clicks, and formatting text.
openDialog(buttonText: string) {
// Your implementation
}

closeDialog() {
// Your implementation
}

handleButtonClick = () => {
// Your implementation
};

getFormattedText(text: string): string {
return text;
}

private getTextBeforeCaret(caretPosition: number): string {
// Your implementation
}

Example​

Below is an example demonstrating how to use a custom formatter class in components such as CometChatConversations, CometChatMessageList, CometChatMessageComposer.

Image
Image
import { CometChatTextFormatter } from "@cometchat/uikit-shared";
import { Subject } from 'rxjs';
import { CometChat } from "@cometchat/chat-sdk-javascript";

export class ShortcutFormatter extends CometChatTextFormatter {
private shortcuts: { [key: string]: string } = {};
private dialogIsOpen: boolean = false;
private currentShortcut: string | null = null;
private openDialogSubject = new Subject<{ closeDialog?: boolean, buttonText?: string, shortcut?: string, handleButtonClick?:any }>();
openDialog$ = this.openDialogSubject.asObservable();

constructor() {
super();
this.setTrackingCharacter('!');
CometChat.callExtension('message-shortcuts', 'GET', 'v1/fetch', undefined)
.then((data: any) => {
if (data && data.shortcuts) {
this.shortcuts = data.shortcuts;
}
})
.catch(error => console.log("error fetching shortcuts", error));
}

override onKeyDown(event: KeyboardEvent) {
const caretPosition = this.currentCaretPosition instanceof Selection
? this.currentCaretPosition.anchorOffset
: 0;
const textBeforeCaret = this.getTextBeforeCaret(caretPosition);

const match = textBeforeCaret.match(/!([a-zA-Z]+)$/);
if (match) {
const shortcut = match[0];
const replacement = this.shortcuts[shortcut];
if (replacement) {
if (this.dialogIsOpen && this.currentShortcut !== shortcut) {
this.closeDialog();
}
this.openDialog(replacement, shortcut);
}
}
}

getCaretPosition() {
if (!this.currentCaretPosition?.rangeCount) return { x: 0, y: 0 };
const range = this.currentCaretPosition?.getRangeAt(0);
const rect = range.getBoundingClientRect();
return {
x: rect.left,
y: rect.top
};
}

openDialog(buttonText: string, shortcut: string) {
this.openDialogSubject.next({ buttonText, shortcut , handleButtonClick: this.handleButtonClick});
this.dialogIsOpen = true;
this.currentShortcut = shortcut;
}

closeDialog() {
this.openDialogSubject.next({closeDialog: true});
}

handleButtonClick = (buttonText: string) => {
console.log(buttonText);

if (this.currentCaretPosition && this.currentRange) {
const shortcut = Object.keys(this.shortcuts).find(key => this.shortcuts[key] === buttonText);
if (shortcut) {
const replacement = this.shortcuts[shortcut];
this.addAtCaretPosition(replacement, this.currentCaretPosition, this.currentRange);
}
}
if (this.dialogIsOpen) {
this.closeDialog();
}
};

override getFormattedText(text: string): string {
return text;
}

private getTextBeforeCaret(caretPosition: number): string {
if (this.currentRange && this.currentRange.startContainer && typeof this.currentRange.startContainer.textContent === "string") {
const textContent = this.currentRange.startContainer.textContent;
if (textContent.length >= caretPosition) {
return textContent.substring(0, caretPosition);
}
}
return "";
}
}

export default ShortcutFormatter;