import 'package:flutter/material.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/constants.dart'; import '../../core/theme.dart'; import '../../providers/chat_provider.dart'; import 'chat_screen.dart'; class ConversationsTabScreen extends ConsumerStatefulWidget { const ConversationsTabScreen({super.key}); @override ConsumerState createState() => _ConversationsTabScreenState(); } class _ConversationsTabScreenState extends ConsumerState { int? _selectedConvId; Future _createConversation() async { final conv = await ref.read(conversationsProvider.notifier).create(''); if (!mounted) return; final isWide = MediaQuery.of(context).size.width >= 600; if (isWide) { setState(() => _selectedConvId = conv.id); } else { context.push(Routes.chat.replaceFirst(':id', '${conv.id}')); } } void _openConversation(int id) { final isWide = MediaQuery.of(context).size.width >= 600; if (isWide) { setState(() => _selectedConvId = id); } else { context.push(Routes.chat.replaceFirst(':id', '$id')); } } Future _confirmDelete(int id, String title) async { final ok = await showDialog( context: context, builder: (dialogContext) => AlertDialog( title: const Text('Delete conversation?'), content: Text('"$title" will be permanently deleted.'), actions: [ TextButton( onPressed: () => Navigator.pop(dialogContext, false), child: const Text('Cancel')), FilledButton( onPressed: () => Navigator.pop(dialogContext, true), style: FilledButton.styleFrom( backgroundColor: Theme.of(dialogContext).extension()!.destructive, ), child: const Text('Delete')), ], ), ); if (ok == true) { await ref.read(conversationsProvider.notifier).delete(id); if (_selectedConvId == id) { setState(() => _selectedConvId = null); } } } @override Widget build(BuildContext context) { final isWide = MediaQuery.of(context).size.width >= 600; final theme = Theme.of(context); final convsAsync = ref.watch(conversationsProvider); final listPanel = Scaffold( appBar: AppBar( title: Text('Chat', style: theme.textTheme.titleLarge), actions: [ IconButton( icon: const Icon(LucideIcons.plus), tooltip: 'New conversation', onPressed: _createConversation, ), ], ), body: convsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Error: $e')), data: (convs) { if (convs.isEmpty) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(LucideIcons.messageCircle, size: 48, color: theme.colorScheme.onSurfaceVariant), const SizedBox(height: 16), Text('No conversations yet', style: theme.textTheme.titleMedium), const SizedBox(height: 8), FilledButton.icon( icon: const Icon(LucideIcons.plus), label: const Text('Start a conversation'), onPressed: _createConversation, ), ], ), ); } return RefreshIndicator( onRefresh: () => ref.read(conversationsProvider.notifier).refresh(), child: ListView.builder( itemCount: convs.length, itemBuilder: (ctx, i) { final c = convs[i]; final selected = isWide && c.id == _selectedConvId; return ListTile( leading: const Icon(LucideIcons.messageCircle), title: Text( c.title.isEmpty ? 'New conversation' : c.title, maxLines: 1, overflow: TextOverflow.ellipsis), subtitle: Text( _relativeTime(c.updatedAt), style: theme.textTheme.labelSmall, ), selected: selected, trailing: IconButton( icon: const Icon(LucideIcons.trash2), onPressed: () => _confirmDelete(c.id, c.title), ), onTap: () => _openConversation(c.id), ); }, ), ); }, ), ); if (!isWide) return listPanel; return Row( children: [ SizedBox( width: 320, child: listPanel, ), const VerticalDivider(width: 1), Expanded( child: _selectedConvId != null ? ChatScreen( key: ValueKey(_selectedConvId), conversationId: _selectedConvId!, ) : Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(LucideIcons.messageCircle, size: 48, color: theme.colorScheme.onSurfaceVariant), const SizedBox(height: 16), Text('Select a conversation', style: theme.textTheme.titleMedium), ], ), ), ), ], ); } } String _relativeTime(DateTime dt) { final diff = DateTime.now().difference(dt); if (diff.inMinutes < 1) return 'just now'; if (diff.inHours < 1) return '${diff.inMinutes}m ago'; if (diff.inDays < 1) return '${diff.inHours}h ago'; if (diff.inDays < 7) return '${diff.inDays}d ago'; return '${dt.day}/${dt.month}/${dt.year}'; }