flutter_gen_ai_chat_ui 1.1.5 copy "flutter_gen_ai_chat_ui: ^1.1.5" to clipboard
flutter_gen_ai_chat_ui: ^1.1.5 copied to clipboard

A Flutter package that provides a customizable chat UI for AI applications, featuring streaming responses, code highlighting, and markdown support.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_gen_ai_chat_ui/flutter_gen_ai_chat_ui.dart';
import 'package:dash_chat_2/dash_chat_2.dart';
import 'package:google_fonts/google_fonts.dart';

import 'custom_styling_example.dart';
import 'detailed_example.dart';
import 'markdown_example.dart';
import 'pagination_example.dart';
import 'streaming_example.dart';
import 'simple_chat_screen.dart';

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _isDark = false;

  void toggleTheme() {
    setState(() {
      _isDark = !_isDark;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AI Chat Demo',
      themeMode: _isDark ? ThemeMode.dark : ThemeMode.light,
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4),
          brightness: Brightness.light,
        ).copyWith(
          surface: Colors.white,
        ),
        textTheme: GoogleFonts.interTextTheme(),
        appBarTheme: const AppBarTheme(
          centerTitle: true,
          elevation: 0,
          scrolledUnderElevation: 0,
        ),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4),
          brightness: Brightness.dark,
        ).copyWith(
          surface: const Color(0xFF1A1A1A),
        ),
        textTheme: GoogleFonts.interTextTheme(ThemeData.dark().textTheme),
        appBarTheme: const AppBarTheme(
          centerTitle: true,
          elevation: 0,
          scrolledUnderElevation: 0,
        ),
      ),
      home: ExamplesNavigator(onThemeToggle: toggleTheme, isDark: _isDark),
    );
  }
}

class ExamplesNavigator extends StatefulWidget {
  const ExamplesNavigator({
    super.key,
    required this.onThemeToggle,
    required this.isDark,
  });

  final VoidCallback onThemeToggle;
  final bool isDark;

  @override
  State<ExamplesNavigator> createState() => _ExamplesNavigatorState();
}

class _ExamplesNavigatorState extends State<ExamplesNavigator> {
  int _selectedIndex = 0;

  static final List<Widget> _pages = [
    const MyHomePage(title: 'Basic Example'),
    const CustomStylingExample(),
    const DetailedExample(),
    const MarkdownExample(),
    const PaginationExample(),
    const StreamingExample(),
    const SimpleChatScreen(),
  ];

  static const List<String> _titles = [
    'Basic Example',
    'Custom Styling',
    'Detailed Example',
    'Markdown Example',
    'Pagination Example',
    'Streaming Example',
    'Simple Chat',
  ];

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final colorScheme = theme.colorScheme;

    return Theme(
      data: theme.copyWith(
        colorScheme: colorScheme.copyWith(
          primary: const Color(0xFF6750A4),
          secondary: const Color(0xFF7B61FF),
        ),
      ),
      child: Scaffold(
        appBar: AppBar(
          backgroundColor: colorScheme.surface,
          title: Text(
            _titles[_selectedIndex],
            style: GoogleFonts.inter(
              fontSize: 20,
              fontWeight: FontWeight.w600,
              letterSpacing: -0.5,
            ),
          ),
          leading: Builder(
            builder: (context) => IconButton(
              icon: const Icon(Icons.menu_rounded),
              onPressed: () => Scaffold.of(context).openDrawer(),
            ),
          ),
          actions: [
            Padding(
              padding: const EdgeInsets.only(right: 8.0),
              child: IconButton(
                icon: Icon(
                  widget.isDark
                      ? Icons.light_mode_rounded
                      : Icons.dark_mode_rounded,
                  color: colorScheme.onSurface,
                ),
                style: IconButton.styleFrom(
                  backgroundColor:
                      colorScheme.surfaceContainerHighest.withOpacity(0.3),
                ),
                onPressed: widget.onThemeToggle,
              ),
            ),
          ],
        ),
        body: _pages[_selectedIndex],
        drawer: NavigationDrawer(
          selectedIndex: _selectedIndex,
          onDestinationSelected: (index) {
            setState(() {
              _selectedIndex = index;
            });
            Navigator.pop(context); // Close drawer after selection
          },
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(28, 16, 16, 10),
              child: Text(
                'Examples',
                style: TextStyle(
                  color: colorScheme.primary,
                  fontSize: 16,
                  fontWeight: FontWeight.w600,
                  letterSpacing: 0.15,
                ),
              ),
            ),
            const Divider(indent: 28, endIndent: 28),
            ...List.generate(
              _titles.length,
              (index) => NavigationDrawerDestination(
                icon: Icon(
                  index == _selectedIndex
                      ? Icons.chat_rounded
                      : Icons.chat_outlined,
                ),
                label: Text(_titles[index]),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ChatMessagesController _controller = ChatMessagesController();
  final ChatUser _currentUser = ChatUser(id: '1', firstName: 'User');
  final ChatUser _aiUser = ChatUser(id: '2', firstName: 'AI');
  bool _isLoading = false;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final colorScheme = theme.colorScheme;

    return Container(
      decoration: BoxDecoration(
        color: colorScheme.surface,
      ),
      child: AiChatWidget(
        config: AiChatConfig(
          userName: 'User',
          aiName: 'AI Assistant',
          hintText: 'Type your message...',
          enableAnimation: true,
          showTimestamp: true,
          exampleQuestions: [
            ChatExample(
              question: 'What can you help me with?',
              onTap: (controller) {
                controller.handleExampleQuestion(
                  'What can you help me with?',
                  _currentUser,
                  _aiUser,
                );
              },
            ),
            ChatExample(
              question: 'Tell me about your capabilities',
              onTap: (controller) {
                controller.handleExampleQuestion(
                  'Tell me about your capabilities',
                  _currentUser,
                  _aiUser,
                );
              },
            ),
            ChatExample(
              question: 'How do I get started?',
              onTap: (controller) {
                controller.handleExampleQuestion(
                  'How do I get started?',
                  _currentUser,
                  _aiUser,
                );
              },
            ),
          ],
        ),
        currentUser: _currentUser,
        aiUser: _aiUser,
        controller: _controller,
        isLoading: _isLoading,
        loadingIndicator: LoadingWidget(
          texts: const [
            'AI is thinking...',
            'Processing your message...',
            'Generating response...',
            'Almost there...',
          ],
          interval: const Duration(seconds: 2),
          textStyle: TextStyle(
            color: colorScheme.onSurfaceVariant,
            fontSize: 14,
            fontWeight: FontWeight.w500,
            letterSpacing: 0.1,
          ),
          shimmerBaseColor:
              colorScheme.surfaceContainerHighest.withOpacity(0.5),
          shimmerHighlightColor: colorScheme.surface,
        ),
        onSendMessage: (ChatMessage message) async {
          // Add the user's message to the chat
          _controller.addMessage(message);

          // Start loading state
          setState(() {
            _isLoading = true;
          });

          // Simulate AI response after a delay
          await Future.delayed(const Duration(seconds: 2));

          // Add AI response
          _controller.addMessage(
            ChatMessage(
              text:
                  'I received your message: "${message.text}"\n\nThis is a simulated response that takes 2 seconds to appear, showing the loading indicator in the meantime.',
              user: _aiUser,
              createdAt: DateTime.now(),
            ),
          );

          // Stop loading state
          setState(() {
            _isLoading = false;
          });
        },
      ),
    );
  }
}

class _ActionButton extends StatelessWidget {
  const _ActionButton({
    required this.onPressed,
    required this.icon,
    required this.label,
  });

  final VoidCallback onPressed;
  final IconData icon;
  final String label;

  @override
  Widget build(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;
    final isSmallScreen = MediaQuery.of(context).size.width < 600;

    return Expanded(
      child: Material(
        color: colorScheme.surfaceContainerHighest.withOpacity(0.3),
        borderRadius: BorderRadius.circular(12),
        child: InkWell(
          onTap: onPressed,
          borderRadius: BorderRadius.circular(12),
          child: Container(
            padding: EdgeInsets.all(isSmallScreen ? 12 : 16),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  icon,
                  size: 24,
                  color: colorScheme.primary,
                ),
                const SizedBox(height: 8),
                Text(
                  label,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: colorScheme.onSurface,
                    fontSize: isSmallScreen ? 12 : 13,
                    fontWeight: FontWeight.w500,
                    letterSpacing: 0.1,
                    height: 1.2,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
53
likes
0
points
1.23k
downloads

Publisher

verified publisherdilacode.com

Weekly Downloads

A Flutter package that provides a customizable chat UI for AI applications, featuring streaming responses, code highlighting, and markdown support.

Repository (GitHub)
View/report issues

Documentation

Documentation

License

unknown (license)

Dependencies

dash_chat_2, flutter, flutter_markdown, google_fonts, intl, provider, shimmer, url_launcher

More

Packages that depend on flutter_gen_ai_chat_ui