import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../services/chat_service.dart'; import '../services/reverb_socket_service.dart'; import '../services/dio_client.dart'; import '../providers/chat_unread_provider.dart'; class ChatScreen extends StatefulWidget { const ChatScreen({super.key}); @override State createState() => _ChatScreenState(); } class _ChatScreenState extends State { final TextEditingController _messageCtrl = TextEditingController(); final ScrollController _scrollCtrl = ScrollController(); late ChatService _chatService; final ReverbSocketService _socket = ReverbSocketService(); int? ticketId; List> messages = []; bool isLoading = true; // ============================ // INIT STATE // ============================ @override void initState() { super.initState(); _chatService = ChatService(DioClient.getInstance(context)); // 🔔 Mark chat as OPEN (important) WidgetsBinding.instance.addPostFrameCallback((_) { context.read().setChatOpen(true); }); _initChat(); } // ============================ // INIT CHAT // ============================ Future _initChat() async { // 1️⃣ Start chat final ticketRes = await _chatService.startChat(); ticketId = ticketRes['ticket']['id']; // 2️⃣ Load messages final msgs = await _chatService.getMessages(ticketId!); messages = List>.from(msgs); // 3️⃣ Realtime socket await _socket.connect( context: context, ticketId: ticketId!, onMessage: (msg) { if (!mounted) return; setState(() => messages.add(msg)); _scrollToBottom(); }, onAdminMessage: () { if (!mounted) { context.read().increment(); } }, ); if (!mounted) return; setState(() => isLoading = false); _scrollToBottom(); } // ============================ // SCROLL // ============================ void _scrollToBottom() { WidgetsBinding.instance.addPostFrameCallback((_) { if (_scrollCtrl.hasClients) { _scrollCtrl.jumpTo(_scrollCtrl.position.maxScrollExtent); } }); } // ============================ // SEND MESSAGE // ============================ Future _sendMessage() async { final text = _messageCtrl.text.trim(); if (text.isEmpty) return; _messageCtrl.clear(); await _chatService.sendMessage( ticketId!, message: text, ); } // ============================ // DISPOSE // ============================ @override void dispose() { // 🔕 Mark chat CLOSED context.read().setChatOpen(false); _socket.disconnect(); _messageCtrl.dispose(); _scrollCtrl.dispose(); super.dispose(); } // ============================ // UI // ============================ @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Support Chat")), body: isLoading ? const Center(child: CircularProgressIndicator()) : Column( children: [ Expanded(child: _buildMessages()), _buildInput(), ], ), ); } Widget _buildMessages() { return ListView.builder( controller: _scrollCtrl, padding: const EdgeInsets.all(12), itemCount: messages.length, itemBuilder: (_, index) { final msg = messages[index]; final isUser = msg['sender_type'] == 'App\\Models\\User'; return Align( alignment: isUser ? Alignment.centerRight : Alignment.centerLeft, child: Container( margin: const EdgeInsets.symmetric(vertical: 4), padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: isUser ? Colors.blue : Colors.grey.shade300, borderRadius: BorderRadius.circular(12), ), child: Text( msg['message'] ?? '', style: TextStyle( color: isUser ? Colors.white : Colors.black, ), ), ), ); }, ); } Widget _buildInput() { return SafeArea( child: Row( children: [ Expanded( child: TextField( controller: _messageCtrl, decoration: const InputDecoration(hintText: "Type message"), ), ), IconButton( icon: const Icon(Icons.send), onPressed: _sendMessage, ), ], ), ); } }