mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
add wallet search dialog for labels, address, values and txids
This commit is contained in:
parent
3820b9838d
commit
6d2167428f
22 changed files with 410 additions and 35 deletions
|
@ -34,6 +34,7 @@ import com.sparrowwallet.sparrow.soroban.SorobanServices;
|
||||||
import com.sparrowwallet.sparrow.transaction.TransactionController;
|
import com.sparrowwallet.sparrow.transaction.TransactionController;
|
||||||
import com.sparrowwallet.sparrow.transaction.TransactionData;
|
import com.sparrowwallet.sparrow.transaction.TransactionData;
|
||||||
import com.sparrowwallet.sparrow.transaction.TransactionView;
|
import com.sparrowwallet.sparrow.transaction.TransactionView;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
import com.sparrowwallet.sparrow.wallet.WalletController;
|
import com.sparrowwallet.sparrow.wallet.WalletController;
|
||||||
import com.sparrowwallet.sparrow.wallet.WalletForm;
|
import com.sparrowwallet.sparrow.wallet.WalletForm;
|
||||||
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
|
import com.sparrowwallet.sparrow.whirlpool.Whirlpool;
|
||||||
|
@ -155,6 +156,9 @@ public class AppController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private MenuItem lockWallet;
|
private MenuItem lockWallet;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private MenuItem searchWallet;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private MenuItem refreshWallet;
|
private MenuItem refreshWallet;
|
||||||
|
|
||||||
|
@ -334,6 +338,7 @@ public class AppController implements Initializable {
|
||||||
showPSBT.visibleProperty().bind(saveTransaction.visibleProperty().not());
|
showPSBT.visibleProperty().bind(saveTransaction.visibleProperty().not());
|
||||||
exportWallet.setDisable(true);
|
exportWallet.setDisable(true);
|
||||||
lockWallet.setDisable(true);
|
lockWallet.setDisable(true);
|
||||||
|
searchWallet.disableProperty().bind(exportWallet.disableProperty());
|
||||||
refreshWallet.disableProperty().bind(Bindings.or(exportWallet.disableProperty(), Bindings.or(serverToggle.disableProperty(), AppServices.onlineProperty().not())));
|
refreshWallet.disableProperty().bind(Bindings.or(exportWallet.disableProperty(), Bindings.or(serverToggle.disableProperty(), AppServices.onlineProperty().not())));
|
||||||
sendToMany.disableProperty().bind(exportWallet.disableProperty());
|
sendToMany.disableProperty().bind(exportWallet.disableProperty());
|
||||||
sweepPrivateKey.disableProperty().bind(Bindings.or(serverToggle.disableProperty(), AppServices.onlineProperty().not()));
|
sweepPrivateKey.disableProperty().bind(Bindings.or(serverToggle.disableProperty(), AppServices.onlineProperty().not()));
|
||||||
|
@ -1353,6 +1358,19 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void searchWallet(ActionEvent event) {
|
||||||
|
WalletForm selectedWalletForm = getSelectedWalletForm();
|
||||||
|
if(selectedWalletForm != null) {
|
||||||
|
SearchWalletDialog searchWalletDialog = new SearchWalletDialog(selectedWalletForm);
|
||||||
|
Optional<Entry> optEntry = searchWalletDialog.showAndWait();
|
||||||
|
if(optEntry.isPresent()) {
|
||||||
|
Entry entry = optEntry.get();
|
||||||
|
EventManager.get().post(new FunctionActionEvent(entry.getWalletFunction(), entry.getWallet()));
|
||||||
|
Platform.runLater(() -> EventManager.get().post(new SelectEntryEvent(entry)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void refreshWallet(ActionEvent event) {
|
public void refreshWallet(ActionEvent event) {
|
||||||
WalletForm selectedWalletForm = getSelectedWalletForm();
|
WalletForm selectedWalletForm = getSelectedWalletForm();
|
||||||
if(selectedWalletForm != null) {
|
if(selectedWalletForm != null) {
|
||||||
|
@ -2430,12 +2448,7 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void sendAction(SendActionEvent event) {
|
public void functionAction(FunctionActionEvent event) {
|
||||||
selectTab(event.getWallet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void recieveAction(ReceiveActionEvent event) {
|
|
||||||
selectTab(event.getWallet());
|
selectTab(event.getWallet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ public class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
}
|
}
|
||||||
|
|
||||||
HBox actionBox = new HBox();
|
HBox actionBox = new HBox();
|
||||||
|
actionBox.getStyleClass().add("cell-actions");
|
||||||
Button viewTransactionButton = new Button("");
|
Button viewTransactionButton = new Button("");
|
||||||
viewTransactionButton.setGraphic(getViewTransactionGlyph());
|
viewTransactionButton.setGraphic(getViewTransactionGlyph());
|
||||||
viewTransactionButton.setOnAction(event -> {
|
viewTransactionButton.setOnAction(event -> {
|
||||||
|
@ -118,6 +119,7 @@ public class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
getStyleClass().add("address-cell");
|
getStyleClass().add("address-cell");
|
||||||
|
|
||||||
HBox actionBox = new HBox();
|
HBox actionBox = new HBox();
|
||||||
|
actionBox.getStyleClass().add("cell-actions");
|
||||||
Button receiveButton = new Button("");
|
Button receiveButton = new Button("");
|
||||||
receiveButton.setGraphic(getReceiveGlyph());
|
receiveButton.setGraphic(getReceiveGlyph());
|
||||||
receiveButton.setOnAction(event -> {
|
receiveButton.setOnAction(event -> {
|
||||||
|
@ -152,6 +154,7 @@ public class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
setTooltip(tooltip);
|
setTooltip(tooltip);
|
||||||
|
|
||||||
HBox actionBox = new HBox();
|
HBox actionBox = new HBox();
|
||||||
|
actionBox.getStyleClass().add("cell-actions");
|
||||||
Button viewTransactionButton = new Button("");
|
Button viewTransactionButton = new Button("");
|
||||||
viewTransactionButton.setGraphic(getViewTransactionGlyph());
|
viewTransactionButton.setGraphic(getViewTransactionGlyph());
|
||||||
viewTransactionButton.setOnAction(event -> {
|
viewTransactionButton.setOnAction(event -> {
|
||||||
|
|
|
@ -70,9 +70,6 @@ public class PrivateKeySweepDialog extends Dialog<Transaction> {
|
||||||
dialogPane.setGraphic(imageView);
|
dialogPane.setGraphic(imageView);
|
||||||
}
|
}
|
||||||
|
|
||||||
VBox vBox = new VBox();
|
|
||||||
vBox.setSpacing(20);
|
|
||||||
|
|
||||||
Form form = new Form();
|
Form form = new Form();
|
||||||
Fieldset fieldset = new Fieldset();
|
Fieldset fieldset = new Fieldset();
|
||||||
fieldset.setText("");
|
fieldset.setText("");
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.*;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import org.controlsfx.control.textfield.TextFields;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import tornadofx.control.Field;
|
||||||
|
import tornadofx.control.Fieldset;
|
||||||
|
import tornadofx.control.Form;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SearchWalletDialog extends Dialog<Entry> {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SearchWalletDialog.class);
|
||||||
|
|
||||||
|
private final WalletForm walletForm;
|
||||||
|
private final TextField search;
|
||||||
|
private final CoinTreeTable results;
|
||||||
|
|
||||||
|
public SearchWalletDialog(WalletForm walletForm) {
|
||||||
|
this.walletForm = walletForm;
|
||||||
|
|
||||||
|
final DialogPane dialogPane = getDialogPane();
|
||||||
|
dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
|
||||||
|
dialogPane.getStylesheets().add(AppServices.class.getResource("dialog.css").toExternalForm());
|
||||||
|
dialogPane.getStylesheets().add(AppServices.class.getResource("wallet/wallet.css").toExternalForm());
|
||||||
|
dialogPane.getStylesheets().add(AppServices.class.getResource("search.css").toExternalForm());
|
||||||
|
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
||||||
|
dialogPane.setHeaderText("Search Wallet");
|
||||||
|
|
||||||
|
Image image = new Image("image/sparrow-small.png", 50, 50, false, false);
|
||||||
|
if(!image.isError()) {
|
||||||
|
ImageView imageView = new ImageView();
|
||||||
|
imageView.setSmooth(false);
|
||||||
|
imageView.setImage(image);
|
||||||
|
dialogPane.setGraphic(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
VBox vBox = new VBox();
|
||||||
|
vBox.setSpacing(20);
|
||||||
|
|
||||||
|
Form form = new Form();
|
||||||
|
Fieldset fieldset = new Fieldset();
|
||||||
|
fieldset.setText("");
|
||||||
|
fieldset.setSpacing(10);
|
||||||
|
|
||||||
|
Field searchField = new Field();
|
||||||
|
searchField.setText("Search:");
|
||||||
|
search = TextFields.createClearableTextField();
|
||||||
|
search.setPromptText("Label, address, value or transaction ID");
|
||||||
|
searchField.getInputs().add(search);
|
||||||
|
|
||||||
|
fieldset.getChildren().addAll(searchField);
|
||||||
|
form.getChildren().add(fieldset);
|
||||||
|
|
||||||
|
results = new CoinTreeTable();
|
||||||
|
results.setShowRoot(false);
|
||||||
|
results.setPrefWidth(850);
|
||||||
|
results.setBitcoinUnit(walletForm.getWallet());
|
||||||
|
results.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
|
||||||
|
results.setPlaceholder(new Label("No results"));
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, String> typeColumn = new TreeTableColumn<>("Type");
|
||||||
|
typeColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getEntryType());
|
||||||
|
});
|
||||||
|
results.getColumns().add(typeColumn);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, Entry> entryCol = new TreeTableColumn<>("Date / Address / Output");
|
||||||
|
entryCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Entry> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
|
||||||
|
});
|
||||||
|
entryCol.setCellFactory(p -> new SearchEntryCell());
|
||||||
|
String address = walletForm.getNodeEntry(KeyPurpose.RECEIVE).getAddress().toString();
|
||||||
|
if(address != null) {
|
||||||
|
entryCol.setMinWidth(TextUtils.computeTextWidth(AppServices.getMonospaceFont(), address, 0.0));
|
||||||
|
}
|
||||||
|
results.getColumns().add(entryCol);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, String> labelCol = new TreeTableColumn<>("Label");
|
||||||
|
labelCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
|
||||||
|
return param.getValue().getValue().labelProperty();
|
||||||
|
});
|
||||||
|
labelCol.setCellFactory(p -> new SearchLabelCell());
|
||||||
|
results.getColumns().add(labelCol);
|
||||||
|
|
||||||
|
TreeTableColumn<Entry, Number> amountCol = new TreeTableColumn<>("Value");
|
||||||
|
amountCol.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, Number> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getValue());
|
||||||
|
});
|
||||||
|
amountCol.setCellFactory(p -> new CoinCell());
|
||||||
|
results.getColumns().add(amountCol);
|
||||||
|
|
||||||
|
vBox.getChildren().addAll(form, results);
|
||||||
|
dialogPane.setContent(vBox);
|
||||||
|
|
||||||
|
ButtonType showButtonType = new javafx.scene.control.ButtonType("Show", ButtonBar.ButtonData.APPLY);
|
||||||
|
ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||||
|
|
||||||
|
dialogPane.getButtonTypes().addAll(cancelButtonType, showButtonType);
|
||||||
|
|
||||||
|
Button showButton = (Button) dialogPane.lookupButton(showButtonType);
|
||||||
|
showButton.setDefaultButton(true);
|
||||||
|
showButton.setDisable(true);
|
||||||
|
|
||||||
|
setResultConverter(buttonType -> buttonType == showButtonType ? results.getSelectionModel().getSelectedItem().getValue() : null);
|
||||||
|
|
||||||
|
results.getSelectionModel().getSelectedIndices().addListener((ListChangeListener<Integer>) c -> {
|
||||||
|
showButton.setDisable(results.getSelectionModel().getSelectedCells().isEmpty());
|
||||||
|
});
|
||||||
|
|
||||||
|
search.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
searchWallet(newValue.toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
setResizable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void searchWallet(String searchText) {
|
||||||
|
List<Entry> matchingEntries = new ArrayList<>();
|
||||||
|
|
||||||
|
if(!searchText.isEmpty()) {
|
||||||
|
Long searchValue = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
searchValue = Math.abs(Long.parseLong(searchText));
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletTransactionsEntry walletTransactionsEntry = walletForm.getWalletTransactionsEntry();
|
||||||
|
for(Entry entry : walletTransactionsEntry.getChildren()) {
|
||||||
|
if(entry instanceof TransactionEntry transactionEntry) {
|
||||||
|
if(transactionEntry.getBlockTransaction().getHash().toString().equals(searchText) ||
|
||||||
|
(transactionEntry.getLabel() != null && transactionEntry.getLabel().toLowerCase().contains(searchText)) ||
|
||||||
|
(transactionEntry.getValue() != null && searchValue != null && Math.abs(transactionEntry.getValue()) == searchValue)) {
|
||||||
|
matchingEntries.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(KeyPurpose keyPurpose : KeyPurpose.DEFAULT_PURPOSES) {
|
||||||
|
NodeEntry purposeEntry = walletForm.getNodeEntry(keyPurpose);
|
||||||
|
for(Entry entry : purposeEntry.getChildren()) {
|
||||||
|
if(entry instanceof NodeEntry nodeEntry) {
|
||||||
|
if(nodeEntry.getAddress().toString().contains(searchText) ||
|
||||||
|
(nodeEntry.getLabel() != null && nodeEntry.getLabel().toLowerCase().contains(searchText)) ||
|
||||||
|
(nodeEntry.getValue() != null && searchValue != null && Math.abs(nodeEntry.getValue()) == searchValue)) {
|
||||||
|
matchingEntries.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletUtxosEntry walletUtxosEntry = walletForm.getWalletUtxosEntry();
|
||||||
|
for(Entry entry : walletUtxosEntry.getChildren()) {
|
||||||
|
if(entry instanceof HashIndexEntry hashIndexEntry) {
|
||||||
|
if(hashIndexEntry.getBlockTransaction().getHash().toString().equals(searchText) ||
|
||||||
|
(hashIndexEntry.getLabel() != null && hashIndexEntry.getLabel().toLowerCase().contains(searchText)) ||
|
||||||
|
(hashIndexEntry.getValue() != null && searchValue != null && Math.abs(hashIndexEntry.getValue()) == searchValue)) {
|
||||||
|
matchingEntries.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchWalletEntry rootEntry = new SearchWalletEntry(walletForm.getWallet(), matchingEntries);
|
||||||
|
RecursiveTreeItem<Entry> rootItem = new RecursiveTreeItem<>(rootEntry, Entry::getChildren);
|
||||||
|
results.setRoot(rootItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SearchWalletEntry extends Entry {
|
||||||
|
public SearchWalletEntry(Wallet wallet, List<Entry> entries) {
|
||||||
|
super(wallet, wallet.getName(), entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getValue() {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "Search Wallet Results";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SearchEntryCell extends EntryCell {
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Entry entry, boolean empty) {
|
||||||
|
super.updateItem(entry, empty);
|
||||||
|
setContextMenu(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SearchLabelCell extends LabelCell {
|
||||||
|
@Override
|
||||||
|
public void updateItem(String label, boolean empty) {
|
||||||
|
super.updateItem(label, empty);
|
||||||
|
setContextMenu(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Function;
|
||||||
|
|
||||||
|
public class FunctionActionEvent {
|
||||||
|
private final Function function;
|
||||||
|
private final Wallet wallet;
|
||||||
|
|
||||||
|
public FunctionActionEvent(Function function, Wallet wallet) {
|
||||||
|
this.function = function;
|
||||||
|
this.wallet = wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function getFunction() {
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet getWallet() {
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean selectFunction() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,15 @@
|
||||||
package com.sparrowwallet.sparrow.event;
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Function;
|
||||||
import com.sparrowwallet.sparrow.wallet.NodeEntry;
|
import com.sparrowwallet.sparrow.wallet.NodeEntry;
|
||||||
|
|
||||||
public class ReceiveActionEvent {
|
public class ReceiveActionEvent extends FunctionActionEvent {
|
||||||
private final Wallet wallet;
|
|
||||||
|
|
||||||
public ReceiveActionEvent(NodeEntry receiveEntry) {
|
public ReceiveActionEvent(NodeEntry receiveEntry) {
|
||||||
this.wallet = receiveEntry.getWallet();
|
super(Function.RECEIVE, receiveEntry.getWallet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReceiveActionEvent(Wallet wallet) {
|
public ReceiveActionEvent(Wallet wallet) {
|
||||||
this.wallet = wallet;
|
super(Function.RECEIVE, wallet);
|
||||||
}
|
|
||||||
|
|
||||||
public Wallet getWallet() {
|
|
||||||
return wallet;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Entry;
|
||||||
|
|
||||||
|
public class SelectEntryEvent {
|
||||||
|
private final Entry entry;
|
||||||
|
|
||||||
|
public SelectEntryEvent(Entry entry) {
|
||||||
|
this.entry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry getEntry() {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet getWallet() {
|
||||||
|
return entry.getWallet();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,23 +2,24 @@ package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.wallet.Function;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SendActionEvent {
|
public class SendActionEvent extends FunctionActionEvent {
|
||||||
private final Wallet wallet;
|
|
||||||
private final List<BlockTransactionHashIndex> utxos;
|
private final List<BlockTransactionHashIndex> utxos;
|
||||||
|
|
||||||
public SendActionEvent(Wallet wallet, List<BlockTransactionHashIndex> utxos) {
|
public SendActionEvent(Wallet wallet, List<BlockTransactionHashIndex> utxos) {
|
||||||
this.wallet = wallet;
|
super(Function.SEND, wallet);
|
||||||
this.utxos = utxos;
|
this.utxos = utxos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Wallet getWallet() {
|
|
||||||
return wallet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BlockTransactionHashIndex> getUtxos() {
|
public List<BlockTransactionHashIndex> getUtxos() {
|
||||||
return utxos;
|
return utxos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean selectFunction() {
|
||||||
|
return !getUtxos().isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,16 @@ public class AddressesController extends WalletFormController implements Initial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void selectEntry(SelectEntryEvent event) {
|
||||||
|
if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.ADDRESSES) {
|
||||||
|
List<AddressTreeTable> addressTreeTables = List.of(receiveTable, changeTable);
|
||||||
|
for(AddressTreeTable addressTreeTable : addressTreeTables) {
|
||||||
|
selectEntry(addressTreeTable, event.getEntry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void exportReceiveAddresses(ActionEvent event) {
|
public void exportReceiveAddresses(ActionEvent event) {
|
||||||
exportAddresses(KeyPurpose.RECEIVE);
|
exportAddresses(KeyPurpose.RECEIVE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,10 @@ public abstract class Entry {
|
||||||
|
|
||||||
public abstract Long getValue();
|
public abstract Long getValue();
|
||||||
|
|
||||||
|
public abstract String getEntryType();
|
||||||
|
|
||||||
|
public abstract Function getWalletFunction();
|
||||||
|
|
||||||
public void updateLabel(Entry entry) {
|
public void updateLabel(Entry entry) {
|
||||||
if(this.equals(entry)) {
|
if(this.equals(entry)) {
|
||||||
labelProperty.set(entry.getLabel());
|
labelProperty.set(entry.getLabel());
|
||||||
|
|
|
@ -69,6 +69,16 @@ public class HashIndexEntry extends Entry implements Comparable<HashIndexEntry>
|
||||||
return hashIndex.getValue();
|
return hashIndex.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "Hash Index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return Function.ADDRESSES;
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
INPUT, OUTPUT
|
INPUT, OUTPUT
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,16 @@ public class NodeEntry extends Entry implements Comparable<NodeEntry> {
|
||||||
return node.getUnspentValue();
|
return node.getUnspentValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "Address";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return Function.ADDRESSES;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|
|
@ -74,6 +74,16 @@ public class TransactionEntry extends Entry implements Comparable<TransactionEnt
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "Transaction";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return Function.TRANSACTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isConfirming() {
|
public boolean isConfirming() {
|
||||||
return getConfirmations() < BlockTransactionHash.BLOCKS_TO_CONFIRM;
|
return getConfirmations() < BlockTransactionHash.BLOCKS_TO_CONFIRM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,4 +277,11 @@ public class TransactionsController extends WalletFormController implements Init
|
||||||
public void loadingLogChanged(LoadingLogChangedEvent event) {
|
public void loadingLogChanged(LoadingLogChangedEvent event) {
|
||||||
transactionsMasterDetail.setShowDetailNode(event.isVisible());
|
transactionsMasterDetail.setShowDetailNode(event.isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void selectEntry(SelectEntryEvent event) {
|
||||||
|
if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.TRANSACTIONS) {
|
||||||
|
selectEntry(transactionsTable, event.getEntry());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,16 @@ public class UtxoEntry extends HashIndexEntry {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "UTXO";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return Function.UTXOS;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMixing() {
|
public boolean isMixing() {
|
||||||
return mixStatusProperty != null && ((mixStatusProperty.get().getMixProgress() != null && mixStatusProperty.get().getMixProgress().getMixStep() != MixStep.FAIL) || mixStatusProperty.get().getNextMixUtxo() != null);
|
return mixStatusProperty != null && ((mixStatusProperty.get().getMixProgress() != null && mixStatusProperty.get().getMixProgress().getMixStep() != MixStep.FAIL) || mixStatusProperty.get().getNextMixUtxo() != null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -604,4 +604,12 @@ public class UtxosController extends WalletFormController implements Initializab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void selectEntry(SelectEntryEvent event) {
|
||||||
|
if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.UTXOS) {
|
||||||
|
utxosTable.getSelectionModel().clearSelection();
|
||||||
|
selectEntry(utxosTable, event.getEntry());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,16 +221,9 @@ public class WalletController extends WalletFormController implements Initializa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void receiveAction(ReceiveActionEvent event) {
|
public void functionAction(FunctionActionEvent event) {
|
||||||
if(event.getWallet().equals(walletForm.getWallet())) {
|
if(event.selectFunction() && event.getWallet().equals(walletForm.getWallet())) {
|
||||||
selectFunction(Function.RECEIVE);
|
selectFunction(event.getFunction());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void sendAction(SendActionEvent event) {
|
|
||||||
if(!event.getUtxos().isEmpty() && event.getWallet().equals(walletForm.getWallet())) {
|
|
||||||
selectFunction(Function.SEND);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.WalletTabData;
|
import com.sparrowwallet.sparrow.WalletTabData;
|
||||||
import com.sparrowwallet.sparrow.control.FiatLabel;
|
import com.sparrowwallet.sparrow.control.FiatLabel;
|
||||||
import com.sparrowwallet.sparrow.event.WalletTabsClosedEvent;
|
import com.sparrowwallet.sparrow.event.WalletTabsClosedEvent;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.TreeItem;
|
||||||
|
import javafx.scene.control.TreeTableView;
|
||||||
|
|
||||||
public abstract class WalletFormController extends BaseController {
|
public abstract class WalletFormController extends BaseController {
|
||||||
public WalletForm walletForm;
|
public WalletForm walletForm;
|
||||||
|
@ -64,4 +67,17 @@ public abstract class WalletFormController extends BaseController {
|
||||||
fiatLabel.setBtcRate(0.0);
|
fiatLabel.setBtcRate(0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void selectEntry(TreeTableView<Entry> treeTableView, Entry entry) {
|
||||||
|
for(TreeItem<Entry> treeEntry : treeTableView.getRoot().getChildren()) {
|
||||||
|
if(treeEntry.getValue().equals(entry)) {
|
||||||
|
treeTableView.getSelectionModel().select(treeEntry);
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
treeTableView.requestFocus();
|
||||||
|
treeTableView.scrollTo(treeTableView.getSelectionModel().getSelectedIndex());
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,16 @@ public class WalletTransactionsEntry extends Entry {
|
||||||
return getBalance();
|
return getBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "Wallet Transactions";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return Function.TRANSACTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
private void calculateBalances(boolean resort) {
|
private void calculateBalances(boolean resort) {
|
||||||
long balance = 0L;
|
long balance = 0L;
|
||||||
long mempoolBalance = 0L;
|
long mempoolBalance = 0L;
|
||||||
|
|
|
@ -20,6 +20,16 @@ public class WalletUtxosEntry extends Entry {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEntryType() {
|
||||||
|
return "Wallet UTXOs";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function getWalletFunction() {
|
||||||
|
return Function.UTXOS;
|
||||||
|
}
|
||||||
|
|
||||||
protected void calculateDuplicates() {
|
protected void calculateDuplicates() {
|
||||||
Map<String, UtxoEntry> addressMap = new HashMap<>();
|
Map<String, UtxoEntry> addressMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@
|
||||||
<MenuItem fx:id="lockWallet" mnemonicParsing="false" text="Lock Wallet" accelerator="Shortcut+L" onAction="#lockWallet"/>
|
<MenuItem fx:id="lockWallet" mnemonicParsing="false" text="Lock Wallet" accelerator="Shortcut+L" onAction="#lockWallet"/>
|
||||||
<MenuItem mnemonicParsing="false" text="Lock All Wallets" accelerator="Shortcut+Shift+L" onAction="#lockWallets"/>
|
<MenuItem mnemonicParsing="false" text="Lock All Wallets" accelerator="Shortcut+Shift+L" onAction="#lockWallets"/>
|
||||||
<SeparatorMenuItem />
|
<SeparatorMenuItem />
|
||||||
|
<MenuItem fx:id="searchWallet" mnemonicParsing="false" text="Search Wallet" accelerator="Shortcut+Shift+S" onAction="#searchWallet"/>
|
||||||
<MenuItem fx:id="refreshWallet" mnemonicParsing="false" text="Refresh Wallet" accelerator="Shortcut+R" onAction="#refreshWallet"/>
|
<MenuItem fx:id="refreshWallet" mnemonicParsing="false" text="Refresh Wallet" accelerator="Shortcut+R" onAction="#refreshWallet"/>
|
||||||
</items>
|
</items>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
3
src/main/resources/com/sparrowwallet/sparrow/search.css
Normal file
3
src/main/resources/com/sparrowwallet/sparrow/search.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.cell-actions {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
Loading…
Reference in a new issue