From 0c0efd3fe0714868496f392ff7913bfa17494aa4 Mon Sep 17 00:00:00 2001
From: Manfred Karrer <mk@nucleo.io>
Date: Sat, 14 Mar 2015 12:29:23 +0100
Subject: [PATCH] Add timeout handler to UI

---
 .../main/trade/takeoffer/TakeOfferView.java   | 29 +++++++++++++++----
 .../trade/takeoffer/TakeOfferViewModel.java   | 16 ++++++++++
 .../bitsquare/network/tomp2p/TomP2PNode.java  |  1 +
 .../java/io/bitsquare/trade/TradeManager.java |  3 ++
 .../tasks/RespondToTakeOfferRequest.java      |  2 +-
 .../java/io/bitsquare/util/Utilities.java     |  3 +-
 .../resources/i18n/displayStrings.properties  |  2 +-
 core/src/main/resources/logback.xml           | 29 ++++++++++---------
 8 files changed, 63 insertions(+), 22 deletions(-)

diff --git a/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java b/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java
index 8109c923a4..de3055b4f2 100644
--- a/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java
+++ b/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java
@@ -96,6 +96,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
     private final Navigation navigation;
     private final OverlayManager overlayManager;
     private ChangeListener<Offer.State> offerIsAvailableChangeListener;
+    private ChangeListener<String> errorMessageChangeListener;
     private TradeView.CloseHandler closeHandler;
 
     @Inject
@@ -117,6 +118,9 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
     protected void doDeactivate() {
         if (offerIsAvailableChangeListener != null)
             model.offerIsAvailable.removeListener(offerIsAvailableChangeListener);
+
+        if (errorMessageChangeListener != null)
+            model.errorMessage.removeListener(errorMessageChangeListener);
     }
 
     public void initWithData(Direction direction, Coin amount, Offer offer) {
@@ -152,17 +156,22 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
         model.offerIsAvailable.addListener(offerIsAvailableChangeListener);
         handleOfferIsAvailableState(model.offerIsAvailable.get());
 
-        // In case of returning to a canceled or failed take offer request and if trade wallet is sufficient funded we display directly the payment screen
-        if (!model.isTakeOfferButtonDisabled.get()) {
-            showPayFundsScreen();
-            showPaymentInfoScreenButton.setVisible(false);
-        }
+        errorMessageChangeListener = (ov, oldValue, newValue) -> handleErrorMessage(newValue);
+        model.errorMessage.addListener(errorMessageChangeListener);
     }
 
     public void setCloseHandler(TradeView.CloseHandler closeHandler) {
         this.closeHandler = closeHandler;
     }
 
+
+    private void handleErrorMessage(String errorMessage) {
+        if (errorMessage != null)
+            Popups.openErrorPopup("An error occurred", errorMessage);
+
+        model.errorMessage.set(null);
+    }
+
     private void handleOfferIsAvailableState(Offer.State state) {
         switch (state) {
             case UNKNOWN:
@@ -173,8 +182,16 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
                 isOfferAvailableProgressIndicator.setProgress(0);
                 isOfferAvailableProgressIndicator.setVisible(false);
                 isOfferAvailableProgressIndicator.setManaged(false);
-                if (model.isTakeOfferButtonDisabled.get())
+
+                // In case of returning to a canceled or failed take offer request and if trade wallet is sufficient funded we display directly the payment 
+                // screen
+                if (!model.isTakeOfferButtonDisabled.get()) {
+                    showPayFundsScreen();
+                    showPaymentInfoScreenButton.setVisible(false);
+                }
+                else {
                     showPaymentInfoScreenButton.setVisible(true);
+                }
                 break;
             case OFFERER_OFFLINE:
                 Popups.openWarningPopup("You cannot take that offer", "The offerer is offline.");
diff --git a/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewModel.java b/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewModel.java
index 661f8d0d31..8d2609e69c 100644
--- a/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewModel.java
+++ b/core/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewModel.java
@@ -24,6 +24,7 @@ import io.bitsquare.gui.util.validation.InputValidator;
 import io.bitsquare.locale.BSResources;
 import io.bitsquare.offer.Direction;
 import io.bitsquare.offer.Offer;
+import io.bitsquare.util.Utilities;
 import io.bitsquare.viewfx.model.ActivatableWithDataModel;
 import io.bitsquare.viewfx.model.ViewModel;
 
@@ -32,6 +33,7 @@ import org.bitcoinj.core.Coin;
 
 import javax.inject.Inject;
 
+import javafx.animation.AnimationTimer;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleBooleanProperty;
@@ -39,9 +41,13 @@ import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.property.SimpleStringProperty;
 import javafx.beans.property.StringProperty;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import static javafx.beans.binding.Bindings.createStringBinding;
 
 class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> implements ViewModel {
+    private static final Logger log = LoggerFactory.getLogger(TakeOfferViewModel.class);
 
     private String fiatCode;
     private String amountRange;
@@ -73,6 +79,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
     final StringProperty transactionId = new SimpleStringProperty();
     final StringProperty requestTakeOfferErrorMessage = new SimpleStringProperty();
     final StringProperty btcCode = new SimpleStringProperty();
+    final StringProperty errorMessage = new SimpleStringProperty();
 
 
     final BooleanProperty isTakeOfferButtonVisible = new SimpleBooleanProperty(false);
@@ -86,6 +93,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
 
     // Needed for the addressTextField
     final ObjectProperty<Coin> totalToPayAsCoin = new SimpleObjectProperty<>();
+    private AnimationTimer timeoutTimer;
 
 
     @Inject
@@ -144,6 +152,14 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
         isTakeOfferButtonDisabled.set(true);
         isTakeOfferSpinnerVisible.set(true);
 
+        timeoutTimer = Utilities.setTimeout(20000, animationTimer -> {
+            errorMessage.set("Timeout reached. Maybe there are connection problems. Please try again later.");
+            updateButtonDisableState();
+            isTakeOfferSpinnerVisible.set(false);
+            return null;
+        });
+        timeoutTimer.start();
+
         dataModel.takeOffer();
     }
 
diff --git a/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java b/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java
index e625fed1e3..283663b93b 100644
--- a/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java
+++ b/core/src/main/java/io/bitsquare/network/tomp2p/TomP2PNode.java
@@ -301,6 +301,7 @@ public class TomP2PNode implements ClientNode {
             else {
                 throw new RuntimeException("Received msg from myself. That must never happen.");
             }
+
             return true;
         });
     }
diff --git a/core/src/main/java/io/bitsquare/trade/TradeManager.java b/core/src/main/java/io/bitsquare/trade/TradeManager.java
index 9eed40c5e9..2c0025dc8c 100644
--- a/core/src/main/java/io/bitsquare/trade/TradeManager.java
+++ b/core/src/main/java/io/bitsquare/trade/TradeManager.java
@@ -359,6 +359,9 @@ public class TradeManager {
                 signatureService,
                 user);
 
+        if (pendingTrades.containsKey(openOffer.getId()))
+            model.setTrade(pendingTrades.get(openOffer.getId()));
+
         openOffer.stateProperty().addListener((ov, oldValue, newValue) -> {
             log.debug("openOffer state = " + newValue);
             switch (newValue) {
diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RespondToTakeOfferRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RespondToTakeOfferRequest.java
index c28c84887c..3a80bcb9bb 100644
--- a/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RespondToTakeOfferRequest.java
+++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/RespondToTakeOfferRequest.java
@@ -41,9 +41,9 @@ public class RespondToTakeOfferRequest extends Task<BuyerAsOffererModel> {
         offerIsAvailable = model.getOpenOffer().getState() == OpenOffer.State.OPEN;
 
         if (offerIsAvailable) {
-            model.getOpenOffer().setState(OpenOffer.State.OFFER_ACCEPTED);
             Trade trade = new Trade(model.getOpenOffer().getOffer());
             model.setTrade(trade);
+            model.getOpenOffer().setState(OpenOffer.State.OFFER_ACCEPTED);
         }
         else {
             log.info("Received take offer request but the offer not marked as open anymore.");
diff --git a/core/src/main/java/io/bitsquare/util/Utilities.java b/core/src/main/java/io/bitsquare/util/Utilities.java
index 2ab98d42d2..e55c2fdd52 100644
--- a/core/src/main/java/io/bitsquare/util/Utilities.java
+++ b/core/src/main/java/io/bitsquare/util/Utilities.java
@@ -36,6 +36,7 @@ import java.net.URI;
 import java.util.function.Function;
 
 import javafx.animation.AnimationTimer;
+import javafx.application.Platform;
 import javafx.scene.input.*;
 
 import org.slf4j.Logger;
@@ -209,7 +210,7 @@ public class Utilities {
             @Override
             public void handle(long arg0) {
                 if (System.currentTimeMillis() > delay + lastTimeStamp) {
-                    callback.apply(this);
+                    Platform.runLater(() -> callback.apply(this));
                     this.stop();
                 }
             }
diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties
index c6513ee603..f25ed85961 100644
--- a/core/src/main/resources/i18n/displayStrings.properties
+++ b/core/src/main/resources/i18n/displayStrings.properties
@@ -111,7 +111,7 @@ takeOffer.fundsBox.total=Total:
 takeOffer.fundsBox.showAdvanced=Show advanced settings
 takeOffer.fundsBox.hideAdvanced=Hide advanced settings
 takeOffer.fundsBox.takeOffer=Take offer
-takeOffer.fundsBox.takeOfferSpinnerInfo=Deposit payment is in progress...
+takeOffer.fundsBox.takeOfferSpinnerInfo=Take offer in progress...
 takeOffer.fundsBox.paymentLabel=Bitsquare trade ({0})
 
 takeOffer.advancedBox.title=Advanced settings
diff --git a/core/src/main/resources/logback.xml b/core/src/main/resources/logback.xml
index 0c123b9d56..08baf8845a 100644
--- a/core/src/main/resources/logback.xml
+++ b/core/src/main/resources/logback.xml
@@ -23,35 +23,38 @@
         </encoder>
     </appender>
 
-    <root level="INFO">
+    <root level="WARN">
         <appender-ref ref="CONSOLE_APPENDER"/>
         <appender-ref ref="FILE"/>
     </root>
 
     <logger name="io.bitsquare" level="TRACE"/>
+    <logger name="io.bitsquare.network.tomp2p.BootstrappedPeerBuilder" level="ERROR"/>
+    <logger name="io.bitsquare.gui.util.Profiler" level="ERROR"/>
+    <logger name="io.bitsquare.persistence.Persistence" level="ERROR"/>
+    <logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
+    
+    <logger name="org.bitcoinj" level="ERROR"/>
+    <logger name="net.tomp2p" level="ERROR"/>
+    <logger name="com.vinumeris.updatefx" level="OFF"/>
+    <logger name="io.netty" level="OFF"/>
+    
 
-    <logger name="org.bitcoinj" level="WARN"/>
-    <logger name="net.tomp2p" level="WARN"/>
-    <logger name="com.vinumeris.updatefx" level="INFO"/>
-
-
-    <logger name="net.tomp2p.message.Encoder" level="WARN"/>
+   <!-- <logger name="net.tomp2p.message.Encoder" level="WARN"/>
     <logger name="net.tomp2p.message.Decoder" level="WARN"/>
     <logger name="net.tomp2p.message.MessageHeaderCodec" level="WARN"/>
 
 
     <logger name="io.netty.util" level="WARN"/>
     <logger name="io.netty.channel" level="WARN"/>
-    <logger name="io.netty.buffer" level="WARN"/>
+    <logger name="io.netty.buffer" level="WARN"/>-->
 
-    <logger name="io.bitsquare.gui.util.Profiler" level="WARN"/>
-    <logger name="io.bitsquare.persistence.Persistence" level="WARN"/>
-    <logger name="io.bitsquare.locale.BSResources" level="OFF"/>
+   
 
 
-    <logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
+   <!-- <logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
     <logger name="org.bitcoinj.core.AbstractBlockChain" level="WARN"/>
-    <logger name="org.bitcoinj.wallet.DeterministicKeyChain" level="WARN"/>
+    <logger name="org.bitcoinj.wallet.DeterministicKeyChain" level="WARN"/>-->
     <!-- <logger name="io.bitsquare.btc.WalletService" level="WARN"/>-->
 
     <!--