mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 23:36:00 -04:00
Refactor pending trades steps subviews
This commit is contained in:
parent
de79eba7f0
commit
e2e5a6864f
@ -17,16 +17,16 @@
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.*;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.*;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
public class BuyerSubView extends TradeSubView {
|
||||
private TradeWizardItem waitTxInBlockchain;
|
||||
private TradeWizardItem startPayment;
|
||||
private TradeWizardItem waitPaymentReceived;
|
||||
private TradeWizardItem waitPayoutUnlock;
|
||||
private TradeWizardItem completed;
|
||||
private TradeWizardItem step1;
|
||||
private TradeWizardItem step2;
|
||||
private TradeWizardItem step3;
|
||||
private TradeWizardItem step4;
|
||||
private TradeWizardItem step5;
|
||||
|
||||
private final ChangeListener<PendingTradesViewModel.BuyerState> stateChangeListener;
|
||||
|
||||
@ -55,16 +55,16 @@ public class BuyerSubView extends TradeSubView {
|
||||
|
||||
@Override
|
||||
protected void addWizards() {
|
||||
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
||||
startPayment = new TradeWizardItem(StartPaymentView.class, "Start payment");
|
||||
waitPaymentReceived = new TradeWizardItem(WaitPaymentReceivedView.class, "Wait until payment arrived");
|
||||
waitPayoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock");
|
||||
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
||||
step1 = new TradeWizardItem(BuyerStep1View.class, "Wait for blockchain confirmation");
|
||||
step2 = new TradeWizardItem(BuyerStep2View.class, "Start payment");
|
||||
step3 = new TradeWizardItem(BuyerStep3View.class, "Wait until payment arrived");
|
||||
step4 = new TradeWizardItem(BuyerStep4View.class, "Wait for payout unlock");
|
||||
step5 = new TradeWizardItem(BuyerStep5View.class, "Completed");
|
||||
|
||||
if (model.getLockTime() > 0)
|
||||
leftVBox.getChildren().setAll(waitTxInBlockchain, startPayment, waitPaymentReceived, waitPayoutUnlock, completed);
|
||||
leftVBox.getChildren().setAll(step1, step2, step3, step4, step5);
|
||||
else
|
||||
leftVBox.getChildren().setAll(waitTxInBlockchain, startPayment, waitPaymentReceived, completed);
|
||||
leftVBox.getChildren().setAll(step1, step2, step3, step5);
|
||||
}
|
||||
|
||||
|
||||
@ -72,17 +72,17 @@ public class BuyerSubView extends TradeSubView {
|
||||
// State
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void applyState(PendingTradesViewModel.BuyerState state) {
|
||||
private void applyState(PendingTradesViewModel.BuyerState state) {
|
||||
log.debug("applyState " + state);
|
||||
|
||||
waitTxInBlockchain.setDisabled();
|
||||
startPayment.setDisabled();
|
||||
waitPaymentReceived.setDisabled();
|
||||
waitPayoutUnlock.setDisabled();
|
||||
completed.setDisabled();
|
||||
step1.setDisabled();
|
||||
step2.setDisabled();
|
||||
step3.setDisabled();
|
||||
step4.setDisabled();
|
||||
step5.setDisabled();
|
||||
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.doDeactivate();
|
||||
if (tradeStepView != null)
|
||||
tradeStepView.doDeactivate();
|
||||
|
||||
switch (state) {
|
||||
case UNDEFINED:
|
||||
@ -90,58 +90,48 @@ public class BuyerSubView extends TradeSubView {
|
||||
leftVBox.getChildren().clear();
|
||||
break;
|
||||
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
|
||||
showItem(waitTxInBlockchain);
|
||||
|
||||
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Deposit transaction has been published. You need to wait for at least " +
|
||||
"one blockchain confirmation.");
|
||||
showItem(step1);
|
||||
break;
|
||||
case REQUEST_START_FIAT_PAYMENT:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
showItem(startPayment);
|
||||
step1.setCompleted();
|
||||
showItem(step2);
|
||||
break;
|
||||
case WAIT_FOR_FIAT_PAYMENT_RECEIPT:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
startPayment.setCompleted();
|
||||
showItem(waitPaymentReceived);
|
||||
|
||||
((WaitPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("Waiting for the bitcoin sellers confirmation " +
|
||||
"that the {0} payment has arrived.",
|
||||
model.getCurrencyCode()));
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
showItem(step3);
|
||||
break;
|
||||
case WAIT_FOR_UNLOCK_PAYOUT:
|
||||
if (model.getLockTime() > 0) {
|
||||
waitTxInBlockchain.setCompleted();
|
||||
startPayment.setCompleted();
|
||||
waitPaymentReceived.setCompleted();
|
||||
showItem(waitPayoutUnlock);
|
||||
|
||||
((WaitPayoutLockTimeView) tradeStepDetailsView).setInfoLabelText("The payout transaction is signed and finalized by both parties." +
|
||||
"\nFor reducing bank charge back risks you need to wait until the payout gets unlocked to transfer your bitcoin.");
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
step3.setCompleted();
|
||||
showItem(step4);
|
||||
}
|
||||
break;
|
||||
case REQUEST_WITHDRAWAL:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
startPayment.setCompleted();
|
||||
waitPaymentReceived.setCompleted();
|
||||
waitPayoutUnlock.setCompleted();
|
||||
showItem(completed);
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
step3.setCompleted();
|
||||
step4.setCompleted();
|
||||
showItem(step5);
|
||||
|
||||
CompletedView completedView = (CompletedView) tradeStepDetailsView;
|
||||
completedView.setBtcTradeAmountLabelText("You have bought:");
|
||||
completedView.setFiatTradeAmountLabelText("You have paid:");
|
||||
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
|
||||
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
|
||||
completedView.setFeesTextFieldText(model.getTotalFees());
|
||||
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
|
||||
completedView.setWithdrawAmountTextFieldText(model.getPayoutAmount());
|
||||
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;
|
||||
default:
|
||||
log.warn("unhandled buyerState " + state);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.doActivate();
|
||||
if (tradeStepView != null)
|
||||
tradeStepView.doActivate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,6 @@ import javafx.collections.ObservableList;
|
||||
import org.bitcoinj.core.BlockChainListener;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -208,6 +207,19 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
List<Transaction> candidates = new ArrayList<>();
|
||||
List<Transaction> transactions = walletService.getWallet().getRecentTransactions(100, true);
|
||||
transactions.stream().forEach(transaction -> {
|
||||
Coin valueSentFromMe = transaction.getValueSentFromMe(walletService.getWallet());
|
||||
if (!valueSentFromMe.isZero()) {
|
||||
// spending tx
|
||||
// MS tx
|
||||
candidates.addAll(transaction.getOutputs().stream()
|
||||
.filter(transactionOutput -> !transactionOutput.isMine(walletService.getWallet()))
|
||||
.filter(transactionOutput -> transactionOutput.getScriptPubKey().isPayToScriptHash())
|
||||
.map(transactionOutput -> transaction)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
});
|
||||
|
||||
/*transactions.stream().forEach(transaction -> {
|
||||
Coin valueSentFromMe = transaction.getValueSentFromMe(walletService.getWallet());
|
||||
if (!valueSentFromMe.isZero()) {
|
||||
// spending tx
|
||||
@ -220,15 +232,13 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});*/
|
||||
|
||||
if (candidates.size() == 1)
|
||||
doOpenDispute(isSupportTicket, candidates.get(0));
|
||||
else if (candidates.size() > 1)
|
||||
new SelectDepositTxPopup().transactions(candidates)
|
||||
.onSelect(transaction -> {
|
||||
doOpenDispute(isSupportTicket, transaction);
|
||||
})
|
||||
.onSelect(transaction -> doOpenDispute(isSupportTicket, transaction))
|
||||
.closeButtonText("Cancel")
|
||||
.show();
|
||||
else
|
||||
@ -365,7 +375,10 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
}
|
||||
|
||||
public PaymentAccountContractData getSellersPaymentAccountContractData() {
|
||||
return trade.getContract().getSellerPaymentAccountContractData();
|
||||
if (trade.getContract() != null)
|
||||
return trade.getContract().getSellerPaymentAccountContractData();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getReference() {
|
||||
|
@ -22,8 +22,6 @@ import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* We could remove that wrapper if it is not needed for additional UI only fields.
|
||||
*/
|
||||
@ -31,39 +29,20 @@ public class PendingTradesListItem {
|
||||
|
||||
private final Trade trade;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PendingTradesListItem(Trade trade) {
|
||||
this.trade = trade;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Trade getTrade() {
|
||||
return trade;
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<Coin> tradeAmountProperty() {
|
||||
if (trade instanceof Trade)
|
||||
return trade.tradeAmountProperty();
|
||||
else
|
||||
return trade.tradeAmountProperty();
|
||||
return trade.tradeAmountProperty();
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<Fiat> tradeVolumeProperty() {
|
||||
if (trade instanceof Trade)
|
||||
return trade.tradeVolumeProperty();
|
||||
else
|
||||
return trade.tradeVolumeProperty();
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return trade.getDate();
|
||||
return trade.tradeVolumeProperty();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -18,7 +18,7 @@
|
||||
-->
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.cell.*?>
|
||||
<?import javafx.scene.control.cell.PropertyValueFactory?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesView"
|
||||
@ -34,11 +34,7 @@
|
||||
<PropertyValueFactory property="id"/>
|
||||
</cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="130">
|
||||
<cellValueFactory>
|
||||
<PropertyValueFactory property="date"/>
|
||||
</cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="130"/>
|
||||
<TableColumn text="Trade amount in BTC" fx:id="tradeAmountColumn" minWidth="130">
|
||||
<cellValueFactory>
|
||||
<PropertyValueFactory property="tradeAmount"/>
|
||||
|
@ -45,7 +45,6 @@ import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Date;
|
||||
|
||||
@FxmlView
|
||||
public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTradesViewModel> {
|
||||
@ -54,13 +53,9 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
@FXML
|
||||
TableView<PendingTradesListItem> table;
|
||||
@FXML
|
||||
TableColumn<PendingTradesListItem, Fiat> priceColumn;
|
||||
TableColumn<PendingTradesListItem, Fiat> priceColumn, tradeVolumeColumn;
|
||||
@FXML
|
||||
TableColumn<PendingTradesListItem, Fiat> tradeVolumeColumn;
|
||||
@FXML
|
||||
TableColumn<PendingTradesListItem, PendingTradesListItem> roleColumn, paymentMethodColumn, idColumn;
|
||||
@FXML
|
||||
TableColumn<PendingTradesListItem, Date> dateColumn;
|
||||
TableColumn<PendingTradesListItem, PendingTradesListItem> roleColumn, paymentMethodColumn, idColumn, dateColumn;
|
||||
@FXML
|
||||
TableColumn<PendingTradesListItem, Coin> tradeAmountColumn;
|
||||
|
||||
@ -119,31 +114,35 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
|
||||
currentTradeChangeListener = (observable, oldValue, newValue) -> {
|
||||
log.debug("currentTradeChangeListener {} ", newValue);
|
||||
setNewSubView(newValue);
|
||||
// setNewSubView(newValue);
|
||||
};
|
||||
|
||||
// we use a hidden emergency shortcut to open support ticket
|
||||
keyEventEventHandler = event -> {
|
||||
if (new KeyCodeCombination(KeyCode.O, KeyCombination.SHORTCUT_DOWN).match(event))
|
||||
new OpenEmergencyTicketPopup().onOpenTicket(() -> model.dataModel.onOpenSupportTicket()).show();
|
||||
new OpenEmergencyTicketPopup().onOpenTicket(model.dataModel::onOpenSupportTicket).show();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
scene = root.getScene();
|
||||
appFocusProperty = scene.getWindow().focusedProperty();
|
||||
if (scene != null) {
|
||||
appFocusProperty = scene.getWindow().focusedProperty();
|
||||
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
|
||||
}
|
||||
|
||||
appFocusProperty.addListener(appFocusChangeListener);
|
||||
model.currentTrade().addListener(currentTradeChangeListener);
|
||||
//setNewSubView(model.currentTrade().get());
|
||||
table.setItems(model.getList());
|
||||
table.getSelectionModel().selectedItemProperty().addListener(selectedItemChangeListener);
|
||||
updateSelectedItem();
|
||||
|
||||
if (model.getSelectedItem() == null)
|
||||
model.getList().addListener(listChangeListener);
|
||||
|
||||
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
|
||||
|
||||
updateSelectedItem();
|
||||
}
|
||||
|
||||
private void updateSelectedItem() {
|
||||
@ -204,7 +203,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
else
|
||||
currentSubView = new BuyerSubView(model);
|
||||
}
|
||||
currentSubView.setMinHeight(420);
|
||||
currentSubView.setMinHeight(430);
|
||||
VBox.setVgrow(currentSubView, Priority.ALWAYS);
|
||||
root.getChildren().add(1, currentSubView);
|
||||
|
||||
@ -249,18 +248,33 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
}
|
||||
|
||||
private void setDateColumnCellFactory() {
|
||||
dateColumn.setCellFactory(TextFieldTableCell.<PendingTradesListItem, Date>forTableColumn(
|
||||
new StringConverter<Date>() {
|
||||
dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||
dateColumn.setCellFactory(
|
||||
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
|
||||
PendingTradesListItem>>() {
|
||||
@Override
|
||||
public String toString(Date value) {
|
||||
return model.formatDate(value);
|
||||
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
|
||||
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
|
||||
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
|
||||
@Override
|
||||
public void updateItem(final PendingTradesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (model.showDispute(item.getTrade())) {
|
||||
setStyle("-fx-text-fill: -bs-error-red");
|
||||
} else if (model.showWarning(item.getTrade())) {
|
||||
setStyle("-fx-text-fill: -bs-orange");
|
||||
} else {
|
||||
setId("-fx-text-fill: black");
|
||||
}
|
||||
setText(model.getDate(item));
|
||||
} else {
|
||||
setText(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date fromString(String string) {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
private void setAmountColumnCellFactory() {
|
||||
|
@ -167,7 +167,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
return sellerState;
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty getTxId() {
|
||||
public ReadOnlyStringProperty txIdProperty() {
|
||||
return txId;
|
||||
}
|
||||
|
||||
@ -244,6 +244,32 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
return formatter.formatFiatWithCode(value);
|
||||
}
|
||||
|
||||
public String getRemainingTime() {
|
||||
return formatter.getPeriodBetweenBlockHeights(getBestChainHeight(),
|
||||
dataModel.getTrade().getOpenDisputeTimeAsBlockHeight());
|
||||
}
|
||||
|
||||
public double getRemainingTimeAsPercentage() {
|
||||
double remainingBlocks = dataModel.getTrade().getOpenDisputeTimeAsBlockHeight() - getBestChainHeight();
|
||||
double maxPeriod = dataModel.getTrade().getOffer().getPaymentMethod().getMaxTradePeriod();
|
||||
if (maxPeriod != 0)
|
||||
return 1 - remainingBlocks / maxPeriod;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
String getDate(PendingTradesListItem item) {
|
||||
return formatter.formatDateTime(item.getTrade().getDate());
|
||||
}
|
||||
|
||||
public boolean showWarning(Trade trade) {
|
||||
return getBestChainHeight() >= trade.getCheckPaymentTimeAsBlockHeight();
|
||||
}
|
||||
|
||||
public boolean showDispute(Trade trade) {
|
||||
return getBestChainHeight() >= trade.getOpenDisputeTimeAsBlockHeight();
|
||||
}
|
||||
|
||||
String getMyRole(PendingTradesListItem item) {
|
||||
Trade trade = item.getTrade();
|
||||
Contract contract = trade.getContract();
|
||||
@ -288,7 +314,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
return dataModel.getCheckPaymentTimeAsBlockHeight();
|
||||
}
|
||||
|
||||
public long getOpenDisputeTimeAsBlockHeight() {
|
||||
private long getOpenDisputeTimeAsBlockHeight() {
|
||||
return dataModel.getOpenDisputeTimeAsBlockHeight();
|
||||
}
|
||||
|
||||
@ -297,8 +323,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
return dataModel.getBestChainHeight();
|
||||
}
|
||||
|
||||
public String getDateFromBlocks(long missingBlocks) {
|
||||
return formatter.getDateFromBlocks(missingBlocks);
|
||||
public String getOpenDisputeTimeAsFormattedDate() {
|
||||
return formatter.addBlocksToNowDateFormatted(getOpenDisputeTimeAsBlockHeight() - getBestChainHeight());
|
||||
}
|
||||
|
||||
public String getReference() {
|
||||
|
@ -17,16 +17,16 @@
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.*;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller.*;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
public class SellerSubView extends TradeSubView {
|
||||
private TradeWizardItem waitTxInBlockchain;
|
||||
private TradeWizardItem waitPaymentStarted;
|
||||
private TradeWizardItem confirmPaymentReceived;
|
||||
private TradeWizardItem waitPayoutUnlock;
|
||||
private TradeWizardItem completed;
|
||||
private TradeWizardItem step1;
|
||||
private TradeWizardItem step2;
|
||||
private TradeWizardItem step3;
|
||||
private TradeWizardItem step4;
|
||||
private TradeWizardItem step5;
|
||||
|
||||
private final ChangeListener<PendingTradesViewModel.SellerState> stateChangeListener;
|
||||
|
||||
@ -55,16 +55,16 @@ public class SellerSubView extends TradeSubView {
|
||||
|
||||
@Override
|
||||
protected void addWizards() {
|
||||
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
||||
waitPaymentStarted = new TradeWizardItem(WaitPaymentStartedView.class, "Wait until payment has started");
|
||||
confirmPaymentReceived = new TradeWizardItem(ConfirmPaymentReceivedView.class, "Confirm payment received");
|
||||
waitPayoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock");
|
||||
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
||||
step1 = new TradeWizardItem(SellerStep1View.class, "Wait for blockchain confirmation");
|
||||
step2 = new TradeWizardItem(SellerStep2View.class, "Wait until payment has started");
|
||||
step3 = new TradeWizardItem(SellerStep3View.class, "Confirm payment received");
|
||||
step4 = new TradeWizardItem(SellerStep4aView.class, "Wait for payout unlock");
|
||||
step5 = new TradeWizardItem(SellerStep5View.class, "Completed");
|
||||
|
||||
if (model.getLockTime() > 0)
|
||||
leftVBox.getChildren().setAll(waitTxInBlockchain, waitPaymentStarted, confirmPaymentReceived, waitPayoutUnlock, completed);
|
||||
leftVBox.getChildren().setAll(step1, step2, step3, step4, step5);
|
||||
else
|
||||
leftVBox.getChildren().setAll(waitTxInBlockchain, waitPaymentStarted, confirmPaymentReceived, completed);
|
||||
leftVBox.getChildren().setAll(step1, step2, step3, step5);
|
||||
}
|
||||
|
||||
|
||||
@ -75,14 +75,14 @@ public class SellerSubView extends TradeSubView {
|
||||
private void applyState(PendingTradesViewModel.SellerState viewState) {
|
||||
log.debug("applyState " + viewState);
|
||||
|
||||
waitTxInBlockchain.setDisabled();
|
||||
waitPaymentStarted.setDisabled();
|
||||
confirmPaymentReceived.setDisabled();
|
||||
waitPayoutUnlock.setDisabled();
|
||||
completed.setDisabled();
|
||||
step1.setDisabled();
|
||||
step2.setDisabled();
|
||||
step3.setDisabled();
|
||||
step4.setDisabled();
|
||||
step5.setDisabled();
|
||||
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.doDeactivate();
|
||||
if (tradeStepView != null)
|
||||
tradeStepView.doDeactivate();
|
||||
|
||||
switch (viewState) {
|
||||
case UNDEFINED:
|
||||
@ -90,83 +90,57 @@ public class SellerSubView extends TradeSubView {
|
||||
leftVBox.getChildren().clear();
|
||||
break;
|
||||
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
|
||||
showItem(waitTxInBlockchain);
|
||||
|
||||
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Deposit transaction has been published. " +
|
||||
"The bitcoin buyer need to wait for at least one blockchain confirmation.");
|
||||
showItem(step1);
|
||||
break;
|
||||
case WAIT_FOR_FIAT_PAYMENT_STARTED:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
showItem(waitPaymentStarted);
|
||||
|
||||
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText(BSResources.get("Deposit transaction has at least one blockchain " +
|
||||
"confirmation. " +
|
||||
"Waiting that the bitcoin buyer starts the {0} payment.",
|
||||
model.getCurrencyCode()));
|
||||
step1.setCompleted();
|
||||
showItem(step2);
|
||||
break;
|
||||
case REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
waitPaymentStarted.setCompleted();
|
||||
showItem(confirmPaymentReceived);
|
||||
|
||||
if (model.isBlockChainMethod()) {
|
||||
((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The bitcoin buyer has started the {0} payment. " +
|
||||
"Check your Altcoin wallet or Block explorer and confirm when you have received the payment.",
|
||||
model.getCurrencyCode()));
|
||||
} else {
|
||||
((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The bitcoin buyer has started the {0} payment. " +
|
||||
"Check your payment account and confirm when you have received the payment.",
|
||||
model.getCurrencyCode()));
|
||||
}
|
||||
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
showItem(step3);
|
||||
break;
|
||||
case WAIT_FOR_PAYOUT_TX:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
waitPaymentStarted.setCompleted();
|
||||
confirmPaymentReceived.setCompleted();
|
||||
showItem(waitPayoutUnlock);
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
step3.setCompleted();
|
||||
showItem(step4);
|
||||
|
||||
// We don't use a wizard for that step as it only gets displayed in case the other peer is offline
|
||||
tradeStepDetailsView = new WaitPayoutFinalizedView(model);
|
||||
contentPane.getChildren().setAll(tradeStepDetailsView);
|
||||
|
||||
((WaitPayoutFinalizedView) tradeStepDetailsView).setInfoLabelText("We requested the trading peer to sign and finalize the payout " +
|
||||
"transaction.\n" +
|
||||
"It might be that the other peer is offline, so we need to wait until he finalize the transaction when he goes online again.");
|
||||
tradeStepView = new SellerStep4bView(model);
|
||||
contentPane.getChildren().setAll(tradeStepView);
|
||||
break;
|
||||
case WAIT_FOR_UNLOCK_PAYOUT:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
waitPaymentStarted.setCompleted();
|
||||
confirmPaymentReceived.setCompleted();
|
||||
showItem(waitPayoutUnlock);
|
||||
|
||||
((WaitPayoutLockTimeView) tradeStepDetailsView).setInfoLabelText("The payout transaction is signed and finalized by both parties." +
|
||||
"\nFor reducing bank charge back risks you need to wait until the payout gets unlocked to transfer your bitcoin.");
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
step3.setCompleted();
|
||||
showItem(step4);
|
||||
break;
|
||||
case REQUEST_WITHDRAWAL:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
waitPaymentStarted.setCompleted();
|
||||
confirmPaymentReceived.setCompleted();
|
||||
waitPayoutUnlock.setCompleted();
|
||||
showItem(completed);
|
||||
step1.setCompleted();
|
||||
step2.setCompleted();
|
||||
step3.setCompleted();
|
||||
step4.setCompleted();
|
||||
showItem(step5);
|
||||
|
||||
CompletedView completedView = (CompletedView) tradeStepDetailsView;
|
||||
completedView.setBtcTradeAmountLabelText("You have sold:");
|
||||
completedView.setFiatTradeAmountLabelText("You have received:");
|
||||
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
|
||||
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
|
||||
completedView.setFeesTextFieldText(model.getTotalFees());
|
||||
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
|
||||
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());
|
||||
|
||||
completedView.setWithdrawAmountTextFieldText(model.getPayoutAmount());
|
||||
sellerStep5View.setWithdrawAmountTextFieldText(model.getPayoutAmount());
|
||||
break;
|
||||
default:
|
||||
log.warn("unhandled viewState " + viewState);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.doActivate();
|
||||
if (tradeStepView != null)
|
||||
tradeStepView.doActivate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,23 +17,31 @@
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepDetailsView;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.addMultilineLabel;
|
||||
import static io.bitsquare.gui.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
public abstract class TradeSubView extends HBox {
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
protected final PendingTradesViewModel model;
|
||||
protected VBox leftVBox;
|
||||
protected AnchorPane contentPane;
|
||||
protected TradeStepDetailsView tradeStepDetailsView;
|
||||
protected TradeStepView tradeStepView;
|
||||
private Button openDisputeButton;
|
||||
private Tuple3<GridPane, TitledGroupBg, Label> notificationTuple;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -48,24 +56,48 @@ public abstract class TradeSubView extends HBox {
|
||||
}
|
||||
|
||||
protected void activate() {
|
||||
// don't call tradeStepDetailsView.activate() as that will be called when state is set
|
||||
}
|
||||
|
||||
protected void deactivate() {
|
||||
if (tradeStepDetailsView != null)
|
||||
tradeStepDetailsView.doDeactivate();
|
||||
if (tradeStepView != null)
|
||||
tradeStepView.doDeactivate();
|
||||
|
||||
if (openDisputeButton != null)
|
||||
leftVBox.getChildren().remove(openDisputeButton);
|
||||
if (notificationTuple != null)
|
||||
leftVBox.getChildren().remove(notificationTuple.first);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Misc
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
private void buildViews() {
|
||||
addLeftBox();
|
||||
addContentPane();
|
||||
addWizards();
|
||||
|
||||
openDisputeButton = new Button("Open Dispute");
|
||||
openDisputeButton.setPrefHeight(40);
|
||||
openDisputeButton.setPrefWidth(360);
|
||||
openDisputeButton.setPadding(new Insets(0, 20, 0, 10));
|
||||
openDisputeButton.setAlignment(Pos.CENTER);
|
||||
openDisputeButton.setDefaultButton(true);
|
||||
openDisputeButton.setId("open-dispute-button");
|
||||
openDisputeButton.setVisible(false);
|
||||
openDisputeButton.setManaged(false);
|
||||
leftVBox.getChildren().add(openDisputeButton);
|
||||
VBox.setMargin(openDisputeButton, new Insets(10, 0, 0, 0));
|
||||
|
||||
// notification fields
|
||||
GridPane gridPane = new GridPane();
|
||||
gridPane.setPrefWidth(340);
|
||||
VBox.setMargin(gridPane, new Insets(10, 10, 10, 10));
|
||||
gridPane.setHgap(Layout.GRID_GAP);
|
||||
gridPane.setVgap(Layout.GRID_GAP);
|
||||
gridPane.setVisible(false);
|
||||
gridPane.setManaged(false);
|
||||
leftVBox.getChildren().add(gridPane);
|
||||
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, 0, 4, "Important notice", 20);
|
||||
Label label = addMultilineLabel(gridPane, 0, Layout.FIRST_ROW_DISTANCE + 20);
|
||||
notificationTuple = new Tuple3<>(gridPane, titledGroupBg, label);
|
||||
}
|
||||
|
||||
protected void showItem(TradeWizardItem item) {
|
||||
@ -75,10 +107,13 @@ public abstract class TradeSubView extends HBox {
|
||||
|
||||
abstract protected void addWizards();
|
||||
|
||||
private void createAndAddTradeStepView(Class<? extends TradeStepDetailsView> viewClass) {
|
||||
private void createAndAddTradeStepView(Class<? extends TradeStepView> viewClass) {
|
||||
try {
|
||||
tradeStepDetailsView = viewClass.getDeclaredConstructor(PendingTradesViewModel.class).newInstance(model);
|
||||
contentPane.getChildren().setAll(tradeStepDetailsView);
|
||||
tradeStepView = viewClass.getDeclaredConstructor(PendingTradesViewModel.class).newInstance(model);
|
||||
contentPane.getChildren().setAll(tradeStepView);
|
||||
|
||||
tradeStepView.setNotificationFields(notificationTuple);
|
||||
tradeStepView.setOpenDisputeButton(openDisputeButton);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -1,295 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.arbitration.Dispute;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.main.help.Help;
|
||||
import io.bitsquare.gui.main.help.HelpId;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.popups.Popup;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.bitcoinj.core.*;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public abstract class TradeStepDetailsView extends AnchorPane {
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
protected final PendingTradesViewModel model;
|
||||
protected final GridPane gridPane;
|
||||
protected int gridRow = 0;
|
||||
private final BlockChainListener blockChainListener;
|
||||
|
||||
private long checkPaymentTimeInBlocks;
|
||||
protected long openDisputeTimeInBlocks;
|
||||
protected Label infoLabel;
|
||||
protected TitledGroupBg infoTitledGroupBg;
|
||||
protected Button openDisputeButton;
|
||||
protected Button openSupportTicketButton;
|
||||
|
||||
private Trade trade;
|
||||
private Subscription errorMessageSubscription;
|
||||
private Subscription disputeStateSubscription;
|
||||
private Subscription tradePeriodStateSubscription;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TradeStepDetailsView(PendingTradesViewModel model) {
|
||||
this.model = model;
|
||||
|
||||
AnchorPane.setLeftAnchor(this, 0d);
|
||||
AnchorPane.setRightAnchor(this, 0d);
|
||||
AnchorPane.setTopAnchor(this, -10d);
|
||||
AnchorPane.setBottomAnchor(this, 0d);
|
||||
|
||||
gridPane = addGridPane(this);
|
||||
|
||||
buildGridEntries();
|
||||
|
||||
blockChainListener = new BlockChainListener() {
|
||||
@Override
|
||||
public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
|
||||
setDateFromBlocks(block.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks) throws VerificationException {
|
||||
setDateFromBlocks(model.getBestChainHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveFromBlock(Transaction tx, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset) throws
|
||||
VerificationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset)
|
||||
throws VerificationException {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// That is called at every state change!
|
||||
public void doActivate() {
|
||||
trade = model.getTrade();
|
||||
|
||||
errorMessageSubscription = EasyBind.subscribe(trade.errorMessageProperty(), newValue -> {
|
||||
if (newValue != null) {
|
||||
addErrorLabel();
|
||||
}
|
||||
});
|
||||
|
||||
disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), newValue -> {
|
||||
if (newValue != null) {
|
||||
updateDisputeState(newValue);
|
||||
}
|
||||
});
|
||||
|
||||
tradePeriodStateSubscription = EasyBind.subscribe(trade.getTradePeriodStateProperty(), newValue -> {
|
||||
if (newValue != null) {
|
||||
updateTradePeriodState(newValue);
|
||||
}
|
||||
});
|
||||
|
||||
setDateFromBlocks(model.getBestChainHeight());
|
||||
|
||||
// first call updateTradePeriodState as there is the dispute button created in case we are in period over time
|
||||
updateTradePeriodState(trade.getTradePeriodState());
|
||||
updateDisputeState(trade.getDisputeState());
|
||||
|
||||
model.addBlockChainListener(blockChainListener);
|
||||
}
|
||||
|
||||
public void doDeactivate() {
|
||||
model.removeBlockChainListener(blockChainListener);
|
||||
|
||||
if (errorMessageSubscription != null)
|
||||
errorMessageSubscription.unsubscribe();
|
||||
if (disputeStateSubscription != null)
|
||||
disputeStateSubscription.unsubscribe();
|
||||
if (tradePeriodStateSubscription != null)
|
||||
tradePeriodStateSubscription.unsubscribe();
|
||||
|
||||
if (openDisputeButton != null)
|
||||
openDisputeButton.setOnAction(null);
|
||||
if (openSupportTicketButton != null)
|
||||
openSupportTicketButton.setOnAction(null);
|
||||
}
|
||||
|
||||
protected void disputeInProgress() {
|
||||
if (openDisputeButton != null)
|
||||
openDisputeButton.setDisable(true);
|
||||
|
||||
addDisputeInfoLabel();
|
||||
}
|
||||
|
||||
protected void addDisputeInfoLabel() {
|
||||
if (infoLabel == null) {
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
}
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
}
|
||||
|
||||
protected void addOpenDisputeButton() {
|
||||
if (openDisputeButton == null) {
|
||||
openDisputeButton = addButtonAfterGroup(gridPane, ++gridRow, "Open a dispute with arbitrator");
|
||||
GridPane.setColumnIndex(openDisputeButton, 0);
|
||||
GridPane.setHalignment(openDisputeButton, HPos.LEFT);
|
||||
openDisputeButton.setOnAction(e -> {
|
||||
openDisputeButton.setDisable(true);
|
||||
disputeInProgress();
|
||||
model.dataModel.onOpenDispute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void addErrorLabel() {
|
||||
new Popup().warning(trade.errorMessageProperty().getValue()
|
||||
+ "\n\nPlease report the problem to your arbitrator. He will forward it to the developers to investigate the problem.\n" +
|
||||
"After the problem has be analysed you will get back all the funds you paid in.\n" +
|
||||
"There will be no arbitration fee charged if it was a technical error.").show();
|
||||
|
||||
/*if (infoLabel == null) {
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Error", Layout.GROUP_DISTANCE);
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
}
|
||||
infoTitledGroupBg.setText("Error message");
|
||||
infoLabel.setText(trade.errorMessageProperty().getValue()
|
||||
+ "\n\nPlease report the problem to your arbitrator. He will forward it to the developers to investigate the problem.\n" +
|
||||
"After the problem has be analysed you will get back all the funds you paid in.\n" +
|
||||
"There will be no arbitration fee charged if it was a technical error.");
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");*/
|
||||
|
||||
if (openSupportTicketButton == null) {
|
||||
openSupportTicketButton = addButton(gridPane, ++gridRow, "Request support");
|
||||
GridPane.setHalignment(openSupportTicketButton, HPos.LEFT);
|
||||
openSupportTicketButton.setOnAction(e -> model.dataModel.onOpenSupportTicket());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateDisputeState(Trade.DisputeState disputeState) {
|
||||
Optional<Dispute> ownDispute = model.dataModel.getDisputeManager().findOwnDispute(trade.getId());
|
||||
|
||||
switch (disputeState) {
|
||||
case NONE:
|
||||
break;
|
||||
case DISPUTE_REQUESTED:
|
||||
disputeInProgress();
|
||||
ownDispute.ifPresent(dispute -> {
|
||||
String msg;
|
||||
if (dispute.isSupportTicket())
|
||||
msg = "You opened already a support ticket.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
else
|
||||
msg = "You opened already a dispute.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
|
||||
infoLabel.setText(msg);
|
||||
});
|
||||
|
||||
break;
|
||||
case DISPUTE_STARTED_BY_PEER:
|
||||
disputeInProgress();
|
||||
ownDispute.ifPresent(dispute -> {
|
||||
String msg;
|
||||
if (dispute.isSupportTicket())
|
||||
msg = "Your trading peer opened a support ticket due technical problems.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
else
|
||||
msg = "Your trading peer opened a dispute.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
|
||||
infoLabel.setText(msg);
|
||||
});
|
||||
break;
|
||||
case DISPUTE_CLOSED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateTradePeriodState(Trade.TradePeriodState tradePeriodState) {
|
||||
switch (tradePeriodState) {
|
||||
case NORMAL:
|
||||
break;
|
||||
case HALF_REACHED:
|
||||
displayRequestCheckPayment();
|
||||
break;
|
||||
case TRADE_PERIOD_OVER:
|
||||
displayOpenForDisputeForm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void setDateFromBlocks(long bestBlocKHeight) {
|
||||
checkPaymentTimeInBlocks = model.getCheckPaymentTimeAsBlockHeight() - bestBlocKHeight;
|
||||
openDisputeTimeInBlocks = model.getOpenDisputeTimeAsBlockHeight() - bestBlocKHeight;
|
||||
updateDateFromBlocks(bestBlocKHeight);
|
||||
}
|
||||
|
||||
protected void updateDateFromBlocks(long bestBlocKHeight) {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI Handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void onOpenHelp() {
|
||||
Help.openWindow(model.isOfferer() ? HelpId.PENDING_TRADE_OFFERER : HelpId.PENDING_TRADE_TAKER);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
abstract void buildGridEntries();
|
||||
|
||||
protected void displayRequestCheckPayment() {
|
||||
}
|
||||
|
||||
protected void displayOpenForDisputeForm() {
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.arbitration.Dispute;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.components.TxIdTextField;
|
||||
import io.bitsquare.gui.components.paymentmethods.PaymentMethodForm;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.popups.Popup;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ProgressBar;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.reactfx.util.FxTimer;
|
||||
import org.reactfx.util.Timer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public abstract class TradeStepView extends AnchorPane {
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
protected final PendingTradesViewModel model;
|
||||
private final Trade trade;
|
||||
protected final Preferences preferences;
|
||||
protected final GridPane gridPane;
|
||||
private final ChangeListener<String> txIdChangeListener;
|
||||
|
||||
private Subscription errorMessageSubscription;
|
||||
private Subscription disputeStateSubscription;
|
||||
private Subscription tradePeriodStateSubscription;
|
||||
private Timer timer;
|
||||
protected int gridRow = 0;
|
||||
protected TitledGroupBg tradeInfoTitledGroupBg;
|
||||
private TextField timeLeftTextField;
|
||||
private ProgressBar timeLeftProgressBar;
|
||||
private GridPane notificationGridPane;
|
||||
private Label notificationLabel;
|
||||
private TitledGroupBg notificationTitledGroupBg;
|
||||
protected Button openDisputeButton;
|
||||
private TxIdTextField txIdTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected TradeStepView(PendingTradesViewModel model) {
|
||||
this.model = model;
|
||||
preferences = model.dataModel.getPreferences();
|
||||
trade = model.getTrade();
|
||||
|
||||
gridPane = addGridPane(this);
|
||||
|
||||
AnchorPane.setLeftAnchor(this, 0d);
|
||||
AnchorPane.setRightAnchor(this, 0d);
|
||||
AnchorPane.setTopAnchor(this, -10d);
|
||||
AnchorPane.setBottomAnchor(this, 0d);
|
||||
|
||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
|
||||
|
||||
addContent();
|
||||
}
|
||||
|
||||
public void doActivate() {
|
||||
if (txIdTextField != null) {
|
||||
txIdTextField.setup(model.txIdProperty().get());
|
||||
|
||||
model.txIdProperty().addListener(txIdChangeListener);
|
||||
}
|
||||
|
||||
errorMessageSubscription = EasyBind.subscribe(trade.errorMessageProperty(), newValue -> {
|
||||
if (newValue != null) {
|
||||
showSupportFields();
|
||||
}
|
||||
});
|
||||
|
||||
disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), newValue -> {
|
||||
if (newValue != null) {
|
||||
updateDisputeState(newValue);
|
||||
}
|
||||
});
|
||||
|
||||
timer = FxTimer.runPeriodically(Duration.ofSeconds(1), this::updateTimeLeft);
|
||||
|
||||
tradePeriodStateSubscription = EasyBind.subscribe(trade.getTradePeriodStateProperty(), newValue -> {
|
||||
if (newValue != null) {
|
||||
updateTradePeriodState(newValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void doDeactivate() {
|
||||
if (txIdTextField != null) {
|
||||
txIdTextField.cleanup();
|
||||
|
||||
model.txIdProperty().removeListener(txIdChangeListener);
|
||||
}
|
||||
|
||||
if (errorMessageSubscription != null)
|
||||
errorMessageSubscription.unsubscribe();
|
||||
|
||||
if (disputeStateSubscription != null)
|
||||
disputeStateSubscription.unsubscribe();
|
||||
|
||||
if (tradePeriodStateSubscription != null)
|
||||
tradePeriodStateSubscription.unsubscribe();
|
||||
|
||||
if (openDisputeButton != null)
|
||||
openDisputeButton.setOnAction(null);
|
||||
|
||||
if (timer != null)
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Content
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void addContent() {
|
||||
addTradeInfoBlock();
|
||||
addInfoBlock();
|
||||
}
|
||||
|
||||
protected void addTradeInfoBlock() {
|
||||
tradeInfoTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 4, "Trade information");
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
//TODO
|
||||
PaymentMethodForm.addAllowedPeriod(gridPane, ++gridRow, model.dataModel.getSellersPaymentAccountContractData(),
|
||||
model.getOpenDisputeTimeAsFormattedDate());
|
||||
|
||||
timeLeftTextField = addLabelTextField(gridPane, ++gridRow, "Remaining time:").second;
|
||||
|
||||
timeLeftProgressBar = new ProgressBar(0);
|
||||
timeLeftProgressBar.setOpacity(0.7);
|
||||
timeLeftProgressBar.setMinHeight(9);
|
||||
timeLeftProgressBar.setMaxHeight(9);
|
||||
timeLeftProgressBar.setMaxWidth(Double.MAX_VALUE);
|
||||
|
||||
GridPane.setRowIndex(timeLeftProgressBar, ++gridRow);
|
||||
GridPane.setColumnIndex(timeLeftProgressBar, 1);
|
||||
GridPane.setFillWidth(timeLeftProgressBar, true);
|
||||
gridPane.getChildren().add(timeLeftProgressBar);
|
||||
|
||||
updateTimeLeft();
|
||||
}
|
||||
|
||||
protected void addInfoBlock() {
|
||||
addTitledGroupBg(gridPane, ++gridRow, 1, getInfoBlockTitle(), Layout.GROUP_DISTANCE);
|
||||
addMultilineLabel(gridPane, gridRow, getInfoText(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
}
|
||||
|
||||
protected String getInfoText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected String getInfoBlockTitle() {
|
||||
return "";
|
||||
}
|
||||
|
||||
private void updateTimeLeft() {
|
||||
if (timeLeftTextField != null) {
|
||||
String remainingTime = model.getRemainingTime();
|
||||
timeLeftProgressBar.setProgress(model.getRemainingTimeAsPercentage());
|
||||
if (remainingTime != null) {
|
||||
timeLeftTextField.setText(remainingTime);
|
||||
if (model.showWarning(model.getTrade()) || model.showDispute(model.getTrade())) {
|
||||
timeLeftTextField.setStyle("-fx-text-fill: -bs-error-red");
|
||||
timeLeftProgressBar.setStyle("-fx-accent: -bs-error-red;");
|
||||
}
|
||||
} else {
|
||||
timeLeftTextField.setText("Trade not completed in time (" + model.getOpenDisputeTimeAsFormattedDate() + ")");
|
||||
timeLeftTextField.setStyle("-fx-text-fill: -bs-error-red");
|
||||
timeLeftProgressBar.setStyle("-fx-accent: -bs-error-red;");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute/warning label and button
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We have the dispute button and text field on the left side, but we handle the content here as it
|
||||
// is trade state specific
|
||||
public void setNotificationFields(Tuple3<GridPane, TitledGroupBg, Label> notificationTuple) {
|
||||
this.notificationGridPane = notificationTuple.first;
|
||||
this.notificationTitledGroupBg = notificationTuple.second;
|
||||
this.notificationLabel = notificationTuple.third;
|
||||
}
|
||||
|
||||
public void setOpenDisputeButton(Button openDisputeButton) {
|
||||
this.openDisputeButton = openDisputeButton;
|
||||
}
|
||||
|
||||
private void showDisputeInfoLabel() {
|
||||
if (notificationGridPane != null) {
|
||||
notificationGridPane.setVisible(true);
|
||||
notificationGridPane.setManaged(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void showOpenDisputeButton() {
|
||||
if (openDisputeButton != null) {
|
||||
openDisputeButton.setVisible(true);
|
||||
openDisputeButton.setManaged(true);
|
||||
openDisputeButton.setOnAction(e -> {
|
||||
openDisputeButton.setDisable(true);
|
||||
onDisputeOpened();
|
||||
setDisputeState();
|
||||
model.dataModel.onOpenDispute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected void setWarningState() {
|
||||
if (notificationGridPane != null) {
|
||||
notificationTitledGroupBg.setText("Warning");
|
||||
//notificationGridPane.setId("trade-notification-warning");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setInformationState() {
|
||||
if (notificationGridPane != null) {
|
||||
notificationTitledGroupBg.setText("Notification");
|
||||
notificationTitledGroupBg.setId("titled-group-bg-warn");
|
||||
notificationTitledGroupBg.getLabel().setId("titled-group-bg-label-warn");
|
||||
//notificationLabel.setId("titled-group-bg-label-warn");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setDisputeState() {
|
||||
if (notificationGridPane != null) {
|
||||
notificationTitledGroupBg.setText("Dispute opened");
|
||||
//notificationGridPane.setId("trade-notification-dispute");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setSupportState() {
|
||||
if (notificationGridPane != null) {
|
||||
notificationTitledGroupBg.setText("Support ticket opened");
|
||||
//notificationGridPane.setId("trade-notification-support");
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Support
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void showSupportFields() {
|
||||
if (openDisputeButton != null) {
|
||||
openDisputeButton.setText("Request support");
|
||||
openDisputeButton.setId("open-support-button");
|
||||
openDisputeButton.setOnAction(e -> model.dataModel.onOpenSupportTicket());
|
||||
}
|
||||
new Popup().warning(trade.errorMessageProperty().getValue()
|
||||
+ "\n\nPlease report the problem to your arbitrator.\n\n" +
|
||||
"He will forward teh information to the developers to investigate the problem.\n" +
|
||||
"After the problem has be analyzed you will get back all the funds if they are locked.\n" +
|
||||
"There will be no arbitration fee charged in case of a software bug.")
|
||||
.show();
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void showWarning() {
|
||||
showDisputeInfoLabel();
|
||||
|
||||
if (notificationLabel != null)
|
||||
notificationLabel.setText(getWarningText());
|
||||
}
|
||||
|
||||
protected String getWarningText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onOpenForDispute() {
|
||||
showDisputeInfoLabel();
|
||||
showOpenDisputeButton();
|
||||
|
||||
if (notificationLabel != null)
|
||||
notificationLabel.setText(getOpenForDisputeText());
|
||||
}
|
||||
|
||||
private void onDisputeOpened() {
|
||||
showDisputeInfoLabel();
|
||||
showOpenDisputeButton();
|
||||
applyOnDisputeOpened();
|
||||
|
||||
|
||||
if (openDisputeButton != null)
|
||||
openDisputeButton.setDisable(true);
|
||||
}
|
||||
|
||||
protected String getOpenForDisputeText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected void applyOnDisputeOpened() {
|
||||
}
|
||||
|
||||
private void updateDisputeState(Trade.DisputeState disputeState) {
|
||||
Optional<Dispute> ownDispute;
|
||||
switch (disputeState) {
|
||||
case NONE:
|
||||
break;
|
||||
case DISPUTE_REQUESTED:
|
||||
onDisputeOpened();
|
||||
ownDispute = model.dataModel.getDisputeManager().findOwnDispute(trade.getId());
|
||||
ownDispute.ifPresent(dispute -> {
|
||||
String msg;
|
||||
if (dispute.isSupportTicket()) {
|
||||
setSupportState();
|
||||
msg = "You opened already a support ticket.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
} else {
|
||||
setDisputeState();
|
||||
msg = "You opened already a dispute.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
}
|
||||
if (notificationLabel != null)
|
||||
notificationLabel.setText(msg);
|
||||
});
|
||||
|
||||
break;
|
||||
case DISPUTE_STARTED_BY_PEER:
|
||||
onDisputeOpened();
|
||||
ownDispute = model.dataModel.getDisputeManager().findOwnDispute(trade.getId());
|
||||
ownDispute.ifPresent(dispute -> {
|
||||
String msg;
|
||||
if (dispute.isSupportTicket()) {
|
||||
setSupportState();
|
||||
msg = "Your trading peer opened a support ticket due technical problems.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
} else {
|
||||
setDisputeState();
|
||||
msg = "Your trading peer opened a dispute.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
}
|
||||
if (notificationLabel != null)
|
||||
notificationLabel.setText(msg);
|
||||
});
|
||||
break;
|
||||
case DISPUTE_CLOSED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTradePeriodState(Trade.TradePeriodState tradePeriodState) {
|
||||
if (trade.getDisputeState() != Trade.DisputeState.DISPUTE_REQUESTED &&
|
||||
trade.getDisputeState() != Trade.DisputeState.DISPUTE_STARTED_BY_PEER) {
|
||||
switch (tradePeriodState) {
|
||||
case NORMAL:
|
||||
break;
|
||||
case HALF_REACHED:
|
||||
showWarning();
|
||||
break;
|
||||
case TRADE_PERIOD_OVER:
|
||||
onOpenForDispute();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,13 +26,13 @@ import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
public class TradeWizardItem extends Button {
|
||||
public Class<? extends TradeStepDetailsView> getViewClass() {
|
||||
public Class<? extends TradeStepView> getViewClass() {
|
||||
return viewClass;
|
||||
}
|
||||
|
||||
private final Class<? extends TradeStepDetailsView> viewClass;
|
||||
private final Class<? extends TradeStepView> viewClass;
|
||||
|
||||
public TradeWizardItem(Class<? extends TradeStepDetailsView> viewClass, String title) {
|
||||
public TradeWizardItem(Class<? extends TradeStepView> viewClass, String title) {
|
||||
this.viewClass = viewClass;
|
||||
|
||||
setMouseTransparent(true);
|
||||
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.gui.components.TxIdTextField;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class WaitPaymentReceivedView extends TradeStepDetailsView {
|
||||
private final ChangeListener<String> txIdChangeListener;
|
||||
private TxIdTextField txIdTextField;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public WaitPaymentReceivedView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
|
||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
|
||||
model.getTxId().addListener(txIdChangeListener);
|
||||
txIdTextField.setup(model.getTxId().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
|
||||
model.getTxId().removeListener(txIdChangeListener);
|
||||
txIdTextField.cleanup();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void displayRequestCheckPayment() {
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
infoLabel.setText("The seller still has not confirmed your payment!\n" +
|
||||
"Please check at your payment processor/bank/blockchain if the payment succeeded.\n" +
|
||||
"If the seller has not confirmed the receipt of your payment until " +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) +
|
||||
" the trade will be investigated by the arbitrator.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayOpenForDisputeForm() {
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
infoLabel.setText("The seller has not confirmed your payment!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) +
|
||||
") and you need to contact now the arbitrator to investigate the problem.");
|
||||
|
||||
addOpenDisputeButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disputeInProgress() {
|
||||
super.disputeInProgress();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setInfoLabelText(String text) {
|
||||
if (infoLabel != null)
|
||||
infoLabel.setText(text);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
addTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.addMultilineLabel;
|
||||
import static io.bitsquare.gui.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
public class WaitPayoutFinalizedView extends TradeStepDetailsView {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public WaitPayoutFinalizedView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
}
|
||||
|
||||
public void setInfoLabelText(String text) {
|
||||
if (infoLabel != null)
|
||||
infoLabel.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayRequestCheckPayment() {
|
||||
// we cannot do anything here, beside restart in case of software bugs
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayOpenForDisputeForm() {
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
infoLabel.setText("The trading peer has not finalized the payout transaction!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) + ")." +
|
||||
"\nPlease contact now the arbitrator for opening a dispute.");
|
||||
|
||||
addOpenDisputeButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disputeInProgress() {
|
||||
super.disputeInProgress();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, "Information");
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class WaitPayoutLockTimeView extends TradeStepDetailsView {
|
||||
private TextField blockTextField;
|
||||
private TextField timeTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public WaitPayoutLockTimeView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateDateFromBlocks(long bestBlocKHeight) {
|
||||
long missingBlocks = model.getLockTime() - bestBlocKHeight;
|
||||
blockTextField.setText(String.valueOf(missingBlocks));
|
||||
timeTextField.setText(model.getDateFromBlocks(missingBlocks));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setInfoLabelText(String text) {
|
||||
if (infoLabel != null)
|
||||
infoLabel.setText(text);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
addTitledGroupBg(gridPane, gridRow, 2, "Payout transaction lock time");
|
||||
blockTextField = addLabelTextField(gridPane, gridRow, "Block(s) to wait until unlock:", "", Layout.FIRST_ROW_DISTANCE).second;
|
||||
timeTextField = addLabelTextField(gridPane, ++gridRow, "Approx. date when payout gets unlocked:").second;
|
||||
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.gui.components.TxIdTextField;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class WaitTxInBlockchainView extends TradeStepDetailsView {
|
||||
private final ChangeListener<String> txIdChangeListener;
|
||||
private TxIdTextField txIdTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public WaitTxInBlockchainView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
|
||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
|
||||
model.getTxId().addListener(txIdChangeListener);
|
||||
txIdTextField.setup(model.getTxId().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
|
||||
model.getTxId().removeListener(txIdChangeListener);
|
||||
txIdTextField.cleanup();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setInfoLabelText(String text) {
|
||||
if (infoLabel != null)
|
||||
infoLabel.setText(text);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
addTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
|
||||
public class BuyerStep1View extends TradeStepView {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public BuyerStep1View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Wait for blockchain confirmation";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
return "Deposit transaction has been published.\n" +
|
||||
"You need to wait for at least one blockchain confirmation.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,24 +15,21 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||
|
||||
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.components.TxIdTextField;
|
||||
import io.bitsquare.gui.components.paymentmethods.*;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import io.bitsquare.gui.popups.Popup;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.payment.PaymentAccountContractData;
|
||||
import io.bitsquare.payment.PaymentMethod;
|
||||
import io.bitsquare.user.PopupId;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ProgressIndicator;
|
||||
@ -40,43 +37,33 @@ import javafx.scene.layout.GridPane;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class StartPaymentView extends TradeStepDetailsView {
|
||||
private final Preferences preferences;
|
||||
private TxIdTextField txIdTextField;
|
||||
public class BuyerStep2View extends TradeStepView {
|
||||
|
||||
private Button paymentStartedButton;
|
||||
private Label statusLabel;
|
||||
|
||||
private final ChangeListener<String> txIdChangeListener;
|
||||
private ProgressIndicator statusProgressIndicator;
|
||||
|
||||
private TitledGroupBg txConfirmationGroup;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public StartPaymentView(PendingTradesViewModel model) {
|
||||
public BuyerStep2View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
|
||||
preferences = model.dataModel.getPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
|
||||
model.getTxId().addListener(txIdChangeListener);
|
||||
txIdTextField.setup(model.getTxId().get());
|
||||
|
||||
String key = PopupId.SEND_PAYMENT_INFO;
|
||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||
String id = PopupId.SEND_PAYMENT_INFO;
|
||||
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||
//TODO use payment method and trade values
|
||||
new Popup().information("You need to transfer now the agreed amount to your trading partner.\n" +
|
||||
"Please take care that you use the exact data presented here, including the reference text\n" +
|
||||
"Please do not click the \"Payment started\" button before you have completed the transfer.\n" +
|
||||
"Make sure that you make the transfer soon to not exceed the trading period.")
|
||||
.onClose(() -> preferences.dontShowAgain(key))
|
||||
.onClose(() -> preferences.dontShowAgain(id))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@ -85,62 +72,100 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
|
||||
model.getTxId().removeListener(txIdChangeListener);
|
||||
txIdTextField.cleanup();
|
||||
removeStatusProgressIndicator();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void displayRequestCheckPayment() {
|
||||
addDisputeInfoLabel();
|
||||
infoLabel.setText("You still have not done your payment!\n" +
|
||||
"If the seller does not receive your payment until " +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) +
|
||||
" the trade will be investigated by the arbitrator."
|
||||
);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Content
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void displayOpenForDisputeForm() {
|
||||
addDisputeInfoLabel();
|
||||
infoLabel.setText("You have not completed your payment!\n" +
|
||||
protected void addContent() {
|
||||
addTradeInfoBlock();
|
||||
|
||||
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||
String paymentMethodName = paymentAccountContractData.getPaymentMethodName();
|
||||
TitledGroupBg accountTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1,
|
||||
"Start payment using " + BSResources.get(paymentAccountContractData.getPaymentMethodName()),
|
||||
Layout.GROUP_DISTANCE);
|
||||
TextFieldWithCopyIcon field = addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to transfer:",
|
||||
model.getFiatAmount(),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
field.setCopyWithoutCurrencyPostFix(true);
|
||||
|
||||
switch (paymentMethodName) {
|
||||
case PaymentMethod.OK_PAY_ID:
|
||||
gridRow = OKPayForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.PERFECT_MONEY_ID:
|
||||
gridRow = PerfectMoneyForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.SEPA_ID:
|
||||
gridRow = SepaForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.SWISH_ID:
|
||||
gridRow = SwishForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.ALI_PAY_ID:
|
||||
gridRow = AliPayForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.BLOCK_CHAINS_ID:
|
||||
gridRow = BlockChainForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
default:
|
||||
log.error("Not supported PaymentMethod: " + paymentMethodName);
|
||||
}
|
||||
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference text:", model.getReference());
|
||||
|
||||
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3);
|
||||
|
||||
Tuple3<Button, ProgressIndicator, Label> tuple3 = addButtonWithStatus(gridPane, ++gridRow, "Payment started");
|
||||
paymentStartedButton = tuple3.first;
|
||||
paymentStartedButton.setOnAction(e -> onPaymentStarted());
|
||||
statusProgressIndicator = tuple3.second;
|
||||
statusLabel = tuple3.third;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setWarningState();
|
||||
return "You still have not done your " + model.getCurrencyCode() + " payment!\n" +
|
||||
"Please not that the trade has to be completed until " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
" otherwise the trade will be investigated by the arbitrator.";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getOpenForDisputeText() {
|
||||
return "You have not completed your payment!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) + ")." +
|
||||
"\nPlease contact now the arbitrator for opening a dispute.");
|
||||
|
||||
addOpenDisputeButton();
|
||||
GridPane.setMargin(openDisputeButton, new Insets(0, 0, 0, 0));
|
||||
GridPane.setColumnIndex(openDisputeButton, 1);
|
||||
model.getOpenDisputeTimeAsFormattedDate() + ")." +
|
||||
"\nPlease contact now the arbitrator for opening a dispute.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disputeInProgress() {
|
||||
super.disputeInProgress();
|
||||
|
||||
protected void applyOnDisputeOpened() {
|
||||
paymentStartedButton.setDisable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addDisputeInfoLabel() {
|
||||
if (infoLabel == null) {
|
||||
// we replace tx id field as there is not enough space
|
||||
gridPane.getChildren().removeAll(txConfirmationGroup, txIdTextField);
|
||||
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, 0, 1, "Information");
|
||||
infoLabel = addMultilineLabel(gridPane, 0, Layout.FIRST_ROW_DISTANCE);
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
// grid does not auto update layout correctly
|
||||
infoLabel.setMinHeight(70);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI Handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onPaymentStarted(ActionEvent actionEvent) {
|
||||
log.debug("onPaymentStarted");
|
||||
private void onPaymentStarted() {
|
||||
if (model.isBootstrapped()) {
|
||||
String key = PopupId.PAYMENT_SENT;
|
||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||
@ -149,7 +174,7 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||
.dontShowAgainId(key, preferences)
|
||||
.actionButtonText("Yes I have started the payment")
|
||||
.closeButtonText("No")
|
||||
.onAction(() -> confirmPaymentStarted())
|
||||
.onAction(this::confirmPaymentStarted)
|
||||
.show();
|
||||
} else {
|
||||
confirmPaymentStarted();
|
||||
@ -180,9 +205,9 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||
|
||||
// In case the first send failed we got the support button displayed.
|
||||
// If it succeeds at a second try we remove the support button again.
|
||||
if (openSupportTicketButton != null) {
|
||||
gridPane.getChildren().remove(openSupportTicketButton);
|
||||
openSupportTicketButton = null;
|
||||
if (openDisputeButton != null) {
|
||||
openDisputeButton.setVisible(false);
|
||||
openDisputeButton.setManaged(false);
|
||||
}
|
||||
}, errorMessage -> {
|
||||
removeStatusProgressIndicator();
|
||||
@ -198,55 +223,4 @@ public class StartPaymentView extends TradeStepDetailsView {
|
||||
statusProgressIndicator.setManaged(false);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
txConfirmationGroup = addTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
TitledGroupBg accountTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Payments details", Layout.GROUP_DISTANCE);
|
||||
TextFieldWithCopyIcon field = addLabelTextFieldWithCopyIcon(gridPane, gridRow, "Amount to transfer:", model.getFiatAmount(),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
field.setCopyWithoutCurrencyPostFix(true);
|
||||
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||
|
||||
String paymentMethodName = paymentAccountContractData.getPaymentMethodName();
|
||||
switch (paymentMethodName) {
|
||||
case PaymentMethod.OK_PAY_ID:
|
||||
gridRow = OKPayForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.PERFECT_MONEY_ID:
|
||||
gridRow = PerfectMoneyForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.SEPA_ID:
|
||||
gridRow = SepaForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.SWISH_ID:
|
||||
gridRow = SwishForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.ALI_PAY_ID:
|
||||
gridRow = AliPayForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
case PaymentMethod.BLOCK_CHAINS_ID:
|
||||
gridRow = BlockChainForm.addFormForBuyer(gridPane, gridRow, paymentAccountContractData);
|
||||
break;
|
||||
default:
|
||||
log.error("Not supported PaymentMethod: " + paymentMethodName);
|
||||
}
|
||||
|
||||
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Reference:", model.getReference());
|
||||
|
||||
Tuple3<Button, ProgressIndicator, Label> tuple3 = addButtonWithStatus(gridPane, ++gridRow, "Payment started");
|
||||
paymentStartedButton = tuple3.first;
|
||||
paymentStartedButton.setOnAction(this::onPaymentStarted);
|
||||
statusProgressIndicator = tuple3.second;
|
||||
statusLabel = tuple3.third;
|
||||
|
||||
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 1);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
|
||||
public class BuyerStep3View extends TradeStepView {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public BuyerStep3View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Wait for seller's payment confirmation";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
return BSResources.get("Waiting for the bitcoin seller's confirmation " +
|
||||
"for the receipt of the {0} payment.",
|
||||
model.getCurrencyCode());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setInformationState();
|
||||
String substitute = model.isBlockChainMethod() ?
|
||||
"on the " + model.getCurrencyCode() + "blockchain" :
|
||||
"at your payment provider (e.g. bank)";
|
||||
return "The seller still has not confirmed your payment!\n" +
|
||||
"Please check " + substitute + " if the payment sending was successful.\n" +
|
||||
"If the seller does not confirm the receipt of your payment until " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
" the trade will be investigated by the arbitrator.";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getOpenForDisputeText() {
|
||||
return "The seller has not confirmed your payment!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
") and you need to contact now the arbitrator to investigate the problem.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyOnDisputeOpened() {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import org.bitcoinj.core.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.addLabelTextField;
|
||||
|
||||
public class BuyerStep4View extends TradeStepView {
|
||||
|
||||
private TextField blockTextField;
|
||||
private TextField timeTextField;
|
||||
private final BlockChainListener blockChainListener;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public BuyerStep4View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
|
||||
blockChainListener = new BlockChainListener() {
|
||||
@Override
|
||||
public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
|
||||
updateDateFromBlockHeight(block.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks) throws VerificationException {
|
||||
updateDateFromBlockHeight(model.getBestChainHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveFromBlock(Transaction tx, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset) throws
|
||||
VerificationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset)
|
||||
throws VerificationException {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
|
||||
model.addBlockChainListener(blockChainListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
|
||||
model.removeBlockChainListener(blockChainListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Content
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void addContent() {
|
||||
addTradeInfoBlock();
|
||||
blockTextField = addLabelTextField(gridPane, gridRow, "Block(s) to wait until lock time elapsed:", "", Layout.FIRST_ROW_DISTANCE).second;
|
||||
timeTextField = addLabelTextField(gridPane, ++gridRow, "Approx. date when payout gets unlocked:").second;
|
||||
GridPane.setRowSpan(tradeInfoTitledGroupBg, 4);
|
||||
|
||||
addInfoBlock();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Wait until payout lock time is over";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
return "The payout transaction is signed and finalized by both parties.\n" +
|
||||
"For reducing bank chargeback risks the payout transaction is blocked by a lock time.\n" +
|
||||
"After that lock time is over the payout transaction gets published and you receive " +
|
||||
"your bitcoin.";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setInformationState();
|
||||
return "The payout transaction is still blocked by the lock time!\n" +
|
||||
"If the trade has not been completed on " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
" the arbitrator will investigate.";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateDateFromBlockHeight(long bestBlocKHeight) {
|
||||
long missingBlocks = model.getLockTime() - bestBlocKHeight;
|
||||
blockTextField.setText(String.valueOf(missingBlocks));
|
||||
timeTextField.setText(model.getOpenDisputeTimeAsFormattedDate());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -15,13 +15,14 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.common.UserThread;
|
||||
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.steps.TradeStepView;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.scene.control.Button;
|
||||
@ -30,7 +31,7 @@ import javafx.scene.control.TextField;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
public class CompletedView extends TradeStepDetailsView {
|
||||
public class BuyerStep5View extends TradeStepView {
|
||||
private final ChangeListener<Boolean> focusedPropertyListener;
|
||||
|
||||
private Label btcTradeAmountLabel;
|
||||
@ -48,7 +49,7 @@ public class CompletedView extends TradeStepDetailsView {
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public CompletedView(PendingTradesViewModel model) {
|
||||
public BuyerStep5View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
|
||||
focusedPropertyListener = (ov, oldValue, newValue) -> {
|
||||
@ -87,12 +88,12 @@ public class CompletedView extends TradeStepDetailsView {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
// Content
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
addTitledGroupBg(gridPane, gridRow, 4, "Summary", 0);
|
||||
protected void addContent() {
|
||||
addTitledGroupBg(gridPane, gridRow, 4, "Summary of completed trade ", 0);
|
||||
Tuple2<Label, TextField> btcTradeAmountPair = addLabelTextField(gridPane, gridRow, "You have bought:", "", Layout.FIRST_ROW_DISTANCE);
|
||||
btcTradeAmountLabel = btcTradeAmountPair.first;
|
||||
btcTradeAmountTextField = btcTradeAmountPair.second;
|
||||
@ -120,6 +121,21 @@ public class CompletedView extends TradeStepDetailsView {
|
||||
withdrawAddressTextField.setText("mxAkWWaQBqwqcYstKzqLku3kzR6pbu2zHq");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setInformationState();
|
||||
return "The trade took a bit longer as expected but has been completed successfully in the allowed trade period.";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setBtcTradeAmountLabelText(String text) {
|
||||
btcTradeAmountLabel.setText(text);
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
|
||||
public class SellerStep1View extends TradeStepView {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public SellerStep1View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Wait for blockchain confirmation";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
return "Deposit transaction has been published.\n" +
|
||||
"The bitcoin buyer need to wait for at least one blockchain confirmation before " +
|
||||
"starting the payment.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
|
||||
public class SellerStep2View extends TradeStepView {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public SellerStep2View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Wait for blockchain confirmation";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
return BSResources.get(
|
||||
"The deposit transaction has at least one blockchain confirmation.\n" +
|
||||
"You need to wait until that the bitcoin buyer starts the {0} payment.",
|
||||
model.getCurrencyCode());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setInformationState();
|
||||
return "The buyer still has not done the " + model.getCurrencyCode() + " payment!\n" +
|
||||
"You need to wait until he starts the payment.\n" +
|
||||
"If the trade has not been completed on " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
" the arbitrator will investigate.";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getOpenForDisputeText() {
|
||||
return "The buyer has not started his payment!\n" +
|
||||
"The max. allowed period for the trade has elapsed.\n" +
|
||||
"Please contact the arbitrator for opening a dispute.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyOnDisputeOpened() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -15,17 +15,15 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.gui.components.TxIdTextField;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
import io.bitsquare.gui.popups.Popup;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.user.PopupId;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
@ -34,12 +32,8 @@ import javafx.scene.control.ProgressIndicator;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
public class SellerStep3View extends TradeStepView {
|
||||
|
||||
public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
|
||||
private final ChangeListener<String> txIdChangeListener;
|
||||
|
||||
private TxIdTextField txIdTextField;
|
||||
private Button confirmFiatReceivedButton;
|
||||
private Label statusLabel;
|
||||
private ProgressIndicator statusProgressIndicator;
|
||||
@ -49,63 +43,120 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ConfirmPaymentReceivedView(PendingTradesViewModel model) {
|
||||
public SellerStep3View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
|
||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
|
||||
model.getTxId().addListener(txIdChangeListener);
|
||||
txIdTextField.setup(model.getTxId().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
super.doDeactivate();
|
||||
|
||||
model.getTxId().removeListener(txIdChangeListener);
|
||||
txIdTextField.cleanup();
|
||||
statusProgressIndicator.setProgress(0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Content
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void displayRequestCheckPayment() {
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
infoLabel.setText("You still have not confirmed the receipt of the payment!\n" +
|
||||
"Please check you payment processor or bank account to see if the payment has arrived.\n" +
|
||||
protected void addContent() {
|
||||
super.addContent();
|
||||
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(10);
|
||||
confirmFiatReceivedButton = new Button("Confirm payment receipt");
|
||||
confirmFiatReceivedButton.setDefaultButton(true);
|
||||
confirmFiatReceivedButton.setOnAction(e -> onPaymentReceived());
|
||||
|
||||
statusProgressIndicator = new ProgressIndicator(0);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Confirm payment receipt";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
if (model.isBlockChainMethod()) {
|
||||
return BSResources.get("The bitcoin buyer has started the {0} payment.\n" +
|
||||
"Check for blockchain confirmations at your Altcoin wallet or block explorer and " +
|
||||
"confirm the payment when you have sufficient blockchain confirmations.",
|
||||
model.getCurrencyCode());
|
||||
} else {
|
||||
return BSResources.get("The bitcoin buyer has started the {0} payment.\n" +
|
||||
"Check at your payment account (e.g. bank account) and confirm when you have " +
|
||||
"received the payment.",
|
||||
model.getCurrencyCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setWarningState();
|
||||
String substitute = model.isBlockChainMethod() ?
|
||||
"on the " + model.getCurrencyCode() + "blockchain" :
|
||||
"at your payment provider (e.g. bank)";
|
||||
return "You still have not confirmed the receipt of the payment!\n" +
|
||||
"Please check " + substitute + " if you have received the payment.\n" +
|
||||
"If you do not confirm receipt until " +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) +
|
||||
" the trade will be investigated by the arbitrator.");
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
" the trade will be investigated by the arbitrator.";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void displayOpenForDisputeForm() {
|
||||
infoLabel.setStyle(" -fx-text-fill: -bs-error-red;");
|
||||
infoLabel.setText("You have not confirmed the receipt of the payment!\n" +
|
||||
protected String getOpenForDisputeText() {
|
||||
return "You have not confirmed the receipt of the payment!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) + ")." +
|
||||
"\nPlease contact now the arbitrator for opening a dispute.");
|
||||
|
||||
addOpenDisputeButton();
|
||||
GridPane.setMargin(openDisputeButton, new Insets(0, 0, 0, 0));
|
||||
model.getOpenDisputeTimeAsFormattedDate() + ")." +
|
||||
"\nPlease contact now the arbitrator for opening a dispute.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disputeInProgress() {
|
||||
super.disputeInProgress();
|
||||
|
||||
protected void applyOnDisputeOpened() {
|
||||
confirmFiatReceivedButton.setDisable(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI Handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onPaymentReceived(ActionEvent actionEvent) {
|
||||
private void onPaymentReceived() {
|
||||
log.debug("onPaymentReceived");
|
||||
if (model.isBootstrapped()) {
|
||||
Preferences preferences = model.dataModel.getPreferences();
|
||||
@ -118,7 +169,7 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
|
||||
.dontShowAgainId(key, preferences)
|
||||
.actionButtonText("Yes I have received the payment")
|
||||
.closeButtonText("No")
|
||||
.onAction(() -> confirmPaymentReceived())
|
||||
.onAction(this::confirmPaymentReceived)
|
||||
.show();
|
||||
} else {
|
||||
confirmPaymentReceived();
|
||||
@ -138,51 +189,6 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
|
||||
|
||||
model.fiatPaymentReceived();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setInfoLabelText(String text) {
|
||||
if (infoLabel != null)
|
||||
infoLabel.setText(text);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
addTitledGroupBg(gridPane, gridRow, 1, "Blockchain confirmation");
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, gridRow, "Deposit transaction ID:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
|
||||
infoTitledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||
infoLabel = addMultilineLabel(gridPane, gridRow, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(10);
|
||||
confirmFiatReceivedButton = new Button("Confirm payment receipt");
|
||||
confirmFiatReceivedButton.setDefaultButton(true);
|
||||
confirmFiatReceivedButton.setOnAction(this::onPaymentReceived);
|
||||
|
||||
statusProgressIndicator = new ProgressIndicator(0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,35 +15,20 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.BuyerStep4View;
|
||||
|
||||
public class WaitPaymentStartedView extends WaitTxInBlockchainView {
|
||||
public WaitPaymentStartedView(PendingTradesViewModel model) {
|
||||
public class SellerStep4aView extends BuyerStep4View {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public SellerStep4aView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
super.doActivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayRequestCheckPayment() {
|
||||
// does not make sense to warn here
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void displayOpenForDisputeForm() {
|
||||
addDisputeInfoLabel();
|
||||
infoLabel.setText("The buyer has not started his payment!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getDateFromBlocks(openDisputeTimeInBlocks) + ")." +
|
||||
"\nPlease contact the arbitrator for opening a dispute.");
|
||||
|
||||
addOpenDisputeButton();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
|
||||
public class SellerStep4bView extends TradeStepView {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public SellerStep4bView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Info
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Override
|
||||
protected String getInfoBlockTitle() {
|
||||
return "Wait until peer finalizes the payout transaction";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInfoText() {
|
||||
return "We requested from the trading peer to sign and finalize the payout transaction.\n" +
|
||||
"It might be that the other peer is offline, so we need to wait until he finalize the " +
|
||||
"transaction when he goes online again.";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Warning
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getWarningText() {
|
||||
setInformationState();
|
||||
return "The trading peer has not finalized the payout transaction!\n" +
|
||||
"He might be offline. You need to wait until he finalizes the payout transaction.\n" +
|
||||
"If the trade has not been completed on " +
|
||||
model.getOpenDisputeTimeAsFormattedDate() +
|
||||
" the arbitrator will investigate.";
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Dispute
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected String getOpenForDisputeText() {
|
||||
return "The trading peer has not finalized the payout transaction!\n" +
|
||||
"The max. period for the trade has elapsed (" +
|
||||
model.getOpenDisputeTimeAsFormattedDate() + ").\n" +
|
||||
"Please contact now the arbitrator for opening a dispute.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyOnDisputeOpened() {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.portfolio.pendingtrades.steps.seller;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer.BuyerStep5View;
|
||||
|
||||
public class SellerStep5View extends BuyerStep5View {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public SellerStep5View(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
}
|
@ -23,6 +23,11 @@ public abstract class TorNode<M extends OnionProxyManager, C extends OnionProxyC
|
||||
private static final Logger log = LoggerFactory.getLogger(TorNode.class);
|
||||
|
||||
private final OnionProxyManager tor;
|
||||
|
||||
public Socks5Proxy getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
private final Socks5Proxy proxy;
|
||||
|
||||
public TorNode(M mgr) throws IOException {
|
||||
|
@ -26,6 +26,10 @@
|
||||
<root level="TRACE">
|
||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||
</root>
|
||||
|
||||
<logger name="io.bitsquare.storage.Storage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
|
||||
<!-- <logger name="io.bitsquare.p2p.peers.PeerGroup" level="INFO"/>
|
||||
<logger name="io.bitsquare.p2p.P2PService" level="INFO"/>
|
||||
<logger name="io.bitsquare.p2p.storage.ProtectedExpirableDataStorage" level="INFO"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user