diff --git a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java index 644a1c2..0351550 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java @@ -582,6 +582,40 @@ public class ActionHandler { } } } +// +// public void showChatListAndSelect() { +// if (Session.chatList == null || Session.chatList.isEmpty()) { +// System.out.println("No chats available."); +// return; +// } +// +// System.out.println("\nYour Chats:"); +// for (int i = 0; i < Session.chatList.size(); i++) { +// ChatEntry entry = Session.chatList.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: "); +// int choice = Integer.parseInt(scanner.nextLine()) - 1; +// +// if(choice == -1){ +// System.out.println("Exit..."); +// return; +// } +// if (choice < -1 || choice >= Session.chatList.size()) { +// System.out.println("Invalid selection."); +// return; +// } +// +// ChatEntry selected = Session.chatList.get(choice); +// openChat(selected); +// } + + public void showChatListAndSelect() { if (Session.chatList == null || Session.chatList.isEmpty()) { @@ -589,9 +623,15 @@ public class ActionHandler { return; } + List activeChats = Session.chatList.stream() + .filter(c -> !c.isArchived()) + .toList(); + System.out.println("\nYour Chats:"); - for (int i = 0; i < Session.chatList.size(); i++) { - ChatEntry entry = Session.chatList.get(i); + System.out.println("0. 📦 Archived Chats"); + + for (int i = 0; i < activeChats.size(); i++) { + ChatEntry entry = activeChats.get(i); String time = (entry.getLastMessageTime() == null) ? "No messages yet" : entry.getLastMessageTime().toString(); @@ -600,23 +640,28 @@ public class ActionHandler { } System.out.print("Select a chat by number: "); - int choice = Integer.parseInt(scanner.nextLine()) - 1; + int choice = Integer.parseInt(scanner.nextLine()); - if(choice == -1){ - System.out.println("Exit..."); + if (choice == 0) { + showArchivedChats(); return; } - if (choice < -1 || choice >= Session.chatList.size()) { + + int index = choice - 1; + + if (index < 0 || index >= activeChats.size()) { System.out.println("Invalid selection."); return; } - ChatEntry selected = Session.chatList.get(choice); + ChatEntry selected = activeChats.get(index); openChat(selected); } + + private void openChat(ChatEntry chat) { JSONObject req = new JSONObject(); req.put("action", "get_messages"); @@ -640,6 +685,42 @@ public class ActionHandler { } + private void showArchivedChats() { + List archived = Session.chatList.stream() + .filter(ChatEntry::isArchived) + .toList(); + + if (archived.isEmpty()) { + System.out.println("📭 No archived chats."); + return; + } + + System.out.println("\n📦 Archived Chats:"); + for (int i = 0; i < archived.size(); i++) { + ChatEntry entry = archived.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; + } + + if (choice < 1 || choice > archived.size()) { + System.out.println("❌ Invalid selection."); + return; + } + + ChatEntry selected = archived.get(choice - 1); + openChat(selected); + } @@ -1920,4 +2001,50 @@ public class ActionHandler { return null; } } + + 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")); + } + + + + +// private void toggleArchiveChat(ChatEntry chat) { +// JSONObject req = new JSONObject(); +// if (chat.isArchived()) { +// req.put("action", "unarchive_chat"); +// } else { +// req.put("action", "archive_chat"); +// } +// req.put("chat_id", chat.getId().toString()); +// req.put("chat_type", chat.getType()); +// +// JSONObject res = sendWithResponse(req); +// if (res != null) { +// System.out.println(res.getString("message")); +// +// // تغییر وضعیت آرشیو به‌صورت لوکالی +// chat.setArchived(!chat.isArchived()); +// +// // اگر در لیست اصلی یا آرشیو بود، بعد از تغییر منو رو ببند +// System.out.println("🔄 Returning to chat list..."); +// forceExitChat = true; // از منو خارج بشیم +// } + + + } diff --git a/src/main/java/org/to/telegramfinalproject/Client/Session.java b/src/main/java/org/to/telegramfinalproject/Client/Session.java index 64270a1..b057624 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/Session.java +++ b/src/main/java/org/to/telegramfinalproject/Client/Session.java @@ -3,13 +3,17 @@ package org.to.telegramfinalproject.Client; import org.json.JSONObject; import org.to.telegramfinalproject.Models.ChatEntry; +import java.util.ArrayList; import java.util.List; +import java.util.UUID; // method for save data from server response public class Session { public static JSONObject currentUser; public static List chatList; + public static List archivedChatIds = new ArrayList<>(); + public static String getUserUUID() { if (currentUser.has("uuid")) return currentUser.getString("uuid"); diff --git a/src/main/java/org/to/telegramfinalproject/Database/ArchivedChatDatabase.java b/src/main/java/org/to/telegramfinalproject/Database/ArchivedChatDatabase.java new file mode 100644 index 0000000..7ad71ba --- /dev/null +++ b/src/main/java/org/to/telegramfinalproject/Database/ArchivedChatDatabase.java @@ -0,0 +1,72 @@ +package org.to.telegramfinalproject.Database; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ArchivedChatDatabase { + public static boolean archiveChat(UUID userId, UUID chatId, String chatType) { + String sql = "INSERT INTO archived_chats (user_id, chat_id, chat_type) VALUES (?, ?, ?) ON CONFLICT DO NOTHING"; + try (Connection conn = ConnectionDb.connect(); + PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setObject(1, userId); + ps.setObject(2, chatId); + ps.setString(3, chatType); + return ps.executeUpdate() > 0; + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + + public static boolean unarchiveChat(UUID userId, UUID chatId) { + String sql = "DELETE FROM archived_chats WHERE user_id = ? AND chat_id = ?"; + try (Connection conn = ConnectionDb.connect(); + PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setObject(1, userId); + ps.setObject(2, chatId); + return ps.executeUpdate() > 0; + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + public static boolean isChatArchived(UUID userId, UUID chatId) { + String sql = "SELECT 1 FROM archived_chats WHERE user_id = ? AND chat_id = ?"; + try (Connection conn = ConnectionDb.connect(); + PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setObject(1, userId); + ps.setObject(2, chatId); + ResultSet rs = ps.executeQuery(); + return rs.next(); + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + public static List getArchivedChats(UUID userId) { + List list = new ArrayList<>(); + String sql = "SELECT chat_id FROM archived_chats WHERE user_id = ?"; + try (Connection conn = ConnectionDb.connect(); + PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setObject(1, userId); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + list.add(UUID.fromString(rs.getString("chat_id"))); + } + } catch (Exception e) { + e.printStackTrace(); + } + return list; + } + + + +} diff --git a/src/main/java/org/to/telegramfinalproject/Database/ConnectionDb.java b/src/main/java/org/to/telegramfinalproject/Database/ConnectionDb.java index 8d72664..b58f4c0 100644 --- a/src/main/java/org/to/telegramfinalproject/Database/ConnectionDb.java +++ b/src/main/java/org/to/telegramfinalproject/Database/ConnectionDb.java @@ -7,7 +7,7 @@ import java.sql.SQLException; public class ConnectionDb { private static final String JDBC_URL = "jdbc:postgresql://localhost:5432/Telegram"; private static final String USERNAME = "postgres"; - private static final String PASSWORD = "124postpass"; + private static final String PASSWORD = "Partow@1384"; public ConnectionDb() { } diff --git a/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java b/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java index 008a147..46e1520 100644 --- a/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java +++ b/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java @@ -444,7 +444,7 @@ public class GroupDatabase { stmt.setObject(2, userId); ResultSet rs = stmt.executeQuery(); - return rs.next(); // اگر رکوردی پیدا شد یعنی owner است + return rs.next(); } catch (SQLException e) { e.printStackTrace(); } @@ -460,7 +460,7 @@ public class GroupDatabase { ResultSet rs = stmt.executeQuery(); if (rs.next()) { String role = rs.getString("role"); - return "admin".equals(role) || "owner".equals(role); // owner هم admin هست + return "admin".equals(role) || "owner".equals(role); } } catch (SQLException e) { e.printStackTrace(); @@ -508,7 +508,7 @@ public class GroupDatabase { while (rs.next()) { JSONObject member = new JSONObject(); member.put("profile_name", rs.getString("profile_name")); - member.put("user_id", rs.getString("user_id")); // آیدی قابل نمایش + member.put("user_id", rs.getString("user_id")); member.put("internal_uuid", rs.getObject("internal_uuid").toString()); member.put("role", rs.getString("role")); diff --git a/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java b/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java index a330da4..4d9d998 100644 --- a/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java +++ b/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java @@ -264,6 +264,8 @@ public class userDatabase { return null; } + + public List searchUsers(String keyword, UUID currentUserId) { String query = """ SELECT * FROM users diff --git a/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java b/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java index cbd0940..731999c 100644 --- a/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java +++ b/src/main/java/org/to/telegramfinalproject/Models/ChatEntry.java @@ -87,4 +87,15 @@ public class ChatEntry { public void setPermissions(JSONObject permissions) { this.permissions = permissions; } + + private boolean archived = false; + + public boolean isArchived() { + return archived; + } + + public void setArchived(boolean archived) { + this.archived = archived; + } + } diff --git a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java index 76022b6..d6541de 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java @@ -1189,6 +1189,50 @@ public class ClientHandler implements Runnable { break; } + case "archive_chat": { + 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": { + 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; + } + + case "get_archived_chats": { + if (currentUser == null) { + response = new ResponseModel("error", "Unauthorized. Please login first."); + break; + } + + List archived = ArchivedChatDatabase.getArchivedChats(currentUser.getInternal_uuid()); + + boolean success = archived != null; + + response = success + ? new ResponseModel( + "success", + "Archived chat list fetched successfully.", + new JSONObject().put("archived", new JSONArray(archived.stream().map(UUID::toString).toList())) + ) + : new ResponseModel("error", "Failed to fetch archived chats."); + + break; + } + + + default: