mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-23 20:36:44 +00:00
improve new tx notifications
This commit is contained in:
parent
f0b7409c4a
commit
b2f48a1b05
8 changed files with 91 additions and 46 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit d2582c041479704d609c20ed13195c3f92ced999
|
||||
Subproject commit fff658a3ab33a3f63f5a1cd03c2b7cc1f20bec4a
|
|
@ -44,6 +44,7 @@ import javafx.scene.input.TransferMode;
|
|||
import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import javafx.util.Duration;
|
||||
import org.controlsfx.control.Notifications;
|
||||
import org.controlsfx.control.StatusBar;
|
||||
|
@ -161,9 +162,6 @@ public class AppController implements Initializable {
|
|||
rootStack.getStyleClass().removeAll(DRAG_OVER_CLASS);
|
||||
});
|
||||
|
||||
Stage tabStage = (Stage)tabs.getScene().getWindow();
|
||||
tabStage.getScene().getStylesheets().add(AppController.class.getResource("notificationpopup.css").toExternalForm());
|
||||
|
||||
tabs.getSelectionModel().selectedItemProperty().addListener((observable, old_val, selectedTab) -> {
|
||||
if(selectedTab != null) {
|
||||
TabData tabData = (TabData)selectedTab.getUserData();
|
||||
|
@ -241,15 +239,6 @@ public class AppController implements Initializable {
|
|||
}
|
||||
|
||||
openTransactionIdItem.disableProperty().bind(onlineProperty.not());
|
||||
|
||||
List<File> recentWalletFiles = Config.get().getRecentWalletFiles();
|
||||
if(recentWalletFiles != null) {
|
||||
for(File walletFile : recentWalletFiles) {
|
||||
if(walletFile.exists()) {
|
||||
openWalletFile(walletFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ElectrumServer.ConnectionService createConnectionService() {
|
||||
|
@ -618,7 +607,7 @@ public class AppController implements Initializable {
|
|||
}
|
||||
}
|
||||
|
||||
private void openWalletFile(File file) {
|
||||
public void openWalletFile(File file) {
|
||||
try {
|
||||
Storage storage = new Storage(file);
|
||||
FileType fileType = IOUtils.getFileType(file);
|
||||
|
@ -959,25 +948,46 @@ public class AppController implements Initializable {
|
|||
@Subscribe
|
||||
public void newWalletTransactions(NewWalletTransactionsEvent event) {
|
||||
if(Config.get().isNotifyNewTransactions()) {
|
||||
String text = "New " + (event.getBlockTransactions().size() > 1 ? "transactions: " : "transaction: ");
|
||||
String text;
|
||||
if(event.getBlockTransactions().size() == 1) {
|
||||
BlockTransaction blockTransaction = event.getBlockTransactions().get(0);
|
||||
if(blockTransaction.getHeight() == 0) {
|
||||
text = "New mempool transaction: ";
|
||||
} else {
|
||||
int confirmations = blockTransaction.getConfirmations(getCurrentBlockHeight());
|
||||
if(confirmations == 1) {
|
||||
text = "First transaction confirmation: ";
|
||||
} else if(confirmations <= BlockTransactionHash.BLOCKS_TO_CONFIRM) {
|
||||
text = "Confirming transaction: ";
|
||||
} else {
|
||||
text = "Confirmed transaction: ";
|
||||
}
|
||||
}
|
||||
|
||||
BitcoinUnit unit = Config.get().getBitcoinUnit();
|
||||
if(unit == null || unit.equals(BitcoinUnit.AUTO)) {
|
||||
unit = (event.getTotalValue() >= BitcoinUnit.getAutoThreshold() ? BitcoinUnit.BTC : BitcoinUnit.SATOSHIS);
|
||||
}
|
||||
|
||||
if(unit == BitcoinUnit.BTC) {
|
||||
text += CoinLabel.getBTCFormat().format((double)event.getTotalValue() / Transaction.SATOSHIS_PER_BITCOIN) + " BTC";
|
||||
text += event.getValueAsText(event.getTotalValue());
|
||||
} else {
|
||||
text += String.format(Locale.ENGLISH, "%,d", event.getTotalValue()) + " sats";
|
||||
if(event.getTotalBlockchainValue() > 0 && event.getTotalMempoolValue() > 0) {
|
||||
text = "New transactions: " + event.getValueAsText(event.getTotalValue()) + " (" + event.getValueAsText(event.getTotalMempoolValue()) + " in mempool)";
|
||||
} else if(event.getTotalMempoolValue() > 0) {
|
||||
text = "New mempool transactions: " + event.getValueAsText(event.getTotalMempoolValue());
|
||||
} else {
|
||||
text = "New transactions: " + event.getValueAsText(event.getTotalValue());
|
||||
}
|
||||
}
|
||||
|
||||
Window.getWindows().forEach(window -> {
|
||||
String notificationStyles = AppController.class.getResource("notificationpopup.css").toExternalForm();
|
||||
if(!window.getScene().getStylesheets().contains(notificationStyles)) {
|
||||
window.getScene().getStylesheets().add(notificationStyles);
|
||||
}
|
||||
});
|
||||
|
||||
Image image = new Image("image/sparrow-small.png", 50, 50, false, false);
|
||||
Notifications notificationBuilder = Notifications.create()
|
||||
.title("Sparrow - " + event.getWallet().getName())
|
||||
.text(text)
|
||||
.graphic(new ImageView(image))
|
||||
.hideAfter(Duration.seconds(180))
|
||||
.hideAfter(Duration.seconds(5))
|
||||
.position(Pos.TOP_RIGHT)
|
||||
.threshold(5, Notifications.create().title("Sparrow").text("Multiple new wallet transactions").graphic(new ImageView(image)))
|
||||
.onAction(e -> selectTab(event.getWallet()));
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.sparrowwallet.sparrow.io.Config;
|
|||
import com.sparrowwallet.sparrow.preferences.PreferenceGroup;
|
||||
import com.sparrowwallet.sparrow.preferences.PreferencesDialog;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
|
@ -14,6 +15,8 @@ import javafx.scene.image.Image;
|
|||
import javafx.stage.Stage;
|
||||
import org.controlsfx.glyphfont.GlyphFontRegistry;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MainApp extends Application {
|
||||
|
@ -60,6 +63,15 @@ public class MainApp extends Application {
|
|||
appController.initializeView();
|
||||
|
||||
stage.show();
|
||||
|
||||
List<File> recentWalletFiles = Config.get().getRecentWalletFiles();
|
||||
if(recentWalletFiles != null) {
|
||||
for(File walletFile : recentWalletFiles) {
|
||||
if(walletFile.exists()) {
|
||||
Platform.runLater(() -> appController.openWalletFile(walletFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.sparrow.wallet.TransactionEntry;
|
||||
import com.sparrowwallet.drongo.wallet.BlockTransactionHash;
|
||||
import javafx.animation.*;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.geometry.Pos;
|
||||
|
@ -54,7 +54,7 @@ public class ConfirmationProgressIndicator extends StackPane {
|
|||
arcLengthTimeline.getKeyFrames().add(arcLengthFrame);
|
||||
sequence.getChildren().add(arcLengthTimeline);
|
||||
|
||||
if(newValue.intValue() == TransactionEntry.BLOCKS_TO_CONFIRM) {
|
||||
if(newValue.intValue() == BlockTransactionHash.BLOCKS_TO_CONFIRM) {
|
||||
Timeline arcRadiusTimeline = new Timeline();
|
||||
KeyValue arcRadiusXValue = new KeyValue(arc.radiusXProperty(), 0.0);
|
||||
KeyValue arcRadiusYValue = new KeyValue(arc.radiusYProperty(), 0.0);
|
||||
|
@ -98,7 +98,7 @@ public class ConfirmationProgressIndicator extends StackPane {
|
|||
}
|
||||
|
||||
private static double getDegrees(int confirmations) {
|
||||
int requiredConfirmations = TransactionEntry.BLOCKS_TO_CONFIRM;
|
||||
int requiredConfirmations = BlockTransactionHash.BLOCKS_TO_CONFIRM;
|
||||
return ((double)Math.min(confirmations, requiredConfirmations)/ requiredConfirmations) * -360d;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import com.sparrowwallet.drongo.BitcoinUnit;
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.control.CoinLabel;
|
||||
import com.sparrowwallet.sparrow.io.Config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class NewWalletTransactionsEvent {
|
||||
private final Wallet wallet;
|
||||
private final List<BlockTransaction> blockTransactions;
|
||||
private final long totalValue;
|
||||
private final long totalBlockchainValue;
|
||||
private final long totalMempoolValue;
|
||||
|
||||
public NewWalletTransactionsEvent(Wallet wallet, List<BlockTransaction> blockTransactions, long totalValue) {
|
||||
public NewWalletTransactionsEvent(Wallet wallet, List<BlockTransaction> blockTransactions, long totalBlockchainValue, long totalMempoolValue) {
|
||||
this.wallet = wallet;
|
||||
this.blockTransactions = blockTransactions;
|
||||
this.totalValue = totalValue;
|
||||
this.totalBlockchainValue = totalBlockchainValue;
|
||||
this.totalMempoolValue = totalMempoolValue;
|
||||
}
|
||||
|
||||
public Wallet getWallet() {
|
||||
|
@ -25,6 +32,27 @@ public class NewWalletTransactionsEvent {
|
|||
}
|
||||
|
||||
public long getTotalValue() {
|
||||
return totalValue;
|
||||
return totalBlockchainValue + totalMempoolValue;
|
||||
}
|
||||
|
||||
public long getTotalBlockchainValue() {
|
||||
return totalBlockchainValue;
|
||||
}
|
||||
|
||||
public long getTotalMempoolValue() {
|
||||
return totalMempoolValue;
|
||||
}
|
||||
|
||||
public String getValueAsText(long value) {
|
||||
BitcoinUnit unit = Config.get().getBitcoinUnit();
|
||||
if(unit == null || unit.equals(BitcoinUnit.AUTO)) {
|
||||
unit = (value >= BitcoinUnit.getAutoThreshold() ? BitcoinUnit.BTC : BitcoinUnit.SATOSHIS);
|
||||
}
|
||||
|
||||
if(unit == BitcoinUnit.BTC) {
|
||||
return CoinLabel.getBTCFormat().format((double) value / Transaction.SATOSHIS_PER_BITCOIN) + " BTC";
|
||||
}
|
||||
|
||||
return String.format(Locale.ENGLISH, "%,d", value) + " sats";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
blockStatus.setText(confirmations + " Confirmations");
|
||||
}
|
||||
|
||||
if(confirmations <= TransactionEntry.BLOCKS_TO_CONFIRM) {
|
||||
if(confirmations <= BlockTransactionHash.BLOCKS_TO_CONFIRM) {
|
||||
ConfirmationProgressIndicator indicator;
|
||||
if(blockStatus.getGraphic() == null) {
|
||||
indicator = new ConfirmationProgressIndicator(confirmations);
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.wallet;
|
|||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sparrowwallet.drongo.KeyPurpose;
|
||||
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||
import com.sparrowwallet.drongo.wallet.BlockTransactionHash;
|
||||
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
|
@ -17,9 +18,6 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
public class TransactionEntry extends Entry implements Comparable<TransactionEntry> {
|
||||
public static final int BLOCKS_TO_CONFIRM = 6;
|
||||
public static final int BLOCKS_TO_FULLY_CONFIRM = 100;
|
||||
|
||||
private final Wallet wallet;
|
||||
private final BlockTransaction blockTransaction;
|
||||
|
||||
|
@ -63,29 +61,25 @@ public class TransactionEntry extends Entry implements Comparable<TransactionEnt
|
|||
}
|
||||
|
||||
public boolean isConfirming() {
|
||||
return getConfirmations() < BLOCKS_TO_CONFIRM;
|
||||
return getConfirmations() < BlockTransactionHash.BLOCKS_TO_CONFIRM;
|
||||
}
|
||||
|
||||
public boolean isFullyConfirming() {
|
||||
return getConfirmations() < BLOCKS_TO_FULLY_CONFIRM;
|
||||
return getConfirmations() < BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM;
|
||||
}
|
||||
|
||||
public int calculateConfirmations() {
|
||||
if(blockTransaction.getHeight() <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return wallet.getStoredBlockHeight() - blockTransaction.getHeight() + 1;
|
||||
return blockTransaction.getConfirmations(wallet.getStoredBlockHeight());
|
||||
}
|
||||
|
||||
public String getConfirmationsDescription() {
|
||||
int confirmations = getConfirmations();
|
||||
if(confirmations == 0) {
|
||||
return "Unconfirmed in mempool";
|
||||
} else if(confirmations < BLOCKS_TO_FULLY_CONFIRM) {
|
||||
} else if(confirmations < BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM) {
|
||||
return confirmations + " confirmation" + (confirmations == 1 ? "" : "s");
|
||||
} else {
|
||||
return BLOCKS_TO_FULLY_CONFIRM + "+ confirmations";
|
||||
return BlockTransactionHash.BLOCKS_TO_FULLY_CONFIRM + "+ confirmations";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,8 +69,9 @@ public class WalletTransactionsEntry extends Entry {
|
|||
|
||||
if(!entriesAdded.isEmpty()) {
|
||||
List<BlockTransaction> blockTransactions = entriesAdded.stream().map(txEntry -> ((TransactionEntry)txEntry).getBlockTransaction()).collect(Collectors.toList());
|
||||
long totalValue = entriesAdded.stream().mapToLong(Entry::getValue).sum();
|
||||
EventManager.get().post(new NewWalletTransactionsEvent(wallet, blockTransactions, totalValue));
|
||||
long totalBlockchainValue = entriesAdded.stream().filter(txEntry -> ((TransactionEntry)txEntry).getConfirmations() > 0).mapToLong(Entry::getValue).sum();
|
||||
long totalMempoolValue = entriesAdded.stream().filter(txEntry -> ((TransactionEntry)txEntry).getConfirmations() == 0).mapToLong(Entry::getValue).sum();
|
||||
EventManager.get().post(new NewWalletTransactionsEvent(wallet, blockTransactions, totalBlockchainValue, totalMempoolValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue