Work on send message Real time in UI
This commit is contained in:
@@ -42,10 +42,21 @@ public class ActionHandler {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// private void handleRealTime(JSONObject json) throws IOException {
|
||||||
|
// IncomingMessageListener listener = new IncomingMessageListener(this.in);
|
||||||
|
// listener.handleRealTimeEvent (json);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ActionHandler.java
|
||||||
private void handleRealTime(JSONObject json) throws IOException {
|
private void handleRealTime(JSONObject json) throws IOException {
|
||||||
IncomingMessageListener listener = new IncomingMessageListener(this.in);
|
IncomingMessageListener listener = TelegramClient.getInstance().getListener();
|
||||||
|
if (listener != null) {
|
||||||
listener.handleRealTimeEvent(json);
|
listener.handleRealTimeEvent(json);
|
||||||
|
} else {
|
||||||
|
System.err.println("[RT] Listener not ready; dropping RT event: " + json);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ActionHandler(PrintWriter out, BufferedReader in, Scanner scanner) {
|
public ActionHandler(PrintWriter out, BufferedReader in, Scanner scanner) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.in = in;
|
this.in = in;
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
package org.to.telegramfinalproject.Client;
|
package org.to.telegramfinalproject.Client;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.to.telegramfinalproject.Models.ChatEntry;
|
import org.to.telegramfinalproject.Models.ChatEntry;
|
||||||
|
import org.to.telegramfinalproject.UI.MainController;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
public class IncomingMessageListener implements Runnable {
|
public class IncomingMessageListener implements Runnable {
|
||||||
private final BufferedReader in;
|
private final BufferedReader in;
|
||||||
|
public enum UIMode { CONSOLE, UI }
|
||||||
|
private final UIMode uiMode; // runtime mode
|
||||||
|
|
||||||
public IncomingMessageListener(BufferedReader in) {
|
private final java.util.Set<String> seenMessageIds =
|
||||||
|
java.util.Collections.newSetFromMap(new java.util.concurrent.ConcurrentHashMap<>());
|
||||||
|
|
||||||
|
|
||||||
|
public IncomingMessageListener(BufferedReader in, UIMode uiMode) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
|
this.uiMode = uiMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public IncomingMessageListener(BufferedReader in) {
|
||||||
|
// this.in = in;
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
@@ -79,7 +94,7 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
"update_group_or_channel", "chat_deleted",
|
"update_group_or_channel", "chat_deleted",
|
||||||
"blocked_by_user", "unblocked_by_user", "message_seen",
|
"blocked_by_user", "unblocked_by_user", "message_seen",
|
||||||
"removed_from_group", "removed_from_channel",
|
"removed_from_group", "removed_from_channel",
|
||||||
"became_admin", "removed_admin", "ownership_transferred","admin_permissions_updated","created_private_chat" , "message_reacted" , "message_unreacted" -> true;
|
"became_admin", "removed_admin", "ownership_transferred","admin_permissions_updated","created_private_chat" , "message_reacted" , "message_unreacted","chat_updated" -> true;
|
||||||
default -> false;
|
default -> false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -88,13 +103,15 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
String action = response.getString("action");
|
String action = response.getString("action");
|
||||||
JSONObject msg = response.has("data") ? response.getJSONObject("data") : new JSONObject();
|
JSONObject msg = response.has("data") ? response.getJSONObject("data") : new JSONObject();
|
||||||
|
|
||||||
|
JSONObject finalMsg = msg;
|
||||||
|
JSONObject finalMsg1 = msg;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "added_to_group", "added_to_channel",
|
case "added_to_group", "added_to_channel",
|
||||||
"removed_from_group", "removed_from_channel", "chat_deleted","created_private_chat" -> {
|
"removed_from_group", "removed_from_channel",
|
||||||
|
"chat_deleted", "created_private_chat" -> {
|
||||||
|
// این قسمت مستقل از UI/کنسول است
|
||||||
System.out.println("🔄 Chat list changed. Updating...");
|
System.out.println("🔄 Chat list changed. Updating...");
|
||||||
Session.forceRefreshChatList = true;
|
Session.forceRefreshChatList = true;
|
||||||
System.out.println("🧪 Calling requestChatList() after being added");
|
|
||||||
|
|
||||||
String chatId = msg.getString("chat_id");
|
String chatId = msg.getString("chat_id");
|
||||||
String chatType = msg.getString("chat_type");
|
String chatType = msg.getString("chat_type");
|
||||||
@@ -106,36 +123,67 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case "chat_updated" -> {
|
// case "chat_updated" -> {
|
||||||
System.out.println("\n🔄 Chat info updated.");
|
// if (uiMode == UIMode.UI) {
|
||||||
|
// bumpChatListFromUpdate(msg); // برای UI (سایدبار و سورت)
|
||||||
if (msg.has("last_message_time")) {
|
// } else {
|
||||||
updateLastMessageTime(msg);
|
// updateLastMessageTime(msg); // برای کنسول (لیستهای Session)
|
||||||
} else {
|
// }
|
||||||
new Thread(() -> {
|
// }
|
||||||
try {
|
|
||||||
handleAdminRoleChanged(msg);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case "became_admin", "removed_admin", "ownership_transferred", "admin_permissions_updated" -> {
|
case "became_admin", "removed_admin", "ownership_transferred", "admin_permissions_updated" -> {
|
||||||
System.out.println("🧩 Detected admin/owner role change. Calling handler...");
|
System.out.println("🧩 Detected admin/owner role change. Calling handler...");
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
handleAdminRoleChanged(msg); //new thread
|
handleAdminRoleChanged(finalMsg1);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "new_message" -> {
|
||||||
|
JSONObject data = response.optJSONObject("data");
|
||||||
|
if (data == null) break;
|
||||||
|
|
||||||
default -> displayRealTimeMessage(action, msg);
|
String mid = data.optString("id", data.optString("message_id",""));
|
||||||
|
if (mid.isEmpty()) break;
|
||||||
|
if (!seenMessageIds.add(mid)) break;
|
||||||
|
|
||||||
|
bumpChatListFromMessage(data);
|
||||||
|
|
||||||
|
JSONObject uiMsg = new JSONObject(data.toString());
|
||||||
|
if (!uiMsg.has("message_id") && uiMsg.has("id")) {
|
||||||
|
uiMsg.put("message_id", uiMsg.getString("id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
var mc = MainController.getInstance();
|
||||||
|
var chatCtl = (mc != null) ? mc.getChatPageController() : null;
|
||||||
|
if (chatCtl != null) {
|
||||||
|
chatCtl.onRealTimeNewMessage(uiMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "chat_updated" -> {
|
||||||
|
var data = response.getJSONObject("data");
|
||||||
|
bumpChatListFromUpdate(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
case "message_edited", "message_deleted_global", "message_reacted", "message_unreacted",
|
||||||
|
"user_status_changed", "blocked_by_user", "unblocked_by_user", "message_seen" -> {
|
||||||
|
displayRealTimeMessage(action, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
default -> {
|
||||||
|
System.out.println("\n❓ Unknown real-time action: " + action);
|
||||||
|
System.out.println(msg.toString(2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.print(">> ");
|
System.out.print(">> ");
|
||||||
@@ -362,4 +410,58 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static LocalDateTime parseIsoFlexible(String iso) {
|
||||||
|
if (iso == null || iso.isBlank()) return null;
|
||||||
|
try { return LocalDateTime.parse(iso); } catch (Exception ignore) {}
|
||||||
|
try { return OffsetDateTime.parse(iso).toLocalDateTime(); } catch (Exception ignore) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void bumpChatListFromUpdate(JSONObject data) {
|
||||||
|
try {
|
||||||
|
UUID chatId = UUID.fromString(data.optString("chat_id",""));
|
||||||
|
String chatType = data.optString("chat_type","");
|
||||||
|
LocalDateTime ts = parseIsoFlexible(data.optString("last_message_time", null));
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
var mc = MainController.getInstance();
|
||||||
|
if (mc != null) mc.onChatUpdated(chatId, chatType, ts, /*isIncoming*/ false, null);
|
||||||
|
});
|
||||||
|
} catch (Exception e) { System.err.println("[RT] bumpChatListFromUpdate: " + e.getMessage()); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String previewOf(String type, String content) {
|
||||||
|
String t = type == null ? "" : type.trim().toUpperCase();
|
||||||
|
return switch (t) {
|
||||||
|
case "IMAGE" -> "[Image]";
|
||||||
|
case "AUDIO" -> "[Audio]";
|
||||||
|
case "VIDEO" -> "[Video]";
|
||||||
|
case "FILE" -> "[File]";
|
||||||
|
default -> (content == null ? "" : content);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bumpChatListFromMessage(JSONObject m) {
|
||||||
|
try {
|
||||||
|
UUID chatId = UUID.fromString(m.optString("receiver_id",""));
|
||||||
|
String chatType = m.optString("receiver_type","");
|
||||||
|
LocalDateTime ts = parseIsoFlexible(m.optString("send_at", null));
|
||||||
|
|
||||||
|
String preview = previewOf(m.optString("message_type","TEXT"),
|
||||||
|
m.optString("content",""));
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
var mc = MainController.getInstance();
|
||||||
|
if (mc != null) mc.onChatUpdated(chatId, chatType, ts, /*isIncoming*/ true, preview);
|
||||||
|
});
|
||||||
|
} catch (Exception e) { System.err.println("[RT] bumpChatListFromMessage: " + e.getMessage()); }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,11 +171,22 @@ public class TelegramClient {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public void startConsole() {
|
||||||
|
// try {
|
||||||
|
// connectIfNeeded();
|
||||||
|
// initHandlerIfNeeded();
|
||||||
|
// startListenerOnce();
|
||||||
|
// showMainMenu();
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// System.err.println("❌ Error connecting to server: " + e.getMessage());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
public void startConsole() {
|
public void startConsole() {
|
||||||
try {
|
try {
|
||||||
connectIfNeeded();
|
connectIfNeeded();
|
||||||
initHandlerIfNeeded();
|
initHandlerIfNeeded();
|
||||||
startListenerOnce();
|
startListenerOnce(IncomingMessageListener.UIMode.CONSOLE); // ← کنسول
|
||||||
showMainMenu();
|
showMainMenu();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("❌ Error connecting to server: " + e.getMessage());
|
System.err.println("❌ Error connecting to server: " + e.getMessage());
|
||||||
@@ -185,14 +196,23 @@ public class TelegramClient {
|
|||||||
public void start() { startConsole(); }
|
public void start() { startConsole(); }
|
||||||
|
|
||||||
//UI only
|
//UI only
|
||||||
|
// public static synchronized TelegramClient getOrInitForUI() throws IOException {
|
||||||
|
// TelegramClient cli = getInstance();
|
||||||
|
// cli.connectIfNeeded();
|
||||||
|
// cli.initHandlerIfNeeded();
|
||||||
|
// cli.startListenerOnce();
|
||||||
|
// return cli;
|
||||||
|
// }
|
||||||
|
|
||||||
public static synchronized TelegramClient getOrInitForUI() throws IOException {
|
public static synchronized TelegramClient getOrInitForUI() throws IOException {
|
||||||
TelegramClient cli = getInstance();
|
TelegramClient cli = getInstance();
|
||||||
cli.connectIfNeeded();
|
cli.connectIfNeeded();
|
||||||
cli.initHandlerIfNeeded();
|
cli.initHandlerIfNeeded();
|
||||||
cli.startListenerOnce();
|
cli.startListenerOnce(IncomingMessageListener.UIMode.UI); // ← UI
|
||||||
return cli;
|
return cli;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private synchronized void connectIfNeeded() throws IOException {
|
private synchronized void connectIfNeeded() throws IOException {
|
||||||
if (socket != null && socket.isConnected() && !socket.isClosed()) return;
|
if (socket != null && socket.isConnected() && !socket.isClosed()) return;
|
||||||
|
|
||||||
@@ -208,10 +228,23 @@ public class TelegramClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startListenerOnce() {
|
// private void startListenerOnce() {
|
||||||
|
// if (listenerStarted) return;
|
||||||
|
// listenerStarted = true;
|
||||||
|
// Thread listenerThread = new Thread(new IncomingMessageListener(in), "socket-listener");
|
||||||
|
// listenerThread.setDaemon(true);
|
||||||
|
// listenerThread.start();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private void startListenerOnce(IncomingMessageListener.UIMode mode) {
|
||||||
if (listenerStarted) return;
|
if (listenerStarted) return;
|
||||||
listenerStarted = true;
|
listenerStarted = true;
|
||||||
Thread listenerThread = new Thread(new IncomingMessageListener(in), "socket-listener");
|
|
||||||
|
Thread listenerThread = new Thread(
|
||||||
|
new IncomingMessageListener(in, mode),
|
||||||
|
"socket-listener"
|
||||||
|
);
|
||||||
listenerThread.setDaemon(true);
|
listenerThread.setDaemon(true);
|
||||||
listenerThread.start();
|
listenerThread.start();
|
||||||
}
|
}
|
||||||
@@ -269,5 +302,13 @@ public class TelegramClient {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new TelegramClient().startConsole();
|
new TelegramClient().startConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TelegramClient.java
|
||||||
|
private IncomingMessageListener listener;
|
||||||
|
|
||||||
|
public IncomingMessageListener getListener() {
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,4 +173,7 @@ public class ChatEntry {
|
|||||||
|
|
||||||
public UUID getLastMessageSenderId() { return lastMessageSenderId; }
|
public UUID getLastMessageSenderId() { return lastMessageSenderId; }
|
||||||
public void setLastMessageSenderId(UUID lastMessageSenderId) { this.lastMessageSenderId = lastMessageSenderId; }
|
public void setLastMessageSenderId(UUID lastMessageSenderId) { this.lastMessageSenderId = lastMessageSenderId; }
|
||||||
|
|
||||||
|
public void setUnread(int unreadCount){this.unreadCount = unreadCount;}
|
||||||
|
public int getUnread(){return unreadCount;}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1616,21 +1616,16 @@ public class ClientHandler implements Runnable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// دریافت شناسه چت و نوع حذف (یکطرفه یا دوطرفه)
|
|
||||||
UUID targetId = UUID.fromString(requestJson.getString("chat_id"));
|
UUID targetId = UUID.fromString(requestJson.getString("chat_id"));
|
||||||
boolean both = requestJson.getBoolean("both");
|
boolean both = requestJson.getBoolean("both");
|
||||||
|
|
||||||
// Real-Time Event Dispatch (اطلاعرسانی ریل تایم)
|
|
||||||
if (both) {
|
if (both) {
|
||||||
// حذف دوطرفه
|
|
||||||
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
||||||
RealTimeEventDispatcher.notifyChatDeleted("private", currentUser.getInternal_uuid(), List.of(targetId));
|
RealTimeEventDispatcher.notifyChatDeleted("private", currentUser.getInternal_uuid(), List.of(targetId));
|
||||||
} else {
|
} else {
|
||||||
// حذف یکطرفه
|
|
||||||
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// فراخوانی متد حذف چت
|
|
||||||
response = handleDeleteChat(requestJson);
|
response = handleDeleteChat(requestJson);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2910,6 +2905,8 @@ public class ClientHandler implements Runnable {
|
|||||||
RealTimeEventDispatcher.sendToUser(receiver, chatPayload);
|
RealTimeEventDispatcher.sendToUser(receiver, chatPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RealTimeEventDispatcher.sendToUser(senderId, chatPayload);
|
||||||
|
|
||||||
JSONObject data = new JSONObject();
|
JSONObject data = new JSONObject();
|
||||||
data.put("message_id", messageId.toString());
|
data.put("message_id", messageId.toString());
|
||||||
return new ResponseModel("success", "Message sent successfully.", data);
|
return new ResponseModel("success", "Message sent successfully.", data);
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ public class ChatPageController {
|
|||||||
// ===== state =====
|
// ===== state =====
|
||||||
private String chatName;
|
private String chatName;
|
||||||
private final ThemeManager themeManager = ThemeManager.getInstance();
|
private final ThemeManager themeManager = ThemeManager.getInstance();
|
||||||
|
private final java.util.Set<String> pendingClientMsgIds =
|
||||||
|
java.util.Collections.newSetFromMap(new java.util.concurrent.ConcurrentHashMap<>());
|
||||||
|
|
||||||
// Where your icons live
|
// Where your icons live
|
||||||
private static final String ICON_BASE = "/org/to/telegramfinalproject/Icons/";
|
private static final String ICON_BASE = "/org/to/telegramfinalproject/Icons/";
|
||||||
@@ -97,6 +99,7 @@ public class ChatPageController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void initCurrentUserId() {
|
private void initCurrentUserId() {
|
||||||
try {
|
try {
|
||||||
String meStr = org.to.telegramfinalproject.Client.Session
|
String meStr = org.to.telegramfinalproject.Client.Session
|
||||||
@@ -332,14 +335,127 @@ public class ChatPageController {
|
|||||||
|
|
||||||
// ----- actions -----
|
// ----- actions -----
|
||||||
|
|
||||||
|
// private void sendMessage() {
|
||||||
|
// String text = messageInput.getText() == null ? "" : messageInput.getText().trim();
|
||||||
|
// if (!text.isEmpty()) {
|
||||||
|
// addMessage("You", text);
|
||||||
|
// messageInput.clear();
|
||||||
|
// // TODO: send to server
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
private void sendMessage() {
|
private void sendMessage() {
|
||||||
String text = messageInput.getText() == null ? "" : messageInput.getText().trim();
|
// 0) Read and validate input
|
||||||
if (!text.isEmpty()) {
|
String raw = messageInput.getText();
|
||||||
addMessage("You", text);
|
String text = (raw == null) ? "" : raw.trim();
|
||||||
|
if (text.isEmpty()) return;
|
||||||
|
|
||||||
|
if (currentChat == null) {
|
||||||
|
addSystemMessage("No chat is selected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) Clear input immediately for good UX
|
||||||
messageInput.clear();
|
messageInput.clear();
|
||||||
// TODO: send to server
|
|
||||||
|
// 2) Snapshot chat info (must be final for lambdas)
|
||||||
|
final UUID targetChatId = currentChat.getId();
|
||||||
|
final String targetType = currentChat.getType(); // "private" | "group" | "channel"
|
||||||
|
final String contentToSend = text; // effectively final
|
||||||
|
|
||||||
|
// 3) Build the SAME JSON as your console method (for TEXT only)
|
||||||
|
org.json.JSONObject req = new org.json.JSONObject();
|
||||||
|
req.put("action", "send_message");
|
||||||
|
req.put("receiver_type", targetType);
|
||||||
|
req.put("receiver_id", targetChatId.toString());
|
||||||
|
req.put("content", contentToSend);
|
||||||
|
req.put("message_type", "TEXT");
|
||||||
|
|
||||||
|
// 4) Send on a background thread
|
||||||
|
new Thread(() -> {
|
||||||
|
org.json.JSONObject resp;
|
||||||
|
try {
|
||||||
|
resp = org.to.telegramfinalproject.Client.ActionHandler.sendWithResponse(req);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
Platform.runLater(() -> addSystemMessage("Send failed: " + ex.getMessage()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5) Check status like your console method
|
||||||
|
if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) {
|
||||||
|
String err = (resp != null) ? resp.optString("message", "No response") : "No response";
|
||||||
|
Platform.runLater(() -> addSystemMessage("Send failed: " + err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6) Extract fields (your console reads data.message_id; handle both shapes)
|
||||||
|
org.json.JSONObject data = resp.optJSONObject("data");
|
||||||
|
String messageId = null;
|
||||||
|
String sendAtIso = null;
|
||||||
|
if (data != null) {
|
||||||
|
// If server returns { data: { message_id, send_at, ... } }
|
||||||
|
messageId = data.optString("message_id", null);
|
||||||
|
|
||||||
|
// Some servers nest: { data: { message: {...} } }
|
||||||
|
if (messageId == null) {
|
||||||
|
org.json.JSONObject msgObj = data.optJSONObject("message");
|
||||||
|
if (msgObj != null) {
|
||||||
|
messageId = msgObj.optString("message_id", null);
|
||||||
|
sendAtIso = msgObj.optString("send_at", null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendAtIso = data.optString("send_at", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (messageId == null) messageId = java.util.UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
final java.time.LocalDateTime ts =
|
||||||
|
(sendAtIso != null && !sendAtIso.isBlank()) ? parseWhen(sendAtIso)
|
||||||
|
: java.time.LocalDateTime.now();
|
||||||
|
|
||||||
|
final String fMessageId = messageId;
|
||||||
|
final java.time.LocalDateTime fTs = ts;
|
||||||
|
|
||||||
|
// 7) Update UI on FX thread (render outgoing bubble + index for reply previews)
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
// If user switched chats while sending, don’t render here
|
||||||
|
if (currentChat == null || !currentChat.getId().equals(targetChatId)) return;
|
||||||
|
|
||||||
|
addBubble(
|
||||||
|
true, // outgoing
|
||||||
|
"You", // display name
|
||||||
|
"TEXT", // message type
|
||||||
|
contentToSend, // content
|
||||||
|
fTs, // timestamp
|
||||||
|
fMessageId, // message_id
|
||||||
|
"", "", "", // forwarded_from, forwarded_by, reply_to_id
|
||||||
|
false, // edited
|
||||||
|
null // reactions
|
||||||
|
);
|
||||||
|
|
||||||
|
//Real time
|
||||||
|
var mc = MainController.getInstance();
|
||||||
|
if (mc != null) {
|
||||||
|
String preview = "You: " + (contentToSend.isBlank() ? "[Message]" : contentToSend);
|
||||||
|
mc.onChatUpdated(targetChatId, targetType, fTs, /*isIncoming*/ false, preview);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep it in msgIndex for reply previews
|
||||||
|
org.json.JSONObject idx = new org.json.JSONObject();
|
||||||
|
idx.put("message_id", fMessageId);
|
||||||
|
idx.put("message_type", "TEXT");
|
||||||
|
idx.put("content", contentToSend);
|
||||||
|
idx.put("sender_name", "You");
|
||||||
|
idx.put("sender_id", (me != null) ? me.toString() : "");
|
||||||
|
idx.put("send_at", fTs.toString());
|
||||||
|
msgIndex.put(fMessageId, idx);
|
||||||
|
});
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void openFileChooser() {
|
private void openFileChooser() {
|
||||||
FileChooser fc = new FileChooser();
|
FileChooser fc = new FileChooser();
|
||||||
@@ -706,7 +822,6 @@ public class ChatPageController {
|
|||||||
row.setAlignment(outgoing ? javafx.geometry.Pos.CENTER_RIGHT
|
row.setAlignment(outgoing ? javafx.geometry.Pos.CENTER_RIGHT
|
||||||
: javafx.geometry.Pos.CENTER_LEFT);
|
: javafx.geometry.Pos.CENTER_LEFT);
|
||||||
|
|
||||||
// کمی padding اطراف هر پیام برای کاهش فاصلههای ناخوشایند
|
|
||||||
row.setPadding(new javafx.geometry.Insets(2, 6, 2, 6));
|
row.setPadding(new javafx.geometry.Insets(2, 6, 2, 6));
|
||||||
|
|
||||||
messageContainer.getChildren().add(row);
|
messageContainer.getChildren().add(row);
|
||||||
@@ -799,9 +914,64 @@ public class ChatPageController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean notBlank(String s) { return s != null && !s.isBlank(); }
|
|
||||||
private static String ellipsize(String s, int max) { return s.length() > max ? s.substring(0, max) + "…" : s; }
|
private static String ellipsize(String s, int max) { return s.length() > max ? s.substring(0, max) + "…" : s; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isSameChat(UUID chatId, String type) {
|
||||||
|
return currentChat != null
|
||||||
|
&& currentChat.getId().equals(chatId)
|
||||||
|
&& currentChat.getType().equalsIgnoreCase(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRealTimeNewMessage(JSONObject m) {
|
||||||
|
try {
|
||||||
|
String chatIdStr = str(m,"receiver_id");
|
||||||
|
String chatType = str(m,"receiver_type");
|
||||||
|
if (chatIdStr.isEmpty() || chatType.isEmpty()) return;
|
||||||
|
|
||||||
|
UUID chatId = UUID.fromString(chatIdStr);
|
||||||
|
if (!isSameChat(chatId, chatType)) {
|
||||||
|
System.out.println("[UI] RT msg for another chat: " + chatId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// id → message_id fallback
|
||||||
|
if (!m.has("message_id") && m.has("id")) {
|
||||||
|
m.put("message_id", m.getString("id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String senderName = hasVal(str(m,"sender_name")) ? str(m,"sender_name")
|
||||||
|
: (hasVal(str(m,"sender_id")) ? shortId(str(m,"sender_id")) : "Unknown");
|
||||||
|
|
||||||
|
String type = hasVal(str(m,"message_type")) ? str(m,"message_type") : "TEXT";
|
||||||
|
String content = str(m,"content");
|
||||||
|
String whenIso = str(m,"send_at");
|
||||||
|
String msgId = str(m,"message_id");
|
||||||
|
|
||||||
|
LocalDateTime ts = parseWhen(whenIso);
|
||||||
|
if (ts == null) ts = LocalDateTime.now();
|
||||||
|
|
||||||
|
addBubble(false, senderName, type, content, ts, msgId,
|
||||||
|
str(m,"forwarded_from"), str(m,"forwarded_by"), str(m,"reply_to_id"),
|
||||||
|
bool(m,"is_edited"), arr(m,"reactions"));
|
||||||
|
|
||||||
|
if (hasVal(msgId)) msgIndex.put(msgId, m);
|
||||||
|
|
||||||
|
if (currentChat != null) markAsRead(currentChat);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ import javafx.scene.Node;
|
|||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
import org.to.telegramfinalproject.Client.Session;
|
||||||
import org.to.telegramfinalproject.Models.ChatEntry;
|
import org.to.telegramfinalproject.Models.ChatEntry;
|
||||||
import org.to.telegramfinalproject.Client.ActionHandler;
|
import org.to.telegramfinalproject.Client.ActionHandler;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -75,6 +77,62 @@ public class MainController {
|
|||||||
private final Map<UUID, ChatItemController> itemControllers = new HashMap<>();
|
private final Map<UUID, ChatItemController> itemControllers = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
//For realtime handling
|
||||||
|
|
||||||
|
public void onChatUpdated(UUID chatId,
|
||||||
|
String chatType,
|
||||||
|
LocalDateTime lastTs,
|
||||||
|
boolean isIncoming,
|
||||||
|
String lastPreview) {
|
||||||
|
var opt = java.util.stream.Stream
|
||||||
|
.of(Session.chatList, Session.activeChats, Session.archivedChats)
|
||||||
|
.flatMap(java.util.Collection::stream)
|
||||||
|
.filter(c -> c.getId().equals(chatId))
|
||||||
|
.findFirst();
|
||||||
|
if (opt.isEmpty()) return;
|
||||||
|
|
||||||
|
ChatEntry chat = opt.get();
|
||||||
|
|
||||||
|
if (lastTs != null) chat.setLastMessageTime(String.valueOf(lastTs)); // ← نوع: LocalDateTime
|
||||||
|
if (lastPreview != null) chat.setLastMessagePreview(lastPreview);
|
||||||
|
|
||||||
|
boolean isOpen = Session.currentChatId != null &&
|
||||||
|
Session.currentChatId.equals(chatId.toString());
|
||||||
|
if (isIncoming && !isOpen) {
|
||||||
|
chat.setUnread(chat.getUnread() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
java.util.Comparator<ChatEntry> byTimeDesc = (c1, c2) -> {
|
||||||
|
var t1 = c1.getLastMessageTime();
|
||||||
|
var t2 = c2.getLastMessageTime();
|
||||||
|
if (t1 == null && t2 == null) return 0;
|
||||||
|
if (t1 == null) return 1;
|
||||||
|
if (t2 == null) return -1;
|
||||||
|
return t2.compareTo(t1);
|
||||||
|
};
|
||||||
|
Session.chatList.sort(byTimeDesc);
|
||||||
|
Session.activeChats.sort(byTimeDesc);
|
||||||
|
Session.archivedChats.sort(byTimeDesc);
|
||||||
|
|
||||||
|
refreshChatListUI();
|
||||||
|
refreshBadgesIfAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void refreshChatListUI() {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
chatListContainer.getChildren().clear();
|
||||||
|
itemControllers.clear();
|
||||||
|
populateChatListFromSession(); // همون متدی که نودها رو میسازه و میچسبونه
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void refreshBadgesIfAny() {
|
||||||
|
// آپدیت نشانها اگر لازم است
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
// addSampleChats();
|
// addSampleChats();
|
||||||
@@ -270,6 +328,30 @@ public class MainController {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// private void addChatNode(ChatEntry chat) {
|
||||||
|
// try {
|
||||||
|
// FXMLLoader fx = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
|
||||||
|
// Node item = fx.load();
|
||||||
|
// ChatItemController cc = fx.getController();
|
||||||
|
//
|
||||||
|
// String preview = chat.getLastMessagePreview() == null ? "" : chat.getLastMessagePreview();
|
||||||
|
// String timeText = formatChatTime(chat.getLastMessageTime());
|
||||||
|
// FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
|
||||||
|
// Node chatItem = loader.load();
|
||||||
|
// ChatItemController controller = loader.getController();
|
||||||
|
//
|
||||||
|
// cc.setChatData(chat.getName(), preview, timeText, chat.getUnreadCount(), "/org/to/telegramfinalproject/Avatars/default_profile.png");
|
||||||
|
// item.setOnMouseClicked(e -> openChat(chat));
|
||||||
|
// chatListContainer.getChildren().add(item);
|
||||||
|
//
|
||||||
|
// itemControllers.put(chat.getId(), cc);
|
||||||
|
//
|
||||||
|
// } catch (Exception ex) {
|
||||||
|
// ex.printStackTrace();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
private void addChatNode(ChatEntry chat) {
|
private void addChatNode(ChatEntry chat) {
|
||||||
try {
|
try {
|
||||||
FXMLLoader fx = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
|
FXMLLoader fx = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
|
||||||
@@ -277,22 +359,30 @@ public class MainController {
|
|||||||
ChatItemController cc = fx.getController();
|
ChatItemController cc = fx.getController();
|
||||||
|
|
||||||
String preview = chat.getLastMessagePreview() == null ? "" : chat.getLastMessagePreview();
|
String preview = chat.getLastMessagePreview() == null ? "" : chat.getLastMessagePreview();
|
||||||
String timeText = formatChatTime(chat.getLastMessageTime());
|
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/to/telegramfinalproject/Fxml/chat_item.fxml"));
|
|
||||||
Node chatItem = loader.load();
|
|
||||||
ChatItemController controller = loader.getController();
|
|
||||||
|
|
||||||
cc.setChatData(chat.getName(), preview, timeText, chat.getUnreadCount(), "/org/to/telegramfinalproject/Avatars/default_profile.png");
|
// اگر lastMessageTime از نوع LocalDateTime است:
|
||||||
|
String timeText = chat.getLastMessageTime() == null
|
||||||
|
? ""
|
||||||
|
: formatChatTime(chat.getLastMessageTime());
|
||||||
|
|
||||||
|
cc.setChatData(
|
||||||
|
chat.getName(),
|
||||||
|
preview,
|
||||||
|
timeText,
|
||||||
|
chat.getUnreadCount(),
|
||||||
|
"/org/to/telegramfinalproject/Avatars/default_profile.png"
|
||||||
|
);
|
||||||
|
|
||||||
item.setOnMouseClicked(e -> openChat(chat));
|
item.setOnMouseClicked(e -> openChat(chat));
|
||||||
chatListContainer.getChildren().add(item);
|
chatListContainer.getChildren().add(item);
|
||||||
|
|
||||||
itemControllers.put(chat.getId(), cc);
|
itemControllers.put(chat.getId(), cc);
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String mapTypeToLabel(String t) {
|
private String mapTypeToLabel(String t) {
|
||||||
switch (t.toUpperCase()) {
|
switch (t.toUpperCase()) {
|
||||||
case "IMAGE": return "[Image]";
|
case "IMAGE": return "[Image]";
|
||||||
@@ -325,6 +415,9 @@ public class MainController {
|
|||||||
ChatPageController controller = loader.getController();
|
ChatPageController controller = loader.getController();
|
||||||
controller.showChat(chat);
|
controller.showChat(chat);
|
||||||
|
|
||||||
|
this.chatPageController = controller;
|
||||||
|
Session.currentChatId = chat.getId().toString();
|
||||||
|
|
||||||
chatDisplayArea.getChildren().setAll(chatPage);
|
chatDisplayArea.getChildren().setAll(chatPage);
|
||||||
|
|
||||||
ChatItemController item = itemControllers.get(chat.getId());
|
ChatItemController item = itemControllers.get(chat.getId());
|
||||||
@@ -463,6 +556,17 @@ public class MainController {
|
|||||||
// ===== Search UI state =====
|
// ===== Search UI state =====
|
||||||
private final java.util.List<SearchResult> searchBacking = new java.util.ArrayList<>();
|
private final java.util.List<SearchResult> searchBacking = new java.util.ArrayList<>();
|
||||||
|
|
||||||
|
@FXML private AnchorPane chatHost; // کانتینر مناسب در مین برای قرار دادن ChatPage
|
||||||
|
|
||||||
|
private ChatPageController chatPageController;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public ChatPageController getChatPageController() {
|
||||||
|
return chatPageController;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private enum SRType { USER, GROUP, CHANNEL, MESSAGE }
|
private enum SRType { USER, GROUP, CHANNEL, MESSAGE }
|
||||||
|
|
||||||
private static class SearchResult {
|
private static class SearchResult {
|
||||||
@@ -483,7 +587,6 @@ public class MainController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String toDisplay() {
|
String toDisplay() {
|
||||||
// رشتهای که داخل ListView نشان میدهیم
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MESSAGE:
|
case MESSAGE:
|
||||||
String left = (title == null || title.isBlank()) ? "Message" : title;
|
String left = (title == null || title.isBlank()) ? "Message" : title;
|
||||||
@@ -512,7 +615,6 @@ public class MainController {
|
|||||||
|
|
||||||
showSearchPanel();
|
showSearchPanel();
|
||||||
|
|
||||||
// درخواست به سرور (مثل کنسول)
|
|
||||||
org.json.JSONObject req = new org.json.JSONObject();
|
org.json.JSONObject req = new org.json.JSONObject();
|
||||||
req.put("action", "search");
|
req.put("action", "search");
|
||||||
req.put("keyword", keyword);
|
req.put("keyword", keyword);
|
||||||
@@ -582,7 +684,7 @@ public class MainController {
|
|||||||
String subtitle = (ctx.isBlank()? "" : ctx) + (content.isBlank()? "" : (subtitleSep(ctx)+content));
|
String subtitle = (ctx.isBlank()? "" : ctx) + (content.isBlank()? "" : (subtitleSep(ctx)+content));
|
||||||
tmp.add(new SearchResult(
|
tmp.add(new SearchResult(
|
||||||
SRType.MESSAGE, senderName, subtitle, rType, rUuid,
|
SRType.MESSAGE, senderName, subtitle, rType, rUuid,
|
||||||
it.optString("receiver_display_id", ""), // اگر داشتی
|
it.optString("receiver_display_id", ""),
|
||||||
it.optString("message_id", null),
|
it.optString("message_id", null),
|
||||||
time
|
time
|
||||||
));
|
));
|
||||||
@@ -612,11 +714,10 @@ public class MainController {
|
|||||||
private void openSearchResult(SearchResult r) {
|
private void openSearchResult(SearchResult r) {
|
||||||
switch (r.type) {
|
switch (r.type) {
|
||||||
case USER: {
|
case USER: {
|
||||||
// مثل کنسول: اگر چت private با این یوزر داریم بازش کن؛
|
|
||||||
// وگرنه chat_id را از سرور بگیر/بساز، بعد باز کن.
|
|
||||||
java.util.UUID chatId = findExistingPrivateChatId(r.uuid);
|
java.util.UUID chatId = findExistingPrivateChatId(r.uuid);
|
||||||
if (chatId == null) {
|
if (chatId == null) {
|
||||||
chatId = fetchOrCreatePrivateChat(r.uuid); // نیاز به API سمت سرور
|
chatId = fetchOrCreatePrivateChat(r.uuid);
|
||||||
if (chatId == null) {
|
if (chatId == null) {
|
||||||
System.out.println("❌ Failed to create/find private chat.");
|
System.out.println("❌ Failed to create/find private chat.");
|
||||||
return;
|
return;
|
||||||
@@ -629,13 +730,12 @@ public class MainController {
|
|||||||
ce.setName(r.title); // profile_name
|
ce.setName(r.title); // profile_name
|
||||||
ce.setType("private");
|
ce.setType("private");
|
||||||
|
|
||||||
openChat(ce); // همون متد فعلی MainController
|
openChat(ce);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GROUP:
|
case GROUP:
|
||||||
case CHANNEL: {
|
case CHANNEL: {
|
||||||
// اگر تو لیست هست بازش کن، وگرنه با همون uuid باز کن
|
|
||||||
org.to.telegramfinalproject.Models.ChatEntry existing =
|
org.to.telegramfinalproject.Models.ChatEntry existing =
|
||||||
findExistingChat(r.uuid, r.receiverType);
|
findExistingChat(r.uuid, r.receiverType);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
@@ -652,7 +752,6 @@ public class MainController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case MESSAGE: {
|
case MESSAGE: {
|
||||||
// مثل کنسول: چتِ پیام را باز کن (اسکرول به پیام را بعداً اضافه کن)
|
|
||||||
org.to.telegramfinalproject.Models.ChatEntry existing =
|
org.to.telegramfinalproject.Models.ChatEntry existing =
|
||||||
findExistingChat(r.uuid, r.receiverType);
|
findExistingChat(r.uuid, r.receiverType);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
@@ -661,7 +760,7 @@ public class MainController {
|
|||||||
org.to.telegramfinalproject.Models.ChatEntry ce = new org.to.telegramfinalproject.Models.ChatEntry();
|
org.to.telegramfinalproject.Models.ChatEntry ce = new org.to.telegramfinalproject.Models.ChatEntry();
|
||||||
ce.setId(r.uuid.toString()); // receiver internal_uuid
|
ce.setId(r.uuid.toString()); // receiver internal_uuid
|
||||||
ce.setType(r.receiverType);
|
ce.setType(r.receiverType);
|
||||||
ce.setName(guessNameForReceiver(r)); // اگر خواستی از subtitle استفاده کن
|
ce.setName(guessNameForReceiver(r));
|
||||||
ce.setDisplayId(r.displayId);
|
ce.setDisplayId(r.displayId);
|
||||||
openChat(ce);
|
openChat(ce);
|
||||||
}
|
}
|
||||||
@@ -684,14 +783,12 @@ public class MainController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private java.util.UUID findExistingPrivateChatId(java.util.UUID otherUserUuid) {
|
private java.util.UUID findExistingPrivateChatId(java.util.UUID otherUserUuid) {
|
||||||
// اگر در لیست چتها private با همین طرف داری و internal_id همان chat_id است، برش گردان
|
|
||||||
var list = (org.to.telegramfinalproject.Client.Session.chatList==null)
|
var list = (org.to.telegramfinalproject.Client.Session.chatList==null)
|
||||||
? java.util.Collections.<org.to.telegramfinalproject.Models.ChatEntry>emptyList()
|
? java.util.Collections.<org.to.telegramfinalproject.Models.ChatEntry>emptyList()
|
||||||
: org.to.telegramfinalproject.Client.Session.chatList;
|
: org.to.telegramfinalproject.Client.Session.chatList;
|
||||||
|
|
||||||
for (var c : list) {
|
for (var c : list) {
|
||||||
if ("private".equalsIgnoreCase(c.getType())) {
|
if ("private".equalsIgnoreCase(c.getType())) {
|
||||||
// اگر مدلات otherUserId در ChatEntry دارد، از آن استفاده کن
|
|
||||||
if (otherUserUuid.equals(c.getOtherUserId())) {
|
if (otherUserUuid.equals(c.getOtherUserId())) {
|
||||||
try { return java.util.UUID.fromString(c.getId().toString()); } catch (Exception ignored) {}
|
try { return java.util.UUID.fromString(c.getId().toString()); } catch (Exception ignored) {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user