diff --git a/src/main/java/org/to/telegramfinalproject/UI/AvatarFX.java b/src/main/java/org/to/telegramfinalproject/UI/AvatarFX.java index c26d0f4..3957985 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/AvatarFX.java +++ b/src/main/java/org/to/telegramfinalproject/UI/AvatarFX.java @@ -14,7 +14,7 @@ public final class AvatarFX { Circle c = new Circle(); c.radiusProperty().bind(Bindings.min(iv.fitWidthProperty(), iv.fitHeightProperty()).divide(2)); - c.centerXProperty().bind(iv.fitWidthProperty().divide(2)); + c.centerXProperty().bind(iv.fitWidthProperty().divide(3)); c.centerYProperty().bind(iv.fitHeightProperty().divide(2)); iv.setClip(c); } diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java b/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java index 9a69172..c582da4 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java @@ -842,7 +842,7 @@ public class ChatPageController { } else { setDefaultHeaderAvatarByType(entry.getType()); } - AvatarFX.circleClip(userAvatar, 36); + AvatarFX.circleClip(userAvatar, 40); // حالت اولیه (بدون انتظار هدر) @@ -863,11 +863,13 @@ public class ChatPageController { // === (3-dot menu + header click) === configureHeaderActions(entry); + + requestBlockStatusByChat(entry); } - private void requestBlockStatusByChat(ChatEntry entry) { + public void requestBlockStatusByChat(ChatEntry entry) { if (entry == null || !"private".equalsIgnoreCase(entry.getType())) return; String viewerId = Session.getUserUUID(); // internal_uuid کاربر فعلی @@ -890,7 +892,7 @@ public class ChatPageController { }).start(); } - private void applyBlockUi(boolean blockedByMe, boolean blockedMe) { + public void applyBlockUi(boolean blockedByMe, boolean blockedMe) { this.blockedByMeFlag = blockedByMe; this.blockedMeFlag = blockedMe; @@ -945,6 +947,8 @@ public class ChatPageController { // Wire up menu + header click configureHeaderActions(entry); + + requestBlockStatusByChat(entry); } private void configureHeaderActions(ChatEntry entry) { @@ -983,6 +987,7 @@ public class ChatPageController { private void openInfoScene(ChatEntry entry) { JSONObject req = new JSONObject(); + String targetId = null; // 👈 capture it here for the private case switch (entry.getType().toLowerCase()) { case "private" -> { @@ -1003,7 +1008,7 @@ public class ChatPageController { return; } - String targetId = targetResp.optJSONObject("data").optString("target_id", null); + targetId = targetResp.optJSONObject("data").optString("target_id", null); if (targetId == null || targetId.isBlank()) { Platform.runLater(() -> MainController.getInstance().showAlert( @@ -1038,6 +1043,8 @@ public class ChatPageController { } } + final String finalTargetId = targetId; // 👈 capture for use in the FX thread + new Thread(() -> { JSONObject resp = ActionHandler.sendWithResponse(req); if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) { @@ -1074,7 +1081,8 @@ public class ChatPageController { "/org/to/telegramfinalproject/Fxml/user_info.fxml")); overlay = loader.load(); UserInfoController c = loader.getController(); - c.setProfileDataFromJson(entry, data); + // 👇 pass targetId so UserInfoController gets the real UUID + c.setProfileDataFromJson(entry, data, finalTargetId); } case "group" -> { loader = new FXMLLoader(getClass().getResource( diff --git a/src/main/java/org/to/telegramfinalproject/UI/UserInfoController.java b/src/main/java/org/to/telegramfinalproject/UI/UserInfoController.java index cf90a85..d61c043 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/UserInfoController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/UserInfoController.java @@ -40,6 +40,7 @@ public class UserInfoController { @FXML private ImageView usernameIcon; private String otherUserId; // internal_uuid of the other user + private ChatEntry entry; private static final String ICON_PATH = "/org/to/telegramfinalproject/Icons/"; @@ -73,8 +74,8 @@ public class UserInfoController { }); deleteChatItem.setOnAction(e -> handleDeleteChat()); - blockItem.setOnAction(e -> handleBlock()); - unblockItem.setOnAction(e -> handleUnblock()); + blockItem.setOnAction(e -> handleToggleBlock(entry)); + unblockItem.setOnAction(e -> handleToggleBlock(entry)); // Register scene for ThemeManager → stylesheet swap will handle colors/icons Platform.runLater(() -> { @@ -93,7 +94,11 @@ public class UserInfoController { } /** Backend JSON → UI */ - public void setProfileDataFromJson(ChatEntry entry, JSONObject data) { + public void setProfileDataFromJson(ChatEntry entry, JSONObject data, String targetUuid) { + // save the correct UUID + this.otherUserId = targetUuid; + this.entry = entry; + // --- Profile name --- String name = data.optString("profile_name", entry.getName()); profileName.setText(name); @@ -141,9 +146,6 @@ public class UserInfoController { ); } - // --- Other user ID (needed for block/delete) --- - this.otherUserId = data.optString("other_user_id", entry.getId().toString()); - // --- Block/Unblock --- boolean blocked = data.optBoolean("blocked", false) || data.optBoolean("is_blocked", false) @@ -163,28 +165,55 @@ public class UserInfoController { } } - private void handleBlock() { + private void handleToggleBlock(ChatEntry entry) { + if (otherUserId == null) return; + + // 1) Send toggle request JSONObject req = new JSONObject() - .put("action", "block_user") - .put("target_id", otherUserId) - .put("viewer_id", Session.getUserUUID()); + .put("action", "toggle_block") + .put("user_id", Session.getUserUUID()) + .put("target_id", otherUserId); JSONObject resp = ActionHandler.sendWithResponse(req); - if (resp != null && "success".equalsIgnoreCase(resp.optString("status"))) { - updateBlockMenu(true); + if (resp == null) { + MainController.getInstance().showAlert("Error", "No response from server.", Alert.AlertType.ERROR); + return; } - } - private void handleUnblock() { - JSONObject req = new JSONObject() - .put("action", "unblock_user") - .put("target_id", otherUserId) - .put("viewer_id", Session.getUserUUID()); - - JSONObject resp = ActionHandler.sendWithResponse(req); - if (resp != null && "success".equalsIgnoreCase(resp.optString("status"))) { - updateBlockMenu(false); + if (!"success".equalsIgnoreCase(resp.optString("status"))) { + MainController.getInstance().showAlert("Error", + resp.optString("message", "Failed to toggle block"), + Alert.AlertType.ERROR); + return; } + + // 2) Immediately re-check block state from server + JSONObject checkReq = new JSONObject() + .put("action", "check_block_status_by_chat") + .put("viewer_id", Session.getUserUUID()) + .put("chat_id", entry.getId().toString()); + + JSONObject checkResp = ActionHandler.sendWithResponse(checkReq); + if (checkResp == null || !"success".equalsIgnoreCase(checkResp.optString("status"))) { + System.err.println("⚠️ Failed to refresh block status after toggle."); + return; + } + + JSONObject data = checkResp.optJSONObject("data"); + boolean blockedByMe = data != null && data.optBoolean("blocked_by_me", false); + boolean blockedMe = data != null && data.optBoolean("blocked_me", false); + + // 3) Update UI on FX thread + Platform.runLater(() -> { + // update overlay (block/unblock menu) + updateBlockMenu(blockedByMe); + + // update chat page input bar + ChatPageController c = ChatPageController.getInstance(); + if (c != null) { + c.applyBlockUi(blockedByMe, blockedMe); + } + }); } private void updateBlockMenu(boolean isBlocked) { diff --git a/src/main/resources/org/to/telegramfinalproject/Fxml/user_info.fxml b/src/main/resources/org/to/telegramfinalproject/Fxml/user_info.fxml index 7be8882..f53506c 100644 --- a/src/main/resources/org/to/telegramfinalproject/Fxml/user_info.fxml +++ b/src/main/resources/org/to/telegramfinalproject/Fxml/user_info.fxml @@ -35,15 +35,6 @@ - - - - - - - - - @@ -62,6 +53,15 @@ + + + + + + + + +