From f604ca4f2247195d1d687090410519363ca50a43 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Wed, 30 Jul 2025 21:10:33 +0330 Subject: [PATCH] Send text message Real time updated --- .../Client/ActionHandler.java | 12 ++++- .../Client/IncomingMessageListener.java | 38 +++++++++++++++ .../telegramfinalproject/Client/Session.java | 46 ++++++++++++++++++- .../Models/ChatEntry.java | 18 +++++++- .../Server/ClientHandler.java | 1 - 5 files changed, 109 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java index 0bb8ce1..4d5ee15 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java @@ -2508,14 +2508,22 @@ public class ActionHandler { return; } + System.out.println("\n💬 Your Chats:"); + System.out.println("0. 📦 Archived chats"); + int index = 1; - System.out.println("0. Archived chats"); for (ChatEntry chat : Session.activeChats) { - System.out.printf("%d. [%s] %s (%s)\n", index++, chat.getType(), chat.getName(), chat.getDisplayId()); + String time = (chat.getLastMessageTime() == null) + ? "No messages yet" + : chat.getLastMessageTime().toString(); + + System.out.printf("%d. [%s] %s (%s) - Last: %s\n", + index++, chat.getType(), chat.getName(), chat.getDisplayId(), time); } } + public static class ChatStateMonitor implements Runnable { private final PrintWriter out; diff --git a/src/main/java/org/to/telegramfinalproject/Client/IncomingMessageListener.java b/src/main/java/org/to/telegramfinalproject/Client/IncomingMessageListener.java index c0e8180..5168ba9 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/IncomingMessageListener.java +++ b/src/main/java/org/to/telegramfinalproject/Client/IncomingMessageListener.java @@ -158,6 +158,44 @@ public class IncomingMessageListener implements Runnable { System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId()); }); + Session.activeChats.stream() + .filter(chat -> chat.getId().equals(chatUUID)) + .findFirst() + .ifPresent(chat -> { + chat.setLastMessageTime(newTime); + System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId()); + }); + + Session.archivedChats.stream() + .filter(chat -> chat.getId().equals(chatUUID)) + .findFirst() + .ifPresent(chat -> { + chat.setLastMessageTime(newTime); + System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId()); + }); + + Session.chatList.sort((c1, c2) -> { + if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0; + if (c1.getLastMessageTime() == null) return 1; + if (c2.getLastMessageTime() == null) return -1; + return c2.getLastMessageTime().compareTo(c1.getLastMessageTime()); // descending + }); + Session.activeChats.sort((c1, c2) -> { + if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0; + if (c1.getLastMessageTime() == null) return 1; + if (c2.getLastMessageTime() == null) return -1; + return c2.getLastMessageTime().compareTo(c1.getLastMessageTime()); // descending + }); + Session.archivedChats.sort((c1, c2) -> { + if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0; + if (c1.getLastMessageTime() == null) return 1; + if (c2.getLastMessageTime() == null) return -1; + return c2.getLastMessageTime().compareTo(c1.getLastMessageTime()); // descending + }); + + + + if (Session.inChatListMenu) { ActionHandler.displayChatList(); System.out.print("Select a chat by number: "); diff --git a/src/main/java/org/to/telegramfinalproject/Client/Session.java b/src/main/java/org/to/telegramfinalproject/Client/Session.java index c49bb3d..11b11d9 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/Session.java +++ b/src/main/java/org/to/telegramfinalproject/Client/Session.java @@ -4,6 +4,7 @@ import org.json.JSONArray; import org.json.JSONObject; import org.to.telegramfinalproject.Models.ChatEntry; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -36,24 +37,65 @@ public class Session { throw new RuntimeException("❌ No UUID found in currentUser!"); } +// public static void updateChatList(JSONArray chatArray) { +// chatList.clear(); +// for (int i = 0; i < chatArray.length(); i++) { +// JSONObject obj = chatArray.getJSONObject(i); +// ChatEntry entry = new ChatEntry( +// UUID.fromString(obj.getString("internal_id")), +// obj.optString("id", ""), // displayId +// obj.optString("name", ""), // name +// obj.optString("image_url", ""), +// obj.getString("type"), +// null, // last message time (if needed, parse it) +// obj.optBoolean("is_owner", false), +// obj.optBoolean("is_admin", false) +// ); +// entry.setPermissions(obj.optJSONObject("permissions")); +// chatList.add(entry); +// } +// } + + public static void updateChatList(JSONArray chatArray) { chatList.clear(); for (int i = 0; i < chatArray.length(); i++) { JSONObject obj = chatArray.getJSONObject(i); + + LocalDateTime lastMessageTime = null; + if (obj.has("last_message_time") && !obj.isNull("last_message_time")) { + String timeStr = obj.getString("last_message_time"); + if (!timeStr.isBlank()) { + lastMessageTime = LocalDateTime.parse(timeStr); + } + } + ChatEntry entry = new ChatEntry( UUID.fromString(obj.getString("internal_id")), obj.optString("id", ""), // displayId obj.optString("name", ""), // name obj.optString("image_url", ""), obj.getString("type"), - null, // last message time (if needed, parse it) + lastMessageTime, obj.optBoolean("is_owner", false), obj.optBoolean("is_admin", false) ); - entry.setPermissions(obj.optJSONObject("permissions")); // اگر permissions وجود داره + + entry.setPermissions(obj.optJSONObject("permissions")); chatList.add(entry); } + + chatList.sort((c1, c2) -> { + if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0; + if (c1.getLastMessageTime() == null) return 1; + if (c2.getLastMessageTime() == null) return -1; + return c2.getLastMessageTime().compareTo(c1.getLastMessageTime()); + }); + + activeChats = chatList.stream().filter(c -> !c.isArchived()).toList(); + archivedChats = chatList.stream().filter(ChatEntry::isArchived).toList(); } + public static List getChatList() { return chatList; } diff --git a/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java b/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java index 6060f0d..aa98d0b 100644 --- a/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java +++ b/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java @@ -115,6 +115,22 @@ public class ChatEntry { this.archived = archived; } - public void setLastMessageTime(String newTime) {this.lastMessageTime = LocalDateTime.parse(newTime); +// public void setLastMessageTime(String newTime) {this.lastMessageTime = LocalDateTime.parse(newTime); +// } + + + public void setLastMessageTime(String newTime) { + if (newTime == null || newTime.isBlank()) { + this.lastMessageTime = null; + return; + } + + try { + this.lastMessageTime = LocalDateTime.parse(newTime); + } catch (Exception e) { + System.out.println("❌ Failed to parse lastMessageTime: " + newTime); + this.lastMessageTime = null; + } } + } diff --git a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java index 78e0aa8..9596845 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java @@ -1930,7 +1930,6 @@ public class ClientHandler implements Runnable { return new ResponseModel("error", "Message inserted but failed to attach files."); } - // ری‌ل‌تایم (اختیاری: dispatchMessageToReceiver(messageId, receiverId, receiverType)) Message msg = new Message(messageId, senderId, receiverId, receiverType, content, messageType, LocalDateTime.now());