diff --git a/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java b/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java index fd06ad4..fade114 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/ChangeCredentialsController.java @@ -4,13 +4,16 @@ import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.layout.Pane; -import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import org.json.JSONObject; +import org.to.telegramfinalproject.Client.ActionHandler; +import org.to.telegramfinalproject.Client.Session; public class ChangeCredentialsController { @FXML private VBox credentialsCard; @FXML private Pane overlayBackground; + @FXML private TextField usernameField; @FXML private Label usernameLabel; @@ -31,22 +34,21 @@ public class ChangeCredentialsController { private boolean passwordVisible = false; private boolean confirmVisible = false; + // ↓↓↓ متدی که از CheckPasswordController مقدار می‌گیرد + private String currentPassword; + public void setCurrentPassword(String p) { this.currentPassword = p; } + @FXML private void initialize() { // Toggle password visibility togglePasswordBtn.setOnAction(e -> togglePasswordVisibility()); toggleConfirmBtn.setOnAction(e -> toggleConfirmVisibility()); - saveButton.setOnAction(e -> validateAndSave()); - - // Close the overlay - closeButton.setOnAction(e -> - MainController.getInstance().closeOverlay(credentialsCard.getParent())); - cancelButton.setOnAction(e -> - MainController.getInstance().closeOverlay(credentialsCard.getParent())); - overlayBackground.setOnMouseClicked(e -> - MainController.getInstance().closeOverlay(credentialsCard.getParent()) - ); + // «ذخیره و بستن» مثل ادیت پروفایل + saveButton.setOnAction(e -> saveAndClose()); + closeButton.setOnAction(e -> saveAndClose()); + cancelButton.setOnAction(e -> saveAndClose()); + overlayBackground.setOnMouseClicked(e -> saveAndClose()); // Reset error when typing usernameField.textProperty().addListener((obs, o, n) -> removeError(usernameField, usernameLabel)); @@ -73,10 +75,19 @@ public class ChangeCredentialsController { removeError(visibleConfirmPasswordField, confirmPasswordLabel); }); - // Auto_focus password field when overlay opens Platform.runLater(() -> usernameField.requestFocus()); } + // ← از CheckPasswordController بلافاصله بعد از load صدا بزن + public void prefillFromSession() { + var u = Session.currentUser; + if (u == null) return; + String handle = u.optString("user_id", + u.optString("username", + u.optString("display_id",""))); + usernameField.setText(handle); + } + private void togglePasswordVisibility() { passwordVisible = !passwordVisible; visiblePasswordField.setText(passwordField.getText()); @@ -101,47 +112,68 @@ public class ChangeCredentialsController { toggleConfirmBtn.setText(confirmVisible ? "👁" : "👁"); } - private void validateAndSave() { - boolean hasError = false; + // ارسال تغییرات (در صورت پر بودن/تغییر) و بستن + private void saveAndClose() { + boolean anyError = false; + boolean sentSomething = false; - // --- Username check --- - if (usernameField.getText().trim().isEmpty()) { - addError(usernameField, usernameLabel); - hasError = true; - } else { - removeError(usernameField, usernameLabel); + // 1) یوزرنیم + var cu = Session.currentUser; + String oldUsername = cu != null ? cu.optString("user_id", + cu.optString("username", + cu.optString("display_id",""))) : ""; + + String newUsername = usernameField.getText().trim(); + if (!newUsername.isEmpty() && !newUsername.equals(oldUsername)) { + sentSomething = true; + + JSONObject req = new JSONObject() + .put("action", "update_username") + .put("current_password", currentPassword) // با اینکه سرور فعلاً چک نمی‌کند، می‌فرستیم + .put("new_username", newUsername); + + JSONObject resp = ActionHandler.sendWithResponse(req); + if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) { + anyError = true; + showError("Changing username failed", + resp != null ? resp.optString("message","Unknown error") : "No response"); + } else { + if (cu != null) cu.put("user_id", newUsername); + } } - // --- Password check --- - String pwd = passwordVisible ? visiblePasswordField.getText().trim() : passwordField.getText().trim(); - if (pwd.isEmpty()) { - addError(passwordField, passwordLabel); - addError(visiblePasswordField, passwordLabel); - hasError = true; - } else { - removeError(passwordField, passwordLabel); - removeError(visiblePasswordField, passwordLabel); + // 2) پسورد + String newPwd = (passwordVisible ? visiblePasswordField.getText() : passwordField.getText()).trim(); + String confirm = (confirmVisible ? visibleConfirmPasswordField.getText() : confirmPasswordField.getText()).trim(); + + if (!newPwd.isEmpty()) { + if (confirm.isEmpty() || !confirm.equals(newPwd)) { + addError(confirmPasswordField, confirmPasswordLabel); + addError(visibleConfirmPasswordField, confirmPasswordLabel); + return; // نذار بسته شه تا کاربر درست کنه + } + + sentSomething = true; + + JSONObject req = new JSONObject() + .put("action", "update_password") + .put("current_password", currentPassword) + .put("new_password", newPwd); + + JSONObject resp = ActionHandler.sendWithResponse(req); + if (resp == null || !"success".equalsIgnoreCase(resp.optString("status"))) { + anyError = true; + showError("Changing password failed", + resp != null ? resp.optString("message","Unknown error") : "No response"); + } } - // --- Confirm password check --- - String confirm = confirmVisible ? visibleConfirmPasswordField.getText().trim() : confirmPasswordField.getText().trim(); - if (confirm.isEmpty()) { - addError(confirmPasswordField, confirmPasswordLabel); - addError(visibleConfirmPasswordField, confirmPasswordLabel); - hasError = true; - } else if (!confirm.equals(pwd)) { - addError(confirmPasswordField, confirmPasswordLabel); - addError(visibleConfirmPasswordField, confirmPasswordLabel); - hasError = true; - } else { - removeError(confirmPasswordField, confirmPasswordLabel); - removeError(visibleConfirmPasswordField, confirmPasswordLabel); + // اگر چیزی نفرستادیم یا همه‌چیز OK بود → ببند و رفرش Settings + if (!sentSomething || !anyError) { + var sc = SettingsController.getInstance(); + if (sc != null) sc.populateFromSession(); + MainController.getInstance().closeOverlay(credentialsCard.getParent()); } - - if (hasError) return; - - // TODO: send to server - System.out.println("Saving new credentials..."); } private void addError(TextField field, Label label) { @@ -157,4 +189,15 @@ public class ChangeCredentialsController { field.getStyleClass().remove("error-input"); label.getStyleClass().remove("error-label"); } + + private void showError(String title, String msg) { + Alert a = new Alert(Alert.AlertType.ERROR); + a.setTitle(title); + a.setHeaderText(null); + a.setContentText(msg); + if (a.getDialogPane().getScene()!=null) { + ThemeManager.getInstance().registerScene(a.getDialogPane().getScene()); + } + a.showAndWait(); + } } diff --git a/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java b/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java index b023d71..fd7b036 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/CheckPasswordController.java @@ -98,26 +98,38 @@ public class CheckPasswordController { } private void validatePassword() { - String entered = passwordField.getText().trim(); - String correct = "12345"; // demo only + String entered = (passwordVisible ? visiblePasswordField.getText() : passwordField.getText()).trim(); + if (entered.isEmpty()) { + // استایل خطا مثل قبل + if (!passwordField.getStyleClass().contains("error")) + passwordField.getStyleClass().add("error"); + if (!visiblePasswordField.getStyleClass().contains("error")) + visiblePasswordField.getStyleClass().add("error"); + if (!passwordLabel.getStyleClass().contains("error")) + passwordLabel.getStyleClass().add("error"); + return; + } - if (entered.equals(correct)) { - // Success → reset error styles + // تماس با سرور + org.json.JSONObject req = new org.json.JSONObject() + .put("action", "verify_password") + .put("current_password", entered); + + org.json.JSONObject resp = org.to.telegramfinalproject.Client.ActionHandler.sendWithResponse(req); + boolean ok = (resp != null && "success".equalsIgnoreCase(resp.optString("status"))); + + if (ok) { + // پاک کردن خطاها passwordField.getStyleClass().remove("error"); visiblePasswordField.getStyleClass().remove("error"); passwordLabel.getStyleClass().remove("error"); - // Go to the next scene - openChangeCredentials(); - + openChangeCredentials(entered); // ← پسورد فعلی را پاس بده } else { - // Error → add error styles if (!passwordField.getStyleClass().contains("error")) passwordField.getStyleClass().add("error"); - if (!visiblePasswordField.getStyleClass().contains("error")) visiblePasswordField.getStyleClass().add("error"); - if (!passwordLabel.getStyleClass().contains("error")) passwordLabel.getStyleClass().add("error"); } @@ -146,15 +158,17 @@ public class CheckPasswordController { backButton.setGraphic(icon); } - private void openChangeCredentials() { + private void openChangeCredentials(String currentPassword) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource( "/org/to/telegramfinalproject/Fxml/change_credentials.fxml")); Node overlay = loader.load(); - // Show new overlay - MainController.getInstance().showOverlay(overlay); + ChangeCredentialsController c = loader.getController(); + c.setCurrentPassword(currentPassword); // ← مهم + c.prefillFromSession(); // ← پیش‌پر کردن + MainController.getInstance().showOverlay(overlay); } catch (IOException ex) { ex.printStackTrace(); } diff --git a/src/main/java/org/to/telegramfinalproject/UI/EditProfileController.java b/src/main/java/org/to/telegramfinalproject/UI/EditProfileController.java index 8d4fac0..90543d1 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/EditProfileController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/EditProfileController.java @@ -49,6 +49,13 @@ public class EditProfileController { @FXML private TextField bioField; @FXML private TextField usernameField; + // EditProfileController.java + private SettingsController parentSettings; + public void setParentSettings(SettingsController sc) { + this.parentSettings = sc; + } + + @FXML private void initialize() { backButton.setGraphic(new ImageView( @@ -56,19 +63,34 @@ public class EditProfileController { )); // close on background click +// overlayBackground.setOnMouseClicked(e -> { +// saveChangesAndClose(); +// closeEdit(); +// }); +// +// closeButton.setOnAction(e -> { +// saveChangesAndClose(); +// closeEdit(); +// }); +// +// backButton.setOnAction(e -> { +// saveChangesAndClose(); +// MainController.getInstance().goBack(overlayBackground); +// }); + overlayBackground.setOnMouseClicked(e -> { saveChangesAndClose(); - closeEdit(); + closeEdit(); // ← همینه }); closeButton.setOnAction(e -> { saveChangesAndClose(); - closeEdit(); + closeEdit(); // ← همینه }); backButton.setOnAction(e -> { saveChangesAndClose(); - MainController.getInstance().goBack(overlayBackground); + closeEdit(); // ← قبلاً goBack بود }); // Load your camera icon image (white camera icon for visibility) @@ -122,7 +144,9 @@ public class EditProfileController { private void closeEdit() { //MainController.getInstance().closeOverlay(editCard.getParent()); - MainController.getInstance().goBack(overlayBackground); +// MainController.getInstance().goBack(overlayBackground); + MainController.getInstance().closeOverlay(editCard.getParent()); + } @@ -233,21 +257,33 @@ public class EditProfileController { } if (!anyError) { - MyProfileController.getInstance().setProfileData( - currentUser.optString("profile_name"), - "online", - currentUser.optString("bio"), - currentUser.optString("user_id"), - currentUser.optString("image_url", "/org/to/telegramfinalproject/Avatars/default_user_profile.png") + // 1) اگر صفحه‌ی MyProfile باز است + var mp = MyProfileController.getInstance(); + if (mp != null) { + mp.setProfileData( + currentUser.optString("profile_name"), + "online", + currentUser.optString("bio"), + currentUser.optString("user_id"), + currentUser.optString("image_url", "/org/to/telegramfinalproject/Avatars/default_user_profile.png") + ); + } + // 2) خودِ کارت Settings را فوراً از Session ریفرش کن + if (parentSettings != null) { + parentSettings.populateFromSession(); + } - ); -// MainController mc = MainController.getInstance(); + // 3) سایدبار بالایی (اسم/آواتار خود کاربر) اگر داری MainController.getInstance().refreshSidebarUserFromSession(); - MainController.getInstance().goBack(overlayBackground); -// MainController.getInstance().closeOverlay(bioField.getParent().getParent()); + // 4) بستن اورلی ادیت +// MainController.getInstance().goBack(overlayBackground); + MainController.getInstance().closeOverlay(editCard.getParent()); + } + + } private void showAlert(String title, String message, Alert.AlertType type) { diff --git a/src/main/java/org/to/telegramfinalproject/UI/SettingsController.java b/src/main/java/org/to/telegramfinalproject/UI/SettingsController.java index 05d4a95..bc04c31 100644 --- a/src/main/java/org/to/telegramfinalproject/UI/SettingsController.java +++ b/src/main/java/org/to/telegramfinalproject/UI/SettingsController.java @@ -8,7 +8,6 @@ import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; -import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.shape.Circle; @@ -33,17 +32,25 @@ public class SettingsController { private static final String ICON_PATH = "/org/to/telegramfinalproject/Icons/"; + private Image cachedAvatar; + private String cachedName = ""; + private String cachedUsername = ""; + private String cachedStatus = ""; + private String cachedBio = ""; + + private static String nz(String s){ return s==null? "": s.trim(); } + private static boolean hasVal(String s){ return s!=null && !s.trim().isEmpty() && !"null".equalsIgnoreCase(s); } + + private static SettingsController instance; + public static SettingsController getInstance() { return instance; } @FXML public void initialize() { + instance = this; + editProfileItem.setOnAction(e -> openEditProfile()); logoutItem.setOnAction(e -> System.out.println("Log Out clicked")); - // Example data – load from DB or user session later - profileName.setText("Asal"); - profileId.setText("@Whales_suicide"); - profileImage.setImage(new Image( - getClass().getResourceAsStream("/org/to/telegramfinalproject/Avatars/default_user_profile.png") - )); + populateFromSession(); // Make it circular Circle clip = new Circle(48, 28, 38); // centerX, centerY, radius @@ -104,19 +111,20 @@ public class SettingsController { EditProfileController controller = loader.getController(); controller.setProfileData( - profileName.getText(), - "online", - "Pass me that lovely little gun♡.", - "@Whales_suicide", - profileImage.getImage() + cachedName, + cachedStatus, + cachedBio, + cachedUsername, + cachedAvatar ); - + controller.setParentSettings(this); MainController.getInstance().showOverlay(editOverlay); } catch (IOException ex) { ex.printStackTrace(); } } + private void updateEditIcon(boolean darkMode) { String editPath = darkMode ? "/org/to/telegramfinalproject/Icons/edit_light.png" @@ -169,4 +177,57 @@ public class SettingsController { } return new Image(res.toExternalForm()); } + + + + + void populateFromSession() { + var u = org.to.telegramfinalproject.Client.Session.currentUser; + if (u == null) return; + + // نام + String name = nz(u.optString("profile_name", + u.optString("name", + u.optString("first_name","")))); + + // یوزرنیم/آی‌دی نمایشی + String handle = nz(u.optString("username", + u.optString("display_id", + u.optString("user_name","")))); + // وضعیت + String status = u.optBoolean("online", false) ? "online" : "online"; + String lastSeen = nz(u.optString("last_seen", "")); + if (!u.optBoolean("online", false) && hasVal(lastSeen)) status = "online"; // ساده + + // بیو (اگر داری) + String bio = nz(u.optString("bio","")); + + // آواتار + Image avatar = null; + String imageUrl = nz(u.optString("image_url","")); + if (hasVal(imageUrl)) { + try { avatar = org.to.telegramfinalproject.Client.AvatarLocalResolver.load(imageUrl); } + catch (Exception ignore) {} + } + if (avatar == null) { + avatar = new Image(getClass().getResourceAsStream( + "/org/to/telegramfinalproject/Avatars/default_user_profile.png")); + } + + // کش محلی برای استفاده در صفحه‌ی ویرایش + cachedName = hasVal(name) ? name : "User"; + cachedUsername = hasVal(handle) ? handle : ""; + cachedStatus = status; + cachedBio = bio; + cachedAvatar = avatar; + + // ست کردن در UI + profileName.setText(cachedName); + profileId.setText(cachedUsername); + profileImage.setImage(cachedAvatar); + + // گرد کردن تصویر (با توجه به اندازه‌ی واقعی) + Circle clip = new Circle(38, 38, 38); // centerX, centerY, radius + profileImage.setClip(clip); + } }