omni_chat 1.0.3
omni_chat: ^1.0.3 copied to clipboard
A professional, feature-rich Flutter chat UI package. Supports 17+ message types including text, image, video, audio waveform, sticker, GIF, document, location, contact, link preview, poll, profile ca [...]
omni_chat #
OmniChat is a professional, feature-rich Flutter chat UI package. It supports 17+ message types, built-in media viewers, audio waveform recording, swipe-to-reply, emoji reactions, profile card messages, screenshot protection, full theme customisation, and built-in localisation via OmniChatStrings.
Designed for FlutterFlow integration and any Flutter app.
✨ Features #
| Feature | Details |
|---|---|
| 17+ Message Types | Text, Image, Video, Audio (waveform), Sticker (Lottie), GIF, Document, Location, Contact, Link Preview, Poll, Profile Card, View-Once Image, View-Once Video, System, Custom |
| Swipe-to-Reply | Swipe any message left/right to quote-reply, with haptic feedback |
| Audio Waveform | WhatsApp-style voice note with animated waveform, 1×/1.5×/2× playback speed |
| Built-in Image Viewer | Pinch-to-zoom, multi-image gallery swipe, hero animation |
| Built-in Video Player | Full-screen player with seek, speed control, and landscape support |
| View-Once Media | Ephemeral image & video that vanishes after one viewing |
| Profile Card | @username card with verified badge; tapping navigates to profile |
| Media Source Badge | 📷 Camera / 🖼 Gallery label shown on image & video bubbles |
| Emoji Reactions | Long-press → pick emoji, reaction chips with counts |
| Message Editing | Edit your own messages, shows "edited" indicator |
| Message Deletion | Delete for me / delete for everyone |
| Encryption Banner | 🔒 End-to-end encrypted banner + per-message lock icon |
| Screenshot Protection | Android FLAG_SECURE toggle |
| Full Theming | OmniChatTheme with light/dark presets and every token overridable |
| Wallpapers | Solid color, gradient, or network/asset image background |
| FlutterFlow Ready | Drop-in Custom Widget instructions below |
📦 Installation #
dependencies:
omni_chat: ^1.0.3
flutter pub get
Android permissions (AndroidManifest.xml) #
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
iOS (Info.plist) #
<key>NSCameraUsageDescription</key>
<string>Required to capture photos and videos for chat</string>
<key>NSMicrophoneUsageDescription</key>
<string>Required to record voice messages</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Required to pick photos and videos from your library</string>
🚀 Quick Start #
import 'package:omni_chat/omni_chat.dart';
OmniChatThemeScope(
theme: OmniChatTheme.dark(),
child: Column(
children: [
Expanded(
child: OmniChatList(
messages: _messages, // List<ChatMessage>
currentUserId: 'user_me',
isEncrypted: true,
screenshotProtection: true,
onReply: (msg) => setState(() => _replyTo = msg),
onProfileTap: (uid) => Navigator.pushNamed(context, '/profile/$uid'),
onPollVote: (msg, optionId) { /* update your backend */ },
),
),
OmniChatInput(
replyMessage: _replyTo,
onCancelReply: () => setState(() => _replyTo = null),
onSendText: (text) => _sendMessage(TextMessage(...)),
onSendAudio: (path, duration, waveform) => _sendMessage(AudioMessage(...)),
onAttachment: (type) => _handleAttachment(type),
),
],
),
);
📨 Message Types #
All message types extend ChatMessage. Use ChatMessage.fromJson() and
toJson() for serialisation.
Text #
TextMessage(
id: 'msg_1',
senderId: 'user_a',
timestamp: DateTime.now(),
text: 'Hello @john! Check https://flutter.cn',
)
Image with source badge #
ImageMessage(
id: 'msg_2',
senderId: 'user_b',
timestamp: DateTime.now(),
imageUrl: 'https://example.com/photo.jpg',
caption: 'Look at this!',
source: MediaSource.camera, // shows 📷 Camera badge
)
Audio (waveform) #
AudioMessage(
id: 'msg_3',
senderId: 'user_a',
timestamp: DateTime.now(),
audioUrl: 'https://example.com/voice.m4a',
duration: 45, // seconds
waveformData: [0.2, 0.8, 0.5, 0.9, ...], // normalised amplitudes 0.0–1.0
source: MediaSource.microphone,
)
Profile Card #
ProfileCardMessage(
id: 'msg_4',
senderId: 'user_a', // sender
userId: 'user_a', // profile being shared (same → shows verified badge)
username: 'odama_studio',
displayName: 'Odama Studio',
avatarUrl: 'https://example.com/avatar.jpg',
isVerified: true,
bio: 'Professional UI/UX design studio',
timestamp: DateTime.now(),
)
View-Once Image #
EphemeralImageMessage(
id: 'msg_5',
senderId: 'user_b',
timestamp: DateTime.now(),
imageUrl: 'https://example.com/secret.jpg',
hasBeenViewed: false,
)
Custom Message #
CustomMessage(
id: 'msg_6',
senderId: 'user_a',
timestamp: DateTime.now(),
customType: 'payment',
payload: {'amount': 25.0, 'currency': 'USD'},
)
// In OmniChatList:
OmniChatList(
messages: _messages,
currentUserId: 'me',
customMessageBuilder: (context, msg) {
if (msg.customType == 'payment') {
return PaymentBubble(payload: msg.payload);
}
return const SizedBox.shrink();
},
)
🎨 Theming #
// Built-in presets
OmniChatTheme.light()
OmniChatTheme.dark()
// Custom theme
OmniChatTheme.light().copyWith(
outgoingBubbleColor: Color(0xFF4CAF50),
bubbleRadius: 20,
waveformActiveColor: Colors.teal,
wallpaper: OmniChatWallpaper.gradient(
LinearGradient(
colors: [Color(0xFFE0F2F1), Color(0xFFB2DFDB)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
)
Wrap your widget tree with OmniChatThemeScope:
OmniChatThemeScope(
theme: myTheme,
child: OmniChatList(...),
)
🔒 Security #
OmniChatList(
messages: _messages,
currentUserId: 'me',
isEncrypted: true, // shows 🔒 banner
screenshotProtection: true, // Android FLAG_SECURE
)
Note: iOS does not support complete screenshot prevention via Flutter. The encryption banner is shown but screenshots can still be taken. For sensitive apps, consider additional platform-channel implementations.
📱 FlutterFlow Custom Widget Integration #
- In FlutterFlow, go to Custom Code → Custom Widgets → Add Widget
- Name it
OmniChatWidget - Paste the following skeleton and adjust parameters as needed:
import 'package:omni_chat/omni_chat.dart';
class OmniChatWidget extends StatefulWidget {
const OmniChatWidget({
Key? key,
required this.messages, // List<dynamic> (JSON maps)
required this.currentUserId, // String
this.isEncrypted = false,
this.onSendText, // Action
this.onProfileTap, // Action with userId param
}) : super(key: key);
final List<dynamic> messages;
final String currentUserId;
final bool isEncrypted;
final Future<void> Function()? onSendText;
final Future<void> Function()? onProfileTap;
@override
State<OmniChatWidget> createState() => _OmniChatWidgetState();
}
class _OmniChatWidgetState extends State<OmniChatWidget> {
late List<ChatMessage> _parsed;
@override
void initState() {
super.initState();
_parsed = widget.messages
.map((e) => ChatMessage.fromJson(Map<String, dynamic>.from(e as Map)))
.toList();
}
@override
Widget build(BuildContext context) {
return OmniChatThemeScope(
theme: OmniChatTheme.light(),
child: Column(
children: [
Expanded(
child: OmniChatList(
messages: _parsed,
currentUserId: widget.currentUserId,
isEncrypted: widget.isEncrypted,
),
),
OmniChatInput(
onSendText: (_) => widget.onSendText?.call(),
),
],
),
);
}
}
- Add
omni_chatto your FlutterFlow project'spubspec.yamlunder Project Settings → Custom Code → pubspec.yaml.
🤝 Contributing #
Pull requests are welcome! Please open an issue first to discuss changes.
📄 License #
MIT © 2024 OmniChat Contributors