supabase_chat_sdk 0.1.0
supabase_chat_sdk: ^0.1.0 copied to clipboard
Offline-first Flutter chat SDK built on Supabase and PowerSync with real-time messaging, channels, reactions, and file uploads.
Supabase Chat SDK #
A Flutter SDK for building offline-first chat applications with Supabase and PowerSync.
Features #
- Offline-First Architecture: Built on PowerSync for seamless offline support with automatic sync
- Real-time Updates: Live message delivery using Supabase Realtime
- Type-Safe: Full type safety with Result types for error handling
- Production-Ready: Comprehensive error handling, retry logic, and state management
Core Features #
- ✅ Channel management (Direct, Group, Public)
- ✅ Real-time messaging with offline support
- ✅ Message read receipts
- ✅ Emoji reactions
- ✅ File uploads (images, videos, documents)
- ✅ Typing indicators
- ✅ User presence (online/offline)
- ✅ Push notifications
- ✅ User blocking
- ✅ Message search
- ✅ Pagination
- ✅ Profile metadata (for custom badges, premium status, etc.)
Installation #
Add to your pubspec.yaml:
dependencies:
supabase_chat_sdk: ^0.1.0
Quick Start #
1. Initialize #
import 'package:supabase_chat_sdk/supabase_chat_sdk.dart';
await ChatClient.instance.initialize(
supabaseUrl: 'YOUR_SUPABASE_URL',
supabaseAnonKey: 'YOUR_SUPABASE_ANON_KEY',
powerSyncUrl: 'YOUR_POWERSYNC_URL',
);
2. Connect User #
// After signing in with Supabase Auth
await ChatClient.instance.connectUser();
3. Create a Channel #
// Create a group channel
final result = await ChatClient.instance.channels.createChannel(
type: ChannelType.group,
name: 'My Team',
memberIds: ['user-id-1', 'user-id-2'],
);
if (result.isSuccess) {
final channel = result.valueOrNull!;
print('Channel created: ${channel.id}');
}
4. Send Messages #
final result = await ChatClient.instance.messages.sendMessage(
channelId: 'channel-id',
content: 'Hello, World!',
);
5. Watch Messages #
ChatClient.instance.messages.watchMessages('channel-id').listen((messages) {
print('Received ${messages.length} messages');
});
Usage #
Channels #
// Watch all channels for current user
ChatClient.instance.channels.watchChannels().listen((channels) {
// Update UI
});
// Get or create direct message channel
final result = await ChatClient.instance.channels
.getOrCreateDirectChannel('other-user-id');
// Update channel metadata
await ChatClient.instance.channels.updateChannel(
channelId,
name: 'New Name',
description: 'Updated description',
);
// Leave a channel
await ChatClient.instance.channels.leaveChannel(channelId);
Messages #
// Send text message
await ChatClient.instance.messages.sendMessage(
channelId: channelId,
content: 'Hello!',
);
// Send image
await ChatClient.instance.messages.sendMessage(
channelId: channelId,
content: '',
type: MessageType.image,
metadata: MessageMetadata(fileUrl: imageUrl),
);
// Reply to message
await ChatClient.instance.messages.sendMessage(
channelId: channelId,
content: 'Reply text',
parentId: originalMessageId,
);
// Delete message
await ChatClient.instance.messages.deleteMessage(messageId);
Reactions #
// Add reaction
await ChatClient.instance.reactions.addReaction(
messageId: messageId,
emoji: '👍',
);
// Remove reaction
await ChatClient.instance.reactions.removeReaction(reactionId);
// Watch reactions for a message
ChatClient.instance.reactions.watchReactions(messageId).listen((reactions) {
// Update UI
});
Read Receipts #
// Send read receipt
await ChatClient.instance.readReceipts.sendReadReceipt(
channelId: channelId,
messageId: lastMessageId,
);
// Watch read receipts
ChatClient.instance.readReceipts.watchReadReceipts(channelId).listen((receipts) {
// Update UI
});
File Uploads #
// Upload file
final result = await ChatClient.instance.files.uploadFile(
file: File('path/to/file.jpg'),
bucket: 'chat-files',
);
if (result.isSuccess) {
final url = result.valueOrNull!;
// Use url in message metadata
}
Real-time Features #
// Join channel for real-time updates
await ChatClient.instance.realtime.joinChannel(channelId);
// Send typing indicator
await ChatClient.instance.realtime.sendTypingIndicator(channelId, true);
// Watch typing indicators
ChatClient.instance.realtime.watchTyping(channelId).listen((events) {
final typingUsers = events.where((e) => e.isTyping).map((e) => e.userId);
});
// Watch user presence
ChatClient.instance.realtime.watchPresence(channelId).listen((presence) {
final onlineUsers = presence.where((p) => p.isOnline);
});
User Blocking #
// Block user
await ChatClient.instance.blocks.blockUser('user-id');
// Unblock user
await ChatClient.instance.blocks.unblockUser('user-id');
// Get blocked users
final result = await ChatClient.instance.blocks.getBlockedUsers();
Backend Setup #
1. Run Migrations #
cd supabase
supabase db push
2. Configure PowerSync #
Upload the sync_rules.yaml to your PowerSync instance.
3. Storage Bucket #
Create a chat-files storage bucket with public access policy.
Architecture #
The SDK uses a clean architecture with:
- Models: Type-safe data models
- Repositories: Data access layer with offline-first support
- Services: Business logic (file upload, push notifications, realtime)
- Result Type: Type-safe error handling
All write operations return Result<T> for explicit error handling:
final result = await ChatClient.instance.channels.createChannel(...);
if (result.isSuccess) {
final channel = result.valueOrNull!;
// Success
} else {
final error = result.exceptionOrNull!;
// Handle error
}
License #
MIT License - see LICENSE file for details.