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.flutter-io.cn is automated through GitHub Actions when a version tag is pushed.
Before the workflow can publish, the package must already exist on pub.flutter-io.cn. If
this is the first release, publish it manually once with dart pub publish or
flutter pub publish.
Enable automated publishing from the pub.flutter-io.cn package admin page with:
- Repository:
ConvoKitApp/ConvoKit-Flutter-SDK - Tag pattern:
v{{version}} - GitHub Actions environment:
pub.flutter-io.cn
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.