work on archived chats

This commit is contained in:
2025-07-27 16:15:25 +03:30
parent a43cd594f8
commit 775350f8ce
4 changed files with 356 additions and 25 deletions
@@ -440,8 +440,11 @@ public class ActionHandler {
Session.currentUser = response.getJSONObject("data"); Session.currentUser = response.getJSONObject("data");
JSONArray chatListJson = Session.currentUser.getJSONArray("chat_list"); JSONArray chatListJson = Session.currentUser.getJSONArray("chat_list");
JSONArray Archived = Session.currentUser.getJSONArray("archived_chat_list");
JSONArray Active = Session.currentUser.getJSONArray("active_chat_lis");
List<ChatEntry> chatList = new ArrayList<>(); List<ChatEntry> chatList = new ArrayList<>();
for (Object obj : chatListJson) { for (Object obj : chatListJson) {
JSONObject chat = (JSONObject) obj; JSONObject chat = (JSONObject) obj;
@@ -462,7 +465,48 @@ public class ActionHandler {
} }
List<ChatEntry> archivedChats = new ArrayList<>();
for (Object obj : Archived){
JSONObject chat = (JSONObject) obj;
ChatEntry entry = new ChatEntry(
UUID.fromString(chat.getString("internal_id")),
chat.getString("id"),
chat.getString("name"),
chat.optString("image_url", ""),
chat.getString("type"),
chat.isNull("last_message_time") ? null : LocalDateTime.parse(chat.getString("last_message_time")),
chat.optBoolean("is_owner", false),
chat.optBoolean("is_admin", false)
);
archivedChats.add(entry);
}
List<ChatEntry> activeChats = new ArrayList<>();
for (Object obj : Active){
JSONObject chat = (JSONObject) obj;
ChatEntry entry = new ChatEntry(
UUID.fromString(chat.getString("internal_id")),
chat.getString("id"),
chat.getString("name"),
chat.optString("image_url", ""),
chat.getString("type"),
chat.isNull("last_message_time") ? null : LocalDateTime.parse(chat.getString("last_message_time")),
chat.optBoolean("is_owner", false),
chat.optBoolean("is_admin", false)
);
activeChats.add(entry);
}
Session.activeChats = activeChats;
Session.archivedChats = archivedChats;
Session.chatList = chatList; Session.chatList = chatList;
break; break;
@@ -725,34 +769,110 @@ public class ActionHandler {
} }
} }
// public void showChatListAndSelect() {
//
//
// List<ChatEntry> chatList = Session.getChatList();
// if (chatList.isEmpty()) {
// System.out.println("📭 You have no chats.");
// return;
// }
//
// System.out.println("\nYour Chats:");
// for (int i = 0; i < chatList.size(); i++) {
// ChatEntry entry = chatList.get(i);
// String last = entry.getLastMessageTime() == null ? "No messages yet" : entry.getLastMessageTime().toString();
// System.out.printf("%d. [%s] %s - Last: %s\n", i + 1, entry.getType(), entry.getName(), last);
// }
//
// System.out.print("Select a chat by number: ");
// int choice = Integer.parseInt(scanner.nextLine());
// if (choice < 1 || choice > chatList.size()) {
// System.out.println("❌ Invalid choice.");
// return;
// }
//
// openChat(chatList.get(choice - 1));
// }
public void showChatListAndSelect() { public void showChatListAndSelect() {
if (Session.activeChats == null || Session.activeChats.isEmpty()) {
System.out.println("No active chats.");
List<ChatEntry> chatList = Session.getChatList();
if (chatList.isEmpty()) {
System.out.println("📭 You have no chats.");
return; return;
} }
System.out.println("\nYour Chats:"); System.out.println("\nYour Chats:");
for (int i = 0; i < chatList.size(); i++) { System.out.println("0. 📦 Archived Chats");
ChatEntry entry = chatList.get(i);
String last = entry.getLastMessageTime() == null ? "No messages yet" : entry.getLastMessageTime().toString(); for (int i = 0; i < Session.activeChats.size(); i++) {
System.out.printf("%d. [%s] %s - Last: %s\n", i + 1, entry.getType(), entry.getName(), last); ChatEntry entry = Session.activeChats.get(i);
String time = (entry.getLastMessageTime() == null)
? "No messages yet"
: entry.getLastMessageTime().toString();
System.out.println((i + 1) + ". [" + entry.getType() + "] " +
entry.getName() + " - Last: " + time);
} }
System.out.print("Select a chat by number: "); System.out.print("Select a chat by number: ");
int choice = Integer.parseInt(scanner.nextLine()); int choice = Integer.parseInt(scanner.nextLine());
if (choice < 1 || choice > chatList.size()) {
System.out.println("❌ Invalid choice."); if (choice == 0) {
showArchivedChats();
return; return;
} }
openChat(chatList.get(choice - 1)); int index = choice - 1;
if (index < 0 || index >= Session.activeChats.size()) {
System.out.println("Invalid selection.");
return;
}
ChatEntry selected = Session.activeChats.get(index);
openChat(selected);
} }
private void showArchivedChats() {
if (Session.archivedChats == null || Session.archivedChats.isEmpty()) {
System.out.println("📭 No archived chats.");
return;
}
System.out.println("\n📦 Archived Chats:");
for (int i = 0; i < Session.archivedChats.size(); i++) {
ChatEntry entry = Session.archivedChats.get(i);
String time = (entry.getLastMessageTime() == null)
? "No messages yet"
: entry.getLastMessageTime().toString();
System.out.println((i + 1) + ". [" + entry.getType() + "] " +
entry.getName() + " - Last: " + time);
}
System.out.print("Select a chat by number (or 0 to return): ");
int choice = Integer.parseInt(scanner.nextLine());
if (choice == 0) {
System.out.println("🔙 Returning to main chat list...");
return;
}
int index = choice - 1;
if (index < 0 || index >= Session.archivedChats.size()) {
System.out.println("❌ Invalid selection.");
return;
}
ChatEntry selected = Session.archivedChats.get(index);
openChat(selected);
}
private void openChat(ChatEntry chat) { private void openChat(ChatEntry chat) {
JSONObject req = new JSONObject(); JSONObject req = new JSONObject();
req.put("action", "get_messages"); req.put("action", "get_messages");
@@ -856,7 +976,8 @@ public class ActionHandler {
System.out.println("3. Delete chat (one-sided)"); System.out.println("3. Delete chat (one-sided)");
System.out.println("4. Delete chat (both sides)"); System.out.println("4. Delete chat (both sides)");
System.out.println("5. View profile"); System.out.println("5. View profile");
System.out.println("6. Back"); System.out.println("6. Archive/Unarchived");
System.out.println("7. Back");
String input = scanner.nextLine(); String input = scanner.nextLine();
@@ -897,7 +1018,13 @@ public class ActionHandler {
return true; return true;
} }
case "6" -> { case "6" ->{
toggleArchive(chat.getId() , "private");
return true;
}
case "7" -> {
return false; return false;
} }
default -> System.out.println("Invalid choice."); default -> System.out.println("Invalid choice.");
@@ -961,6 +1088,8 @@ public class ActionHandler {
System.out.println("11. Edit Admin Permissions"); System.out.println("11. Edit Admin Permissions");
} }
System.out.println("12. Archive/Unarchived");
System.out.println("0. Back to Chat List"); System.out.println("0. Back to Chat List");
String input = scanner.nextLine(); String input = scanner.nextLine();
@@ -1010,6 +1139,10 @@ public class ActionHandler {
} }
} }
case "12"->{
toggleArchive(chat.getId() , "group");
}
case "0" -> { case "0" -> {
return false; return false;
} }
@@ -1076,6 +1209,7 @@ public class ActionHandler {
System.out.println("11. Edit Admin Permissions"); System.out.println("11. Edit Admin Permissions");
} }
System.out.println("12. Archive/Unarchived");
System.out.println("0. Back to Chat List"); System.out.println("0. Back to Chat List");
String input = scanner.nextLine(); String input = scanner.nextLine();
@@ -1155,6 +1289,10 @@ public class ActionHandler {
} }
} }
case "12"->{
toggleArchive(chat.getId() , "channel");
}
case "0" -> { case "0" -> {
return false; return false;
@@ -2714,6 +2852,56 @@ public class ActionHandler {
public void toggleArchive(UUID chatId, String chatType) {
// پیدا کردن چت از Session.chatList
Optional<ChatEntry> optional = Session.chatList.stream()
.filter(c -> c.getId().equals(chatId))
.findFirst();
if (optional.isEmpty()) {
System.out.println("❌ Chat not found.");
return;
}
ChatEntry chat = optional.get();
if (chat.isArchived()) {
unarchiveChat(chatId, chatType);
chat.setArchived(false);
System.out.println("✅ Chat unarchived.");
} else {
archiveChat(chatId, chatType);
chat.setArchived(true);
System.out.println("✅ Chat archived.");
}
Session.refreshChatLists();
}
private void archiveChat(UUID chatId, String chatType) {
JSONObject req = new JSONObject();
req.put("action", "archive_chat");
req.put("chat_id", chatId.toString());
req.put("chat_type", chatType);
JSONObject res = sendWithResponse(req);
if (res != null) System.out.println(res.getString("message"));
}
private void unarchiveChat(UUID chatId, String chatType) {
JSONObject req = new JSONObject();
req.put("action", "unarchive_chat");
req.put("chat_id", chatId.toString());
req.put("chat_type", chatType);
JSONObject res = sendWithResponse(req);
if (res != null) System.out.println(res.getString("message"));
}
} }
@@ -13,6 +13,9 @@ import java.util.UUID;
public class Session { public class Session {
public static JSONObject currentUser; public static JSONObject currentUser;
public static List<ChatEntry> chatList = new ArrayList<>(); public static List<ChatEntry> chatList = new ArrayList<>();
public static List<ChatEntry> archivedChats = new ArrayList<>();
public static List<ChatEntry> activeChats = new ArrayList<>();
public static volatile boolean forceRefreshChatList = false; public static volatile boolean forceRefreshChatList = false;
public static volatile boolean backToChatList = false; public static volatile boolean backToChatList = false;
public static boolean inChatListMenu = false; public static boolean inChatListMenu = false;
@@ -55,4 +58,14 @@ public class Session {
return chatList; return chatList;
} }
public static void refreshChatLists() {
Session.activeChats = Session.chatList.stream()
.filter(c -> !c.isArchived())
.toList();
Session.archivedChats = Session.chatList.stream()
.filter(ChatEntry::isArchived)
.toList();
}
} }
@@ -12,8 +12,9 @@ public class ChatEntry {
private String imageUrl; private String imageUrl;
private String type; private String type;
private LocalDateTime lastMessageTime; private LocalDateTime lastMessageTime;
private boolean archived = false;
// 🔹 نقش‌ها
private boolean isOwner = false; private boolean isOwner = false;
private boolean isAdmin = false; private boolean isAdmin = false;
private JSONObject permissions; private JSONObject permissions;
@@ -28,7 +29,6 @@ public class ChatEntry {
this.lastMessageTime = lastMessageTime; this.lastMessageTime = lastMessageTime;
} }
// ✅ کانستراکتور اضافه‌شده برای پشتیبانی از نقش‌ها (اختیاری، برای استفاده‌های جدید)
public ChatEntry(UUID internalId, String displayId, String name, String imageUrl, String type, LocalDateTime lastMessageTime, boolean isOwner, boolean isAdmin) { public ChatEntry(UUID internalId, String displayId, String name, String imageUrl, String type, LocalDateTime lastMessageTime, boolean isOwner, boolean isAdmin) {
this(internalId, displayId, name, imageUrl, type, lastMessageTime); this(internalId, displayId, name, imageUrl, type, lastMessageTime);
this.isOwner = isOwner; this.isOwner = isOwner;
@@ -41,7 +41,6 @@ public class ChatEntry {
} }
// 🟩 گتر و ستر جدید
public boolean isOwner() { public boolean isOwner() {
return isOwner; return isOwner;
} }
@@ -108,4 +107,12 @@ public class ChatEntry {
public boolean isArchived() {
return archived;
}
public void setArchived(boolean archived) {
this.archived = archived;
}
} }
@@ -87,36 +87,80 @@ public class ClientHandler implements Runnable {
List<Group> groups = GroupDatabase.getGroupsByUser(user.getInternal_uuid()); List<Group> groups = GroupDatabase.getGroupsByUser(user.getInternal_uuid());
List<Channel> channels = ChannelDatabase.getChannelsByUser(user.getInternal_uuid()); List<Channel> channels = ChannelDatabase.getChannelsByUser(user.getInternal_uuid());
List<Message> unreadMessages = MessageDatabase.getUnreadMessages(user.getInternal_uuid()); List<Message> unreadMessages = MessageDatabase.getUnreadMessages(user.getInternal_uuid());
List<UUID> archivedChatIds = ArchivedChatDatabase.getArchivedChats(user.getInternal_uuid());
user.setContactList(contacts); user.setContactList(contacts);
user.setGroupList(groups); user.setGroupList(groups);
user.setChannelList(channels); user.setChannelList(channels);
user.setUnreadMessages(unreadMessages); user.setUnreadMessages(unreadMessages);
List<ChatEntry> chatList = new ArrayList<>(); List<ChatEntry> chatList = new ArrayList<>();
List<ChatEntry> archivedChatList = new ArrayList<>();
List<ChatEntry> activeChatList = new ArrayList<>();
for (Contact contact : contacts) { for (Contact contact : contacts) {
User target = userDatabase.findByInternalUUID(contact.getContact_id()); User target = userDatabase.findByInternalUUID(contact.getContact_id());
if (target == null) continue; if (target == null) continue;
LocalDateTime last = MessageDatabase.getLastMessageTimeBetween(user.getInternal_uuid(), target.getInternal_uuid(), "private"); LocalDateTime last = MessageDatabase.getLastMessageTimeBetween(user.getInternal_uuid(), target.getInternal_uuid(), "private");
chatList.add(new ChatEntry( // chatList.add(new ChatEntry(
target.getInternal_uuid(), // internal UUID // target.getInternal_uuid(), // internal UUID
target.getUser_id(), // public display ID // target.getUser_id(), // public display ID
// target.getProfile_name(),
// target.getImage_url(),
// "private",
// last,
// false,
// false
// ));
UUID targetId = target.getInternal_uuid();
ChatEntry entry = new ChatEntry(
targetId,
target.getUser_id(),
target.getProfile_name(), target.getProfile_name(),
target.getImage_url(), target.getImage_url(),
"private", "private",
last, last,
false, false,
false false
)); );
if (archivedChatIds.contains(targetId)) {
archivedChatList.add(entry);
chatList.add(entry);
} else {
activeChatList.add(entry);
chatList.add(entry);
}
} }
for (Group group : groups) { for (Group group : groups) {
LocalDateTime last = MessageDatabase.getLastMessageTime(group.getInternal_uuid(), "group"); LocalDateTime last = MessageDatabase.getLastMessageTime(group.getInternal_uuid(), "group");
boolean isOwner = GroupDatabase.isOwner(group.getInternal_uuid(), user.getInternal_uuid()); boolean isOwner = GroupDatabase.isOwner(group.getInternal_uuid(), user.getInternal_uuid());
boolean isAdmin = GroupDatabase.isAdmin(group.getInternal_uuid(), user.getInternal_uuid()); boolean isAdmin = GroupDatabase.isAdmin(group.getInternal_uuid(), user.getInternal_uuid());
chatList.add(new ChatEntry( // chatList.add(new ChatEntry(
// group.getInternal_uuid(),
// group.getGroup_id(),
// group.getGroup_name(),
// group.getImage_url(),
// "group",
// last,
// isOwner,
// isAdmin
// ));
ChatEntry entry = new ChatEntry(
group.getInternal_uuid(), group.getInternal_uuid(),
group.getGroup_id(), group.getGroup_id(),
group.getGroup_name(), group.getGroup_name(),
@@ -125,7 +169,17 @@ public class ClientHandler implements Runnable {
last, last,
isOwner, isOwner,
isAdmin isAdmin
)); );
if (archivedChatIds.contains(group.getInternal_uuid())) {
archivedChatList.add(entry);
chatList.add(entry);
} else {
activeChatList.add(entry);
chatList.add(entry);
}
} }
for (Channel channel : channels) { for (Channel channel : channels) {
@@ -133,7 +187,18 @@ public class ClientHandler implements Runnable {
boolean isOwner = ChannelDatabase.isOwner(channel.getInternal_uuid(), user.getInternal_uuid()); boolean isOwner = ChannelDatabase.isOwner(channel.getInternal_uuid(), user.getInternal_uuid());
boolean isAdmin = ChannelDatabase.isAdmin(channel.getInternal_uuid(), user.getInternal_uuid()); boolean isAdmin = ChannelDatabase.isAdmin(channel.getInternal_uuid(), user.getInternal_uuid());
chatList.add(new ChatEntry( // chatList.add(new ChatEntry(
// channel.getInternal_uuid(),
// channel.getChannel_id(),
// channel.getChannel_name(),
// channel.getImage_url(),
// "channel",
// last,
// isOwner,
// isAdmin
// ));
ChatEntry entry = new ChatEntry(
channel.getInternal_uuid(), channel.getInternal_uuid(),
channel.getChannel_id(), channel.getChannel_id(),
channel.getChannel_name(), channel.getChannel_name(),
@@ -142,9 +207,29 @@ public class ClientHandler implements Runnable {
last, last,
isOwner, isOwner,
isAdmin isAdmin
)); );
if (archivedChatIds.contains(channel.getInternal_uuid())) {
archivedChatList.add(entry);
chatList.add(entry);
} else {
activeChatList.add(entry);
chatList.add(entry);
}
} }
activeChatList.sort((a, b) -> {
if (a.getLastMessageTime() == null) return 1;
if (b.getLastMessageTime() == null) return -1;
return b.getLastMessageTime().compareTo(a.getLastMessageTime());
});
archivedChatList.sort((a, b) -> {
if (a.getLastMessageTime() == null) return 1;
if (b.getLastMessageTime() == null) return -1;
return b.getLastMessageTime().compareTo(a.getLastMessageTime());
});
chatList.sort((a, b) -> { chatList.sort((a, b) -> {
if (a.getLastMessageTime() == null) return 1; if (a.getLastMessageTime() == null) return 1;
@@ -154,6 +239,8 @@ public class ClientHandler implements Runnable {
JSONObject userData = JsonUtil.userToJson(user); JSONObject userData = JsonUtil.userToJson(user);
userData.put("chat_list", JsonUtil.chatListToJson(chatList)); userData.put("chat_list", JsonUtil.chatListToJson(chatList));
userData.put("archived_chat_list", JsonUtil.chatListToJson(archivedChatList));
userData.put("active_chat_lis", JsonUtil.chatListToJson(activeChatList));
response = new ResponseModel("success", "Welcome " + user.getProfile_name(), userData); response = new ResponseModel("success", "Welcome " + user.getProfile_name(), userData);
} }
break; break;
@@ -1708,6 +1795,42 @@ public class ClientHandler implements Runnable {
// } // }
// //
case "archive_chat": {
if (currentUser == null) {
response = new ResponseModel("error", "Unauthorized. Please login first.");
break;
}
UUID chatId = UUID.fromString(requestJson.getString("chat_id"));
String chatType = requestJson.getString("chat_type");
boolean success = ArchivedChatDatabase.archiveChat(currentUser.getInternal_uuid(), chatId, chatType);
response = success
? new ResponseModel("success", "Chat archived successfully.")
: new ResponseModel("error", "Failed to archive chat.");
break;
}
case "unarchive_chat": {
if (currentUser == null) {
response = new ResponseModel("error", "Unauthorized. Please login first.");
break;
}
UUID chatId = UUID.fromString(requestJson.getString("chat_id"));
boolean success = ArchivedChatDatabase.unarchiveChat(currentUser.getInternal_uuid(), chatId);
response = success
? new ResponseModel("success", "Chat unarchived successfully.")
: new ResponseModel("error", "Failed to unarchive chat.");
break;
}
default: default: