flutter_chat_io 1.1.0
flutter_chat_io: ^1.1.0 copied to clipboard
Live customer support for Flutter apps with Slack integration. Users chat in-app, your team responds in Slack.
example/lib/main.dart
// ignore_for_file: public_member_api_docs
import 'package:flutter/material.dart';
import 'package:flutter_chat_io/flutter_chat_io.dart';
/// Example application demonstrating FlutterChatIO integration.
///
/// This example shows:
/// - SDK initialization
/// - User identification
/// - Theme customization
/// - Navigation to chat widget
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Initialize FlutterChatIO with your client token
// Get your token from https://flutterchat.io/dashboard
FlutterChatIO.initialize(clientToken: 'your-client-token');
runApp(const FlutterChatIOExampleApp());
}
/// Root application widget.
class FlutterChatIOExampleApp extends StatelessWidget {
const FlutterChatIOExampleApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
title: 'FlutterChatIO Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.indigo,
brightness: Brightness.dark,
),
useMaterial3: true,
),
home: const HomePage(),
);
}
/// Home page with options to open different themed chats.
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _userIdController = TextEditingController(text: 'demo-user-123');
final _emailController = TextEditingController(text: 'demo@example.com');
final _nameController = TextEditingController(text: 'Demo User');
@override
void dispose() {
_userIdController.dispose();
_emailController.dispose();
_nameController.dispose();
super.dispose();
}
void _updateUserInfo() {
FlutterChatIO.setUserId(userId: _userIdController.text);
FlutterChatIO.setUserInfo(
email: _emailController.text,
userName: _nameController.text,
);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('User info updated'),
behavior: SnackBarBehavior.floating,
),
);
}
void _openChat(FlutterChatIOTheme theme) {
// Ensure user info is set before opening chat
FlutterChatIO.setUserId(userId: _userIdController.text);
FlutterChatIO.setUserInfo(
email: _emailController.text,
userName: _nameController.text,
);
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (_) => FlutterChatIOChat(theme: theme),
),
);
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('FlutterChatIO Example'),
centerTitle: true,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// User Configuration Section
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'User Configuration',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
TextField(
controller: _userIdController,
decoration: const InputDecoration(
labelText: 'User ID',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person),
),
),
const SizedBox(height: 12),
TextField(
controller: _emailController,
decoration: const InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.email),
),
),
const SizedBox(height: 12),
TextField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Display Name',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.badge),
),
),
const SizedBox(height: 16),
FilledButton.icon(
onPressed: _updateUserInfo,
icon: const Icon(Icons.save),
label: const Text('Save User Info'),
),
],
),
),
),
const SizedBox(height: 24),
// Theme Examples Section
Text(
'Theme Examples',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
// Default Theme
_ThemeCard(
title: 'Default Theme',
subtitle: 'Material Blue styling',
color: const Color(0xFF1976D2),
onTap: () => _openChat(const FlutterChatIOTheme()),
),
// Indigo Theme
_ThemeCard(
title: 'Indigo Theme',
subtitle: 'Purple/indigo accent colors',
color: Colors.indigo,
onTap: () => _openChat(
FlutterChatIOTheme(
appBarColor: Colors.indigo,
appBarTitle: 'Help Center',
outgoingMessageColor: Colors.indigo,
sendButtonColor: Colors.indigo,
emptyStateTitle: 'How can we help?',
emptyStateSubtitle: 'Our team is here to assist you',
),
),
),
// Teal Theme
_ThemeCard(
title: 'Teal Theme',
subtitle: 'Fresh teal accent colors',
color: Colors.teal,
onTap: () => _openChat(
FlutterChatIOTheme(
appBarColor: Colors.teal,
appBarTitle: 'Support Chat',
outgoingMessageColor: Colors.teal,
sendButtonColor: Colors.teal,
onlineColor: Colors.teal,
emptyStateTitle: 'Welcome!',
emptyStateSubtitle: 'Start a conversation with us',
),
),
),
// Dark Theme
_ThemeCard(
title: 'Dark Theme',
subtitle: 'Dark mode styling',
color: const Color(0xFF2D2D2D),
onTap: () => _openChat(
FlutterChatIOTheme(
// AppBar
appBarColor: const Color(0xFF1E1E1E),
appBarTitle: 'Night Support',
// Background
backgroundColor: const Color(0xFF121212),
// Messages
incomingMessageColor: const Color(0xFF2D2D2D),
outgoingMessageColor: Colors.indigo,
incomingMessageTextStyle: const TextStyle(
fontSize: 15,
color: Colors.white,
),
incomingTimeTextStyle: const TextStyle(
fontSize: 11,
color: Colors.white54,
),
// Input
inputBackgroundColor: const Color(0xFF2D2D2D),
inputTextColor: Colors.white,
inputHintColor: Colors.white54,
keyboardAppearance: Brightness.dark,
sendButtonColor: Colors.indigo,
// Empty state
emptyStateTitle: 'Night Owl Support',
emptyStateSubtitle: 'We are here 24/7',
emptyStateTitleStyle: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.white,
),
emptyStateSubtitleStyle: const TextStyle(
fontSize: 14,
color: Colors.white70,
),
),
),
),
// Spanish Localization
_ThemeCard(
title: 'Spanish Localization',
subtitle: 'Localización en español',
color: Colors.orange,
onTap: () => _openChat(
FlutterChatIOTheme(
appBarColor: Colors.orange,
appBarTitle: 'Soporte',
outgoingMessageColor: Colors.orange,
sendButtonColor: Colors.orange,
emptyStateTitle: 'Bienvenido',
emptyStateSubtitle: 'Envíanos un mensaje para comenzar',
offlineFormTitle: 'Estamos fuera de línea',
offlineFormSubtitle:
'Deja tu información de contacto y te responderemos:',
offlineFormButtonText: 'Continuar al chat',
offlineFormNameHint: 'Tu nombre',
offlineFormEmailHint: 'Tu email',
offlineFormNameEmailError:
'Por favor ingresa tu nombre y email',
offlineFormEmailValidError:
'Por favor ingresa un email válido',
offlineFormBlockedMessage:
'Completa el formulario arriba para enviar mensajes',
supportUserName: 'Soporte',
),
),
),
const SizedBox(height: 24),
// SDK Info
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'SDK Information',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
_InfoRow(
label: 'Initialized',
value: FlutterChatIO.isInitialized ? 'Yes' : 'No',
),
_InfoRow(
label: 'WebSocket Endpoint',
value: FlutterChatIO.apiWss,
),
_InfoRow(
label: 'HTTP Endpoint',
value: FlutterChatIO.apiHttpHistory,
),
],
),
),
),
],
),
),
);
}
/// A card displaying a theme option.
class _ThemeCard extends StatelessWidget {
const _ThemeCard({
required this.title,
required this.subtitle,
required this.color,
required this.onTap,
});
final String title;
final String subtitle;
final Color color;
final VoidCallback onTap;
@override
Widget build(BuildContext context) => Card(
margin: const EdgeInsets.only(bottom: 8),
child: ListTile(
leading: Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(8),
),
child: const Icon(Icons.chat, color: Colors.white),
),
title: Text(title),
subtitle: Text(subtitle),
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
onTap: onTap,
),
);
}
/// A row displaying label-value information.
class _InfoRow extends StatelessWidget {
const _InfoRow({
required this.label,
required this.value,
});
final String label;
final String value;
@override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 140,
child: Text(
label,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
Expanded(
child: Text(
value,
style: Theme.of(context).textTheme.bodyMedium,
),
),
],
),
);
}