@@ -12,6 +12,7 @@ class ChatController extends ChangeNotifier {
1212 List <Conversation > inbox = [];
1313 List <Message > activeChat = [];
1414 List <dynamic > contactSearchResults = [];
15+
1516 String ? currentChatUserId;
1617 bool isPeerTyping = false ;
1718 bool isPeerOnline = false ;
@@ -22,9 +23,12 @@ class ChatController extends ChangeNotifier {
2223 _ws.stream? .listen (
2324 (rawFrame) {
2425 try {
25- _handleIncomingWebSocketEvent (jsonDecode (rawFrame));
26+ final decoded = jsonDecode (rawFrame);
27+ if (decoded is Map <String , dynamic >) {
28+ _handleIncomingWebSocketEvent (decoded);
29+ }
2630 } catch (e) {
27- debugPrint ("WebSocket stream payload error: $e " );
31+ debugPrint ("WebSocket payload error: $e " );
2832 }
2933 },
3034 onError: (err) => debugPrint ("WS Pipeline Error: $err " ),
@@ -36,18 +40,10 @@ class ChatController extends ChangeNotifier {
3640 Future <void > loadInbox () async {
3741 try {
3842 final res = await _api.getConversations ();
39- dynamic targetData;
40-
41- if (res.data is List ) {
42- targetData = res.data;
43- } else if (res.data is Map ) {
44- targetData = res.data['data' ] ?? res.data['conversations' ] ?? res.data;
45- }
43+ final targetList = _extractDataList (res.data, ['conversations' ]);
4644
47- if (targetData is List ) {
48- inbox = targetData.map ((json) => Conversation .fromJson (json)).toList ();
49- notifyListeners ();
50- }
45+ inbox = targetList.map ((json) => Conversation .fromJson (json)).toList ();
46+ notifyListeners ();
5147 } catch (e) {
5248 debugPrint ("Inbox read error: $e " );
5349 }
@@ -62,29 +58,23 @@ class ChatController extends ChangeNotifier {
6258
6359 try {
6460 final res = await _api.getChatHistory (targetUid);
65- dynamic targetData;
66-
67- if (res.data is List ) {
68- targetData = res.data;
69- } else if (res.data is Map ) {
70- targetData = res.data['data' ] ?? res.data['messages' ] ?? res.data;
71- }
61+ final targetList = _extractDataList (res.data, ['messages' ]);
7262
73- if (targetData is List ) {
74- activeChat = targetData
75- .map ((json) => Message .fromJson (json))
76- .toList ()
77- .reversed
78- .toList ();
79- }
63+ activeChat = targetList
64+ .map ((json) => Message .fromJson (json))
65+ .toList ()
66+ .reversed
67+ .toList ();
8068
8169 _ws.sendReadReceipt (targetId: targetUid);
8270 _ws.sendRequestStatus (targetId: targetUid);
71+
72+ notifyListeners ();
8373 await loadInbox ();
8474 } catch (e) {
8575 debugPrint ("Timeline tracking fail: $e " );
76+ notifyListeners ();
8677 }
87- notifyListeners ();
8878 }
8979
9080 Future <void > queryUsers (String term) async {
@@ -101,26 +91,15 @@ class ChatController extends ChangeNotifier {
10191 notifyListeners ();
10292 return ;
10393 }
94+
10495 isSearchLoading = true ;
10596 notifyListeners ();
10697
10798 try {
108- final res = await _api.searchUsers (cleanTerm);
109- if (res.data == null ) {
110- contactSearchResults = [];
111- } else if (res.data is List ) {
112- contactSearchResults = res.data;
113- } else if (res.data is Map ) {
114- if (res.data['data' ] != null && res.data['data' ] is List ) {
115- contactSearchResults = res.data['data' ];
116- } else if (res.data['users' ] != null && res.data['users' ] is List ) {
117- contactSearchResults = res.data['users' ];
118- } else {
119- contactSearchResults = [];
120- }
121- }
99+ final res = await _api.searchUsers (term);
100+ contactSearchResults = _extractDataList (res.data, ['users' ]);
122101 } catch (e) {
123- debugPrint ("User query pipeline failure: $e " );
102+ debugPrint ("User query failure: $e " );
124103 contactSearchResults.clear ();
125104 } finally {
126105 isSearchLoading = false ;
@@ -137,16 +116,15 @@ class ChatController extends ChangeNotifier {
137116 }
138117
139118 void sendTextMessage (String text) {
140- if (currentChatUserId == null || text.trim ().isEmpty) return ;
119+ final cleanContent = text.trim ();
120+ if (currentChatUserId == null || cleanContent.isEmpty) return ;
141121
142- final String clientMessageId =
143- "cli_${DateTime .now ().millisecondsSinceEpoch }" ;
144- final String targetId = currentChatUserId! ;
145- final String cleanContent = text.trim ();
122+ final targetId = currentChatUserId! ;
123+ final clientMessageId = "cli_${DateTime .now ().millisecondsSinceEpoch }" ;
146124
147125 _ws.sendChat (messageId: "" , targetId: targetId, content: cleanContent);
148126
149- final Message optimisticMsg = Message (
127+ final optimisticMsg = Message (
150128 id: clientMessageId,
151129 senderId: "me" ,
152130 receiverId: targetId,
@@ -157,6 +135,7 @@ class ChatController extends ChangeNotifier {
157135
158136 activeChat.add (optimisticMsg);
159137 notifyListeners ();
138+
160139 loadInbox ();
161140 }
162141
@@ -168,13 +147,14 @@ class ChatController extends ChangeNotifier {
168147
169148 void _handleIncomingWebSocketEvent (Map <String , dynamic > data) {
170149 final String ? type = data['type' ];
171- final String ? senderId =
172- data['sender_id' ] ?? data['sender' ] ?? data['receiver_id' ];
173-
174150 if (type == null ) return ;
175151
152+ final String ? senderId =
153+ data['sender_id' ] ?? data['sender' ] ?? data['receiver_id' ];
176154 final String ? cleanSender = senderId? .trim ().toLowerCase ();
177155 final String ? cleanCurrentChat = currentChatUserId? .trim ().toLowerCase ();
156+ final bool isCurrentChat =
157+ cleanSender != null && cleanSender == cleanCurrentChat;
178158
179159 switch (type) {
180160 case 'user_status' :
@@ -188,35 +168,54 @@ class ChatController extends ChangeNotifier {
188168 notifyListeners ();
189169 }
190170 break ;
171+
191172 case 'chat' :
192173 case 'message' :
193- if (cleanSender != null && cleanSender == cleanCurrentChat ) {
174+ if (isCurrentChat ) {
194175 activeChat.add (Message .fromJson (data));
195176 _ws.sendReadReceipt (targetId: currentChatUserId! );
196177 notifyListeners ();
197- } else {
198- loadInbox ();
199178 }
179+ loadInbox ();
200180 break ;
181+
201182 case 'typing' :
202- if (cleanSender != null && cleanSender == cleanCurrentChat ) {
183+ if (isCurrentChat ) {
203184 isPeerTyping = data['content' ] == 'true' ;
204185 notifyListeners ();
205186 }
206187 break ;
188+
207189 case 'read_receipt' :
208- if (cleanSender != null && cleanSender == cleanCurrentChat) {
190+ if (isCurrentChat) {
191+ bool updated = false ;
209192 activeChat = activeChat.map ((msg) {
210193 final String sId = msg.senderId.trim ().toLowerCase ();
211- if (sId == 'me' || sId != cleanCurrentChat) {
194+ if (! msg.isRead && (sId == 'me' || sId != cleanCurrentChat)) {
195+ updated = true ;
212196 return msg.copyWith (isRead: true );
213197 }
214198 return msg;
215199 }).toList ();
216- notifyListeners ();
217- loadInbox ();
200+
201+ if (updated) {
202+ notifyListeners ();
203+ loadInbox ();
204+ }
218205 }
219206 break ;
220207 }
221208 }
209+
210+ List <dynamic > _extractDataList (dynamic data, List <String > fallbackKeys) {
211+ if (data == null ) return [];
212+ if (data is List ) return data;
213+ if (data is Map ) {
214+ if (data['data' ] is List ) return data['data' ];
215+ for (final key in fallbackKeys) {
216+ if (data[key] is List ) return data[key];
217+ }
218+ }
219+ return [];
220+ }
222221}
0 commit comments