From 02258dea8d5626bcc93a2cd27a5132634cc1e763 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Wed, 13 May 2020 18:15:46 +0200 Subject: [PATCH] refactor and cleanup importing --- .../sparrow/control/DeviceAccordion.java | 32 ---- .../sparrow/control/DevicePane.java | 150 ++++-------------- .../control/KeystoreImportAccordion.java | 32 ---- .../control/TitledDescriptionPane.java | 6 +- .../sparrow/control/WalletImportDialog.java | 7 +- .../sparrow/io/ColdcardSinglesig.java | 2 +- .../sparrowwallet/sparrow/io/Electrum.java | 4 +- .../keystoreimport/HwAirgappedController.java | 17 +- .../HwUsbDevicesController.java | 11 +- .../sparrow/keystoreimport/SwController.java | 27 +++- .../sparrow/keystoreimport/hw_airgapped.fxml | 4 +- .../keystoreimport/hw_usb-devices.fxml | 3 +- .../sparrow/keystoreimport/sw.fxml | 3 +- 13 files changed, 77 insertions(+), 221 deletions(-) delete mode 100644 src/main/java/com/sparrowwallet/sparrow/control/DeviceAccordion.java delete mode 100644 src/main/java/com/sparrowwallet/sparrow/control/KeystoreImportAccordion.java diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DeviceAccordion.java b/src/main/java/com/sparrowwallet/sparrow/control/DeviceAccordion.java deleted file mode 100644 index e73c24db..00000000 --- a/src/main/java/com/sparrowwallet/sparrow/control/DeviceAccordion.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sparrowwallet.sparrow.control; - -import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.io.Device; -import javafx.collections.ObservableList; -import javafx.scene.control.Accordion; - -public class DeviceAccordion extends Accordion { - private ObservableList devices; - private DeviceOperation deviceOperation = DeviceOperation.IMPORT; - - public void setDevices(Wallet wallet, ObservableList devices) { - this.devices = devices; - - for(Device device : devices) { - DevicePane devicePane = new DevicePane(this, wallet, device); - this.getPanes().add(devicePane); - } - } - - public DeviceOperation getDeviceOperation() { - return deviceOperation; - } - - public void setDeviceOperation(DeviceOperation deviceOperation) { - this.deviceOperation = deviceOperation; - } - - public enum DeviceOperation { - IMPORT; - } -} diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java index 3ed5fdeb..02e09e30 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java @@ -12,14 +12,11 @@ import com.sparrowwallet.sparrow.io.Device; import com.sparrowwallet.sparrow.io.Hwi; import com.sparrowwallet.drongo.wallet.WalletModel; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; -import javafx.application.Platform; import javafx.beans.property.SimpleStringProperty; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.*; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; import javafx.scene.layout.*; import org.controlsfx.control.textfield.CustomPasswordField; import org.controlsfx.control.textfield.CustomTextField; @@ -32,115 +29,28 @@ import org.controlsfx.validation.decoration.StyleClassValidationDecoration; import java.util.List; -public class DevicePane extends TitledPane { - private final DeviceAccordion deviceAccordion; +public class DevicePane extends TitledDescriptionPane { + private final DeviceOperation deviceOperation; private final Wallet wallet; private final Device device; - private Label mainLabel; - private Label statusLabel; - private Hyperlink showHideLink; private CustomPasswordField pinField; - private CustomTextField passphraseField; private Button unlockButton; private Button enterPinButton; private Button setPassphraseButton; private SplitMenuButton importButton; - private final SimpleStringProperty status = new SimpleStringProperty(""); private final SimpleStringProperty passphrase = new SimpleStringProperty(""); - public DevicePane(DeviceAccordion deviceAccordion, Wallet wallet, Device device) { - super(); - this.deviceAccordion = deviceAccordion; + public DevicePane(DeviceOperation deviceOperation, Wallet wallet, Device device) { + super(device.getModel().toDisplayString(), "", "", "image/" + device.getType() + ".png"); + this.deviceOperation = deviceOperation; this.wallet = wallet; this.device = device; - setPadding(Insets.EMPTY); - - setGraphic(getTitle()); - getStyleClass().add("titled-description-pane"); setDefaultStatus(); - - removeArrow(); - } - - private void removeArrow() { - Platform.runLater(() -> { - Node arrow = this.lookup(".arrow"); - if (arrow != null) { - arrow.setVisible(false); - arrow.setManaged(false); - } else { - removeArrow(); - } - }); - } - - private void setDefaultStatus() { - setStatus(device.getNeedsPinSent() ? "Locked" : device.getNeedsPassphraseSent() ? "Passphrase Required" : "Unlocked"); - } - - private Node getTitle() { - HBox listItem = new HBox(); - listItem.setPadding(new Insets(10, 20, 10, 10)); - listItem.setSpacing(10); - - HBox imageBox = new HBox(); - imageBox.setMinWidth(50); - imageBox.setMinHeight(50); - listItem.getChildren().add(imageBox); - - Image image = new Image("image/" + device.getType() + ".png", 50, 50, true, true); - if (!image.isError()) { - ImageView imageView = new ImageView(); - imageView.setImage(image); - imageBox.getChildren().add(imageView); - } - - VBox labelsBox = new VBox(); - labelsBox.setSpacing(5); - labelsBox.setAlignment(Pos.CENTER_LEFT); - this.mainLabel = new Label(); - mainLabel.setText(device.getModel().toDisplayString()); - mainLabel.getStyleClass().add("main-label"); - labelsBox.getChildren().add(mainLabel); - - HBox statusBox = new HBox(); - statusBox.setSpacing(7); - this.statusLabel = new Label(); - statusLabel.getStyleClass().add("status-label"); - statusLabel.textProperty().bind(status); - statusBox.getChildren().add(statusLabel); - - showHideLink = new Hyperlink("Show details..."); - showHideLink.managedProperty().bind(showHideLink.visibleProperty()); showHideLink.setVisible(false); - showHideLink.setOnAction(event -> { - if(this.isExpanded()) { - setExpanded(false); - } else { - setExpanded(true); - } - }); - this.expandedProperty().addListener((observable, oldValue, newValue) -> { - if(newValue) { - showHideLink.setText(showHideLink.getText().replace("Show", "Hide")); - } else { - showHideLink.setText(showHideLink.getText().replace("Hide", "Show")); - } - }); - statusBox.getChildren().add(showHideLink); - labelsBox.getChildren().add(statusBox); - - listItem.getChildren().add(labelsBox); - HBox.setHgrow(labelsBox, Priority.ALWAYS); - - HBox buttonBox = new HBox(); - buttonBox.setAlignment(Pos.CENTER_RIGHT); - - createUnlockButton(); createSetPassphraseButton(); createImportButton(); @@ -152,15 +62,17 @@ public class DevicePane extends TitledPane { showOperationButton(); } - buttonBox.getChildren().addAll(unlockButton, setPassphraseButton, importButton); - listItem.getChildren().add(buttonBox); + buttonBox.getChildren().addAll(setPassphraseButton, importButton); + } - this.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> { - //Hack to force listItem to expand to full available width less border - listItem.setPrefWidth(newValue.getWidth() - 2); - }); + @Override + protected Control createButton() { + createUnlockButton(); + return unlockButton; + } - return listItem; + private void setDefaultStatus() { + setDescription(device.getNeedsPinSent() ? "Locked" : device.getNeedsPassphraseSent() ? "Passphrase Required" : "Unlocked"); } private void createUnlockButton() { @@ -256,7 +168,7 @@ public class DevicePane extends TitledPane { } private Node getPassphraseEntry() { - passphraseField = (CustomTextField)TextFields.createClearableTextField(); + CustomTextField passphraseField = (CustomTextField)TextFields.createClearableTextField(); passphrase.bind(passphraseField.textProperty()); HBox.setHgrow(passphraseField, Priority.ALWAYS); @@ -284,12 +196,12 @@ public class DevicePane extends TitledPane { setContent(getPinEntry()); setExpanded(true); } else { - setErrorStatus("Could not request PIN"); + setError("Could not request PIN", null); unlockButton.setDisable(false); } }); promptPinService.setOnFailed(workerStateEvent -> { - setErrorStatus(promptPinService.getException().getMessage()); + setError(promptPinService.getException().getMessage(), null); unlockButton.setDisable(false); }); promptPinService.start(); @@ -314,7 +226,7 @@ public class DevicePane extends TitledPane { showOperationButton(); } } else { - setErrorStatus("Incorrect PIN"); + setError("Incorrect PIN", null); enterPinButton.setDisable(false); if(pinField != null) { pinField.setText(""); @@ -322,7 +234,7 @@ public class DevicePane extends TitledPane { } }); sendPinService.setOnFailed(workerStateEvent -> { - setErrorStatus(sendPinService.getException().getMessage()); + setError(sendPinService.getException().getMessage(), null); enterPinButton.setDisable(false); }); sendPinService.start(); @@ -344,13 +256,13 @@ public class DevicePane extends TitledPane { setDefaultStatus(); showOperationButton(); } else { - setErrorStatus("Passphrase send failed"); + setError("Passphrase send failed", null); setPassphraseButton.setDisable(false); setPassphraseButton.setVisible(true); } }); enumerateService.setOnFailed(workerStateEvent -> { - setErrorStatus(enumerateService.getException().getMessage()); + setError(enumerateService.getException().getMessage(), null); setPassphraseButton.setDisable(false); setPassphraseButton.setVisible(true); }); @@ -371,7 +283,7 @@ public class DevicePane extends TitledPane { importXpub(derivation); }); enumerateService.setOnFailed(workerStateEvent -> { - setErrorStatus(enumerateService.getException().getMessage()); + setError(enumerateService.getException().getMessage(), null); importButton.setDisable(false); }); enumerateService.start(); @@ -397,24 +309,14 @@ public class DevicePane extends TitledPane { EventManager.get().post(new KeystoreImportEvent(keystore)); }); getXpubService.setOnFailed(workerStateEvent -> { - setErrorStatus(getXpubService.getException().getMessage()); + setError(getXpubService.getException().getMessage(), null); importButton.setDisable(false); }); getXpubService.start(); } - private void setStatus(String statusMessage) { - statusLabel.getStyleClass().remove("status-error"); - status.setValue(statusMessage); - } - - private void setErrorStatus(String statusMessage) { - statusLabel.getStyleClass().add("status-error"); - status.setValue(statusMessage); - } - private void showOperationButton() { - if(deviceAccordion.getDeviceOperation().equals(DeviceAccordion.DeviceOperation.IMPORT)) { + if(deviceOperation.equals(DeviceOperation.IMPORT)) { importButton.setVisible(true); showHideLink.setText("Show derivation..."); showHideLink.setVisible(true); @@ -459,4 +361,8 @@ public class DevicePane extends TitledPane { return contentBox; } + + public enum DeviceOperation { + IMPORT; + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/KeystoreImportAccordion.java b/src/main/java/com/sparrowwallet/sparrow/control/KeystoreImportAccordion.java deleted file mode 100644 index 9e800f02..00000000 --- a/src/main/java/com/sparrowwallet/sparrow/control/KeystoreImportAccordion.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sparrowwallet.sparrow.control; - -import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.io.KeystoreFileImport; -import com.sparrowwallet.sparrow.io.KeystoreImport; -import com.sparrowwallet.sparrow.io.KeystoreMnemonicImport; -import javafx.collections.ObservableList; -import javafx.scene.control.Accordion; - -import java.util.List; - -public class KeystoreImportAccordion extends Accordion { - private List importers; - - public void setKeystoreImporters(Wallet wallet, ObservableList importers) { - this.importers = importers; - - for(KeystoreImport importer : importers) { - TitledDescriptionPane importPane = null; - - if(importer instanceof KeystoreFileImport) { - importPane = new FileKeystoreImportPane(wallet, (KeystoreFileImport)importer); - } else if(importer instanceof KeystoreMnemonicImport) { - importPane = new MnemonicKeystoreImportPane(wallet, (KeystoreMnemonicImport)importer); - } else { - throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass()); - } - - this.getPanes().add(importPane); - } - } -} diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java b/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java index 0a27f893..be40ab0c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java @@ -106,8 +106,10 @@ public class TitledDescriptionPane extends TitledPane { descriptionLabel.getStyleClass().remove("description-label"); descriptionLabel.getStyleClass().add("description-error"); descriptionLabel.setText(title); - setContent(getContentBox(detail)); - setExpanded(true); + if(detail != null && !detail.isEmpty()) { + setContent(getContentBox(detail)); + setExpanded(true); + } } protected Node getContentBox(String message) { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java index 20d6ec13..da9a1507 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -26,8 +26,7 @@ public class WalletImportDialog extends Dialog { stackPane.getChildren().add(anchorPane); ScrollPane scrollPane = new ScrollPane(); - scrollPane.setPrefWidth(500); - scrollPane.setPrefHeight(500); + scrollPane.setPrefHeight(280); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); anchorPane.getChildren().add(scrollPane); scrollPane.setFitToWidth(true); @@ -44,8 +43,8 @@ public class WalletImportDialog extends Dialog { final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); dialogPane.getButtonTypes().addAll(cancelButtonType); - dialogPane.setPrefWidth(650); - dialogPane.setPrefHeight(600); + dialogPane.setPrefWidth(500); + dialogPane.setPrefHeight(360); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); } diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java index b1f3cdb5..846ffa9f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardSinglesig.java @@ -46,7 +46,7 @@ public class ColdcardSinglesig implements KeystoreFileImport { Map map = gson.fromJson(new InputStreamReader(inputStream), stringStringMap); if (map.get("xfp") == null) { - throw new ImportException("This is not a valid Coldcard wallet export"); + throw new ImportException("File was not a valid Coldcard wallet export"); } String masterFingerprint = map.get("xfp").getAsString(); diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java b/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java index c17df8d0..99636003 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java @@ -43,7 +43,7 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport Wallet wallet = importWallet(inputStream, password); if(!wallet.getPolicyType().equals(PolicyType.SINGLE) || wallet.getKeystores().size() != 1) { - throw new ImportException("Multisig wallet detected - import it using File > Import > Electrum"); + throw new ImportException("Multisig wallet detected - import it using File > Import Wallet"); } if(!wallet.getScriptType().equals(scriptType)) { @@ -71,7 +71,7 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport ElectrumJsonWallet ew = new ElectrumJsonWallet(); if(map.get("wallet_type") == null) { - throw new ImportException("This is not a valid Electrum wallet"); + throw new ImportException("File was not a valid Electrum wallet"); } ew.wallet_type = map.get("wallet_type").getAsString(); diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java index cb518a74..b79a92f2 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java @@ -1,28 +1,29 @@ package com.sparrowwallet.sparrow.keystoreimport; import com.sparrowwallet.drongo.policy.PolicyType; -import com.sparrowwallet.sparrow.control.KeystoreImportAccordion; -import com.sparrowwallet.sparrow.io.ColdcardMultisig; -import com.sparrowwallet.sparrow.io.ColdcardSinglesig; -import com.sparrowwallet.sparrow.io.KeystoreImport; -import javafx.collections.FXCollections; +import com.sparrowwallet.sparrow.control.FileKeystoreImportPane; +import com.sparrowwallet.sparrow.io.*; import javafx.fxml.FXML; +import javafx.scene.control.Accordion; import java.util.Collections; import java.util.List; public class HwAirgappedController extends KeystoreImportDetailController { @FXML - private KeystoreImportAccordion importAccordion; + private Accordion importAccordion; public void initializeView() { - List importers = Collections.emptyList(); + List importers = Collections.emptyList(); if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) { importers = List.of(new ColdcardSinglesig()); } else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) { importers = List.of(new ColdcardMultisig()); } - importAccordion.setKeystoreImporters(getMasterController().getWallet(), FXCollections.observableList(importers)); + for(KeystoreImport importer : importers) { + FileKeystoreImportPane importPane = new FileKeystoreImportPane(getMasterController().getWallet(), (KeystoreFileImport)importer);; + importAccordion.getPanes().add(importPane); + } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java index 5945858a..598d8814 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwUsbDevicesController.java @@ -1,18 +1,21 @@ package com.sparrowwallet.sparrow.keystoreimport; -import com.sparrowwallet.sparrow.control.DeviceAccordion; +import com.sparrowwallet.sparrow.control.DevicePane; import com.sparrowwallet.sparrow.io.Device; import javafx.collections.FXCollections; import javafx.fxml.FXML; +import javafx.scene.control.Accordion; import java.util.List; public class HwUsbDevicesController extends KeystoreImportDetailController { @FXML - private DeviceAccordion deviceAccordion; + private Accordion deviceAccordion; public void initializeView(List devices) { - deviceAccordion.setDeviceOperation(DeviceAccordion.DeviceOperation.IMPORT); - deviceAccordion.setDevices(getMasterController().getWallet(), FXCollections.observableList(devices)); + for(Device device : devices) { + DevicePane devicePane = new DevicePane(DevicePane.DeviceOperation.IMPORT, getMasterController().getWallet(), device); + deviceAccordion.getPanes().add(devicePane); + } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java index 1443daa7..253aaa61 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/SwController.java @@ -1,20 +1,33 @@ package com.sparrowwallet.sparrow.keystoreimport; -import com.sparrowwallet.sparrow.control.KeystoreImportAccordion; -import com.sparrowwallet.sparrow.io.Bip39; -import com.sparrowwallet.sparrow.io.Electrum; -import com.sparrowwallet.sparrow.io.KeystoreImport; -import javafx.collections.FXCollections; +import com.sparrowwallet.sparrow.control.FileKeystoreImportPane; +import com.sparrowwallet.sparrow.control.MnemonicKeystoreImportPane; +import com.sparrowwallet.sparrow.control.TitledDescriptionPane; +import com.sparrowwallet.sparrow.io.*; import javafx.fxml.FXML; +import javafx.scene.control.Accordion; import java.util.List; public class SwController extends KeystoreImportDetailController { @FXML - private KeystoreImportAccordion importAccordion; + private Accordion importAccordion; public void initializeView() { List importers = List.of(new Bip39(), new Electrum()); - importAccordion.setKeystoreImporters(getMasterController().getWallet(), FXCollections.observableList(importers)); + + for(KeystoreImport importer : importers) { + TitledDescriptionPane importPane = null; + + if(importer instanceof KeystoreFileImport) { + importPane = new FileKeystoreImportPane(getMasterController().getWallet(), (KeystoreFileImport)importer); + } else if(importer instanceof KeystoreMnemonicImport) { + importPane = new MnemonicKeystoreImportPane(getMasterController().getWallet(), (KeystoreMnemonicImport)importer); + } else { + throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass()); + } + + importAccordion.getPanes().add(importPane); + } } } diff --git a/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_airgapped.fxml b/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_airgapped.fxml index e5c85782..606da858 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_airgapped.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_airgapped.fxml @@ -6,10 +6,8 @@ - - - + diff --git a/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_usb-devices.fxml b/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_usb-devices.fxml index 9de99e2e..61c6c4d7 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_usb-devices.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/hw_usb-devices.fxml @@ -5,10 +5,9 @@ - - + diff --git a/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/sw.fxml b/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/sw.fxml index 3f8f6952..adcd8e7e 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/sw.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/keystoreimport/sw.fxml @@ -5,10 +5,9 @@ - - +