heyllo_ai_chatbot 0.0.2+1 copy "heyllo_ai_chatbot: ^0.0.2+1" to clipboard
heyllo_ai_chatbot: ^0.0.2+1 copied to clipboard

An AI powered Flutter chatbot plugin for integrating into your flutter app.

example/lib/main.dart

// example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:heyllo_ai_chatbot/chat_plugin.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Chat Plugin Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const AdvancedChatDemo(),
    );
  }
}

class AdvancedChatDemo extends StatefulWidget {
  const AdvancedChatDemo({super.key});

  @override
  State<AdvancedChatDemo> createState() => _AdvancedChatDemoState();
}

class _AdvancedChatDemoState extends State<AdvancedChatDemo> {
  static const domain = 'https://heyllo.co';
  static const chatbotId =
      'zqrfsxffb2fkjllyrlj73ddq'; // Replace with your actual chatbot ID

  // Theme customization options
  Color _userBubbleColor = Colors.blue;
  Color _botBubbleColor = const Color(0xFFE1E1E1);
  Color _userTextColor = Colors.white;
  Color _botTextColor = Colors.black;
  double _bubbleRadius = 16.0;
  bool _showAvatars = true;
  bool _showTimestamps = true;
  bool _usePresets = false;
  String _inputPlaceholder = 'Type a message...';

  // Theme presets
  final Map<String, ChatTheme> _presets = {
    'Default': const ChatTheme(),
    'Dark Mode': const ChatTheme(
      userBubbleColor: Colors.indigo,
      botBubbleColor: Color(0xFF2D2D2D),
      userTextStyle: TextStyle(color: Colors.white),
      botTextStyle: TextStyle(color: Colors.white),
      backgroundColor: Color(0xFF121212),
      loadingIndicatorColor: Colors.white,
      sendButtonColor: Colors.indigo,
    ),
    'Bubbly': ChatTheme(
      userBubbleColor: Colors.pink,
      botBubbleColor: Colors.purple.shade50,
      userTextStyle: const TextStyle(color: Colors.white),
      botTextStyle: const TextStyle(color: Colors.purple),
      userBubbleBorderRadius: BorderRadius.circular(24),
      botBubbleBorderRadius: BorderRadius.circular(24),
      sendButtonColor: Colors.pink,
    ),
    'Professional': ChatTheme(
      userBubbleColor: Colors.blueGrey.shade700,
      botBubbleColor: Colors.blueGrey.shade50,
      userTextStyle: const TextStyle(color: Colors.white),
      botTextStyle: TextStyle(color: Colors.blueGrey.shade700),
      userBubbleBorderRadius: BorderRadius.circular(8),
      botBubbleBorderRadius: BorderRadius.circular(8),
      sendButtonColor: Colors.blueGrey.shade700,
      inputDecoration: InputDecoration(
        hintText: 'Enter your message...',
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(8),
          borderSide: BorderSide(color: Colors.blueGrey.shade200),
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(8),
          borderSide: BorderSide(color: Colors.blueGrey.shade700, width: 2),
        ),
      ),
    ),
    'Minimalist': const ChatTheme(
      userBubbleColor: Colors.black,
      botBubbleColor: Color(0xFFF5F5F5),
      userTextStyle: TextStyle(color: Colors.white),
      botTextStyle: TextStyle(color: Colors.black),
      sendButtonColor: Colors.black,
      inputDecoration: InputDecoration(
        hintText: 'Message',
        border: UnderlineInputBorder(),
      ),
    ),
  };

  String _selectedPreset = 'Default';

  @override
  Widget build(BuildContext context) {
    // Build current theme based on customization options
    final ChatTheme currentTheme = _usePresets
        ? _presets[_selectedPreset]!
        : ChatTheme(
            userBubbleColor: _userBubbleColor,
            botBubbleColor: _botBubbleColor,
            userTextStyle: TextStyle(color: _userTextColor),
            botTextStyle: TextStyle(color: _botTextColor),
            userBubbleBorderRadius: BorderRadius.circular(_bubbleRadius),
            botBubbleBorderRadius: BorderRadius.circular(_bubbleRadius),
            inputDecoration: InputDecoration(
              hintText: _inputPlaceholder,
              border: const OutlineInputBorder(),
            ),
          );

    return Scaffold(
      appBar: AppBar(
        title: const Text('Chat Theming Demo'),
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {
              _showThemeEditor();
            },
          ),
        ],
      ),
      body: Column(
        children: [
          // Theme selector chips
          if (_usePresets)
            SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: Row(
                children: _presets.keys.map((String presetName) {
                  return Padding(
                    padding: const EdgeInsets.only(right: 8),
                    child: ChoiceChip(
                      label: Text(presetName),
                      selected: _selectedPreset == presetName,
                      onSelected: (bool selected) {
                        if (selected) {
                          setState(() {
                            _selectedPreset = presetName;
                          });
                        }
                      },
                    ),
                  );
                }).toList(),
              ),
            ),

          // Chat widget
          Expanded(
            child: ChatWidget(
              domain: domain,
              chatbotId: chatbotId,
              theme: currentTheme,
              showTimestamps: _showTimestamps,
              initialMessages: [
                ChatMessage(
                  message: 'Hello! How can I help you today?',
                  isUser: false,
                  timestamp:
                      DateTime.now().subtract(const Duration(minutes: 5)),
                ),
              
              ],
              onError: (error) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Error: $error')),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  void _showThemeEditor() {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      builder: (context) {
        return StatefulBuilder(
          builder: (context, setModalState) {
            return Container(
              padding: const EdgeInsets.all(16),
              height: MediaQuery.of(context).size.height * 0.8,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'Theme Editor',
                    style: TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 16),

                  // Toggle between presets and custom
                  Row(
                    children: [
                      const Text('Use preset themes:'),
                      const Spacer(),
                      Switch(
                        value: _usePresets,
                        onChanged: (value) {
                          setModalState(() {
                            _usePresets = value;
                          });
                          setState(() {
                            _usePresets = value;
                          });
                        },
                      ),
                    ],
                  ),

                  const Divider(),

                  Expanded(
                    child: _usePresets
                        ? _buildPresetSelector(setModalState)
                        : _buildCustomThemeEditor(setModalState),
                  ),

                  // Apply button
                  SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                      onPressed: () {
                        Navigator.pop(context);
                      },
                      child: const Text('Apply Theme'),
                    ),
                  ),
                ],
              ),
            );
          },
        );
      },
    );
  }

  Widget _buildPresetSelector(StateSetter setModalState) {
    return ListView(
      children: _presets.entries.map((entry) {
        final String name = entry.key;
        final ChatTheme theme = entry.value;

        return Card(
          margin: const EdgeInsets.only(bottom: 16),
          child: ListTile(
            title: Text(name),
            leading: CircleAvatar(
              backgroundColor: theme.userBubbleColor ?? Colors.blue,
            ),
            trailing: Radio<String>(
              value: name,
              groupValue: _selectedPreset,
              onChanged: (String? value) {
                setModalState(() {
                  _selectedPreset = value!;
                });
                setState(() {
                  _selectedPreset = value!;
                });
              },
            ),
            onTap: () {
              setModalState(() {
                _selectedPreset = name;
              });
              setState(() {
                _selectedPreset = name;
              });
            },
          ),
        );
      }).toList(),
    );
  }

  Widget _buildCustomThemeEditor(StateSetter setModalState) {
    return SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text('User Bubble',
              style: TextStyle(fontWeight: FontWeight.bold)),
          const SizedBox(height: 8),

          // User bubble color
          Row(
            children: [
              const Text('Color:'),
              const SizedBox(width: 16),
              GestureDetector(
                onTap: () async {
                  final Color? pickedColor = await showColorPicker(
                    context,
                    _userBubbleColor,
                  );
                  if (pickedColor != null) {
                    setModalState(() {
                      _userBubbleColor = pickedColor;
                    });
                    setState(() {
                      _userBubbleColor = pickedColor;
                    });
                  }
                },
                child: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    color: _userBubbleColor,
                    shape: BoxShape.circle,
                    border: Border.all(
                      color: Colors.grey,
                      width: 1,
                    ),
                  ),
                ),
              ),
              const SizedBox(width: 16),

              // User text color
              const Text('Text:'),
              const SizedBox(width: 16),
              GestureDetector(
                onTap: () async {
                  final Color? pickedColor = await showColorPicker(
                    context,
                    _userTextColor,
                  );
                  if (pickedColor != null) {
                    setModalState(() {
                      _userTextColor = pickedColor;
                    });
                    setState(() {
                      _userTextColor = pickedColor;
                    });
                  }
                },
                child: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    color: _userTextColor,
                    shape: BoxShape.circle,
                    border: Border.all(
                      color: Colors.grey,
                      width: 1,
                    ),
                  ),
                ),
              ),
            ],
          ),

          const SizedBox(height: 24),
          const Text('Bot Bubble',
              style: TextStyle(fontWeight: FontWeight.bold)),
          const SizedBox(height: 8),

          // Bot bubble color
          Row(
            children: [
              const Text('Color:'),
              const SizedBox(width: 16),
              GestureDetector(
                onTap: () async {
                  final Color? pickedColor = await showColorPicker(
                    context,
                    _botBubbleColor,
                  );
                  if (pickedColor != null) {
                    setModalState(() {
                      _botBubbleColor = pickedColor;
                    });
                    setState(() {
                      _botBubbleColor = pickedColor;
                    });
                  }
                },
                child: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    color: _botBubbleColor,
                    shape: BoxShape.circle,
                    border: Border.all(
                      color: Colors.grey,
                      width: 1,
                    ),
                  ),
                ),
              ),
              const SizedBox(width: 16),

              // Bot text color
              const Text('Text:'),
              const SizedBox(width: 16),
              GestureDetector(
                onTap: () async {
                  final Color? pickedColor = await showColorPicker(
                    context,
                    _botTextColor,
                  );
                  if (pickedColor != null) {
                    setModalState(() {
                      _botTextColor = pickedColor;
                    });
                    setState(() {
                      _botTextColor = pickedColor;
                    });
                  }
                },
                child: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    color: _botTextColor,
                    shape: BoxShape.circle,
                    border: Border.all(
                      color: Colors.grey,
                      width: 1,
                    ),
                  ),
                ),
              ),
            ],
          ),

          const SizedBox(height: 24),

          // Bubble corner radius
          Row(
            children: [
              const Text('Bubble radius:'),
              const SizedBox(width: 16),
              Expanded(
                child: Slider(
                  value: _bubbleRadius,
                  min: 0,
                  max: 24,
                  divisions: 24,
                  label: _bubbleRadius.round().toString(),
                  onChanged: (value) {
                    setModalState(() {
                      _bubbleRadius = value;
                    });
                    setState(() {
                      _bubbleRadius = value;
                    });
                  },
                ),
              ),
              Text('${_bubbleRadius.toInt()}'),
            ],
          ),

          // Input placeholder
          const SizedBox(height: 16),
          const Text('Input placeholder:'),
          const SizedBox(height: 8),
          TextFormField(
            initialValue: _inputPlaceholder,
            decoration: const InputDecoration(
              border: OutlineInputBorder(),
              hintText: 'Enter placeholder text',
            ),
            onChanged: (value) {
              setModalState(() {
                _inputPlaceholder = value;
              });
              setState(() {
                _inputPlaceholder = value;
              });
            },
          ),

          const SizedBox(height: 16),

          // Toggle options
          CheckboxListTile(
            title: const Text('Show avatars'),
            value: _showAvatars,
            onChanged: (value) {
              setModalState(() {
                _showAvatars = value!;
              });
              setState(() {
                _showAvatars = value!;
              });
            },
          ),

          CheckboxListTile(
            title: const Text('Show timestamps'),
            value: _showTimestamps,
            onChanged: (value) {
              setModalState(() {
                _showTimestamps = value!;
              });
              setState(() {
                _showTimestamps = value!;
              });
            },
          ),
        ],
      ),
    );
  }

  Future<Color?> showColorPicker(
      BuildContext context, Color initialColor) async {
    Color pickedColor = initialColor;

    await showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: const Text('Pick a color'),
          content: SingleChildScrollView(
            child: ColorPicker(
              pickerColor: initialColor,
              onColorChanged: (color) {
                pickedColor = color;
              },
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('Cancel'),
              onPressed: () {
                Navigator.of(context).pop();
                pickedColor = initialColor;
              },
            ),
            TextButton(
              child: const Text('Select'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );

    return pickedColor;
  }
}

/// Simple color picker for demonstration purposes
/// In a real app, you might want to use a package like flutter_colorpicker
class ColorPicker extends StatefulWidget {
  final Color pickerColor;
  final ValueChanged<Color> onColorChanged;

  const ColorPicker({
    super.key,
    required this.pickerColor,
    required this.onColorChanged,
  });

  @override
  State<ColorPicker> createState() => _ColorPickerState();
}

class _ColorPickerState extends State<ColorPicker> {
  late HSVColor _currentHsvColor;

  @override
  void initState() {
    super.initState();
    _currentHsvColor = HSVColor.fromColor(widget.pickerColor);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        // Hue slider
        const Text('Hue'),
        Slider(
          value: _currentHsvColor.hue,
          min: 0,
          max: 360,
          onChanged: (value) {
            setState(() {
              _currentHsvColor = _currentHsvColor.withHue(value);
              widget.onColorChanged(_currentHsvColor.toColor());
            });
          },
        ),

        // Saturation slider
        const Text('Saturation'),
        Slider(
          value: _currentHsvColor.saturation,
          min: 0,
          max: 1,
          onChanged: (value) {
            setState(() {
              _currentHsvColor = _currentHsvColor.withSaturation(value);
              widget.onColorChanged(_currentHsvColor.toColor());
            });
          },
        ),

        // Value slider
        const Text('Value (Brightness)'),
        Slider(
          value: _currentHsvColor.value,
          min: 0,
          max: 1,
          onChanged: (value) {
            setState(() {
              _currentHsvColor = _currentHsvColor.withValue(value);
              widget.onColorChanged(_currentHsvColor.toColor());
            });
          },
        ),

        // Preview
        const SizedBox(height: 10),
        Container(
          width: 50,
          height: 50,
          decoration: BoxDecoration(
            color: _currentHsvColor.toColor(),
            shape: BoxShape.circle,
            border: Border.all(color: Colors.grey),
          ),
        ),
      ],
    );
  }
}
3
likes
150
points
181
downloads

Publisher

verified publisherheyllo.co

Weekly Downloads

An AI powered Flutter chatbot plugin for integrating into your flutter app.

Homepage

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter, flutter_client_sse, http, mockito, plugin_platform_interface

More

Packages that depend on heyllo_ai_chatbot