mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-06 22:29:10 -04:00
Add footer with status info
This commit is contained in:
parent
33a539ca52
commit
24d29eaa83
15 changed files with 380 additions and 207 deletions
18
core/pom.xml
18
core/pom.xml
|
@ -13,24 +13,6 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<filtering>false</filtering>
|
|
||||||
<directory>${basedir}/src/main/java</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*.fxml</include>
|
|
||||||
<include>**/*.css</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
<resource>
|
|
||||||
<filtering>false</filtering>
|
|
||||||
<directory>${basedir}/src/main/resources</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*.*</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
|
|
@ -66,6 +66,10 @@ import java.util.stream.Collectors;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import javafx.beans.property.DoubleProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||||
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -87,8 +91,7 @@ public class WalletService {
|
||||||
private final List<TxConfidenceListener> txConfidenceListeners = new CopyOnWriteArrayList<>();
|
private final List<TxConfidenceListener> txConfidenceListeners = new CopyOnWriteArrayList<>();
|
||||||
private final List<BalanceListener> balanceListeners = new CopyOnWriteArrayList<>();
|
private final List<BalanceListener> balanceListeners = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
private final ObservableDownloadListener downloadListener = new ObservableDownloadListener();
|
private final DownloadListener downloadListener = new DownloadListener();
|
||||||
private final Observable<Double> downloadProgress = downloadListener.getObservable();
|
|
||||||
private final WalletEventListener walletEventListener = new BitsquareWalletEventListener();
|
private final WalletEventListener walletEventListener = new BitsquareWalletEventListener();
|
||||||
|
|
||||||
private RegTestHost regTestHost;
|
private RegTestHost regTestHost;
|
||||||
|
@ -209,7 +212,6 @@ public class WalletService {
|
||||||
walletAppKit.startAsync();
|
walletAppKit.startAsync();
|
||||||
|
|
||||||
return status.timeout(30, TimeUnit.SECONDS);
|
return status.timeout(30, TimeUnit.SECONDS);
|
||||||
//return status.mergeWith(downloadProgress).timeout(30, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWallet() {
|
private void initWallet() {
|
||||||
|
@ -227,8 +229,8 @@ public class WalletService {
|
||||||
walletAppKit.stopAsync();
|
walletAppKit.stopAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Double> getDownloadProgress() {
|
public ReadOnlyDoubleProperty downloadPercentageProperty() {
|
||||||
return downloadProgress;
|
return downloadListener.percentageProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Wallet getWallet() {
|
public Wallet getWallet() {
|
||||||
|
@ -536,24 +538,23 @@ public class WalletService {
|
||||||
// Inner classes
|
// Inner classes
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private static class ObservableDownloadListener extends DownloadProgressTracker {
|
private static class DownloadListener extends DownloadProgressTracker {
|
||||||
|
private final DoubleProperty percentage = new SimpleDoubleProperty(-1);
|
||||||
private final Subject<Double, Double> subject = BehaviorSubject.create(0d);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void progress(double percentage, int blocksLeft, Date date) {
|
protected void progress(double percentage, int blocksLeft, Date date) {
|
||||||
super.progress(percentage, blocksLeft, date);
|
super.progress(percentage, blocksLeft, date);
|
||||||
subject.onNext(percentage);
|
Threading.USER_THREAD.execute(() -> this.percentage.set(percentage / 100d));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doneDownload() {
|
protected void doneDownload() {
|
||||||
super.doneDownload();
|
super.doneDownload();
|
||||||
subject.onCompleted();
|
Threading.USER_THREAD.execute(() -> this.percentage.set(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Double> getObservable() {
|
public ReadOnlyDoubleProperty percentageProperty() {
|
||||||
return subject.asObservable();
|
return percentage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,47 +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.p2p;
|
|
||||||
|
|
||||||
public enum BootstrapState {
|
|
||||||
PEER_CREATION_FAILED,
|
|
||||||
DISCOVERY_STARTED,
|
|
||||||
DISCOVERY_DIRECT_SUCCEEDED,
|
|
||||||
DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED,
|
|
||||||
DISCOVERY_FAILED,
|
|
||||||
DISCOVERY_AUTO_PORT_FORWARDING_STARTED,
|
|
||||||
DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED,
|
|
||||||
DISCOVERY_AUTO_PORT_FORWARDING_FAILED,
|
|
||||||
RELAY_STARTED,
|
|
||||||
RELAY_SUCCEEDED,
|
|
||||||
RELAY_FAILED,
|
|
||||||
BOOT_STRAP_SUCCEEDED,
|
|
||||||
BOOT_STRAP_FAILED;
|
|
||||||
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
BootstrapState() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessage(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,16 +17,18 @@
|
||||||
|
|
||||||
package io.bitsquare.p2p;
|
package io.bitsquare.p2p;
|
||||||
|
|
||||||
|
import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder;
|
||||||
|
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
public interface ClientNode {
|
public interface ClientNode {
|
||||||
ConnectionType getConnectionType();
|
BootstrappedPeerBuilder.ConnectionType getConnectionType();
|
||||||
|
|
||||||
Node getAddress();
|
Node getAddress();
|
||||||
|
|
||||||
Node getBootstrapNodeAddress();
|
Node getBootstrapNodeAddress();
|
||||||
|
|
||||||
Observable<BootstrapState> bootstrap(KeyPair keyPair);
|
Observable<BootstrappedPeerBuilder.State> bootstrap(KeyPair keyPair);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +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.p2p;
|
|
||||||
|
|
||||||
public enum ConnectionType {
|
|
||||||
UNKNOWN, DIRECT, MANUAL_PORT_FORWARDING, AUTO_PORT_FORWARDING, RELAY
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package io.bitsquare.p2p.tomp2p;
|
package io.bitsquare.p2p.tomp2p;
|
||||||
|
|
||||||
import io.bitsquare.p2p.BootstrapState;
|
|
||||||
import io.bitsquare.p2p.Node;
|
import io.bitsquare.p2p.Node;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
@ -34,6 +33,7 @@ import java.security.KeyPair;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
|
||||||
import net.tomp2p.connection.Bindings;
|
import net.tomp2p.connection.Bindings;
|
||||||
|
@ -76,6 +76,40 @@ public class BootstrappedPeerBuilder {
|
||||||
static final String NETWORK_INTERFACE_UNSPECIFIED = "<unspecified>";
|
static final String NETWORK_INTERFACE_UNSPECIFIED = "<unspecified>";
|
||||||
static final String USE_MANUAL_PORT_FORWARDING_KEY = "node.useManualPortForwarding";
|
static final String USE_MANUAL_PORT_FORWARDING_KEY = "node.useManualPortForwarding";
|
||||||
|
|
||||||
|
public enum ConnectionType {
|
||||||
|
UNDEFINED, DIRECT, MANUAL_PORT_FORWARDING, AUTO_PORT_FORWARDING, RELAY
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum State {
|
||||||
|
UNDEFINED,
|
||||||
|
PEER_CREATION_FAILED,
|
||||||
|
DISCOVERY_STARTED,
|
||||||
|
DISCOVERY_DIRECT_SUCCEEDED,
|
||||||
|
DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED,
|
||||||
|
DISCOVERY_FAILED,
|
||||||
|
DISCOVERY_AUTO_PORT_FORWARDING_STARTED,
|
||||||
|
DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED,
|
||||||
|
DISCOVERY_AUTO_PORT_FORWARDING_FAILED,
|
||||||
|
RELAY_STARTED,
|
||||||
|
RELAY_SUCCEEDED,
|
||||||
|
RELAY_FAILED,
|
||||||
|
BOOT_STRAP_SUCCEEDED,
|
||||||
|
BOOT_STRAP_FAILED;
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
State() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private KeyPair keyPair;
|
private KeyPair keyPair;
|
||||||
private final int port;
|
private final int port;
|
||||||
private final boolean useManualPortForwarding;
|
private final boolean useManualPortForwarding;
|
||||||
|
@ -84,7 +118,8 @@ public class BootstrappedPeerBuilder {
|
||||||
|
|
||||||
private final SettableFuture<PeerDHT> settableFuture = SettableFuture.create();
|
private final SettableFuture<PeerDHT> settableFuture = SettableFuture.create();
|
||||||
|
|
||||||
private final ObjectProperty<BootstrapState> bootstrapState = new SimpleObjectProperty<>();
|
private final ObjectProperty<State> state = new SimpleObjectProperty<>(State.UNDEFINED);
|
||||||
|
private final ObjectProperty<ConnectionType> connectionType = new SimpleObjectProperty<>(ConnectionType.UNDEFINED);
|
||||||
|
|
||||||
private Peer peer;
|
private Peer peer;
|
||||||
private PeerDHT peerDHT;
|
private PeerDHT peerDHT;
|
||||||
|
@ -175,7 +210,7 @@ public class BootstrappedPeerBuilder {
|
||||||
|
|
||||||
discoverExternalAddress();
|
discoverExternalAddress();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
handleError(BootstrapState.PEER_CREATION_FAILED, "Cannot create a peer with port: " +
|
handleError(State.PEER_CREATION_FAILED, "Cannot create a peer with port: " +
|
||||||
port + ". Exception: " + e);
|
port + ". Exception: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +237,7 @@ public class BootstrappedPeerBuilder {
|
||||||
|
|
||||||
private void discoverExternalAddress() {
|
private void discoverExternalAddress() {
|
||||||
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
|
FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start();
|
||||||
setState(BootstrapState.DISCOVERY_STARTED, "Starting discovery...");
|
setState(State.DISCOVERY_STARTED);
|
||||||
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
PeerNAT peerNAT = new PeerBuilderNAT(peer).start();
|
||||||
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover);
|
||||||
FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover, futureNAT);
|
FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover, futureNAT);
|
||||||
|
@ -212,32 +247,35 @@ public class BootstrappedPeerBuilder {
|
||||||
public void operationComplete(BaseFuture futureRelayNAT) throws Exception {
|
public void operationComplete(BaseFuture futureRelayNAT) throws Exception {
|
||||||
if (futureDiscover.isSuccess()) {
|
if (futureDiscover.isSuccess()) {
|
||||||
if (useManualPortForwarding) {
|
if (useManualPortForwarding) {
|
||||||
setState(BootstrapState.DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED,
|
setState(State.DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED,
|
||||||
"Now visible to the Bitsquare network (with manual port forwarding).");
|
"NAT traversal successful with manual port forwarding.");
|
||||||
|
setConnectionType(ConnectionType.MANUAL_PORT_FORWARDING);
|
||||||
bootstrap();
|
bootstrap();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setState(BootstrapState.DISCOVERY_DIRECT_SUCCEEDED, "Now visible to the Bitsquare network.");
|
setState(State.DISCOVERY_DIRECT_SUCCEEDED, "Visible to the network. No NAT traversal needed.");
|
||||||
|
setConnectionType(ConnectionType.DIRECT);
|
||||||
bootstrap();
|
bootstrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setState(BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_STARTED,
|
setState(State.DISCOVERY_AUTO_PORT_FORWARDING_STARTED);
|
||||||
"Configuring automatic port forwarding");
|
|
||||||
if (futureNAT.isSuccess()) {
|
if (futureNAT.isSuccess()) {
|
||||||
setState(BootstrapState.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED,
|
setState(State.DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED,
|
||||||
"Now visible to the Bitsquare network (with automatic port forwarding).");
|
"NAT traversal successful with automatic port forwarding.");
|
||||||
|
setConnectionType(ConnectionType.AUTO_PORT_FORWARDING);
|
||||||
bootstrap();
|
bootstrap();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (futureRelayNAT.isSuccess()) {
|
if (futureRelayNAT.isSuccess()) {
|
||||||
// relay mode succeeded
|
// relay mode succeeded
|
||||||
setState(BootstrapState.RELAY_SUCCEEDED, "Bootstrap using relay was successful.");
|
setState(State.RELAY_SUCCEEDED, "NAT traversal not successful. Using relay mode.");
|
||||||
|
setConnectionType(ConnectionType.RELAY);
|
||||||
bootstrap();
|
bootstrap();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// All attempts failed. Give up...
|
// All attempts failed. Give up...
|
||||||
handleError(BootstrapState.RELAY_FAILED, "Bootstrap using relay has failed " +
|
handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " +
|
||||||
futureRelayNAT.failedReason());
|
futureRelayNAT.failedReason());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,7 +284,7 @@ public class BootstrappedPeerBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
public void exceptionCaught(Throwable t) throws Exception {
|
||||||
handleError(BootstrapState.RELAY_FAILED, "Exception at bootstrap: " + t.getMessage());
|
handleError(State.RELAY_FAILED, "Exception at bootstrap: " + t.getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -263,18 +301,18 @@ public class BootstrappedPeerBuilder {
|
||||||
public void operationComplete(BaseFuture future) throws Exception {
|
public void operationComplete(BaseFuture future) throws Exception {
|
||||||
if (futureBootstrap.isSuccess()) {
|
if (futureBootstrap.isSuccess()) {
|
||||||
log.trace("bootstrap complete");
|
log.trace("bootstrap complete");
|
||||||
setState(BootstrapState.BOOT_STRAP_SUCCEEDED, "Bootstrap using relay was successful.");
|
setState(State.BOOT_STRAP_SUCCEEDED, "Bootstrap was successful.");
|
||||||
settableFuture.set(peerDHT);
|
settableFuture.set(peerDHT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
handleError(BootstrapState.BOOT_STRAP_FAILED, "Bootstrapping failed. " +
|
handleError(State.BOOT_STRAP_FAILED, "Bootstrap failed. " +
|
||||||
futureBootstrap.failedReason());
|
futureBootstrap.failedReason());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(Throwable t) throws Exception {
|
public void exceptionCaught(Throwable t) throws Exception {
|
||||||
handleError(BootstrapState.BOOT_STRAP_FAILED, "Exception at bootstrap: " + t.getMessage());
|
handleError(State.BOOT_STRAP_FAILED, "Exception at bootstrap: " + t.getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -295,25 +333,41 @@ public class BootstrappedPeerBuilder {
|
||||||
return bootstrapNode;
|
return bootstrapNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<BootstrapState> getBootstrapState() {
|
public ConnectionType getConnectionType() {
|
||||||
return bootstrapState;
|
return connectionType.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setState(BootstrapState bootstrapState, String message) {
|
public ReadOnlyObjectProperty<ConnectionType> connectionTypeProperty() {
|
||||||
setState(bootstrapState, message, true);
|
return connectionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setState(BootstrapState bootstrapState, String message, boolean isSuccess) {
|
private void setConnectionType(ConnectionType discoveryState) {
|
||||||
|
this.connectionType.set(discoveryState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<State> getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setState(State state) {
|
||||||
|
setState(state, "", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setState(State state, String message) {
|
||||||
|
setState(state, message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setState(State state, String message, boolean isSuccess) {
|
||||||
if (isSuccess)
|
if (isSuccess)
|
||||||
log.info(message);
|
log.info(message);
|
||||||
else
|
else
|
||||||
log.error(message);
|
log.error(message);
|
||||||
|
|
||||||
bootstrapState.setMessage(message);
|
state.setMessage(message);
|
||||||
this.bootstrapState.set(bootstrapState);
|
this.state.set(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleError(BootstrapState state, String errorMessage) {
|
private void handleError(State state, String errorMessage) {
|
||||||
setState(state, errorMessage, false);
|
setState(state, errorMessage, false);
|
||||||
peerDHT.shutdown();
|
peerDHT.shutdown();
|
||||||
settableFuture.setException(new Exception(errorMessage));
|
settableFuture.setException(new Exception(errorMessage));
|
||||||
|
|
|
@ -19,9 +19,7 @@ package io.bitsquare.p2p.tomp2p;
|
||||||
|
|
||||||
import io.bitsquare.BitsquareException;
|
import io.bitsquare.BitsquareException;
|
||||||
import io.bitsquare.common.handlers.ResultHandler;
|
import io.bitsquare.common.handlers.ResultHandler;
|
||||||
import io.bitsquare.p2p.BootstrapState;
|
|
||||||
import io.bitsquare.p2p.ClientNode;
|
import io.bitsquare.p2p.ClientNode;
|
||||||
import io.bitsquare.p2p.ConnectionType;
|
|
||||||
import io.bitsquare.p2p.Node;
|
import io.bitsquare.p2p.Node;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
@ -54,7 +52,7 @@ public class TomP2PNode implements ClientNode {
|
||||||
|
|
||||||
private PeerDHT peerDHT;
|
private PeerDHT peerDHT;
|
||||||
private BootstrappedPeerBuilder bootstrappedPeerBuilder;
|
private BootstrappedPeerBuilder bootstrappedPeerBuilder;
|
||||||
private final Subject<BootstrapState, BootstrapState> bootstrapStateSubject;
|
private final Subject<BootstrappedPeerBuilder.State, BootstrappedPeerBuilder.State> bootstrapStateSubject;
|
||||||
private final List<ResultHandler> resultHandlers = new CopyOnWriteArrayList<>();
|
private final List<ResultHandler> resultHandlers = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,10 +78,10 @@ public class TomP2PNode implements ClientNode {
|
||||||
// Public methods
|
// Public methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Observable<BootstrapState> bootstrap(KeyPair keyPair) {
|
public Observable<BootstrappedPeerBuilder.State> bootstrap(KeyPair keyPair) {
|
||||||
bootstrappedPeerBuilder.setKeyPair(keyPair);
|
bootstrappedPeerBuilder.setKeyPair(keyPair);
|
||||||
|
|
||||||
bootstrappedPeerBuilder.getBootstrapState().addListener((ov, oldValue, newValue) -> {
|
bootstrappedPeerBuilder.getState().addListener((ov, oldValue, newValue) -> {
|
||||||
log.debug("BootstrapState changed " + newValue);
|
log.debug("BootstrapState changed " + newValue);
|
||||||
bootstrapStateSubject.onNext(newValue);
|
bootstrapStateSubject.onNext(newValue);
|
||||||
});
|
});
|
||||||
|
@ -118,20 +116,8 @@ public class TomP2PNode implements ClientNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConnectionType getConnectionType() {
|
public BootstrappedPeerBuilder.ConnectionType getConnectionType() {
|
||||||
BootstrapState bootstrapState = bootstrappedPeerBuilder.getBootstrapState().get();
|
return bootstrappedPeerBuilder.getConnectionType();
|
||||||
switch (bootstrapState) {
|
|
||||||
case DISCOVERY_DIRECT_SUCCEEDED:
|
|
||||||
return ConnectionType.DIRECT;
|
|
||||||
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
|
|
||||||
return ConnectionType.MANUAL_PORT_FORWARDING;
|
|
||||||
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
|
|
||||||
return ConnectionType.AUTO_PORT_FORWARDING;
|
|
||||||
case RELAY_SUCCEEDED:
|
|
||||||
return ConnectionType.RELAY;
|
|
||||||
default:
|
|
||||||
throw new BitsquareException("Invalid bootstrap state: %s", bootstrapState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
package io.bitsquare.msg;
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
import io.bitsquare.p2p.BootstrapNodes;
|
import io.bitsquare.p2p.BootstrapNodes;
|
||||||
import io.bitsquare.p2p.ConnectionType;
|
|
||||||
import io.bitsquare.p2p.Node;
|
import io.bitsquare.p2p.Node;
|
||||||
|
import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder;
|
||||||
import io.bitsquare.util.Repeat;
|
import io.bitsquare.util.Repeat;
|
||||||
import io.bitsquare.util.RepeatRule;
|
import io.bitsquare.util.RepeatRule;
|
||||||
|
|
||||||
|
@ -84,11 +84,11 @@ public class TomP2PTests {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TomP2PTests.class);
|
private static final Logger log = LoggerFactory.getLogger(TomP2PTests.class);
|
||||||
|
|
||||||
// If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN
|
// If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN
|
||||||
private static final ConnectionType FORCED_CONNECTION_TYPE = ConnectionType.RELAY;
|
private static final BootstrappedPeerBuilder.ConnectionType FORCED_CONNECTION_TYPE = BootstrappedPeerBuilder.ConnectionType.RELAY;
|
||||||
|
|
||||||
// Typically you run the bootstrap node in localhost to test direct connection.
|
// Typically you run the bootstrap node in localhost to test direct connection.
|
||||||
// If you have a setup where you are not behind a router you can also use a WAN bootstrap node.
|
// If you have a setup where you are not behind a router you can also use a WAN bootstrap node.
|
||||||
private static final Node BOOTSTRAP_NODE = (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) ?
|
private static final Node BOOTSTRAP_NODE = (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.DIRECT) ?
|
||||||
BootstrapNodes.LOCALHOST : Node.at("digitalocean1.dev.bitsquare.io", "188.226.179.109", 7367);
|
BootstrapNodes.LOCALHOST : Node.at("digitalocean1.dev.bitsquare.io", "188.226.179.109", 7367);
|
||||||
|
|
||||||
private static final PeerAddress BOOTSTRAP_NODE_ADDRESS;
|
private static final PeerAddress BOOTSTRAP_NODE_ADDRESS;
|
||||||
|
@ -111,7 +111,7 @@ public class TomP2PTests {
|
||||||
private PeerDHT peer2DHT;
|
private PeerDHT peer2DHT;
|
||||||
private int client1Port;
|
private int client1Port;
|
||||||
private int client2Port;
|
private int client2Port;
|
||||||
private ConnectionType resolvedConnectionType;
|
private BootstrappedPeerBuilder.ConnectionType resolvedConnectionType;
|
||||||
public @Rule RepeatRule repeatRule = new RepeatRule();
|
public @Rule RepeatRule repeatRule = new RepeatRule();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -135,7 +135,7 @@ public class TomP2PTests {
|
||||||
@Test
|
@Test
|
||||||
@Repeat(STRESS_TEST_COUNT)
|
@Repeat(STRESS_TEST_COUNT)
|
||||||
public void bootstrapInUnknownMode() throws Exception {
|
public void bootstrapInUnknownMode() throws Exception {
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.UNKNOWN) {
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.UNDEFINED) {
|
||||||
peer = bootstrapInUnknownMode(client1Port);
|
peer = bootstrapInUnknownMode(client1Port);
|
||||||
assertNotNull(peer);
|
assertNotNull(peer);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ public class TomP2PTests {
|
||||||
@Test
|
@Test
|
||||||
@Repeat(STRESS_TEST_COUNT)
|
@Repeat(STRESS_TEST_COUNT)
|
||||||
public void testBootstrapDirectConnection() throws Exception {
|
public void testBootstrapDirectConnection() throws Exception {
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) {
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.DIRECT) {
|
||||||
peer = bootstrapDirectConnection(client1Port);
|
peer = bootstrapDirectConnection(client1Port);
|
||||||
assertNotNull(peer);
|
assertNotNull(peer);
|
||||||
}
|
}
|
||||||
|
@ -153,8 +153,8 @@ public class TomP2PTests {
|
||||||
@Test
|
@Test
|
||||||
@Repeat(STRESS_TEST_COUNT)
|
@Repeat(STRESS_TEST_COUNT)
|
||||||
public void testBootstrapWithPortForwarding() throws Exception {
|
public void testBootstrapWithPortForwarding() throws Exception {
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.AUTO_PORT_FORWARDING ||
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.AUTO_PORT_FORWARDING ||
|
||||||
FORCED_CONNECTION_TYPE == ConnectionType.MANUAL_PORT_FORWARDING) {
|
FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.MANUAL_PORT_FORWARDING) {
|
||||||
peer = bootstrapWithPortForwarding(client2Port);
|
peer = bootstrapWithPortForwarding(client2Port);
|
||||||
assertNotNull(peer);
|
assertNotNull(peer);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ public class TomP2PTests {
|
||||||
@Test
|
@Test
|
||||||
@Repeat(STRESS_TEST_COUNT)
|
@Repeat(STRESS_TEST_COUNT)
|
||||||
public void testBootstrapInRelayMode() throws Exception {
|
public void testBootstrapInRelayMode() throws Exception {
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) {
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.RELAY) {
|
||||||
peer = bootstrapInRelayMode(client1Port);
|
peer = bootstrapInRelayMode(client1Port);
|
||||||
assertNotNull(peer);
|
assertNotNull(peer);
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,8 @@ public class TomP2PTests {
|
||||||
@Test
|
@Test
|
||||||
@Repeat(STRESS_TEST_COUNT)
|
@Repeat(STRESS_TEST_COUNT)
|
||||||
public void testSendDirectBetweenLocalPeers() throws Exception {
|
public void testSendDirectBetweenLocalPeers() throws Exception {
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT || resolvedConnectionType == ConnectionType.DIRECT) {
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.DIRECT || resolvedConnectionType == BootstrappedPeerBuilder.ConnectionType
|
||||||
|
.DIRECT) {
|
||||||
peer1DHT = getDHTPeer(client1Port);
|
peer1DHT = getDHTPeer(client1Port);
|
||||||
peer2DHT = getDHTPeer(client2Port);
|
peer2DHT = getDHTPeer(client2Port);
|
||||||
|
|
||||||
|
@ -594,8 +595,8 @@ public class TomP2PTests {
|
||||||
Number160 peerId = Number160.createHash(UUID.randomUUID().toString());
|
Number160 peerId = Number160.createHash(UUID.randomUUID().toString());
|
||||||
Peer peer = null;
|
Peer peer = null;
|
||||||
try {
|
try {
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.MANUAL_PORT_FORWARDING ||
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.MANUAL_PORT_FORWARDING ||
|
||||||
resolvedConnectionType == ConnectionType.MANUAL_PORT_FORWARDING) {
|
resolvedConnectionType == BootstrappedPeerBuilder.ConnectionType.MANUAL_PORT_FORWARDING) {
|
||||||
peer = new PeerBuilder(peerId).bindings(getBindings())
|
peer = new PeerBuilder(peerId).bindings(getBindings())
|
||||||
.behindFirewall()
|
.behindFirewall()
|
||||||
.tcpPortForwarding(clientPort)
|
.tcpPortForwarding(clientPort)
|
||||||
|
@ -700,22 +701,22 @@ public class TomP2PTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Peer bootstrapInUnknownMode(int clientPort) {
|
private Peer bootstrapInUnknownMode(int clientPort) {
|
||||||
resolvedConnectionType = ConnectionType.DIRECT;
|
resolvedConnectionType = BootstrappedPeerBuilder.ConnectionType.DIRECT;
|
||||||
Peer peer = bootstrapDirectConnection(clientPort);
|
Peer peer = bootstrapDirectConnection(clientPort);
|
||||||
if (peer != null)
|
if (peer != null)
|
||||||
return peer;
|
return peer;
|
||||||
|
|
||||||
resolvedConnectionType = ConnectionType.MANUAL_PORT_FORWARDING;
|
resolvedConnectionType = BootstrappedPeerBuilder.ConnectionType.MANUAL_PORT_FORWARDING;
|
||||||
peer = bootstrapWithPortForwarding(clientPort);
|
peer = bootstrapWithPortForwarding(clientPort);
|
||||||
if (peer != null)
|
if (peer != null)
|
||||||
return peer;
|
return peer;
|
||||||
|
|
||||||
resolvedConnectionType = ConnectionType.AUTO_PORT_FORWARDING;
|
resolvedConnectionType = BootstrappedPeerBuilder.ConnectionType.AUTO_PORT_FORWARDING;
|
||||||
peer = bootstrapWithPortForwarding(clientPort);
|
peer = bootstrapWithPortForwarding(clientPort);
|
||||||
if (peer != null)
|
if (peer != null)
|
||||||
return peer;
|
return peer;
|
||||||
|
|
||||||
resolvedConnectionType = ConnectionType.RELAY;
|
resolvedConnectionType = BootstrappedPeerBuilder.ConnectionType.RELAY;
|
||||||
peer = bootstrapInRelayMode(clientPort);
|
peer = bootstrapInRelayMode(clientPort);
|
||||||
if (peer != null)
|
if (peer != null)
|
||||||
return peer;
|
return peer;
|
||||||
|
@ -728,13 +729,13 @@ public class TomP2PTests {
|
||||||
|
|
||||||
private PeerDHT getDHTPeer(int clientPort) {
|
private PeerDHT getDHTPeer(int clientPort) {
|
||||||
Peer peer;
|
Peer peer;
|
||||||
if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) {
|
if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.DIRECT) {
|
||||||
peer = bootstrapDirectConnection(clientPort);
|
peer = bootstrapDirectConnection(clientPort);
|
||||||
}
|
}
|
||||||
else if (FORCED_CONNECTION_TYPE == ConnectionType.AUTO_PORT_FORWARDING) {
|
else if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.AUTO_PORT_FORWARDING) {
|
||||||
peer = bootstrapWithPortForwarding(clientPort);
|
peer = bootstrapWithPortForwarding(clientPort);
|
||||||
}
|
}
|
||||||
else if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) {
|
else if (FORCED_CONNECTION_TYPE == BootstrappedPeerBuilder.ConnectionType.RELAY) {
|
||||||
peer = bootstrapInRelayMode(clientPort);
|
peer = bootstrapInRelayMode(clientPort);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -39,13 +39,6 @@
|
||||||
<include>**/*.css</include>
|
<include>**/*.css</include>
|
||||||
</includes>
|
</includes>
|
||||||
</resource>
|
</resource>
|
||||||
<resource>
|
|
||||||
<filtering>false</filtering>
|
|
||||||
<directory>${basedir}/src/main/resources</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*.*</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class BitsquareApp extends Application {
|
||||||
CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
|
CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class);
|
||||||
View view = viewLoader.load(MainView.class);
|
View view = viewLoader.load(MainView.class);
|
||||||
|
|
||||||
scene = new Scene((Parent) view.getRoot(), 1000, 620);
|
scene = new Scene((Parent) view.getRoot(), 1000, 650);
|
||||||
scene.getStylesheets().setAll(
|
scene.getStylesheets().setAll(
|
||||||
"/io/bitsquare/gui/bitsquare.css",
|
"/io/bitsquare/gui/bitsquare.css",
|
||||||
"/io/bitsquare/gui/images.css");
|
"/io/bitsquare/gui/images.css");
|
||||||
|
|
|
@ -56,6 +56,21 @@ lower gradient color on tab: dddddd
|
||||||
-fx-background-color: #f4f4f4;
|
-fx-background-color: #f4f4f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#footer-pane {
|
||||||
|
-fx-background-color: #ddd;
|
||||||
|
-fx-font-size: 12;
|
||||||
|
-fx-text-fill: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-pane-line {
|
||||||
|
-fx-background: #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer-bitcoin-network-label {
|
||||||
|
-fx-text-fill: -fx-accent;
|
||||||
|
-fx-font-size: 12;
|
||||||
|
}
|
||||||
|
|
||||||
#headline-label {
|
#headline-label {
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
-fx-font-size: 18;
|
-fx-font-size: 18;
|
||||||
|
|
|
@ -114,7 +114,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
setLeftAnchor(this, 0d);
|
setLeftAnchor(this, 0d);
|
||||||
setRightAnchor(this, 0d);
|
setRightAnchor(this, 0d);
|
||||||
setTopAnchor(this, 60d);
|
setTopAnchor(this, 60d);
|
||||||
setBottomAnchor(this, 25d);
|
setBottomAnchor(this, 10d);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
AnchorPane applicationContainer = new AnchorPane(leftNavPane, rightNavPane, contentContainer) {{
|
AnchorPane applicationContainer = new AnchorPane(leftNavPane, rightNavPane, contentContainer) {{
|
||||||
|
@ -124,6 +124,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
BorderPane baseApplicationContainer = new BorderPane(applicationContainer) {{
|
BorderPane baseApplicationContainer = new BorderPane(applicationContainer) {{
|
||||||
setId("base-content-container");
|
setId("base-content-container");
|
||||||
}};
|
}};
|
||||||
|
baseApplicationContainer.setBottom(createFooter());
|
||||||
|
|
||||||
setupNotificationIcon(portfolioButtonHolder);
|
setupNotificationIcon(portfolioButtonHolder);
|
||||||
|
|
||||||
|
@ -187,15 +188,84 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private VBox createSplashScreen() {
|
private AnchorPane createFooter() {
|
||||||
VBox vBox = new VBox();
|
// BTC
|
||||||
vBox.setAlignment(Pos.CENTER);
|
Label blockchainSyncLabel = new Label();
|
||||||
vBox.setSpacing(0);
|
blockchainSyncLabel.setId("footer-pane");
|
||||||
vBox.setId("splash");
|
blockchainSyncLabel.textProperty().bind(model.blockchainSyncInfoFooter);
|
||||||
|
model.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> {
|
||||||
|
blockchainSyncLabel.setId("splash-error-state-msg");
|
||||||
|
Popups.openErrorPopup("Error", "Connecting to the bitcoin network failed. \n\nReason: " +
|
||||||
|
newValue);
|
||||||
|
});
|
||||||
|
|
||||||
ImageView logo = new ImageView();
|
ProgressBar blockchainSyncIndicator = new ProgressBar(-1);
|
||||||
logo.setId("image-splash-logo");
|
blockchainSyncIndicator.setPrefWidth(120);
|
||||||
|
blockchainSyncIndicator.setMaxHeight(10);
|
||||||
|
blockchainSyncIndicator.progressProperty().bind(model.blockchainSyncProgress);
|
||||||
|
|
||||||
|
Label bitcoinNetworkLabel = new Label();
|
||||||
|
bitcoinNetworkLabel.setId("footer-bitcoin-network-label");
|
||||||
|
bitcoinNetworkLabel.setText(model.bitcoinNetworkAsString);
|
||||||
|
|
||||||
|
model.blockchainSyncProgress.addListener((ov, oldValue, newValue) -> {
|
||||||
|
if ((double) newValue >= 1) {
|
||||||
|
blockchainSyncIndicator.setVisible(false);
|
||||||
|
blockchainSyncIndicator.setManaged(false);
|
||||||
|
blockchainSyncLabel.setVisible(false);
|
||||||
|
blockchainSyncLabel.setManaged(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox blockchainSyncBox = new HBox();
|
||||||
|
blockchainSyncBox.setSpacing(10);
|
||||||
|
blockchainSyncBox.setAlignment(Pos.CENTER);
|
||||||
|
blockchainSyncBox.getChildren().addAll(blockchainSyncLabel, blockchainSyncIndicator, bitcoinNetworkLabel);
|
||||||
|
setLeftAnchor(blockchainSyncBox, 20d);
|
||||||
|
setBottomAnchor(blockchainSyncBox, 7d);
|
||||||
|
|
||||||
|
// version
|
||||||
|
Label versionLabel = new Label();
|
||||||
|
versionLabel.setId("footer-pane");
|
||||||
|
versionLabel.setTextAlignment(TextAlignment.CENTER);
|
||||||
|
versionLabel.setAlignment(Pos.BASELINE_CENTER);
|
||||||
|
versionLabel.setText(model.version);
|
||||||
|
root.widthProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
|
versionLabel.setLayoutX(((double) newValue - versionLabel.getWidth()) / 2);
|
||||||
|
});
|
||||||
|
setBottomAnchor(versionLabel, 7d);
|
||||||
|
|
||||||
|
|
||||||
|
// P2P
|
||||||
|
Label bootstrapLabel = new Label();
|
||||||
|
bootstrapLabel.setId("footer-pane");
|
||||||
|
setRightAnchor(bootstrapLabel, 60d);
|
||||||
|
setBottomAnchor(bootstrapLabel, 7d);
|
||||||
|
bootstrapLabel.textProperty().bind(model.bootstrapInfoFooter);
|
||||||
|
|
||||||
|
ImageView bootstrapIcon = new ImageView();
|
||||||
|
setRightAnchor(bootstrapIcon, 20d);
|
||||||
|
setBottomAnchor(bootstrapIcon, 9d);
|
||||||
|
bootstrapIcon.idProperty().bind(model.bootstrapIconId);
|
||||||
|
|
||||||
|
// line
|
||||||
|
Separator separator = new Separator();
|
||||||
|
separator.setId("footer-pane-line");
|
||||||
|
separator.setPrefHeight(1);
|
||||||
|
setLeftAnchor(separator, 0d);
|
||||||
|
setRightAnchor(separator, 0d);
|
||||||
|
setTopAnchor(separator, 0d);
|
||||||
|
|
||||||
|
AnchorPane footerContainer = new AnchorPane(separator, blockchainSyncBox, versionLabel, bootstrapLabel, bootstrapIcon) {{
|
||||||
|
setId("footer-pane");
|
||||||
|
setMinHeight(30);
|
||||||
|
setMaxHeight(30);
|
||||||
|
}};
|
||||||
|
|
||||||
|
return footerContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HBox createBitcoinInfoBox() {
|
||||||
Label blockchainSyncLabel = new Label();
|
Label blockchainSyncLabel = new Label();
|
||||||
blockchainSyncLabel.textProperty().bind(model.blockchainSyncInfo);
|
blockchainSyncLabel.textProperty().bind(model.blockchainSyncInfo);
|
||||||
model.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> {
|
model.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> {
|
||||||
|
@ -232,7 +302,10 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
blockchainSyncBox.setPrefHeight(50);
|
blockchainSyncBox.setPrefHeight(50);
|
||||||
blockchainSyncBox.getChildren().addAll(blockchainSyncLabel, blockchainSyncIndicator,
|
blockchainSyncBox.getChildren().addAll(blockchainSyncLabel, blockchainSyncIndicator,
|
||||||
blockchainSyncIcon, bitcoinNetworkLabel);
|
blockchainSyncIcon, bitcoinNetworkLabel);
|
||||||
|
return blockchainSyncBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HBox createP2PNetworkBox() {
|
||||||
Label bootstrapStateLabel = new Label();
|
Label bootstrapStateLabel = new Label();
|
||||||
bootstrapStateLabel.setWrapText(true);
|
bootstrapStateLabel.setWrapText(true);
|
||||||
bootstrapStateLabel.setMaxWidth(500);
|
bootstrapStateLabel.setMaxWidth(500);
|
||||||
|
@ -272,8 +345,10 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
bootstrapBox.setAlignment(Pos.CENTER);
|
bootstrapBox.setAlignment(Pos.CENTER);
|
||||||
bootstrapBox.setPrefHeight(50);
|
bootstrapBox.setPrefHeight(50);
|
||||||
bootstrapBox.getChildren().addAll(bootstrapStateLabel, bootstrapIndicator, bootstrapIcon);
|
bootstrapBox.getChildren().addAll(bootstrapStateLabel, bootstrapIndicator, bootstrapIcon);
|
||||||
|
return bootstrapBox;
|
||||||
|
}
|
||||||
|
|
||||||
// software update
|
private HBox createUpdateBox() {
|
||||||
Label updateInfoLabel = new Label();
|
Label updateInfoLabel = new Label();
|
||||||
updateInfoLabel.setTextAlignment(TextAlignment.RIGHT);
|
updateInfoLabel.setTextAlignment(TextAlignment.RIGHT);
|
||||||
updateInfoLabel.textProperty().bind(model.updateInfo);
|
updateInfoLabel.textProperty().bind(model.updateInfo);
|
||||||
|
@ -297,8 +372,121 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
updateBox.setAlignment(Pos.CENTER);
|
updateBox.setAlignment(Pos.CENTER);
|
||||||
updateBox.setPrefHeight(20);
|
updateBox.setPrefHeight(20);
|
||||||
updateBox.getChildren().addAll(updateInfoLabel, restartButton, updateIcon);
|
updateBox.getChildren().addAll(updateInfoLabel, restartButton, updateIcon);
|
||||||
|
return updateBox;
|
||||||
|
}
|
||||||
|
|
||||||
vBox.getChildren().addAll(logo, blockchainSyncBox, bootstrapBox, updateBox);
|
private VBox createSplashScreen() {
|
||||||
|
VBox vBox = new VBox();
|
||||||
|
vBox.setAlignment(Pos.CENTER);
|
||||||
|
vBox.setSpacing(0);
|
||||||
|
vBox.setId("splash");
|
||||||
|
|
||||||
|
ImageView logo = new ImageView();
|
||||||
|
logo.setId("image-splash-logo");
|
||||||
|
|
||||||
|
/*Label blockchainSyncLabel = new Label();
|
||||||
|
blockchainSyncLabel.textProperty().bind(model.blockchainSyncInfo);
|
||||||
|
model.walletServiceErrorMsg.addListener((ov, oldValue, newValue) -> {
|
||||||
|
blockchainSyncLabel.setId("splash-error-state-msg");
|
||||||
|
Popups.openErrorPopup("Error", "Connecting to the bitcoin network failed. \n\nReason: " +
|
||||||
|
newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
ProgressBar blockchainSyncIndicator = new ProgressBar(-1);
|
||||||
|
blockchainSyncIndicator.setPrefWidth(120);
|
||||||
|
blockchainSyncIndicator.progressProperty().bind(model.blockchainSyncProgress);
|
||||||
|
|
||||||
|
ImageView blockchainSyncIcon = new ImageView();
|
||||||
|
blockchainSyncIcon.setVisible(false);
|
||||||
|
blockchainSyncIcon.setManaged(false);
|
||||||
|
|
||||||
|
model.blockchainSyncIconId.addListener((ov, oldValue, newValue) -> {
|
||||||
|
blockchainSyncIcon.setId(newValue);
|
||||||
|
blockchainSyncIcon.setVisible(true);
|
||||||
|
blockchainSyncIcon.setManaged(true);
|
||||||
|
|
||||||
|
blockchainSyncIndicator.setVisible(false);
|
||||||
|
blockchainSyncIndicator.setManaged(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
Label bitcoinNetworkLabel = new Label();
|
||||||
|
bitcoinNetworkLabel.setText(model.bitcoinNetworkAsString);
|
||||||
|
bitcoinNetworkLabel.setId("splash-bitcoin-network-label");
|
||||||
|
|
||||||
|
HBox blockchainSyncBox = new HBox();
|
||||||
|
blockchainSyncBox.setSpacing(10);
|
||||||
|
blockchainSyncBox.setAlignment(Pos.CENTER);
|
||||||
|
blockchainSyncBox.setPadding(new Insets(40, 0, 0, 0));
|
||||||
|
blockchainSyncBox.setPrefHeight(50);
|
||||||
|
blockchainSyncBox.getChildren().addAll(blockchainSyncLabel, blockchainSyncIndicator,
|
||||||
|
blockchainSyncIcon, bitcoinNetworkLabel);*/
|
||||||
|
|
||||||
|
/* Label bootstrapStateLabel = new Label();
|
||||||
|
bootstrapStateLabel.setWrapText(true);
|
||||||
|
bootstrapStateLabel.setMaxWidth(500);
|
||||||
|
bootstrapStateLabel.setTextAlignment(TextAlignment.CENTER);
|
||||||
|
bootstrapStateLabel.textProperty().bind(model.bootstrapInfo);
|
||||||
|
|
||||||
|
ProgressIndicator bootstrapIndicator = new ProgressIndicator();
|
||||||
|
bootstrapIndicator.setMaxSize(24, 24);
|
||||||
|
bootstrapIndicator.progressProperty().bind(model.bootstrapProgress);
|
||||||
|
|
||||||
|
model.bootstrapErrorMsg.addListener((ov, oldValue, newValue) -> {
|
||||||
|
bootstrapStateLabel.setId("splash-error-state-msg");
|
||||||
|
bootstrapIndicator.setVisible(false);
|
||||||
|
|
||||||
|
Popups.openErrorPopup("Error", "Connecting to the Bitsquare network failed. \n\nReason: " +
|
||||||
|
model.bootstrapErrorMsg.get());
|
||||||
|
});
|
||||||
|
|
||||||
|
ImageView bootstrapIcon = new ImageView();
|
||||||
|
bootstrapIcon.setVisible(false);
|
||||||
|
bootstrapIcon.setManaged(false);
|
||||||
|
|
||||||
|
model.bootstrapIconId.addListener((ov, oldValue, newValue) -> {
|
||||||
|
bootstrapIcon.setId(newValue);
|
||||||
|
bootstrapIcon.setVisible(true);
|
||||||
|
bootstrapIcon.setManaged(true);
|
||||||
|
});
|
||||||
|
model.bootstrapProgress.addListener((ov, oldValue, newValue) -> {
|
||||||
|
if ((double) newValue >= 1) {
|
||||||
|
bootstrapIndicator.setVisible(false);
|
||||||
|
bootstrapIndicator.setManaged(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox bootstrapBox = new HBox();
|
||||||
|
bootstrapBox.setSpacing(10);
|
||||||
|
bootstrapBox.setAlignment(Pos.CENTER);
|
||||||
|
bootstrapBox.setPrefHeight(50);
|
||||||
|
bootstrapBox.getChildren().addAll(bootstrapStateLabel, bootstrapIndicator, bootstrapIcon);*/
|
||||||
|
|
||||||
|
// software update
|
||||||
|
/* Label updateInfoLabel = new Label();
|
||||||
|
updateInfoLabel.setTextAlignment(TextAlignment.RIGHT);
|
||||||
|
updateInfoLabel.textProperty().bind(model.updateInfo);
|
||||||
|
|
||||||
|
Button restartButton = new Button("Restart");
|
||||||
|
restartButton.setDefaultButton(true);
|
||||||
|
restartButton.visibleProperty().bind(model.showRestartButton);
|
||||||
|
restartButton.managedProperty().bind(model.showRestartButton);
|
||||||
|
restartButton.setOnAction(e -> model.restart());
|
||||||
|
|
||||||
|
ImageView updateIcon = new ImageView();
|
||||||
|
updateIcon.setId(model.updateIconId.get());
|
||||||
|
model.updateIconId.addListener((ov, oldValue, newValue) -> {
|
||||||
|
updateIcon.setId(newValue);
|
||||||
|
updateIcon.setVisible(true);
|
||||||
|
updateIcon.setManaged(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox updateBox = new HBox();
|
||||||
|
updateBox.setSpacing(10);
|
||||||
|
updateBox.setAlignment(Pos.CENTER);
|
||||||
|
updateBox.setPrefHeight(20);
|
||||||
|
updateBox.getChildren().addAll(updateInfoLabel, restartButton, updateIcon);*/
|
||||||
|
|
||||||
|
vBox.getChildren().addAll(logo, createBitcoinInfoBox(), createP2PNetworkBox(), createUpdateBox());
|
||||||
return vBox;
|
return vBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.bitsquare.gui.main;
|
package io.bitsquare.gui.main;
|
||||||
|
|
||||||
import io.bitsquare.app.UpdateProcess;
|
import io.bitsquare.app.UpdateProcess;
|
||||||
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||||
import io.bitsquare.btc.BitcoinNetwork;
|
import io.bitsquare.btc.BitcoinNetwork;
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.btc.WalletService;
|
||||||
|
@ -27,8 +28,8 @@ import io.bitsquare.gui.common.model.ViewModel;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.locale.CountryUtil;
|
import io.bitsquare.locale.CountryUtil;
|
||||||
import io.bitsquare.p2p.BaseP2PService;
|
import io.bitsquare.p2p.BaseP2PService;
|
||||||
import io.bitsquare.p2p.BootstrapState;
|
|
||||||
import io.bitsquare.p2p.ClientNode;
|
import io.bitsquare.p2p.ClientNode;
|
||||||
|
import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.TradeManager;
|
import io.bitsquare.trade.TradeManager;
|
||||||
import io.bitsquare.trade.offer.OpenOfferManager;
|
import io.bitsquare.trade.offer.OpenOfferManager;
|
||||||
|
@ -61,18 +62,22 @@ class MainViewModel implements ViewModel {
|
||||||
|
|
||||||
// BTC network
|
// BTC network
|
||||||
final StringProperty blockchainSyncInfo = new SimpleStringProperty("Initializing");
|
final StringProperty blockchainSyncInfo = new SimpleStringProperty("Initializing");
|
||||||
|
final StringProperty blockchainSyncInfoFooter = new SimpleStringProperty("Initializing");
|
||||||
final DoubleProperty blockchainSyncProgress = new SimpleDoubleProperty(-1);
|
final DoubleProperty blockchainSyncProgress = new SimpleDoubleProperty(-1);
|
||||||
final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
|
final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
|
||||||
final StringProperty blockchainSyncIconId = new SimpleStringProperty();
|
final StringProperty blockchainSyncIconId = new SimpleStringProperty();
|
||||||
|
|
||||||
// P2P network
|
// P2P network
|
||||||
final StringProperty bootstrapInfo = new SimpleStringProperty();
|
final StringProperty bootstrapInfo = new SimpleStringProperty("Connecting to P2P network...");
|
||||||
|
final StringProperty bootstrapInfoFooter = new SimpleStringProperty();
|
||||||
final DoubleProperty bootstrapProgress = new SimpleDoubleProperty(-1);
|
final DoubleProperty bootstrapProgress = new SimpleDoubleProperty(-1);
|
||||||
final StringProperty bootstrapErrorMsg = new SimpleStringProperty();
|
final StringProperty bootstrapErrorMsg = new SimpleStringProperty();
|
||||||
final StringProperty bootstrapIconId = new SimpleStringProperty();
|
final StringProperty bootstrapIconId = new SimpleStringProperty();
|
||||||
|
|
||||||
// software update
|
// software update
|
||||||
final StringProperty updateInfo = new SimpleStringProperty();
|
final StringProperty updateInfo = new SimpleStringProperty();
|
||||||
|
String version = "v." + Version.VERSION;
|
||||||
|
|
||||||
final BooleanProperty showRestartButton = new SimpleBooleanProperty(false);
|
final BooleanProperty showRestartButton = new SimpleBooleanProperty(false);
|
||||||
final StringProperty updateIconId = new SimpleStringProperty();
|
final StringProperty updateIconId = new SimpleStringProperty();
|
||||||
|
|
||||||
|
@ -110,7 +115,7 @@ class MainViewModel implements ViewModel {
|
||||||
this.updateProcess = updateProcess;
|
this.updateProcess = updateProcess;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
|
||||||
bitcoinNetworkAsString = bitcoinNetwork.toString();
|
bitcoinNetworkAsString = formatter.formatBitcoinNetwork(bitcoinNetwork);
|
||||||
|
|
||||||
updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue));
|
updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue));
|
||||||
applyUpdateState(updateProcess.state.get());
|
applyUpdateState(updateProcess.state.get());
|
||||||
|
@ -131,26 +136,22 @@ class MainViewModel implements ViewModel {
|
||||||
public void initBackend() {
|
public void initBackend() {
|
||||||
Platform.runLater(updateProcess::init);
|
Platform.runLater(updateProcess::init);
|
||||||
|
|
||||||
setBitcoinNetworkSyncProgress(-1);
|
walletService.downloadPercentageProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
walletService.getDownloadProgress().subscribe(
|
setBitcoinNetworkSyncProgress((double) newValue);
|
||||||
percentage -> Platform.runLater(() -> {
|
});
|
||||||
if (percentage > 0)
|
setBitcoinNetworkSyncProgress(walletService.downloadPercentageProperty().get());
|
||||||
setBitcoinNetworkSyncProgress(percentage / 100.0);
|
|
||||||
}),
|
|
||||||
error -> log.error(error.toString()),
|
|
||||||
() -> Platform.runLater(() -> setBitcoinNetworkSyncProgress(1.0)));
|
|
||||||
|
|
||||||
// Set executor for all P2PServices
|
// Set executor for all P2PServices
|
||||||
BaseP2PService.setUserThread(Platform::runLater);
|
BaseP2PService.setUserThread(Platform::runLater);
|
||||||
|
|
||||||
Observable<BootstrapState> bootstrapStateAsObservable = clientNode.bootstrap(keyRing.getDhtSignatureKeyPair());
|
Observable<BootstrappedPeerBuilder.State> bootstrapStateAsObservable = clientNode.bootstrap(keyRing.getDhtSignatureKeyPair());
|
||||||
bootstrapStateAsObservable.publish();
|
bootstrapStateAsObservable.publish();
|
||||||
bootstrapStateAsObservable.subscribe(
|
bootstrapStateAsObservable.subscribe(
|
||||||
state -> Platform.runLater(() -> setBootstrapState(state)),
|
state -> Platform.runLater(() -> setBootstrapState(state)),
|
||||||
error -> Platform.runLater(() -> {
|
error -> Platform.runLater(() -> {
|
||||||
log.error(error.toString());
|
log.error(error.toString());
|
||||||
bootstrapErrorMsg.set(error.getMessage());
|
bootstrapErrorMsg.set(error.getMessage());
|
||||||
bootstrapInfo.set("Connecting to the Bitsquare network failed.");
|
bootstrapInfo.set("Connecting to the P2P network failed.");
|
||||||
bootstrapProgress.set(0);
|
bootstrapProgress.set(0);
|
||||||
|
|
||||||
}),
|
}),
|
||||||
|
@ -220,7 +221,7 @@ class MainViewModel implements ViewModel {
|
||||||
private void applyUpdateState(UpdateProcess.State state) {
|
private void applyUpdateState(UpdateProcess.State state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case CHECK_FOR_UPDATES:
|
case CHECK_FOR_UPDATES:
|
||||||
updateInfo.set("Checking for updates...");
|
updateInfo.set("Check for updates...");
|
||||||
updateIconId.set("image-update-in-progress");
|
updateIconId.set("image-update-in-progress");
|
||||||
break;
|
break;
|
||||||
case UPDATE_AVAILABLE:
|
case UPDATE_AVAILABLE:
|
||||||
|
@ -229,30 +230,33 @@ class MainViewModel implements ViewModel {
|
||||||
showRestartButton.set(true);
|
showRestartButton.set(true);
|
||||||
break;
|
break;
|
||||||
case UP_TO_DATE:
|
case UP_TO_DATE:
|
||||||
updateInfo.set("Software is up to date.");
|
updateInfo.set("Software is up to date. Version: " + Version.VERSION);
|
||||||
updateIconId.set("image-update-up-to-date");
|
updateIconId.set("image-update-up-to-date");
|
||||||
break;
|
break;
|
||||||
case FAILURE:
|
case FAILURE:
|
||||||
updateInfo.set(updateProcess.getErrorMessage());
|
log.error(updateProcess.getErrorMessage());
|
||||||
|
updateInfo.set("Check for updates failed. ");
|
||||||
updateIconId.set("image-update-failed");
|
updateIconId.set("image-update-failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBootstrapState(BootstrapState state) {
|
private void setBootstrapState(BootstrappedPeerBuilder.State state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case DISCOVERY_DIRECT_SUCCEEDED:
|
case DISCOVERY_DIRECT_SUCCEEDED:
|
||||||
bootstrapIconId.set("image-connection-direct");
|
bootstrapIconId.set("image-connection-direct");
|
||||||
|
bootstrapInfoFooter.set("Direct connection");
|
||||||
break;
|
break;
|
||||||
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
|
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
|
||||||
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
|
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
|
||||||
bootstrapIconId.set("image-connection-nat");
|
bootstrapIconId.set("image-connection-nat");
|
||||||
|
bootstrapInfoFooter.set("Connected with port forwarding");
|
||||||
break;
|
break;
|
||||||
case RELAY_SUCCEEDED:
|
case RELAY_SUCCEEDED:
|
||||||
bootstrapIconId.set("image-connection-relay");
|
bootstrapIconId.set("image-connection-relay");
|
||||||
|
bootstrapInfoFooter.set("Connected with relay node");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bootstrapIconId.set(null);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,15 +265,13 @@ class MainViewModel implements ViewModel {
|
||||||
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
|
case DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED:
|
||||||
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
|
case DISCOVERY_AUTO_PORT_FORWARDING_SUCCEEDED:
|
||||||
case RELAY_SUCCEEDED:
|
case RELAY_SUCCEEDED:
|
||||||
bootstrapInfo.set("Bootstrapping to P2P network: " + state.getMessage());
|
bootstrapInfo.set(state.getMessage());
|
||||||
bootstrapProgress.set(-1);
|
bootstrapProgress.set(-1);
|
||||||
break;
|
break;
|
||||||
case BOOT_STRAP_SUCCEEDED:
|
case BOOT_STRAP_SUCCEEDED:
|
||||||
bootstrapInfo.set("Successfully connected to P2P network: " + state.getMessage());
|
|
||||||
bootstrapProgress.set(1);
|
bootstrapProgress.set(1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bootstrapInfo.set("Connecting to P2P network: " + state.getMessage());
|
|
||||||
bootstrapProgress.set(-1);
|
bootstrapProgress.set(-1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -278,6 +280,7 @@ class MainViewModel implements ViewModel {
|
||||||
private void setWalletServiceException(Throwable error) {
|
private void setWalletServiceException(Throwable error) {
|
||||||
setBitcoinNetworkSyncProgress(0);
|
setBitcoinNetworkSyncProgress(0);
|
||||||
blockchainSyncInfo.set("Connecting to the bitcoin network failed.");
|
blockchainSyncInfo.set("Connecting to the bitcoin network failed.");
|
||||||
|
blockchainSyncInfoFooter.set("Connection failed.");
|
||||||
if (error instanceof TimeoutException) {
|
if (error instanceof TimeoutException) {
|
||||||
walletServiceErrorMsg.set("Please check your network connection.\n\n" +
|
walletServiceErrorMsg.set("Please check your network connection.\n\n" +
|
||||||
"You must allow outgoing TCP connections to port 18333 for the bitcoin testnet.\n\n" +
|
"You must allow outgoing TCP connections to port 18333 for the bitcoin testnet.\n\n" +
|
||||||
|
@ -332,9 +335,11 @@ class MainViewModel implements ViewModel {
|
||||||
}
|
}
|
||||||
else if (value > 0.0) {
|
else if (value > 0.0) {
|
||||||
blockchainSyncInfo.set("Synchronizing blockchain: " + formatter.formatToPercent(value));
|
blockchainSyncInfo.set("Synchronizing blockchain: " + formatter.formatToPercent(value));
|
||||||
|
blockchainSyncInfoFooter.set("Synchronizing: " + formatter.formatToPercent(value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
blockchainSyncInfo.set("Connecting to the bitcoin network...");
|
blockchainSyncInfo.set("Connecting to the bitcoin network...");
|
||||||
|
blockchainSyncInfoFooter.set("Connecting...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ package io.bitsquare.gui.main.settings.network;
|
||||||
import io.bitsquare.btc.BitcoinNetwork;
|
import io.bitsquare.btc.BitcoinNetwork;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
import io.bitsquare.gui.common.view.InitializableView;
|
import io.bitsquare.gui.common.view.InitializableView;
|
||||||
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.p2p.ClientNode;
|
import io.bitsquare.p2p.ClientNode;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -30,19 +31,19 @@ import javafx.scene.control.*;
|
||||||
@FxmlView
|
@FxmlView
|
||||||
public class NetworkSettingsView extends InitializableView {
|
public class NetworkSettingsView extends InitializableView {
|
||||||
|
|
||||||
private final String bitcoinNetworkValue;
|
private final String bitcoinNetworkString;
|
||||||
private final ClientNode clientNode;
|
private final ClientNode clientNode;
|
||||||
|
|
||||||
@FXML TextField bitcoinNetwork, connectionType, nodeAddress, bootstrapNodeAddress;
|
@FXML TextField bitcoinNetwork, connectionType, nodeAddress, bootstrapNodeAddress;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NetworkSettingsView(BitcoinNetwork bitcoinNetwork, ClientNode clientNode) {
|
public NetworkSettingsView(BitcoinNetwork bitcoinNetwork, ClientNode clientNode, BSFormatter formatter) {
|
||||||
this.bitcoinNetworkValue = bitcoinNetwork.toString();
|
this.bitcoinNetworkString = formatter.formatBitcoinNetwork(bitcoinNetwork);
|
||||||
this.clientNode = clientNode;
|
this.clientNode = clientNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
bitcoinNetwork.setText(bitcoinNetworkValue);
|
bitcoinNetwork.setText(bitcoinNetworkString);
|
||||||
connectionType.setText(clientNode.getConnectionType().toString());
|
connectionType.setText(clientNode.getConnectionType().toString());
|
||||||
nodeAddress.setText(clientNode.getAddress().toString());
|
nodeAddress.setText(clientNode.getAddress().toString());
|
||||||
bootstrapNodeAddress.setText(clientNode.getBootstrapNodeAddress().toString());
|
bootstrapNodeAddress.setText(clientNode.getBootstrapNodeAddress().toString());
|
||||||
|
|
|
@ -19,6 +19,7 @@ package io.bitsquare.gui.util;
|
||||||
|
|
||||||
import io.bitsquare.arbitration.ArbitrationRepository;
|
import io.bitsquare.arbitration.ArbitrationRepository;
|
||||||
import io.bitsquare.arbitration.Arbitrator;
|
import io.bitsquare.arbitration.Arbitrator;
|
||||||
|
import io.bitsquare.btc.BitcoinNetwork;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
import io.bitsquare.locale.Country;
|
import io.bitsquare.locale.Country;
|
||||||
import io.bitsquare.locale.CurrencyUtil;
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
|
@ -363,4 +364,17 @@ public class BSFormatter {
|
||||||
Date unlockDate = new Date(new Date().getTime() + missingBlocks * 10 * 60 * 1000);
|
Date unlockDate = new Date(new Date().getTime() + missingBlocks * 10 * 60 * 1000);
|
||||||
return dateFormatter.format(unlockDate) + " " + timeFormatter.format(unlockDate);
|
return dateFormatter.format(unlockDate) + " " + timeFormatter.format(unlockDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String formatBitcoinNetwork(BitcoinNetwork bitcoinNetwork) {
|
||||||
|
switch (bitcoinNetwork) {
|
||||||
|
case MAINNET:
|
||||||
|
return "Mainnet";
|
||||||
|
case TESTNET:
|
||||||
|
return "Testnet";
|
||||||
|
case REGTEST:
|
||||||
|
return "Regtest";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue