Flutter Usage
The Lovina Chat SDK provides a LovinaChatWidget widget and LovinaChatModal helper for embedding chat in your Flutter app.
Inline Widget
Embed the chat directly in your widget tree:
import 'package:flutter/material.dart';
import 'package:lovina_chat_sdk/lovina_chat_sdk.dart';
class ChatPage extends StatelessWidget {
const ChatPage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Support Chat')),
body: LovinaChatWidget(
config: LovinaChatConfig(
websiteToken: 'your-website-token',
baseUrl: 'https://chat.lovina.app',
),
onLoaded: (event) {
debugPrint('Chat loaded, token: ${event.authToken}');
},
onMessageReceived: (event) {
debugPrint('Message: ${event.message}');
},
onUnreadCountChanged: (event) {
debugPrint('Unread: ${event.count}');
},
onClosed: (event) {
debugPrint('Closed: ${event.reason}');
},
onError: (event) {
debugPrint('Error: ${event.code} - ${event.message}');
},
),
);
}
}
Modal Bottom Sheet
Show the chat as a draggable bottom sheet:
ElevatedButton(
onPressed: () {
LovinaChatModal.showBottomSheet(
context: context,
config: LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
),
onMessageReceived: (event) {
debugPrint('New message received');
},
);
},
child: const Text('Open Chat'),
)
Full-Screen Modal
Show the chat as a full-screen page:
LovinaChatModal.showFullScreen(
context: context,
config: LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
),
);
User Identification
Pre-identify users to associate messages with their account:
final config = LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
user: LovinaChatUser(
identifier: 'user-123',
name: 'John Doe',
email: 'john@example.com',
avatarUrl: 'https://example.com/avatar.png',
identifierHash: 'hmac-hash-for-verification',
phoneNumber: '+62812345678',
customAttributes: {
'plan': 'premium',
'company': 'Acme Corp',
},
),
);
Theming
Color Scheme
LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
colorScheme: 'auto', // or 'light', 'dark'
)
Custom Brand Color
LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
customColor: '#FF6B35', // Orange header and bubbles
)
Session Management
The SDK automatically persists conversation cookies via flutter_secure_storage. Users resume their existing conversation when reopening the chat.
To manually clear a session:
await CookieStore.clear('your-website-token');
Generic Event Handler
Use the onEvent callback to handle all events in a single place:
LovinaChatWidget(
config: config,
onEvent: (event) {
if (event is ChatLoadedEvent) {
debugPrint('Loaded with token: ${event.authToken}');
} else if (event is MessageReceivedEvent) {
debugPrint('Message: ${event.message}');
} else if (event is UnreadCountChangedEvent) {
debugPrint('Unread count: ${event.count}');
} else if (event is ChatClosedEvent) {
debugPrint('Closed: ${event.reason}');
} else if (event is ChatErrorEvent) {
debugPrint('Error [${event.code}]: ${event.message}');
}
},
)
Common Patterns
Navigation: Push chat page, pop on close
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: LovinaChatWidget(
config: config,
onClosed: (_) => Navigator.of(context).pop(),
),
),
),
);
Modal bottom sheet with auto-dismiss
LovinaChatModal.showBottomSheet(
context: context,
config: config,
onClosed: (_) => Navigator.of(context).pop(),
);
Unread badge on tab
int _unreadCount = 0;
LovinaChatWidget(
config: config,
onUnreadCountChanged: (event) {
setState(() => _unreadCount = event.count);
},
)
// In BottomNavigationBar
BottomNavigationBarItem(
icon: Badge(
isLabelVisible: _unreadCount > 0,
label: Text('$_unreadCount'),
child: const Icon(Icons.chat),
),
label: 'Chat',
)