diff --git a/src/main/java/com/sparrowwallet/sparrow/control/AddressCell.java b/src/main/java/com/sparrowwallet/sparrow/control/AddressCell.java index 7603d5e8..506fcf72 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/AddressCell.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/AddressCell.java @@ -61,7 +61,7 @@ public class AddressCell extends TreeTableCell { return utxoEntry.getNode().getDerivationPath() + (utxoEntry.isDuplicateAddress() ? " (Duplicate address)" : ""); } - private static Glyph getDuplicateGlyph() { + public static Glyph getDuplicateGlyph() { Glyph duplicateGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.EXCLAMATION_CIRCLE); duplicateGlyph.getStyleClass().add("duplicate-warning"); duplicateGlyph.setFontSize(12); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java index 663fd86c..b8aa8260 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java @@ -109,4 +109,9 @@ public class AddressTreeTable extends TreeTableView { sort(); } + + public void updateLabel(Entry entry) { + Entry rootEntry = getRoot().getValue(); + rootEntry.updateLabel(entry); + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TransactionsTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/TransactionsTreeTable.java index 890c28b0..ff2b7517 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TransactionsTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TransactionsTreeTable.java @@ -75,4 +75,9 @@ public class TransactionsTreeTable extends TreeTableView { rootEntry.updateTransactions(); sort(); } + + public void updateLabel(Entry entry) { + Entry rootEntry = getRoot().getValue(); + rootEntry.updateLabel(entry); + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java index 0bb18a6b..04c33245 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/UtxosTreeTable.java @@ -92,4 +92,9 @@ public class UtxosTreeTable extends TreeTableView { rootEntry.updateUtxos(); sort(); } + + public void updateLabel(Entry entry) { + Entry rootEntry = getRoot().getValue(); + rootEntry.updateLabel(entry); + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/AddressesController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/AddressesController.java index 52fe0631..1f0b560a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/AddressesController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/AddressesController.java @@ -5,6 +5,7 @@ import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.wallet.WalletNode; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.AddressTreeTable; +import com.sparrowwallet.sparrow.event.WalletEntryLabelChangedEvent; import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent; import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent; import javafx.fxml.FXML; @@ -54,4 +55,12 @@ public class AddressesController extends WalletFormController implements Initial } } } + + @Subscribe + public void walletEntryLabelChanged(WalletEntryLabelChangedEvent event) { + if(event.getWallet().equals(walletForm.getWallet())) { + receiveTable.updateLabel(event.getEntry()); + changeTable.updateLabel(event.getEntry()); + } + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/Entry.java b/src/main/java/com/sparrowwallet/sparrow/wallet/Entry.java index 1bbae905..28dfb7ec 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/Entry.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/Entry.java @@ -33,4 +33,14 @@ public abstract class Entry { } public abstract Long getValue(); + + public void updateLabel(Entry entry) { + if(this.equals(entry)) { + labelProperty.set(entry.getLabel()); + } + + for(Entry child : getChildren()) { + child.updateLabel(entry); + } + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java b/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java index 7e71ec06..230c3e38 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/HashIndexEntry.java @@ -74,7 +74,7 @@ public class HashIndexEntry extends Entry implements Comparable @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (!(o instanceof HashIndexEntry)) return false; HashIndexEntry that = (HashIndexEntry) o; return wallet.equals(that.wallet) && hashIndex.equals(that.hashIndex) && diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java index 293dabc7..18f2b4e9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java @@ -7,13 +7,19 @@ import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.sparrowwallet.drongo.KeyPurpose; +import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex; +import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.EventManager; +import com.sparrowwallet.sparrow.control.AddressCell; import com.sparrowwallet.sparrow.control.CopyableLabel; import com.sparrowwallet.sparrow.control.CopyableTextField; import com.sparrowwallet.sparrow.event.ReceiveToEvent; +import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent; +import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -22,9 +28,14 @@ import org.fxmisc.richtext.CodeArea; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.net.URL; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ResourceBundle; +import java.util.Set; public class ReceiveController extends WalletFormController implements Initializable { + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + @FXML private CopyableTextField address; @@ -35,7 +46,7 @@ public class ReceiveController extends WalletFormController implements Initializ private CopyableLabel derivationPath; @FXML - private CopyableLabel lastUsed; + private Label lastUsed; @FXML private ImageView qrCode; @@ -64,15 +75,11 @@ public class ReceiveController extends WalletFormController implements Initializ } this.currentEntry = nodeEntry; - address.setText(nodeEntry.getAddress().toString()); - label.textProperty().bindBidirectional(nodeEntry.labelProperty()); - derivationPath.setText(nodeEntry.getNode().getDerivationPath()); - //TODO: Find last used block height if available (red flag?) - lastUsed.setText("Unknown"); + updateLastUsed(); Image qrImage = getQrCode(nodeEntry.getAddress().toString()); if(qrImage != null) { @@ -86,6 +93,22 @@ public class ReceiveController extends WalletFormController implements Initializ outputDescriptor.appendText(nodeEntry.getOutputDescriptor()); } + private void updateLastUsed() { + Set currentOutputs = currentEntry.getNode().getTransactionOutputs(); + if(AppController.isOnline() && currentOutputs.isEmpty()) { + lastUsed.setText("Never"); + lastUsed.setGraphic(null); + } else if(!currentOutputs.isEmpty()) { + long count = currentOutputs.size(); + BlockTransactionHashIndex lastUsedReference = currentOutputs.stream().skip(count - 1).findFirst().get(); + lastUsed.setText(DATE_FORMAT.format(lastUsedReference.getDate())); + lastUsed.setGraphic(AddressCell.getDuplicateGlyph()); + } else { + lastUsed.setText("Unknown"); + lastUsed.setGraphic(null); + } + } + private Image getQrCode(String address) { try { QRCodeWriter qrCodeWriter = new QRCodeWriter(); @@ -108,10 +131,42 @@ public class ReceiveController extends WalletFormController implements Initializ setNodeEntry(freshEntry); } + public void clear() { + if(currentEntry != null) { + label.textProperty().unbindBidirectional(currentEntry.labelProperty()); + } + + address.setText(""); + label.setText(""); + derivationPath.setText(""); + lastUsed.setText(""); + lastUsed.setGraphic(null); + qrCode.setImage(null); + scriptPubKeyArea.clear(); + outputDescriptor.clear(); + this.currentEntry = null; + } + @Subscribe public void receiveTo(ReceiveToEvent event) { if(event.getReceiveEntry().getWallet().equals(getWalletForm().getWallet())) { setNodeEntry(event.getReceiveEntry()); } } + + @Subscribe + public void walletNodesChanged(WalletNodesChangedEvent event) { + if(event.getWallet().equals(walletForm.getWallet())) { + clear(); + } + } + + @Subscribe + public void walletHistoryChanged(WalletHistoryChangedEvent event) { + if(event.getWallet().equals(walletForm.getWallet())) { + if(event.getHistoryChangedNodes().contains(currentEntry.getNode())) { + updateLastUsed(); + } + } + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java index 47f58ffd..d7623a22 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java @@ -4,6 +4,7 @@ import com.google.common.eventbus.Subscribe; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.TransactionsTreeTable; import com.sparrowwallet.sparrow.event.WalletBlockHeightChangedEvent; +import com.sparrowwallet.sparrow.event.WalletEntryLabelChangedEvent; import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent; import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent; import javafx.fxml.FXML; @@ -42,6 +43,13 @@ public class TransactionsController extends WalletFormController implements Init } } + @Subscribe + public void walletEntryLabelChanged(WalletEntryLabelChangedEvent event) { + if(event.getWallet().equals(walletForm.getWallet())) { + transactionsTable.updateLabel(event.getEntry()); + } + } + //TODO: Remove public void advanceBlock(MouseEvent event) { Integer currentBlock = getWalletForm().getWallet().getStoredBlockHeight(); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java index 5c5ab181..6cefb47e 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/UtxosController.java @@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.wallet; import com.google.common.eventbus.Subscribe; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.UtxosTreeTable; +import com.sparrowwallet.sparrow.event.WalletEntryLabelChangedEvent; import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent; import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent; import javafx.collections.ListChangeListener; @@ -97,6 +98,13 @@ public class UtxosController extends WalletFormController implements Initializab } } + @Subscribe + public void walletEntryLabelChanged(WalletEntryLabelChangedEvent event) { + if(event.getWallet().equals(walletForm.getWallet())) { + utxosTable.updateLabel(event.getEntry()); + } + } + private static class UtxoData { public final Entry entry; public final String name; diff --git a/src/main/resources/com/sparrowwallet/sparrow/wallet/receive.fxml b/src/main/resources/com/sparrowwallet/sparrow/wallet/receive.fxml index 1d747b6f..41a29e80 100644 --- a/src/main/resources/com/sparrowwallet/sparrow/wallet/receive.fxml +++ b/src/main/resources/com/sparrowwallet/sparrow/wallet/receive.fxml @@ -43,7 +43,7 @@ - +