baxcloud_chat_uikit_sdk 0.1.0
baxcloud_chat_uikit_sdk: ^0.1.0 copied to clipboard
BaxCloud Chat UI Kit — realtime messaging with ready-made layouts (standard, compact, live overlay) and bring-your-own design hooks.
BaxCloud Chat UI Kit #
Flutter UI kit for room-based realtime chat — team chat, live stream comments, compact embeds, and bring-your-own design.
Package: baxcloud_chat_uikit_sdk
Requires: baxcloud_core · Flutter 3.10+
Features #
- Drop-in chat via
BaxChatView— joins a BaxCloud room and renders messaging UI - Ready-made modes: standard (full chat screen), compact (side panel), liveOverlay (stream comments)
- Deep theming: colors, radii, fonts, spacing, edge fade (messages dissolve at top/bottom)
- Join / leave presence lines — toggle on/off +
{name}templates or builders (i18n) - Typing indicators — off by default; opt in with
enableTypingIndicators+ BYOtypingBuilder - Hide input (
showInput: false) and send viaBaxChatController BaxChatsbootstrap +BaxChatControllerfor programmatic send / reactions- Persist messages yourself:
onMessage+initialMessages/seedMessages(BaxCloud does not store history) - BYO design:
messageBuilder,inputBuilder,typingBuilder,inChatBuilder - HTTP send via BaxCloud API + LiveKit data receive (server broadcast)
- Shared
BaxcloudUseridentity model (same as Calls / Meet / Live kits) - Automatic SDK telemetry on join (via
baxcloud_core)
Documentation #
| Resource | Link |
|---|---|
| Chat UI Kit guide (modes, customization, i18n) | baxcloud.tech/docs/uikits/chat |
| UI Kits overview | baxcloud.tech/docs/uikits |
| API authentication | baxcloud.tech/docs/api/authentication |
| Dashboard | baxcloud.tech/dashboard |
Installation #
dependencies:
baxcloud_core: ^0.1.5
baxcloud_chat_uikit_sdk: ^0.1.0
flutter pub get
Use a client key (bax_pk_…) with messaging scopes from the dashboard.
Rooms: Chat always requires a
roomName. Pre-create the room via REST or enable auto-create rooms on the project so the first join creates it.
No chat history: BaxCloud delivers messages in realtime only. It does not store chat history. If you need messages later, save them in your own database (see Message persistence).
Quick start #
import 'package:baxcloud_core/baxcloud_core.dart';
import 'package:baxcloud_chat_uikit_sdk/baxcloud_chat_uikit_sdk.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await BaxChats.initialize(
config: BaxConfig(
projectId: 'your-project-id',
apiKey: 'bax_pk_your_client_key',
),
localUser: const BaxcloudUser(
userId: 'u1',
name: 'Ada',
avatarUrl: 'https://example.com/ada.png',
metadata: {'role': 'member', 'locale': 'en'},
),
);
runApp(const MyApp());
}
class ChatScreen extends StatelessWidget {
const ChatScreen({super.key});
@override
Widget build(BuildContext context) {
return BaxChatScope(
config: BaxConfig(
projectId: 'your-project-id',
apiKey: 'bax_pk_your_client_key',
),
child: BaxChatView(
roomName: 'support-lobby',
// user: optional — falls back to BaxChats.initialize localUser
uiConfig: BaxChatUiConfig.standard(),
),
);
}
}
Update local user #
await BaxChats.updateLocalUser(
BaxcloudUser(
userId: 'u1',
name: 'Ada Lovelace',
metadata: {'locale': 'pt-BR'},
),
);
Hide input (controller-only send) #
BaxChatView(
roomName: 'support-lobby',
uiConfig: BaxChatUiConfig.standard(showInput: false),
);
// From your chrome / toolbar:
await BaxChats.instance.activeController?.sendText('Hello from my UI');
Ready-made UI modes #
Start from a preset and pass overrides as named args (no copyWith required):
| Preset | Use case |
|---|---|
BaxChatUiConfig.standard(...) |
Full chat screen — header, bubbles, input |
BaxChatUiConfig.compact(...) |
Side panel / embedded widget |
BaxChatUiConfig.liveOverlay(...) |
Live stream comments over video |
Full chat screen #
BaxChatView(
roomName: 'team-general',
user: me,
uiConfig: BaxChatUiConfig.standard(
showTimestamps: true,
bubbleBorderRadius: 18,
localBubbleColor: const Color(0xFF2563EB),
),
);
Live streaming comments #
Overlay the kit on your video. Messages fade at the top by default.
Stack(
fit: StackFit.expand,
children: [
MyLiveVideoPlayer(),
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 280,
child: BaxChatView(
roomName: 'live-123',
user: me,
uiConfig: BaxChatUiConfig.liveOverlay(
joinedTextTemplate: '{name} joined the stream',
edgeFade: BaxChatEdgeFade.top,
edgeFadeExtent: 64,
),
),
),
),
],
);
Compact side panel #
SizedBox(
width: 320,
child: BaxChatView(
roomName: 'support-42',
user: me,
uiConfig: BaxChatUiConfig.compact(),
),
);
Join / leave messages (i18n) #
Control whether presence lines are generated and shown:
BaxChatUiConfig.standard(
showJoinMessages: true, // generate join events
showLeaveMessages: true, // generate leave events
showSystemMessages: true, // paint system bubbles
// Simple template — {name} is replaced:
joinedTextTemplate: '{name} entrou',
leftTextTemplate: '{name} saiu',
// Or full builder for complex i18n:
joinedTextBuilder: (name) => '$name joined the chat',
leftTextBuilder: (name) => '$name left the chat',
);
Typing indicators #
Off by default for every preset. Opt in explicitly:
BaxChatUiConfig.standard(
enableTypingIndicators: true,
typingOneTemplate: '{name} is typing…',
typingTwoTemplate: '{name1} and {name2} are typing…',
typingManyTemplate: 'Several people are typing…',
// Or full i18n:
typingTextBuilder: (names) => '${names.join(', ')} typing…',
);
Bring-your-own typing UI (still requires enableTypingIndicators: true for built-in emit + slot):
BaxChatView(
roomName: room,
uiConfig: BaxChatUiConfig.standard(enableTypingIndicators: true),
typingBuilder: (context, users, controller) {
return Text(users.map((u) => u.userName).join(', ') + '…');
},
onTypingChanged: (users) => debugPrint('typing: $users'),
);
Or drive signals yourself without the built-in label (enableTypingIndicators: false):
await BaxChats.instance.activeController?.startTyping();
await BaxChats.instance.activeController?.stopTyping();
final who = BaxChats.instance.activeController?.typingUsers ?? [];
Customization #
Three levels — same pattern as the Calls UI Kit.
1. Theme / layout (BaxChatUiConfig) #
BaxChatUiConfig.standard(
backgroundColor: const Color(0xFF0B1220),
localBubbleColor: const Color(0xFF7C3AED),
remoteBubbleColor: const Color(0xFF374151),
bubbleBorderRadius: 20,
bubbleTailRadius: 4,
messageFontSize: 15,
showAvatars: true,
showReactionPicker: true,
reactionEmojis: ['👍', '❤️', '🔥'],
edgeFade: BaxChatEdgeFade.both,
edgeFadeExtent: 48,
inputHint: 'Type a message…',
emptyStateText: 'Say hello!',
);
Key options:
| Category | Fields |
|---|---|
| Visibility | showHeader, showSenderName, showAvatars, showTimestamps, showInput, showReactionPicker, showLeaveButton, showConnectionStatus |
| Presence | showJoinMessages, showLeaveMessages, showSystemMessages, joinedTextTemplate, leftTextTemplate, joinedTextBuilder, leftTextBuilder |
| Colors | backgroundColor, localBubbleColor, remoteBubbleColor, localTextColor, remoteTextColor, inputBackgroundColor, accentColor, … |
| Radii | bubbleBorderRadius, bubbleTailRadius, inputBorderRadius, systemMessageBorderRadius, avatarRadius |
| Edge fade | edgeFade (none / top / bottom / both), edgeFadeExtent |
| Copy (i18n) | inputHint, emptyStateText, connectedStatusText, connectingStatusText, leaveTooltip |
2. Partial chrome builders #
BaxChatView(
roomName: room,
user: me,
messageBuilder: (context, message) {
return MyMessageBubble(message: message);
},
inputBuilder: (context, controller, onSend) {
return MyChatInput(onSend: onSend);
},
);
3. Full custom screen (inChatBuilder) #
The kit manages the room session; you own the chrome.
BaxChatView(
roomName: room,
user: me,
inChatBuilder: (context, session) {
return Column(
children: [
MyAppBar(
title: session.roomName,
onLeave: session.leave,
),
Expanded(child: session.chatSurface),
],
);
},
);
Drive chat from anywhere while connected:
BaxChats.instance.activeController?.sendText('Hello from my toolbar!');
Controller #
BaxChatController is bound while BaxChatView is connected.
final controller = BaxChats.instance.activeController;
// Send
await controller?.sendText('Hello!');
await controller?.sendReaction('👍');
// Read
final messages = controller?.messages ?? [];
final connected = controller?.isConnected ?? false;
// Persist / restore
controller?.onMessage = (msg) => myDb.insert(msg.toJson());
controller?.seedMessages(await myDb.loadForRoom('support-lobby'));
Message persistence #
BaxCloud is a realtime transport for chat — messages are broadcast to connected participants and are not retained after the session. If your product needs history, store messages in your database.
Save every message #
BaxChatView(
roomName: 'support-lobby',
user: me,
onMessage: (message) {
// Skip system lines if you only want user content:
if (message.type == BaxChatMessageType.system) return;
unawaited(myDb.upsertChatMessage(message.toJson()));
},
);
onMessage fires for local sends, remote receives, and (if enabled) join/leave system lines. Use message.isLocal, message.type, and message.toJson() as needed.
Restore history on join #
Load from your DB, then pass as initialMessages (or call controller.seedMessages(...)). Seeded items are shown in the UI but do not re-trigger onMessage.
final history = await myDb.loadMessages(roomId: 'support-lobby');
BaxChatView(
roomName: 'support-lobby',
user: me,
initialMessages: history
.map((row) => BaxChatMessage.fromJson(row, isLocal: row['senderId'] == me.userId))
.toList(),
onMessage: (message) => myDb.upsertChatMessage(message.toJson()),
);
BaxChatView options #
| Option | Description |
|---|---|
roomName |
BaxCloud room to join (required) |
user |
Optional BaxcloudUser — falls back to BaxChats.initialize localUser |
metadata |
Optional per-join map merged over user.metadata |
isHost |
Mark local participant as host (default false) |
canJoinWithNoHost |
Allow join when no host present (default true) |
config |
Override BaxConfig (else BaxChats / BaxChatScope) |
uiConfig |
Preset with named overrides (showInput, enableTypingIndicators, …); copyWith still available |
messageBuilder |
Custom message bubble |
inputBuilder |
Custom input bar |
typingBuilder |
Custom typing indicator UI |
inChatBuilder |
Replace entire screen chrome |
onMessage |
Persist each new message to your DB |
onTypingChanged |
Remote typing set changed |
initialMessages |
Prefill UI from your DB (no onMessage for these) |
onLeave |
Called when user leaves or disconnects |
loadingWidget / errorBuilder |
Join UX |
BaxChats.initialize(localUser:) sets the app-wide identity used for invites / default View identity. Pass user: on the View to override for that session (e.g. guest vs logged-in). If user is omitted, the kit uses localUser from initialize.
Example app #
Bundled demos: Chat screen, Live streaming comments, Compact side panel, Bring your own chrome.
cd example
flutter run \
--dart-define=BAXCLOUD_PROJECT_ID=your_project_id \
--dart-define=BAXCLOUD_API_KEY=bax_pk_your_client_key
Build release APK:
cd example
flutter build apk --release \
--dart-define=BAXCLOUD_PROJECT_ID=your_project_id \
--dart-define=BAXCLOUD_API_KEY=bax_pk_your_client_key
Two-device test #
- Device A → user id
user1, roomdemo-chat→ Save profile → Open demo - Device B → user id
user2, same room → Save profile → Open demo - Send messages on either device — they appear on both within the same room
Toggle Show join / leave messages on the home screen to test presence lines and i18n templates.
Support #
License #
See LICENSE.