convokit_flutter 0.0.1
convokit_flutter: ^0.0.1 copied to clipboard
Flutter SDK for ConvoKit - real-time messaging integration.
ConvoKit Flutter SDK #
Flutter SDK for adding ConvoKit conversations, messages, realtime events, and media uploads to a Flutter app.
The SDK talks to your ConvoKit backend over REST and uses Supabase Realtime for live messaging events. Your ConvoKit client secret should stay on your server; mobile and web clients should only receive short-lived user tokens from your own token endpoint.
Features #
- Configure a ConvoKit app client and connect an app user.
- Create, fetch, archive, unarchive, and leave conversations.
- Send and paginate messages with text, image, and file media.
- Subscribe to realtime message, typing, read receipt, and presence events.
- Upload user avatars, conversation images, and message attachments through signed Cloudinary upload URLs.
- Use typed Dart models for
Conversation,Message, andParticipant.
Installation #
Add the package to your Flutter app:
flutter pub add convokit_flutter
Then import it:
import 'package:convokit_flutter/convokit_flutter.dart';
Setup #
Configure ConvoKit once when your app starts. The tokenProvider must call your
own backend and return a ConvoKit JWT for the current app user. Do not embed
your ConvoKit client secret in a Flutter app.
import 'dart:convert';
import 'package:convokit_flutter/convokit_flutter.dart';
import 'package:http/http.dart' as http;
Future<void> bootstrapConvoKit() async {
ConvoKit.configure(
backendUrl: 'https://api.your-convokit-backend.com',
clientId: 'your-convokit-client-id',
tokenProvider: (appUserId) async {
final response = await http.post(
Uri.parse('https://your-api.example.com/convokit/token'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'appUserId': appUserId}),
);
if (response.statusCode != 200) {
throw Exception('Failed to fetch ConvoKit token');
}
final body = jsonDecode(response.body) as Map<String, dynamic>;
return body['token'] as String;
},
);
}
Call connectUser after your app has identified the current user:
await ConvoKit.connectUser('app-user-123');
When the user signs out, disconnect realtime subscriptions:
await ConvoKit.disconnectUser();
Conversations #
final conversations = await ConvoKit.getConversations(limit: 20);
final conversation = await ConvoKit.createConversation(
participants: ['app-user-123', 'app-user-456'],
title: 'Product support',
);
await ConvoKit.updateConversationTitle(
conversationId: conversation.id,
title: 'Billing support',
);
await ConvoKit.archiveConversation(conversation.id);
await ConvoKit.unarchiveConversation(conversation.id);
await ConvoKit.leaveConversation(conversation.id);
Messages #
final message = await ConvoKit.sendMessage(
conversationId: conversation.id,
text: 'Hey, can you take a look?',
);
final messages = await ConvoKit.getMessages(
conversationId: conversation.id,
limit: 50,
);
To send media, upload the bytes first and pass the returned URL in the message payload:
final url = await ConvoKit.uploadMessageMedia(
bytes: imageBytes,
fileName: 'screenshot.png',
);
await ConvoKit.sendMessage(
conversationId: conversation.id,
text: 'Screenshot attached',
media: [
{
'type': 'image',
'url': url,
'name': 'screenshot.png',
},
],
);
Realtime #
Subscribe through ConvoKit.realtime after connectUser completes.
final messageSub = ConvoKit.realtime
.onMessage(conversation.id)
.listen((message) {
// Render the incoming message.
});
final typingSub = ConvoKit.realtime
.onTyping(conversation.id)
.listen((event) {
// event.userId and event.isTyping
});
final readSub = ConvoKit.realtime
.onReadReceipt(conversation.id)
.listen((event) {
// event.userId and event.readAt
});
Send typing indicators and read receipts with the REST helpers:
await ConvoKit.sendTyping(
conversationId: conversation.id,
isTyping: true,
);
await ConvoKit.markConversationRead(conversation.id);
Presence events are scoped to the ConvoKit app client ID:
final presenceSub = ConvoKit.realtime
.onPresence(ConvoKit.clientId)
.listen((event) {
// event.userId, event.isOnline, event.lastSeenAt
});
await ConvoKit.updatePresence(isOnline: true);
Cancel stream subscriptions from your widget or state manager when they are no longer needed.
Media Helpers #
final avatarUrl = await ConvoKit.uploadUserAvatar(
userId: ConvoKit.currentUserId,
imageBytes: avatarBytes,
fileName: 'avatar.png',
);
final conversationImageUrl = await ConvoKit.uploadConversationImage(
conversationId: conversation.id,
imageBytes: imageBytes,
fileName: 'group.png',
);
await ConvoKit.deleteUserAvatar(userId: ConvoKit.currentUserId);
await ConvoKit.deleteConversationImage(conversationId: conversation.id);
Error Handling #
REST helpers throw ConvoKitException when the backend returns a non-success
response.
try {
await ConvoKit.sendMessage(
conversationId: conversation.id,
text: 'Hello',
);
} on ConvoKitException catch (error) {
// Show a retry state or log error.message.
}
Publishing #
Publishing to pub.dev is automated through GitHub Actions when a version tag is pushed.
Before the workflow can publish, the package must already exist on pub.dev. If
this is the first release, publish it manually once with dart pub publish or
flutter pub publish.
Enable automated publishing from the pub.dev package admin page with:
- Repository:
ConvoKitApp/ConvoKit-Flutter-SDK - Tag pattern:
v{{version}} - GitHub Actions environment:
pub.dev
To publish a new version:
- Update
versioninpubspec.yaml. - Update
CHANGELOG.md. - Commit and push the changes.
- Push a matching version tag:
git tag v0.0.2
git push origin v0.0.2
License #
ConvoKit Flutter SDK is licensed under the Apache License, Version 2.0. See
LICENSE for details.