diff --git a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java index 5f8f068..f2f56a9 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java @@ -2778,6 +2778,35 @@ public class ClientHandler implements Runnable { break; } + case "get_other_user_status": { + try { + String userIdStr = requestJson.getString("user_id"); + UUID user_id = UUID.fromString(userIdStr); + + String lastSeenStr = userDatabase.getLastSeen(user_id); // returns ISO string? + JSONObject data = new JSONObject(); + + if (lastSeenStr != null && !"Unknown".equals(lastSeenStr)) { + // parse string to time + LocalDateTime lastSeen = LocalDateTime.parse(lastSeenStr); + long diffMillis = java.time.Duration.between(lastSeen, LocalDateTime.now()).toMillis(); + + boolean online = diffMillis <= 120_000; + + data.put("online", online); + data.put("last_seen", lastSeen.toString()); + + response = new ResponseModel("success", "Status fetched.", data); + } else { + response = new ResponseModel("error", "User not found."); + } + + } catch (Exception e) { + e.printStackTrace(); + response = new ResponseModel("error", "Failed to fetch status."); + } + break; + } default: response = new ResponseModel("error", "Unknown action: " + action); diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java b/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java index f905548..5b92471 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java @@ -23,6 +23,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; +import java.util.Objects; import java.util.UUID; public class ChatPageController { @@ -109,12 +110,6 @@ public class ChatPageController { } } - //Time formatter for messages - -// private static final DateTimeFormatter FMT_HHMM = DateTimeFormatter.ofPattern("HH:mm"); -// private static final DateTimeFormatter FMT_DATE_TIME = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); -// private static final String YESTERDAY_LABEL = "Yesterday"; - private static String str(org.json.JSONObject j, String k) { try { return (j.has(k) && !j.isNull(k)) ? j.getString(k) : ""; } catch (Exception e) { return ""; } } @@ -306,31 +301,31 @@ public class ChatPageController { MainController.getInstance().showSearchPanel(); } - /** - * Called by main controller when opening a chat. - */ - public void setChat(String chatName, String avatarPath) { - this.chatName = chatName; - - // Header text (if present) - if (chatTitle != null) chatTitle.setText(chatName); - if (chatStatus != null) chatStatus.setText("last seen recently"); // or live status - - // Load avatar if provided - if (userAvatar != null && avatarPath != null) { - try { - Image avatarImg = new Image(getClass().getResourceAsStream(avatarPath)); - userAvatar.setImage(avatarImg); - Circle clip = new Circle(18, 18, 18); // x, y, radius - userAvatar.setClip(clip); - } catch (Exception e) { - System.err.println("Could not load avatar: " + avatarPath); - } - } - - addSystemMessage("Chat with " + chatName + " opened."); - Platform.runLater(() -> messageInput.requestFocus()); - } +// /** +// * Called by main controller when opening a chat. +// */ +// public void setChat(String chatName, String avatarPath) { +// this.chatName = chatName; +// +// // Header text (if present) +// if (chatTitle != null) chatTitle.setText(chatName); +// if (chatStatus != null) chatStatus.setText("last seen recently"); // or live status +// +// // Load avatar if provided +// if (userAvatar != null && avatarPath != null) { +// try { +// Image avatarImg = new Image(getClass().getResourceAsStream(avatarPath)); +// userAvatar.setImage(avatarImg); +// Circle clip = new Circle(18, 18, 18); // x, y, radius +// userAvatar.setClip(clip); +// } catch (Exception e) { +// System.err.println("Could not load avatar: " + avatarPath); +// } +// } +// +// addSystemMessage("Chat with " + chatName + " opened."); +// Platform.runLater(() -> messageInput.requestFocus()); +// } // ----- actions ----- @@ -467,24 +462,24 @@ public class ChatPageController { // ----- UI helpers ----- - /** - * Add a normal message bubble (very simple for now). - */ - public void addMessage(String sender, String content) { - Label msg = new Label(sender + ": " + content); - msg.setWrapText(true); - - boolean dark = themeManager.isDarkMode(); - String bubbleColor = dark ? "#20405a" : "#4fa8f0"; - String textColor = dark ? "#e8f1f8" : "#0f141a"; - msg.setStyle( - "-fx-background-color: " + bubbleColor + ";" + - "-fx-text-fill: " + textColor + ";" + - "-fx-padding: 6 10; -fx-background-radius: 10;" - ); - - messageContainer.getChildren().add(msg); - } +// /** +// * Add a normal message bubble (very simple for now). +// */ +// public void addMessage(String sender, String content) { +// Label msg = new Label(sender + ": " + content); +// msg.setWrapText(true); +// +// boolean dark = themeManager.isDarkMode(); +// String bubbleColor = dark ? "#20405a" : "#4fa8f0"; +// String textColor = dark ? "#e8f1f8" : "#0f141a"; +// msg.setStyle( +// "-fx-background-color: " + bubbleColor + ";" + +// "-fx-text-fill: " + textColor + ";" + +// "-fx-padding: 6 10; -fx-background-radius: 10;" +// ); +// +// messageContainer.getChildren().add(msg); +// } private void addSystemMessage(String content) { Label sys = new Label(content); @@ -539,20 +534,68 @@ public class ChatPageController { public void showChat(ChatEntry entry) { this.currentChat = entry; - // Header chatTitle.setText(entry.getName()); - chatStatus.setText(""); + + // Default avatar if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) { - try { - userAvatar.setImage(new Image(entry.getImageUrl() != null ? entry.getImageUrl() : "/org/to/telegramfinalproject/Avatars/default_user_profile.png")); - userAvatar.setClip(new Circle(18, 18, 18)); - } catch (Exception ignored) { - } + userAvatar.setImage(new Image(entry.getImageUrl())); + } else if ("channel".equals(entry.getType())) { + userAvatar.setImage(new Image( + Objects.requireNonNull(getClass().getResourceAsStream( + "/org/to/telegramfinalproject/Avatars/default_channel_profile.png")) + )); + } else if ("group".equals(entry.getType())) { + userAvatar.setImage(new Image( + Objects.requireNonNull(getClass().getResourceAsStream( + "/org/to/telegramfinalproject/Avatars/default_group_profile.png")) + )); + } else { + userAvatar.setImage(new Image( + Objects.requireNonNull(getClass().getResourceAsStream( + "/org/to/telegramfinalproject/Avatars/default_user_profile.png")) + )); + } + userAvatar.setClip(new Circle(20, 20, 20)); + + // === Private chat? Fetch other user status === + if ("private".equalsIgnoreCase(entry.getType()) && entry.getOtherUserId() != null) { + UUID otherId = entry.getOtherUserId(); + + new Thread(() -> { + JSONObject req = new JSONObject(); + req.put("action", "get_other_user_status"); + req.put("user_id", otherId.toString()); + + JSONObject resp = ActionHandler.sendWithResponse(req); + if (resp != null && "success".equals(resp.optString("status"))) { + JSONObject data = resp.optJSONObject("data"); + boolean online = data.optBoolean("online", false); + String lastSeenIso = data.optString("last_seen", null); + + String statusText; + if (online) { + statusText = "online"; + } else { + // fallback if no timestamp + statusText = (lastSeenIso == null || lastSeenIso.isEmpty()) + ? "last seen recently" + : "last seen " + formatWhen(parseWhen(lastSeenIso)); + } + + Platform.runLater(() -> chatStatus.setText(statusText)); + } + }).start(); + } else if ("group".equalsIgnoreCase(entry.getType())) { + chatStatus.setText("Group"); + } else if ("channel".equalsIgnoreCase(entry.getType())) { + chatStatus.setText("Channel"); + } else { + chatStatus.setText(""); } + // Load chat messages messageContainer.getChildren().clear(); loadMessages(entry); - markAsRead(entry); Platform.runLater(() -> messageInput.requestFocus()); diff --git a/src/main/java/org/to/telegramfinalproject/UI/MainController.java b/src/main/java/org/to/telegramfinalproject/UI/MainController.java index 9b714c5..2da29ff 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/MainController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/MainController.java @@ -287,30 +287,6 @@ public class MainController { searchBar.clear(); } -// private void addSampleChats() { -// addChat("Archived Chats", "Your archived chats", "10:45", 0); -// addChat("Saved Messages", "Keep messages for later", "Yesterday", 0); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// addChat("Alice", "Hey, how are you?", "14:12", 3); -// addChat("Bob", "Let's meet tomorrow", "12:08", 1); -// -// -// } - - // ... private String formatChatTime(java.time.LocalDateTime ts) { if (ts == null) return ""; var today = java.time.LocalDate.now(); @@ -441,20 +417,6 @@ public class MainController { } } -// private void addChat(String name, String lastMsg, String time, int unread) { -// try { -// FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml")); -// Node chatItem = loader.load(); -// ChatItemController controller = loader.getController(); -// controller.setChatData(name, lastMsg, time, unread); -// -// chatItem.setOnMouseClicked(e -> openChat(name)); -// chatListContainer.getChildren().add(chatItem); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// } - private void openChat(ChatEntry chat) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_page.fxml")); diff --git a/src/main/resources/org/to/telegramfinalproject/Avatars/img.png b/src/main/resources/org/to/telegramfinalproject/Avatars/img.png new file mode 100644 index 0000000..281de74 Binary files /dev/null and b/src/main/resources/org/to/telegramfinalproject/Avatars/img.png differ