This repository has been archived on 2021-12-05. You can view files and clone it, but cannot push or open issues or pull requests.
envoy/client/src/main/java/envoy/client/ui/settings/UserSettingsPane.java

208 lines
7.2 KiB
Java

package envoy.client.ui.settings;
import java.io.*;
import java.nio.file.Files;
import java.util.logging.*;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.*;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.*;
import javafx.scene.input.InputEvent;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.util.Duration;
import dev.kske.eventbus.core.EventBus;
import envoy.event.*;
import envoy.util.*;
import envoy.client.ui.control.ProfilePicImageView;
import envoy.client.util.*;
/**
* @author Leon Hofmeister
* @since Envoy Client v0.2-beta
*/
public final class UserSettingsPane extends OnlineOnlySettingsPane {
private boolean profilePicChanged, usernameChanged, validPassword;
private byte[] currentImageBytes;
private String newUsername, newPassword = "";
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");
private final Button deleteAccountButton = new Button("Delete Account (Locally)");
private static final EventBus eventBus = EventBus.getInstance();
private static final Logger logger = EnvoyLog.getLogger(UserSettingsPane.class);
/**
* Creates a new {@code UserSettingsPane}.
*
* @since Envoy Client v0.2-beta
*/
public UserSettingsPane() {
super("User");
setSpacing(10);
// Display of profile pic change mechanism
final var hbox = new HBox();
// TODO: display current profile pic
profilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon"));
profilePic.setCursor(Cursor.HAND);
profilePic.setFitWidth(60);
profilePic.setFitHeight(60);
profilePic.setOnMouseClicked(e -> {
if (!client.isOnline())
return;
final var pictureChooser = new FileChooser();
pictureChooser.setTitle("Select a new profile pic");
pictureChooser.setInitialDirectory(new File(System.getProperty("user.home")));
pictureChooser.getExtensionFilters().add(
new FileChooser.ExtensionFilter("Pictures", "*.png", "*.jpg", "*.bmp", "*.gif"));
final var file = pictureChooser.showOpenDialog(context.getSceneContext().getStage());
if (file != null) {
// Check max file size
// TODO: Move to config
if (file.length() > 5E6) {
new Alert(AlertType.WARNING, "The selected file exceeds the size limit of 5MB!")
.showAndWait();
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);
// Displaying the username change mechanism
final var username = client.getSender().getName();
newUsername = username;
usernameTextField.setText(username);
final EventHandler<? super InputEvent> textChanged = e -> {
newUsername = usernameTextField.getText();
usernameChanged = newUsername != username;
};
usernameTextField.setOnInputMethodTextChanged(textChanged);
usernameTextField.setOnKeyTyped(textChanged);
hbox.getChildren().add(usernameTextField);
getChildren().add(hbox);
// "Displaying" the password change mechanism
final HBox[] passwordHBoxes = { new HBox(), new HBox(), new HBox() };
final Label[] passwordLabels =
{ new Label("Enter current password:"), new Label("Enter new password:"),
new Label("Repeat new password:") };
final PasswordField[] passwordFields =
{ currentPasswordField, newPasswordField, repeatNewPasswordField };
final EventHandler<? super InputEvent> passwordEntered =
e -> {
newPassword =
newPasswordField
.getText();
validPassword =
newPassword.equals(
repeatNewPasswordField
.getText())
&& !newPasswordField
.getText()
.isBlank();
};
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];
passwordLabels[i].setWrapText(true);
hBox2.getChildren().add(passwordLabels[i]);
hBox2.getChildren().add(passwordFields[i]);
getChildren().add(hBox2);
}
// Displaying the save button
saveButton
.setOnAction(e -> save(currentPasswordField.getText()));
saveButton.setAlignment(Pos.BOTTOM_RIGHT);
getChildren().add(saveButton);
// Displaying the delete account button
deleteAccountButton.setAlignment(Pos.BASELINE_CENTER);
deleteAccountButton.setOnAction(e -> UserUtil.deleteAccount());
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);
getChildren().add(deleteAccountButton);
}
/**
* Saves the given input and sends the changed input to the server
*
* @param username the new username
* @since Envoy Client v0.2-beta
*/
private void save(String oldPassword) {
// The profile pic was changed
if (profilePicChanged) {
final var profilePicChangeEvent = new ProfilePicChange(currentImageBytes);
eventBus.dispatch(profilePicChangeEvent);
client.send(profilePicChangeEvent);
logger.log(Level.INFO, "The user just changed his profile pic.");
}
// The username was changed
final var validContactName = Bounds.isValidContactName(newUsername);
if (usernameChanged && validContactName) {
final var nameChangeEvent = new NameChange(client.getSender().getID(), newUsername);
eventBus.dispatch(nameChangeEvent);
client.send(nameChangeEvent);
logger.log(Level.INFO, "The user just changed his name to " + newUsername + ".");
} else if (!validContactName) {
final var alert = new Alert(AlertType.ERROR);
alert.setTitle("Invalid username");
alert.setContentText(
"The entered username does not conform with the naming limitations: "
+ Bounds.CONTACT_NAME_PATTERN);
alert.showAndWait();
logger.log(Level.INFO, "An invalid username was requested.");
return;
}
// The password was changed
if (validPassword) {
client.send(new PasswordChangeRequest(newPassword, oldPassword));
logger.log(Level.INFO, "The user just tried to change his password!");
} else if (!(validPassword || newPassword.isBlank())) {
final var alert = new Alert(AlertType.ERROR);
alert.setTitle("Unequal Password");
alert.setContentText("Repeated password is unequal to the chosen new password");
alert.showAndWait();
}
}
}