fix chat header
This commit is contained in:
@@ -172,11 +172,25 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
bumpChatListFromUpdate(data);
|
bumpChatListFromUpdate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "user_status_changed" -> {
|
||||||
|
|
||||||
|
displayRealTimeMessage(action, msg);
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
var mc = org.to.telegramfinalproject.UI.MainController.getInstance();
|
||||||
|
var cp = (mc != null) ? mc.getChatPageController() : null;
|
||||||
|
if (cp != null) cp.onUserStatusChanged(
|
||||||
|
msg.optString("user_id",""),
|
||||||
|
msg.optString("status",""),
|
||||||
|
msg.optString("last_seen","")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "message_edited", "message_deleted_global", "message_reacted", "message_unreacted",
|
|
||||||
"user_status_changed", "blocked_by_user", "unblocked_by_user", "message_seen" -> {
|
case "message_edited", "message_deleted_global", "message_reacted", "message_unreacted"
|
||||||
|
, "blocked_by_user", "unblocked_by_user", "message_seen" -> {
|
||||||
displayRealTimeMessage(action, msg);
|
displayRealTimeMessage(action, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package org.to.telegramfinalproject.Database;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ChatInfoDatabase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* هدر چت را بر اساس نوع آن برمیگرداند.
|
||||||
|
* private: name,image_url, online,last_seen
|
||||||
|
* group : name,image_url, member_count
|
||||||
|
* channel: name,image_url, member_count
|
||||||
|
*/
|
||||||
|
public static JSONObject getHeaderInfo(String type, UUID receiverId, UUID viewerId) throws SQLException {
|
||||||
|
try (Connection conn = ConnectionDb.connect()) {
|
||||||
|
switch (type.toLowerCase()) {
|
||||||
|
case "private":
|
||||||
|
return getPrivateHeader(conn, receiverId, viewerId);
|
||||||
|
case "group":
|
||||||
|
return getGroupHeader(conn, receiverId);
|
||||||
|
case "channel":
|
||||||
|
return getChannelHeader(conn, receiverId);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unsupported receiver_type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** هدر چت خصوصی: other-user نسبت به viewerId را پیدا میکنیم */
|
||||||
|
private static JSONObject getPrivateHeader(Connection conn, UUID chatId, UUID viewerId) throws SQLException {
|
||||||
|
if (viewerId == null) throw new IllegalArgumentException("viewerId is required for private header.");
|
||||||
|
|
||||||
|
final String sql = """
|
||||||
|
SELECT
|
||||||
|
u.profile_name AS name,
|
||||||
|
COALESCE(u.image_url, '') AS image_url,
|
||||||
|
(u.status = 'online') AS online,
|
||||||
|
u.status AS status,
|
||||||
|
u.last_seen AS last_seen
|
||||||
|
FROM private_chat pc
|
||||||
|
JOIN users u
|
||||||
|
ON u.internal_uuid = CASE WHEN pc.user1_id = ? THEN pc.user2_id ELSE pc.user1_id END
|
||||||
|
WHERE pc.chat_id = ?
|
||||||
|
AND (pc.user1_id = ? OR pc.user2_id = ?)
|
||||||
|
LIMIT 1
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
int i = 1;
|
||||||
|
ps.setObject(i++, viewerId);
|
||||||
|
ps.setObject(i++, chatId);
|
||||||
|
ps.setObject(i++, viewerId);
|
||||||
|
ps.setObject(i++, viewerId);
|
||||||
|
|
||||||
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
|
if (!rs.next()) throw new SQLException("Private chat not found or viewer is not a participant.");
|
||||||
|
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
j.put("type", "private");
|
||||||
|
j.put("name", rs.getString("name"));
|
||||||
|
j.put("image_url", rs.getString("image_url"));
|
||||||
|
|
||||||
|
// خواندن بولینِ online با سازگاری DB
|
||||||
|
Object onlineObj = rs.getObject("online");
|
||||||
|
boolean online = (onlineObj instanceof Boolean) ? (Boolean) onlineObj
|
||||||
|
: rs.getInt("online") == 1;
|
||||||
|
j.put("online", online);
|
||||||
|
j.put("status", rs.getString("status")); // رشتهی وضعیت هم میآید
|
||||||
|
|
||||||
|
Timestamp ts = rs.getTimestamp("last_seen");
|
||||||
|
j.put("last_seen", ts == null ? JSONObject.NULL : ts.toInstant().toString());
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** هدر گروه: نام، عکس و تعداد اعضا */
|
||||||
|
private static JSONObject getGroupHeader(Connection conn, UUID groupInternalId) throws SQLException {
|
||||||
|
String sql = """
|
||||||
|
SELECT
|
||||||
|
g.group_name AS name,
|
||||||
|
COALESCE(g.image_url, '') AS image_url,
|
||||||
|
(SELECT COUNT(*) FROM group_members gm WHERE gm.group_id = g.internal_uuid) AS member_count
|
||||||
|
FROM groups g
|
||||||
|
WHERE g.internal_uuid = ?
|
||||||
|
LIMIT 1
|
||||||
|
""";
|
||||||
|
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, groupInternalId);
|
||||||
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
|
if (!rs.next()) throw new SQLException("Group not found.");
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
j.put("type", "group");
|
||||||
|
j.put("name", rs.getString("name"));
|
||||||
|
j.put("image_url", rs.getString("image_url"));
|
||||||
|
j.put("member_count", rs.getInt("member_count"));
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** هدر کانال: نام، عکس و تعداد سابسکرایبر */
|
||||||
|
private static JSONObject getChannelHeader(Connection conn, UUID channelInternalId) throws SQLException {
|
||||||
|
String sql = """
|
||||||
|
SELECT
|
||||||
|
c.channel_name AS name,
|
||||||
|
COALESCE(c.image_url, '') AS image_url,
|
||||||
|
(SELECT COUNT(*) FROM channel_subscribers cs WHERE cs.channel_id = c.internal_uuid) AS member_count
|
||||||
|
FROM channels c
|
||||||
|
WHERE c.internal_uuid = ?
|
||||||
|
LIMIT 1
|
||||||
|
""";
|
||||||
|
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, channelInternalId);
|
||||||
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
|
if (!rs.next()) throw new SQLException("Channel not found.");
|
||||||
|
JSONObject j = new JSONObject();
|
||||||
|
j.put("type", "channel");
|
||||||
|
j.put("name", rs.getString("name"));
|
||||||
|
j.put("image_url", rs.getString("image_url"));
|
||||||
|
j.put("member_count", rs.getInt("member_count"));
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -448,22 +448,19 @@ public class MessageDatabase {
|
|||||||
|
|
||||||
|
|
||||||
public static List<Message> getUnreadMessages(UUID userId) {
|
public static List<Message> getUnreadMessages(UUID userId) {
|
||||||
return getUnreadMessages(userId, 200); // یک سقف معقول
|
return getUnreadMessages(userId, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Message> getUnreadMessages(UUID userId, int limit) {
|
public static List<Message> getUnreadMessages(UUID userId, int limit) {
|
||||||
List<Message> messages = new ArrayList<>();
|
List<Message> messages = new ArrayList<>();
|
||||||
|
|
||||||
// توجه: نام جدول private_chats/gm/cs را با اسامی واقعی دیتابیست هماهنگ کن
|
|
||||||
String sql = """
|
String sql = """
|
||||||
SELECT m.*
|
SELECT m.*
|
||||||
FROM messages m
|
FROM messages m
|
||||||
LEFT JOIN message_receipts r
|
LEFT JOIN message_receipts r
|
||||||
ON r.message_id = m.message_id
|
ON r.message_id = m.message_id AND r.user_id = ?
|
||||||
AND r.user_id = ?
|
|
||||||
LEFT JOIN deleted_messages d
|
LEFT JOIN deleted_messages d
|
||||||
ON d.message_id = m.message_id
|
ON d.message_id = m.message_id AND d.user_id = ?
|
||||||
AND d.user_id = ?
|
|
||||||
WHERE r.message_id IS NULL
|
WHERE r.message_id IS NULL
|
||||||
AND d.message_id IS NULL
|
AND d.message_id IS NULL
|
||||||
AND m.is_deleted_globally = FALSE
|
AND m.is_deleted_globally = FALSE
|
||||||
@@ -474,14 +471,14 @@ public class MessageDatabase {
|
|||||||
FROM private_chat pc
|
FROM private_chat pc
|
||||||
WHERE pc.chat_id = m.receiver_id
|
WHERE pc.chat_id = m.receiver_id
|
||||||
AND (pc.user1_id = ? OR pc.user2_id = ?)
|
AND (pc.user1_id = ? OR pc.user2_id = ?)
|
||||||
)))
|
))
|
||||||
OR (m.receiver_type = 'group' AND EXISTS (
|
OR (m.receiver_type = 'group' AND EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM group_members gm
|
FROM group_members gm
|
||||||
WHERE gm.group_id = m.receiver_id
|
WHERE gm.group_id = m.receiver_id
|
||||||
AND gm.user_id = ?
|
AND gm.user_id = ?
|
||||||
))
|
))
|
||||||
OR (m.receiver_type = 'channel' AND EXISTS (
|
OR (m.receiver_type = 'channel' AND EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM channel_subscribers cs
|
FROM channel_subscribers cs
|
||||||
WHERE cs.channel_id = m.receiver_id
|
WHERE cs.channel_id = m.receiver_id
|
||||||
@@ -499,16 +496,14 @@ public class MessageDatabase {
|
|||||||
ps.setObject(i++, userId); // r.user_id
|
ps.setObject(i++, userId); // r.user_id
|
||||||
ps.setObject(i++, userId); // d.user_id
|
ps.setObject(i++, userId); // d.user_id
|
||||||
ps.setObject(i++, userId); // m.sender_id <> ?
|
ps.setObject(i++, userId); // m.sender_id <> ?
|
||||||
ps.setObject(i++, userId); // pc.user1_id=userId
|
ps.setObject(i++, userId); // pc.user1_id
|
||||||
ps.setObject(i++, userId); // pc.user2_id=userId
|
ps.setObject(i++, userId); // pc.user2_id
|
||||||
ps.setObject(i++, userId); // gm.user_id
|
ps.setObject(i++, userId); // gm.user_id
|
||||||
ps.setObject(i++, userId); // cs.user_id
|
ps.setObject(i++, userId); // cs.user_id
|
||||||
ps.setInt(i++, Math.max(1, limit));
|
ps.setInt(i, Math.max(1, limit));
|
||||||
|
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
while (rs.next()) {
|
while (rs.next()) messages.add(mapMessage(rs));
|
||||||
messages.add(mapMessage(rs)); // همان mapMessage که گفتیم
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -517,6 +512,7 @@ public class MessageDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static java.util.UUID readUUID(ResultSet rs, String col) throws SQLException {
|
private static java.util.UUID readUUID(ResultSet rs, String col) throws SQLException {
|
||||||
Object o = rs.getObject(col);
|
Object o = rs.getObject(col);
|
||||||
if (o == null) return null;
|
if (o == null) return null;
|
||||||
|
|||||||
@@ -2808,6 +2808,37 @@ public class ClientHandler implements Runnable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
case "get_header_info": {
|
||||||
|
try {
|
||||||
|
String type = requestJson.getString("receiver_type"); // "private" | "group" | "channel"
|
||||||
|
UUID receiverId = UUID.fromString(requestJson.getString("receiver_id"));
|
||||||
|
|
||||||
|
UUID viewerId = null;
|
||||||
|
if ("private".equalsIgnoreCase(type)) {
|
||||||
|
String v = requestJson.optString("viewer_id",
|
||||||
|
requestJson.optString("my_id", null));
|
||||||
|
if (v == null) {
|
||||||
|
response = new ResponseModel("error", "viewer_id (or my_id) is required for private chats.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
viewerId = UUID.fromString(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
org.json.JSONObject data = org.to.telegramfinalproject.Database.ChatInfoDatabase
|
||||||
|
.getHeaderInfo(type, receiverId, viewerId);
|
||||||
|
|
||||||
|
response = new ResponseModel("success", "Header info fetched.", data);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
response = new ResponseModel("error", "Failed to fetch header info.");
|
||||||
|
}
|
||||||
|
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.time.temporal.ChronoUnit;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -536,7 +537,7 @@ public class ChatPageController {
|
|||||||
|
|
||||||
chatTitle.setText(entry.getName());
|
chatTitle.setText(entry.getName());
|
||||||
|
|
||||||
// Default avatar
|
// آواتار پیشفرض بر اساس نوع
|
||||||
if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) {
|
if (entry.getImageUrl() != null && !entry.getImageUrl().isEmpty()) {
|
||||||
userAvatar.setImage(new Image(entry.getImageUrl()));
|
userAvatar.setImage(new Image(entry.getImageUrl()));
|
||||||
} else if ("channel".equals(entry.getType())) {
|
} else if ("channel".equals(entry.getType())) {
|
||||||
@@ -557,43 +558,9 @@ public class ChatPageController {
|
|||||||
}
|
}
|
||||||
userAvatar.setClip(new Circle(20, 20, 20));
|
userAvatar.setClip(new Circle(20, 20, 20));
|
||||||
|
|
||||||
// === Private chat? Fetch other user status ===
|
fetchAndRenderHeader(entry);
|
||||||
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);
|
||||||
@@ -601,6 +568,7 @@ public class ChatPageController {
|
|||||||
Platform.runLater(() -> messageInput.requestFocus());
|
Platform.runLater(() -> messageInput.requestFocus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void loadMessages(ChatEntry entry) {
|
private void loadMessages(ChatEntry entry) {
|
||||||
JSONObject req = new JSONObject();
|
JSONObject req = new JSONObject();
|
||||||
req.put("action", "get_messages_UI");
|
req.put("action", "get_messages_UI");
|
||||||
@@ -993,4 +961,140 @@ public class ChatPageController {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void fetchAndRenderHeader(ChatEntry entry) {
|
||||||
|
JSONObject req = new JSONObject();
|
||||||
|
req.put("action", "get_header_info");
|
||||||
|
req.put("receiver_id", entry.getId().toString());
|
||||||
|
req.put("receiver_type", entry.getType()); // باید "private" باشه
|
||||||
|
|
||||||
|
// 👇 اضافه کن: آیدی کاربر فعلی (current user)
|
||||||
|
UUID viewerId = UUID.fromString(Session.getUserUUID()); // هر جایی که نگه میداری
|
||||||
|
if ("private".equalsIgnoreCase(entry.getType()) && viewerId != null) {
|
||||||
|
req.put("viewer_id", viewerId.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
JSONObject resp;
|
||||||
|
try {
|
||||||
|
resp = org.to.telegramfinalproject.Client.ActionHandler.sendWithResponse(req);
|
||||||
|
} catch (Exception ex) { ex.printStackTrace(); return; }
|
||||||
|
|
||||||
|
if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) {
|
||||||
|
System.err.println("get_header_info failed: " + (resp != null ? resp.optString("message") : "null resp"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSONObject data = resp.optJSONObject("data");
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
Platform.runLater(() -> renderHeaderFromData(entry, data));
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderHeaderFromData(ChatEntry entry, JSONObject data) {
|
||||||
|
String t = entry.getType() == null ? "" : entry.getType().toLowerCase();
|
||||||
|
switch (t) {
|
||||||
|
case "private" -> updatePrivateHeader(entry, data);
|
||||||
|
case "group" -> updateGroupHeader(entry, data);
|
||||||
|
case "channel" -> updateChannelHeader(entry, data);
|
||||||
|
default -> chatStatus.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePrivateHeader(ChatEntry entry, JSONObject data) {
|
||||||
|
String name = nz(data.optString("profile_name", entry.getName()));
|
||||||
|
chatTitle.setText(name);
|
||||||
|
|
||||||
|
// other_user_id برای ریلتایم status
|
||||||
|
String other = data.optString("other_user_id", "");
|
||||||
|
if (!other.isBlank()) {
|
||||||
|
try { entry.setOtherUserId(java.util.UUID.fromString(other)); } catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// تصویر
|
||||||
|
String img = data.optString("image_url", "");
|
||||||
|
if (hasVal(img)) {
|
||||||
|
try {
|
||||||
|
userAvatar.setImage(new Image(img, true));
|
||||||
|
userAvatar.setClip(new Circle(20, 20, 20));
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
chatStatus.setText(userStatusText(
|
||||||
|
data.optBoolean("online", false),
|
||||||
|
data.optString("last_seen", null)
|
||||||
|
));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGroupHeader(ChatEntry entry, JSONObject data) {
|
||||||
|
chatTitle.setText(nz(data.optString("group_name", entry.getName())));
|
||||||
|
|
||||||
|
String img = data.optString("image_url", "");
|
||||||
|
if (hasVal(img)) {
|
||||||
|
try {
|
||||||
|
userAvatar.setImage(new Image(img, true));
|
||||||
|
userAvatar.setClip(new Circle(20, 20, 20));
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
int members = data.optInt("member_count", 0);
|
||||||
|
int online = data.optInt("online_count", -1);
|
||||||
|
chatStatus.setText(online >= 0 ? (members + " members, " + online + " online")
|
||||||
|
: (members + " members"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChannelHeader(ChatEntry entry, JSONObject data) {
|
||||||
|
chatTitle.setText(nz(data.optString("channel_name", entry.getName())));
|
||||||
|
|
||||||
|
String img = data.optString("image_url", "");
|
||||||
|
if (hasVal(img)) {
|
||||||
|
try {
|
||||||
|
userAvatar.setImage(new Image(img, true));
|
||||||
|
userAvatar.setClip(new Circle(20, 20, 20));
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
int subs = data.optInt("member_count", 0);
|
||||||
|
chatStatus.setText(subs + " subscribers");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUserStatusChanged(String userUuid, String status, String lastSeenIso) {
|
||||||
|
if (currentChat == null || !"private".equalsIgnoreCase(currentChat.getType())) return;
|
||||||
|
var other = currentChat.getOtherUserId();
|
||||||
|
if (other == null || !other.toString().equalsIgnoreCase(userUuid)) return;
|
||||||
|
|
||||||
|
if ("online".equalsIgnoreCase(status)) {
|
||||||
|
chatStatus.setText("online");
|
||||||
|
} else {
|
||||||
|
if (hasVal(lastSeenIso)) {
|
||||||
|
var ts = parseWhen(lastSeenIso);
|
||||||
|
chatStatus.setText(ts != null ? ("last seen " + formatWhen(ts)) : "last seen recently");
|
||||||
|
} else {
|
||||||
|
chatStatus.setText("last seen recently");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String userStatusText(boolean online, String lastSeenIso) {
|
||||||
|
if (online) return "online";
|
||||||
|
|
||||||
|
LocalDateTime ts = parseWhen(lastSeenIso);
|
||||||
|
if (ts == null) return "Last seen recently";
|
||||||
|
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
LocalDate d = ts.toLocalDate();
|
||||||
|
|
||||||
|
if (d.isEqual(today)) {
|
||||||
|
return FMT_HHMM.format(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
long days = ChronoUnit.DAYS.between(d, today);
|
||||||
|
if (days > 30) {
|
||||||
|
return "Last seen long time ago";
|
||||||
|
}
|
||||||
|
return "recently";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -963,4 +963,11 @@ public class MainController {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user