From 6b6b23b51ae5d828b9c089f81dd84ca01f3a3595 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Fri, 29 Oct 2021 13:23:27 +0200 Subject: [PATCH] pay to the next fresh address of any open wallet via dropdown on send tab address field --- drongo | 2 +- .../sparrowwallet/sparrow/AppController.java | 2 +- .../sparrow/control/ComboBoxTextField.java | 47 +++++++++++++++++++ .../control/KeystorePassphraseDialog.java | 2 +- .../sparrow/control/TransactionDiagram.java | 4 +- .../sparrow/transaction/InputController.java | 2 +- .../sparrow/wallet/PaymentController.java | 36 +++++++++++++- .../sparrow/wallet/SettingsController.java | 2 +- .../wallet/TransactionsController.java | 2 +- .../com/sparrowwallet/sparrow/general.css | 19 ++++++++ .../sparrowwallet/sparrow/wallet/payment.fxml | 17 ++++--- 11 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/control/ComboBoxTextField.java diff --git a/drongo b/drongo index 360550a7..bdb9900d 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 360550a7183683ad4ee929a4c5411075bd751ffd +Subproject commit bdb9900d8d94f62b8714e14e151635813c7c258d diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index 38d86cfd..1fab5134 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -912,7 +912,7 @@ public class AppController implements Initializable { if(!wallet.isMasterWallet() && wallet.getMasterWallet().getKeystores().size() == copy.getKeystores().size() && wallet.getMasterWallet().getKeystores().get(i).hasSeed()) { copyKeystore.getSeed().setPassphrase(wallet.getMasterWallet().getKeystores().get(i).getSeed().getPassphrase()); } else { - KeystorePassphraseDialog passphraseDialog = new KeystorePassphraseDialog(wallet.getFullName(), copyKeystore); + KeystorePassphraseDialog passphraseDialog = new KeystorePassphraseDialog(wallet.getFullDisplayName(), copyKeystore); Optional optionalPassphrase = passphraseDialog.showAndWait(); if(optionalPassphrase.isPresent()) { copyKeystore.getSeed().setPassphrase(optionalPassphrase.get()); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/ComboBoxTextField.java b/src/main/java/com/sparrowwallet/sparrow/control/ComboBoxTextField.java new file mode 100644 index 00000000..f0ce04a4 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/control/ComboBoxTextField.java @@ -0,0 +1,47 @@ +package com.sparrowwallet.sparrow.control; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.Cursor; +import javafx.scene.Node; +import javafx.scene.control.ComboBox; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import org.controlsfx.control.textfield.CustomTextField; + +public class ComboBoxTextField extends CustomTextField { + private final ObjectProperty> comboProperty = new SimpleObjectProperty<>(); + + public ComboBoxTextField() { + super(); + getStyleClass().add("combo-text-field"); + setupCopyButtonField(super.rightProperty()); + } + + private void setupCopyButtonField(ObjectProperty rightProperty) { + Region showComboButton = new Region(); + showComboButton.getStyleClass().addAll("graphic"); //$NON-NLS-1$ + StackPane showComboButtonPane = new StackPane(showComboButton); + showComboButtonPane.getStyleClass().addAll("combo-button"); //$NON-NLS-1$ + showComboButtonPane.setCursor(Cursor.DEFAULT); + showComboButtonPane.setOnMouseReleased(e -> { + if(comboProperty.isNotNull().get()) { + comboProperty.get().show(); + } + }); + + rightProperty.set(showComboButtonPane); + } + + public ComboBox getComboProperty() { + return comboProperty.get(); + } + + public ObjectProperty> walletComboProperty() { + return comboProperty; + } + + public void setComboProperty(ComboBox comboProperty) { + this.comboProperty.set(comboProperty); + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java index 30e93c65..507086f3 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java @@ -28,7 +28,7 @@ public class KeystorePassphraseDialog extends Dialog { this.passphrase = (CustomPasswordField) TextFields.createClearablePasswordField(); final DialogPane dialogPane = getDialogPane(); - setTitle("Keystore Passphrase" + (walletName != null ? " - " + walletName : "")); + setTitle("Keystore Passphrase" + (walletName != null ? " for " + walletName : "")); dialogPane.setHeaderText((confirm ? "Re-enter" : "Enter") + " the BIP39 passphrase\n" + (confirm ? "to confirm:" : "for keystore: " + keystore.getLabel())); dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); AppServices.setStageIcon(dialogPane.getScene().getWindow()); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java index 967822c5..a42b01d6 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java @@ -222,7 +222,7 @@ public class TransactionDiagram extends GridPane { Tooltip tooltip = new Tooltip(); if(walletNode != null) { - tooltip.setText("Spending " + getSatsValue(input.getValue()) + " sats from " + (isFinal() ? walletTx.getWallet().getFullName() : "") + " " + walletNode + "\n" + input.getHashAsString() + ":" + input.getIndex() + "\n" + walletTx.getWallet().getAddress(walletNode)); + tooltip.setText("Spending " + getSatsValue(input.getValue()) + " sats from " + (isFinal() ? walletTx.getWallet().getFullDisplayName() : "") + " " + walletNode + "\n" + input.getHashAsString() + ":" + input.getIndex() + "\n" + walletTx.getWallet().getAddress(walletNode)); tooltip.getStyleClass().add("input-label"); if(input.getLabel() == null || input.getLabel().isEmpty()) { @@ -400,7 +400,7 @@ public class TransactionDiagram extends GridPane { WalletNode toNode = walletTx.getWallet() != null ? walletTx.getWallet().getWalletAddresses().get(payment.getAddress()) : null; Tooltip recipientTooltip = new Tooltip((toWallet == null ? (toNode != null ? "Consolidate " : "Pay ") : "Receive ") + getSatsValue(payment.getAmount()) + " sats to " - + (payment instanceof AdditionalPayment ? "\n" + payment : (toWallet == null ? (payment.getLabel() == null ? (toNode != null ? toNode : "external address") : payment.getLabel()) : toWallet.getFullName()) + "\n" + payment.getAddress().toString())); + + (payment instanceof AdditionalPayment ? "\n" + payment : (toWallet == null ? (payment.getLabel() == null ? (toNode != null ? toNode : "external address") : payment.getLabel()) : toWallet.getFullDisplayName()) + "\n" + payment.getAddress().toString())); recipientTooltip.getStyleClass().add("recipient-label"); recipientTooltip.setShowDelay(new Duration(TOOLTIP_SHOW_DELAY)); recipientLabel.setTooltip(recipientTooltip); diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java index b2d28b88..e71ade76 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/InputController.java @@ -146,7 +146,7 @@ public class InputController extends TransactionFormController implements Initia String baseText = getLegendText(txInput); if(signingWallet != null) { if(inputForm.isWalletTxo()) { - inputFieldset.setText(baseText + " - " + signingWallet.getFullName()); + inputFieldset.setText(baseText + " from " + signingWallet.getFullDisplayName()); inputFieldset.setIcon(TransactionDiagram.getTxoGlyph()); } else { inputFieldset.setText(baseText + " - Payjoin"); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java index 095af18f..24674364 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java @@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.wallet; import com.google.common.eventbus.Subscribe; import com.sparrowwallet.drongo.BitcoinUnit; +import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.address.InvalidAddressException; import com.sparrowwallet.drongo.address.P2PKHAddress; @@ -16,6 +17,7 @@ import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent; import com.sparrowwallet.sparrow.event.ExchangeRatesUpdatedEvent; import com.sparrowwallet.sparrow.event.FiatCurrencySelectedEvent; +import com.sparrowwallet.sparrow.event.OpenWalletsEvent; import com.sparrowwallet.sparrow.io.Config; import com.sparrowwallet.sparrow.net.ExchangeSource; import javafx.application.Platform; @@ -23,11 +25,13 @@ import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; +import javafx.util.StringConverter; import org.controlsfx.validation.ValidationResult; import org.controlsfx.validation.ValidationSupport; import org.controlsfx.validation.Validator; @@ -38,6 +42,7 @@ import java.net.URL; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.*; +import java.util.stream.Collectors; import static com.sparrowwallet.sparrow.AppServices.showErrorDialog; @@ -49,7 +54,10 @@ public class PaymentController extends WalletFormController implements Initializ private ValidationSupport validationSupport; @FXML - private CopyableTextField address; + private ComboBox openWallets; + + @FXML + private ComboBoxTextField address; @FXML private TextField label; @@ -121,6 +129,27 @@ public class PaymentController extends WalletFormController implements Initializ @Override public void initializeView() { + openWallets.setConverter(new StringConverter<>() { + @Override + public String toString(Wallet wallet) { + return wallet == null ? "" : wallet.getFullDisplayName() + (wallet == sendController.getWalletForm().getWallet() ? " (Consolidation)" : ""); + } + + @Override + public Wallet fromString(String string) { + return null; + } + }); + openWallets.setItems(FXCollections.observableList(AppServices.get().getOpenWallets().keySet().stream().filter(Wallet::isValid).collect(Collectors.toList()))); + openWallets.prefWidthProperty().bind(address.widthProperty()); + openWallets.valueProperty().addListener((observable, oldValue, newValue) -> { + if(newValue != null) { + WalletNode freshNode = newValue.getFreshNode(KeyPurpose.RECEIVE); + Address freshAddress = newValue.getAddress(freshNode); + address.setText(freshAddress.toString()); + } + }); + address.textProperty().addListener((observable, oldValue, newValue) -> { try { BitcoinURI bitcoinURI = new BitcoinURI(newValue); @@ -443,4 +472,9 @@ public class PaymentController extends WalletFormController implements Initializ public void exchangeRatesUpdated(ExchangeRatesUpdatedEvent event) { setFiatAmount(event.getCurrencyRate(), getRecipientValueSats()); } + + @Subscribe + public void openWallets(OpenWalletsEvent event) { + openWallets.setItems(FXCollections.observableList(event.getWallets().stream().filter(Wallet::isValid).collect(Collectors.toList()))); + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java index add4e8a2..94f3b442 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java @@ -439,7 +439,7 @@ public class SettingsController extends WalletFormController implements Initiali } if(wallet == null) { - throw new IllegalStateException("Cannot find child wallet " + walletForm.getWallet().getFullName() + " to export"); + throw new IllegalStateException("Cannot find child wallet " + walletForm.getWallet().getFullDisplayName() + " to export"); } WalletExportDialog dlg = new WalletExportDialog(wallet); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java index e1028f87..c89df25b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java @@ -102,7 +102,7 @@ public class TransactionsController extends WalletFormController implements Init }); transactionsMasterDetail.setShowDetailNode(Config.get().isShowLoadingLog()); - loadingLog.appendText("Wallet loading history for " + getWalletForm().getWallet().getFullName()); + loadingLog.appendText("Wallet loading history for " + getWalletForm().getWallet().getFullDisplayName()); loadingLog.setEditable(false); } diff --git a/src/main/resources/com/sparrowwallet/sparrow/general.css b/src/main/resources/com/sparrowwallet/sparrow/general.css index ec6f7125..99048543 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/general.css +++ b/src/main/resources/com/sparrowwallet/sparrow/general.css @@ -132,6 +132,25 @@ -fx-background-color: #116a8d; } +.combo-text-field .combo-button { + -fx-padding: 0 3 0 0; +} + +.combo-text-field .combo-button > .graphic { + -fx-background-color: #949494; + -fx-scale-shape: false; + -fx-padding: 4.5 6 4.5 4.5; + -fx-shape: "M11.8513+192L19.004+192C19.4989+192+19.7463+192.554+19.396+192.878L15.821+196.191C15.6042+196.392+15.2511+196.392+15.0343+196.191L11.4594+192.878C11.1091+192.554+11.3565+192+11.8513+192Z "; +} + +.combo-text-field .combo-button:hover > .graphic { + -fx-background-color: #0184bc; +} + +.combo-text-field .combo-button:pressed > .graphic { + -fx-background-color: #116a8d; +} + .readonly.text-input { -fx-text-fill: derive(-fx-text-inner-color, 40%); } diff --git a/src/main/resources/com/sparrowwallet/sparrow/wallet/payment.fxml b/src/main/resources/com/sparrowwallet/sparrow/wallet/payment.fxml index 6ca8a75f..919e210c 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/wallet/payment.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/wallet/payment.fxml @@ -9,13 +9,13 @@ - - + + @@ -31,11 +31,14 @@
- - - - - + + + + + + + +