Skip to content

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_chat

sendsar_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 calls
xml
<!-- 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
  • [ ] SendsarChatTheme registered on MaterialApp
  • [ ] User directory for readable DM titles
  • [ ] Create room in your app → openRoom on the shell
  • [ ] Calls (if needed): dashboard flag + mic/camera permissions

Next