flutter_chat_io 2.2.0 copy "flutter_chat_io: ^2.2.0" to clipboard
flutter_chat_io: ^2.2.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';
import 'package:flutter_localizations/flutter_localizations.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 credentials
  // Get your client ID and token from https://flutterchat.io/dashboard
  FlutterChatIO.initialize(
    clientId: 'your-client-id',
    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',
        // Add localization support for RTL languages (Arabic, Hebrew, etc.)
        localizationsDelegates: const [
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
        ],
        supportedLocales: const [
          Locale('en'), // English
          Locale('zh'), // Chinese
          Locale('es'), // Spanish
          Locale('ar'), // Arabic (RTL)
          Locale('hi'), // Hindi
          Locale('ru'), // Russian
        ],
        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> {
  // User Info controllers
  final _userIdController = TextEditingController(text: 'demo-user-123');
  final _emailController = TextEditingController(text: 'demo@example.com');
  final _nameController = TextEditingController(text: 'Demo User');

  // Custom User Data controllers (key-value pairs)
  final _subscriptionController = TextEditingController(text: 'premium');
  final _accountTypeController = TextEditingController(text: 'business');
  final _signupDateController = TextEditingController(text: '2024-01-15');

  @override
  void dispose() {
    _userIdController.dispose();
    _emailController.dispose();
    _nameController.dispose();
    _subscriptionController.dispose();
    _accountTypeController.dispose();
    _signupDateController.dispose();
    super.dispose();
  }

  /// Builds custom user data map from controllers, excluding empty values.
  Map<String, String> _buildUserData() {
    final data = <String, String>{};
    if (_subscriptionController.text.isNotEmpty) {
      data['subscription'] = _subscriptionController.text;
    }
    if (_accountTypeController.text.isNotEmpty) {
      data['accountType'] = _accountTypeController.text;
    }
    if (_signupDateController.text.isNotEmpty) {
      data['signupDate'] = _signupDateController.text;
    }
    return data;
  }

  void _updateUserInfo() {
    FlutterChatIO.setUserId(userId: _userIdController.text);

    // Set user info and custom data in a single call
    // Note: Device info is automatically detected by the SDK
    final customData = _buildUserData();
    FlutterChatIO.setUserInfo(
      email: _emailController.text,
      userName: _nameController.text,
      customData: customData.isNotEmpty ? customData : null,
    );

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('User info updated'),
        behavior: SnackBarBehavior.floating,
      ),
    );
  }

  void _openChat(FlutterChatIOTheme theme, [Locale? locale]) {
    // Ensure user info is set before opening chat
    FlutterChatIO.setUserId(userId: _userIdController.text);

    // Set user info and custom data in a single call
    // Note: Device info is automatically detected by the SDK
    final customData = _buildUserData();
    FlutterChatIO.setUserInfo(
      email: _emailController.text,
      userName: _nameController.text,
      customData: customData.isNotEmpty ? customData : null,
    );

    Navigator.push(
      context,
      MaterialPageRoute<void>(
        builder: (_) {
          final chat = FlutterChatIOChat(theme: theme);

          // Wrap with locale override for RTL support
          if (locale != null) {
            return Localizations.override(
              context: context,
              locale: locale,
              child: Directionality(
                textDirection: _isRtlLocale(locale)
                    ? TextDirection.rtl
                    : TextDirection.ltr,
                child: chat,
              ),
            );
          }

          return chat;
        },
      ),
    );
  }

  /// Returns true if the locale uses Right-to-Left text direction.
  bool _isRtlLocale(Locale locale) {
    const rtlLanguages = ['ar', 'he', 'fa', 'ur'];
    return rtlLanguages.contains(locale.languageCode);
  }

  @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: 20),
                      // Custom User Data Section
                      Row(
                        children: [
                          Text(
                            'Custom User Data',
                            style: Theme.of(context).textTheme.titleSmall,
                          ),
                          const SizedBox(width: 8),
                          Tooltip(
                            message:
                                'Key-value pairs sent to your support team',
                            child: Icon(
                              Icons.info_outline,
                              size: 16,
                              color: Theme.of(context).colorScheme.outline,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 12),
                      TextField(
                        controller: _subscriptionController,
                        decoration: const InputDecoration(
                          labelText: 'Subscription',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.card_membership),
                          hintText: 'e.g., premium, free, enterprise',
                        ),
                      ),
                      const SizedBox(height: 12),
                      TextField(
                        controller: _accountTypeController,
                        decoration: const InputDecoration(
                          labelText: 'Account Type',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.business),
                          hintText: 'e.g., business, personal',
                        ),
                      ),
                      const SizedBox(height: 12),
                      TextField(
                        controller: _signupDateController,
                        decoration: const InputDecoration(
                          labelText: 'Signup Date',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.calendar_today),
                          hintText: 'e.g., 2024-01-15',
                        ),
                      ),
                      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,
                    ),
                  ),
                ),
              ),

              const SizedBox(height: 24),

              // Auto-Localization Section
              Text(
                'Auto-Localized Themes',
                style: Theme.of(context).textTheme.titleMedium,
              ),
              const SizedBox(height: 8),
              Text(
                'Uses FlutterChatIOTheme.localized() for automatic translation',
                style: Theme.of(context).textTheme.bodySmall?.copyWith(
                      color: Theme.of(context).colorScheme.onSurfaceVariant,
                    ),
              ),
              const SizedBox(height: 12),

              // Device Locale (Auto-detect)
              _ThemeCard(
                title: 'Device Locale',
                subtitle: 'Auto-detect from device settings',
                color: Colors.deepPurple,
                onTap: () => _openChat(
                  FlutterChatIOTheme.localized(
                    Localizations.localeOf(context),
                    appBarColor: Colors.deepPurple,
                    outgoingMessageColor: Colors.deepPurple,
                    sendButtonColor: Colors.deepPurple,
                  ),
                ),
              ),

              // Chinese
              _ThemeCard(
                title: 'Chinese',
                subtitle: '中文本地化',
                color: Colors.red,
                onTap: () => _openChat(
                  FlutterChatIOTheme.localized(
                    const Locale('zh'),
                    appBarColor: Colors.red,
                    outgoingMessageColor: Colors.red,
                    sendButtonColor: Colors.red,
                  ),
                ),
              ),

              // Spanish
              _ThemeCard(
                title: 'Spanish',
                subtitle: 'Localización en español',
                color: Colors.orange,
                onTap: () => _openChat(
                  FlutterChatIOTheme.localized(
                    const Locale('es'),
                    appBarColor: Colors.orange,
                    outgoingMessageColor: Colors.orange,
                    sendButtonColor: Colors.orange,
                  ),
                ),
              ),

              // Arabic (RTL)
              _ThemeCard(
                title: 'Arabic (RTL)',
                subtitle: 'التوطين العربي',
                color: Colors.green,
                onTap: () => _openChat(
                  FlutterChatIOTheme.localized(
                    const Locale('ar'),
                    appBarColor: Colors.green,
                    outgoingMessageColor: Colors.green,
                    sendButtonColor: Colors.green,
                  ),
                  const Locale('ar'), // Enable RTL
                ),
              ),

              // Hindi
              _ThemeCard(
                title: 'Hindi',
                subtitle: 'हिंदी स्थानीयकरण',
                color: Colors.amber.shade800,
                onTap: () => _openChat(
                  FlutterChatIOTheme.localized(
                    const Locale('hi'),
                    appBarColor: Colors.amber.shade800,
                    outgoingMessageColor: Colors.amber.shade800,
                    sendButtonColor: Colors.amber.shade800,
                  ),
                ),
              ),

              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,
              ),
            ),
          ],
        ),
      );
}
8
likes
140
points
419
downloads

Publisher

unverified uploader

Weekly Downloads

Live customer support for Flutter apps with Slack integration. Users chat in-app, your team responds in Slack.

Homepage

Topics

#chat #customer-support #slack #live-chat #helpdesk

Documentation

Documentation
API reference

License

BSD-3-Clause (license)

Dependencies

device_info_plus, flutter, flutter_chat_core, flutter_chat_ui, http, http_parser, image_picker, uuid, web_socket_channel

More

Packages that depend on flutter_chat_io