diff --git a/src/main/java/org/to/telegramfinalproject/UI/AddMembersController.java b/src/main/java/org/to/telegramfinalproject/UI/AddMembersController.java index 9d8d61a..23073a5 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/AddMembersController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/AddMembersController.java @@ -29,7 +29,6 @@ public class AddMembersController { @FXML private Button cancelButton; @FXML private Button createButton; - // گروه هدف private UUID groupInternalId; private String groupName; private String groupDisplayId; @@ -42,9 +41,7 @@ public class AddMembersController { private Mode mode = Mode.CREATE; // default - // انتخاب‌ها private final Set selectedContacts = new HashSet<>(); - // همه‌ی کانتکت‌ها private final List allContacts = new ArrayList<>(); @FXML @@ -61,7 +58,6 @@ public class AddMembersController { contactsScroll.setVvalue(contactsScroll.getVvalue() - deltaY); }); - // آیکن سرچ با تم Platform.runLater(() -> { if (addMembersCard.getScene() != null) { ThemeManager.getInstance().registerScene(addMembersCard.getScene()); @@ -70,19 +66,15 @@ public class AddMembersController { ThemeManager.getInstance().darkModeProperty().addListener((obs, ov, nv) -> updateSearchIcon(nv)); updateSearchIcon(ThemeManager.getInstance().isDarkMode()); - // بستن اُورلی cancelButton.setOnAction(e -> MainController.getInstance().closeOverlay(addMembersCard.getParent())); overlayBackground.setOnMouseClicked(e -> MainController.getInstance().closeOverlay(addMembersCard.getParent())); - // دکمه Add (افزودن اعضا) createButton.setOnAction(e -> onAddMembers()); - // سرچ searchField.textProperty().addListener((obs, ov, nv) -> applyFilter(nv)); Platform.runLater(() -> searchField.requestFocus()); - // دیتا را از Session بارگذاری کن loadContactsFromSession(); updateMemberCount(); renderContacts(allContacts); @@ -132,7 +124,6 @@ public class AddMembersController { allContacts.add(new Contact(id, name, status, imageUrl)); } } - // اگر خالی بود، چیزی نشون نده (یا می‌تونی دمو بسازی) allContacts.sort(Comparator.comparing(Contact::getName, String.CASE_INSENSITIVE_ORDER)); } @@ -295,9 +286,8 @@ public class AddMembersController { a.show(); } - // ================== مدل Contact ================== public static class Contact { - private final String id; // internal_uuid کاربر + private final String id; // internal_uuid private final String name; private final String status; private final String imageUrl; diff --git a/src/main/java/org/to/telegramfinalproject/UI/AddSubscriberController.java b/src/main/java/org/to/telegramfinalproject/UI/AddSubscriberController.java index 908005e..57dd7fd 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/AddSubscriberController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/AddSubscriberController.java @@ -29,20 +29,17 @@ public class AddSubscriberController { @FXML private Button skipButton; @FXML private Button addButton; - // اطلاعات کانال private UUID channelInternalId; private String channelName; private String channelDisplayId; private File channelImageFile; private String description; - // انتخاب‌ها و منبع داده private final Set selected = new HashSet<>(); private final List allContacts = new ArrayList<>(); @FXML public void initialize() { - // اسکرول نرم contactsScroll.getStylesheets().add( getClass().getResource("/org/to/telegramfinalproject/CSS/scrollpane.css").toExternalForm() ); @@ -54,7 +51,6 @@ public class AddSubscriberController { contactsScroll.setVvalue(contactsScroll.getVvalue() - deltaY); }); - // تم آیکن Platform.runLater(() -> { if (addMembersCard.getScene() != null) { ThemeManager.getInstance().registerScene(addMembersCard.getScene()); @@ -63,22 +59,18 @@ public class AddSubscriberController { ThemeManager.getInstance().darkModeProperty().addListener((obs, ov, nv) -> updateSearchIcon(nv)); updateSearchIcon(ThemeManager.getInstance().isDarkMode()); - // بستن اُورلی overlayBackground.setOnMouseClicked(e -> MainController.getInstance().closeOverlay(addMembersCard.getParent())); skipButton.setOnAction(e -> MainController.getInstance().closeOverlay(addMembersCard.getParent())); addButton.setOnAction(e -> onAddSubscribers()); - // سرچ searchField.textProperty().addListener((obs, ov, nv) -> applyFilter(nv)); Platform.runLater(() -> searchField.requestFocus()); - // لود کانتکت‌ها از Session loadContactsFromSession(); updateCount(); renderContacts(allContacts); } - /** NewChannelController این را بعد از ساخت کانال صدا بزند */ public void setChannelInfo(UUID internalId, String name, String displayId, File imageFile, String description) { this.channelInternalId = internalId; this.channelName = name; @@ -87,7 +79,6 @@ public class AddSubscriberController { this.description = description; } - // برای سازگاری با امضای قدیمی (اختیاری) public void setChannelInfo(String name, String id, String description, File image) { this.channelName = name; this.channelDisplayId = id; @@ -226,7 +217,6 @@ public class AddSubscriberController { return; } - // fallback: تک‌به‌تک boolean allOk = true; for (String uid : ids) { JSONObject single = new JSONObject() @@ -277,9 +267,8 @@ public class AddSubscriberController { a.show(); } - // ===== مدل Contact ===== public static class Contact { - private final String id; // internal_uuid کاربر + private final String id; // internal_uuid private final String name; private final String status; private final String imageUrl; diff --git a/src/main/java/org/to/telegramfinalproject/UI/BlockedUsersController.java b/src/main/java/org/to/telegramfinalproject/UI/BlockedUsersController.java index 1539b5c..631ab85 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/BlockedUsersController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/BlockedUsersController.java @@ -27,14 +27,12 @@ public class BlockedUsersController { @FXML private ListView blockedList; @FXML private VBox blockedCard; - // نگاشت برای حذف سریع ردیف بعد از Unblock private final Map rowByUserId = new HashMap<>(); @FXML public void initialize() { backButton.setGraphic(makeIcon("/org/to/telegramfinalproject/Icons/back_button_dark.png")); - // بارگذاری واقعی از سرور loadBlockedUsers(); closeButton.setOnAction(e -> MainController.getInstance().closeOverlay(overlayBackground.getParent())); @@ -72,7 +70,6 @@ public class BlockedUsersController { /* ===================== Networking ===================== */ private void loadBlockedUsers() { - // درخواست به سرور new Thread(() -> { JSONObject req = new JSONObject().put("action", "get_blocked_users"); JSONObject resp = ActionHandler.sendWithResponse(req); @@ -102,8 +99,8 @@ public class BlockedUsersController { new Thread(() -> { JSONObject req = new JSONObject() .put("action", "toggle_block") - .put("user_id", me) // UUID من - .put("target_id", targetId.toString()); // UUID طرف + .put("user_id", me) // UUID + .put("target_id", targetId.toString()); // UUID JSONObject resp = ActionHandler.sendWithResponse(req); boolean ok = resp != null && "success".equalsIgnoreCase(resp.optString("status")); @@ -127,7 +124,6 @@ public class BlockedUsersController { blockedList.getItems().clear(); rowByUserId.clear(); - // انتظار میره هر آبجکت حداقل: internal_uuid, profile_name, user_id/username/display_id, image_url داشته باشه IntStream.range(0, list.length()).forEach(i -> { JSONObject o = list.optJSONObject(i); if (o == null) return; @@ -229,7 +225,6 @@ public class BlockedUsersController { } private void showToast(String msg) { - // ساده: از Alert استفاده کن؛ اگر Toast اختصاصی داری جایگزینش کن Alert a = new Alert(Alert.AlertType.INFORMATION, msg, ButtonType.OK); if (a.getDialogPane().getScene() != null) { ThemeManager.getInstance().registerScene(a.getDialogPane().getScene()); diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java b/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java index fade114..8f52bcb 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java @@ -34,7 +34,6 @@ public class ChangeCredentialsController { private boolean passwordVisible = false; private boolean confirmVisible = false; - // ↓↓↓ متدی که از CheckPasswordController مقدار می‌گیرد private String currentPassword; public void setCurrentPassword(String p) { this.currentPassword = p; } @@ -44,7 +43,6 @@ public class ChangeCredentialsController { togglePasswordBtn.setOnAction(e -> togglePasswordVisibility()); toggleConfirmBtn.setOnAction(e -> toggleConfirmVisibility()); - // «ذخیره و بستن» مثل ادیت پروفایل saveButton.setOnAction(e -> saveAndClose()); closeButton.setOnAction(e -> saveAndClose()); cancelButton.setOnAction(e -> saveAndClose()); @@ -78,7 +76,6 @@ public class ChangeCredentialsController { Platform.runLater(() -> usernameField.requestFocus()); } - // ← از CheckPasswordController بلافاصله بعد از load صدا بزن public void prefillFromSession() { var u = Session.currentUser; if (u == null) return; @@ -112,12 +109,10 @@ public class ChangeCredentialsController { toggleConfirmBtn.setText(confirmVisible ? "👁" : "👁"); } - // ارسال تغییرات (در صورت پر بودن/تغییر) و بستن private void saveAndClose() { boolean anyError = false; boolean sentSomething = false; - // 1) یوزرنیم var cu = Session.currentUser; String oldUsername = cu != null ? cu.optString("user_id", cu.optString("username", @@ -129,7 +124,7 @@ public class ChangeCredentialsController { JSONObject req = new JSONObject() .put("action", "update_username") - .put("current_password", currentPassword) // با اینکه سرور فعلاً چک نمی‌کند، می‌فرستیم + .put("current_password", currentPassword) .put("new_username", newUsername); JSONObject resp = ActionHandler.sendWithResponse(req); @@ -150,7 +145,7 @@ public class ChangeCredentialsController { if (confirm.isEmpty() || !confirm.equals(newPwd)) { addError(confirmPasswordField, confirmPasswordLabel); addError(visibleConfirmPasswordField, confirmPasswordLabel); - return; // نذار بسته شه تا کاربر درست کنه + return; } sentSomething = true; @@ -168,7 +163,6 @@ public class ChangeCredentialsController { } } - // اگر چیزی نفرستادیم یا همه‌چیز OK بود → ببند و رفرش Settings if (!sentSomething || !anyError) { var sc = SettingsController.getInstance(); if (sc != null) sc.populateFromSession(); diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java b/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java index 273798a..435a2c2 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ChatItemController.java @@ -121,8 +121,7 @@ public class ChatItemController { // ChatItemController.java @FXML private ImageView avatarImage; - // اگر نوع چت نیاز داری برای دیفالت‌ها (private|group|channel) - private String chatType; // اگر داری از setChatData بگیرش و نگه دار + private String chatType; public void updateAvatar(String url) { try { diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java b/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java index 8845f68..6acdcc0 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ChatPageController.java @@ -337,12 +337,10 @@ public class ChatPageController { // Menu item actions viewProfileItem.setOnAction(e -> { System.out.println("Viewing profile of " + chatName); - // TODO: open profile UI }); deleteChatItem.setOnAction(e -> { System.out.println("Deleting chat with " + chatName); - // TODO: delete logic }); if (archiveItem != null) { @@ -511,7 +509,6 @@ public class ChatPageController { Platform.runLater(() -> { if (currentChat == null || !currentChat.getId().equals(chatId)) return; - // حباب outgoing addBubble( true, // outgoing "You", // display name @@ -594,7 +591,7 @@ public class ChatPageController { private HBox addPendingMediaBubble(String messageId, File file, String type, String caption) { HBox root = new HBox(8); root.setFillHeight(true); - root.setAlignment(Pos.CENTER_RIGHT); // چون outgoing است + root.setAlignment(Pos.CENTER_RIGHT); // preview if ("IMAGE".equalsIgnoreCase(type)) { @@ -1032,7 +1029,6 @@ public class ChatPageController { if (archiveItem != null) archiveItem.setDisable(false); if (resp != null && "success".equalsIgnoreCase(resp.optString("status"))) { - // 1) جابه‌جایی در Session if (!currentlyArchived) { Session.moveToArchived(entry); if (archiveItem != null) archiveItem.setText("Unarchive chat"); @@ -1361,7 +1357,7 @@ public class ChatPageController { String rel = pathOrUrl.startsWith("/") ? pathOrUrl.substring(1) : pathOrUrl; java.nio.file.Path p = java.nio.file.Paths.get(UPLOADS_DIR, rel.replace("/", java.io.File.separator)); - java.net.URI uri = p.toUri(); // می‌شود file:///C:/Users/.../uploads/images/... + java.net.URI uri = p.toUri(); return uri.toString(); @@ -1683,10 +1679,7 @@ public class ChatPageController { } } } - // imports لازم: -// import javafx.scene.media.Media; -// import javafx.scene.media.MediaPlayer; -// import javafx.util.Duration; + private Node buildAudioNodeLocal(String localPathOrUri, String caption) { @@ -1708,14 +1701,12 @@ public class ChatPageController { } root.getChildren().add(right); - // مسیر را به file URI تبدیل کن String playable = toFileUri(localPathOrUri); if (playable == null) { btn.setDisable(true); seek.setDisable(true); time.setText("no audio"); return root; } - // قبل از ساخت Media، وجود فایل را چک کن try { java.net.URI uri = java.net.URI.create(playable); java.nio.file.Path p = java.nio.file.Paths.get(uri); @@ -1724,7 +1715,7 @@ public class ChatPageController { System.err.println("Audio file not found: " + p); return root; } - } catch (Exception ignore) { /* اگر نشد، ادامه می‌دهیم */ } + } catch (Exception ignore) { } MediaPlayer[] holder = new MediaPlayer[1]; try { @@ -1782,7 +1773,7 @@ public class ChatPageController { if (pathOrUri.startsWith("file:/")) return pathOrUri; java.io.File f = new java.io.File(pathOrUri); - return f.toURI().toString(); // -> file:///C:/... یا file:///home/... + return f.toURI().toString(); } @@ -2057,7 +2048,7 @@ public class ChatPageController { org.to.telegramfinalproject.Models.ContactEntry ce = new org.to.telegramfinalproject.Models.ContactEntry( other, // contact_id (UUID) - currentChat.getDisplayId(), // contact_display_id / user_id دیدنی + currentChat.getDisplayId(), // contact_display_id / user_id currentChat.getDisplayId(), nz(chatTitle.getText()), currentChat.getImageUrl(), @@ -2139,8 +2130,8 @@ public class ChatPageController { org.json.JSONObject req = new org.json.JSONObject() .put("action", "toggle_block") - .put("user_id", viewerUuid) // internal_uuid خودت - .put("target_id", other.toString()); // internal_uuid طرف مقابل + .put("user_id", viewerUuid) + .put("target_id", other.toString()); org.json.JSONObject res = org.to.telegramfinalproject.Client.ActionHandler.sendWithResponse(req); boolean ok = res != null && "success".equalsIgnoreCase(res.optString("status")); @@ -2546,7 +2537,6 @@ public class ChatPageController { org.json.JSONObject cu = org.to.telegramfinalproject.Client.Session.currentUser; if (cu == null) return new java.util.ArrayList<>(); - // دو منبع معمول در Session: chat_list و active_chat_list org.json.JSONArray[] sources = new org.json.JSONArray[]{ cu.optJSONArray("chat_list"), cu.optJSONArray("active_chat_list") @@ -2704,121 +2694,7 @@ public class ChatPageController { return profileName + (userId != null && !userId.isBlank() ? " [" + userId + "]" : ""); } } -// private void onLeaveGroupMenuClicked(ChatEntry entry) { -// if (entry == null || !"group".equalsIgnoreCase(entry.getType())) { -// alert(Alert.AlertType.INFORMATION, "This action is only available for groups."); -// return; -// } -// -// String myUuidStr = Session.getUserUUID(); -// if (myUuidStr == null || myUuidStr.isBlank()) { -// alert(Alert.AlertType.ERROR, "Cannot determine your identity."); -// return; -// } -// if (entry.isOwner()) { -// // 1. گرفتن لیست ادمین‌ها -// JSONObject req = new JSONObject() -// .put("action", "view_group_admins") -// .put("group_id", entry.getId().toString()); -// -// JSONObject res = ActionHandler.sendWithResponse(req); -// if (res == null || !"success".equalsIgnoreCase(res.optString("status"))) { -// alert(Alert.AlertType.ERROR, "Failed to fetch admins."); -// return; -// } -// -// JSONArray admins = res.getJSONObject("data").optJSONArray("admins"); -// if (admins == null || admins.isEmpty()) { -// alert(Alert.AlertType.WARNING, "No other admins available. Promote someone first."); -// return; -// } -// -// String myUuid = Session.getUserUUID(); -// List candidates = new ArrayList<>(); -// for (int i = 0; i < admins.length(); i++) { -// JSONObject a = admins.getJSONObject(i); -// String uuid = a.optString("internal_uuid"); -// if (uuid != null && uuid.equals(myUuid)) continue; // حذف Owner -// candidates.add(a); -// } -// -// if (candidates.isEmpty()) { -// alert(Alert.AlertType.WARNING, "No other admins available."); -// return; -// } -// -// // 2. نمایش لیست در یک Dialog ساده -// Dialog dialog = new Dialog<>(); -// dialog.setTitle("Transfer Ownership"); -// dialog.setHeaderText("Select a new owner before leaving"); -// dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); -// -// ListView listView = new ListView<>(); -// listView.getItems().addAll(candidates); -// listView.setCellFactory(v -> new ListCell<>() { -// @Override protected void updateItem(JSONObject item, boolean empty) { -// super.updateItem(item, empty); -// if (empty || item == null) { -// setText(null); -// } else { -// setText(item.optString("profile_name", "Unknown") -// + " (" + item.optString("user_id") + ")"); -// } -// } -// }); -// -// dialog.getDialogPane().setContent(listView); -// Node okBtn = dialog.getDialogPane().lookupButton(ButtonType.OK); -// okBtn.setDisable(true); -// -// listView.getSelectionModel().selectedItemProperty().addListener((obs, old, sel) -> { -// okBtn.setDisable(sel == null); -// }); -// -// dialog.setResultConverter(bt -> -// bt == ButtonType.OK ? listView.getSelectionModel().getSelectedItem() : null); -// -// Optional pick = dialog.showAndWait(); -// if (pick.isEmpty()) return; -// -// JSONObject selected = pick.get(); -// String newOwnerId = selected.optString("internal_uuid"); -// -// JSONObject promoteReq = new JSONObject() -// .put("action", "transfer_group_ownership") -// .put("group_id", entry.getId().toString()) -// .put("new_owner_user_id", newOwnerId); -// -// JSONObject promoteRes = ActionHandler.sendWithResponse(promoteReq); -// if (promoteRes == null || !"success".equalsIgnoreCase(promoteRes.optString("status"))) { -// alert(Alert.AlertType.ERROR, "Ownership transfer failed."); -// return; -// } -// -// // 4. بعد از انتقال، خروج از گروه -// JSONObject leaveReq = new JSONObject() -// .put("action", "leave_chat") -// .put("user_id", myUuid) -// .put("chat_id", entry.getId().toString()) -// .put("chat_type", "group"); -// -// JSONObject leaveRes = ActionHandler.sendWithResponse(leaveReq); -// if (leaveRes != null && "success".equalsIgnoreCase(leaveRes.optString("status"))) { -// alert(Alert.AlertType.INFORMATION, "Ownership transferred and you left the group."); -// MainController.getInstance().refreshChatListUI(); -// AppRouter.showMain(); -// } else { -// alert(Alert.AlertType.ERROR, "Leave failed."); -// } -// return; -// } -// -// -// -// if (confirm("Leave Group", "Are you sure you want to leave this group?")) { -// sendLeaveRequest(entry.getId(), myUuidStr); -// } -// } + private void onLeaveGroupMenuClicked(ChatEntry entry) { if (entry == null || !"group".equalsIgnoreCase(entry.getType())) {