Skip to main content

Chat Module

Quick Answer

The chat module lives in src/core/chat. It provides conversation lists, one-to-one chat, group chat, messages, reactions, media messages, typing state, and backend hooks.

For Firebase-backed apps, chat uses a mix of Firestore listeners and Firebase callable Functions. That means local UI can render without a custom server, but production chat still needs Firebase Functions deployed and Firestore rules configured.

Source Map

src/core/chat
├── IMChat
├── IMChatScreen
├── IMConversationList
├── IMConversationListView
├── IMConversationView
├── api
├── assets
├── config.ts
└── index.ts

Important exports:

ExportPurpose
IMChatScreenFull chat room screen for one-to-one and group conversations.
IMConversationListViewConversation list UI for the current user.
IMConversationIconViewAvatar/group icon display for conversations.
IMCreateGroupScreenGroup chat creation flow when the group chat flag is enabled.
useChatChannelsHook for the user's conversation list.
useChatMessagesHook for messages in one channel.
useChatSingleChannelHook for a single channel document.
useChatChannelsAndFriendsCombined chat and friend data when social graph is enabled.

Backend Providers

The active chat backend is selected in:

src/core/chat/api/index.ts

Current provider options may include:

ProviderPathUse case
Firebasesrc/core/chat/api/firebaseDefault production path for Firebase apps.
AWSsrc/core/chat/api/awsAWS-backed app variants.
Backendsrc/core/chat/api/backendCustom server implementation.
Localsrc/core/chat/api/localDemo/local data implementation.

Do not mix providers inside one app unless you intentionally migrate the full chat data layer.

Open A Chat Screen

Use the channel object expected by the app navigation flow. A one-to-one channel usually uses a deterministic ID made from the two user IDs.

const firstUserID = currentUser.id
const secondUserID = otherUser.id
const channelID =
firstUserID < secondUserID
? firstUserID + secondUserID
: secondUserID + firstUserID

navigation.navigate('ChatScreen', {
channel: {
id: channelID,
channelID,
participants: [currentUser, otherUser],
},
})

Prefer using the existing app screens and managers to create channels. They already handle group metadata, participant shape, and backend calls.

Firebase Requirements

For Firebase chat, verify:

  • Firebase Auth is enabled.
  • Firestore is enabled.
  • Firebase Functions are deployed for channel and message operations.
  • Firestore rules restrict channel/message reads to participants.
  • Composite indexes exist for the queries used by conversation and message lists.
  • Push notifications are configured if the app sends message notifications.
  • Storage or media upload Functions are configured if chat supports media messages.

The Firebase chat client intentionally returns empty arrays on listener errors to avoid infinite loading. If a conversation list is blank, check logs and Firebase rules before changing UI state.

Media Messages

Media messages usually flow through:

src/core/camera
src/core/media
src/core/chat

A chat screen should handle these failure states separately:

  • permission denied;
  • image/video picker canceled;
  • upload failed;
  • message insert failed after upload;
  • channel listener permission denied.

Switching To A Custom Backend

To replace Firebase chat with your own backend:

  1. Keep the UI exports from src/core/chat.
  2. Implement the same hook contracts in src/core/chat/api/backend.
  3. Switch exports in src/core/chat/api/index.ts.
  4. Make sure the new backend supports list channels, subscribe/fetch messages, create channel, send message, reactions, group updates, and delete/leave behavior.
  5. Re-test one-to-one chat, group chat, media messages, and blocked-user filtering.

Verification Checklist

Test:

  • empty conversation list resolves without infinite loading;
  • existing conversations load;
  • one-to-one chat opens;
  • group chat opens if enabled;
  • text message sends;
  • media message sends if enabled;
  • message list updates in real time;
  • unread/read state updates;
  • blocked users are filtered;
  • Firebase permission errors are visible in logs and do not leave a permanent spinner.

Troubleshooting

ProblemFix
Conversation screen loads foreverConfirm listener errors call the empty-state callback, then check Firestore rules and current user ID.
Messages do not sendDeploy Firebase Functions and check callable Function region/config.
User can read another user's chatTighten Firestore rules and validate channel participants.
Media messages failCheck src/core/media, Firebase Storage/Functions, and Blaze plan requirements for uploads.
Group chat crashesConfirm social graph/friends data is present and the group chat flag did not remove required screens.