mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-05 05:46:44 +00:00
add button to view password field contents
This commit is contained in:
parent
4cbd778ca1
commit
1defe51fd7
8 changed files with 141 additions and 8 deletions
|
@ -332,7 +332,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
VBox vBox = new VBox();
|
VBox vBox = new VBox();
|
||||||
vBox.setMaxHeight(120);
|
vBox.setMaxHeight(120);
|
||||||
vBox.setSpacing(42);
|
vBox.setSpacing(42);
|
||||||
pinField = (CustomPasswordField)TextFields.createClearablePasswordField();
|
pinField = new ViewPasswordField();
|
||||||
Platform.runLater(() -> pinField.requestFocus());
|
Platform.runLater(() -> pinField.requestFocus());
|
||||||
enterPinButton = new Button("Enter PIN");
|
enterPinButton = new Button("Enter PIN");
|
||||||
enterPinButton.setDefaultButton(true);
|
enterPinButton.setDefaultButton(true);
|
||||||
|
@ -372,7 +372,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Node getPassphraseEntry() {
|
private Node getPassphraseEntry() {
|
||||||
CustomPasswordField passphraseField = (CustomPasswordField)TextFields.createClearablePasswordField();
|
CustomPasswordField passphraseField = new ViewPasswordField();
|
||||||
passphrase.bind(passphraseField.textProperty());
|
passphrase.bind(passphraseField.textProperty());
|
||||||
HBox.setHgrow(passphraseField, Priority.ALWAYS);
|
HBox.setHgrow(passphraseField, Priority.ALWAYS);
|
||||||
passphraseField.setOnAction(event -> {
|
passphraseField.setOnAction(event -> {
|
||||||
|
|
|
@ -190,7 +190,7 @@ public abstract class FileImportPane extends TitledDescriptionPane {
|
||||||
protected abstract void importFile(String fileName, InputStream inputStream, String password) throws ImportException;
|
protected abstract void importFile(String fileName, InputStream inputStream, String password) throws ImportException;
|
||||||
|
|
||||||
private Node getPasswordEntry(File file) {
|
private Node getPasswordEntry(File file) {
|
||||||
CustomPasswordField passwordField = (CustomPasswordField) TextFields.createClearablePasswordField();
|
CustomPasswordField passwordField = new ViewPasswordField();
|
||||||
passwordField.setPromptText("Wallet password");
|
passwordField.setPromptText("Wallet password");
|
||||||
password.bind(passwordField.textProperty());
|
password.bind(passwordField.textProperty());
|
||||||
HBox.setHgrow(passwordField, Priority.ALWAYS);
|
HBox.setHgrow(passwordField, Priority.ALWAYS);
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class KeystorePassphraseDialog extends Dialog<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeystorePassphraseDialog(String walletName, Keystore keystore, boolean confirm) {
|
public KeystorePassphraseDialog(String walletName, Keystore keystore, boolean confirm) {
|
||||||
this.passphrase = (CustomPasswordField) TextFields.createClearablePasswordField();
|
this.passphrase = new ViewPasswordField();
|
||||||
|
|
||||||
final DialogPane dialogPane = getDialogPane();
|
final DialogPane dialogPane = getDialogPane();
|
||||||
setTitle("Keystore Passphrase" + (walletName != null ? " for " + walletName : ""));
|
setTitle("Keystore Passphrase" + (walletName != null ? " for " + walletName : ""));
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Skin;
|
||||||
|
import org.controlsfx.control.textfield.CustomPasswordField;
|
||||||
|
|
||||||
|
public class ViewPasswordField extends CustomPasswordField {
|
||||||
|
public ViewPasswordField() {
|
||||||
|
super();
|
||||||
|
getStyleClass().add("view-password-text-field");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Skin<?> createDefaultSkin() {
|
||||||
|
return new ViewPasswordFieldSkin(this) {
|
||||||
|
@Override
|
||||||
|
public ObjectProperty<Node> leftProperty() {
|
||||||
|
return ViewPasswordField.this.leftProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectProperty<Node> rightProperty() {
|
||||||
|
return ViewPasswordField.this.rightProperty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import impl.org.controlsfx.skin.CustomTextFieldSkin;
|
||||||
|
import javafx.animation.FadeTransition;
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
|
import javafx.beans.Observable;
|
||||||
|
import javafx.scene.Cursor;
|
||||||
|
import javafx.scene.control.PasswordField;
|
||||||
|
import javafx.scene.layout.*;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
import org.controlsfx.control.textfield.CustomPasswordField;
|
||||||
|
|
||||||
|
public abstract class ViewPasswordFieldSkin extends CustomTextFieldSkin {
|
||||||
|
private static final Duration FADE_DURATION = Duration.millis(350);
|
||||||
|
public static final char BULLET = '\u25CF';
|
||||||
|
|
||||||
|
private boolean mask = true;
|
||||||
|
|
||||||
|
public ViewPasswordFieldSkin(CustomPasswordField textField) {
|
||||||
|
super(textField);
|
||||||
|
|
||||||
|
Region viewPasswordButton = new Region();
|
||||||
|
viewPasswordButton.getStyleClass().addAll("graphic");
|
||||||
|
StackPane viewPasswordButtonPane = new StackPane(viewPasswordButton);
|
||||||
|
viewPasswordButtonPane.getStyleClass().addAll("view-password-button");
|
||||||
|
viewPasswordButtonPane.setOpacity(0.0);
|
||||||
|
viewPasswordButtonPane.setCursor(Cursor.DEFAULT);
|
||||||
|
|
||||||
|
viewPasswordButtonPane.setOnMouseReleased(e -> {
|
||||||
|
if(mask) {
|
||||||
|
viewPasswordButtonPane.getStyleClass().remove("view-password-button");
|
||||||
|
viewPasswordButtonPane.getStyleClass().addAll("hide-password-button");
|
||||||
|
mask = false;
|
||||||
|
} else {
|
||||||
|
viewPasswordButtonPane.getStyleClass().remove("hide-password-button");
|
||||||
|
viewPasswordButtonPane.getStyleClass().addAll("view-password-button");
|
||||||
|
mask = true;
|
||||||
|
}
|
||||||
|
textField.setText(textField.getText());
|
||||||
|
textField.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
textField.rightProperty().set(viewPasswordButtonPane);
|
||||||
|
|
||||||
|
final FadeTransition fader = new FadeTransition(FADE_DURATION, viewPasswordButtonPane);
|
||||||
|
fader.setCycleCount(1);
|
||||||
|
|
||||||
|
textField.textProperty().addListener(new InvalidationListener() {
|
||||||
|
@Override
|
||||||
|
public void invalidated(Observable arg0) {
|
||||||
|
String text = textField.getText();
|
||||||
|
boolean isTextEmpty = text == null || text.isEmpty();
|
||||||
|
boolean isButtonVisible = fader.getNode().getOpacity() > 0;
|
||||||
|
|
||||||
|
if (isTextEmpty && isButtonVisible) {
|
||||||
|
setButtonVisible(false);
|
||||||
|
} else if (!isTextEmpty && !isButtonVisible) {
|
||||||
|
setButtonVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setButtonVisible( boolean visible ) {
|
||||||
|
fader.setFromValue(visible? 0.0: 1.0);
|
||||||
|
fader.setToValue(visible? 1.0: 0.0);
|
||||||
|
fader.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String maskText(String txt) {
|
||||||
|
if(getSkinnable() instanceof PasswordField && mask) {
|
||||||
|
int n = txt.length();
|
||||||
|
StringBuilder passwordBuilder = new StringBuilder(n);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
passwordBuilder.append(BULLET);
|
||||||
|
}
|
||||||
|
return passwordBuilder.toString();
|
||||||
|
} else {
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ import javafx.beans.binding.BooleanBinding;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.controlsfx.control.textfield.CustomPasswordField;
|
import org.controlsfx.control.textfield.CustomPasswordField;
|
||||||
import org.controlsfx.control.textfield.TextFields;
|
|
||||||
import org.controlsfx.glyphfont.FontAwesome;
|
import org.controlsfx.glyphfont.FontAwesome;
|
||||||
import org.controlsfx.glyphfont.Glyph;
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
import org.controlsfx.validation.ValidationResult;
|
import org.controlsfx.validation.ValidationResult;
|
||||||
|
@ -31,8 +30,8 @@ public class WalletPasswordDialog extends Dialog<SecureString> {
|
||||||
|
|
||||||
public WalletPasswordDialog(String walletName, PasswordRequirement requirement, boolean suggestChangePassword) {
|
public WalletPasswordDialog(String walletName, PasswordRequirement requirement, boolean suggestChangePassword) {
|
||||||
this.requirement = requirement;
|
this.requirement = requirement;
|
||||||
this.password = (CustomPasswordField)TextFields.createClearablePasswordField();
|
this.password = new ViewPasswordField();
|
||||||
this.passwordConfirm = (CustomPasswordField)TextFields.createClearablePasswordField();
|
this.passwordConfirm = new ViewPasswordField();
|
||||||
this.backupExisting = new CheckBox("Backup existing wallet first");
|
this.backupExisting = new CheckBox("Backup existing wallet first");
|
||||||
this.changePassword = new CheckBox("Change password");
|
this.changePassword = new CheckBox("Change password");
|
||||||
this.deleteBackups = new CheckBox("Delete any backups");
|
this.deleteBackups = new CheckBox("Delete any backups");
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.sparrowwallet.drongo.crypto.InvalidPasswordException;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.AppServices;
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
import com.sparrowwallet.sparrow.control.ViewPasswordField;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
import com.sparrowwallet.sparrow.io.Storage;
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
@ -147,7 +148,7 @@ public class WalletController extends WalletFormController implements Initializa
|
||||||
Label label = new Label("Enter password to unlock:");
|
Label label = new Label("Enter password to unlock:");
|
||||||
label.managedProperty().bind(label.visibleProperty());
|
label.managedProperty().bind(label.visibleProperty());
|
||||||
label.visibleProperty().bind(walletEncryptedProperty);
|
label.visibleProperty().bind(walletEncryptedProperty);
|
||||||
CustomPasswordField passwordField = (CustomPasswordField)TextFields.createClearablePasswordField();
|
CustomPasswordField passwordField = new ViewPasswordField();
|
||||||
passwordField.setMaxWidth(300);
|
passwordField.setMaxWidth(300);
|
||||||
passwordField.managedProperty().bind(passwordField.visibleProperty());
|
passwordField.managedProperty().bind(passwordField.visibleProperty());
|
||||||
passwordField.visibleProperty().bind(walletEncryptedProperty);
|
passwordField.visibleProperty().bind(walletEncryptedProperty);
|
||||||
|
|
|
@ -156,6 +156,28 @@
|
||||||
-fx-background-color: #116a8d;
|
-fx-background-color: #116a8d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.view-password-text-field .view-password-button > .graphic {
|
||||||
|
-fx-background-color: #949494;
|
||||||
|
-fx-scale-shape: false;
|
||||||
|
-fx-padding: 0 25 0 0;
|
||||||
|
-fx-shape: "M10.4617+4.5C6.16092+4.5+2.48807+7.02125+1+10.5802C2.48807+14.1391+6.16092+16.6604+10.4617+16.6604C14.7625+16.6604+18.4353+14.1391+19.9234+10.5802C18.4353+7.02125+14.7625+4.5+10.4617+4.5ZM10.4617+14.6336C8.08767+14.6336+6.16092+12.8177+6.16092+10.5802C6.16092+8.34268+8.08767+6.52673+10.4617+6.52673C12.8357+6.52673+14.7625+8.34268+14.7625+10.5802C14.7625+12.8177+12.8357+14.6336+10.4617+14.6336ZM10.4617+8.14811C9.03384+8.14811+7.88123+9.23444+7.88123+10.5802C7.88123+11.9259+9.03384+13.0123+10.4617+13.0123C11.8896+13.0123+13.0422+11.9259+13.0422+10.5802C13.0422+9.23444+11.8896+8.14811+10.4617+8.14811Z";
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-password-text-field .hide-password-button > .graphic {
|
||||||
|
-fx-background-color: #949494;
|
||||||
|
-fx-scale-shape: false;
|
||||||
|
-fx-padding: 0 25 0 0;
|
||||||
|
-fx-shape: "M10.6168+6.26674C13.9302+6.26674+16.8852+7.95776+18.3277+10.6332C17.8119+11.6018+17.0863+12.4354+16.2208+13.1102L17.4535+14.2296C18.6687+13.2531+19.6304+12.0305+20.2336+10.6332C18.7212+7.14798+14.9881+4.67893+10.6168+4.67893C9.50651+4.67893+8.43991+4.83772+7.43452+5.13146L8.87704+6.4414C9.44531+6.3382+10.0223+6.26674+10.6168+6.26674ZM9.68136+7.1718L11.4911+8.81518C11.9894+9.01366+12.3915+9.37885+12.6101+9.83138L14.4198+11.4748C14.4898+11.2048+14.5422+10.919+14.5422+10.6253C14.551+8.6564+12.785+7.06065+10.6168+7.06065C10.2933+7.06065+9.98735+7.10034+9.68136+7.1718ZM1.883+4.57573L4.226+6.70339C2.80097+7.71959+1.67318+9.06923+1+10.6332C2.51246+14.1185+6.24553+16.5875+10.6168+16.5875C11.9457+16.5875+13.2221+16.3573+14.3936+15.9365L17.3835+18.6517L18.6162+17.5323L3.1157+3.44838L1.883+4.57573ZM8.43991+10.53L10.7217+12.6021C10.6868+12.61+10.6518+12.618+10.6168+12.618C9.41034+12.618+8.43117+11.7288+8.43117+10.6332C8.43117+10.5935+8.43991+10.5697+8.43991+10.53ZM5.46745+7.83074L6.99739+9.22007C6.79631+9.65672+6.68266+10.1331+6.68266+10.6332C6.68266+12.6021+8.44866+14.2058+10.6168+14.2058C11.1676+14.2058+11.6921+14.1026+12.1642+13.92L13.021+14.698C12.2517+14.8886+11.4474+14.9997+10.6168+14.9997C7.30338+14.9997+4.3484+13.3087+2.90588+10.6332C3.51786+9.49794+4.4096+8.56113+5.46745+7.83074Z";
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-password-text-field .view-password-button:hover > .graphic, .view-password-text-field .hide-password-button:hover > .graphic {
|
||||||
|
-fx-background-color: #0184bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-password-text-field .view-password-button:pressed > .graphic, .view-password-text-field .hide-password-button:pressed > .graphic {
|
||||||
|
-fx-background-color: #116a8d;
|
||||||
|
}
|
||||||
|
|
||||||
.readonly.text-input {
|
.readonly.text-input {
|
||||||
-fx-text-fill: derive(-fx-text-inner-color, 40%);
|
-fx-text-fill: derive(-fx-text-inner-color, 40%);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue