Skip to main content
Version: v5

Conversations

Overview

The Conversations is a Component, that shows all conversations related to the currently logged-in user.

This component lists the most recent or latest conversations or contacts with whom you have exchanged messages. It provides a convenient way to quickly access and resume conversations with the people you have been in contact with recently.

Image

Usage

Integration

import {
CometChatConversations,
TitleAlignment,
} from "@cometchat/chat-uikit-react";

function ConversationsDemo() {
return (
<div className="conversations" style={{ width: "100%", height: "100%" }}>
<div>
<CometChatConversations />
</div>
</div>
);
}

export default ConversationsDemo;

Actions

Actions dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs.

1. OnItemClick

OnItemClick is triggered when you click on a ListItem of the Conversations component. The OnItemClick action doesn't have a predefined behavior. You can override this action using the following code snippet.

import { CometChatConversations } from "@cometchat/chat-uikit-react";

const getOnItemClick = (conversation: CometChat.Conversation) => {
console.log("ItemClick:", conversation);
// Your custom action here
};

<CometChatConversations onItemClick={getOnItemClick} />;

2. OnSelect

The OnSelect event is triggered upon the completion of a selection in SelectionMode. It does not have a default behavior. However, you can override its behavior using the following code snippet.

import {
CometChatConversations,
SelectionMode,
} from "@cometchat/chat-uikit-react";

const getOnSelect = (
conversation: CometChat.Conversation,
selected: boolean
) => {
console.log("Selected, ", conversation.getConversationId(), selected);
// Your custom action on select
};

<CometChatConversations
selectionMode={SelectionMode.multiple}
onSelect={getOnSelect}
/>;

3. OnError

This action doesn't change the behavior of the component but rather listens for any errors that occur in the Conversations component.

import { CometChatConversations } from "@cometchat/chat-uikit-react";

const handleOnError = (error: CometChat.CometChatException) => {
// Your exception handling code
};

<CometChatConversations onError={handleOnError} />;

Filters

You can set ConversationsRequestBuilder in the Conversations Component to filter the conversation list. You can modify the builder as per your specific requirements with multiple options available to know more refer to ConversationRequestBuilder.

You can set filters using the following parameters.

  1. Conversation Type: Filters on type of Conversation, User or Groups
  2. Limit: Number of conversations fetched in a single request.
  3. WithTags: Filter on fetching conversations containing tags
  4. Tags: Filters on specific Tag
  5. UserTags: Filters on specific User Tag
  6. GroupTags: Filters on specific Group Tag
import { CometChatConversations } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

<CometChatConversations
conversationsRequestBuilder={new CometChat.ConversationsRequestBuilder().setLimit(
10
)}
/>;

Events

Events are emitted by a Component. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed.

const ccConversationDeleted =
CometChatConversationEvents.ccConversationDeleted.subscribe(
(conversation: CometChat.Conversation) => {
// Your code here
}
);

ccConversationDeleted?.unsubscribe();

Customization

To fit your app's design requirements, you can customize the appearance of the conversation component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs.

Style

Using CSS you can customize the look and feel of the component in your app like the color, size, shape, and fonts.

Image
<CometChatConversations />

Functionality

These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements.

<div className="conversations" style={{ width: "100%", height: "100%" }}>
<div>
<CometChatConversations title="Your Custom Title" />
</div>
</div>

Below is a list of customizations along with corresponding code snippets

PropertyDescriptionCode
Hide ReceiptsDisables the display of message read receipts. If set to true, the receipt status of the sent message won't be displayed.hideReceipts={false}
Hide ErrorHides the default and the custom error view passed in the errorView prop.hideError={true}
Hide Delete ConversationHides the delete conversation option in the default context menu.hideDeleteConversation={false}
Hide User StatusHides the user's online/offline status indicator.hideUserStatus={true}
Hide Group TypeHides the group type icon.hideGroupType={false}
Active ConversationSpecifies the conversation to highlight in the list.activeConversation={activeConversation}
Selection ModeDetermines the selection mode for the component.selectionMode={SelectionMode.multiple}
Disable Sound For MessagesUsed to Disable sound for incoming messages.disableSoundForMessages={false}
Custom Sound For MessagesCustom audio sound for incoming messages.customSoundForMessages="Your custom sound url"
Loading ViewA custom component to display during the loading state.loadingView={<>Custom Loading View</>}
Empty ViewA custom component to display when there are no conversations available.emptyView={<>Custom Empty View</>}
Error ViewA custom component to display when an error occurs.errorView={<>Custom Error View</>}

Advanced

For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component.


ItemView

With this function, you can assign a custom ListItem to the Conversations Component.

Shown below is the default chat interface.

Image

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
CometChatListItem,
CometChatConversations,
} from "@cometchat/chat-uikit-react";

const getItemView = (conversation: CometChat.Conversation) => {
const title = conversation.getConversationWith().getName();
const timestamp = conversation?.getLastMessage()?.getSentAt();

return (
<CometChatListItem
title={title}
avatarName={title}
id={conversation.getConversationId()}
trailingView={<CometChatDate timestamp={timestamp} />}
onListItemClicked={() => {
// Logic here
}}
/>
);
};

<CometChatConversations
itemView={getItemView} // Custom list item view
/>;

LeadingView

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import React from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatConversations,CometChatAvatar } from "@cometchat/chat-uikit-react";
import {useEffect, useRef, useState} from "react";
const [isTyping, setIsTyping] = useState<boolean>(false);
const typingObjRef = useRef<CometChat.TypingIndicator | null>(null);

useEffect(()=>{
//adding typing listeners
const messageListenerId: string = "typing_demo_" + new Date().getTime();
CometChat.addMessageListener(messageListenerId, new CometChat.MessageListener({
onTypingStarted: (typingIndicator: CometChat.TypingIndicator) => {
typingObjRef.current = typingIndicator;
setIsTyping(true)
},
onTypingEnded: (typingIndicator: CometChat.TypingIndicator) => {
if(typingObjRef.current && typingObjRef.current.getSender().getUid() == typingIndicator.getSender().getUid()){
typingObjRef.current = null;
setIsTyping(false)
}
},}))
return () => {
CometChat.removeMessageListener(messageListenerId)
};
},[setIsTyping])

// Custom leading view component
const CustomLeadingView = (conversation: CometChat.Conversation) => {
const conversationObj = conversation.getConversationWith();
const isUser = conversationObj instanceof CometChat.User;
const isGroup = conversationObj instanceof CometChat.Group;

// Check if the current user is typing
const isMyTyping = isUser
? (conversationObj as CometChat.User).getUid() === typingObjRef.current?.getSender().getUid() &&
loggedInUser?.getUid() === typingObjRef.current?.getReceiverId()
: isGroup &&
(conversationObj as CometChat.Group).getGuid() === typingObjRef.current?.getReceiverId();

// Determine avatar and name
const avatar = isUser
? (conversationObj as CometChat.User).getAvatar()
: (conversationObj as CometChat.Group).getIcon();
const name = isTyping && isMyTyping ? undefined : conversationObj.getName();
const image = isTyping && isMyTyping ? "TYPING_ICON_HERE" : avatar;

return (
<div className="conversations__leading-view">
<CometChatAvatar image={image} name={name} />
</div>
);
};
<CometChatConversations leadingView={CustomLeadingView} />;

TrailingView

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import React from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
CometChatConversations
} from "@cometchat/chat-uikit-react";

// Custom trailing view component
const CustomTrailingButtonView = (conv: CometChat.Conversation) => {
if (!conv.getLastMessage()) {
return <></>;
}
const timestamp = conv.getLastMessage()?.getSentAt() * 1000;
const now = new Date();
const time = new Date(timestamp);

// Calculate time difference
const diffInMs = now.getTime() - time.getTime();
const diffInMinutes = Math.floor(diffInMs / (1000 * 60));
const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60));

// Determine the labels
let backgroundColorClass = "conversations__trailing-view-min"; // Default (less than 1 hour)
let topLabel = `${diffInMinutes}`; // Default minutes
let bottomLabel = `${diffInMinutes === 1 ? "Min ago" : "Mins ago"}`; // Default "Mins ago"

if (diffInHours >= 1 && diffInHours <= 10) {
// 1-10 hours
backgroundColorClass = "conversations__trailing-view-hour";
topLabel = `${diffInHours}`;
bottomLabel = `${diffInHours === 1 ? "Hour ago" : "Hours ago"}`;
} else if (diffInHours > 10) {
// More than 10 hours
backgroundColorClass = "conversations__trailing-view-date";
topLabel = time.toLocaleDateString("en-US", { day: "numeric" });
bottomLabel = time.toLocaleDateString("en-US", {
month: "short",
year: "numeric",
});
}
return (
<div className={`conversations__trailing-view ${backgroundColorClass}`}>
<span className="conversations__trailing-view-time">{topLabel}</span>
<span className="conversations__trailing-view-status">{bottomLabel}</span>
</div>
);
};

<CometChatConversations trailingView={CustomTrailingButtonView} />;

TextFormatters

Assigns the list of text formatters. If the provided list is not null, it sets the list. Otherwise, it assigns the default text formatters retrieved from the data source. To configure the existing Mentions look and feel check out CometChatMentionsFormatter

import { CometChatTextFormatter } from "@cometchat/chat-uikit-react";
import DialogHelper from "./Dialog";
import { CometChat } from "@cometchat/chat-sdk-javascript";

class ShortcutFormatter extends CometChatTextFormatter {
private shortcuts: { [key: string]: string } = {};
private dialogIsOpen: boolean = false;
private dialogHelper = new DialogHelper();
private currentShortcut: string | null = null; // Track the currently open shortcut

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));
}

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) {
// Close the currently open dialog, if any
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.dialogHelper.createDialog(
() => this.handleButtonClick(buttonText),
buttonText
);
this.dialogIsOpen = true;
this.currentShortcut = shortcut;
}

closeDialog() {
this.dialogHelper.closeDialog(); // Use DialogHelper to close the dialog
this.dialogIsOpen = false;
this.currentShortcut = null;
}

handleButtonClick = (buttonText: string) => {
if (this.currentCaretPosition && this.currentRange) {
// Inserting the replacement text corresponding to the shortcut
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();
}
};

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;

Header View

You can set the Custom Header view to add more options to the Conversations component.

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import {
CometChatButton,
CometChatConversations,
} from "@cometchat/chat-uikit-react";

const getHeaderView = () => {
return (
<div className="conversations__header">
<div className="conversations__header__title">
{localize("CHATS")}
</div>
<CometChatButton
onClick={() => {
// logic here
}}
iconURL={ICON_URL}
/>
</div>
);
};

<CometChatConversations headerView={getHeaderView()} />;

DatePattern

You can modify the date pattern to your requirement using DatePattern. datePattern formats date and time values according to a predefined standard, enhancing consistency and clarity in their presentation.

Shown below is the default chat interface.

Image

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import {
DatePatterns,
CometChatConversations,
} from "@cometchat/chat-uikit-react";

<CometChatConversations datePattern={DatePatterns.DateTime} />;

DatePatterns describes a specific format or arrangement used to represent dates in a human-readable form.

NameDescription
timeDate format displayed in the format hh:mm a
DayDateDate format displayed in the following format.
  1. If timestamp < 24hrs display “Today”
  2. If timestamp < 48hrs display “Yesterday”
  3. If timestamp < 7days display “EEE” i.e , SUNDAY
  4. else display “d MMM, yyyy”
DayDateTimeDate format displayed in the following format.
  1. If timestamp < 24hrs display “hh:mm a”
  2. If timestamp < 48hrs display “Yesterday”
  3. If timestamp < 7days display “EEE” i.e SUNDAY
  4. else display “dd MM yyyy”

TitleView

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import React from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatConversations } from "@cometchat/chat-uikit-react";

// Custom title view component
const customTitleView = (conversation:CometChat.Conversation)=> {
let user = conversation.getConversationType() == "user" ? conversation.getConversationWith() as CometChat.User : undefined;
return <div className="conversations__title-view">
<span className="conversations__title-view-name">{ user ? conversation.getConversationWith().getName() + " • " : conversation.getConversationWith().getName()}</span>
{user ? <span className="conversations__title-view-status">{user.getStatusMessage()}</span> : null}
</div>;
}

<CometChatConversations titleView={customTitleView} />;

SubtitleView

You can customize the subtitle view for each conversation item to meet your requirements.

Shown below is the default chat interface.

Image

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatConversations } from "@cometchat/chat-uikit-react";

const subtitleView = (conversation: CometChat.Conversation) => {
if (conversation.getConversationType() === "user") {
return (
<>
Last Active at:{" "}
{getFormattedTimestamp(
(
conversation.getConversationWith() as CometChat.User
).getLastActiveAt()
)}
</>
);
} else {
return (
<>
Created at:{" "}
{getFormattedTimestamp(
(conversation.getConversationWith() as CometChat.Group).getCreatedAt()
)}
</>
);
}
};

function getFormattedTimestamp(timestamp: number): string {
const date = new Date(timestamp * 1000);
return date.toLocaleString();
}

<CometChatConversations subtitleView={subtitleView} />;

Options

A function that returns a list of actions available when hovering over a conversation item.

Shown below is the default chat interface.

Image

The customized chat interface is displayed below.

Image

Use the following code to achieve the customization shown above.

import {
CometChatOption,
CometChatConversations,
} from "@cometchat/chat-uikit-react";

const getOptions = (conversation: CometChat.Conversation) => {
return [
new CometChatOption({
title: "Delete",
iconURL: deleteIcon,
id: "delete",
onClick: () => {
// Logic here
},
}),
new CometChatOption({
title: "Mute Notification",
id: "mute",
onClick: () => {
// Logic here
},
}),
new CometChatOption({
title: "Mark as Unread",
id: "unread",
onClick: () => {
// Logic here
},
}),
new CometChatOption({
title: "Block",
id: "block",
onClick: () => {
// Logic here
},
}),
];
};

<CometChatConversations options={getOptions} />;
Structure of CometChatOption
NameDescription
idUnique identifier for each option.
titleHeading text for each option.
iconURLSets the asset URL of the icon for each option.
onClickMethod to be invoked when user clicks on each option.