Pre-built UI Components
Abrova Chat ships a two-package architecture — a headless core SDK and an optional UI kit with ChatScreen, ChatInputField, TypingIndicator, PresenceIndicator, UnreadBadge, and more.
AbrovaChat ships a two-package architecture: a headless core SDK for full control, and an optional UI kit with ready-made components.
- Core SDK — Headless SDK for 100% custom UI
- UI Kit — Pre-built components that depend on core
Available Widgets
ChatScreen— Complete drop-in chat UIChatMessageBubble— Single message bubbleChatInputField— Input with emoji & attachmentsTypingIndicator— Animated typing dotsPresenceIndicator— Online / offline status dotUnreadBadge— Unread message count badgeSwipeableMessage— Swipe-to-reply gestureMessageReactionPicker— Emoji reaction selector
Flutter UI Kit#
The abrova_chat_ui package uses InheritedWidget (no Riverpod/Bloc required).
// The abrova_chat_ui package uses InheritedWidget (no Riverpod/Bloc required)
import 'package:abrova_chat/abrova_chat.dart';
import 'package:abrova_chat_ui/abrova_chat_ui.dart';
// Step 1: Wrap your app with AbrovaChatScope
AbrovaChatScope(
config: AbrovaChatConfig(apiKey: 'ab_live_your_api_key', userId: 'user-123'),
child: MaterialApp(...),
)
// Step 2: Use pre-built widgets
// Option A: Full chat screen (drop-in)
ChatScreen(
roomId: 'room-uuid',
currentUserId: 'buyer-2',
)
// Option B: Build custom layout with individual widgets
ChatChannelScope(
roomId: 'room-uuid',
child: Column(
children: [
Expanded(
child: Builder(builder: (context) {
final state = ChatChannelScope.of(context);
return ListView(children: [
for (final m in state.messages)
ChatMessageBubble(message: m, isMe: m.senderUserId == 'buyer-2'),
]);
}),
),
TypingIndicator(roomId: 'room-uuid'),
ChatInputField(roomId: 'room-uuid'),
],
),
)
// Access state via InheritedWidget:
final client = AbrovaChatScope.of(context); // Get AbrovaChatClient
final state = ChatChannelScope.of(context); // Get room state
// Available widgets:
ChatScreen // Complete chat UI
ChatMessageBubble // Single message bubble
ChatInputField // Input with emoji, attachments
TypingIndicator // Animated typing dots
PresenceIndicator // Online/offline dot
UnreadBadge // Unread count badgeiOS UI Kit#
The AbrovaChatUI package uses SwiftUI Environment.
import AbrovaChat
import AbrovaChatUI
// Step 1: Wrap your app with AbrovaChatScope
let config = AbrovaChatConfig(apiKey: "ab_live_your_api_key", userId: "user-123")
AbrovaChatScope(config: config) {
ContentView()
}
// Step 2: Use pre-built views
// Option A: Full chat screen (drop-in)
ChatScreen(roomId: "room-uuid", currentUserId: "buyer-2")
// Option B: Build custom layout with ChatChannelScope
// (@State private var draft = "" in your view)
ChatChannelScope(roomId: "room-uuid", currentUserId: "buyer-2") { state in
VStack {
ScrollView {
ForEach(state.messages, id: \.id) { message in
ChatMessageBubble(message: message, isMe: message.senderUserId == "buyer-2")
}
}
TypingIndicator(typingUsers: state.typingUsers)
ChatInputField(text: $draft, onSend: { text in
Task { await state.sendMessage(content: text) }
})
}
}
// Access client via Environment:
@Environment(\.abrovaChatClient) var client
// Available views:
ChatScreen // Complete chat UI
ChatMessageBubble // Single message bubble
ChatInputField // Input with emoji, attachments
TypingIndicator // Animated typing dots
PresenceIndicator // Online/offline status
UnreadBadge // Unread count badgeAndroid UI Kit#
The abrova-chat-ui package uses Jetpack Compose CompositionLocal.
import ir.abrova.chat.AbrovaChatClient
import ir.abrova.chat.AbrovaChatConfig
import ir.abrova.chat.ui.components.*
import ir.abrova.chat.ui.state.*
// Step 1: Wrap your app with AbrovaChatScope
val config = AbrovaChatConfig(apiKey = "ab_live_your_api_key", userId = "user-123")
AbrovaChatScope(config = config) {
App()
}
// Step 2: Use pre-built composables
// Option A: Full chat screen (drop-in)
ChatScreen(roomId = "room-uuid", currentUserId = "buyer-2")
// Option B: Build custom layout with rememberChatChannelState
val state = rememberChatChannelState(roomId = "room-uuid", currentUserId = "buyer-2")
val scope = rememberCoroutineScope()
Column {
LazyColumn(modifier = Modifier.weight(1f)) {
items(state.messages) { message ->
ChatMessageBubble(message = message, isMe = message.senderUserId == "buyer-2")
}
}
TypingIndicator(typingUsers = state.typingUsers)
ChatInputField(onSendMessage = { text -> scope.launch { state.sendMessage(text) } })
}
// Access client via CompositionLocal:
val client = LocalAbrovaChatClient.current
// Available composables:
ChatScreen // Complete chat UI
ChatMessageBubble // Single message bubble
ChatInputField // Input with emoji, attachments
TypingIndicator // Animated typing dots
PresenceIndicator // Online/offline status
UnreadBadge // Unread count badgeReact Native UI Kit#
The @abrova/react-native-chat-ui package uses React Context.
import { AbrovaChatClient } from '@abrova/react-native-chat';
import { AbrovaChatProvider, ChatScreen } from '@abrova/react-native-chat-ui';
// Step 1: Create client and wrap your app
const client = new AbrovaChatClient({
apiKey: 'ab_live_your_api_key',
userId: 'user-123',
});
<AbrovaChatProvider client={client} autoConnect>
<App />
</AbrovaChatProvider>
// Step 2: Use pre-built components
// Option A: Full chat screen (drop-in)
<ChatScreen roomId="room-uuid" currentUserId="buyer-2" />
// Option B: Build custom layout with the useChatChannel hook
import { useChatChannel, ChatMessageBubble, TypingIndicator, ChatInputField } from '@abrova/react-native-chat-ui';
function CustomChat({ roomId, currentUserId }) {
const { messages, typingUsers, sendMessage } = useChatChannel(roomId, currentUserId);
return (
<View>
{messages.map((m) => (
<ChatMessageBubble key={m.id} message={m} isMe={m.senderUserId === currentUserId} />
))}
<TypingIndicator typingUsers={typingUsers} />
<ChatInputField onSendMessage={(text) => sendMessage(text)} />
</View>
);
}
// Available components:
ChatScreen // Complete chat UI
ChatMessageBubble // Single message bubble
ChatInputField // Input with emoji, attachments
TypingIndicator // Animated typing dots
PresenceIndicator // Online/offline status
UnreadBadge // Unread count badgeWeb UI Kit#
The @abrova/web-chat-ui package uses React Context. It will be published on Abrova Center after the headless @abrova/web-chat package; the example below shows how it will be used.
import { AbrovaChatClient } from '@abrova/web-chat';
import { AbrovaChatProvider, ChatScreen } from '@abrova/web-chat-ui';
// Step 1: Create client and wrap your app
const client = new AbrovaChatClient({
apiKey: 'ab_live_your_api_key',
userId: 'user-123',
});
<AbrovaChatProvider client={client} autoConnect>
<App />
</AbrovaChatProvider>
// Step 2: Use pre-built components
// Option A: Full chat screen (drop-in)
<ChatScreen roomId="room-uuid" currentUserId="buyer-2" />
// Option B: Build custom layout with the useChatChannel hook
import { useChatChannel, ChatMessageBubble, TypingIndicator, ChatInputField } from '@abrova/web-chat-ui';
function CustomChat({ roomId, currentUserId }) {
const { messages, typingUsers, sendMessage } = useChatChannel(roomId, currentUserId);
return (
<div>
{messages.map((m) => (
<ChatMessageBubble key={m.id} message={m} isMe={m.senderUserId === currentUserId} />
))}
<TypingIndicator typingUsers={typingUsers} />
<ChatInputField onSendMessage={(text) => sendMessage(text)} />
</div>
);
}
// Available components:
ChatScreen // Complete chat UI
ChatMessageBubble // Single message bubble
ChatInputField // Input with emoji, attachments
TypingIndicator // Animated typing dots
PresenceIndicator // Online/offline status
UnreadBadge // Unread count badgeNode.js#
Node.js is a server-side SDK — no UI components. Use it for backend operations:
// 1. Room management from your server
const { room } = await abrovaChat.rooms.findOrCreate({
externalId: 'order-456',
participants: [
{ externalUserId: 'seller-1', displayName: 'TechShop' },
{ externalUserId: 'buyer-2', displayName: 'Alice' },
],
});
// 2. Send system messages from your backend
await abrovaChat.messages.send(room.id, {
senderUserId: 'system',
content: 'Order #456 has been shipped!',
type: 'system',
});
// 3. Configure webhooks and push notifications
await abrovaChat.webhooks.setWebhook({
url: 'https://your-server.com/webhooks/abrova-chat',
secret: 'your-hmac-secret',
});
// 4. Generate user tokens for client apps (returned by their tokenProvider)
const { token } = await abrovaChat.users.createToken({
userId: 'user-123',
});
// For UI, use the client SDKs:
// Flutter: abrova_chat + abrova_chat_ui
// Web: @abrova/web-chat + @abrova/web-chat-ui
// React Native: @abrova/react-native-chat + @abrova/react-native-chat-uiREST API#
Use the REST endpoints to build any custom interface.
# Get messages for display
curl "https://chat.abrova.ir/api/v1/rooms/{roomId}/messages?userId={userId}&limit=50" \
-H "X-API-Key: ab_live_your_api_key" -H "X-Server-Secret: $ABROVA_SERVER_SECRET"
# Send a message
curl -X POST "https://chat.abrova.ir/api/v1/rooms/{roomId}/messages" \
-H "X-API-Key: ab_live_your_api_key" -H "X-Server-Secret: $ABROVA_SERVER_SECRET" \
-H "Content-Type: application/json" \
-d '{"senderUserId": "user-123", "content": "Hello!"}'
# For realtime updates, use a client SDK (a WebSocket connection with automatic reconnect):
# 1. Get a user token: POST /api/v1/users/token (server secret required)
# 2. Return it from the client SDK's tokenProvider; the SDK connects and subscribes for you