mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-26 00:15:18 -04:00
Add notification popups, Cleanup pending trades view
This commit is contained in:
parent
59e4fc6842
commit
615f5570c3
16 changed files with 694 additions and 852 deletions
|
@ -70,9 +70,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -135,6 +133,8 @@ public class MainViewModel implements ViewModel {
|
||||||
private java.util.Timer numberofBtcPeersTimer;
|
private java.util.Timer numberofBtcPeersTimer;
|
||||||
private java.util.Timer numberofP2PNetworkPeersTimer;
|
private java.util.Timer numberofP2PNetworkPeersTimer;
|
||||||
private Timer startupTimeout;
|
private Timer startupTimeout;
|
||||||
|
private Set<Subscription> tradeStateSubscriptions = new HashSet<>();
|
||||||
|
private Set<Subscription> disputeStateSubscriptions = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -375,13 +375,13 @@ public class MainViewModel implements ViewModel {
|
||||||
|
|
||||||
tradeManager.getTrades().addListener((ListChangeListener<Trade>) change -> {
|
tradeManager.getTrades().addListener((ListChangeListener<Trade>) change -> {
|
||||||
change.next();
|
change.next();
|
||||||
addDisputeStateListeners(change.getAddedSubList());
|
setDisputeStateSubscriptions();
|
||||||
addTradeStateListeners(change.getAddedSubList());
|
setTradeStateSubscriptions();
|
||||||
pendingTradesChanged();
|
pendingTradesChanged();
|
||||||
});
|
});
|
||||||
pendingTradesChanged();
|
pendingTradesChanged();
|
||||||
addDisputeStateListeners(tradeManager.getTrades());
|
setDisputeStateSubscriptions();
|
||||||
addTradeStateListeners(tradeManager.getTrades());
|
setTradeStateSubscriptions();
|
||||||
|
|
||||||
|
|
||||||
// arbitratorManager
|
// arbitratorManager
|
||||||
|
@ -533,7 +533,7 @@ public class MainViewModel implements ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateP2pNetworkInfoWithPeersChanged(int numPeers) {
|
private void updateP2pNetworkInfoWithPeersChanged(int numPeers) {
|
||||||
p2PNetworkInfo.set("Nr. of connections: " + numPeers);
|
p2PNetworkInfo.set("Nr. of P2P network peers: " + numPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayAlertIfPresent(Alert alert) {
|
private void displayAlertIfPresent(Alert alert) {
|
||||||
|
@ -652,8 +652,8 @@ public class MainViewModel implements ViewModel {
|
||||||
|
|
||||||
private void setWalletServiceException(Throwable error) {
|
private void setWalletServiceException(Throwable error) {
|
||||||
setBitcoinNetworkSyncProgress(0);
|
setBitcoinNetworkSyncProgress(0);
|
||||||
btcSplashInfo.set("Nr. of peers: " + numBTCPeers + " / connecting to " + btcNetworkAsString + " failed");
|
btcSplashInfo.set("Nr. of Bitcoin network peers: " + numBTCPeers + " / connecting to " + btcNetworkAsString + " failed");
|
||||||
btcFooterInfo.set("Nr. of eers: " + numBTCPeers + " / connecting to " + btcNetworkAsString + " failed");
|
btcFooterInfo.set(btcSplashInfo.get());
|
||||||
if (error instanceof TimeoutException) {
|
if (error instanceof TimeoutException) {
|
||||||
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
||||||
} else if (error.getCause() instanceof BlockStoreException) {
|
} else if (error.getCause() instanceof BlockStoreException) {
|
||||||
|
@ -684,7 +684,7 @@ public class MainViewModel implements ViewModel {
|
||||||
break;
|
break;
|
||||||
case HALF_REACHED:
|
case HALF_REACHED:
|
||||||
id = "displayHalfTradePeriodOver" + trade.getId();
|
id = "displayHalfTradePeriodOver" + trade.getId();
|
||||||
if (preferences.showAgain(id)) {
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||||
preferences.dontShowAgain(id);
|
preferences.dontShowAgain(id);
|
||||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||||
" has reached the half of the max. allowed trading period and " +
|
" has reached the half of the max. allowed trading period and " +
|
||||||
|
@ -696,7 +696,7 @@ public class MainViewModel implements ViewModel {
|
||||||
break;
|
break;
|
||||||
case TRADE_PERIOD_OVER:
|
case TRADE_PERIOD_OVER:
|
||||||
id = "displayTradePeriodOver" + trade.getId();
|
id = "displayTradePeriodOver" + trade.getId();
|
||||||
if (preferences.showAgain(id)) {
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||||
preferences.dontShowAgain(id);
|
preferences.dontShowAgain(id);
|
||||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||||
" has reached the max. allowed trading period and is " +
|
" has reached the max. allowed trading period and is " +
|
||||||
|
@ -738,71 +738,21 @@ public class MainViewModel implements ViewModel {
|
||||||
showPendingTradesNotification.set(numPendingTrades > 0);
|
showPendingTradesNotification.set(numPendingTrades > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTradeStateListeners(List<? extends Trade> addedTrades) {
|
private void setTradeStateSubscriptions() {
|
||||||
addedTrades.stream().forEach(trade -> {
|
tradeStateSubscriptions.stream().forEach(Subscription::unsubscribe);
|
||||||
|
tradeStateSubscriptions.clear();
|
||||||
|
|
||||||
|
tradeManager.getTrades().stream().forEach(trade -> {
|
||||||
Subscription tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> {
|
Subscription tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> {
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
applyState(trade);
|
applyTradeState(trade);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
tradeStateSubscriptions.add(tradeStateSubscription);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* addedTrades.stream()
|
|
||||||
.forEach(trade -> trade.stateProperty().addListener((observable, oldValue, newValue) -> {
|
|
||||||
String msg = "";
|
|
||||||
log.debug("addTradeStateListeners " + newValue);
|
|
||||||
switch (newValue) {
|
|
||||||
case PREPARATION:
|
|
||||||
case TAKER_FEE_PAID:
|
|
||||||
case DEPOSIT_PUBLISH_REQUESTED:
|
|
||||||
case DEPOSIT_PUBLISHED:
|
|
||||||
case DEPOSIT_SEEN_IN_NETWORK:
|
|
||||||
case DEPOSIT_PUBLISHED_MSG_SENT:
|
|
||||||
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
|
|
||||||
break;
|
|
||||||
case DEPOSIT_CONFIRMED:
|
|
||||||
msg = newValue.name();
|
|
||||||
break;
|
|
||||||
case FIAT_PAYMENT_STARTED:
|
|
||||||
break;
|
|
||||||
case FIAT_PAYMENT_STARTED_MSG_SENT:
|
|
||||||
break;
|
|
||||||
case FIAT_PAYMENT_STARTED_MSG_RECEIVED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FIAT_PAYMENT_RECEIPT:
|
|
||||||
break;
|
|
||||||
case FIAT_PAYMENT_RECEIPT_MSG_SENT:
|
|
||||||
break;
|
|
||||||
case FIAT_PAYMENT_RECEIPT_MSG_RECEIVED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case PAYOUT_TX_SENT:
|
|
||||||
break;
|
|
||||||
case PAYOUT_TX_RECEIVED:
|
|
||||||
break;
|
|
||||||
case PAYOUT_TX_COMMITTED:
|
|
||||||
break;
|
|
||||||
case PAYOUT_BROAD_CASTED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WITHDRAW_COMPLETED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
log.warn("unhandled processState " + newValue);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//new Popup().information(msg).show();
|
private void applyTradeState(Trade trade) {
|
||||||
|
|
||||||
}));*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyState(Trade trade) {
|
|
||||||
Trade.State state = trade.getState();
|
Trade.State state = trade.getState();
|
||||||
log.debug("addTradeStateListeners " + state);
|
log.debug("addTradeStateListeners " + state);
|
||||||
boolean isBtcBuyer = tradeManager.isMyOfferInBtcBuyerRole(trade.getOffer());
|
boolean isBtcBuyer = tradeManager.isMyOfferInBtcBuyerRole(trade.getOffer());
|
||||||
|
@ -818,6 +768,7 @@ public class MainViewModel implements ViewModel {
|
||||||
case DEPOSIT_CONFIRMED:
|
case DEPOSIT_CONFIRMED:
|
||||||
message = "The deposit transaction of your trade has got the first blockchain confirmation.\n" +
|
message = "The deposit transaction of your trade has got the first blockchain confirmation.\n" +
|
||||||
"You have to start the payment to the bitcoin seller now.";
|
"You have to start the payment to the bitcoin seller now.";
|
||||||
|
|
||||||
break;
|
break;
|
||||||
/* case FIAT_PAYMENT_RECEIPT_MSG_RECEIVED:
|
/* case FIAT_PAYMENT_RECEIPT_MSG_RECEIVED:
|
||||||
case PAYOUT_TX_COMMITTED:
|
case PAYOUT_TX_COMMITTED:
|
||||||
|
@ -853,13 +804,13 @@ public class MainViewModel implements ViewModel {
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
//TODO we get that called initially before the navigation is inited
|
//TODO we get that called initially before the navigation is inited
|
||||||
if (isPendingTradesViewCurrentView || currentPath == null) {
|
if (isPendingTradesViewCurrentView || currentPath == null) {
|
||||||
if (preferences.showAgain(id))
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE)
|
||||||
new Popup().headLine(headLine)
|
new Popup().headLine(headLine)
|
||||||
.message(message)
|
.message(message)
|
||||||
.show();
|
.show();
|
||||||
preferences.dontShowAgain(id);
|
preferences.dontShowAgain(id);
|
||||||
} else {
|
} else {
|
||||||
if (preferences.showAgain(id))
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE)
|
||||||
new Popup().headLine(headLine)
|
new Popup().headLine(headLine)
|
||||||
.message(message)
|
.message(message)
|
||||||
.actionButtonText("Go to \"Portfolio/Open trades\"")
|
.actionButtonText("Go to \"Portfolio/Open trades\"")
|
||||||
|
@ -874,9 +825,22 @@ public class MainViewModel implements ViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDisputeStateListeners(List<? extends Trade> addedTrades) {
|
private void setDisputeStateSubscriptions() {
|
||||||
addedTrades.stream().forEach(trade -> trade.disputeStateProperty().addListener((observable, oldValue, newValue) -> {
|
disputeStateSubscriptions.stream().forEach(Subscription::unsubscribe);
|
||||||
switch (newValue) {
|
disputeStateSubscriptions.clear();
|
||||||
|
|
||||||
|
tradeManager.getTrades().stream().forEach(trade -> {
|
||||||
|
Subscription disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), disputeState -> {
|
||||||
|
if (disputeState != null) {
|
||||||
|
applyDisputeState(trade, disputeState);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
disputeStateSubscriptions.add(disputeStateSubscription);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyDisputeState(Trade trade, Trade.DisputeState disputeState) {
|
||||||
|
switch (disputeState) {
|
||||||
case NONE:
|
case NONE:
|
||||||
break;
|
break;
|
||||||
case DISPUTE_REQUESTED:
|
case DISPUTE_REQUESTED:
|
||||||
|
@ -898,15 +862,14 @@ public class MainViewModel implements ViewModel {
|
||||||
new Popup().information("A support ticket for trade with ID " + trade.getShortId() + " has been closed.").show();
|
new Popup().information("A support ticket for trade with ID " + trade.getShortId() + " has been closed.").show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBitcoinNetworkSyncProgress(double value) {
|
private void setBitcoinNetworkSyncProgress(double value) {
|
||||||
btcSyncProgress.set(value);
|
btcSyncProgress.set(value);
|
||||||
String numPeers = "Nr. of peers: " + numBTCPeers;
|
String numPeers = "Nr. of Bitcoin network peers: " + numBTCPeers;
|
||||||
if (value == 1) {
|
if (value == 1) {
|
||||||
btcSplashInfo.set(numPeers + " / synchronized with " + btcNetworkAsString);
|
btcSplashInfo.set(numPeers + " / synchronized with " + btcNetworkAsString);
|
||||||
btcFooterInfo.set(numPeers + " / synchronized with " + btcNetworkAsString);
|
btcFooterInfo.set(btcSplashInfo.get());
|
||||||
btcSplashSyncIconId.set("image-connection-synced");
|
btcSplashSyncIconId.set("image-connection-synced");
|
||||||
stopCheckForBtcSyncStateTimer();
|
stopCheckForBtcSyncStateTimer();
|
||||||
} else if (value > 0.0) {
|
} else if (value > 0.0) {
|
||||||
|
@ -916,7 +879,7 @@ public class MainViewModel implements ViewModel {
|
||||||
stopCheckForBtcSyncStateTimer();
|
stopCheckForBtcSyncStateTimer();
|
||||||
} else if (value == -1) {
|
} else if (value == -1) {
|
||||||
btcSplashInfo.set(numPeers + " / connecting to " + btcNetworkAsString);
|
btcSplashInfo.set(numPeers + " / connecting to " + btcNetworkAsString);
|
||||||
btcFooterInfo.set(numPeers + " / connecting to " + btcNetworkAsString);
|
btcFooterInfo.set(btcSplashInfo.get());
|
||||||
} else {
|
} else {
|
||||||
log.error("Not allowed value at setBitcoinNetworkSyncProgress: " + value);
|
log.error("Not allowed value at setBitcoinNetworkSyncProgress: " + value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.*;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.*;
|
||||||
import javafx.beans.value.ChangeListener;
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
|
||||||
public class BuyerSubView extends TradeSubView {
|
public class BuyerSubView extends TradeSubView {
|
||||||
private TradeWizardItem step1;
|
private TradeWizardItem step1;
|
||||||
|
@ -28,8 +29,6 @@ public class BuyerSubView extends TradeSubView {
|
||||||
private TradeWizardItem step4;
|
private TradeWizardItem step4;
|
||||||
private TradeWizardItem step5;
|
private TradeWizardItem step5;
|
||||||
|
|
||||||
private final ChangeListener<PendingTradesViewModel.BuyerState> stateChangeListener;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor, Initialisation
|
// Constructor, Initialisation
|
||||||
|
@ -37,20 +36,13 @@ public class BuyerSubView extends TradeSubView {
|
||||||
|
|
||||||
public BuyerSubView(PendingTradesViewModel model) {
|
public BuyerSubView(PendingTradesViewModel model) {
|
||||||
super(model);
|
super(model);
|
||||||
stateChangeListener = (ov, oldValue, newValue) -> applyState(newValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
|
viewStateSubscription = EasyBind.subscribe(model.getBuyerState(), this::onViewStateChanged);
|
||||||
super.activate();
|
super.activate();
|
||||||
model.getBuyerState().addListener(stateChangeListener);
|
|
||||||
applyState(model.getBuyerState().get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deactivate() {
|
|
||||||
super.deactivate();
|
|
||||||
model.getBuyerState().removeListener(stateChangeListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,8 +73,11 @@ public class BuyerSubView extends TradeSubView {
|
||||||
// State
|
// State
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void applyState(PendingTradesViewModel.BuyerState state) {
|
@Override
|
||||||
log.debug("applyState " + state);
|
protected void onViewStateChanged(PendingTradesViewModel.State viewState) {
|
||||||
|
Log.traceCall(viewState.toString());
|
||||||
|
if (viewState != null) {
|
||||||
|
PendingTradesViewModel.BuyerState buyerState = (PendingTradesViewModel.BuyerState) viewState;
|
||||||
|
|
||||||
step1.setDisabled();
|
step1.setDisabled();
|
||||||
step2.setDisabled();
|
step2.setDisabled();
|
||||||
|
@ -90,13 +85,8 @@ public class BuyerSubView extends TradeSubView {
|
||||||
step4.setDisabled();
|
step4.setDisabled();
|
||||||
step5.setDisabled();
|
step5.setDisabled();
|
||||||
|
|
||||||
if (tradeStepView != null)
|
switch (buyerState) {
|
||||||
tradeStepView.doDeactivate();
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case UNDEFINED:
|
case UNDEFINED:
|
||||||
contentPane.getChildren().clear();
|
|
||||||
leftVBox.getChildren().clear();
|
|
||||||
break;
|
break;
|
||||||
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
|
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
|
||||||
showItem(step1);
|
showItem(step1);
|
||||||
|
@ -122,23 +112,12 @@ public class BuyerSubView extends TradeSubView {
|
||||||
step3.setCompleted();
|
step3.setCompleted();
|
||||||
step4.setCompleted();
|
step4.setCompleted();
|
||||||
showItem(step5);
|
showItem(step5);
|
||||||
|
|
||||||
BuyerStep5View buyerStep5View = (BuyerStep5View) tradeStepView;
|
|
||||||
buyerStep5View.setBtcTradeAmountLabelText("You have bought:");
|
|
||||||
buyerStep5View.setFiatTradeAmountLabelText("You have paid:");
|
|
||||||
buyerStep5View.setBtcTradeAmountTextFieldText(model.getTradeVolume());
|
|
||||||
buyerStep5View.setFiatTradeAmountTextFieldText(model.getFiatVolume());
|
|
||||||
buyerStep5View.setFeesTextFieldText(model.getTotalFees());
|
|
||||||
buyerStep5View.setSecurityDepositTextFieldText(model.getSecurityDeposit());
|
|
||||||
buyerStep5View.setWithdrawAmountTextFieldText(model.getPayoutAmount());
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log.warn("unhandled buyerState " + state);
|
log.warn("unhandled buyerState " + buyerState);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (tradeStepView != null)
|
|
||||||
tradeStepView.doActivate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,17 @@ import io.bitsquare.gui.main.disputes.DisputesView;
|
||||||
import io.bitsquare.gui.popups.SelectDepositTxPopup;
|
import io.bitsquare.gui.popups.SelectDepositTxPopup;
|
||||||
import io.bitsquare.gui.popups.WalletPasswordPopup;
|
import io.bitsquare.gui.popups.WalletPasswordPopup;
|
||||||
import io.bitsquare.payment.PaymentAccountContractData;
|
import io.bitsquare.payment.PaymentAccountContractData;
|
||||||
import io.bitsquare.trade.*;
|
import io.bitsquare.trade.BuyerTrade;
|
||||||
|
import io.bitsquare.trade.SellerTrade;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.TradeManager;
|
||||||
import io.bitsquare.trade.offer.Offer;
|
import io.bitsquare.trade.offer.Offer;
|
||||||
import io.bitsquare.user.Preferences;
|
import io.bitsquare.user.Preferences;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
@ -48,6 +54,7 @@ import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
import org.spongycastle.crypto.params.KeyParameter;
|
import org.spongycastle.crypto.params.KeyParameter;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -56,24 +63,22 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
public class PendingTradesDataModel extends ActivatableDataModel {
|
public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
private final TradeManager tradeManager;
|
public final TradeManager tradeManager;
|
||||||
private final WalletService walletService;
|
public final WalletService walletService;
|
||||||
private final TradeWalletService tradeWalletService;
|
private final TradeWalletService tradeWalletService;
|
||||||
private final User user;
|
private final User user;
|
||||||
private final KeyRing keyRing;
|
private final KeyRing keyRing;
|
||||||
private final DisputeManager disputeManager;
|
public final DisputeManager disputeManager;
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private final WalletPasswordPopup walletPasswordPopup;
|
private final WalletPasswordPopup walletPasswordPopup;
|
||||||
|
|
||||||
private final ObservableList<PendingTradesListItem> list = FXCollections.observableArrayList();
|
final ObservableList<PendingTradesListItem> list = FXCollections.observableArrayList();
|
||||||
private PendingTradesListItem selectedItem;
|
|
||||||
private final ListChangeListener<Trade> tradesListChangeListener;
|
private final ListChangeListener<Trade> tradesListChangeListener;
|
||||||
private boolean isOfferer;
|
private boolean isOfferer;
|
||||||
|
|
||||||
private final ObjectProperty<Trade> tradeProperty = new SimpleObjectProperty<>();
|
final ObjectProperty<PendingTradesListItem> selectedItemProperty = new SimpleObjectProperty<>();
|
||||||
private final StringProperty txId = new SimpleStringProperty();
|
public final StringProperty txId = new SimpleStringProperty();
|
||||||
private Trade trade;
|
public final Preferences preferences;
|
||||||
private final Preferences preferences;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -108,88 +113,37 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
tradeManager.getTrades().removeListener(tradesListChangeListener);
|
tradeManager.getTrades().removeListener(tradesListChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onListChanged() {
|
|
||||||
Log.traceCall();
|
|
||||||
list.clear();
|
|
||||||
list.addAll(tradeManager.getTrades().stream().map(PendingTradesListItem::new).collect(Collectors.toList()));
|
|
||||||
|
|
||||||
// we sort by date, earliest first
|
|
||||||
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
|
|
||||||
|
|
||||||
// TODO improve selectedItem handling
|
|
||||||
// selectedItem does not get set to null if we dont have the view visible
|
|
||||||
// So if the item gets removed form the list, and a new item is added we need to check if the old
|
|
||||||
// selectedItem is in the new list, if not we know it is an invalid one
|
|
||||||
if (list.size() == 1)
|
|
||||||
onSelectTrade(list.get(0));
|
|
||||||
else if (list.size() > 1 && (selectedItem == null || !list.contains(selectedItem)))
|
|
||||||
onSelectTrade(list.get(0));
|
|
||||||
else if (list.size() == 0)
|
|
||||||
onSelectTrade(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// UI actions
|
// UI actions
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void onSelectTrade(PendingTradesListItem item) {
|
void onSelectItem(PendingTradesListItem item) {
|
||||||
// clean up previous selectedItem
|
doSelectItem(item);
|
||||||
selectedItem = item;
|
|
||||||
|
|
||||||
if (item == null) {
|
|
||||||
trade = null;
|
|
||||||
tradeProperty.set(null);
|
|
||||||
} else {
|
|
||||||
trade = item.getTrade();
|
|
||||||
tradeProperty.set(trade);
|
|
||||||
|
|
||||||
isOfferer = tradeManager.isMyOffer(trade.getOffer());
|
|
||||||
|
|
||||||
if (trade.getDepositTx() != null)
|
|
||||||
txId.set(trade.getDepositTx().getHashAsString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
checkNotNull(trade, "trade must not be null");
|
checkNotNull(getTrade(), "trade must not be null");
|
||||||
checkArgument(trade instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade");
|
checkArgument(getTrade() instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade");
|
||||||
checkArgument(trade.getDisputeState() == Trade.DisputeState.NONE, "Check failed: trade.getDisputeState() == Trade.DisputeState.NONE");
|
checkArgument(getTrade().getDisputeState() == Trade.DisputeState.NONE, "Check failed: trade.getDisputeState() == Trade.DisputeState.NONE");
|
||||||
((BuyerTrade) trade).onFiatPaymentStarted(resultHandler, errorMessageHandler);
|
((BuyerTrade) getTrade()).onFiatPaymentStarted(resultHandler, errorMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onFiatPaymentReceived() {
|
public void onFiatPaymentReceived() {
|
||||||
checkNotNull(trade, "trade must not be null");
|
checkNotNull(getTrade(), "trade must not be null");
|
||||||
if (trade instanceof SellerTrade && trade.getDisputeState() == Trade.DisputeState.NONE)
|
checkArgument(getTrade() instanceof SellerTrade, "Check failed: trade instanceof SellerTrade");
|
||||||
((SellerTrade) trade).onFiatPaymentReceived();
|
if (getTrade().getDisputeState() == Trade.DisputeState.NONE)
|
||||||
|
((SellerTrade) getTrade()).onFiatPaymentReceived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onWithdrawRequest(String toAddress, ResultHandler resultHandler, FaultHandler faultHandler) {
|
public void onWithdrawRequest(String toAddress, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||||
checkNotNull(trade, "trade must not be null");
|
checkNotNull(getTrade(), "trade must not be null");
|
||||||
if (walletService.getWallet().isEncrypted()) {
|
if (walletService.getWallet().isEncrypted()) {
|
||||||
walletPasswordPopup.onAesKey(aesKey -> doWithdrawRequest(toAddress, aesKey, resultHandler, faultHandler)).show();
|
walletPasswordPopup.onAesKey(aesKey -> doWithdrawRequest(toAddress, aesKey, resultHandler, faultHandler)).show();
|
||||||
} else
|
} else
|
||||||
doWithdrawRequest(toAddress, null, resultHandler, faultHandler);
|
doWithdrawRequest(toAddress, null, resultHandler, faultHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doWithdrawRequest(String toAddress, KeyParameter aesKey, ResultHandler resultHandler, FaultHandler faultHandler) {
|
|
||||||
if (toAddress != null && toAddress.length() > 0) {
|
|
||||||
tradeManager.onWithdrawRequest(
|
|
||||||
toAddress,
|
|
||||||
aesKey,
|
|
||||||
trade,
|
|
||||||
() -> {
|
|
||||||
resultHandler.handleResult();
|
|
||||||
},
|
|
||||||
(errorMessage, throwable) -> {
|
|
||||||
log.error(errorMessage);
|
|
||||||
faultHandler.handleFault(errorMessage, throwable);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
faultHandler.handleFault("No receiver address defined", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onOpenDispute() {
|
public void onOpenDispute() {
|
||||||
tryOpenDispute(false);
|
tryOpenDispute(false);
|
||||||
}
|
}
|
||||||
|
@ -198,11 +152,142 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
tryOpenDispute(true);
|
tryOpenDispute(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PendingTradesListItem getSelectedItem() {
|
||||||
|
return selectedItemProperty.get() != null ? selectedItemProperty.get() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Trade getTrade() {
|
||||||
|
return selectedItemProperty.get() != null ? selectedItemProperty.get().getTrade() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Offer getOffer() {
|
||||||
|
return getTrade() != null ? getTrade().getOffer() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isBuyOffer() {
|
||||||
|
return getOffer() != null && getOffer().getDirection() == Offer.Direction.BUY;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isOfferer(Offer offer) {
|
||||||
|
return tradeManager.isMyOffer(offer);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isOfferer() {
|
||||||
|
return isOfferer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Coin getTotalFees() {
|
||||||
|
return FeePolicy.getFixedTxFeeForTrades().add(isOfferer() ? FeePolicy.getCreateOfferFee() : FeePolicy.getTakeOfferFee());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCurrencyCode() {
|
||||||
|
return getOffer() != null ? getOffer().getCurrencyCode() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Offer.Direction getDirection(Offer offer) {
|
||||||
|
isOfferer = tradeManager.isMyOffer(offer);
|
||||||
|
return isOfferer ? offer.getDirection() : offer.getMirroredDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
tradeWalletService.addBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
|
tradeWalletService.removeBlockChainListener(blockChainListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLockTime() {
|
||||||
|
return getTrade() != null ? getTrade().getLockTimeAsBlockHeight() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOpenDisputeTimeAsBlockHeight() {
|
||||||
|
return getTrade() != null ? getTrade().getOpenDisputeTimeAsBlockHeight() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBestChainHeight() {
|
||||||
|
return tradeWalletService.getBestChainHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PaymentAccountContractData getSellersPaymentAccountContractData() {
|
||||||
|
if (getTrade() != null && getTrade().getContract() != null)
|
||||||
|
return getTrade().getContract().getSellerPaymentAccountContractData();
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReference() {
|
||||||
|
return getOffer() != null ? getOffer().getReferenceText() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void onListChanged() {
|
||||||
|
Log.traceCall();
|
||||||
|
list.clear();
|
||||||
|
list.addAll(tradeManager.getTrades().stream().map(PendingTradesListItem::new).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
// we sort by date, earliest first
|
||||||
|
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
|
||||||
|
|
||||||
|
selectBestItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectBestItem() {
|
||||||
|
if (list.size() == 1)
|
||||||
|
doSelectItem(list.get(0));
|
||||||
|
else if (list.size() > 1 && (selectedItemProperty.get() == null || !list.contains(selectedItemProperty.get())))
|
||||||
|
doSelectItem(list.get(0));
|
||||||
|
else if (list.size() == 0)
|
||||||
|
doSelectItem(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doSelectItem(PendingTradesListItem item) {
|
||||||
|
if (item != null) {
|
||||||
|
Trade trade = item.getTrade();
|
||||||
|
isOfferer = tradeManager.isMyOffer(trade.getOffer());
|
||||||
|
if (trade.getDepositTx() != null)
|
||||||
|
txId.set(trade.getDepositTx().getHashAsString());
|
||||||
|
}
|
||||||
|
selectedItemProperty.set(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doWithdrawRequest(String toAddress, KeyParameter aesKey, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||||
|
if (toAddress != null && toAddress.length() > 0) {
|
||||||
|
tradeManager.onWithdrawRequest(
|
||||||
|
toAddress,
|
||||||
|
aesKey,
|
||||||
|
getTrade(),
|
||||||
|
() -> {
|
||||||
|
resultHandler.handleResult();
|
||||||
|
selectBestItem();
|
||||||
|
},
|
||||||
|
(errorMessage, throwable) -> {
|
||||||
|
log.error(errorMessage);
|
||||||
|
faultHandler.handleFault(errorMessage, throwable);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
faultHandler.handleFault("No receiver address defined", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void tryOpenDispute(boolean isSupportTicket) {
|
private void tryOpenDispute(boolean isSupportTicket) {
|
||||||
if (trade != null) {
|
if (getTrade() != null) {
|
||||||
Transaction depositTx = trade.getDepositTx();
|
Transaction depositTx = getTrade().getDepositTx();
|
||||||
if (depositTx != null) {
|
if (depositTx != null) {
|
||||||
doOpenDispute(isSupportTicket, trade.getDepositTx());
|
doOpenDispute(isSupportTicket, getTrade().getDepositTx());
|
||||||
} else {
|
} else {
|
||||||
log.warn("Trade.depositTx is null. We try to find the tx in our wallet.");
|
log.warn("Trade.depositTx is null. We try to find the tx in our wallet.");
|
||||||
List<Transaction> candidates = new ArrayList<>();
|
List<Transaction> candidates = new ArrayList<>();
|
||||||
|
@ -220,21 +305,6 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*transactions.stream().forEach(transaction -> {
|
|
||||||
Coin valueSentFromMe = transaction.getValueSentFromMe(walletService.getWallet());
|
|
||||||
if (!valueSentFromMe.isZero()) {
|
|
||||||
// spending tx
|
|
||||||
for (TransactionOutput transactionOutput : transaction.getOutputs()) {
|
|
||||||
if (!transactionOutput.isMine(walletService.getWallet())) {
|
|
||||||
if (transactionOutput.getScriptPubKey().isPayToScriptHash()) {
|
|
||||||
// MS tx
|
|
||||||
candidates.add(transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
|
|
||||||
if (candidates.size() == 1)
|
if (candidates.size() == 1)
|
||||||
doOpenDispute(isSupportTicket, candidates.get(0));
|
doOpenDispute(isSupportTicket, candidates.get(0));
|
||||||
else if (candidates.size() > 1)
|
else if (candidates.size() > 1)
|
||||||
|
@ -262,12 +332,13 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
} else {
|
} else {
|
||||||
log.warn("depositTx is null");
|
log.warn("depositTx is null");
|
||||||
}
|
}
|
||||||
Transaction payoutTx = trade.getPayoutTx();
|
Transaction payoutTx = getTrade().getPayoutTx();
|
||||||
if (payoutTx != null) {
|
if (payoutTx != null) {
|
||||||
payoutTxSerialized = payoutTx.bitcoinSerialize();
|
payoutTxSerialized = payoutTx.bitcoinSerialize();
|
||||||
payoutTxHashAsString = payoutTx.getHashAsString();
|
payoutTxHashAsString = payoutTx.getHashAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Trade trade = getTrade();
|
||||||
Dispute dispute = new Dispute(disputeManager.getDisputeStorage(),
|
Dispute dispute = new Dispute(disputeManager.getDisputeStorage(),
|
||||||
trade.getId(),
|
trade.getId(),
|
||||||
keyRing.getPubKeyRing().hashCode(), // traderId
|
keyRing.getPubKeyRing().hashCode(), // traderId
|
||||||
|
@ -292,110 +363,5 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||||
disputeManager.sendOpenNewDisputeMessage(dispute);
|
disputeManager.sendOpenNewDisputeMessage(dispute);
|
||||||
navigation.navigateTo(MainView.class, DisputesView.class);
|
navigation.navigateTo(MainView.class, DisputesView.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Getters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ObservableList<PendingTradesListItem> getList() {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isBuyOffer() {
|
|
||||||
return trade.getOffer().getDirection() == Offer.Direction.BUY;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isOfferer(Offer offer) {
|
|
||||||
return tradeManager.isMyOffer(offer);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isOfferer() {
|
|
||||||
return isOfferer;
|
|
||||||
}
|
|
||||||
|
|
||||||
Coin getTotalFees() {
|
|
||||||
return FeePolicy.getFixedTxFeeForTrades().add(isOfferer() ? FeePolicy.getCreateOfferFee() : FeePolicy.getTakeOfferFee());
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTradesListItem getSelectedItem() {
|
|
||||||
return selectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getCurrencyCode() {
|
|
||||||
return trade.getOffer().getCurrencyCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Offer.Direction getDirection(Offer offer) {
|
|
||||||
// gets called earlier than onSelectTrade event handler
|
|
||||||
isOfferer = tradeManager.isMyOffer(offer);
|
|
||||||
return isOfferer ? offer.getDirection() : offer.getMirroredDirection();
|
|
||||||
}
|
|
||||||
|
|
||||||
Coin getPayoutAmount() {
|
|
||||||
return trade.getPayoutAmount();
|
|
||||||
}
|
|
||||||
|
|
||||||
Contract getContract() {
|
|
||||||
return trade.getContract();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Trade getTrade() {
|
|
||||||
return trade;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlyObjectProperty<Trade> getTradeProperty() {
|
|
||||||
return tradeProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlyStringProperty getTxId() {
|
|
||||||
return txId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addBlockChainListener(BlockChainListener blockChainListener) {
|
|
||||||
tradeWalletService.addBlockChainListener(blockChainListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeBlockChainListener(BlockChainListener blockChainListener) {
|
|
||||||
tradeWalletService.removeBlockChainListener(blockChainListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLockTime() {
|
|
||||||
return trade.getLockTimeAsBlockHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getCheckPaymentTimeAsBlockHeight() {
|
|
||||||
return trade.getCheckPaymentTimeAsBlockHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getOpenDisputeTimeAsBlockHeight() {
|
|
||||||
return trade.getOpenDisputeTimeAsBlockHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBestChainHeight() {
|
|
||||||
return tradeWalletService.getBestChainHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PaymentAccountContractData getSellersPaymentAccountContractData() {
|
|
||||||
if (trade.getContract() != null)
|
|
||||||
return trade.getContract().getSellerPaymentAccountContractData();
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getReference() {
|
|
||||||
return trade.getOffer().getReferenceText();
|
|
||||||
}
|
|
||||||
|
|
||||||
public WalletService getWalletService() {
|
|
||||||
return walletService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DisputeManager getDisputeManager() {
|
|
||||||
return disputeManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Preferences getPreferences() {
|
|
||||||
return preferences;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,4 +52,5 @@ public class PendingTradesListItem {
|
||||||
public Fiat getPrice() {
|
public Fiat getPrice() {
|
||||||
return trade.getOffer().getPrice();
|
return trade.getOffer().getPrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
|
@ -24,11 +25,7 @@ import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||||
import io.bitsquare.gui.popups.OpenEmergencyTicketPopup;
|
import io.bitsquare.gui.popups.OpenEmergencyTicketPopup;
|
||||||
import io.bitsquare.gui.popups.TradeDetailsPopup;
|
import io.bitsquare.gui.popups.TradeDetailsPopup;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.trade.Trade;
|
|
||||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
|
||||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
import javafx.collections.ListChangeListener;
|
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
@ -44,6 +41,8 @@ import javafx.util.Callback;
|
||||||
import javafx.util.StringConverter;
|
import javafx.util.StringConverter;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.utils.Fiat;
|
import org.bitcoinj.utils.Fiat;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
import org.fxmisc.easybind.Subscription;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -61,14 +60,12 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||||
@FXML
|
@FXML
|
||||||
TableColumn<PendingTradesListItem, Coin> tradeAmountColumn;
|
TableColumn<PendingTradesListItem, Coin> tradeAmountColumn;
|
||||||
|
|
||||||
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
|
private TradeSubView selectedSubView;
|
||||||
private TradeSubView currentSubView;
|
|
||||||
private ChangeListener<Boolean> appFocusChangeListener;
|
|
||||||
private ReadOnlyBooleanProperty appFocusProperty;
|
|
||||||
private ChangeListener<Trade> currentTradeChangeListener;
|
|
||||||
private EventHandler<KeyEvent> keyEventEventHandler;
|
private EventHandler<KeyEvent> keyEventEventHandler;
|
||||||
private Scene scene;
|
private Scene scene;
|
||||||
private ListChangeListener<PendingTradesListItem> listChangeListener;
|
private Subscription selectedTableItemSubscription;
|
||||||
|
private Subscription selectedItemSubscription;
|
||||||
|
private Subscription appFocusSubscription;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -95,30 +92,6 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||||
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||||
table.setPlaceholder(new Label("No pending trades available"));
|
table.setPlaceholder(new Label("No pending trades available"));
|
||||||
table.setMinHeight(100);
|
table.setMinHeight(100);
|
||||||
selectedItemChangeListener = (ov, oldValue, newValue) -> {
|
|
||||||
model.onSelectTrade(newValue);
|
|
||||||
log.debug("selectedItemChangeListener {} ", newValue);
|
|
||||||
if (newValue != null)
|
|
||||||
setNewSubView(newValue.getTrade());
|
|
||||||
};
|
|
||||||
listChangeListener = c -> updateSelectedItem();
|
|
||||||
|
|
||||||
appFocusChangeListener = (observable, oldValue, newValue) -> {
|
|
||||||
if (newValue && model.getSelectedItem() != null) {
|
|
||||||
// Focus selectedItem from model
|
|
||||||
int index = table.getItems().indexOf(model.getSelectedItem());
|
|
||||||
UserThread.execute(() -> {
|
|
||||||
//TODO app wide focus
|
|
||||||
//table.requestFocus();
|
|
||||||
//UserThread.execute(() -> table.getFocusModel().focus(index));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
currentTradeChangeListener = (observable, oldValue, newValue) -> {
|
|
||||||
log.debug("currentTradeChangeListener {} ", newValue);
|
|
||||||
// setNewSubView(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
// we use a hidden emergency shortcut to open support ticket
|
// we use a hidden emergency shortcut to open support ticket
|
||||||
keyEventEventHandler = event -> {
|
keyEventEventHandler = event -> {
|
||||||
|
@ -129,51 +102,95 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
|
Log.traceCall();
|
||||||
scene = root.getScene();
|
scene = root.getScene();
|
||||||
if (scene != null) {
|
if (scene != null) {
|
||||||
appFocusProperty = scene.getWindow().focusedProperty();
|
|
||||||
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
|
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
|
||||||
|
|
||||||
|
/*appFocusSubscription = EasyBind.subscribe(scene.getWindow().focusedProperty(), isFocused -> {
|
||||||
|
if (isFocused && model.dataModel.selectedItemProperty.get() != null) {
|
||||||
|
// Focus selectedItem from model
|
||||||
|
int index = table.getItems().indexOf(model.dataModel.selectedItemProperty.get());
|
||||||
|
UserThread.execute(() -> {
|
||||||
|
//TODO app wide focus
|
||||||
|
//table.requestFocus();
|
||||||
|
//UserThread.execute(() -> table.getFocusModel().focus(index));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
}
|
||||||
|
table.setItems(model.dataModel.list);
|
||||||
|
|
||||||
|
selectedItemSubscription = EasyBind.subscribe(model.dataModel.selectedItemProperty, selectedItem -> {
|
||||||
|
if (selectedItem != null) {
|
||||||
|
if (selectedSubView != null)
|
||||||
|
selectedSubView.deactivate();
|
||||||
|
|
||||||
|
if (selectedItem.getTrade() != null) {
|
||||||
|
// If we are the offerer the direction is like expected
|
||||||
|
// If we are the taker the direction is mirrored
|
||||||
|
if (model.dataModel.isOfferer())
|
||||||
|
selectedSubView = model.dataModel.isBuyOffer() ? new BuyerSubView(model) : new SellerSubView(model);
|
||||||
|
else
|
||||||
|
selectedSubView = model.dataModel.isBuyOffer() ? new SellerSubView(model) : new BuyerSubView(model);
|
||||||
|
|
||||||
|
selectedSubView.setMinHeight(430);
|
||||||
|
VBox.setVgrow(selectedSubView, Priority.ALWAYS);
|
||||||
|
if (root.getChildren().size() == 1)
|
||||||
|
root.getChildren().add(selectedSubView);
|
||||||
|
else if (root.getChildren().size() == 2)
|
||||||
|
root.getChildren().set(1, selectedSubView);
|
||||||
|
selectedSubView.activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
appFocusProperty.addListener(appFocusChangeListener);
|
updateTableSelection();
|
||||||
model.currentTrade().addListener(currentTradeChangeListener);
|
} else {
|
||||||
//setNewSubView(model.currentTrade().get());
|
removeSelectedSubView();
|
||||||
table.setItems(model.getList());
|
}
|
||||||
table.getSelectionModel().selectedItemProperty().addListener(selectedItemChangeListener);
|
|
||||||
|
|
||||||
if (model.getSelectedItem() == null)
|
model.onSelectedItemChanged(selectedItem);
|
||||||
model.getList().addListener(listChangeListener);
|
});
|
||||||
|
|
||||||
|
selectedTableItemSubscription = EasyBind.subscribe(table.getSelectionModel().selectedItemProperty(),
|
||||||
|
selectedItem -> {
|
||||||
|
if (selectedItem != null && !selectedItem.equals(model.dataModel.selectedItemProperty.get()))
|
||||||
|
model.dataModel.onSelectItem(selectedItem);
|
||||||
|
});
|
||||||
|
|
||||||
updateSelectedItem();
|
updateTableSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deactivate() {
|
protected void deactivate() {
|
||||||
table.getSelectionModel().selectedItemProperty().removeListener(selectedItemChangeListener);
|
selectedItemSubscription.unsubscribe();
|
||||||
|
selectedTableItemSubscription.unsubscribe();
|
||||||
|
if (appFocusSubscription != null)
|
||||||
|
appFocusSubscription.unsubscribe();
|
||||||
|
|
||||||
model.getList().removeListener(listChangeListener);
|
removeSelectedSubView();
|
||||||
|
|
||||||
if (model.currentTrade() != null)
|
|
||||||
model.currentTrade().removeListener(currentTradeChangeListener);
|
|
||||||
|
|
||||||
if (appFocusProperty != null) {
|
|
||||||
appFocusProperty.removeListener(appFocusChangeListener);
|
|
||||||
appFocusProperty = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentSubView != null)
|
|
||||||
currentSubView.deactivate();
|
|
||||||
|
|
||||||
if (scene != null)
|
if (scene != null)
|
||||||
scene.removeEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
|
scene.removeEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSelectedItem() {
|
private void removeSelectedSubView() {
|
||||||
PendingTradesListItem selectedItem = model.getSelectedItem();
|
if (selectedSubView != null) {
|
||||||
if (selectedItem != null) {
|
selectedSubView.deactivate();
|
||||||
|
root.getChildren().remove(selectedSubView);
|
||||||
|
selectedSubView = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void updateTableSelection() {
|
||||||
|
PendingTradesListItem selectedItemFromModel = model.dataModel.selectedItemProperty.get();
|
||||||
|
if (selectedItemFromModel != null) {
|
||||||
// Select and focus selectedItem from model
|
// Select and focus selectedItem from model
|
||||||
int index = table.getItems().indexOf(selectedItem);
|
int index = table.getItems().indexOf(selectedItemFromModel);
|
||||||
UserThread.execute(() -> {
|
UserThread.execute(() -> {
|
||||||
//TODO app wide focus
|
//TODO app wide focus
|
||||||
table.getSelectionModel().select(index);
|
table.getSelectionModel().select(index);
|
||||||
|
@ -184,37 +201,6 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Subviews
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void setNewSubView(Trade trade) {
|
|
||||||
if (currentSubView != null) {
|
|
||||||
currentSubView.deactivate();
|
|
||||||
root.getChildren().remove(currentSubView);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trade != null) {
|
|
||||||
if (model.isOfferer()) {
|
|
||||||
if (model.isBuyOffer())
|
|
||||||
currentSubView = new BuyerSubView(model);
|
|
||||||
else
|
|
||||||
currentSubView = new SellerSubView(model);
|
|
||||||
} else {
|
|
||||||
if (model.isBuyOffer())
|
|
||||||
currentSubView = new SellerSubView(model);
|
|
||||||
else
|
|
||||||
currentSubView = new BuyerSubView(model);
|
|
||||||
}
|
|
||||||
currentSubView.setMinHeight(430);
|
|
||||||
VBox.setVgrow(currentSubView, Priority.ALWAYS);
|
|
||||||
root.getChildren().add(1, currentSubView);
|
|
||||||
|
|
||||||
currentSubView.activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// CellFactories
|
// CellFactories
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -18,34 +18,31 @@
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.btc.FeePolicy;
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
|
||||||
import io.bitsquare.common.handlers.ResultHandler;
|
|
||||||
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
||||||
import io.bitsquare.gui.common.model.ViewModel;
|
import io.bitsquare.gui.common.model.ViewModel;
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.gui.util.validation.*;
|
import io.bitsquare.gui.util.validation.BtcAddressValidator;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
import io.bitsquare.p2p.P2PService;
|
import io.bitsquare.p2p.P2PService;
|
||||||
import io.bitsquare.payment.PaymentMethod;
|
import io.bitsquare.payment.PaymentMethod;
|
||||||
import io.bitsquare.trade.Contract;
|
import io.bitsquare.trade.Contract;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.offer.Offer;
|
import io.bitsquare.trade.offer.Offer;
|
||||||
|
import io.bitsquare.user.User;
|
||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.beans.value.ChangeListener;
|
||||||
import org.bitcoinj.core.BlockChainListener;
|
import org.bitcoinj.core.BlockChainListener;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
import org.fxmisc.easybind.EasyBind;
|
||||||
import org.fxmisc.easybind.Subscription;
|
import org.fxmisc.easybind.Subscription;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel.SellerState.*;
|
import static io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel.SellerState.*;
|
||||||
|
|
||||||
public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataModel> implements ViewModel {
|
public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataModel> implements ViewModel {
|
||||||
private Subscription tradeStateSubscription;
|
private Subscription tradeStateSubscription;
|
||||||
|
|
||||||
private interface State {
|
interface State {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BuyerState implements State {
|
enum BuyerState implements State {
|
||||||
|
@ -67,20 +64,15 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
REQUEST_WITHDRAWAL
|
REQUEST_WITHDRAWAL
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BSFormatter formatter;
|
public final BSFormatter formatter;
|
||||||
private final BtcAddressValidator btcAddressValidator;
|
private final BtcAddressValidator btcAddressValidator;
|
||||||
|
|
||||||
private final IBANValidator ibanValidator;
|
public final P2PService p2PService;
|
||||||
private final BICValidator bicValidator;
|
public User user;
|
||||||
private final InputValidator inputValidator;
|
|
||||||
private final OKPayValidator okPayValidator;
|
|
||||||
private final AltCoinAddressValidator altCoinAddressValidator;
|
|
||||||
private final P2PService p2PService;
|
|
||||||
|
|
||||||
private final ObjectProperty<BuyerState> buyerState = new SimpleObjectProperty<>(PendingTradesViewModel.BuyerState.UNDEFINED);
|
private final ObjectProperty<BuyerState> buyerState = new SimpleObjectProperty<>();
|
||||||
private final ObjectProperty<SellerState> sellerState = new SimpleObjectProperty<>(UNDEFINED);
|
private final ObjectProperty<SellerState> sellerState = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
private final StringProperty txId = new SimpleStringProperty();
|
|
||||||
private final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
|
private final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,30 +84,30 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
public PendingTradesViewModel(PendingTradesDataModel dataModel,
|
public PendingTradesViewModel(PendingTradesDataModel dataModel,
|
||||||
BSFormatter formatter,
|
BSFormatter formatter,
|
||||||
BtcAddressValidator btcAddressValidator,
|
BtcAddressValidator btcAddressValidator,
|
||||||
IBANValidator ibanValidator,
|
P2PService p2PService,
|
||||||
BICValidator bicValidator,
|
User user
|
||||||
InputValidator inputValidator,
|
|
||||||
OKPayValidator okPayValidator,
|
|
||||||
AltCoinAddressValidator altCoinAddressValidator,
|
|
||||||
P2PService p2PService
|
|
||||||
) {
|
) {
|
||||||
super(dataModel);
|
super(dataModel);
|
||||||
|
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
this.btcAddressValidator = btcAddressValidator;
|
this.btcAddressValidator = btcAddressValidator;
|
||||||
this.ibanValidator = ibanValidator;
|
|
||||||
this.bicValidator = bicValidator;
|
|
||||||
this.inputValidator = inputValidator;
|
|
||||||
this.okPayValidator = okPayValidator;
|
|
||||||
this.altCoinAddressValidator = altCoinAddressValidator;
|
|
||||||
this.p2PService = p2PService;
|
this.p2PService = p2PService;
|
||||||
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ChangeListener<Trade.State> tradeStateChangeListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
setTradeStateSubscription();
|
}
|
||||||
|
|
||||||
txId.bind(dataModel.getTxId());
|
// Dont set own listener as we need to control the order of the calls
|
||||||
|
public void onSelectedItemChanged(PendingTradesListItem selectedItem) {
|
||||||
|
if (tradeStateSubscription != null)
|
||||||
|
tradeStateSubscription.unsubscribe();
|
||||||
|
|
||||||
|
if (selectedItem != null)
|
||||||
|
tradeStateSubscription = EasyBind.subscribe(selectedItem.getTrade().stateProperty(), this::onTradeStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,33 +116,6 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
tradeStateSubscription.unsubscribe();
|
tradeStateSubscription.unsubscribe();
|
||||||
tradeStateSubscription = null;
|
tradeStateSubscription = null;
|
||||||
}
|
}
|
||||||
txId.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTradeStateSubscription() {
|
|
||||||
if (tradeStateSubscription != null)
|
|
||||||
tradeStateSubscription.unsubscribe();
|
|
||||||
|
|
||||||
if (dataModel.getTrade() != null) {
|
|
||||||
tradeStateSubscription = EasyBind.subscribe(dataModel.getTrade().stateProperty(), newValue -> {
|
|
||||||
log.debug("tradeStateSubscription " + newValue);
|
|
||||||
if (newValue != null) {
|
|
||||||
applyState(newValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// UI actions
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void onSelectTrade(PendingTradesListItem item) {
|
|
||||||
dataModel.onSelectTrade(item);
|
|
||||||
|
|
||||||
// call it after dataModel.onSelectTrade as trade is set
|
|
||||||
setTradeStateSubscription();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,76 +131,34 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
return sellerState;
|
return sellerState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyStringProperty txIdProperty() {
|
|
||||||
return txId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReadOnlyBooleanProperty getWithdrawalButtonDisable() {
|
|
||||||
return withdrawalButtonDisable;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isBuyOffer() {
|
|
||||||
return dataModel.isBuyOffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlyObjectProperty<Trade> currentTrade() {
|
|
||||||
return dataModel.getTradeProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
|
||||||
dataModel.onFiatPaymentStarted(resultHandler, errorMessageHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fiatPaymentReceived() {
|
|
||||||
dataModel.onFiatPaymentReceived();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void withdrawAddressFocusOut(String text) {
|
public void withdrawAddressFocusOut(String text) {
|
||||||
withdrawalButtonDisable.set(!btcAddressValidator.validate(text).isValid);
|
withdrawalButtonDisable.set(!btcAddressValidator.validate(text).isValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPayoutAmount() {
|
public String getPayoutAmount() {
|
||||||
return formatter.formatCoinWithCode(dataModel.getPayoutAmount());
|
return dataModel.getTrade() != null ? formatter.formatCoinWithCode(dataModel.getTrade().getPayoutAmount()) : "";
|
||||||
}
|
|
||||||
|
|
||||||
ObservableList<PendingTradesListItem> getList() {
|
|
||||||
return dataModel.getList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOfferer() {
|
|
||||||
return dataModel.isOfferer();
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTradesListItem getSelectedItem() {
|
|
||||||
return dataModel.getSelectedItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrencyCode() {
|
|
||||||
return dataModel.getCurrencyCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BtcAddressValidator getBtcAddressValidator() {
|
|
||||||
return btcAddressValidator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBootstrapped() {
|
|
||||||
return p2PService.isBootstrapped();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// columns
|
// columns
|
||||||
|
|
||||||
public String getRemainingTime() {
|
public String getRemainingTime() {
|
||||||
|
if (dataModel.getTrade() != null)
|
||||||
return formatter.getPeriodBetweenBlockHeights(getBestChainHeight(),
|
return formatter.getPeriodBetweenBlockHeights(getBestChainHeight(),
|
||||||
dataModel.getTrade().getOpenDisputeTimeAsBlockHeight());
|
dataModel.getTrade().getOpenDisputeTimeAsBlockHeight());
|
||||||
|
else
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getRemainingTimeAsPercentage() {
|
public double getRemainingTimeAsPercentage() {
|
||||||
|
if (dataModel.getTrade() != null && dataModel.getOffer() != null) {
|
||||||
double remainingBlocks = dataModel.getTrade().getOpenDisputeTimeAsBlockHeight() - getBestChainHeight();
|
double remainingBlocks = dataModel.getTrade().getOpenDisputeTimeAsBlockHeight() - getBestChainHeight();
|
||||||
double maxPeriod = dataModel.getTrade().getOffer().getPaymentMethod().getMaxTradePeriod();
|
double maxPeriod = dataModel.getOffer().getPaymentMethod().getMaxTradePeriod();
|
||||||
if (maxPeriod != 0)
|
if (maxPeriod != 0)
|
||||||
return 1 - remainingBlocks / maxPeriod;
|
return 1 - remainingBlocks / maxPeriod;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean showWarning(Trade trade) {
|
public boolean showWarning(Trade trade) {
|
||||||
|
@ -270,10 +193,6 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatDate(Date value) {
|
|
||||||
return formatter.formatDateTime(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addBlockChainListener(BlockChainListener blockChainListener) {
|
public void addBlockChainListener(BlockChainListener blockChainListener) {
|
||||||
dataModel.addBlockChainListener(blockChainListener);
|
dataModel.addBlockChainListener(blockChainListener);
|
||||||
}
|
}
|
||||||
|
@ -286,64 +205,40 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
return dataModel.getLockTime();
|
return dataModel.getLockTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getCheckPaymentTimeAsBlockHeight() {
|
|
||||||
return dataModel.getCheckPaymentTimeAsBlockHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getOpenDisputeTimeAsBlockHeight() {
|
private long getOpenDisputeTimeAsBlockHeight() {
|
||||||
return dataModel.getOpenDisputeTimeAsBlockHeight();
|
return dataModel.getOpenDisputeTimeAsBlockHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getBestChainHeight() {
|
public int getBestChainHeight() {
|
||||||
return dataModel.getBestChainHeight();
|
return dataModel.getBestChainHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOpenDisputeTimeAsFormattedDate() {
|
public String getOpenDisputeTimeAsFormattedDate() {
|
||||||
|
if (dataModel.getOffer() != null)
|
||||||
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() +
|
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight() +
|
||||||
(dataModel.getTrade().getOffer().getPaymentMethod().getLockTime()));
|
(dataModel.getOffer().getPaymentMethod().getLockTime()));
|
||||||
}
|
else
|
||||||
|
return "";
|
||||||
public String getReference() {
|
|
||||||
return dataModel.getReference();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPaymentMethod() {
|
public String getPaymentMethod() {
|
||||||
checkNotNull(dataModel.getContract(), "dataModel.getContract() must not be null");
|
if (dataModel.getTrade() != null && dataModel.getTrade().getContract() != null)
|
||||||
return BSResources.get(dataModel.getContract().getPaymentMethodName());
|
return BSResources.get(dataModel.getTrade().getContract().getPaymentMethodName());
|
||||||
|
else
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFiatAmount() {
|
public String getFiatAmount() {
|
||||||
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
|
return dataModel.getTrade() != null ? formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume()) : "";
|
||||||
}
|
|
||||||
|
|
||||||
public IBANValidator getIbanValidator() {
|
|
||||||
return ibanValidator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AltCoinAddressValidator getAltCoinAddressValidator() {
|
|
||||||
return altCoinAddressValidator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BICValidator getBicValidator() {
|
|
||||||
return bicValidator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputValidator getInputValidator() {
|
|
||||||
return inputValidator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OKPayValidator getOkPayValidator() {
|
|
||||||
return okPayValidator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// summary
|
// summary
|
||||||
public String getTradeVolume() {
|
public String getTradeVolume() {
|
||||||
return formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount());
|
return dataModel.getTrade() != null ? formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount()) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFiatVolume() {
|
public String getFiatVolume() {
|
||||||
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
|
return dataModel.getTrade() != null ? formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume()) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTotalFees() {
|
public String getTotalFees() {
|
||||||
|
@ -355,11 +250,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBlockChainMethod() {
|
public boolean isBlockChainMethod() {
|
||||||
return dataModel.getTrade().getOffer().getPaymentMethod().equals(PaymentMethod.BLOCK_CHAINS);
|
return dataModel.getOffer() != null && dataModel.getOffer().getPaymentMethod().equals(PaymentMethod.BLOCK_CHAINS);
|
||||||
}
|
|
||||||
|
|
||||||
public Trade getTrade() {
|
|
||||||
return dataModel.getTrade();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,8 +258,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
// States
|
// States
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void applyState(Trade.State tradeState) {
|
private void onTradeStateChanged(Trade.State tradeState) {
|
||||||
log.debug("updateSellerState (SellerTradeState) " + tradeState);
|
Log.traceCall(tradeState.toString());
|
||||||
switch (tradeState) {
|
switch (tradeState) {
|
||||||
case PREPARATION:
|
case PREPARATION:
|
||||||
sellerState.set(UNDEFINED);
|
sellerState.set(UNDEFINED);
|
||||||
|
@ -389,10 +280,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEPOSIT_CONFIRMED:
|
case DEPOSIT_CONFIRMED:
|
||||||
case FIAT_PAYMENT_STARTED:
|
|
||||||
sellerState.set(WAIT_FOR_FIAT_PAYMENT_STARTED);
|
|
||||||
buyerState.set(PendingTradesViewModel.BuyerState.REQUEST_START_FIAT_PAYMENT);
|
buyerState.set(PendingTradesViewModel.BuyerState.REQUEST_START_FIAT_PAYMENT);
|
||||||
|
sellerState.set(WAIT_FOR_FIAT_PAYMENT_STARTED);
|
||||||
break;
|
break;
|
||||||
|
case FIAT_PAYMENT_STARTED:
|
||||||
case FIAT_PAYMENT_STARTED_MSG_SENT:
|
case FIAT_PAYMENT_STARTED_MSG_SENT:
|
||||||
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_FIAT_PAYMENT_RECEIPT);
|
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_FIAT_PAYMENT_RECEIPT);
|
||||||
break;
|
break;
|
||||||
|
@ -415,7 +306,6 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||||
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
|
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
|
||||||
break;
|
break;
|
||||||
case PAYOUT_TX_RECEIVED:
|
case PAYOUT_TX_RECEIVED:
|
||||||
break;
|
|
||||||
case PAYOUT_TX_COMMITTED:
|
case PAYOUT_TX_COMMITTED:
|
||||||
sellerState.set(SellerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
|
sellerState.set(SellerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller.*;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller.*;
|
||||||
import javafx.beans.value.ChangeListener;
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
|
||||||
public class SellerSubView extends TradeSubView {
|
public class SellerSubView extends TradeSubView {
|
||||||
private TradeWizardItem step1;
|
private TradeWizardItem step1;
|
||||||
|
@ -28,8 +29,6 @@ public class SellerSubView extends TradeSubView {
|
||||||
private TradeWizardItem step4;
|
private TradeWizardItem step4;
|
||||||
private TradeWizardItem step5;
|
private TradeWizardItem step5;
|
||||||
|
|
||||||
private final ChangeListener<PendingTradesViewModel.SellerState> stateChangeListener;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor, Initialisation
|
// Constructor, Initialisation
|
||||||
|
@ -37,20 +36,12 @@ public class SellerSubView extends TradeSubView {
|
||||||
|
|
||||||
public SellerSubView(PendingTradesViewModel model) {
|
public SellerSubView(PendingTradesViewModel model) {
|
||||||
super(model);
|
super(model);
|
||||||
stateChangeListener = (ov, oldValue, newValue) -> applyState(newValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void activate() {
|
protected void activate() {
|
||||||
|
viewStateSubscription = EasyBind.subscribe(model.getSellerState(), this::onViewStateChanged);
|
||||||
super.activate();
|
super.activate();
|
||||||
model.getSellerState().addListener(stateChangeListener);
|
|
||||||
applyState(model.getSellerState().get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deactivate() {
|
|
||||||
super.deactivate();
|
|
||||||
model.getSellerState().removeListener(stateChangeListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,8 +72,11 @@ public class SellerSubView extends TradeSubView {
|
||||||
// State
|
// State
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void applyState(PendingTradesViewModel.SellerState viewState) {
|
@Override
|
||||||
log.debug("applyState " + viewState);
|
protected void onViewStateChanged(PendingTradesViewModel.State viewState) {
|
||||||
|
Log.traceCall(viewState.toString());
|
||||||
|
if (viewState != null) {
|
||||||
|
PendingTradesViewModel.SellerState sellerState = (PendingTradesViewModel.SellerState) viewState;
|
||||||
|
|
||||||
step1.setDisabled();
|
step1.setDisabled();
|
||||||
step2.setDisabled();
|
step2.setDisabled();
|
||||||
|
@ -90,13 +84,8 @@ public class SellerSubView extends TradeSubView {
|
||||||
step4.setDisabled();
|
step4.setDisabled();
|
||||||
step5.setDisabled();
|
step5.setDisabled();
|
||||||
|
|
||||||
if (tradeStepView != null)
|
switch (sellerState) {
|
||||||
tradeStepView.doDeactivate();
|
|
||||||
|
|
||||||
switch (viewState) {
|
|
||||||
case UNDEFINED:
|
case UNDEFINED:
|
||||||
contentPane.getChildren().clear();
|
|
||||||
leftVBox.getChildren().clear();
|
|
||||||
break;
|
break;
|
||||||
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
|
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
|
||||||
showItem(step1);
|
showItem(step1);
|
||||||
|
@ -131,24 +120,12 @@ public class SellerSubView extends TradeSubView {
|
||||||
step3.setCompleted();
|
step3.setCompleted();
|
||||||
step4.setCompleted();
|
step4.setCompleted();
|
||||||
showItem(step5);
|
showItem(step5);
|
||||||
|
|
||||||
SellerStep5View sellerStep5View = (SellerStep5View) tradeStepView;
|
|
||||||
sellerStep5View.setBtcTradeAmountLabelText("You have sold:");
|
|
||||||
sellerStep5View.setFiatTradeAmountLabelText("You have received:");
|
|
||||||
sellerStep5View.setBtcTradeAmountTextFieldText(model.getTradeVolume());
|
|
||||||
sellerStep5View.setFiatTradeAmountTextFieldText(model.getFiatVolume());
|
|
||||||
sellerStep5View.setFeesTextFieldText(model.getTotalFees());
|
|
||||||
sellerStep5View.setSecurityDepositTextFieldText(model.getSecurityDeposit());
|
|
||||||
|
|
||||||
sellerStep5View.setWithdrawAmountTextFieldText(model.getPayoutAmount());
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log.warn("unhandled viewState " + viewState);
|
log.warn("unhandled viewState " + sellerState);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (tradeStepView != null)
|
|
||||||
tradeStepView.doActivate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
|
import org.fxmisc.easybind.Subscription;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ public abstract class TradeSubView extends HBox {
|
||||||
protected GridPane leftGridPane;
|
protected GridPane leftGridPane;
|
||||||
protected TitledGroupBg tradeProcessTitledGroupBg;
|
protected TitledGroupBg tradeProcessTitledGroupBg;
|
||||||
protected int leftGridPaneRowIndex = 0;
|
protected int leftGridPaneRowIndex = 0;
|
||||||
|
protected Subscription viewStateSubscription;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -59,11 +61,15 @@ public abstract class TradeSubView extends HBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deactivate() {
|
protected void deactivate() {
|
||||||
|
if (viewStateSubscription != null)
|
||||||
|
viewStateSubscription.unsubscribe();
|
||||||
|
|
||||||
if (tradeStepView != null)
|
if (tradeStepView != null)
|
||||||
tradeStepView.doDeactivate();
|
tradeStepView.deactivate();
|
||||||
|
|
||||||
if (openDisputeButton != null)
|
if (openDisputeButton != null)
|
||||||
leftGridPane.getChildren().remove(openDisputeButton);
|
leftGridPane.getChildren().remove(openDisputeButton);
|
||||||
|
|
||||||
if (notificationGroup != null)
|
if (notificationGroup != null)
|
||||||
notificationGroup.removeItselfFrom(leftGridPane);
|
notificationGroup.removeItselfFrom(leftGridPane);
|
||||||
}
|
}
|
||||||
|
@ -74,9 +80,9 @@ public abstract class TradeSubView extends HBox {
|
||||||
|
|
||||||
leftGridPane = new GridPane();
|
leftGridPane = new GridPane();
|
||||||
leftGridPane.setPrefWidth(340);
|
leftGridPane.setPrefWidth(340);
|
||||||
VBox.setMargin(leftGridPane, new Insets(0, 10, 10, 10));
|
|
||||||
leftGridPane.setHgap(Layout.GRID_GAP);
|
leftGridPane.setHgap(Layout.GRID_GAP);
|
||||||
leftGridPane.setVgap(Layout.GRID_GAP);
|
leftGridPane.setVgap(Layout.GRID_GAP);
|
||||||
|
VBox.setMargin(leftGridPane, new Insets(0, 10, 10, 10));
|
||||||
leftVBox.getChildren().add(leftGridPane);
|
leftVBox.getChildren().add(leftGridPane);
|
||||||
|
|
||||||
leftGridPaneRowIndex = 0;
|
leftGridPaneRowIndex = 0;
|
||||||
|
@ -132,6 +138,8 @@ public abstract class TradeSubView extends HBox {
|
||||||
|
|
||||||
abstract protected void addWizards();
|
abstract protected void addWizards();
|
||||||
|
|
||||||
|
abstract protected void onViewStateChanged(PendingTradesViewModel.State viewState);
|
||||||
|
|
||||||
protected void addWizardsToGridPane(TradeWizardItem tradeWizardItem) {
|
protected void addWizardsToGridPane(TradeWizardItem tradeWizardItem) {
|
||||||
if (leftGridPaneRowIndex == 0)
|
if (leftGridPaneRowIndex == 0)
|
||||||
GridPane.setMargin(tradeWizardItem, new Insets(Layout.FIRST_ROW_DISTANCE, 0, 0, 0));
|
GridPane.setMargin(tradeWizardItem, new Insets(Layout.FIRST_ROW_DISTANCE, 0, 0, 0));
|
||||||
|
@ -143,12 +151,15 @@ public abstract class TradeSubView extends HBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAndAddTradeStepView(Class<? extends TradeStepView> viewClass) {
|
private void createAndAddTradeStepView(Class<? extends TradeStepView> viewClass) {
|
||||||
|
if (tradeStepView != null)
|
||||||
|
tradeStepView.deactivate();
|
||||||
try {
|
try {
|
||||||
tradeStepView = viewClass.getDeclaredConstructor(PendingTradesViewModel.class).newInstance(model);
|
tradeStepView = viewClass.getDeclaredConstructor(PendingTradesViewModel.class).newInstance(model);
|
||||||
contentPane.getChildren().setAll(tradeStepView);
|
contentPane.getChildren().setAll(tradeStepView);
|
||||||
|
|
||||||
tradeStepView.setNotificationGroup(notificationGroup);
|
tradeStepView.setNotificationGroup(notificationGroup);
|
||||||
|
tradeStepView.activate();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
log.error("Creating viewClass {} caused an error {}", viewClass, e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.arbitration.Dispute;
|
import io.bitsquare.arbitration.Dispute;
|
||||||
import io.bitsquare.gui.components.TitledGroupBg;
|
import io.bitsquare.gui.components.TitledGroupBg;
|
||||||
import io.bitsquare.gui.components.TxIdTextField;
|
import io.bitsquare.gui.components.TxIdTextField;
|
||||||
|
@ -27,7 +28,6 @@ import io.bitsquare.gui.popups.Popup;
|
||||||
import io.bitsquare.gui.util.Layout;
|
import io.bitsquare.gui.util.Layout;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.user.Preferences;
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
import javafx.scene.control.ProgressBar;
|
import javafx.scene.control.ProgressBar;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
@ -42,16 +42,16 @@ import org.slf4j.LoggerFactory;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||||
|
|
||||||
public abstract class TradeStepView extends AnchorPane {
|
public abstract class TradeStepView extends AnchorPane {
|
||||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
protected final PendingTradesViewModel model;
|
protected final PendingTradesViewModel model;
|
||||||
private final Trade trade;
|
protected final Trade trade;
|
||||||
protected final Preferences preferences;
|
protected final Preferences preferences;
|
||||||
protected final GridPane gridPane;
|
protected final GridPane gridPane;
|
||||||
private final ChangeListener<String> txIdChangeListener;
|
|
||||||
|
|
||||||
private Subscription errorMessageSubscription;
|
private Subscription errorMessageSubscription;
|
||||||
private Subscription disputeStateSubscription;
|
private Subscription disputeStateSubscription;
|
||||||
|
@ -63,6 +63,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
private ProgressBar timeLeftProgressBar;
|
private ProgressBar timeLeftProgressBar;
|
||||||
private TxIdTextField txIdTextField;
|
private TxIdTextField txIdTextField;
|
||||||
protected TradeSubView.NotificationGroup notificationGroup;
|
protected TradeSubView.NotificationGroup notificationGroup;
|
||||||
|
private Subscription txIdSubscription;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -71,8 +72,9 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
|
|
||||||
protected TradeStepView(PendingTradesViewModel model) {
|
protected TradeStepView(PendingTradesViewModel model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
preferences = model.dataModel.getPreferences();
|
preferences = model.dataModel.preferences;
|
||||||
trade = model.getTrade();
|
trade = model.dataModel.getTrade();
|
||||||
|
checkNotNull(trade, "trade must not be null at TradeStepView");
|
||||||
|
|
||||||
gridPane = addGridPane(this);
|
gridPane = addGridPane(this);
|
||||||
|
|
||||||
|
@ -81,16 +83,16 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
AnchorPane.setTopAnchor(this, -10d);
|
AnchorPane.setTopAnchor(this, -10d);
|
||||||
AnchorPane.setBottomAnchor(this, 0d);
|
AnchorPane.setBottomAnchor(this, 0d);
|
||||||
|
|
||||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
|
|
||||||
|
|
||||||
addContent();
|
addContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doActivate() {
|
public void activate() {
|
||||||
if (txIdTextField != null) {
|
if (txIdTextField != null) {
|
||||||
txIdTextField.setup(model.txIdProperty().get());
|
txIdTextField.setup(model.dataModel.txId.get());
|
||||||
|
if (txIdSubscription != null)
|
||||||
|
txIdSubscription.unsubscribe();
|
||||||
|
|
||||||
model.txIdProperty().addListener(txIdChangeListener);
|
txIdSubscription = EasyBind.subscribe(model.dataModel.txId, id -> txIdTextField.setup(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessageSubscription = EasyBind.subscribe(trade.errorMessageProperty(), newValue -> {
|
errorMessageSubscription = EasyBind.subscribe(trade.errorMessageProperty(), newValue -> {
|
||||||
|
@ -111,17 +113,17 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
timer = FxTimer.runPeriodically(Duration.ofSeconds(1), this::updateTimeLeft);
|
timer = FxTimer.runPeriodically(Duration.ofMinutes(1), this::updateTimeLeft);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doDeactivate() {
|
public void deactivate() {
|
||||||
if (txIdTextField != null) {
|
Log.traceCall();
|
||||||
|
if (txIdSubscription != null)
|
||||||
|
txIdSubscription.unsubscribe();
|
||||||
|
|
||||||
|
if (txIdTextField != null)
|
||||||
txIdTextField.cleanup();
|
txIdTextField.cleanup();
|
||||||
|
|
||||||
model.txIdProperty().removeListener(txIdChangeListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorMessageSubscription != null)
|
if (errorMessageSubscription != null)
|
||||||
errorMessageSubscription.unsubscribe();
|
errorMessageSubscription.unsubscribe();
|
||||||
|
|
||||||
|
@ -189,7 +191,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
timeLeftProgressBar.setProgress(model.getRemainingTimeAsPercentage());
|
timeLeftProgressBar.setProgress(model.getRemainingTimeAsPercentage());
|
||||||
if (remainingTime != null) {
|
if (remainingTime != null) {
|
||||||
timeLeftTextField.setText(remainingTime);
|
timeLeftTextField.setText(remainingTime);
|
||||||
if (model.showWarning(model.getTrade()) || model.showDispute(model.getTrade())) {
|
if (model.showWarning(trade) || model.showDispute(trade)) {
|
||||||
timeLeftTextField.setStyle("-fx-text-fill: -bs-error-red");
|
timeLeftTextField.setStyle("-fx-text-fill: -bs-error-red");
|
||||||
timeLeftProgressBar.setStyle("-fx-accent: -bs-error-red;");
|
timeLeftProgressBar.setStyle("-fx-accent: -bs-error-red;");
|
||||||
}
|
}
|
||||||
|
@ -231,44 +233,36 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
protected void setWarningHeadline() {
|
protected void setWarningHeadline() {
|
||||||
if (notificationGroup != null) {
|
if (notificationGroup != null) {
|
||||||
notificationGroup.titledGroupBg.setText("Warning");
|
notificationGroup.titledGroupBg.setText("Warning");
|
||||||
//notificationGroup.setId("trade-notification-warning");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setInformationHeadline() {
|
protected void setInformationHeadline() {
|
||||||
if (notificationGroup != null) {
|
if (notificationGroup != null) {
|
||||||
notificationGroup.titledGroupBg.setText("Notification");
|
notificationGroup.titledGroupBg.setText("Notification");
|
||||||
//notificationGroup.titledGroupBg.setId("titled-group-bg-warn");
|
|
||||||
//notificationGroup.label.setId("titled-group-bg-label-warn");
|
|
||||||
//notificationLabel.setId("titled-group-bg-label-warn");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setOpenDisputeHeadline() {
|
protected void setOpenDisputeHeadline() {
|
||||||
if (notificationGroup != null) {
|
if (notificationGroup != null) {
|
||||||
notificationGroup.titledGroupBg.setText("Open a dispute");
|
notificationGroup.titledGroupBg.setText("Open a dispute");
|
||||||
//notificationGroup.setId("trade-notification-dispute");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setDisputeOpenedHeadline() {
|
protected void setDisputeOpenedHeadline() {
|
||||||
if (notificationGroup != null) {
|
if (notificationGroup != null) {
|
||||||
notificationGroup.titledGroupBg.setText("Dispute opened");
|
notificationGroup.titledGroupBg.setText("Dispute opened");
|
||||||
//notificationGroup.setId("trade-notification-dispute");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setRequestSupportHeadline() {
|
protected void setRequestSupportHeadline() {
|
||||||
if (notificationGroup != null) {
|
if (notificationGroup != null) {
|
||||||
notificationGroup.titledGroupBg.setText("Open support ticket");
|
notificationGroup.titledGroupBg.setText("Open support ticket");
|
||||||
//notificationGroup.setId("trade-notification-support");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setSupportOpenedHeadline() {
|
protected void setSupportOpenedHeadline() {
|
||||||
if (notificationGroup != null) {
|
if (notificationGroup != null) {
|
||||||
notificationGroup.titledGroupBg.setText("Support ticket opened");
|
notificationGroup.titledGroupBg.setText("Support ticket opened");
|
||||||
//notificationGroup.setId("trade-notification-support");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +344,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
break;
|
break;
|
||||||
case DISPUTE_REQUESTED:
|
case DISPUTE_REQUESTED:
|
||||||
onDisputeOpened();
|
onDisputeOpened();
|
||||||
ownDispute = model.dataModel.getDisputeManager().findOwnDispute(trade.getId());
|
ownDispute = model.dataModel.disputeManager.findOwnDispute(trade.getId());
|
||||||
ownDispute.ifPresent(dispute -> {
|
ownDispute.ifPresent(dispute -> {
|
||||||
String msg;
|
String msg;
|
||||||
if (dispute.isSupportTicket()) {
|
if (dispute.isSupportTicket()) {
|
||||||
|
@ -369,7 +363,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||||
break;
|
break;
|
||||||
case DISPUTE_STARTED_BY_PEER:
|
case DISPUTE_STARTED_BY_PEER:
|
||||||
onDisputeOpened();
|
onDisputeOpened();
|
||||||
ownDispute = model.dataModel.getDisputeManager().findOwnDispute(trade.getId());
|
ownDispute = model.dataModel.disputeManager.findOwnDispute(trade.getId());
|
||||||
ownDispute.ifPresent(dispute -> {
|
ownDispute.ifPresent(dispute -> {
|
||||||
String msg;
|
String msg;
|
||||||
if (dispute.isSupportTicket()) {
|
if (dispute.isSupportTicket()) {
|
||||||
|
|
|
@ -27,13 +27,18 @@ import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||||
import io.bitsquare.gui.popups.Popup;
|
import io.bitsquare.gui.popups.Popup;
|
||||||
import io.bitsquare.gui.util.Layout;
|
import io.bitsquare.gui.util.Layout;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
|
import io.bitsquare.payment.BlockChainAccountContractData;
|
||||||
import io.bitsquare.payment.PaymentAccountContractData;
|
import io.bitsquare.payment.PaymentAccountContractData;
|
||||||
import io.bitsquare.payment.PaymentMethod;
|
import io.bitsquare.payment.PaymentMethod;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.user.PopupId;
|
import io.bitsquare.user.PopupId;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ProgressIndicator;
|
import javafx.scene.control.ProgressIndicator;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
import org.fxmisc.easybind.Subscription;
|
||||||
|
|
||||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||||
|
|
||||||
|
@ -42,6 +47,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
private Button paymentStartedButton;
|
private Button paymentStartedButton;
|
||||||
private Label statusLabel;
|
private Label statusLabel;
|
||||||
private ProgressIndicator statusProgressIndicator;
|
private ProgressIndicator statusProgressIndicator;
|
||||||
|
private Subscription tradeStatePropertySubscription;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -53,26 +59,54 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doActivate() {
|
public void activate() {
|
||||||
super.doActivate();
|
super.activate();
|
||||||
|
//TODO we get called twice, check why
|
||||||
/* String id = PopupId.SEND_PAYMENT_INFO;
|
if (tradeStatePropertySubscription == null) {
|
||||||
|
tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||||
|
if (state.equals(Trade.State.DEPOSIT_CONFIRMED)) {
|
||||||
|
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||||
|
String id = "StartPaymentPopup_" + trade.getId();
|
||||||
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||||
//TODO use payment method and trade values
|
String message = "";
|
||||||
new Popup().information("You need to transfer now the agreed amount to your trading partner.\n" +
|
if (paymentAccountContractData instanceof BlockChainAccountContractData)
|
||||||
"Please take care that you use the exact data presented here, including the reference text\n" +
|
message = "Please transfer from your external " +
|
||||||
"Please do not click the \"Payment started\" button before you have completed the transfer.\n" +
|
CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()) + " wallet\n" +
|
||||||
"Make sure that you make the transfer soon to not exceed the trading period.")
|
model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" +
|
||||||
.onClose(() -> preferences.dontShowAgain(id))
|
"Here are the payment account details of the bitcoin seller:\n" +
|
||||||
|
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" +
|
||||||
|
"You can copy & paste the receivers address from the main screen after closing that popup.";
|
||||||
|
else if (paymentAccountContractData != null)
|
||||||
|
message = "Please go to your online banking web page and pay\n" +
|
||||||
|
model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" +
|
||||||
|
"Here are the payment account details of the bitcoin seller:\n" +
|
||||||
|
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" +
|
||||||
|
"Please don't forget to add the reference text " + trade.getShortId() +
|
||||||
|
" so the receiver can assign your payment to this trade.\n" +
|
||||||
|
"DO NOT use any additional notice in the reference text like " +
|
||||||
|
"Bitcoin, Btc, Trade or Bitsquare.\n\n" +
|
||||||
|
"You can copy & paste the values from the main screen after closing that popup.";
|
||||||
|
|
||||||
|
new Popup().headLine("Notification for trade with ID " + trade.getShortId())
|
||||||
|
.message(message)
|
||||||
|
.closeButtonText("I understand")
|
||||||
|
.dontShowAgainId(id, preferences)
|
||||||
.show();
|
.show();
|
||||||
}*/
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doDeactivate() {
|
public void deactivate() {
|
||||||
super.doDeactivate();
|
super.deactivate();
|
||||||
|
|
||||||
removeStatusProgressIndicator();
|
removeStatusProgressIndicator();
|
||||||
|
if (tradeStatePropertySubscription != null) {
|
||||||
|
tradeStatePropertySubscription.unsubscribe();
|
||||||
|
tradeStatePropertySubscription = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,11 +151,12 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
log.error("Not supported PaymentMethod: " + paymentMethodName);
|
log.error("Not supported PaymentMethod: " + paymentMethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.getReference());
|
if (!(paymentAccountContractData instanceof BlockChainAccountContractData))
|
||||||
|
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.dataModel.getReference());
|
||||||
|
|
||||||
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3);
|
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3);
|
||||||
|
|
||||||
Tuple3<Button, ProgressIndicator, Label> tuple3 = addButtonWithStatus(gridPane, ++gridRow, "Payment started");
|
Tuple3<Button, ProgressIndicator, Label> tuple3 = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "Payment started");
|
||||||
paymentStartedButton = tuple3.first;
|
paymentStartedButton = tuple3.first;
|
||||||
paymentStartedButton.setOnAction(e -> onPaymentStarted());
|
paymentStartedButton.setOnAction(e -> onPaymentStarted());
|
||||||
statusProgressIndicator = tuple3.second;
|
statusProgressIndicator = tuple3.second;
|
||||||
|
@ -136,7 +171,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
@Override
|
@Override
|
||||||
protected String getWarningText() {
|
protected String getWarningText() {
|
||||||
setWarningHeadline();
|
setWarningHeadline();
|
||||||
return "You still have not done your " + model.getCurrencyCode() + " payment!\n" +
|
return "You still have not done your " + model.dataModel.getCurrencyCode() + " payment!\n" +
|
||||||
"Please note that the trade has to be completed until " +
|
"Please note that the trade has to be completed until " +
|
||||||
model.getOpenDisputeTimeAsFormattedDate() +
|
model.getOpenDisputeTimeAsFormattedDate() +
|
||||||
" otherwise the trade will be investigated by the arbitrator.";
|
" otherwise the trade will be investigated by the arbitrator.";
|
||||||
|
@ -165,7 +200,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void onPaymentStarted() {
|
private void onPaymentStarted() {
|
||||||
if (model.isBootstrapped()) {
|
if (model.p2PService.isBootstrapped()) {
|
||||||
String key = PopupId.PAYMENT_SENT;
|
String key = PopupId.PAYMENT_SENT;
|
||||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||||
new Popup().headLine("Confirmation")
|
new Popup().headLine("Confirmation")
|
||||||
|
@ -197,7 +232,7 @@ public class BuyerStep2View extends TradeStepView {
|
||||||
statusLabel.setText("Sending message to your trading partner.\n" +
|
statusLabel.setText("Sending message to your trading partner.\n" +
|
||||||
"Please wait until you get the confirmation that the message has arrived.");
|
"Please wait until you get the confirmation that the message has arrived.");
|
||||||
|
|
||||||
model.fiatPaymentStarted(() -> {
|
model.dataModel.onPaymentStarted(() -> {
|
||||||
// We would not really need an update as the success triggers a screen change
|
// We would not really need an update as the success triggers a screen change
|
||||||
removeStatusProgressIndicator();
|
removeStatusProgressIndicator();
|
||||||
statusLabel.setText("");
|
statusLabel.setText("");
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class BuyerStep3View extends TradeStepView {
|
||||||
@Override
|
@Override
|
||||||
protected String getInfoText() {
|
protected String getInfoText() {
|
||||||
return "Waiting for the bitcoin seller's confirmation " +
|
return "Waiting for the bitcoin seller's confirmation " +
|
||||||
"for the receipt of the " + model.getCurrencyCode() + " payment.";
|
"for the receipt of the " + model.dataModel.getCurrencyCode() + " payment.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public class BuyerStep3View extends TradeStepView {
|
||||||
protected String getWarningText() {
|
protected String getWarningText() {
|
||||||
setInformationHeadline();
|
setInformationHeadline();
|
||||||
String substitute = model.isBlockChainMethod() ?
|
String substitute = model.isBlockChainMethod() ?
|
||||||
"on the " + model.getCurrencyCode() + "blockchain" :
|
"on the " + model.dataModel.getCurrencyCode() + "blockchain" :
|
||||||
"at your payment provider (e.g. bank)";
|
"at your payment provider (e.g. bank)";
|
||||||
return "The seller still has not confirmed your payment!\n" +
|
return "The seller still has not confirmed your payment!\n" +
|
||||||
"Please check " + substitute + " if the payment sending was successful.\n" +
|
"Please check " + substitute + " if the payment sending was successful.\n" +
|
||||||
|
|
|
@ -71,16 +71,16 @@ public class BuyerStep4View extends TradeStepView {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doActivate() {
|
public void activate() {
|
||||||
super.doActivate();
|
super.activate();
|
||||||
|
|
||||||
model.addBlockChainListener(blockChainListener);
|
model.addBlockChainListener(blockChainListener);
|
||||||
updateDateFromBlockHeight(model.getBestChainHeight());
|
updateDateFromBlockHeight(model.getBestChainHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doDeactivate() {
|
public void deactivate() {
|
||||||
super.doDeactivate();
|
super.deactivate();
|
||||||
|
|
||||||
model.removeBlockChainListener(blockChainListener);
|
model.removeBlockChainListener(blockChainListener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,8 @@
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||||
|
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.common.util.Tuple2;
|
import io.bitsquare.common.util.Tuple2;
|
||||||
import io.bitsquare.gui.components.InputTextField;
|
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||||
import io.bitsquare.gui.popups.Popup;
|
import io.bitsquare.gui.popups.Popup;
|
||||||
|
@ -35,14 +34,9 @@ import static io.bitsquare.gui.util.FormBuilder.*;
|
||||||
public class BuyerStep5View extends TradeStepView {
|
public class BuyerStep5View extends TradeStepView {
|
||||||
private final ChangeListener<Boolean> focusedPropertyListener;
|
private final ChangeListener<Boolean> focusedPropertyListener;
|
||||||
|
|
||||||
private Label btcTradeAmountLabel;
|
protected Label btcTradeAmountLabel;
|
||||||
private TextField btcTradeAmountTextField;
|
protected Label fiatTradeAmountLabel;
|
||||||
private Label fiatTradeAmountLabel;
|
private TextField withdrawAddressTextField;
|
||||||
private TextField fiatTradeAmountTextField;
|
|
||||||
private TextField feesTextField;
|
|
||||||
private TextField securityDepositTextField;
|
|
||||||
private InputTextField withdrawAddressTextField;
|
|
||||||
private TextField withdrawAmountTextField;
|
|
||||||
private Button withdrawButton;
|
private Button withdrawButton;
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,8 +54,8 @@ public class BuyerStep5View extends TradeStepView {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doActivate() {
|
public void activate() {
|
||||||
super.doActivate();
|
super.activate();
|
||||||
|
|
||||||
// TODO valid. handler need improvement
|
// TODO valid. handler need improvement
|
||||||
//withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
|
//withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
|
||||||
|
@ -70,21 +64,22 @@ public class BuyerStep5View extends TradeStepView {
|
||||||
|
|
||||||
// We need to handle both cases: Address not set and address already set (when returning from other view)
|
// We need to handle both cases: Address not set and address already set (when returning from other view)
|
||||||
// We get address validation after focus out, so first make sure we loose focus and then set it again as hint for user to put address in
|
// We get address validation after focus out, so first make sure we loose focus and then set it again as hint for user to put address in
|
||||||
UserThread.execute(() -> {
|
|
||||||
//TODO app wide focus
|
//TODO app wide focus
|
||||||
// withdrawAddressTextField.requestFocus();
|
|
||||||
/* UserThread.execute(() -> {
|
/* UserThread.execute(() -> {
|
||||||
|
withdrawAddressTextField.requestFocus();
|
||||||
|
UserThread.execute(() -> {
|
||||||
this.requestFocus();
|
this.requestFocus();
|
||||||
UserThread.execute(() -> withdrawAddressTextField.requestFocus());
|
UserThread.execute(() -> withdrawAddressTextField.requestFocus());
|
||||||
});*/
|
|
||||||
});
|
});
|
||||||
|
});*/
|
||||||
|
|
||||||
hideNotificationGroup();
|
hideNotificationGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doDeactivate() {
|
public void deactivate() {
|
||||||
super.doDeactivate();
|
Log.traceCall();
|
||||||
|
super.deactivate();
|
||||||
//withdrawAddressTextField.focusedProperty().removeListener(focusedPropertyListener);
|
//withdrawAddressTextField.focusedProperty().removeListener(focusedPropertyListener);
|
||||||
// withdrawButton.disableProperty().unbind();
|
// withdrawButton.disableProperty().unbind();
|
||||||
}
|
}
|
||||||
|
@ -97,22 +92,18 @@ public class BuyerStep5View extends TradeStepView {
|
||||||
@Override
|
@Override
|
||||||
protected void addContent() {
|
protected void addContent() {
|
||||||
addTitledGroupBg(gridPane, gridRow, 4, "Summary of completed trade ", 0);
|
addTitledGroupBg(gridPane, gridRow, 4, "Summary of completed trade ", 0);
|
||||||
Tuple2<Label, TextField> btcTradeAmountPair = addLabelTextField(gridPane, gridRow, "You have bought:", "", Layout.FIRST_ROW_DISTANCE);
|
Tuple2<Label, TextField> btcTradeAmountPair = addLabelTextField(gridPane, gridRow, getBtcTradeAmountLabel(), model.getTradeVolume(), Layout.FIRST_ROW_DISTANCE);
|
||||||
btcTradeAmountLabel = btcTradeAmountPair.first;
|
btcTradeAmountLabel = btcTradeAmountPair.first;
|
||||||
btcTradeAmountTextField = btcTradeAmountPair.second;
|
|
||||||
|
|
||||||
Tuple2<Label, TextField> fiatTradeAmountPair = addLabelTextField(gridPane, ++gridRow, "You have paid:");
|
Tuple2<Label, TextField> fiatTradeAmountPair = addLabelTextField(gridPane, ++gridRow, getFiatTradeAmountLabel(), model.getFiatVolume());
|
||||||
fiatTradeAmountLabel = fiatTradeAmountPair.first;
|
fiatTradeAmountLabel = fiatTradeAmountPair.first;
|
||||||
fiatTradeAmountTextField = fiatTradeAmountPair.second;
|
|
||||||
|
|
||||||
Tuple2<Label, TextField> feesPair = addLabelTextField(gridPane, ++gridRow, "Total fees paid:");
|
Tuple2<Label, TextField> feesPair = addLabelTextField(gridPane, ++gridRow, "Total fees paid:", model.getTotalFees());
|
||||||
feesTextField = feesPair.second;
|
|
||||||
|
|
||||||
Tuple2<Label, TextField> securityDepositPair = addLabelTextField(gridPane, ++gridRow, "Refunded security deposit:");
|
Tuple2<Label, TextField> securityDepositPair = addLabelTextField(gridPane, ++gridRow, "Refunded security deposit:", model.getSecurityDeposit());
|
||||||
securityDepositTextField = securityDepositPair.second;
|
|
||||||
|
|
||||||
addTitledGroupBg(gridPane, ++gridRow, 2, "Withdraw your bitcoins", Layout.GROUP_DISTANCE);
|
addTitledGroupBg(gridPane, ++gridRow, 2, "Withdraw your bitcoins", Layout.GROUP_DISTANCE);
|
||||||
withdrawAmountTextField = addLabelTextField(gridPane, gridRow, "Amount to withdraw:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
addLabelTextField(gridPane, gridRow, "Amount to withdraw:", model.getPayoutAmount(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
withdrawAddressTextField = addLabelInputTextField(gridPane, ++gridRow, "Withdraw to address:").second;
|
withdrawAddressTextField = addLabelInputTextField(gridPane, ++gridRow, "Withdraw to address:").second;
|
||||||
withdrawButton = addButtonAfterGroup(gridPane, ++gridRow, "Withdraw to external wallet");
|
withdrawButton = addButtonAfterGroup(gridPane, ++gridRow, "Withdraw to external wallet");
|
||||||
withdrawButton.setOnAction(e -> {
|
withdrawButton.setOnAction(e -> {
|
||||||
|
@ -143,36 +134,11 @@ public class BuyerStep5View extends TradeStepView {
|
||||||
withdrawAddressTextField.setText("mhpVDvMjJT1Gn7da44dkq1HXd3wXdFZpXu");
|
withdrawAddressTextField.setText("mhpVDvMjJT1Gn7da44dkq1HXd3wXdFZpXu");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getBtcTradeAmountLabel() {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
return "You have bought:";
|
||||||
// Setters
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public void setBtcTradeAmountLabelText(String text) {
|
|
||||||
btcTradeAmountLabel.setText(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFiatTradeAmountLabelText(String text) {
|
protected String getFiatTradeAmountLabel() {
|
||||||
fiatTradeAmountLabel.setText(text);
|
return "You have paid:";
|
||||||
}
|
|
||||||
|
|
||||||
public void setBtcTradeAmountTextFieldText(String text) {
|
|
||||||
btcTradeAmountTextField.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFiatTradeAmountTextFieldText(String text) {
|
|
||||||
fiatTradeAmountTextField.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFeesTextFieldText(String text) {
|
|
||||||
feesTextField.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecurityDepositTextFieldText(String text) {
|
|
||||||
securityDepositTextField.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWithdrawAmountTextFieldText(String text) {
|
|
||||||
withdrawAmountTextField.setText(text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class SellerStep2View extends TradeStepView {
|
||||||
@Override
|
@Override
|
||||||
protected String getInfoText() {
|
protected String getInfoText() {
|
||||||
return "The deposit transaction has at least one blockchain confirmation.\n" +
|
return "The deposit transaction has at least one blockchain confirmation.\n" +
|
||||||
"You need to wait until that the bitcoin buyer starts the \" + model.getCurrencyCode() + \" payment.";
|
"You need to wait until that the bitcoin buyer starts the " + model.dataModel.getCurrencyCode() + " payment.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public class SellerStep2View extends TradeStepView {
|
||||||
@Override
|
@Override
|
||||||
protected String getWarningText() {
|
protected String getWarningText() {
|
||||||
setInformationHeadline();
|
setInformationHeadline();
|
||||||
return "The buyer still has not done the " + model.getCurrencyCode() + " payment.\n" +
|
return "The buyer still has not done the " + model.dataModel.getCurrencyCode() + " payment.\n" +
|
||||||
"You need to wait until he starts the payment.\n" +
|
"You need to wait until he starts the payment.\n" +
|
||||||
"If the trade has not been completed on " +
|
"If the trade has not been completed on " +
|
||||||
model.getOpenDisputeTimeAsFormattedDate() +
|
model.getOpenDisputeTimeAsFormattedDate() +
|
||||||
|
|
|
@ -18,24 +18,37 @@
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||||
|
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
|
import io.bitsquare.common.util.Tuple3;
|
||||||
|
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
|
||||||
|
import io.bitsquare.gui.components.TitledGroupBg;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||||
import io.bitsquare.gui.popups.Popup;
|
import io.bitsquare.gui.popups.Popup;
|
||||||
|
import io.bitsquare.gui.util.Layout;
|
||||||
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
|
import io.bitsquare.payment.BlockChainAccountContractData;
|
||||||
|
import io.bitsquare.payment.PaymentAccountContractData;
|
||||||
|
import io.bitsquare.trade.Contract;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.user.PopupId;
|
import io.bitsquare.user.PopupId;
|
||||||
import io.bitsquare.user.Preferences;
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.geometry.HPos;
|
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ProgressIndicator;
|
import javafx.scene.control.ProgressIndicator;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.HBox;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
import org.fxmisc.easybind.Subscription;
|
||||||
|
|
||||||
|
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||||
|
|
||||||
public class SellerStep3View extends TradeStepView {
|
public class SellerStep3View extends TradeStepView {
|
||||||
|
|
||||||
private Button confirmFiatReceivedButton;
|
private Button confirmFiatReceivedButton;
|
||||||
private Label statusLabel;
|
private Label statusLabel;
|
||||||
private ProgressIndicator statusProgressIndicator;
|
private ProgressIndicator statusProgressIndicator;
|
||||||
|
private Subscription tradeStatePropertySubscription;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -48,45 +61,100 @@ public class SellerStep3View extends TradeStepView {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doActivate() {
|
public void activate() {
|
||||||
super.doActivate();
|
super.activate();
|
||||||
|
|
||||||
|
tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||||
|
if (state.equals(Trade.State.FIAT_PAYMENT_STARTED_MSG_RECEIVED)) {
|
||||||
|
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||||
|
String id = "ConfirmPaymentPopup_" + trade.getId();
|
||||||
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||||
|
String message;
|
||||||
|
String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume());
|
||||||
|
if (paymentAccountContractData instanceof BlockChainAccountContractData) {
|
||||||
|
String nameByCode = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode());
|
||||||
|
String address = ((BlockChainAccountContractData) paymentAccountContractData).getAddress();
|
||||||
|
message = "Please check on your favorite " +
|
||||||
|
nameByCode +
|
||||||
|
" blockchain explorer if the transaction to your receiving address\n" +
|
||||||
|
"" + address + "\n" +
|
||||||
|
"has already " +
|
||||||
|
"sufficient blockchain confirmations.\n" +
|
||||||
|
"The payment amount has to be " + tradeAmountWithCode + "\n\n" +
|
||||||
|
"You can copy & paste your " + nameByCode + " address from the main screen after " +
|
||||||
|
"closing that popup.";
|
||||||
|
} else {
|
||||||
|
message = "Please go to your online banking web page and check if you have received " +
|
||||||
|
tradeAmountWithCode + " from the bitcoin buyer.\n\n" +
|
||||||
|
"The reference text of the transaction is: " + trade.getShortId();
|
||||||
|
}
|
||||||
|
new Popup().headLine("Notification for trade with ID " + trade.getShortId())
|
||||||
|
.message(message)
|
||||||
|
.closeButtonText("I understand")
|
||||||
|
.dontShowAgainId(id, preferences)
|
||||||
|
.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doDeactivate() {
|
public void deactivate() {
|
||||||
super.doDeactivate();
|
super.deactivate();
|
||||||
|
|
||||||
|
if (tradeStatePropertySubscription != null)
|
||||||
|
tradeStatePropertySubscription.unsubscribe();
|
||||||
statusProgressIndicator.setProgress(0);
|
statusProgressIndicator.setProgress(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Content
|
// Content
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addContent() {
|
protected void addContent() {
|
||||||
super.addContent();
|
addTradeInfoBlock();
|
||||||
|
|
||||||
HBox hBox = new HBox();
|
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 2, "Confirm payment receipt", Layout.GROUP_DISTANCE);
|
||||||
hBox.setSpacing(10);
|
|
||||||
confirmFiatReceivedButton = new Button("Confirm payment receipt");
|
TextFieldWithCopyIcon field = addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to receive:",
|
||||||
confirmFiatReceivedButton.setDefaultButton(true);
|
model.getFiatAmount(), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
|
field.setCopyWithoutCurrencyPostFix(true);
|
||||||
|
|
||||||
|
String paymentDetails = "";
|
||||||
|
String title = "";
|
||||||
|
boolean isBlockChain = false;
|
||||||
|
String nameByCode = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode());
|
||||||
|
Contract contract = trade.getContract();
|
||||||
|
if (contract != null) {
|
||||||
|
PaymentAccountContractData paymentAccountContractData = contract.getSellerPaymentAccountContractData();
|
||||||
|
if (paymentAccountContractData instanceof BlockChainAccountContractData) {
|
||||||
|
paymentDetails = ((BlockChainAccountContractData) paymentAccountContractData).getAddress();
|
||||||
|
title = "Your " + nameByCode + " address:";
|
||||||
|
isBlockChain = true;
|
||||||
|
} else {
|
||||||
|
paymentDetails = paymentAccountContractData.getPaymentDetails();
|
||||||
|
title = "Your payment account:";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFieldWithCopyIcon paymentDetailsTextField = addLabelTextFieldWithCopyIcon(gridPane, ++gridRow,
|
||||||
|
title, StringUtils.abbreviate(paymentDetails, 56)).second;
|
||||||
|
paymentDetailsTextField.setMouseTransparent(false);
|
||||||
|
paymentDetailsTextField.setTooltip(new Tooltip(paymentDetails));
|
||||||
|
|
||||||
|
if (!isBlockChain) {
|
||||||
|
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.dataModel.getReference());
|
||||||
|
GridPane.setRowSpan(titledGroupBg, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple3<Button, ProgressIndicator, Label> tuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "Confirm payment receipt");
|
||||||
|
confirmFiatReceivedButton = tuple.first;
|
||||||
confirmFiatReceivedButton.setOnAction(e -> onPaymentReceived());
|
confirmFiatReceivedButton.setOnAction(e -> onPaymentReceived());
|
||||||
|
statusProgressIndicator = tuple.second;
|
||||||
statusProgressIndicator = new ProgressIndicator(0);
|
statusLabel = tuple.third;
|
||||||
statusProgressIndicator.setPrefHeight(24);
|
|
||||||
statusProgressIndicator.setPrefWidth(24);
|
|
||||||
statusProgressIndicator.setVisible(false);
|
|
||||||
|
|
||||||
statusLabel = new Label();
|
|
||||||
statusLabel.setPadding(new Insets(5, 0, 0, 0));
|
|
||||||
|
|
||||||
hBox.getChildren().addAll(confirmFiatReceivedButton, statusProgressIndicator, statusLabel);
|
|
||||||
GridPane.setRowIndex(hBox, ++gridRow);
|
|
||||||
GridPane.setColumnIndex(hBox, 0);
|
|
||||||
GridPane.setHalignment(hBox, HPos.LEFT);
|
|
||||||
GridPane.setMargin(hBox, new Insets(15, 0, 0, 0));
|
|
||||||
gridPane.getChildren().add(hBox);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,19 +162,15 @@ public class SellerStep3View extends TradeStepView {
|
||||||
// Info
|
// Info
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getInfoBlockTitle() {
|
|
||||||
return "Confirm payment receipt";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getInfoText() {
|
protected String getInfoText() {
|
||||||
if (model.isBlockChainMethod()) {
|
if (model.isBlockChainMethod()) {
|
||||||
return "The bitcoin buyer has started the " + model.getCurrencyCode() + " payment.\n" +
|
return "The bitcoin buyer has started the " + model.dataModel.getCurrencyCode() + " payment.\n" +
|
||||||
"Check for blockchain confirmations at your Altcoin wallet or block explorer and " +
|
"Check for blockchain confirmations at your cryptocurrency wallet or block explorer and " +
|
||||||
"confirm the payment when you have sufficient blockchain confirmations.";
|
"confirm the payment when you have sufficient blockchain confirmations.";
|
||||||
} else {
|
} else {
|
||||||
return "The bitcoin buyer has started the " + model.getCurrencyCode() + " payment.\n" +
|
return "The bitcoin buyer has started the " + model.dataModel.getCurrencyCode() + " payment.\n" +
|
||||||
"Check at your payment account (e.g. bank account) and confirm when you have " +
|
"Check at your payment account (e.g. bank account) and confirm when you have " +
|
||||||
"received the payment.";
|
"received the payment.";
|
||||||
}
|
}
|
||||||
|
@ -121,7 +185,7 @@ public class SellerStep3View extends TradeStepView {
|
||||||
protected String getWarningText() {
|
protected String getWarningText() {
|
||||||
setWarningHeadline();
|
setWarningHeadline();
|
||||||
String substitute = model.isBlockChainMethod() ?
|
String substitute = model.isBlockChainMethod() ?
|
||||||
"on the " + model.getCurrencyCode() + "blockchain" :
|
"on the " + model.dataModel.getCurrencyCode() + "blockchain" :
|
||||||
"at your payment provider (e.g. bank)";
|
"at your payment provider (e.g. bank)";
|
||||||
return "You still have not confirmed the receipt of the payment!\n" +
|
return "You still have not confirmed the receipt of the payment!\n" +
|
||||||
"Please check " + substitute + " if you have received the payment.\n" +
|
"Please check " + substitute + " if you have received the payment.\n" +
|
||||||
|
@ -154,8 +218,8 @@ public class SellerStep3View extends TradeStepView {
|
||||||
|
|
||||||
private void onPaymentReceived() {
|
private void onPaymentReceived() {
|
||||||
log.debug("onPaymentReceived");
|
log.debug("onPaymentReceived");
|
||||||
if (model.isBootstrapped()) {
|
if (model.p2PService.isBootstrapped()) {
|
||||||
Preferences preferences = model.dataModel.getPreferences();
|
Preferences preferences = model.dataModel.preferences;
|
||||||
String key = PopupId.PAYMENT_RECEIVED;
|
String key = PopupId.PAYMENT_RECEIVED;
|
||||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||||
new Popup().headLine("Confirmation")
|
new Popup().headLine("Confirmation")
|
||||||
|
@ -183,7 +247,7 @@ public class SellerStep3View extends TradeStepView {
|
||||||
statusProgressIndicator.setProgress(-1);
|
statusProgressIndicator.setProgress(-1);
|
||||||
statusLabel.setText("Sending message to trading partner...");
|
statusLabel.setText("Sending message to trading partner...");
|
||||||
|
|
||||||
model.fiatPaymentReceived();
|
model.dataModel.onFiatPaymentReceived();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,4 +29,14 @@ public class SellerStep5View extends BuyerStep5View {
|
||||||
public SellerStep5View(PendingTradesViewModel model) {
|
public SellerStep5View(PendingTradesViewModel model) {
|
||||||
super(model);
|
super(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getBtcTradeAmountLabel() {
|
||||||
|
return "You have sold:";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getFiatTradeAmountLabel() {
|
||||||
|
return "You have received:";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue