mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
unregister closed tab and dialog subscribers, fix connection error reset behaviour
This commit is contained in:
parent
d5aba35184
commit
77dd8ca5d7
22 changed files with 188 additions and 15 deletions
|
@ -188,6 +188,18 @@ public class AppController implements Initializable {
|
|||
EventManager.get().post(new OpenWalletsEvent(getOpenWallets()));
|
||||
}
|
||||
|
||||
List<WalletTabData> closedWalletTabs = c.getRemoved().stream().map(tab -> (TabData)tab.getUserData())
|
||||
.filter(tabData -> tabData.getType() == TabData.TabType.WALLET).map(tabData -> (WalletTabData)tabData).collect(Collectors.toList());
|
||||
if(!closedWalletTabs.isEmpty()) {
|
||||
EventManager.get().post(new WalletTabsClosedEvent(closedWalletTabs));
|
||||
}
|
||||
|
||||
List<TransactionTabData> closedTransactionTabs = c.getRemoved().stream().map(tab -> (TabData)tab.getUserData())
|
||||
.filter(tabData -> tabData.getType() == TabData.TabType.TRANSACTION).map(tabData -> (TransactionTabData)tabData).collect(Collectors.toList());
|
||||
if(!closedTransactionTabs.isEmpty()) {
|
||||
EventManager.get().post(new TransactionTabsClosedEvent(closedTransactionTabs));
|
||||
}
|
||||
|
||||
if(tabs.getTabs().isEmpty()) {
|
||||
Stage tabStage = (Stage)tabs.getScene().getWindow();
|
||||
tabStage.setTitle("Sparrow");
|
||||
|
@ -268,10 +280,14 @@ public class AppController implements Initializable {
|
|||
}
|
||||
});
|
||||
connectionService.setOnFailed(failEvent -> {
|
||||
//Close connection here to create a new transport next time we try
|
||||
connectionService.resetConnection();
|
||||
|
||||
changeMode = false;
|
||||
onlineProperty.setValue(false);
|
||||
changeMode = true;
|
||||
|
||||
log.debug("Connection failed", failEvent.getSource().getException());
|
||||
EventManager.get().post(new ConnectionFailedEvent(failEvent.getSource().getException()));
|
||||
});
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ public class WalletTabData extends TabData {
|
|||
this.walletForm = walletForm;
|
||||
}
|
||||
|
||||
public WalletForm getWalletForm() {
|
||||
return walletForm;
|
||||
}
|
||||
|
||||
public Wallet getWallet() {
|
||||
return walletForm.getWallet();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ public class DeviceAddressDialog extends DeviceDialog<String> {
|
|||
this.keyDerivation = keyDerivation;
|
||||
|
||||
EventManager.get().register(this);
|
||||
setOnCloseRequest(event -> {
|
||||
EventManager.get().unregister(this);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,7 +31,6 @@ public class DeviceAddressDialog extends DeviceDialog<String> {
|
|||
|
||||
@Subscribe
|
||||
public void addressDisplayed(AddressDisplayedEvent event) {
|
||||
EventManager.get().unregister(this);
|
||||
setResult(event.getAddress());
|
||||
this.close();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ public class DeviceSignDialog extends DeviceDialog<PSBT> {
|
|||
super(devices);
|
||||
this.psbt = psbt;
|
||||
EventManager.get().register(this);
|
||||
setOnCloseRequest(event -> {
|
||||
EventManager.get().unregister(this);
|
||||
});
|
||||
setResultConverter(dialogButton -> dialogButton.getButtonData().isCancelButton() ? null : psbt);
|
||||
}
|
||||
|
||||
|
@ -26,7 +29,6 @@ public class DeviceSignDialog extends DeviceDialog<PSBT> {
|
|||
@Subscribe
|
||||
public void psbtSigned(PSBTSignedEvent event) {
|
||||
if(psbt == event.getPsbt()) {
|
||||
EventManager.get().unregister(this);
|
||||
setResult(event.getSignedPsbt());
|
||||
this.close();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ public class WalletExportDialog extends Dialog<Wallet> {
|
|||
|
||||
public WalletExportDialog(Wallet wallet) {
|
||||
EventManager.get().register(this);
|
||||
setOnCloseRequest(event -> {
|
||||
EventManager.get().unregister(this);
|
||||
});
|
||||
|
||||
final DialogPane dialogPane = getDialogPane();
|
||||
|
||||
|
@ -64,7 +67,6 @@ public class WalletExportDialog extends Dialog<Wallet> {
|
|||
|
||||
@Subscribe
|
||||
public void walletExported(WalletExportEvent event) {
|
||||
EventManager.get().unregister(this);
|
||||
wallet = event.getWallet();
|
||||
setResult(wallet);
|
||||
this.close();
|
||||
|
|
|
@ -16,6 +16,9 @@ public class WalletImportDialog extends Dialog<Wallet> {
|
|||
|
||||
public WalletImportDialog() {
|
||||
EventManager.get().register(this);
|
||||
setOnCloseRequest(event -> {
|
||||
EventManager.get().unregister(this);
|
||||
});
|
||||
|
||||
final DialogPane dialogPane = getDialogPane();
|
||||
|
||||
|
@ -51,7 +54,6 @@ public class WalletImportDialog extends Dialog<Wallet> {
|
|||
|
||||
@Subscribe
|
||||
public void walletImported(WalletImportEvent event) {
|
||||
EventManager.get().unregister(this);
|
||||
wallet = event.getWallet();
|
||||
setResult(wallet);
|
||||
this.close();
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import com.sparrowwallet.sparrow.TransactionTabData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TransactionTabsClosedEvent {
|
||||
private final List<TransactionTabData> closedTransactionTabData;
|
||||
|
||||
public TransactionTabsClosedEvent(List<TransactionTabData> closedTransactionTabData) {
|
||||
this.closedTransactionTabData = closedTransactionTabData;
|
||||
}
|
||||
|
||||
public List<TransactionTabData> getClosedTransactionTabData() {
|
||||
return closedTransactionTabData;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
import com.sparrowwallet.sparrow.WalletTabData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WalletTabsClosedEvent {
|
||||
private final List<WalletTabData> closedWalletTabData;
|
||||
|
||||
public WalletTabsClosedEvent(List<WalletTabData> closedWalletTabData) {
|
||||
this.closedWalletTabData = closedWalletTabData;
|
||||
}
|
||||
|
||||
public List<WalletTabData> getClosedWalletTabData() {
|
||||
return closedWalletTabData;
|
||||
}
|
||||
}
|
|
@ -27,6 +27,10 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
|
|||
|
||||
public KeystoreImportDialog(Wallet wallet, KeystoreSource initialSource) {
|
||||
EventManager.get().register(this);
|
||||
setOnCloseRequest(event -> {
|
||||
EventManager.get().unregister(this);
|
||||
});
|
||||
|
||||
final DialogPane dialogPane = getDialogPane();
|
||||
|
||||
try {
|
||||
|
|
|
@ -579,7 +579,6 @@ public class ElectrumServer {
|
|||
private final boolean subscribe;
|
||||
private boolean firstCall = true;
|
||||
private Thread reader;
|
||||
private Throwable lastReaderException;
|
||||
private long feeRatesRetrievedAt;
|
||||
|
||||
public ConnectionService() {
|
||||
|
@ -598,7 +597,7 @@ public class ElectrumServer {
|
|||
if(firstCall) {
|
||||
electrumServer.connect();
|
||||
|
||||
reader = new Thread(new ReadRunnable());
|
||||
reader = new Thread(new ReadRunnable(), "ElectrumServerReadThread");
|
||||
reader.setDaemon(true);
|
||||
reader.setUncaughtExceptionHandler(ConnectionService.this);
|
||||
reader.start();
|
||||
|
@ -639,8 +638,7 @@ public class ElectrumServer {
|
|||
return new FeeRatesUpdatedEvent(blockTargetFeeRates);
|
||||
}
|
||||
} else {
|
||||
firstCall = true;
|
||||
throw new ServerException("Connection to server failed", lastReaderException);
|
||||
resetConnection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,12 +647,21 @@ public class ElectrumServer {
|
|||
};
|
||||
}
|
||||
|
||||
public void resetConnection() {
|
||||
try {
|
||||
closeActiveConnection();
|
||||
firstCall = true;
|
||||
} catch (ServerException e) {
|
||||
log.error("Error closing connection during connection reset", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel() {
|
||||
try {
|
||||
closeActiveConnection();
|
||||
} catch (ServerException e) {
|
||||
log.error("Eror closing connection", e);
|
||||
log.error("Error closing connection", e);
|
||||
}
|
||||
|
||||
return super.cancel();
|
||||
|
@ -664,12 +671,11 @@ public class ElectrumServer {
|
|||
public void reset() {
|
||||
super.reset();
|
||||
firstCall = true;
|
||||
lastReaderException = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
this.lastReaderException = e;
|
||||
log.error("Uncaught error in ConnectionService", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -679,8 +685,9 @@ public class ElectrumServer {
|
|||
try {
|
||||
TcpTransport tcpTransport = (TcpTransport)getTransport();
|
||||
tcpTransport.readInputLoop();
|
||||
} catch (ServerException e) {
|
||||
throw new RuntimeException(e.getCause() != null ? e.getCause() : e);
|
||||
} catch(ServerException e) {
|
||||
//Only debug logging here as the exception has been passed on to the ConnectionService thread via TcpTransport
|
||||
log.debug("Read thread terminated", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ public class TcpTransport implements Transport, Closeable {
|
|||
private final JsonRpcServer jsonRpcServer = new JsonRpcServer();
|
||||
private final SubscriptionService subscriptionService = new SubscriptionService();
|
||||
|
||||
private Exception lastException;
|
||||
|
||||
public TcpTransport(HostAndPort server) {
|
||||
this.server = server;
|
||||
this.socketFactory = SocketFactory.getDefault();
|
||||
|
@ -50,7 +52,7 @@ public class TcpTransport implements Transport, Closeable {
|
|||
out.flush();
|
||||
}
|
||||
|
||||
private synchronized String readResponse() {
|
||||
private synchronized String readResponse() throws IOException {
|
||||
while(reading) {
|
||||
try {
|
||||
wait();
|
||||
|
@ -60,6 +62,10 @@ public class TcpTransport implements Transport, Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
if(lastException != null) {
|
||||
throw new IOException("Error reading response", lastException);
|
||||
}
|
||||
|
||||
reading = true;
|
||||
|
||||
notifyAll();
|
||||
|
@ -83,8 +89,12 @@ public class TcpTransport implements Transport, Closeable {
|
|||
} catch(InterruptedException e) {
|
||||
//Restore interrupt status and continue
|
||||
Thread.currentThread().interrupt();
|
||||
} catch(IOException e) {
|
||||
} catch(Exception e) {
|
||||
if(running) {
|
||||
lastException = e;
|
||||
reading = false;
|
||||
notifyAll();
|
||||
//Allow this thread to terminate as we will need to reconnect with a new transport anyway
|
||||
throw new ServerException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,6 +196,11 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
initializeView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionForm getTransactionForm() {
|
||||
return headersForm;
|
||||
}
|
||||
|
||||
private void initializeView() {
|
||||
Transaction tx = headersForm.getTransaction();
|
||||
|
||||
|
|
|
@ -461,6 +461,11 @@ public class InputController extends TransactionFormController implements Initia
|
|||
initializeView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionForm getTransactionForm() {
|
||||
return inputForm;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String describeScriptChunk(ScriptChunk chunk) {
|
||||
String chunkString = super.describeScriptChunk(chunk);
|
||||
|
|
|
@ -49,6 +49,11 @@ public class InputsController extends TransactionFormController implements Initi
|
|||
initialiseView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionForm getTransactionForm() {
|
||||
return inputsForm;
|
||||
}
|
||||
|
||||
private void initialiseView() {
|
||||
Transaction tx = inputsForm.getTransaction();
|
||||
count.setText(Integer.toString(tx.getInputs().size()));
|
||||
|
|
|
@ -147,6 +147,11 @@ public class OutputController extends TransactionFormController implements Initi
|
|||
initializeView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionForm getTransactionForm() {
|
||||
return outputForm;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void blockTransactionOutputsFetched(BlockTransactionOutputsFetchedEvent event) {
|
||||
if(event.getTxId().equals(outputForm.getTransaction().getTxId()) && outputForm.getPsbt() == null && outputForm.getIndex() >= event.getPageStart() && outputForm.getIndex() < event.getPageEnd()) {
|
||||
|
|
|
@ -51,6 +51,11 @@ public class OutputsController extends TransactionFormController implements Init
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionForm getTransactionForm() {
|
||||
return outputsForm;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) {
|
||||
total.refresh(event.getBitcoinUnit());
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.sparrowwallet.drongo.psbt.PSBTOutput;
|
|||
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||
import com.sparrowwallet.sparrow.AppController;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.TransactionTabData;
|
||||
import com.sparrowwallet.sparrow.control.TransactionHexArea;
|
||||
import com.sparrowwallet.sparrow.event.*;
|
||||
import com.sparrowwallet.sparrow.net.ElectrumServer;
|
||||
|
@ -489,4 +490,13 @@ public class TransactionController implements Initializable {
|
|||
highlightTxHex();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void transactionTabsClosed(TransactionTabsClosedEvent event) {
|
||||
for(TransactionTabData tabData : event.getClosedTransactionTabData()) {
|
||||
if(tabData.getTransactionData() == txdata) {
|
||||
EventManager.get().unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,10 @@ public abstract class TransactionForm {
|
|||
this.txdata = txdata;
|
||||
}
|
||||
|
||||
public TransactionData getTransactionData() {
|
||||
return txdata;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return txdata.getTransaction();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sparrowwallet.drongo.address.Address;
|
||||
import com.sparrowwallet.drongo.protocol.NonStandardScriptException;
|
||||
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||
import com.sparrowwallet.sparrow.BaseController;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.TransactionTabData;
|
||||
import com.sparrowwallet.sparrow.event.TransactionTabsClosedEvent;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.chart.PieChart;
|
||||
|
@ -18,6 +22,8 @@ import java.util.List;
|
|||
public abstract class TransactionFormController extends BaseController {
|
||||
private static final int MAX_PIE_SEGMENTS = 200;
|
||||
|
||||
protected abstract TransactionForm getTransactionForm();
|
||||
|
||||
protected void addPieData(PieChart pie, List<TransactionOutput> outputs) {
|
||||
ObservableList<PieChart.Data> outputsPieData = FXCollections.observableArrayList();
|
||||
|
||||
|
@ -64,6 +70,15 @@ public abstract class TransactionFormController extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void transactionTabsClosed(TransactionTabsClosedEvent event) {
|
||||
for(TransactionTabData tabData : event.getClosedTransactionTabData()) {
|
||||
if(tabData.getTransactionData() == getTransactionForm().getTransactionData()) {
|
||||
EventManager.get().unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class TransactionReferenceContextMenu extends ContextMenu {
|
||||
public TransactionReferenceContextMenu(String reference) {
|
||||
MenuItem referenceItem = new MenuItem("Copy Reference");
|
||||
|
|
|
@ -7,8 +7,10 @@ import com.sparrowwallet.drongo.wallet.BlockTransactionHash;
|
|||
import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.WalletTabData;
|
||||
import com.sparrowwallet.sparrow.event.WalletBlockHeightChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletEntryLabelChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletTabsClosedEvent;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.IntegerPropertyBase;
|
||||
import javafx.beans.property.LongProperty;
|
||||
|
@ -204,4 +206,13 @@ public class TransactionEntry extends Entry implements Comparable<TransactionEnt
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletTabsClosed(WalletTabsClosedEvent event) {
|
||||
for(WalletTabData tabData : event.getClosedWalletTabData()) {
|
||||
if(tabData.getWalletForm().getWallet() == wallet) {
|
||||
EventManager.get().unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
|||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||
import com.sparrowwallet.sparrow.AppController;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.WalletTabData;
|
||||
import com.sparrowwallet.sparrow.event.*;
|
||||
import com.sparrowwallet.sparrow.net.ElectrumServer;
|
||||
import com.sparrowwallet.sparrow.io.Storage;
|
||||
|
@ -216,4 +217,13 @@ public class WalletForm {
|
|||
refreshHistory(AppController.getCurrentBlockHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletTabsClosed(WalletTabsClosedEvent event) {
|
||||
for(WalletTabData tabData : event.getClosedWalletTabData()) {
|
||||
if(tabData.getWalletForm() == this) {
|
||||
EventManager.get().unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package com.sparrowwallet.sparrow.wallet;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sparrowwallet.sparrow.BaseController;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.WalletTabData;
|
||||
import com.sparrowwallet.sparrow.event.WalletTabsClosedEvent;
|
||||
|
||||
public abstract class WalletFormController extends BaseController {
|
||||
public WalletForm walletForm;
|
||||
|
@ -15,4 +19,15 @@ public abstract class WalletFormController extends BaseController {
|
|||
}
|
||||
|
||||
public abstract void initializeView();
|
||||
|
||||
@Subscribe
|
||||
public void walletTabsClosed(WalletTabsClosedEvent event) {
|
||||
for(WalletTabData tabData : event.getClosedWalletTabData()) {
|
||||
if(tabData.getWalletForm() == walletForm) {
|
||||
EventManager.get().unregister(this);
|
||||
} else if(walletForm instanceof SettingsWalletForm && tabData.getStorage() == walletForm.getStorage()) {
|
||||
EventManager.get().unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue