import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/constants.dart'; import '../../core/exceptions.dart'; import '../../providers/chat_provider.dart'; class ConversationsListScreen extends ConsumerWidget { const ConversationsListScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final convsAsync = ref.watch(conversationsProvider); return Scaffold( body: convsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (_, _) => Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.cloud_off, size: 48), const SizedBox(height: 12), const Text('Could not load conversations.'), const SizedBox(height: 4), TextButton( onPressed: () => ref.invalidate(conversationsProvider), child: const Text('Retry'), ), ], ), ), data: (convs) { if (convs.isEmpty) { return const Center( child: Text('No conversations yet. Tap + to start one.')); } return RefreshIndicator( onRefresh: () => ref.refresh(conversationsProvider.future), child: ListView.separated( itemCount: convs.length, separatorBuilder: (_, _) => const Divider(height: 1), itemBuilder: (context, i) { final conv = convs[i]; return ListTile( leading: const Icon(Icons.chat_bubble_outline), title: Text( conv.title.isNotEmpty ? conv.title : 'New conversation', ), subtitle: Text( conv.updatedAt.toLocal().toString().substring(0, 16), style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), onTap: () => context.push( Routes.chat.replaceFirst(':id', '${conv.id}'), ), onLongPress: () async { final confirm = await showDialog( context: context, builder: (dialogContext) => AlertDialog( title: const Text('Delete conversation?'), content: Text( conv.title.isNotEmpty ? conv.title : 'New conversation', ), actions: [ TextButton( onPressed: () => Navigator.pop(dialogContext, false), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.pop(dialogContext, true), child: const Text('Delete'), ), ], ), ); if (confirm == true) { await ref .read(conversationsProvider.notifier) .delete(conv.id); } }, ); }, ), ); }, ), floatingActionButton: FloatingActionButton( heroTag: 'chat_fab', onPressed: () => _newConversation(context, ref), child: const Icon(Icons.add), ), ); } Future _newConversation(BuildContext context, WidgetRef ref) async { try { final conv = await ref.read(conversationsProvider.notifier).create(''); if (context.mounted) { context.push(Routes.chat.replaceFirst(':id', '${conv.id}')); } } on AppException catch (e) { if (context.mounted) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(e.message))); } } } }