Appearance
Flutter UI Kit
Drop-in chat UI for Flutter (sendsar_chat_uikit). Conversation list, thread, composer, and call UI — no custom screens required.
Before code: mint a session token on your server. Never ship sk_* in the app.
Guided path: Quick start → Flutter UI Kit.
Own the UI instead? Use the Flutter SDK.
Fast path
Do this in order — most integrations are these steps.
1. Install
bash
flutter pub add sendsar_chat_uikit sendsar_chatsendsar_call is pulled in by the UI kit for voice/video.
2. Theme + scope + shell
Register theme extensions on MaterialApp, wrap with SendsarScope, mount SendsarChatShell.
dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:sendsar_chat/sendsar_chat.dart';
import 'package:sendsar_chat_uikit/sendsar_chat_uikit.dart';
Future<SessionResponse> fetchChatSession() async {
final res = await http.post(
Uri.parse('https://your-app.com/api/chat/session'),
headers: {'Cookie': '…'},
);
if (res.statusCode < 200 || res.statusCode >= 300) {
throw Exception(res.body);
}
// { token, expiresAt, apiUrl, chatUserId, displayName }
return SessionResponse.fromJson(
jsonDecode(res.body) as Map<String, dynamic>,
);
}
final shellKey = GlobalKey<SendsarChatShellState>();
MaterialApp(
theme: ThemeData(
useMaterial3: true,
extensions: const [SendsarChatTheme.light],
),
darkTheme: ThemeData(
useMaterial3: true,
extensions: const [SendsarChatTheme.dark],
),
home: SendsarScope(
config: SendsarConfig(fetchSession: fetchChatSession),
// autoStart: true (default) — mint + connect after mount
child: SendsarChatShell(
key: shellKey,
users: [
UserDirectoryEntry(id: 'user_bob', displayName: 'Bob'),
],
),
),
);Pass a user directory so DMs show names instead of raw ids.
3. Create a room, then open it
The shell does not create rooms. Your app (or BFF) creates the room, then call openRoom:
dart
final session = context.read<SendsarSessionService>();
final client = session.client!;
final me = session.session!.chatUserId;
final room = await client.createRoom(CreateRoomParams(
externalId: 'dm:$me:user_bob',
participants: [
CreateRoomParticipant(id: me),
CreateRoomParticipant(id: 'user_bob'),
],
));
await shellKey.currentState?.openRoom(room.id, title: 'Bob');Peers must already exist (logged in once, or upserted with sk_*). Prefer externalId for stable DMs.
4. Voice & video (optional)
Call UI ships in the shell (sendsar_call). Enable Calls in the dashboard, add permissions, then dial from an open room.
xml
<!-- ios/Runner/Info.plist -->
NSMicrophoneUsageDescription = Needed for voice and video calls
NSCameraUsageDescription = Needed for video callsxml
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />What the shell includes
- Conversation list (unread, presence) + message thread + composer
- Long-press actions: reactions, pin / unpin, forward, edit / delete
- Leave group / delete chat / clear history; group members live-refresh
- Voice & video overlay (ring, active call, minimized chip, call-log redial)
Theming: SendsarChatTheme.light / .dark, optional SendsarThemeOverride, or per-list styles / bubble builders.
Checklist
- [ ] Session from your BFF — no
sk_*in the app - [ ]
SendsarChatThemeregistered onMaterialApp - [ ] User directory for readable DM titles
- [ ] Create room in your app →
openRoomon the shell - [ ] Calls (if needed): dashboard flag + mic/camera permissions