From 2142eb55b4e32c0704bb69b6ec907c92ee61af9f Mon Sep 17 00:00:00 2001 From: Suman Biswas Date: Sun, 5 Jul 2026 12:32:27 +0530 Subject: [PATCH] fixed session --- mobile/lib/controllers/chat.dart | 146 ++++++++++-------- mobile/lib/pages/settings pages/accounts.dart | 50 ++++-- 2 files changed, 116 insertions(+), 80 deletions(-) diff --git a/mobile/lib/controllers/chat.dart b/mobile/lib/controllers/chat.dart index 81beb07..e39196e 100644 --- a/mobile/lib/controllers/chat.dart +++ b/mobile/lib/controllers/chat.dart @@ -12,23 +12,29 @@ class ChatController extends ChangeNotifier { List inbox = []; List activeChat = []; List contactSearchResults = []; - String? currentChatUserId; bool isPeerTyping = false; bool isPeerOnline = false; bool isSearchLoading = false; Future initSession(String token) async { + _ws.disconnect(); + + inbox.clear(); + activeChat.clear(); + contactSearchResults.clear(); + currentChatUserId = null; + isPeerTyping = false; + isPeerOnline = false; + notifyListeners(); + await _ws.connect(token); _ws.stream?.listen( (rawFrame) { try { - final decoded = jsonDecode(rawFrame); - if (decoded is Map) { - _handleIncomingWebSocketEvent(decoded); - } + _handleIncomingWebSocketEvent(jsonDecode(rawFrame)); } catch (e) { - debugPrint("WebSocket payload error: $e"); + debugPrint("WebSocket stream payload error: $e"); } }, onError: (err) => debugPrint("WS Pipeline Error: $err"), @@ -37,13 +43,32 @@ class ChatController extends ChangeNotifier { await loadInbox(); } + void clearSessionData() { + _ws.disconnect(); + inbox.clear(); + activeChat.clear(); + contactSearchResults.clear(); + currentChatUserId = null; + isPeerTyping = false; + isPeerOnline = false; + notifyListeners(); + } + Future loadInbox() async { try { final res = await _api.getConversations(); - final targetList = _extractDataList(res.data, ['conversations']); + dynamic targetData; - inbox = targetList.map((json) => Conversation.fromJson(json)).toList(); - notifyListeners(); + if (res.data is List) { + targetData = res.data; + } else if (res.data is Map) { + targetData = res.data['data'] ?? res.data['conversations'] ?? res.data; + } + + if (targetData is List) { + inbox = targetData.map((json) => Conversation.fromJson(json)).toList(); + notifyListeners(); + } } catch (e) { debugPrint("Inbox read error: $e"); } @@ -58,34 +83,33 @@ class ChatController extends ChangeNotifier { try { final res = await _api.getChatHistory(targetUid); - final targetList = _extractDataList(res.data, ['messages']); + dynamic targetData; - activeChat = targetList - .map((json) => Message.fromJson(json)) - .toList() - .reversed - .toList(); + if (res.data is List) { + targetData = res.data; + } else if (res.data is Map) { + targetData = res.data['data'] ?? res.data['messages'] ?? res.data; + } + + if (targetData is List) { + activeChat = targetData + .map((json) => Message.fromJson(json)) + .toList() + .reversed + .toList(); + } _ws.sendReadReceipt(targetId: targetUid); _ws.sendRequestStatus(targetId: targetUid); - - notifyListeners(); await loadInbox(); } catch (e) { debugPrint("Timeline tracking fail: $e"); - notifyListeners(); } + notifyListeners(); } Future queryUsers(String term) async { final String cleanTerm = term.trim(); - - if (cleanTerm.isEmpty) { - contactSearchResults.clear(); - notifyListeners(); - return; - } - if (cleanTerm.length < 3) { contactSearchResults.clear(); notifyListeners(); @@ -96,10 +120,22 @@ class ChatController extends ChangeNotifier { notifyListeners(); try { - final res = await _api.searchUsers(term); - contactSearchResults = _extractDataList(res.data, ['users']); + final res = await _api.searchUsers(cleanTerm); + if (res.data == null) { + contactSearchResults = []; + } else if (res.data is List) { + contactSearchResults = res.data; + } else if (res.data is Map) { + if (res.data['data'] != null && res.data['data'] is List) { + contactSearchResults = res.data['data']; + } else if (res.data['users'] != null && res.data['users'] is List) { + contactSearchResults = res.data['users']; + } else { + contactSearchResults = []; + } + } } catch (e) { - debugPrint("User query failure: $e"); + debugPrint("User query pipeline failure: $e"); contactSearchResults.clear(); } finally { isSearchLoading = false; @@ -116,15 +152,16 @@ class ChatController extends ChangeNotifier { } void sendTextMessage(String text) { - final cleanContent = text.trim(); - if (currentChatUserId == null || cleanContent.isEmpty) return; + if (currentChatUserId == null || text.trim().isEmpty) return; - final targetId = currentChatUserId!; - final clientMessageId = "cli_${DateTime.now().millisecondsSinceEpoch}"; + final String clientMessageId = + "cli_${DateTime.now().millisecondsSinceEpoch}"; + final String targetId = currentChatUserId!; + final String cleanContent = text.trim(); _ws.sendChat(messageId: "", targetId: targetId, content: cleanContent); - final optimisticMsg = Message( + final Message optimisticMsg = Message( id: clientMessageId, senderId: "me", receiverId: targetId, @@ -135,7 +172,6 @@ class ChatController extends ChangeNotifier { activeChat.add(optimisticMsg); notifyListeners(); - loadInbox(); } @@ -147,14 +183,13 @@ class ChatController extends ChangeNotifier { void _handleIncomingWebSocketEvent(Map data) { final String? type = data['type']; - if (type == null) return; - final String? senderId = data['sender_id'] ?? data['sender'] ?? data['receiver_id']; + + if (type == null) return; + final String? cleanSender = senderId?.trim().toLowerCase(); final String? cleanCurrentChat = currentChatUserId?.trim().toLowerCase(); - final bool isCurrentChat = - cleanSender != null && cleanSender == cleanCurrentChat; switch (type) { case 'user_status': @@ -168,54 +203,35 @@ class ChatController extends ChangeNotifier { notifyListeners(); } break; - case 'chat': case 'message': - if (isCurrentChat) { + if (cleanSender != null && cleanSender == cleanCurrentChat) { activeChat.add(Message.fromJson(data)); _ws.sendReadReceipt(targetId: currentChatUserId!); notifyListeners(); + } else { + loadInbox(); } - loadInbox(); break; - case 'typing': - if (isCurrentChat) { + if (cleanSender != null && cleanSender == cleanCurrentChat) { isPeerTyping = data['content'] == 'true'; notifyListeners(); } break; - case 'read_receipt': - if (isCurrentChat) { - bool updated = false; + if (cleanSender != null && cleanSender == cleanCurrentChat) { activeChat = activeChat.map((msg) { final String sId = msg.senderId.trim().toLowerCase(); - if (!msg.isRead && (sId == 'me' || sId != cleanCurrentChat)) { - updated = true; + if (sId == 'me' || sId != cleanCurrentChat) { return msg.copyWith(isRead: true); } return msg; }).toList(); - - if (updated) { - notifyListeners(); - loadInbox(); - } + notifyListeners(); + loadInbox(); } break; } } - - List _extractDataList(dynamic data, List fallbackKeys) { - if (data == null) return []; - if (data is List) return data; - if (data is Map) { - if (data['data'] is List) return data['data']; - for (final key in fallbackKeys) { - if (data[key] is List) return data[key]; - } - } - return []; - } } diff --git a/mobile/lib/pages/settings pages/accounts.dart b/mobile/lib/pages/settings pages/accounts.dart index 0e81b13..4e41cf8 100644 --- a/mobile/lib/pages/settings pages/accounts.dart +++ b/mobile/lib/pages/settings pages/accounts.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mobile/controllers/auth.dart'; +import 'package:mobile/controllers/chat.dart'; +import 'package:mobile/providers/basic_providers.dart'; import 'package:mobile/main.dart'; import 'package:provider/provider.dart'; @@ -9,37 +11,55 @@ class AccountsSettings extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Accounts')), + backgroundColor: Colors.white, + appBar: AppBar( + title: const Text('Accounts'), + backgroundColor: Colors.white, + elevation: 0, + scrolledUnderElevation: 0, + ), body: ListView( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), children: [ - SizedBox( + const SizedBox( width: double.infinity, height: 150, child: Hero( tag: 'User Profile', - child: const Padding( + child: Padding( padding: EdgeInsets.only(left: 16.0, top: 10.0, bottom: 10.0), child: CircleAvatar( backgroundColor: Color(0xFFD6E4FF), - child: Icon(Icons.person, color: Color(0xFF1890FF)), + child: Icon(Icons.person, color: Color(0xFF1890FF), size: 40), ), ), ), ), - SizedBox(height: 200), + const SizedBox(height: 100), FilledButton( - style: ButtonStyle( - backgroundColor: WidgetStatePropertyAll(Colors.red), + style: const ButtonStyle( + backgroundColor: WidgetStatePropertyAll(Colors.redAccent), ), - onPressed: () { - context.read().logout(); - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) => SessionGateway()), - (route) => false, - ); + onPressed: () async { + await context.read().logout(); + await context.read().logOutSave(); + + if (context.mounted) { + context.read().clearSessionData(); + + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (context) => const SessionGateway(), + ), + (route) => false, + ); + } }, - child: Text('Log out'), + child: const Text( + 'Log out', + style: TextStyle(fontWeight: FontWeight.bold), + ), ), ], ),