Skip to main content

Quick Start: Flutter

Embed the Lovina chat widget in your Flutter app using a WebView widget with native event bridging, session persistence, and theme support.

Step 1: Add the Dependency

Add the SDK to your pubspec.yaml:

dependencies:
lovina_chat_sdk:
path: packages/flutter # or from pub.dev when published

Then run:

flutter pub get

Platform-Specific Setup

Android -- add Internet permission in android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

iOS -- if using HTTPS (recommended), no changes are needed. For local development with HTTP, add to ios/Runner/Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

Step 2: Add the Chat Widget

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}');
},
),
);
}
}

Display Options

Inline Widget

Embed the chat directly in your widget tree:

LovinaChatWidget(
config: LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
locale: 'en',
colorScheme: 'auto',
),
onLoaded: (event) => print('Loaded'),
onMessageReceived: (event) => print('Message received'),
onUnreadCountChanged: (event) => print('Unread: ${event.count}'),
onClosed: (event) => print('Closed: ${event.reason}'),
onError: (event) => print('Error: ${event.code} - ${event.message}'),
)
ElevatedButton(
onPressed: () {
LovinaChatModal.showBottomSheet(
context: context,
config: LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
),
onMessageReceived: (event) => print('New message'),
);
},
child: const Text('Open Chat'),
)

Full-Screen Modal

LovinaChatModal.showFullScreen(
context: context,
config: LovinaChatConfig(
websiteToken: 'your-token',
baseUrl: 'https://chat.lovina.app',
),
);

Configuration Options

ParameterTypeDefaultDescription
websiteTokenStringrequiredWebsite channel token from your Lovina dashboard
baseUrlStringrequiredBase URL of your Lovina instance
localeString'id'Widget locale code (3 languages supported)
colorSchemeString'auto''light', 'dark', or 'auto'
userLovinaChatUser?nullPre-identified user
customColorString?nullHex color for theming (e.g., '#FF6B35')
displayModeString'fullscreen''popup', 'sidebar', or 'fullscreen'

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',
},
),
);

Event Handling

Use typed callbacks or the generic onEvent handler:

LovinaChatWidget(
config: config,
onEvent: (event) {
if (event is ChatLoadedEvent) {
print('Loaded with token: ${event.authToken}');
} else if (event is MessageReceivedEvent) {
print('Message: ${event.message}');
} else if (event is UnreadCountChangedEvent) {
print('Unread count: ${event.count}');
} else if (event is ChatClosedEvent) {
print('Closed: ${event.reason}');
} else if (event is ChatErrorEvent) {
print('Error [${event.code}]: ${event.message}');
}
},
)
EventDescription
ChatLoadedEventWidget finished loading. Contains optional authToken.
MessageReceivedEventNew message received. Contains message map.
UnreadCountChangedEventUnread count changed. Contains count.
ChatClosedEventChat closed. Contains optional reason.
ChatErrorEventError occurred. Contains code and message.

Theming

// Follow system theme
LovinaChatConfig(colorScheme: 'auto', ...)

// Force light or dark
LovinaChatConfig(colorScheme: 'dark', ...)

// Custom brand color
LovinaChatConfig(customColor: '#FF6B35', ...)

Session Management

Sessions are persisted automatically via flutter_secure_storage. To clear a session:

await CookieStore.clear('your-website-token');

Requirements

  • Flutter 3.0+
  • Dart 2.19+
  • Android: API 24+ with Internet permission
  • iOS: 15.0+

Next Steps