2020-08-01 09:43:15 +02:00
|
|
|
package envoy.client.ui.settings;
|
|
|
|
|
2020-09-08 20:41:01 +02:00
|
|
|
import java.io.*;
|
2020-08-01 10:00:29 +02:00
|
|
|
import java.nio.file.Files;
|
2020-09-08 20:41:01 +02:00
|
|
|
import java.util.logging.*;
|
2020-08-01 10:00:29 +02:00
|
|
|
|
2020-08-01 09:54:18 +02:00
|
|
|
import javafx.event.EventHandler;
|
2020-08-01 10:17:39 +02:00
|
|
|
import javafx.geometry.Pos;
|
2020-08-01 10:00:29 +02:00
|
|
|
import javafx.scene.Cursor;
|
2020-08-01 10:17:39 +02:00
|
|
|
import javafx.scene.control.*;
|
2020-08-01 09:43:15 +02:00
|
|
|
import javafx.scene.control.Alert.AlertType;
|
2020-09-08 20:41:01 +02:00
|
|
|
import javafx.scene.image.*;
|
2020-08-01 09:54:18 +02:00
|
|
|
import javafx.scene.input.InputEvent;
|
|
|
|
import javafx.scene.layout.HBox;
|
2020-08-01 10:00:29 +02:00
|
|
|
import javafx.stage.FileChooser;
|
2020-10-24 12:19:11 +02:00
|
|
|
import javafx.util.Duration;
|
2020-08-01 09:43:15 +02:00
|
|
|
|
2020-10-19 18:17:51 +02:00
|
|
|
import dev.kske.eventbus.EventBus;
|
|
|
|
|
2020-08-01 09:43:15 +02:00
|
|
|
import envoy.event.*;
|
2020-09-08 20:41:01 +02:00
|
|
|
import envoy.util.*;
|
|
|
|
|
2020-10-19 18:17:51 +02:00
|
|
|
import envoy.client.ui.control.ProfilePicImageView;
|
2020-10-19 22:16:18 +02:00
|
|
|
import envoy.client.util.*;
|
2020-08-01 09:43:15 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Leon Hofmeister
|
|
|
|
* @since Envoy Client v0.2-beta
|
|
|
|
*/
|
2020-09-25 14:29:23 +02:00
|
|
|
public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
2020-08-01 09:43:15 +02:00
|
|
|
|
2020-08-01 14:57:08 +02:00
|
|
|
private boolean profilePicChanged, usernameChanged, validPassword;
|
2020-08-02 20:26:22 +02:00
|
|
|
private byte[] currentImageBytes;
|
2020-08-01 10:17:39 +02:00
|
|
|
private String newUsername, newPassword = "";
|
2020-08-01 09:43:15 +02:00
|
|
|
|
2020-08-02 20:26:22 +02:00
|
|
|
private final ImageView profilePic = new ProfilePicImageView(null, 60);
|
|
|
|
private final TextField usernameTextField = new TextField();
|
|
|
|
private final PasswordField currentPasswordField = new PasswordField();
|
|
|
|
private final PasswordField newPasswordField = new PasswordField();
|
|
|
|
private final PasswordField repeatNewPasswordField = new PasswordField();
|
|
|
|
private final Button saveButton = new Button("Save");
|
2020-10-24 12:19:11 +02:00
|
|
|
private final Button deleteAccountButton = new Button("Delete Account (Locally)");
|
2020-08-02 20:26:22 +02:00
|
|
|
|
|
|
|
private static final EventBus eventBus = EventBus.getInstance();
|
|
|
|
private static final Logger logger = EnvoyLog.getLogger(UserSettingsPane.class);
|
|
|
|
|
2020-08-01 09:43:15 +02:00
|
|
|
/**
|
|
|
|
* Creates a new {@code UserSettingsPane}.
|
|
|
|
*
|
|
|
|
* @since Envoy Client v0.2-beta
|
|
|
|
*/
|
2020-09-25 14:29:23 +02:00
|
|
|
public UserSettingsPane() {
|
|
|
|
super("User");
|
2020-08-02 20:26:22 +02:00
|
|
|
setSpacing(10);
|
2020-08-01 10:00:29 +02:00
|
|
|
|
|
|
|
// Display of profile pic change mechanism
|
2020-08-01 09:54:18 +02:00
|
|
|
final var hbox = new HBox();
|
2020-08-01 10:00:29 +02:00
|
|
|
// TODO: display current profile pic
|
2020-08-02 20:26:22 +02:00
|
|
|
profilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon"));
|
2020-08-01 10:00:29 +02:00
|
|
|
profilePic.setCursor(Cursor.HAND);
|
2020-08-02 20:26:22 +02:00
|
|
|
profilePic.setFitWidth(60);
|
|
|
|
profilePic.setFitHeight(60);
|
2020-08-01 10:00:29 +02:00
|
|
|
profilePic.setOnMouseClicked(e -> {
|
2020-10-19 18:17:51 +02:00
|
|
|
if (!client.isOnline())
|
|
|
|
return;
|
2020-08-01 10:00:29 +02:00
|
|
|
final var pictureChooser = new FileChooser();
|
|
|
|
|
2020-08-02 20:26:22 +02:00
|
|
|
pictureChooser.setTitle("Select a new profile pic");
|
2020-08-01 10:00:29 +02:00
|
|
|
pictureChooser.setInitialDirectory(new File(System.getProperty("user.home")));
|
2020-10-19 18:17:51 +02:00
|
|
|
pictureChooser.getExtensionFilters().add(
|
|
|
|
new FileChooser.ExtensionFilter("Pictures", "*.png", "*.jpg", "*.bmp", "*.gif"));
|
2020-08-01 10:00:29 +02:00
|
|
|
|
2020-10-07 23:43:30 +02:00
|
|
|
final var file = pictureChooser.showOpenDialog(context.getSceneContext().getStage());
|
2020-08-01 10:00:29 +02:00
|
|
|
|
|
|
|
if (file != null) {
|
|
|
|
|
|
|
|
// Check max file size
|
2020-09-25 14:29:23 +02:00
|
|
|
// TODO: Move to config
|
2020-08-01 10:00:29 +02:00
|
|
|
if (file.length() > 5E6) {
|
2020-10-19 18:17:51 +02:00
|
|
|
new Alert(AlertType.WARNING, "The selected file exceeds the size limit of 5MB!")
|
|
|
|
.showAndWait();
|
2020-08-01 10:00:29 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
currentImageBytes = Files.readAllBytes(file.toPath());
|
|
|
|
profilePic.setImage(new Image(new ByteArrayInputStream(currentImageBytes)));
|
|
|
|
profilePicChanged = true;
|
|
|
|
} catch (final IOException e1) {
|
|
|
|
e1.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
hbox.getChildren().add(profilePic);
|
2020-08-01 09:54:18 +02:00
|
|
|
|
|
|
|
// Displaying the username change mechanism
|
2020-09-25 14:29:23 +02:00
|
|
|
final var username = client.getSender().getName();
|
2020-08-01 10:17:39 +02:00
|
|
|
newUsername = username;
|
2020-08-02 20:26:22 +02:00
|
|
|
usernameTextField.setText(username);
|
|
|
|
final EventHandler<? super InputEvent> textChanged = e -> {
|
2020-10-19 18:17:51 +02:00
|
|
|
newUsername = usernameTextField.getText();
|
|
|
|
usernameChanged = newUsername != username;
|
2020-08-01 09:54:18 +02:00
|
|
|
};
|
|
|
|
usernameTextField.setOnInputMethodTextChanged(textChanged);
|
|
|
|
usernameTextField.setOnKeyTyped(textChanged);
|
|
|
|
hbox.getChildren().add(usernameTextField);
|
2020-08-02 20:26:22 +02:00
|
|
|
getChildren().add(hbox);
|
2020-08-01 10:17:39 +02:00
|
|
|
|
|
|
|
// "Displaying" the password change mechanism
|
|
|
|
final HBox[] passwordHBoxes = { new HBox(), new HBox(), new HBox() };
|
2020-10-19 18:17:51 +02:00
|
|
|
final Label[] passwordLabels =
|
|
|
|
{ new Label("Enter current password:"), new Label("Enter new password:"),
|
2020-08-01 10:17:39 +02:00
|
|
|
new Label("Repeat new password:") };
|
|
|
|
|
2020-10-19 18:17:51 +02:00
|
|
|
final PasswordField[] passwordFields =
|
|
|
|
{ currentPasswordField, newPasswordField, repeatNewPasswordField };
|
2020-10-19 22:16:18 +02:00
|
|
|
final EventHandler<? super InputEvent> passwordEntered =
|
|
|
|
e -> {
|
|
|
|
newPassword =
|
|
|
|
newPasswordField
|
|
|
|
.getText();
|
|
|
|
validPassword =
|
|
|
|
newPassword.equals(
|
|
|
|
repeatNewPasswordField
|
|
|
|
.getText())
|
|
|
|
&& !newPasswordField
|
|
|
|
.getText()
|
|
|
|
.isBlank();
|
|
|
|
};
|
2020-08-01 10:17:39 +02:00
|
|
|
newPasswordField.setOnInputMethodTextChanged(passwordEntered);
|
|
|
|
newPasswordField.setOnKeyTyped(passwordEntered);
|
|
|
|
repeatNewPasswordField.setOnInputMethodTextChanged(passwordEntered);
|
|
|
|
repeatNewPasswordField.setOnKeyTyped(passwordEntered);
|
|
|
|
|
|
|
|
for (int i = 0; i < passwordHBoxes.length; i++) {
|
|
|
|
final var hBox2 = passwordHBoxes[i];
|
2020-08-02 20:26:22 +02:00
|
|
|
passwordLabels[i].setWrapText(true);
|
2020-08-01 10:17:39 +02:00
|
|
|
hBox2.getChildren().add(passwordLabels[i]);
|
|
|
|
hBox2.getChildren().add(passwordFields[i]);
|
2020-08-02 20:26:22 +02:00
|
|
|
getChildren().add(hBox2);
|
2020-08-01 10:17:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Displaying the save button
|
2020-10-19 18:17:51 +02:00
|
|
|
saveButton
|
2020-10-27 23:01:44 +01:00
|
|
|
.setOnAction(e -> save(currentPasswordField.getText()));
|
2020-08-01 10:17:39 +02:00
|
|
|
saveButton.setAlignment(Pos.BOTTOM_RIGHT);
|
2020-08-02 20:26:22 +02:00
|
|
|
getChildren().add(saveButton);
|
2020-10-19 22:16:18 +02:00
|
|
|
|
|
|
|
// Displaying the delete account button
|
|
|
|
deleteAccountButton.setAlignment(Pos.BASELINE_CENTER);
|
|
|
|
deleteAccountButton.setOnAction(e -> UserUtil.deleteAccount());
|
2020-10-24 12:19:11 +02:00
|
|
|
deleteAccountButton.setText("Delete Account (locally)");
|
|
|
|
deleteAccountButton.setPrefHeight(25);
|
|
|
|
deleteAccountButton.getStyleClass().clear();
|
|
|
|
deleteAccountButton.getStyleClass().add("danger-button");
|
|
|
|
final var tooltip = new Tooltip("Remote deletion is currently unsupported.");
|
|
|
|
tooltip.setShowDelay(Duration.millis(100));
|
|
|
|
deleteAccountButton.setTooltip(tooltip);
|
2020-10-19 22:16:18 +02:00
|
|
|
getChildren().add(deleteAccountButton);
|
2020-08-01 09:54:18 +02:00
|
|
|
}
|
2020-08-01 09:43:15 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Saves the given input and sends the changed input to the server
|
|
|
|
*
|
|
|
|
* @param username the new username
|
|
|
|
* @since Envoy Client v0.2-beta
|
|
|
|
*/
|
2020-10-27 23:01:44 +01:00
|
|
|
private void save(String oldPassword) {
|
2020-08-01 09:43:15 +02:00
|
|
|
|
|
|
|
// The profile pic was changed
|
2020-08-02 20:26:22 +02:00
|
|
|
if (profilePicChanged) {
|
2020-10-27 23:01:44 +01:00
|
|
|
final var profilePicChangeEvent = new ProfilePicChange(currentImageBytes);
|
2020-08-01 14:57:08 +02:00
|
|
|
eventBus.dispatch(profilePicChangeEvent);
|
2020-09-25 14:29:23 +02:00
|
|
|
client.send(profilePicChangeEvent);
|
2020-08-01 14:57:08 +02:00
|
|
|
logger.log(Level.INFO, "The user just changed his profile pic.");
|
|
|
|
}
|
2020-08-01 09:43:15 +02:00
|
|
|
|
|
|
|
// The username was changed
|
|
|
|
final var validContactName = Bounds.isValidContactName(newUsername);
|
2020-08-01 14:57:08 +02:00
|
|
|
if (usernameChanged && validContactName) {
|
2020-10-27 23:01:44 +01:00
|
|
|
final var nameChangeEvent = new NameChange(client.getSender().getID(), newUsername);
|
2020-08-01 14:57:08 +02:00
|
|
|
eventBus.dispatch(nameChangeEvent);
|
2020-09-25 14:29:23 +02:00
|
|
|
client.send(nameChangeEvent);
|
2020-08-01 14:57:08 +02:00
|
|
|
logger.log(Level.INFO, "The user just changed his name to " + newUsername + ".");
|
|
|
|
} else if (!validContactName) {
|
2020-08-01 09:43:15 +02:00
|
|
|
final var alert = new Alert(AlertType.ERROR);
|
|
|
|
alert.setTitle("Invalid username");
|
2020-10-19 18:17:51 +02:00
|
|
|
alert.setContentText(
|
|
|
|
"The entered username does not conform with the naming limitations: "
|
|
|
|
+ Bounds.CONTACT_NAME_PATTERN);
|
2020-08-01 09:43:15 +02:00
|
|
|
alert.showAndWait();
|
2020-08-01 14:57:08 +02:00
|
|
|
logger.log(Level.INFO, "An invalid username was requested.");
|
2020-08-01 09:43:15 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The password was changed
|
2020-08-01 14:57:08 +02:00
|
|
|
if (validPassword) {
|
2020-10-27 23:01:44 +01:00
|
|
|
client.send(new PasswordChangeRequest(newPassword, oldPassword));
|
2020-08-01 14:57:08 +02:00
|
|
|
logger.log(Level.INFO, "The user just tried to change his password!");
|
|
|
|
} else if (!(validPassword || newPassword.isBlank())) {
|
2020-08-01 09:43:15 +02:00
|
|
|
final var alert = new Alert(AlertType.ERROR);
|
|
|
|
alert.setTitle("Unequal Password");
|
|
|
|
alert.setContentText("Repeated password is unequal to the chosen new password");
|
|
|
|
alert.showAndWait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|