Add UI info for P2P network

This commit is contained in:
Manfred Karrer 2015-11-09 22:07:17 +01:00
parent b81e263c24
commit d666c6cd3b
30 changed files with 232 additions and 625 deletions

View file

@ -66,7 +66,6 @@ class BitsquareAppModule extends AppModule {
bind(File.class).annotatedWith(named(KeyStorage.DIR_KEY)).toInstance(keyStorageDir);
bind(BitsquareEnvironment.class).toInstance((BitsquareEnvironment) env);
bind(UpdateProcess.class).in(Singleton.class);
// ordering is used for shut down sequence
install(tradeModule());

View file

@ -1,164 +0,0 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.app;
import com.google.inject.Inject;
import io.bitsquare.common.handlers.ResultHandler;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import org.reactfx.util.Timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// TODO
// Deactivated for the moment.
// UpdateFX use https for getting the version nr./jars, which we want to avoid with the Tor P2p network
// We need to wait until tor is setup and then request from a hidden service the version and jars
public class UpdateProcess {
private static final Logger log = LoggerFactory.getLogger(UpdateProcess.class);
// private static final List<ECPoint> UPDATE_SIGNING_KEYS = Crypto.decode("029EF2D0D33A2546CB15FB10D969B7D65CAFB811CB3AC902E8D9A46BE847B1DA21");
// private static final String UPDATES_BASE_URL = "https://bitsquare.io/updateFX/v03";
private static final int UPDATE_SIGNING_THRESHOLD = 1;
// private static final Path ROOT_CLASS_PATH = UpdateFX.findCodePath(BitsquareAppMain.class);
private final BitsquareEnvironment environment;
private ResultHandler resultHandler;
public enum State {
INIT,
CHECK_FOR_UPDATES,
UPDATE_AVAILABLE,
UP_TO_DATE,
NEW_RELEASE, // if a new minor release is out we inform the user to download the new binary
FAILURE
}
public final ObjectProperty<State> state = new SimpleObjectProperty<>(State.INIT);
private String releaseUrl;
private Timer timeoutTimer;
@Inject
public UpdateProcess(BitsquareEnvironment environment) {
this.environment = environment;
}
public void restart() {
// UpdateFX.restartApp();
}
public void setResultHandler(ResultHandler resultHandler) {
this.resultHandler = resultHandler;
resultHandler.handleResult();
}
public void init() {
//log.info("UpdateFX checking for patch version " + Version.PATCH_VERSION);
// process.timeout() will cause an error state back but we don't want to break startup in case of an timeout
/* timeoutTimer = FxTimer.runLater(Duration.ofMillis(10000), () -> {
log.error("Timeout reached for UpdateFX");
resultHandler.handleResult();
});
String userAgent = environment.getProperty(BitsquareEnvironment.APP_NAME_KEY) + Version.VERSION;
*/
// Check if there is a new minor version release out. The release_url should be empty if no release is available, otherwise the download url.
/* try {
releaseUrl = Utilities.readTextFileFromServer(UPDATES_BASE_URL + "/release_url", userAgent);
if (releaseUrl != null && releaseUrl.length() > 0) {
log.info("New release available at: " + releaseUrl);
state.set(State.NEW_RELEASE);
timeoutTimer.stop();
return;
}
else {
// All ok. Empty file if we have no new release.
}
} catch (IOException e) {
// ignore. File might be missing
}*/
/* Updater updater = new Updater(UPDATES_BASE_URL, userAgent, Version.PATCH_VERSION,
Paths.get(environment.getProperty(BitsquareEnvironment.APP_DATA_DIR_KEY)),
ROOT_CLASS_PATH, UPDATE_SIGNING_KEYS, UPDATE_SIGNING_THRESHOLD) {
@Override
protected void updateProgress(long workDone, long max) {
//log.trace("updateProgress " + workDone + "/" + max);
super.updateProgress(workDone, max);
}
};*/
/* updater.progressProperty().addListener((observableValue, oldValue, newValue) -> {
log.trace("progressProperty newValue = " + newValue);
});*/
/* updater.setOnSucceeded(event -> {
try {
UpdateSummary summary = updater.get();
//log.info("summary " + summary.toString());
if (summary.descriptions != null && summary.descriptions.size() > 0) {
log.info("One liner: {}", summary.descriptions.get(0).getOneLiner());
log.info("{}", summary.descriptions.get(0).getDescription());
}
if (summary.highestVersion > Version.PATCH_VERSION) {
log.info("UPDATE_AVAILABLE");
state.set(State.UPDATE_AVAILABLE);
// We stop the timeout and treat it not completed.
// The user should click the restart button manually if there are updates available.
timeoutTimer.stop();
}
else if (summary.highestVersion == Version.PATCH_VERSION) {
log.info("UP_TO_DATE");
state.set(State.UP_TO_DATE);
timeoutTimer.stop();
resultHandler.handleResult();
}
} catch (Throwable e) {
log.error("Exception at processing UpdateSummary: " + e.getMessage());
// we treat errors as update not as critical errors to prevent startup,
// so we use state.onCompleted() instead of state.onError()
state.set(State.FAILURE);
timeoutTimer.stop();
resultHandler.handleResult();
}
});
updater.setOnFailed(event -> {
log.error("Update failed: " + updater.getException());
updater.getException().printStackTrace();
// we treat errors as update not as critical errors to prevent startup,
// so we use state.onCompleted() instead of state.onError()
state.set(State.FAILURE);
timeoutTimer.stop();
resultHandler.handleResult();
});
Thread thread = new Thread(updater, "Online update check");
thread.setDaemon(true);
thread.start();*/
}
public String getReleaseUrl() {
return releaseUrl;
}
}

View file

@ -129,6 +129,10 @@
}
/* connection state*/
#image-connection-tor {
-fx-image: url("../../../images/connection/tor.png");
}
#image-connection-direct {
-fx-image: url("../../../images/connection/direct.png");
}

View file

@ -20,7 +20,6 @@ package io.bitsquare.gui.main;
import io.bitsquare.BitsquareException;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.*;
import io.bitsquare.gui.components.SystemNotification;
@ -79,19 +78,14 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
private final String title;
private ChangeListener<String> walletServiceErrorMsgListener;
private ChangeListener<String> blockchainSyncIconIdListener;
private ChangeListener<String> bootstrapErrorMsgListener;
private ChangeListener<String> bootstrapIconIdListener;
private ChangeListener<Number> bootstrapProgressListener;
private ChangeListener<String> updateIconIdListener;
private Button restartButton;
private Button downloadButton;
private ProgressIndicator bootstrapIndicator;
private Label bootstrapStateLabel;
private ChangeListener<String> splashP2PNetworkErrorMsgListener;
private ChangeListener<String> splashP2PNetworkIconIdListener;
private ChangeListener<Number> splashP2PNetworkProgressListener;
private ProgressIndicator splashP2PNetworkIndicator;
private Label splashP2PNetworkLabel;
private ProgressBar blockchainSyncIndicator;
private Label blockchainSyncLabel;
private Label updateInfoLabel;
private List<String> persistedFilesCorrupted;
private Tooltip downloadButtonTooltip;
private static BorderPane baseApplicationContainer;
@Inject
@ -269,116 +263,68 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
blockchainSyncIcon, bitcoinNetworkLabel);
// createP2PNetworkBox
bootstrapStateLabel = new Label();
bootstrapStateLabel.setWrapText(true);
bootstrapStateLabel.setMaxWidth(500);
bootstrapStateLabel.setTextAlignment(TextAlignment.CENTER);
bootstrapStateLabel.textProperty().bind(model.bootstrapInfo);
// create P2PNetworkBox
splashP2PNetworkLabel = new Label();
splashP2PNetworkLabel.setWrapText(true);
splashP2PNetworkLabel.setMaxWidth(500);
splashP2PNetworkLabel.setTextAlignment(TextAlignment.CENTER);
splashP2PNetworkLabel.textProperty().bind(model.splashP2PNetworkInfo);
bootstrapIndicator = new ProgressIndicator();
bootstrapIndicator.setMaxSize(24, 24);
bootstrapIndicator.progressProperty().bind(model.bootstrapProgress);
splashP2PNetworkIndicator = new ProgressIndicator();
splashP2PNetworkIndicator.setMaxSize(24, 24);
splashP2PNetworkIndicator.progressProperty().bind(model.splashP2PNetworkProgress);
bootstrapErrorMsgListener = (ov, oldValue, newValue) -> {
bootstrapStateLabel.setId("splash-error-state-msg");
bootstrapIndicator.setVisible(false);
splashP2PNetworkErrorMsgListener = (ov, oldValue, newValue) -> {
splashP2PNetworkLabel.setId("splash-error-state-msg");
splashP2PNetworkIndicator.setVisible(false);
};
model.bootstrapErrorMsg.addListener(bootstrapErrorMsgListener);
model.p2PNetworkErrorMsg.addListener(splashP2PNetworkErrorMsgListener);
ImageView bootstrapIcon = new ImageView();
bootstrapIcon.setVisible(false);
bootstrapIcon.setManaged(false);
bootstrapIconIdListener = (ov, oldValue, newValue) -> {
bootstrapIcon.setId(newValue);
bootstrapIcon.setVisible(true);
bootstrapIcon.setManaged(true);
ImageView splashP2PNetworkIcon = new ImageView();
splashP2PNetworkIcon.setId("image-connection-tor");
splashP2PNetworkIcon.setVisible(false);
splashP2PNetworkIcon.setManaged(false);
HBox.setMargin(splashP2PNetworkIcon, new Insets(0, 0, 5, 0));
splashP2PNetworkIconIdListener = (ov, oldValue, newValue) -> {
splashP2PNetworkIcon.setId(newValue);
splashP2PNetworkIcon.setVisible(true);
splashP2PNetworkIcon.setManaged(true);
};
model.bootstrapIconId.addListener(bootstrapIconIdListener);
model.p2PNetworkIconId.addListener(splashP2PNetworkIconIdListener);
bootstrapProgressListener = (ov, oldValue, newValue) -> {
splashP2PNetworkProgressListener = (ov, oldValue, newValue) -> {
if ((double) newValue >= 1) {
bootstrapIndicator.setVisible(false);
bootstrapIndicator.setManaged(false);
splashP2PNetworkIndicator.setVisible(false);
splashP2PNetworkIndicator.setManaged(false);
}
};
model.bootstrapProgress.addListener(bootstrapProgressListener);
model.splashP2PNetworkProgress.addListener(splashP2PNetworkProgressListener);
HBox bootstrapBox = new HBox();
bootstrapBox.setSpacing(10);
bootstrapBox.setAlignment(Pos.CENTER);
bootstrapBox.setPrefHeight(50);
bootstrapBox.getChildren().addAll(bootstrapStateLabel, bootstrapIndicator, bootstrapIcon);
HBox splashP2PNetworkBox = new HBox();
splashP2PNetworkBox.setSpacing(10);
splashP2PNetworkBox.setAlignment(Pos.CENTER);
splashP2PNetworkBox.setPrefHeight(50);
splashP2PNetworkBox.getChildren().addAll(splashP2PNetworkLabel, splashP2PNetworkIndicator, splashP2PNetworkIcon);
// createUpdateBox
updateInfoLabel = new Label();
updateInfoLabel.setTextAlignment(TextAlignment.RIGHT);
updateInfoLabel.textProperty().bind(model.updateInfo);
restartButton = new Button("Restart");
restartButton.setDefaultButton(true);
restartButton.visibleProperty().bind(model.showRestartButton);
restartButton.managedProperty().bind(model.showRestartButton);
restartButton.setOnAction(e -> model.restart());
downloadButton = new Button("Download");
downloadButton.setDefaultButton(true);
downloadButton.visibleProperty().bind(model.showDownloadButton);
downloadButton.managedProperty().bind(model.showDownloadButton);
downloadButtonTooltip = new Tooltip();
downloadButtonTooltip.textProperty().bind(model.newReleaseUrl);
downloadButton.setTooltip(downloadButtonTooltip);
downloadButton.setOnAction(e -> {
try {
Utilities.openWebPage(model.newReleaseUrl.get());
} catch (Exception e1) {
e1.printStackTrace();
log.error(e1.getMessage());
}
});
ImageView updateIcon = new ImageView();
String id = model.updateIconId.get();
if (id != null && !id.equals(""))
updateIcon.setId(id);
updateIconIdListener = (ov, oldValue, newValue) -> {
updateIcon.setId(newValue);
updateIcon.setVisible(true);
updateIcon.setManaged(true);
};
model.updateIconId.addListener(updateIconIdListener);
HBox updateBox = new HBox();
updateBox.setSpacing(10);
updateBox.setAlignment(Pos.CENTER);
updateBox.setPrefHeight(20);
updateBox.getChildren().addAll(updateInfoLabel, restartButton, downloadButton, updateIcon);
vBox.getChildren().addAll(logo, blockchainSyncBox, bootstrapBox, updateBox);
vBox.getChildren().addAll(logo, blockchainSyncBox, splashP2PNetworkBox);
return vBox;
}
private void disposeSplashScreen() {
model.walletServiceErrorMsg.removeListener(walletServiceErrorMsgListener);
model.blockchainSyncIconId.removeListener(blockchainSyncIconIdListener);
model.bootstrapErrorMsg.removeListener(bootstrapErrorMsgListener);
model.bootstrapIconId.removeListener(bootstrapIconIdListener);
model.bootstrapProgress.removeListener(bootstrapProgressListener);
model.updateIconId.removeListener(updateIconIdListener);
model.p2PNetworkErrorMsg.removeListener(splashP2PNetworkErrorMsgListener);
model.p2PNetworkIconId.removeListener(splashP2PNetworkIconIdListener);
model.splashP2PNetworkProgress.removeListener(splashP2PNetworkProgressListener);
blockchainSyncLabel.textProperty().unbind();
blockchainSyncIndicator.progressProperty().unbind();
bootstrapStateLabel.textProperty().unbind();
bootstrapIndicator.progressProperty().unbind();
updateInfoLabel.textProperty().unbind();
restartButton.visibleProperty().unbind();
restartButton.managedProperty().unbind();
downloadButton.visibleProperty().unbind();
downloadButton.managedProperty().unbind();
downloadButtonTooltip.textProperty().unbind();
splashP2PNetworkLabel.textProperty().unbind();
splashP2PNetworkIndicator.progressProperty().unbind();
model.onSplashScreenRemoved();
}
@ -446,37 +392,31 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
setBottomAnchor(versionLabel, 7d);
// P2P
Label bootstrapLabel = new Label();
bootstrapLabel.setId("footer-pane");
setRightAnchor(bootstrapLabel, 100d);
setBottomAnchor(bootstrapLabel, 7d);
bootstrapLabel.textProperty().bind(model.p2pNetworkInfoFooter);
// P2P Network
Label p2PNetworkLabel = new Label();
p2PNetworkLabel.setId("footer-pane");
setRightAnchor(p2PNetworkLabel, 33d);
setBottomAnchor(p2PNetworkLabel, 7d);
p2PNetworkLabel.textProperty().bind(model.p2PNetworkInfo);
ImageView bootstrapIcon = new ImageView();
setRightAnchor(bootstrapIcon, 60d);
setBottomAnchor(bootstrapIcon, 9d);
bootstrapIcon.idProperty().bind(model.bootstrapIconId);
ImageView p2PNetworkIcon = new ImageView();
setRightAnchor(p2PNetworkIcon, 10d);
setBottomAnchor(p2PNetworkIcon, 7d);
p2PNetworkIcon.idProperty().bind(model.p2PNetworkIconId);
Label numPeersLabel = new Label();
numPeersLabel.setId("footer-num-peers");
setRightAnchor(numPeersLabel, 10d);
setBottomAnchor(numPeersLabel, 7d);
numPeersLabel.textProperty().bind(model.numP2PNetworkPeers);
model.bootstrapErrorMsg.addListener((ov, oldValue, newValue) -> {
model.p2PNetworkErrorMsg.addListener((ov, oldValue, newValue) -> {
if (newValue != null) {
bootstrapLabel.setId("splash-error-state-msg");
bootstrapLabel.textProperty().unbind();
bootstrapLabel.setText("Not connected");
p2PNetworkLabel.setId("splash-error-state-msg");
p2PNetworkLabel.textProperty().unbind();
new Popup().error("Connecting to the P2P network failed. \n" + newValue
+ "\nPlease check your internet connection.").show();
} else {
bootstrapLabel.setId("footer-pane");
bootstrapLabel.textProperty().bind(model.p2pNetworkInfoFooter);
p2PNetworkLabel.setId("footer-pane");
p2PNetworkLabel.textProperty().bind(model.p2PNetworkInfo);
}
});
AnchorPane footerContainer = new AnchorPane(separator, blockchainSyncBox, versionLabel, bootstrapLabel, bootstrapIcon, numPeersLabel) {{
AnchorPane footerContainer = new AnchorPane(separator, blockchainSyncBox, versionLabel, p2PNetworkLabel, p2PNetworkIcon) {{
setId("footer-pane");
setMinHeight(30);
setMaxHeight(30);

View file

@ -21,7 +21,6 @@ import com.google.inject.Inject;
import io.bitsquare.alert.Alert;
import io.bitsquare.alert.AlertManager;
import io.bitsquare.app.BitsquareApp;
import io.bitsquare.app.UpdateProcess;
import io.bitsquare.app.Version;
import io.bitsquare.arbitration.ArbitratorManager;
import io.bitsquare.arbitration.Dispute;
@ -51,7 +50,6 @@ import org.bitcoinj.core.*;
import org.bitcoinj.store.BlockStoreException;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.monadic.MonadicBinding;
import org.jetbrains.annotations.NotNull;
import org.reactfx.util.FxTimer;
import org.reactfx.util.Timer;
import org.slf4j.Logger;
@ -80,10 +78,8 @@ class MainViewModel implements ViewModel {
private final OpenOfferManager openOfferManager;
private final DisputeManager disputeManager;
private final Preferences preferences;
private final KeyRing keyRing;
private final AlertManager alertManager;
private final WalletPasswordPopup walletPasswordPopup;
private final UpdateProcess updateProcess;
private final BSFormatter formatter;
// BTC network
@ -97,22 +93,15 @@ class MainViewModel implements ViewModel {
private final StringProperty numBTCPeers = new SimpleStringProperty();
// P2P network
final StringProperty bootstrapInfo = new SimpleStringProperty("Connecting to P2P network...");
final StringProperty p2pNetworkInfoFooter = new SimpleStringProperty("Setting up Tor hidden service...");
final DoubleProperty bootstrapProgress = new SimpleDoubleProperty(-1);
final StringProperty bootstrapErrorMsg = new SimpleStringProperty();
final StringProperty bootstrapIconId = new SimpleStringProperty();
final StringProperty numP2PNetworkPeers = new SimpleStringProperty();
final StringProperty splashP2PNetworkInfo = new SimpleStringProperty();
final StringProperty p2PNetworkInfo = new SimpleStringProperty();
final DoubleProperty splashP2PNetworkProgress = new SimpleDoubleProperty(-1);
final StringProperty p2PNetworkErrorMsg = new SimpleStringProperty();
final StringProperty p2PNetworkIconId = new SimpleStringProperty();
// software update
final StringProperty updateInfo = new SimpleStringProperty();
final String version = "v." + Version.VERSION;
final BooleanProperty showRestartButton = new SimpleBooleanProperty(false);
final BooleanProperty showDownloadButton = new SimpleBooleanProperty(false);
final StringProperty newReleaseUrl = new SimpleStringProperty();
final StringProperty updateIconId = new SimpleStringProperty();
final BooleanProperty showAppScreen = new SimpleBooleanProperty();
final StringProperty numPendingTradesAsString = new SimpleStringProperty();
final BooleanProperty showPendingTradesNotification = new SimpleBooleanProperty();
@ -139,7 +128,7 @@ class MainViewModel implements ViewModel {
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
KeyRing keyRing, User user,
AlertManager alertManager,
WalletPasswordPopup walletPasswordPopup, UpdateProcess updateProcess, BSFormatter formatter) {
WalletPasswordPopup walletPasswordPopup, BSFormatter formatter) {
this.user = user;
log.debug("in");
this.walletService = walletService;
@ -150,16 +139,12 @@ class MainViewModel implements ViewModel {
this.openOfferManager = openOfferManager;
this.disputeManager = disputeManager;
this.preferences = preferences;
this.keyRing = keyRing;
this.alertManager = alertManager;
this.walletPasswordPopup = walletPasswordPopup;
this.updateProcess = updateProcess;
this.formatter = formatter;
bitcoinNetworkAsString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork());
updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue));
applyUpdateState(updateProcess.state.get());
TxIdTextField.setPreferences(preferences);
TxIdTextField.setWalletService(walletService);
BalanceTextField.setWalletService(walletService);
@ -178,22 +163,14 @@ class MainViewModel implements ViewModel {
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void restart() {
updateProcess.restart();
}
public void initializeAllServices() {
log.trace("initializeAllServices");
p2pNetworkInfoFooter.set("Connecting to tor network...");
BooleanProperty updateProcessDone = initUpdateFx();
BooleanProperty walletInitialized = initBitcoinWallet();
BooleanProperty bootstrapDone = initP2PNetwork();
// need to store it to not get garbage collected
allServicesDone = EasyBind.combine(updateProcessDone, walletInitialized, bootstrapDone,
(a, b, c) -> a.booleanValue() && b.booleanValue() && c.booleanValue());
allServicesDone = EasyBind.combine(walletInitialized, bootstrapDone, (a, b) -> a && b);
allServicesDone.subscribe((observable, oldValue, newValue) -> {
if (newValue)
onAllServicesInitialized();
@ -206,37 +183,41 @@ class MainViewModel implements ViewModel {
///////////////////////////////////////////////////////////////////////////////////////////
private BooleanProperty initP2PNetwork() {
final BooleanProperty p2pNetworkReady = new SimpleBooleanProperty();
final BooleanProperty initialDataReady = new SimpleBooleanProperty();
splashP2PNetworkInfo.set("Connecting to Tor network...");
p2PService.start(new P2PServiceListener() {
@Override
public void onTorNodeReady() {
p2pNetworkInfoFooter.set("Tor node created.");
}
@Override
public void onRequestingDataCompleted() {
p2pNetworkInfoFooter.set("Data received from peer.");
p2pNetworkReady.set(true);
}
@Override
public void onFirstPeerAuthenticated() {
p2pNetworkInfoFooter.set("Authenticated in P2P network.");
splashP2PNetworkInfo.set("Publishing Tor Hidden Service...");
p2PNetworkIconId.set("image-connection-tor");
}
@Override
public void onHiddenServicePublished() {
p2pNetworkInfoFooter.set("Tor hidden service available.");
splashP2PNetworkInfo.set("Authenticating to a seed node...");
}
@Override
public void onRequestingDataCompleted() {
p2PNetworkInfo.set("Publishing Tor Hidden Service...");
initialDataReady.set(true);
}
@Override
public void onFirstPeerAuthenticated() {
updateP2pNetworkInfo();
splashP2PNetworkProgress.set(1);
}
@Override
public void onSetupFailed(Throwable throwable) {
bootstrapErrorMsg.set("Error at starting P2P network. " + throwable.getMessage());
bootstrapInfo.set("Connecting to the P2P network failed.");
bootstrapProgress.set(0);
p2PNetworkErrorMsg.set("Connecting to the P2P network failed. " + throwable.getMessage());
splashP2PNetworkProgress.set(0);
}
});
return p2pNetworkReady;
return initialDataReady;
}
private BooleanProperty initBitcoinWallet() {
@ -281,17 +262,6 @@ class MainViewModel implements ViewModel {
return walletInitialized;
}
@NotNull
private BooleanProperty initUpdateFx() {
updateProcess.init();
final BooleanProperty updateProcessDone = new SimpleBooleanProperty();
updateProcess.setResultHandler(() -> {
log.trace("updateProcess completed");
updateProcessDone.set(true);
});
return updateProcessDone;
}
private void onAllServicesInitialized() {
log.trace("onAllServicesInitialized");
@ -371,10 +341,17 @@ class MainViewModel implements ViewModel {
new TacPopup().url(WebViewPopup.getLocalUrl("tac.html")).onAgree(() -> preferences.setTacAccepted(true)).show();
// update nr of peers in footer
p2PService.numAuthenticatedPeers.addListener((observable, oldValue, newValue) -> updateP2pNetworkInfo());
// now show app
showAppScreen.set(true);
}
private void updateP2pNetworkInfo() {
p2PNetworkInfo.set("Nr. of authenticated connections: " + p2PService.numAuthenticatedPeers.get());
}
private void displayAlertIfPresent(Alert alert) {
boolean alreadyDisplayed = alert != null && alert.equals(user.getDisplayedAlert());
user.setDisplayedAlert(alert);
@ -436,74 +413,6 @@ class MainViewModel implements ViewModel {
// Apply states
///////////////////////////////////////////////////////////////////////////////////////////
private void applyUpdateState(UpdateProcess.State state) {
switch (state) {
case INIT:
updateInfo.set("");
updateIconId.set(null);
break;
case CHECK_FOR_UPDATES:
updateInfo.set("Check for updates...");
updateIconId.set("image-update-in-progress");
break;
case UPDATE_AVAILABLE:
updateInfo.set("New update available. Please restart!");
updateIconId.set("image-update-available");
showRestartButton.set(true);
break;
case UP_TO_DATE:
updateInfo.set("Software is up to date. Version: " + Version.VERSION);
updateIconId.set("image-update-up-to-date");
break;
case NEW_RELEASE:
updateInfo.set("A new release is available.");
updateIconId.set("image-update-available");
newReleaseUrl.set(updateProcess.getReleaseUrl());
showDownloadButton.setValue(true);
break;
case FAILURE:
updateInfo.set("Check for updates failed.");
updateIconId.set("image-update-failed");
break;
}
}
/* private void setBootstrapState(TomP2PNetworkInfo.State state) {
switch (state) {
case DISCOVERY_DIRECT_SUCCEEDED:
bootstrapIconId.set("image-connection-direct");
bootstrapInfoFooter.set("Direct connection");
break;
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
bootstrapIconId.set("image-connection-nat");
bootstrapInfoFooter.set("Connected with port forwarding");
break;
case RELAY_SUCCEEDED:
bootstrapIconId.set("image-connection-relay");
bootstrapInfoFooter.set("Connected with relay node");
break;
default:
break;
}
switch (state) {
case DISCOVERY_DIRECT_SUCCEEDED:
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
case RELAY_SUCCEEDED:
bootstrapInfo.set(state.getMessage());
bootstrapProgress.set(-1);
break;
case BOOT_STRAP_SUCCEEDED:
bootstrapProgress.set(1);
break;
default:
bootstrapProgress.set(-1);
break;
}
}*/
private void applyTradePeriodState() {
updateTradePeriodState();
tradeWalletService.addBlockChainListener(new BlockChainListener() {

View file

@ -62,31 +62,20 @@
</GridPane.margin>
</TitledGroupBg>
<Label text="P2P network connection:" GridPane.rowIndex="3">
<Label text="My onion address:" GridPane.rowIndex="3">
<GridPane.margin>
<Insets top="50.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="connectionType" GridPane.rowIndex="3" GridPane.columnIndex="1"
<TextField fx:id="onionAddress" GridPane.rowIndex="3" GridPane.columnIndex="1"
mouseTransparent="true" focusTraversable="false">
<GridPane.margin>
<Insets top="50.0"/>
</GridPane.margin>
</TextField>
<Label text="Use UPnP:" GridPane.rowIndex="4"/>
<CheckBox fx:id="useUPnP" onAction="#onSelectUPnP" GridPane.rowIndex="4" GridPane.columnIndex="1"/>
<Label text="P2P network connected peers:" GridPane.rowIndex="5"/>
<TextField fx:id="connectedPeersP2P" GridPane.rowIndex="5" GridPane.columnIndex="1"
mouseTransparent="true" focusTraversable="false"/>
<Label text="My external visible P2P network address:" GridPane.rowIndex="6"/>
<TextField fx:id="nodeAddress" GridPane.rowIndex="6" GridPane.columnIndex="1"
mouseTransparent="true" focusTraversable="false"/>
<Label text="P2P seed node addresses:" GridPane.rowIndex="7" GridPane.valignment="TOP"/>
<TextArea fx:id="seedNodeNodeAddress" GridPane.rowIndex="7" GridPane.columnIndex="1"
<Label text="Authenticated peers:" GridPane.rowIndex="5"/>
<TextArea fx:id="authenticatedPeersTextArea" GridPane.rowIndex="7" GridPane.columnIndex="1"
mouseTransparent="true" focusTraversable="false"/>
<columnConstraints>

View file

@ -21,50 +21,60 @@ import io.bitsquare.app.BitsquareApp;
import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.btc.WalletService;
import io.bitsquare.common.UserThread;
import io.bitsquare.gui.common.model.Activatable;
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.common.view.InitializableView;
import io.bitsquare.gui.popups.Popup;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.p2p.Address;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener;
import io.bitsquare.p2p.network.TorNetworkNode;
import io.bitsquare.p2p.seed.SeedNodesRepository;
import io.bitsquare.user.Preferences;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javax.inject.Inject;
import java.util.Set;
import static javafx.beans.binding.Bindings.createStringBinding;
@FxmlView
public class NetworkSettingsView extends InitializableView {
public class NetworkSettingsView extends ActivatableViewAndModel<GridPane, Activatable> {
private final String bitcoinNetworkString;
private final WalletService walletService;
private final SeedNodesRepository bootstrapNodes;
private final Preferences preferences;
private final P2PService p2PService;
@FXML
TextField bitcoinNetwork, connectionType, nodeAddress, connectedPeersBTC, connectedPeersP2P;
@FXML
CheckBox useUPnP;
TextField bitcoinNetwork, onionAddress, connectedPeersBTC;
@FXML
ComboBox<BitcoinNetwork> netWorkComboBox;
@FXML
TextArea seedNodeNodeAddress;
TextArea authenticatedPeersTextArea;
private P2PServiceListener p2PServiceListener;
private ChangeListener<Number> numAuthenticatedPeersChangeListener;
private Set<Address> seedNodeAddresses;
@Inject
public NetworkSettingsView(WalletService walletService, P2PService p2PService, SeedNodesRepository bootstrapNodes, Preferences preferences, BSFormatter
public NetworkSettingsView(WalletService walletService, P2PService p2PService, SeedNodesRepository seedNodesRepository, Preferences preferences, BSFormatter
formatter) {
this.walletService = walletService;
this.bootstrapNodes = bootstrapNodes;
this.preferences = preferences;
this.bitcoinNetworkString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork());
this.p2PService = p2PService;
if (p2PService.getNetworkNode() instanceof TorNetworkNode)
this.seedNodeAddresses = seedNodesRepository.getTorSeedNodeAddresses();
else
this.seedNodeAddresses = seedNodesRepository.getLocalhostSeedNodeAddresses();
}
public void initialize() {
@ -72,29 +82,64 @@ public class NetworkSettingsView extends InitializableView {
connectedPeersBTC.textProperty().bind(createStringBinding(() -> String.valueOf(walletService.numPeersProperty().get()), walletService
.numPeersProperty()));
/* if (networkService.getNetworkInfo() instanceof TomP2PNetworkInfo) {
TomP2PNetworkInfo networkInfo = (TomP2PNetworkInfo) networkService.getNetworkInfo();
connectionType.setText(networkInfo.getConnectionType().toString());
connectedPeersP2P.textProperty().bind(createStringBinding(() -> String.valueOf(networkInfo.numPeersProperty().get()), networkInfo.numPeersProperty()));
nodeAddress.setText(networkInfo.getClientNodeInfo());
}*/
/*List<NodeSpec> bootstrapNodeSpecs = bootstrapNodes.getBootstrapNodes();
String bootstrapNodesText = bootstrapNodeSpecs.stream().map(e -> e.toString() + "\n").collect(Collectors.toList()).toString()
.replace(", ", "").replace("[", "").replace("\n]", "");
bootstrapNodeAddress.setPrefRowCount(bootstrapNodeSpecs.size());
bootstrapNodeAddress.setText(bootstrapNodesText);*/
useUPnP.setSelected(preferences.getUseUPnP());
netWorkComboBox.setItems(FXCollections.observableArrayList(BitcoinNetwork.values()));
netWorkComboBox.getSelectionModel().select(preferences.getBitcoinNetwork());
netWorkComboBox.setOnAction(e -> onSelectNetwork());
}
@FXML
void onSelectUPnP() {
preferences.setUseUPnP(useUPnP.isSelected());
@Override
public void activate() {
Address address = p2PService.getAddress();
if (address == null) {
p2PServiceListener = new P2PServiceListener() {
@Override
public void onRequestingDataCompleted() {
}
@Override
public void onFirstPeerAuthenticated() {
}
@Override
public void onTorNodeReady() {
}
@Override
public void onHiddenServicePublished() {
onionAddress.setText(p2PService.getAddress().getFullAddress());
}
@Override
public void onSetupFailed(Throwable throwable) {
}
};
p2PService.addP2PServiceListener(p2PServiceListener);
} else {
onionAddress.setText(address.getFullAddress());
}
numAuthenticatedPeersChangeListener = (observable, oldValue, newValue) -> updateAuthenticatedPeersTextArea();
p2PService.numAuthenticatedPeers.addListener(numAuthenticatedPeersChangeListener);
updateAuthenticatedPeersTextArea();
}
@Override
public void deactivate() {
if (p2PServiceListener != null)
p2PService.removeP2PServiceListener(p2PServiceListener);
if (numAuthenticatedPeersChangeListener != null)
p2PService.numAuthenticatedPeers.removeListener(numAuthenticatedPeersChangeListener);
}
private void updateAuthenticatedPeersTextArea() {
authenticatedPeersTextArea.clear();
p2PService.getAuthenticatedPeerAddresses().stream().forEach(e -> {
if (authenticatedPeersTextArea.getText().length() > 0)
authenticatedPeersTextArea.appendText("\n");
authenticatedPeersTextArea.appendText(e.getFullAddress());
if (seedNodeAddresses.contains(e))
authenticatedPeersTextArea.appendText(" (Seed node)");
});
}
private void onSelectNetwork() {