preferences update

This commit is contained in:
Craig Raw
2020-07-16 10:25:24 +02:00
parent 3cee45223e
commit bd721be1a2
6 changed files with 168 additions and 38 deletions
@@ -0,0 +1,45 @@
package com.sparrowwallet.sparrow.control;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import org.controlsfx.glyphfont.Glyph;
public class HelpLabel extends Label {
private final Tooltip tooltip;
public HelpLabel() {
super("", getHelpGlyph());
tooltip = new Tooltip();
tooltip.textProperty().bind(helpTextProperty());
setTooltip(tooltip);
getStyleClass().add("help-label");
}
private static Glyph getHelpGlyph() {
Glyph lockGlyph = new Glyph("Font Awesome 5 Free Solid", FontAwesome5.Glyph.QUESTION_CIRCLE);
lockGlyph.getStyleClass().add("help-icon");
lockGlyph.setFontSize(12);
return lockGlyph;
}
public final StringProperty helpTextProperty() {
if(helpText == null) {
helpText = new SimpleStringProperty(this, "helpText", "");
}
return helpText;
}
private StringProperty helpText;
public final void setHelpText(String value) {
helpTextProperty().setValue(value);
}
public final String getHelpText() {
return helpText == null ? "" : helpText.getValue();
}
}
@@ -116,6 +116,15 @@ public class ElectrumServer {
return client.createRequest().returnAs(BlockHeaderTip.class).method("blockchain.headers.subscribe").id(1).execute();
}
public static synchronized boolean isConnected() {
if(transport != null) {
TcpTransport tcpTransport = (TcpTransport)transport;
return tcpTransport.isConnected();
}
return false;
}
public static synchronized void closeActiveConnection() throws ServerException {
try {
if(transport != null) {
@@ -572,6 +581,10 @@ public class ElectrumServer {
public String hex;
public BlockHeader getBlockHeader() {
if(hex == null) {
return null;
}
byte[] blockHeaderBytes = Utils.hexToBytes(hex);
return new BlockHeader(blockHeaderBytes);
}
@@ -715,6 +728,10 @@ public class ElectrumServer {
}
}
public boolean isConnected() {
return socket != null && running;
}
protected Socket createSocket() throws IOException {
return socketFactory.createSocket(server.getHost(), server.getPortOrDefault(DEFAULT_PORT));
}
@@ -832,11 +849,20 @@ public class ElectrumServer {
public static class ConnectionService extends ScheduledService<FeeRatesUpdatedEvent> implements Thread.UncaughtExceptionHandler {
private static final int FEE_RATES_PERIOD = 5 * 60 * 1000;
private final boolean subscribe;
private boolean firstCall = true;
private Thread reader;
private Throwable lastReaderException;
private long feeRatesRetrievedAt;
public ConnectionService() {
this(true);
}
public ConnectionService(boolean subscribe) {
this.subscribe = subscribe;
}
@Override
protected Task<FeeRatesUpdatedEvent> createTask() {
return new Task<>() {
@@ -853,7 +879,13 @@ public class ElectrumServer {
List<String> serverVersion = electrumServer.getServerVersion();
firstCall = false;
BlockHeaderTip tip = electrumServer.subscribeBlockHeaders();
BlockHeaderTip tip;
if(subscribe) {
tip = electrumServer.subscribeBlockHeaders();
} else {
tip = new BlockHeaderTip();
}
String banner = electrumServer.getServerBanner();
Map<Integer, Double> blockTargetFeeRates = electrumServer.getFeeEstimates(SendController.TARGET_BLOCKS_RANGE);
@@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.preferences;
import com.sparrowwallet.drongo.BitcoinUnit;
import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch;
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
import com.sparrowwallet.sparrow.event.FiatCurrencySelectedEvent;
import com.sparrowwallet.sparrow.io.Config;
@@ -24,6 +25,12 @@ public class GeneralPreferencesController extends PreferencesDetailController {
@FXML
private ComboBox<ExchangeSource> exchangeSource;
@FXML
private UnlabeledToggleSwitch groupByAddress;
@FXML
private UnlabeledToggleSwitch includeMempoolChange;
private final ChangeListener<Currency> fiatCurrencyListener = new ChangeListener<Currency>() {
@Override
public void changed(ObservableValue<? extends Currency> observable, Currency oldValue, Currency newValue) {
@@ -58,6 +65,15 @@ public class GeneralPreferencesController extends PreferencesDetailController {
});
updateCurrencies(exchangeSource.getSelectionModel().getSelectedItem());
groupByAddress.setSelected(config.isGroupByAddress());
includeMempoolChange.setSelected(config.isIncludeMempoolChange());
groupByAddress.selectedProperty().addListener((observableValue, oldValue, newValue) -> {
config.setGroupByAddress(newValue);
});
includeMempoolChange.selectedProperty().addListener((observableValue, oldValue, newValue) -> {
config.setIncludeMempoolChange(newValue);
});
}
private void updateCurrencies(ExchangeSource exchangeSource) {
@@ -3,12 +3,13 @@ package com.sparrowwallet.sparrow.preferences;
import com.google.common.net.HostAndPort;
import com.sparrowwallet.sparrow.control.TextFieldValidator;
import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch;
import com.sparrowwallet.sparrow.event.ConnectionEvent;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import com.sparrowwallet.sparrow.io.Config;
import com.sparrowwallet.sparrow.io.ElectrumServer;
import com.sparrowwallet.sparrow.io.ServerException;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.concurrent.WorkerStateEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
@@ -17,6 +18,7 @@ import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.controlsfx.glyphfont.Glyph;
import org.controlsfx.validation.ValidationResult;
import org.controlsfx.validation.ValidationSupport;
@@ -123,40 +125,31 @@ public class ServerPreferencesController extends PreferencesDetailController {
});
testConnection.setOnAction(event -> {
try {
ElectrumServer.closeActiveConnection();
} catch (ServerException e) {
testResults.setText("Failed to disconnect:\n" + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()));
}
ElectrumServer.ServerVersionService serverVersionService = new ElectrumServer.ServerVersionService();
serverVersionService.setOnSucceeded(successEvent -> {
List<String> serverVersion = serverVersionService.getValue();
testResults.setText("Connected to " + serverVersion.get(0) + " on protocol version " + serverVersion.get(1));
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.CHECK_CIRCLE, Color.rgb(80, 161, 79)));
ElectrumServer.ServerBannerService serverBannerService = new ElectrumServer.ServerBannerService();
serverBannerService.setOnSucceeded(bannerSuccessEvent -> {
testResults.setText(testResults.getText() + "\nServer Banner: " + serverBannerService.getValue());
});
serverBannerService.setOnFailed(bannerFailEvent -> {
testResults.setText(testResults.getText() + "\nServer Banner: None");
});
serverBannerService.start();
});
serverVersionService.setOnFailed(failEvent -> {
Throwable e = failEvent.getSource().getException();
String reason = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
if(e.getCause() != null && e.getCause() instanceof SSLHandshakeException) {
reason = "SSL Handshake Error\n" + reason;
}
testResults.setText("Could not connect:\n\n" + reason);
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.EXCLAMATION_CIRCLE, Color.rgb(202, 18, 67)));
});
testResults.setText("Connecting to " + config.getElectrumServer() + "...");
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.ELLIPSIS_H, null));
serverVersionService.start();
boolean existingConnection = ElectrumServer.isConnected();
if(existingConnection) {
ElectrumServer.ServerBannerService serverBannerService = new ElectrumServer.ServerBannerService();
serverBannerService.setOnSucceeded(successEvent -> {
showConnectionSuccess(null, serverBannerService.getValue());
});
serverBannerService.setOnFailed(this::showConnectionFailure);
serverBannerService.start();
} else {
ElectrumServer.ConnectionService connectionService = new ElectrumServer.ConnectionService(false);
connectionService.setPeriod(Duration.minutes(1));
connectionService.setOnSucceeded(successEvent -> {
ConnectionEvent connectionEvent = (ConnectionEvent)connectionService.getValue();
showConnectionSuccess(connectionEvent.getServerVersion(), connectionEvent.getServerBanner());
connectionService.cancel();
});
connectionService.setOnFailed(workerStateEvent -> {
showConnectionFailure(workerStateEvent);
connectionService.cancel();
});
connectionService.start();
}
});
String electrumServer = config.getElectrumServer();
@@ -201,6 +194,27 @@ public class ServerPreferencesController extends PreferencesDetailController {
}
}
private void showConnectionSuccess(List<String> serverVersion, String serverBanner) {
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.CHECK_CIRCLE, Color.rgb(80, 161, 79)));
if(serverVersion != null) {
testResults.setText("Connected to " + serverVersion.get(0) + " on protocol version " + serverVersion.get(1));
}
if(serverBanner != null) {
testResults.setText(testResults.getText() + "\nServer Banner: " + serverBanner);
}
}
private void showConnectionFailure(WorkerStateEvent failEvent) {
Throwable e = failEvent.getSource().getException();
String reason = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
if(e.getCause() != null && e.getCause() instanceof SSLHandshakeException) {
reason = "SSL Handshake Error\n" + reason;
}
testResults.setText("Could not connect:\n\n" + reason);
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.EXCLAMATION_CIRCLE, Color.rgb(202, 18, 67)));
}
private void setupValidation() {
validationSupport.registerValidator(host, Validator.combine(
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Invalid host name", getHost(newValue) == null)