Introduction
Installation
Wrapper
As an initial step, encapsulate your application within the CommtProvider. This step is crucial for integrating your application with the capabilities provided by the Commt plugin. The CommtProvider sets up a context and provides certain functionalities to be used within your App. This integration enables your application to seamlessly communicate with and benefit from the Commt plugin.
import CommtProvider from "@commt/rn-sdk";
const App = () => {
return(...);
}
export default CommtProvider(App);or
import CommtProvider from "@commt/rn-sdk";
const App = () => {
return(
<CommtProvider>
{...}
</CommtProvider>
);
};
export default App;Hooks
To ensure smooth transfer of client information to the package, it is essential to integrate hooks into your application prior to utilizing the UI components. By incorporating these hooks into your codebase, you can establish a connection between the client information and the package, allowing for seamless data transfer. This integration step is crucial for the proper functioning of the UI components and ensuring that your application effectively utilizes the available resources.
useInitiate
This hook adds the necessary configurations to the Commt package and verifies client information.
Usage:
import CommtProvider from "@commt/rn-sdk";
import { useInitiate } from "@commt/rn-sdk/hooks";
const ClientConfig = {
apiKey: "123456789?",
projectId: "0987654321?",
};
function App(): JSX.Element {
useInitiate(ClientConfig); // Initiate a client
return (
<CommtProvider>
{/* All your ThemeProvider, NavigationContainer, etc. */}
</CommtProvider>
);
}Client Props (required parameter) Type Definition:
interface ClientProps {
apiKey: 'string';
projectId: 'string';
}{
"apiKey": "123456789?",
"projectId": "0987654321?",
}Note: You can access both values through the dashboard!
useSetSelfUser
To ensure that the Commt package is aware of the active user logged into your application, it must be defined for the active user information using the useSetSelfUser hook.
Usage:
import { useSetSelfUser } from "@commt/rn-sdk/hooks";
const Login = () => {
const setSelfUser = useSetSelfUser();
useEffect(() => {
if (activeUser) {
setSelfUser(activeUser);
}
}, [activeUser]);
return (...);
};Props Definition:
- activeUser: Logged user in app, required, for expected user type.
useSetUsers
The useSetUsers hook is designed to manage and update the user list in the plugin's state for rendering purposes within pre-built components. It utilizes the provided user list along with specific user properties defined in UserProps. Additionally, it fetches and updates user online status/indicator from Commt services by using the chatAuthId field of the user.
Usage:
import { useSetUsers } from "@commt/rn-sdk/hooks";
const Home = () => {
const setUsers = useSetUsers();
useEffect(async () => {
if (users.length > 0) {
await setUsers(users);
}
}, [users]);
return (...);
};Props Definition:
The useSetUsers hook doesn't take any explicit parameters. However, it relies on the users array, where each element conforms to the UserProps structure, containing user details required for rendering and identification.
useSetRooms
The useSetRooms hook is designed to manage and update the room list in the plugin's state for rendering purposes within pre-built components. It utilizes the provided room list along with specific room properties defined in RoomProps. Additionally, it fetches and updates rooms' last-message-read-token from Commt services by using the chatRoomAuthId field of rooms. This ensures that the message read indicator works properly.
Usage:
import { useSetRooms } from "@commt/rn-sdk/hooks";
const Home = () => {
const setRooms = useSetRooms();
useEffect(async () => {
if (rooms.length > 0) {
await setRooms(rooms);
}
}, [rooms]);
return (...);
};Props Definition:
The useSetRooms hook doesn't take any explicit parameters. However, it relies on the rooms array, where each element conforms to the RoomProps structure, containing room details required for rendering and identification.
useSetMessages
The useSetMessages hook is designed to manage and update the message list in the plugin's state for rendering purposes within pre-built components. It utilizes the provided message list along with specific message properties defined in MessageProps. It also configures messages by rooms.
Usage:
import { useSetMessages } from "@commt/rn-sdk/hooks";
const Home = () => {
const setMessages = useSetMessages();
useEffect(() => {
if (messages.length > 0) {
setMessages(messages);
}
}, [messages]);
return (...);
};Props Definition:
The setMessages function requires a message list as a parameter. It's crucial that each element in this list follows the structure outlined in MessageProps, which contains detailed information for each message.
Note: It is recommended to limit the message array to 10 messages per room when uploading the first set of messages.
useToggleTheme
The useToggleTheme hook is designed to facilitate the customization of UI component colors in the Commt package. When the useToggleTheme hook is invoked, it returns a function named toggleThemeAction. The function takes color values as parameters, constructs a theme object by mapping these colors to specific UI components, and then dispatches an action to update the package's theme based on the provided color styles.
Usage:
import { useToggleTheme } from "@commt/rn-sdk/hooks";
const toggleThemeProps = {
passive: "#8D9293",
bubble: "#A91A24",
bcg: "#1A1D1E",
searchText: "#FFF",
read1: "#1B9C32",
read2: "#E57A81",
app1: "#F8FAFA",
app2: "#D9DBDB",
app3: "#272C2D",
app4: "#3FC610",
app5: "#1A1D1E",
app6: "#FBE9EA",
app7: "#DC4D57",
app8: "#E57A81",
ui1: "#FFF",
ui2: "#272C2D",
};
const Home = () => {
const toggleThemeAction = useToggleTheme();
const handleToggleTheme = () => {
// update @commt/rn-sdk package theme colors
toggleThemeAction(toggleThemeProps);
};
return <Button onPress={handleToggleTheme} title="Update colors" />;
};Props Definition:
The toggleThemeAction function receives an object as its parameter. Each property within this object represents a color code for a specific UI component within the package.
Toggle Theme Props
| Prop Name | Required | Type | Affected UI Components Parts |
|---|---|---|---|
| passive | Yes | String | "QuickChat" title, passive username, online text, etc. |
| bubble | Yes | String | Self user bubble background color |
| bcg | Yes | String | App background color |
| ... | ... | ... | ... |
Note: Refer to the full table in the original documentation for detailed descriptions of each property.
Components
Messages Header
The message header is a user interface (UI) component that you can use on any screen within your application. It serves as a header and is labeled with the title 'Messages'.
Appearance
Usage
import { MessagesHeader } from "@commt/rn-sdk/components";
const MessagesScreen = () => {
return (
<>
<MessagesHeader popUpButtons={customButtons} />
</>
);
};Props Definition
Message Header utilizes the popUpButtons property, providing a mechanism for developers to define a personalized set of buttons. This customization empowers developers to tailor the buttons within the Message Header according to their specific requirements.
popUpButtons
Not required prop. Array of ButtonItem object.
Interface Definition
interface ButtonItem {
icon?: React.JSX.Element;
title: string;
onPress: () => void;
}Example Custom Buttons
const customButtons = [
{
icon: <CustomIcon />,
title: "Extension",
onPress: () => {
console.log("Extension Press");
},
},
];Search Input
The SearchInput component is a user interface (UI) element specifically created for searching within the Message List. It is meant to be used together with the Message List component to provide a seamless search experience for users. By incorporating the SearchInput component into your application, users can easily search for specific messages within the Message List, improving the overall usability and functionality of your messaging system.
Appearance
Usage
import { SearchInput } from "@commt/rn-sdk/components";
const MessagesScreen = () => {
return (
<>
<SearchInput />
</>
);
};Quick Chat
The Quick Chat component is a user interface (UI) element that shows a list of users. When a user is clicked, it redirects to the chat screen within the application.
Appearance
Usage
import { QuickChat } from "@commt/rn-sdk/components";
const MessagesScreen = () => {
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
return (
<>
<QuickChat onPress={navigateToChat} />
</>
);
};Props Definition
The onPress prop in the Quick Chat component is used to define the callback function that will be executed when a user clicks on a specific user in the list. This prop is typically named navigateToChat and is responsible for navigating the user to the Chat Screen that contains chat components and a messaging interface.
The purpose of the navigateToChat function is to handle the logic for redirecting the user to the chat screen, where they can engage in a conversation with the selected user. This function can utilize navigation libraries or frameworks to navigate to the desired(Chat) screen within the app.
Required prop.
roomId: represents the unique identifier of a messaging room.
participants: is an array that contains the IDs of the users who belong to the messaging room.
Interface Definition
interface NavigateProps {
roomId?: 'string';
participants?: 'Array<string>';
}Example Implementation
const navigateToChat = ({
roomId,
participants,
}) => {
navigation.navigate("Chats", { roomId, participants });
};Message List
The Message List component is a UI component that displays a list of messaging rooms and their last messages. It serves as a convenient way for users to access and switch between different conversations within your application. When a user clicks on a specific room, it triggers a redirection to the chat screen(in your app), which contains the necessary chat components for engaging in a conversation with the selected room.
Appearance
Usage
import { MessageList } from "@commt/rn-sdk/components";
const MessagesScreen = () => {
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
const navigateToChat = ({
roomId,
participants,
}: {
roomId?: string;
participants?: Array<string>;
}) => {
navigation.navigate("Chats", { roomId, participants });
};
return (
<>
<MessageList onPress={navigateToChat} />
</>
);
};Props Definition
The onPress prop in the Message List component is used to define the callback function that will be executed when a user clicks on a specific room in the list. Detailed description is in Quick Chat prop definition.
Chat Header
The chat header is an essential UI component that provides important information about the chat participants. In one-to-one messaging rooms, it shows the avatar of the opposite user, their online status, writing status, and name. For group messaging rooms, it displays the group avatar, group name, and the names of the group members. This allows users to quickly identify who they are chatting with and provides a visual representation of the participants.
Appearance
Usage
import { ChatHeader } from "@commt/rn-sdk/components";
const Chats = () => {
const route = useRoute<RouteProp<RootStackParamList, "Chats">>();
const roomId = route.params.roomId;
const participants = route.params.participants;
return (
<>
<ChatHeader
roomId={roomId}
participants={participants}
popUpButtons={customButtons}
onUserProfileClick={YOUR_CALLBACK_FUNCTION}
leftComponent={YOUR_CUSTOM_COMPONENT}
/>
</>
);
};Props Definition
The chat header component receives five props: roomId, participants, onUserProfileClick, leftComponent and popUpButtons. roomId and participants are passed from the Message list and Quick Chat components to the chat screen that you will be creating. In the chat screen, these props can be accessed and utilized using the useRoute hook. The useRoute hook provides access to the route object, which contains information about the current route, including any parameters or props that were passed to it. By using the useRoute hook, you can easily access the roomId, participants props within the chat screen component and customize the UI accordingly.
-
roomId: represents the unique identifier of a messaging room.
-
participants: is an array that contains the IDs of the users who belong to the messaging room.
-
onUserProfileClick (not required): defines a callback function that is invoked when the user clicks on the avatar or username in header. It provides a way to offer additional functionality or navigation options when the user engages with the user profile elements.
-
leftComponent (not required): is used for customization on the left side of the chat header component. It is commonly utilized for elements such as a back button or any other custom component intended for the left section of the header.
-
popUpButtons (not required): The popUpButtons prop of the Message Header component and the popUpButtons prop of the Chat Header component have the same properties. These properties define the buttons that are displayed in the header's popup menu.
PopUpButtons Example Definition
const customButtons = [
{
icon: <EmojiIcon />,
title: "Document",
onPress: () => {
console.log(" Document Press");
},
},
{
title: "Bookmarks",
onPress: () => {
alert(" Bookmarks Press");
},
},
];PopUpButtons Appearance
Chat
The chat component is a UI component that displays message bubbles within a specific messaging room. It also includes an input bar at the bottom for sending messages.
Appearance
Usage
import { Chat } from "@commt/rn-sdk/components";
const Chats = () => {
const route = useRoute<RouteProp<RootStackParamList, "Chats">>();
const roomId = route.params.roomId;
const participants = route.params.participants;
return (
<>
<Chat
roomId={roomId}
participants={participants}
loadMoreMessages={loadMoreMessages}
/>
</>
);
};Props Definition
The chat component requires three props: room ID, participants and loadMoreMessages. To access the room ID and participants values from the Message list and Quick Chat components, you can redirect them to the chat screen you have created. The useRoute hook can be used to extract these values from the route params object. By passing these props to the chat component, you will be able to customize the chat UI according to your preferences for the specific messaging room.
-
roomId: represents the unique identifier of a messaging room.
-
participants: is an array that contains the IDs of the users who belong to the messaging room.
-
loadMoreMessages: The loadMoreMessages prop is a feature used to fetch previous messages from the database when the user scrolls the chat screen. To implement this functionality, you need to create a function that takes the roomId, skip, and limit values as parameters. This function will then retrieve the messages belonging to that room based on the provided limit value.
Function Parameter:
- roomId (required): A string representing the ID of the chat room.
- skip (required): A number representing the number of messages to skip.
- limit (required): A number representing the maximum number of messages to retrieve.
Function Return Parameter:
- messages (required): This represents the list of messages that are fetched from the server. The type of this list should be an array of Message Props.
- hasNext (optional): A boolean indicating whether there are more messages to load.
Room Card
The Room Card component is a UI element crafted using the room properties specified in RoomProps for a particular room. It presents the text of the room's last message, read and time information, and also indicates the number of unread messages from the opposite user. In one-to-one messaging, it displays the avatar, name, online status, and writing status of the opposite user. For group rooms, it shows the group avatar, name and the names of users who are currently writing, along with their writing status.
Appearance
Usage
import { RoomCard } from "@commt/rn-sdk/components";
const MessagesScreen = () => {
return (
<RoomCard
room={roomItem}
onClickAction={() => {...}}
/>
);
};Props Definition
The room card component receives two props: room and onClickAction. By passing the room prop, the room card component obtains the necessary data to display information about the room, and the onClickAction prop defines the behavior when the room card is clicked.
-
room: This is an object that has the properties specified in RoomProps.
-
onClickAction: This prop specifies the action to be performed when the room card component is clicked. This action could involve navigating to the specific screen, opening a chat window, or any other desired behavior.
Data Types
User Data Type
Generic user props:
| Prop name | Required | Type | Description |
|---|---|---|---|
| _id | Yes | String | User Id |
| chatAuthId | Yes | String | User's chat auth Id (required to match user in Commt system) |
| username | Yes | String | User name (will be display in the components) |
| avatar | Yes | String | User avatar uri/source (will be display in the components) |
Note: The 'id' and 'chatAuthId' properties must be prefixed with the keyword 'system' when defining them for system users. This naming convention helps to clearly distinguish system users from regular users and ensures consistency in the codebase.
Room Data Type
Generic room props:
| Prop name | Required | Type | Description |
|---|---|---|---|
| participants | Yes | String[_id] | User Ids in the particular room |
| roomId | Yes | String | Unique room id field |
| chatRoomAuthId | Yes | String | Room's chat auth Id (required to match room in Commt system) |
| groupName | No | String | If the room is a community room the name of the group/community |
| groupAvatar | No | String | If the room is a community room the avatar of the group/community |
Note: For system users, the "system_" prefix must to be added to the beginning of the ID when defining room participant IDs.
Message Data Type
Generic message props:
| Prop name | Required | Type | Description |
|---|---|---|---|
| _id | Yes | String | Message Id |
| text | Yes | String | Message content |
| createdAt | Yes | Date | Message sent time |
| type | Yes | String | Message type such as "text" | "button" | "image" (default text) |
| roomId | Yes | String | Room id where the message was sent |
| user | Yes | String | Message sender id |
| system | No | Boolean | Whether the message is a system message or not (default false) |
| image | No | String | Image uri for system messages, if the system message is true and type field is image, system message will rendered image. |
| onPress | No | void | Press action for button system message, if the system message is true and type field is button then the button will be rendered with text and onPress action. |
Playground
How to Use the @commt/rn-sdk to Create a Chat Application in React Native
Example application: commt-rn-playground
In this article, we will explore how to utilize the @commt/rn-sdk package to develop a chat application in React Native. The @commt/rn-sdk package provides a messaging list and messaging interface, making it ideal for building chat functionality into your app. We will walk through the installation process, as well as the various hooks and components provided by the package. By the end of this guide, you will have a solid understanding of how to integrate the @commt/rn-sdk package into your own application.
Installation
To begin, let's install the @commt/rn-sdk package into our application. You can add it by following the installation step.
Once the package is installed, we can move on to utilizing its various hooks and components.
Wrapper and Initiate Hook
Before using the @commt/rn-sdk components we must wrap our application with the provider of the package. In the App component, use the useInitiate hook of @commt/rn-sdk to set client information and configurations.
import CommtProvider from "@commt/rn-sdk";
import { useInitiate } from "@commt/rn-sdk/hooks";
const ClientConfig = {
apiKey: "123456789?",
projectId: "0987654321?",
secretKey: "123456789018A_7JzPo?23F+4y#erPL"
};
function App(): JSX.Element {
useInitiate(ClientConfig); // Initiate a client
return (
<CommtProvider>
{/* All your ThemeProvider, NavigationContainer, etc. */}
</CommtProvider>
);
}App (commt-rn-playground) Hooks
There are four hooks in the sample application. These hooks are created using React Query (opens in a new tab) and serve the purpose of fetching data from the database or saving it. Let's take a look at the available hooks:
- useGetRooms: This hook retrieves the list of chat rooms from the database.
- useGetMessages: This hook retrieves the messages from the database.
- useGetUsers: This hook retrieves the list of users from the database.
- useSaveUser: This hook is responsible for saving the active user's information to the database.
Application Screens
Our sample application consists of four screens: Login, Home, Chats and Messages. Each screen serves a specific purpose and utilizes the @commt/rn-sdk package to provide a customized user interface for chat functionality.
Login Screen
On the Login screen, users enter their credentials and log in to the application. Once the user's information is validated, we can save it to the database using the useSaveUser hook. This hook also ensures that by passing the user's data to the useSetSelfUser hook of @commt/rn-sdk, we are notifying the package about the active user.
Detail of the app's useSaveUser hook:
import { useSetSelfUser } from "@commt/rn-sdk/hooks";
{...}
export default function useSaveUser() {
{...}
const queryClient = useQueryClient();
return useMutation({
mutationFn: saveUser,
onSuccess: (user) => {
{...}
//pass active user to package
setSelfUser(user);
},
});
}Home Screen
The Home screen fetches the necessary data using the useGetRooms, useGetMessages and useGetUsers app hooks. These hooks retrieve the chat rooms, messages and user information from the database respectively. Once the data is fetched, we can set it using the useSetRooms, useSetUsers and useSetMessages hooks provided by the @commt/rn-sdk package. It is important to note that the data transmitted to the commt hooks must match MessageProps, RoomProps and UserProps. If the data does not align, we need to format it accordingly before setting it.
import {
useSetUsers,
useSetRooms,
useSetMessages
} from "@commt/rn-sdk/hooks"
{...}
const Home = () => {
{...}
// get our data from backend service using app's hook
const { data: users, isSuccess: isUsersSuccess } = useGetUsers();
const { data: rooms, isSuccess: isRoomsSuccess } = useGetRooms();
const { data: messages, isSuccess: isMessagesSuccess } = useGetMessages();
// @commt/rn-sdk hooks
const setUsers = useSetUsers();
const setRooms = useSetRooms();
const setMessages = useSetMessages();
async function setContextData() {
// Format data in accordance with @commt/rn-sdk data structure
const formattedMessages = messages?.map((message: MessageProps) => ({
_id: message._id,
text: message.message,
createdAt: message.createdAt,
type: message.type,
roomId: message.roomId,
user: message.senderId,
}));
const formattedRooms = rooms?.map((room: RoomProps) => {
return {
participants: room.participants,
roomId: room.roomId,
// Match between Commt db and yours
chatRoomAuthId: room.chatRoomAuthId,
unReadMessageCount: 0,
...(room.communityName && { groupName: room.communityName }),
...(room.communityAvatar && { groupAvatar: room.communityAvatar }),
};
});
// Pass the received data from the app's hooks to the package
await setUsers(users);
await setRooms(formattedRooms);
setMessages(formattedMessages);
}
useEffect(() => {
if (isUsersSuccess && isRoomsSuccess && isMessagesSuccess) {
setContextData();
}
}, [isUsersSuccess, isRoomsSuccess, isMessagesSuccess])
return({...})
};Messages Screen
On the Messages screen, we use several UI components provided by the @commt/rn-sdk package to display the list of rooms and users. Components such as MessagesHeader, SearchInput, QuickChat and MessageList help us to create a user-friendly interface for messaging. These components can be easily integrated into your own application by following the examples provided.
In the Messages screen, we define a navigateToChat function that is passed as a prop to the QuickChat and MessageList components. This function allows us to navigate to the Chats screen with the necessary parameters when a user or chat room is clicked.
import {
QuickChat,
MessageList,
SearchInput,
MessagesHeader
} from "@commt/rn-sdk/components";
{...}
const Messages = () => {
{...}
const navigateToChat = ({
roomId,
participants,
}: {
roomId?: string;
participants?: Array<string>;
}) => {
navigation.navigate("Chats", { roomId, participants });
};
return (
<Container>
<MessagesHeader popUpButtons={customButtons}/>
<SearchInput />
<InnerContainer>
<QuickChat onPress={navigateToChat} />
<MessageList onPress={navigateToChat} />
</InnerContainer>
</Container>
);
};Additionally, we can customize the MessagesHeader component by adding a custom button to enhance the user experience. An example of a custom button is shown below.
const customButtons = [
{
icon: <EmojiIcon />,
title: "Extensions",
onPress: () => {
console.log(" Extensions Press");
},
},
]Chats Screen
The Chats screen uses the ChatHeader and Chat components of the @commt/rn-sdk package to create the user interface for active messaging rooms. When switching from the Messages screen to the Chats screen, we pass the roomId and participant information to the ChatHeader and Chat components using the navigateToChat callback function. This ensures a seamless transition between screens.
import { ChatHeader, Chat } from "@commt/rn-sdk/components";
const Chats = () => {
const route = useRoute<RouteProp<RootStackParamList, "Chats">>();
const roomId = route.params.roomId;
const participants = route.params.participants;
return (
<Container>
<ChatHeader roomId={roomId} participants={participants} />
<Chat
roomId={roomId}
participants={participants}
loadMoreMessages={loadMoreMessages}
/>
</Container>
);
};loadMoreMessages Function in Our App
The loadMoreMessages function in our example application is defined in the service folder. This function is responsible for retrieving additional messages from the database for a given chat room, subject to a certain limit. Any message object returned by this function must conform to the structure defined by the MessageProps type. If your messages do not conform to this structure, you will need to format them accordingly. We also use the hasNext property to indicate whether there are more messages in the database that belong to the specified room to make request.
{...}
export const loadMoreMessages = async (props) => {
const { roomId, skip, limit } = props;
try {
const response = await axios.get(chat, {
params: {
roomId,
skip,
limit,
},
});
const formattedMessages = response.data.messages?.map(
(message: MessageProps) => ({
id: message._id,
text: message.message,
createdAt: message.createdAt,
type: message.type,
roomId: message.roomId,
user: message.senderId,
}),
);
return { messages: formattedMessages, hasNext: response.data.hasNext };
}
{...}
};Conclusion
In this article, we have explored how to use the @commt/rn-sdk package by creating a chat application in React Native. We covered the installation process, available hooks and the screens that make up our sample application. By following the steps outlined in this guide, you can easily integrate the @commt/rn-sdk package into your own application and customize it to meet your specific requirements. Happy coding!