heyllo_ai_chatbot 0.0.2 copy "heyllo_ai_chatbot: ^0.0.2" to clipboard
heyllo_ai_chatbot: ^0.0.2 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
0
points
181
downloads

Publisher

verified publisherheyllo.co

Weekly Downloads

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

Homepage

Documentation

Documentation

License

unknown (license)

Dependencies

flutter, flutter_client_sse, http, mockito, plugin_platform_interface

More

Packages that depend on heyllo_ai_chatbot