Last seen & profile in chat fixed.

This commit is contained in:
Asal Lotfi
2025-08-31 03:17:27 +03:30
parent 186d890e7d
commit bdd9d03128
4 changed files with 129 additions and 95 deletions
@@ -2778,6 +2778,35 @@ public class ClientHandler implements Runnable {
break; 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: default:
response = new ResponseModel("error", "Unknown action: " + action); response = new ResponseModel("error", "Unknown action: " + action);
@@ -23,6 +23,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
public class ChatPageController { 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) { 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 ""; } 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(); MainController.getInstance().showSearchPanel();
} }
/** // /**
* Called by main controller when opening a chat. // * Called by main controller when opening a chat.
*/ // */
public void setChat(String chatName, String avatarPath) { // public void setChat(String chatName, String avatarPath) {
this.chatName = chatName; // this.chatName = chatName;
//
// Header text (if present) // // Header text (if present)
if (chatTitle != null) chatTitle.setText(chatName); // if (chatTitle != null) chatTitle.setText(chatName);
if (chatStatus != null) chatStatus.setText("last seen recently"); // or live status // if (chatStatus != null) chatStatus.setText("last seen recently"); // or live status
//
// Load avatar if provided // // Load avatar if provided
if (userAvatar != null && avatarPath != null) { // if (userAvatar != null && avatarPath != null) {
try { // try {
Image avatarImg = new Image(getClass().getResourceAsStream(avatarPath)); // Image avatarImg = new Image(getClass().getResourceAsStream(avatarPath));
userAvatar.setImage(avatarImg); // userAvatar.setImage(avatarImg);
Circle clip = new Circle(18, 18, 18); // x, y, radius // Circle clip = new Circle(18, 18, 18); // x, y, radius
userAvatar.setClip(clip); // userAvatar.setClip(clip);
} catch (Exception e) { // } catch (Exception e) {
System.err.println("Could not load avatar: " + avatarPath); // System.err.println("Could not load avatar: " + avatarPath);
} // }
} // }
//
addSystemMessage("Chat with " + chatName + " opened."); // addSystemMessage("Chat with " + chatName + " opened.");
Platform.runLater(() -> messageInput.requestFocus()); // Platform.runLater(() -> messageInput.requestFocus());
} // }
// ----- actions ----- // ----- actions -----
@@ -467,24 +462,24 @@ public class ChatPageController {
// ----- UI helpers ----- // ----- UI helpers -----
/** // /**
* Add a normal message bubble (very simple for now). // * Add a normal message bubble (very simple for now).
*/ // */
public void addMessage(String sender, String content) { // public void addMessage(String sender, String content) {
Label msg = new Label(sender + ": " + content); // Label msg = new Label(sender + ": " + content);
msg.setWrapText(true); // msg.setWrapText(true);
//
boolean dark = themeManager.isDarkMode(); // boolean dark = themeManager.isDarkMode();
String bubbleColor = dark ? "#20405a" : "#4fa8f0"; // String bubbleColor = dark ? "#20405a" : "#4fa8f0";
String textColor = dark ? "#e8f1f8" : "#0f141a"; // String textColor = dark ? "#e8f1f8" : "#0f141a";
msg.setStyle( // msg.setStyle(
"-fx-background-color: " + bubbleColor + ";" + // "-fx-background-color: " + bubbleColor + ";" +
"-fx-text-fill: " + textColor + ";" + // "-fx-text-fill: " + textColor + ";" +
"-fx-padding: 6 10; -fx-background-radius: 10;" // "-fx-padding: 6 10; -fx-background-radius: 10;"
); // );
//
messageContainer.getChildren().add(msg); // messageContainer.getChildren().add(msg);
} // }
private void addSystemMessage(String content) { private void addSystemMessage(String content) {
Label sys = new Label(content); Label sys = new Label(content);
@@ -539,20 +534,68 @@ public class ChatPageController {
public void showChat(ChatEntry entry) { public void showChat(ChatEntry entry) {
this.currentChat = entry; this.currentChat = entry;
// Header
chatTitle.setText(entry.getName()); chatTitle.setText(entry.getName());
chatStatus.setText("");
// Default avatar
if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) { if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) {
try { userAvatar.setImage(new Image(entry.getImageUrl()));
userAvatar.setImage(new Image(entry.getImageUrl() != null ? entry.getImageUrl() : "/org/to/telegramfinalproject/Avatars/default_user_profile.png")); } else if ("channel".equals(entry.getType())) {
userAvatar.setClip(new Circle(18, 18, 18)); userAvatar.setImage(new Image(
} catch (Exception ignored) { 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(); messageContainer.getChildren().clear();
loadMessages(entry); loadMessages(entry);
markAsRead(entry); markAsRead(entry);
Platform.runLater(() -> messageInput.requestFocus()); Platform.runLater(() -> messageInput.requestFocus());
@@ -287,30 +287,6 @@ public class MainController {
searchBar.clear(); 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) { private String formatChatTime(java.time.LocalDateTime ts) {
if (ts == null) return ""; if (ts == null) return "";
var today = java.time.LocalDate.now(); 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) { private void openChat(ChatEntry chat) {
try { try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_page.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_page.fxml"));
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB