Last seen & profile in chat fixed.
This commit is contained in:
@@ -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 |
Reference in New Issue
Block a user