import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../controllers/conversations_controller.dart'; import '../services/whatsapp_service.dart'; import '../theme/app_theme.dart'; import '../widgets/conversation_tile.dart'; import 'qr_screen.dart'; import 'chat_screen.dart'; import '../models/conversation_model.dart'; class ConversationsScreen extends StatelessWidget { const ConversationsScreen({super.key}); @override Widget build(BuildContext context) { final svc = Get.find(); final ctrl = Get.put(ConversationsController()); final isDark = AppTheme.isDark(context); return Scaffold( backgroundColor: AppTheme.background(context), appBar: _buildAppBar(context, ctrl), body: Obx(() { // Not connected if (svc.status.value == WsStatus.disconnected || svc.status.value == WsStatus.connecting) { return _buildConnecting(context); } // QR Code needed if (svc.qrData.value != null) { return const QrView(); } // Loading conversations if (ctrl.isLoading.value && ctrl.conversations.isEmpty) { return Center( child: CircularProgressIndicator(color: AppTheme.primary), ); } // Error if (ctrl.errorMessage.value != null && ctrl.conversations.isEmpty) { return _buildError(context, ctrl); } // Empty if (ctrl.conversations.isEmpty) { return _buildEmpty(context); } // List return _buildList(context, ctrl); }), ); } PreferredSizeWidget _buildAppBar( BuildContext context, ConversationsController ctrl) { final searching = false.obs; final isDark = AppTheme.isDark(context); return AppBar( backgroundColor: AppTheme.surface(context), elevation: 0, title: Obx(() => searching.value ? TextField( autofocus: true, style: TextStyle(color: isDark ? Colors.white : Colors.white), cursorColor: Colors.white, decoration: InputDecoration( hintText: 'Search...', border: InputBorder.none, hintStyle: TextStyle( color: Colors.white.withOpacity(0.7)), ), onChanged: ctrl.search, ) : const Text( 'WhatsApp', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, ), )), actions: [ Obx(() => IconButton( icon: Icon( searching.value ? Icons.close : Icons.search, color: isDark ? AppTheme.darkTextSecondary : Colors.white, ), onPressed: () { searching.value = !searching.value; if (!searching.value) ctrl.loadConversations(); }, )), IconButton( icon: Icon( Icons.more_vert, color: isDark ? AppTheme.darkTextSecondary : Colors.white, ), onPressed: () => _showOptionsMenu(context, ctrl), ), ], bottom: PreferredSize( preferredSize: const Size.fromHeight(1), child: Container( height: 1, color: isDark ? Colors.white.withOpacity(0.08) : Colors.white.withOpacity(0.15), ), ), ); } void _showOptionsMenu( BuildContext context, ConversationsController ctrl) { showMenu( context: context, position: const RelativeRect.fromLTRB(1000, 56, 0, 0), color: AppTheme.isDark(context) ? AppTheme.darkSurface : Colors.white, items: [ PopupMenuItem( onTap: ctrl.loadConversations, child: Text( 'Refresh', style: TextStyle(color: AppTheme.textPrimary(context)), ), ), ], ); } Widget _buildConnecting(BuildContext context) { final svc = Get.find(); return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(color: AppTheme.primary), const SizedBox(height: 16), Text( 'Connecting to server...', style: TextStyle(color: AppTheme.textSecondary(context)), ), const SizedBox(height: 24), ElevatedButton( onPressed: () { svc.status.value = WsStatus.disconnected; svc.connect(); }, style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primary, ), child: const Text( 'Retry Now', style: TextStyle(color: Colors.white), ), ), ], ), ); } Widget _buildError( BuildContext context, ConversationsController ctrl) => Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.error_outline, color: Colors.redAccent, size: 48), const SizedBox(height: 12), Text( ctrl.errorMessage.value ?? 'Error', style: TextStyle( color: AppTheme.textSecondary(context)), textAlign: TextAlign.center, ), const SizedBox(height: 16), ElevatedButton( onPressed: ctrl.loadConversations, style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primary), child: const Text('Retry', style: TextStyle(color: Colors.white)), ), ], ), ), ); Widget _buildEmpty(BuildContext context) => Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.chat_bubble_outline, size: 64, color: AppTheme.textSecondary(context).withOpacity(0.4)), const SizedBox(height: 16), Text( 'No conversations yet', style: TextStyle( color: AppTheme.textSecondary(context), fontSize: 16), ), ], ), ); Widget _buildList( BuildContext context, ConversationsController ctrl) { return RefreshIndicator( color: AppTheme.primary, backgroundColor: AppTheme.isDark(context) ? AppTheme.darkSurface : Colors.white, onRefresh: ctrl.loadConversations, child: ListView.separated( itemCount: ctrl.conversations.length, separatorBuilder: (_, __) => Divider( height: 1, thickness: 0.5, indent: 76, color: AppTheme.isDark(context) ? Colors.white.withOpacity(0.06) : Colors.black.withOpacity(0.08), ), itemBuilder: (_, i) { final chat = ctrl.conversations[i]; return ConversationTile( conversation: chat, onTap: () => _openChat(chat), ); }, ), ); } void _openChat(ConversationModel chat) { Get.to( () => ChatScreen(conversation: chat), transition: Transition.rightToLeft, ); } }