I worked on a project called EmbeddedChat which is an in-app chat solution that utilizes the RocketChat chat engine through its REST and real-time APIs to support powerful chat features like reactions, online presence, typing status, threads, and much more.
I would maintain this repository as the final report summary of my GSoC 2023 project and a quick guide for all future GSoC aspirants.
The goal of the project is to make a ready-to-use chat solution that could be integrated into any website, web app, or app. This project was a major refactoring and enhancement for the EmbeddedChat 2022 project.
- Improve authentication - support all OAuth services
- Move to a mono repo - auth, api, react, react-native, HTML embed
- HTML embed feature
- Theming
- Improving API
- Support for slash commands
- Migrating from the fuselage to our own minimal components
EmbeddedChat integrated into my esportsweb.in website.
EmbeddedChat's new mono repo structure
- auth - The auth package includes functions to easily log into a Rocket chat server. Though it is used by embeddedchat's react and react-native client, developers can use this package for their own use cases.
- api - The api package includes functions that are all required to create a chat application using the Rocketchat server. It has functions like connect, login, sendMesage, pinMessage, starMessage, deleteMessage, triggerBlockAction, etc. to perform various operations. One can listen to new/updated message events by attaching event listeners using
addMessageListener
. There are other event listeners which could be added usingaddMessageDeleteListener
,addTypingStatusListener
,addActionTriggeredListener
,addUiInteractionListener
. - react - The react package includes the react components to integrate EmbeddedChat.
- react-native - The react-native project aims at using EmbeddedChat in react native mobile apps.
- htmembed - With this project EmbeddedChat could be integrated into any web app by simply embedding an HTML snippet.
Simple integrate embedded chat by pasting html snippet into your website
<div id="embeddedchat"></div>
<script src="http://127.0.0.1:4001/embeddedchat.js"></script>
<script>
// all props for the EmbeddedChat of @embeddedchat/react will go here
// The config will be directly applied as props for the EmbeddedChat Component
const config = {
host: 'http://localhost:3000',
roomId: 'GENERAL',
isClosable: true,
setClosableState: true,
moreOpts: true,
channelName: 'general',
anonymousMode: true,
headerColor: 'white',
toastBarPosition: 'bottom-end',
showRoles: true,
showAvatar: false,
enableThreads: true,
auth: {
flow: 'MANAGED',
},
}
EmbeddedChat.renderInElementWithId(config, 'embeddedchat')
</script>
We can customize EmbeddedChat by passing a custom theme object. Hence, it could take the look and feel of the app or website. We can also customize components by custom stylesheet or passing custom class names through the theme object.
Our api
package exposes the EmbeddedChatApi
class. It comes with a bunch of APIs that could be used to login, send, pin, edit, star or delete message, attach listeners for realtime events. It has the following structure:
class EmbeddedChatApi {
host: string;
rid: string;
rcClient: Rocketchat;
onMessageCallbacks: ((message: any) => void)[];
onMessageDeleteCallbacks: ((messageId: string) => void)[];
onTypingStatusCallbacks: ((users: string[]) => void)[];
onActionTriggeredCallbacks: ((data: any) => void)[];
onUiInteractionCallbacks: ((data: any) => void)[];
typingUsers: string[];
auth: RocketChatAuth;
constructor(host: string, rid: string, { getToken, saveToken, deleteToken, autoLogin }: IRocketChatAuthOptions);
setAuth(auth: RocketChatAuth): void;
getAuth(): RocketChatAuth;
getHost(): string;
googleSSOLogin(signIn: Function, acsCode: string): Promise<any>;
login(userOrEmail: string, password: string, code: string): Promise<{
status: string;
me: any;
} | undefined>;
logout(): Promise<void>;
connect(): Promise<void>;
addMessageListener(callback: (message: any) => void): Promise<void>;
removeMessageListener(callback: (message: any) => void): Promise<void>;
addMessageDeleteListener(callback: (messageId: string) => void): Promise<void>;
removeMessageDeleteListener(callback: (messageId: string) => void): Promise<void>;
addTypingStatusListener(callback: (users: string[]) => void): Promise<void>;
removeTypingStatusListener(callback: (users: string[]) => void): Promise<void>;
addActionTriggeredListener(callback: (data: any) => void): Promise<void>;
removeActionTriggeredListener(callback: (data: any) => void): Promise<void>;
addUiInteractionListener(callback: (data: any) => void): Promise<void>;
removeUiInteractionListener(callback: (data: any) => void): Promise<void>;
handleTypingEvent({ typingUser, isTyping }: {
typingUser: string;
isTyping: boolean;
}): void;
updateUserNameThroughSuggestion(userid: string): Promise<any>;
updateUserUsername(userid: string, username: string): Promise<any>;
channelInfo(): Promise<any>;
close(): Promise<void>;
getMessages(anonymousMode?: boolean, options?: {
query?: object | undefined;
field?: object | undefined;
}): Promise<any>;
getThreadMessages(tmid: string): Promise<any>;
getChannelRoles(): Promise<any>;
sendTypingStatus(username: string, typing: boolean): Promise<void>;
sendMessage(message: any, threadId: string): Promise<any>;
deleteMessage(msgId: string): Promise<any>;
updateMessage(msgId: string, text: string): Promise<any>;
starMessage(mid: string): Promise<any>;
unstarMessage(mid: string): Promise<any>;
getStarredMessages(): Promise<any>;
getPinnedMessages(): Promise<any>;
pinMessage(mid: string): Promise<any>;
unpinMessage(mid: string): Promise<any>;
reactToMessage(emoji: string, messageId: string, shouldReact: string): Promise<any>;
reportMessage(messageId: string, description: string): Promise<any>;
findOrCreateInvite(): Promise<any>;
sendAttachment(file: File, fileName: string, fileDescription?: string, threadId?: undefined): Promise<any>;
me(): Promise<any>;
getChannelMembers(): Promise<any>;
getSearchMessages(text: string): Promise<any>;
triggerBlockAction({ type, actionId, appId, rid, mid, viewId, container, ...rest }: any): Promise<any>;
getCommandsList(): Promise<any>;
execCommand({ command, params }: {
command: string;
params: string;
}): Promise<any>;
}
Demo playgroud for api package
We have worked on supporting slash commands along with any UI interactions they perform.
slashcommands.mp4
We now support token-based authentication for EmbeddedChat. An app can pass the access token of the services that are configured in RocketChat to EmbeddedChat. It would be useful when the app does not want to show any additional login UI for EmbeddedChat.
simplescreenrecorder-2023-09-25_11.26.34.mp4
PR ID | Title with Link |
---|---|
217 | [IMPROVE] Project-restructure Link |
218 | React bootstrap Link |
222 | Theming Foundation Set up Link |
223 | [NEW] Button replacement for fuselage Link |
224 | UI refactoring/box Link |
226 | Improve/auth + ActionButton/Icon/Input Component Link |
227 | New/added apis Link |
228 | New/slash commands+UI kit+theming Link |
229 | New/html embed Link |
230 | New/message component+avatar Link |
232 | React Native Project Link |
233 | Fix/new icon components Link |
Besides EmbeddedChat I also contributed to other RocketChat Projects GSoC Community Hub, RC4Community, RC4Conferences.
A big big thank you to my mentor for the guidance and support before and throughout GSoC. π I learned beyond GSoC from him and am forever grateful to be mentored by him.
-
Read my EmbeddedChat project proposal that got me accepted to GSoC here.
-
My GSoC Presentation can be found here.
-
Watch the above presentation in video - here !
Learned something new today? Reciprocate the love. β this repo for good karma.
Want to discuss about GSoC / Rocket.Chat / Open-source ? Let's connect!
Student | Abhinav Kumar |
---|---|
Organization | Rocket.Chat |
Project | EmbeddedChat 2023 |
GitHub | @abhinavkrin |
abhinavkrin | |
abhinavkr_in | |
Website | avitechlab.com |
abhinav@avitechlab.com | |
Rocket.Chat | abhinav.kumar30 |