mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 15:26:03 -04:00
Ui improvements
This commit is contained in:
parent
e2e5a6864f
commit
e9c0ffc858
@ -141,5 +141,12 @@
|
||||
<artifactId>Enzo</artifactId>
|
||||
<version>0.1.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>
|
||||
<groupId>org.fxmisc.richtext</groupId>
|
||||
<artifactId>richtextfx</artifactId>
|
||||
<version>0.4.1</version>
|
||||
</dependency>-->
|
||||
|
||||
</dependencies>
|
||||
</project>
|
@ -31,7 +31,11 @@ bg color of non edit textFields: fafafa
|
||||
|
||||
-fx-accent: #0f87c3;
|
||||
-bs-green: #00aa33;
|
||||
-bs-green-soft: derive(-bs-green, 60%);
|
||||
-bs-error-red: #dd0000;
|
||||
-bs-red-soft: derive(-bs-error-red, 60%);
|
||||
-bs-orange: #dd8f05;
|
||||
|
||||
|
||||
-bs-blue-transparent: #0f87c344;
|
||||
-bs-green-transparent: #00aa3344;
|
||||
@ -146,7 +150,7 @@ bg color of non edit textFields: fafafa
|
||||
}
|
||||
|
||||
.received-funds-icon {
|
||||
-fx-text-fill: -bs-green;
|
||||
-fx-text-fill: -bs-green-soft;
|
||||
-fx-cursor: hand;
|
||||
}
|
||||
|
||||
@ -156,7 +160,7 @@ bg color of non edit textFields: fafafa
|
||||
}
|
||||
|
||||
.sent-funds-icon {
|
||||
-fx-text-fill: -bs-error-red;
|
||||
-fx-text-fill: -bs-red-soft;
|
||||
-fx-cursor: hand;
|
||||
}
|
||||
|
||||
@ -613,6 +617,65 @@ textfield */
|
||||
-fx-background-radius: 3px, 3px, 2px, 1px;
|
||||
}
|
||||
|
||||
#open-support-button {
|
||||
-fx-font-weight: bold;
|
||||
-fx-font-size: 14;
|
||||
-fx-base: -bs-orange;
|
||||
}
|
||||
|
||||
#open-dispute-button {
|
||||
-fx-font-weight: bold;
|
||||
-fx-font-size: 14;
|
||||
-fx-base: #dd0000;
|
||||
}
|
||||
|
||||
#trade-notification-warning {
|
||||
-fx-font-size: 14;
|
||||
-fx-base: -bs-red-soft;
|
||||
}
|
||||
|
||||
#trade-notification-information {
|
||||
-fx-font-size: 14;
|
||||
-fx-outer-border: linear-gradient(to bottom, #ffb34b, #ff9200);
|
||||
}
|
||||
|
||||
#trade-notification-dispute {
|
||||
-fx-font-size: 14;
|
||||
-fx-base: -bs-error-red;
|
||||
}
|
||||
|
||||
#trade-notification-support {
|
||||
-fx-font-size: 14;
|
||||
-fx-base: -bs-orange;
|
||||
}
|
||||
|
||||
#support-info-label {
|
||||
-fx-font-size: 14;
|
||||
-fx-text-fill: -bs-red-soft;
|
||||
}
|
||||
|
||||
#titled-group-bg-warn {
|
||||
-fx-body-color: linear-gradient(to bottom, -bs-content-bg-grey, #F0F0F0);
|
||||
-fx-outer-border: linear-gradient(to bottom, #ffb34b, #ff9200);
|
||||
-fx-background-color: -fx-shadow-highlight-color,
|
||||
-fx-outer-border,
|
||||
-fx-inner-border,
|
||||
-fx-body-color;
|
||||
-fx-background-insets: 0 0 -1 0, 0, 1, 2;
|
||||
-fx-background-radius: 3px, 3px, 2px, 1px;
|
||||
}
|
||||
|
||||
#titled-group-bg-label-warn {
|
||||
-fx-font-weight: bold;
|
||||
-fx-font-size: 14;
|
||||
-fx-text-fill: #ff9200;
|
||||
-fx-background-color: -bs-content-bg-grey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TitledGroupBg */
|
||||
#titled-group-bg-label {
|
||||
-fx-font-weight: bold;
|
||||
|
@ -62,20 +62,20 @@ public class AddressTextField extends AnchorPane {
|
||||
textField.setId("address-text-field");
|
||||
textField.setEditable(false);
|
||||
textField.textProperty().bind(address);
|
||||
Tooltip.install(textField, new Tooltip("Open your default bitcoin wallet with that address."));
|
||||
textField.setOnMouseClicked(mouseEvent -> {
|
||||
try {
|
||||
Utilities.openURI(URI.create(getBitcoinURI()));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
new Popup().warning("Opening a default bitcoin wallet application has failed. " +
|
||||
"Perhaps you don't have one installed?").show();
|
||||
}
|
||||
});
|
||||
String tooltipText = "Open your default bitcoin wallet";
|
||||
Tooltip.install(textField, new Tooltip(tooltipText));
|
||||
textField.setOnMouseClicked(mouseEvent -> openExtWallet());
|
||||
textField.focusTraversableProperty().set(focusTraversableProperty().get());
|
||||
//TODO app wide focus
|
||||
//focusedProperty().addListener((ov, oldValue, newValue) -> textField.requestFocus());
|
||||
|
||||
Label extWalletIcon = new Label();
|
||||
extWalletIcon.setLayoutY(3);
|
||||
extWalletIcon.getStyleClass().add("copy-icon");
|
||||
Tooltip.install(extWalletIcon, new Tooltip(tooltipText));
|
||||
AwesomeDude.setIcon(extWalletIcon, AwesomeIcon.SIGNIN);
|
||||
extWalletIcon.setOnMouseClicked(e -> openExtWallet());
|
||||
|
||||
Label copyIcon = new Label();
|
||||
copyIcon.setLayoutY(3);
|
||||
copyIcon.getStyleClass().add("copy-icon");
|
||||
@ -121,10 +121,21 @@ public class AddressTextField extends AnchorPane {
|
||||
|
||||
AnchorPane.setRightAnchor(qrCode, 5.0);
|
||||
AnchorPane.setRightAnchor(copyIcon, 30.0);
|
||||
AnchorPane.setRightAnchor(textField, 55.0);
|
||||
AnchorPane.setRightAnchor(extWalletIcon, 55.0);
|
||||
AnchorPane.setRightAnchor(textField, 77.0);
|
||||
AnchorPane.setLeftAnchor(textField, 0.0);
|
||||
|
||||
getChildren().addAll(textField, copyIcon, qrCode);
|
||||
getChildren().addAll(textField, extWalletIcon, copyIcon, qrCode);
|
||||
}
|
||||
|
||||
private void openExtWallet() {
|
||||
try {
|
||||
Utilities.openURI(URI.create(getBitcoinURI()));
|
||||
} catch (Exception e) {
|
||||
log.warn(e.getMessage());
|
||||
new Popup().warning("Opening a default bitcoin wallet application has failed. " +
|
||||
"Perhaps you don't have one installed?").show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,7 +26,6 @@ public class AddressWithIconAndDirection extends AnchorPane {
|
||||
directionIcon.setLayoutY(3);
|
||||
directionIcon.getStyleClass().add(received ? "received-funds-icon" : "sent-funds-icon");
|
||||
AwesomeDude.setIcon(directionIcon, received ? AwesomeIcon.SIGNIN : AwesomeIcon.SIGNOUT);
|
||||
directionIcon.setOpacity(0.7);
|
||||
directionIcon.setMouseTransparent(true);
|
||||
|
||||
HBox hBox = new HBox();
|
||||
@ -48,6 +47,7 @@ public class AddressWithIconAndDirection extends AnchorPane {
|
||||
openLinkIcon = new Label();
|
||||
openLinkIcon.setLayoutY(3);
|
||||
openLinkIcon.getStyleClass().add("external-link-icon");
|
||||
openLinkIcon.setOpacity(0.7);
|
||||
AwesomeDude.setIcon(openLinkIcon, awesomeIcon);
|
||||
|
||||
AnchorPane.setLeftAnchor(directionIcon, 3.0);
|
||||
|
@ -14,7 +14,7 @@ import javafx.scene.layout.Priority;
|
||||
|
||||
public class HyperlinkWithIcon extends HBox {
|
||||
private final Hyperlink hyperlink;
|
||||
private final Label openLinkIcon;
|
||||
private final Label icon;
|
||||
|
||||
public HyperlinkWithIcon(String text, AwesomeIcon awesomeIcon) {
|
||||
this(text, awesomeIcon, false);
|
||||
@ -28,12 +28,13 @@ public class HyperlinkWithIcon extends HBox {
|
||||
setSpacing(5);
|
||||
hyperlink = new Hyperlink(text);
|
||||
|
||||
openLinkIcon = new Label();
|
||||
openLinkIcon.getStyleClass().add("external-link-icon");
|
||||
icon = new Label();
|
||||
icon.getStyleClass().add("external-link-icon");
|
||||
|
||||
AwesomeDude.setIcon(openLinkIcon, awesomeIcon);
|
||||
openLinkIcon.setMinWidth(20);
|
||||
HBox.setMargin(openLinkIcon, new Insets(awesomeIcon == AwesomeIcon.INFO_SIGN ? 2 : 3, 0, 0, 0));
|
||||
AwesomeDude.setIcon(icon, awesomeIcon);
|
||||
icon.setMinWidth(20);
|
||||
icon.setOpacity(0.7);
|
||||
HBox.setMargin(icon, new Insets(awesomeIcon == AwesomeIcon.INFO_SIGN ? 2 : 3, 0, 0, 0));
|
||||
|
||||
if (isCentered) {
|
||||
Pane spacer1 = new Pane();
|
||||
@ -44,20 +45,20 @@ public class HyperlinkWithIcon extends HBox {
|
||||
spacer2.setMaxWidth(Double.MAX_VALUE);
|
||||
HBox.setHgrow(spacer2, Priority.ALWAYS);
|
||||
|
||||
getChildren().addAll(spacer1, hyperlink, openLinkIcon, spacer2);
|
||||
getChildren().addAll(spacer1, hyperlink, icon, spacer2);
|
||||
} else {
|
||||
getChildren().addAll(hyperlink, openLinkIcon);
|
||||
getChildren().addAll(hyperlink, icon);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnAction(EventHandler<ActionEvent> handler) {
|
||||
hyperlink.setOnAction(handler);
|
||||
openLinkIcon.setOnMouseClicked(e -> handler.handle(null));
|
||||
icon.setOnMouseClicked(e -> handler.handle(null));
|
||||
}
|
||||
|
||||
public void setTooltip(Tooltip tooltip) {
|
||||
hyperlink.setTooltip(tooltip);
|
||||
// TODO does not use the right style
|
||||
openLinkIcon.setTooltip(tooltip);
|
||||
icon.setTooltip(tooltip);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import javafx.scene.layout.Pane;
|
||||
|
||||
public class TitledGroupBg extends Pane {
|
||||
|
||||
|
||||
private final Label label;
|
||||
private final StringProperty text = new SimpleStringProperty();
|
||||
|
||||
@ -68,5 +69,8 @@ public class TitledGroupBg extends Pane {
|
||||
this.text.set(text);
|
||||
}
|
||||
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,9 +42,7 @@ public class AliPayForm extends PaymentMethodForm {
|
||||
private InputTextField accountNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((AliPayAccountContractData) paymentAccountContractData).getAccountNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
@ -72,7 +70,7 @@ public class AliPayForm extends PaymentMethodForm {
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) {
|
||||
String accountNr = accountNrInputTextField.getText();
|
||||
accountNr = StringUtils.abbreviate(accountNr, 5);
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
|
@ -49,13 +49,11 @@ public class BlockChainForm extends PaymentMethodForm {
|
||||
private ComboBox<TradeCurrency> currencyComboBox;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Address:", ((BlockChainAccountContractData) paymentAccountContractData).getAddress());
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData &&
|
||||
((BlockChainAccountContractData) paymentAccountContractData).getPaymentId() != null)
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Payment ID:", ((BlockChainAccountContractData) paymentAccountContractData).getPaymentId());
|
||||
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
@ -86,7 +84,7 @@ public class BlockChainForm extends PaymentMethodForm {
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) {
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
String address = addressInputTextField.getText();
|
||||
address = StringUtils.abbreviate(address, 9);
|
||||
|
@ -49,9 +49,7 @@ public class OKPayForm extends PaymentMethodForm {
|
||||
private InputTextField accountNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((OKPayAccountContractData) paymentAccountContractData).getAccountNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
@ -116,7 +114,7 @@ public class OKPayForm extends PaymentMethodForm {
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) {
|
||||
String accountNr = accountNrInputTextField.getText();
|
||||
accountNr = StringUtils.abbreviate(accountNr, 5);
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
|
@ -48,7 +48,7 @@ public abstract class PaymentMethodForm {
|
||||
|
||||
protected int gridRowFrom;
|
||||
protected InputTextField accountNameTextField;
|
||||
protected CheckBox autoFillCheckBox;
|
||||
protected CheckBox useCustomAccountNameCheckBox;
|
||||
private ComboBox<TradeCurrency> currencyComboBox;
|
||||
|
||||
public PaymentMethodForm(PaymentAccount paymentAccount, InputValidator inputValidator, GridPane gridPane, int gridRow) {
|
||||
@ -80,7 +80,7 @@ public abstract class PaymentMethodForm {
|
||||
}
|
||||
|
||||
protected void addAccountNameTextFieldWithAutoFillCheckBox() {
|
||||
Tuple3<Label, InputTextField, CheckBox> tuple = addLabelInputTextFieldCheckBox(gridPane, ++gridRow, "Account name:", "Auto-fill");
|
||||
Tuple3<Label, InputTextField, CheckBox> tuple = addLabelInputTextFieldCheckBox(gridPane, ++gridRow, "Account name:", "Use custom account name");
|
||||
accountNameTextField = tuple.second;
|
||||
accountNameTextField.setPrefWidth(250);
|
||||
accountNameTextField.setEditable(false);
|
||||
@ -89,23 +89,29 @@ public abstract class PaymentMethodForm {
|
||||
paymentAccount.setAccountName(newValue);
|
||||
updateAllInputsValid();
|
||||
});
|
||||
autoFillCheckBox = tuple.third;
|
||||
autoFillCheckBox.setSelected(true);
|
||||
autoFillCheckBox.setOnAction(e -> {
|
||||
accountNameTextField.setEditable(!autoFillCheckBox.isSelected());
|
||||
useCustomAccountNameCheckBox = tuple.third;
|
||||
useCustomAccountNameCheckBox.setSelected(false);
|
||||
useCustomAccountNameCheckBox.setOnAction(e -> {
|
||||
accountNameTextField.setEditable(useCustomAccountNameCheckBox.isSelected());
|
||||
autoFillNameTextField();
|
||||
});
|
||||
}
|
||||
|
||||
static void addAllowedPeriod(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
public static void addAllowedPeriod(GridPane gridPane, int gridRow,
|
||||
PaymentAccountContractData paymentAccountContractData, String dateFromBlocks) {
|
||||
long hours = paymentAccountContractData.getMaxTradePeriod() / 6;
|
||||
String displayText = hours + " hours";
|
||||
String displayText;
|
||||
if (hours == 1)
|
||||
displayText = hours + " hour";
|
||||
else
|
||||
displayText = hours + " hours";
|
||||
if (hours == 24)
|
||||
displayText = "1 day";
|
||||
if (hours > 24)
|
||||
displayText = hours / 24 + " days";
|
||||
|
||||
addLabelTextField(gridPane, gridRow, "Max. allowed trade period:", displayText);
|
||||
|
||||
addLabelTextField(gridPane, gridRow, "Trade period/end date:", displayText + " / " + dateFromBlocks);
|
||||
}
|
||||
|
||||
protected void addAllowedPeriod() {
|
||||
@ -118,9 +124,9 @@ public abstract class PaymentMethodForm {
|
||||
else if (hours > 24)
|
||||
displayText = hours / 24 + " days";
|
||||
|
||||
displayText += " (Max. permitted period until the trade needs to be completed)";
|
||||
displayText += " (Max. permitted period until the trade has to be completed)";
|
||||
|
||||
addLabelTextField(gridPane, ++gridRow, "Max. permitted trade period:", displayText);
|
||||
addLabelTextField(gridPane, ++gridRow, "Allowed trade period:", displayText);
|
||||
}
|
||||
|
||||
abstract protected void autoFillNameTextField();
|
||||
|
@ -42,9 +42,7 @@ public class PerfectMoneyForm extends PaymentMethodForm {
|
||||
private InputTextField accountNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account nr.:", ((PerfectMoneyAccountContractData) paymentAccountContractData).getAccountNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
@ -74,7 +72,7 @@ public class PerfectMoneyForm extends PaymentMethodForm {
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) {
|
||||
String accountNr = accountNrInputTextField.getText();
|
||||
accountNr = StringUtils.abbreviate(accountNr, 5);
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
|
@ -58,12 +58,10 @@ public class SepaForm extends PaymentMethodForm {
|
||||
private final List<CheckBox> nonEuroCountryCheckBoxes = new ArrayList<>();
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Account holder name:", ((SepaAccountContractData) paymentAccountContractData).getHolderName());
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "Country of bank:", CountryUtil.getNameByCode(paymentAccountContractData.getCountryCode()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "IBAN:", ((SepaAccountContractData) paymentAccountContractData).getIban());
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++gridRow, "BIC/SWIFT:", ((SepaAccountContractData) paymentAccountContractData).getBic());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
@ -218,7 +216,7 @@ public class SepaForm extends PaymentMethodForm {
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) {
|
||||
String iban = ibanInputTextField.getText();
|
||||
if (iban.length() > 5)
|
||||
iban = StringUtils.abbreviate(iban, 5);
|
||||
|
@ -43,10 +43,8 @@ public class SwishForm extends PaymentMethodForm {
|
||||
private InputTextField mobileNrInputTextField;
|
||||
|
||||
public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountContractData paymentAccountContractData) {
|
||||
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(paymentAccountContractData.getPaymentMethodName()));
|
||||
addLabelTextField(gridPane, ++gridRow, "Account holder name:", ((SwishAccountContractData) paymentAccountContractData).getHolderName());
|
||||
addLabelTextField(gridPane, ++gridRow, "Mobile nr.:", ((SwishAccountContractData) paymentAccountContractData).getMobileNr());
|
||||
addAllowedPeriod(gridPane, ++gridRow, paymentAccountContractData);
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
@ -81,7 +79,7 @@ public class SwishForm extends PaymentMethodForm {
|
||||
|
||||
@Override
|
||||
protected void autoFillNameTextField() {
|
||||
if (autoFillCheckBox != null && autoFillCheckBox.isSelected()) {
|
||||
if (useCustomAccountNameCheckBox != null && !useCustomAccountNameCheckBox.isSelected()) {
|
||||
String mobileNr = mobileNrInputTextField.getText();
|
||||
mobileNr = StringUtils.abbreviate(mobileNr, 5);
|
||||
String method = BSResources.get(paymentAccount.getPaymentMethod().getId());
|
||||
|
@ -116,7 +116,7 @@ public class MainViewModel implements ViewModel {
|
||||
private final String btcNetworkAsString;
|
||||
final StringProperty p2PNetworkLabelId = new SimpleStringProperty("footer-pane");
|
||||
|
||||
private MonadicBinding<Boolean> allServicesDone;
|
||||
private MonadicBinding<Boolean> allServicesDone, tradesAndUIReady;
|
||||
private final User user;
|
||||
private int numBTCPeers = 0;
|
||||
private Timer checkForBtcSyncStateTimer;
|
||||
@ -383,18 +383,13 @@ public class MainViewModel implements ViewModel {
|
||||
walletPasswordPopup.onAesKey(aesKey -> tradeWalletService.setAesKey(aesKey)).show();
|
||||
}
|
||||
|
||||
if (tradeManager.pendingTradesInitializedProperty().get() && isSplashScreenRemoved.get())
|
||||
applyTradePeriodState();
|
||||
else {
|
||||
isSplashScreenRemoved.addListener((observable, oldValue, newValue) -> {
|
||||
if (tradeManager.pendingTradesInitializedProperty().get() && isSplashScreenRemoved.get())
|
||||
applyTradePeriodState();
|
||||
});
|
||||
tradeManager.pendingTradesInitializedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if (tradeManager.pendingTradesInitializedProperty().get() && isSplashScreenRemoved.get())
|
||||
applyTradePeriodState();
|
||||
});
|
||||
}
|
||||
// We handle the trade period here as we display a global popup if we reached dispute time
|
||||
tradesAndUIReady = EasyBind.combine(isSplashScreenRemoved, tradeManager.pendingTradesInitializedProperty(), (a, b) -> a && b);
|
||||
tradesAndUIReady.subscribe((observable, oldValue, newValue) -> {
|
||||
if (newValue)
|
||||
applyTradePeriodState();
|
||||
});
|
||||
|
||||
walletService.addBalanceListener(new BalanceListener() {
|
||||
@Override
|
||||
public void onBalanceChanged(Coin balance) {
|
||||
@ -445,7 +440,7 @@ public class MainViewModel implements ViewModel {
|
||||
"when using Mainnet.")
|
||||
.headLine("Important information!")
|
||||
.actionButtonText("I understand and want to use Mainnet")
|
||||
.closeButtonText("Use Testnet and restart")
|
||||
.closeButtonText("Restart and use Testnet")
|
||||
.onClose(() -> {
|
||||
UserThread.execute(() -> preferences.setBitcoinNetwork(BitcoinNetwork.TESTNET));
|
||||
UserThread.runAfter(BitsquareApp.shutDownHandler::run, 300, TimeUnit.MILLISECONDS);
|
||||
@ -644,28 +639,40 @@ public class MainViewModel implements ViewModel {
|
||||
private void updateTradePeriodState() {
|
||||
tradeManager.getTrades().stream().forEach(trade -> {
|
||||
int bestChainHeight = tradeWalletService.getBestChainHeight();
|
||||
if (trade.getCheckPaymentTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getCheckPaymentTimeAsBlockHeight())
|
||||
trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED);
|
||||
|
||||
if (trade.getOpenDisputeTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getOpenDisputeTimeAsBlockHeight())
|
||||
trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER);
|
||||
else if (trade.getCheckPaymentTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getCheckPaymentTimeAsBlockHeight())
|
||||
trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED);
|
||||
|
||||
String id;
|
||||
String limitDate = formatter.addBlocksToNowDateFormatted(trade.getOpenDisputeTimeAsBlockHeight() - tradeWalletService.getBestChainHeight());
|
||||
switch (trade.getTradePeriodState()) {
|
||||
case NORMAL:
|
||||
break;
|
||||
case HALF_REACHED:
|
||||
if (!trade.isHalfTradePeriodReachedWarningDisplayed()) {
|
||||
id = "displayHalfTradePeriodOver" + trade.getId();
|
||||
if (preferences.showAgain(id)) {
|
||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||
" has reached the half of the max. allowed trading period and " +
|
||||
"is still not completed.\nPlease check your trade state at \"Portfolio/Open trades\" for further information.").show();
|
||||
trade.setHalfTradePeriodReachedWarningDisplayed(true);
|
||||
"is still not completed.\n\n" +
|
||||
"The trade period ends on " + limitDate + "\n\n" +
|
||||
"Please check your trade state at \"Portfolio/Open trades\" for further information.")
|
||||
.onClose(() -> preferences.dontShowAgain(id))
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
case TRADE_PERIOD_OVER:
|
||||
if (!trade.isTradePeriodOverWarningDisplayed()) {
|
||||
new Popup().warning("Your trade with ID " + trade.getShortId() + " has reached the max. allowed trading period and is " +
|
||||
"not completed.\nPlease check your trade at \"Portfolio/Open trades\" for contacting the arbitrator.").show();
|
||||
trade.setTradePeriodOverWarningDisplayed(true);
|
||||
id = "displayTradePeriodOver" + trade.getId();
|
||||
if (preferences.showAgain(id)) {
|
||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||
" has reached the max. allowed trading period and is " +
|
||||
"not completed.\n\n" +
|
||||
"The trade period ended on " + limitDate + "\n\n" +
|
||||
"Please check your trade at \"Portfolio/Open trades\" for contacting " +
|
||||
"the arbitrator.")
|
||||
.onClose(() -> preferences.dontShowAgain(id))
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel<GridPane, A
|
||||
GridPane.setMargin(table, new Insets(60, -10, 5, -10));
|
||||
root.getChildren().add(table);
|
||||
|
||||
autoSelectAllMatchingCheckBox = addCheckBox(root, ++gridRow, "Auto select all with matching language");
|
||||
autoSelectAllMatchingCheckBox = addCheckBox(root, ++gridRow, "Auto select all arbitrators with matching language");
|
||||
GridPane.setColumnSpan(autoSelectAllMatchingCheckBox, 2);
|
||||
GridPane.setHalignment(autoSelectAllMatchingCheckBox, HPos.LEFT);
|
||||
GridPane.setColumnIndex(autoSelectAllMatchingCheckBox, 0);
|
||||
|
@ -91,7 +91,6 @@ public class DebugView extends InitializableView {
|
||||
SendPublishDepositTxRequest.class,
|
||||
|
||||
ProcessDepositTxPublishedMessage.class,
|
||||
AddDepositTxToWallet.class,
|
||||
|
||||
VerifyTakeOfferFeePayment.class,
|
||||
SendFiatTransferStartedMessage.class,
|
||||
@ -169,7 +168,6 @@ public class DebugView extends InitializableView {
|
||||
SendPublishDepositTxRequest.class,
|
||||
|
||||
ProcessDepositTxPublishedMessage.class,
|
||||
AddDepositTxToWallet.class,
|
||||
|
||||
ProcessFiatTransferStartedMessage.class,
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
<TableView fx:id="table" VBox.vgrow="ALWAYS">
|
||||
<columns>
|
||||
<TableColumn text="Select" fx:id="selectColumn" minWidth="60" maxWidth="60" sortable="false"/>
|
||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="170" maxWidth="170"/>
|
||||
<TableColumn text="Details" fx:id="detailsColumn" minWidth="160" maxWidth="160"/>
|
||||
<TableColumn text="Address" fx:id="addressColumn" minWidth="320" maxWidth="320">
|
||||
@ -37,7 +38,6 @@
|
||||
</cellValueFactory>
|
||||
</TableColumn>
|
||||
<TableColumn text="Balance (BTC)" fx:id="balanceColumn" minWidth="110"/>
|
||||
<TableColumn text="Selection" fx:id="selectColumn" minWidth="160" sortable="false"/>
|
||||
</columns>
|
||||
</TableView>
|
||||
|
||||
@ -56,7 +56,8 @@
|
||||
<Label text="Withdraw to address:" GridPane.rowIndex="2"/>
|
||||
<TextField fx:id="withdrawToTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||
|
||||
<Button fx:id="withdrawButton" text="Withdraw" defaultButton="true" onAction="#onWithdraw" GridPane.rowIndex="3"
|
||||
<Button fx:id="withdrawButton" text="Withdraw selected" defaultButton="true" onAction="#onWithdraw"
|
||||
GridPane.rowIndex="3"
|
||||
GridPane.columnIndex="1"/>
|
||||
|
||||
<columnConstraints>
|
||||
|
@ -531,7 +531,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (checkBox == null) {
|
||||
checkBox = new CheckBox("Select for withdrawal");
|
||||
checkBox = new CheckBox();
|
||||
checkBox.setOnAction(e -> selectForWithdrawal(item, checkBox.isSelected()));
|
||||
setGraphic(checkBox);
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
||||
placeholder.setWrapText(true);
|
||||
tableView.setPlaceholder(placeholder);
|
||||
|
||||
Label titleLabel = new Label(direction.equals(Offer.Direction.BUY) ? "Buy-bitcoin offers (bid)" : "Sell-bitcoin offers (ask)");
|
||||
Label titleLabel = new Label(direction.equals(Offer.Direction.BUY) ? "Offers for buying bitcoin (bid)" : "Offers for selling bitcoin (ask)");
|
||||
titleLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-alignment: center");
|
||||
UserThread.execute(() -> titleLabel.prefWidthProperty().bind(tableView.widthProperty()));
|
||||
|
||||
@ -297,10 +297,10 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
||||
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis, "", ""));
|
||||
|
||||
seriesBuy = new XYChart.Series();
|
||||
seriesBuy.setName("Buy-bitcoin offers ");
|
||||
seriesBuy.setName("Offers for buying bitcoin ");
|
||||
|
||||
seriesSell = new XYChart.Series();
|
||||
seriesSell.setName("Sell-bitcoin offers");
|
||||
seriesSell.setName("Offers for selling bitcoin ");
|
||||
|
||||
areaChart = new AreaChart<>(xAxis, yAxis);
|
||||
areaChart.setAnimated(false);
|
||||
|
@ -30,5 +30,15 @@ public class BuyOfferView extends OfferView {
|
||||
public BuyOfferView(ViewLoader viewLoader, Navigation navigation) {
|
||||
super(viewLoader, navigation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCreateOfferTabName() {
|
||||
return "Create offer for buying bitcoin";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTakeOfferTabName() {
|
||||
return "Take offer for buying bitcoin";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
|
||||
createOfferView = (CreateOfferView) view;
|
||||
createOfferView.initWithData(direction, tradeCurrency);
|
||||
createOfferPane = createOfferView.getRoot();
|
||||
createOfferTab = new Tab("Create offer");
|
||||
createOfferTab = new Tab(getCreateOfferTabName());
|
||||
// close handler from close on create offer action
|
||||
createOfferView.setCloseHandler(() -> tabPane.getTabs().remove(createOfferTab));
|
||||
createOfferTab.setContent(createOfferPane);
|
||||
@ -163,7 +163,7 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
|
||||
takeOfferView = (TakeOfferView) view;
|
||||
takeOfferView.initWithData(offer);
|
||||
takeOfferPane = ((TakeOfferView) view).getRoot();
|
||||
takeOfferTab = new Tab("Take offer");
|
||||
takeOfferTab = new Tab(getTakeOfferTabName());
|
||||
// close handler from close on take offer action
|
||||
takeOfferView.setCloseHandler(() -> tabPane.getTabs().remove(takeOfferTab));
|
||||
takeOfferTab.setContent(takeOfferPane);
|
||||
@ -172,6 +172,10 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getCreateOfferTabName();
|
||||
|
||||
protected abstract String getTakeOfferTabName();
|
||||
|
||||
|
||||
private void onCreateOfferViewRemoved() {
|
||||
createOfferViewOpen = false;
|
||||
|
@ -30,5 +30,15 @@ public class SellOfferView extends OfferView {
|
||||
public SellOfferView(ViewLoader viewLoader, Navigation navigation) {
|
||||
super(viewLoader, navigation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCreateOfferTabName() {
|
||||
return "Create offer for selling bitcoin";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTakeOfferTabName() {
|
||||
return "Take offer for selling bitcoin";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,9 @@ import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.TradeWalletService;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.http.HttpException;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.crypto.KeyRing;
|
||||
import io.bitsquare.gui.common.model.ActivatableDataModel;
|
||||
import io.bitsquare.gui.popups.WalletPasswordPopup;
|
||||
@ -48,6 +50,7 @@ import org.bitcoinj.utils.ExchangeRate;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -85,7 +88,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
|
||||
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
|
||||
final BooleanProperty useMBTC = new SimpleBooleanProperty();
|
||||
final BooleanProperty insufficientFee = new SimpleBooleanProperty();
|
||||
final ObjectProperty<Coin> feeFromFundingTxProperty = new SimpleObjectProperty(Coin.NEGATIVE_SATOSHI);
|
||||
|
||||
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
|
||||
@ -96,6 +99,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
|
||||
|
||||
private PaymentAccount paymentAccount;
|
||||
private int retryRequestFeeCounter = 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -159,15 +163,21 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
btcCode.unbind();
|
||||
}
|
||||
|
||||
boolean isFeeFromFundingTxSufficient() {
|
||||
// if fee was never set because of api provider not available we check with default value and return true
|
||||
log.debug("FeePolicy.getFeePerKb() " + FeePolicy.getFeePerKb());
|
||||
log.debug("feeFromFundingTxProperty " + feeFromFundingTxProperty);
|
||||
log.debug(">? " + (feeFromFundingTxProperty.get().compareTo(FeePolicy.getFeePerKb()) >= 0));
|
||||
return feeFromFundingTxProperty.get().equals(Coin.NEGATIVE_SATOSHI) ||
|
||||
feeFromFundingTxProperty.get().compareTo(FeePolicy.getFeePerKb()) >= 0;
|
||||
}
|
||||
|
||||
private void addListeners() {
|
||||
walletService.addBalanceListener(balanceListener);
|
||||
walletService.getWallet().addEventListener(new WalletEventListener() {
|
||||
@Override
|
||||
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
||||
walletService.requestTransactionFromBlockChain(tx, fee -> {
|
||||
if (fee == null || fee.compareTo(FeePolicy.getFeePerKb()) < 0)
|
||||
insufficientFee.set(true);
|
||||
});
|
||||
requestFee(tx.getHashAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -197,6 +207,20 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
|
||||
}
|
||||
|
||||
private void requestFee(String transactionId) {
|
||||
try {
|
||||
feeFromFundingTxProperty.set(preferences.getBlockchainApiProvider().getFee(transactionId));
|
||||
} catch (IOException | HttpException e) {
|
||||
log.warn("Could not get fee from block explorer" + e);
|
||||
if (retryRequestFeeCounter < 3) {
|
||||
retryRequestFeeCounter++;
|
||||
log.warn("We try again after 5 seconds");
|
||||
// TODO if we have more providers, try another one
|
||||
UserThread.runAfter(() -> requestFee(transactionId), 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void removeListeners() {
|
||||
walletService.removeBalanceListener(balanceListener);
|
||||
|
@ -21,6 +21,7 @@ import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
@ -34,6 +35,8 @@ import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.account.AccountView;
|
||||
import io.bitsquare.gui.main.account.content.arbitratorselection.ArbitratorSelectionView;
|
||||
import io.bitsquare.gui.main.account.settings.AccountSettingsView;
|
||||
import io.bitsquare.gui.main.funds.FundsView;
|
||||
import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView;
|
||||
import io.bitsquare.gui.main.offer.OfferView;
|
||||
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
||||
import io.bitsquare.gui.main.portfolio.openoffer.OpenOffersView;
|
||||
@ -56,11 +59,13 @@ import javafx.scene.layout.*;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.stage.Window;
|
||||
import javafx.util.StringConverter;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.controlsfx.control.PopOver;
|
||||
import org.reactfx.util.FxTimer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
import static javafx.beans.binding.Bindings.createStringBinding;
|
||||
@ -78,7 +83,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
private BalanceTextField balanceTextField;
|
||||
private ProgressIndicator placeOfferSpinner;
|
||||
private TitledGroupBg payFundsPane;
|
||||
private Button showPaymentButton, placeOfferButton;
|
||||
private Button nextButton, cancelButton1, cancelButton2, placeOfferButton;
|
||||
private InputTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
|
||||
private TextField totalToPayTextField, currencyTextField;
|
||||
private Label buyLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel,
|
||||
@ -101,7 +106,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
private ChangeListener<String> errorMessageListener;
|
||||
private ChangeListener<Boolean> isPlaceOfferSpinnerVisibleListener;
|
||||
private ChangeListener<Boolean> showTransactionPublishedScreen;
|
||||
private ChangeListener<Boolean> insufficientFeeListener;
|
||||
private ChangeListener<Coin> feeFromFundingTxListener;
|
||||
private EventHandler<ActionEvent> paymentAccountsComboBoxSelectionHandler;
|
||||
|
||||
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
|
||||
@ -188,7 +193,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
public void onClose() {
|
||||
// we use model.requestPlaceOfferSuccess to not react on close caused by placeOffer
|
||||
if (model.dataModel.isWalletFunded.get() && !model.requestPlaceOfferSuccess.get())
|
||||
new Popup().warning("You have already funds paid in.\nIn the \"Funds/Open for withdrawal\" section you can withdraw those funds.").show();
|
||||
new Popup().warning("You have already funds paid in.\n" +
|
||||
"In the \"Funds/Open for withdrawal\" section you can withdraw those funds.").show();
|
||||
}
|
||||
|
||||
public void setCloseHandler(OfferView.CloseHandler closeHandler) {
|
||||
@ -236,7 +242,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
}
|
||||
}
|
||||
|
||||
showPaymentButton.setVisible(false);
|
||||
nextButton.setVisible(false);
|
||||
nextButton.setManaged(false);
|
||||
cancelButton1.setVisible(false);
|
||||
cancelButton1.setManaged(false);
|
||||
cancelButton1.setOnAction(null);
|
||||
|
||||
payFundsPane.setVisible(true);
|
||||
totalToPayLabel.setVisible(true);
|
||||
@ -246,6 +256,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
addressTextField.setVisible(true);
|
||||
balanceLabel.setVisible(true);
|
||||
balanceTextField.setVisible(true);
|
||||
cancelButton2.setVisible(true);
|
||||
root.requestFocus();
|
||||
|
||||
setupTotalToPayInfoIconLabel();
|
||||
|
||||
@ -423,15 +435,23 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
placeOfferSpinner.setVisible(newValue);
|
||||
};
|
||||
|
||||
insufficientFeeListener = (observable, oldValue, newValue) -> {
|
||||
if (newValue) {
|
||||
new Popup().warning("You need to use at least a mining fee of " +
|
||||
model.formatCoin(FeePolicy.getFeePerKb()) +
|
||||
".\n\nThe trade transactions might take too much time to be included in " +
|
||||
feeFromFundingTxListener = (observable, oldValue, newValue) -> {
|
||||
log.debug("feeFromFundingTxListener " + newValue);
|
||||
if (!model.dataModel.isFeeFromFundingTxSufficient()) {
|
||||
new Popup().warning("The mining fee from your funding transaction is not sufficiently high.\n\n" +
|
||||
"You need to use at least a mining fee of " +
|
||||
model.formatCoin(FeePolicy.getFeePerKb()) + ".\n\n" +
|
||||
"The fee used in your funding transaction was only " + model.formatCoin(newValue) + ".\n\n" +
|
||||
"The trade transactions might take too much time to be included in " +
|
||||
"a block if the fee is too low.\n" +
|
||||
"Please withdraw the amount you have funded back to your wallet and " +
|
||||
"do a funding again with the correct fee.")
|
||||
.onClose(() -> close())
|
||||
"Please check at your external wallet that you set the required fee and " +
|
||||
"do a funding again with the correct fee.\n\n" +
|
||||
"In the \"Funds/Open for withdrawal\" section you can withdraw those funds.")
|
||||
.closeButtonText("Close")
|
||||
.onClose(() -> {
|
||||
close();
|
||||
navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class);
|
||||
})
|
||||
.show();
|
||||
}
|
||||
};
|
||||
@ -451,7 +471,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
() -> {
|
||||
new Popup().headLine(BSResources.get("createOffer.success.headline"))
|
||||
.message(BSResources.get("createOffer.success.info"))
|
||||
.actionButtonText("Go to \"My offers\"")
|
||||
.actionButtonText("Go to \"My open offers\"")
|
||||
.onAction(() -> {
|
||||
close();
|
||||
FxTimer.runLater(Duration.ofMillis(100),
|
||||
@ -479,7 +499,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
model.showWarningAdjustedVolume.addListener(showWarningAdjustedVolumeListener);
|
||||
model.errorMessage.addListener(errorMessageListener);
|
||||
model.isPlaceOfferSpinnerVisible.addListener(isPlaceOfferSpinnerVisibleListener);
|
||||
model.dataModel.insufficientFee.addListener(insufficientFeeListener);
|
||||
model.dataModel.feeFromFundingTxProperty.addListener(feeFromFundingTxListener);
|
||||
|
||||
model.requestPlaceOfferSuccess.addListener(showTransactionPublishedScreen);
|
||||
|
||||
@ -501,7 +521,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
model.showWarningAdjustedVolume.removeListener(showWarningAdjustedVolumeListener);
|
||||
model.errorMessage.removeListener(errorMessageListener);
|
||||
model.isPlaceOfferSpinnerVisible.removeListener(isPlaceOfferSpinnerVisibleListener);
|
||||
model.dataModel.insufficientFee.removeListener(insufficientFeeListener);
|
||||
model.dataModel.feeFromFundingTxProperty.removeListener(feeFromFundingTxListener);
|
||||
|
||||
model.requestPlaceOfferSuccess.removeListener(showTransactionPublishedScreen);
|
||||
|
||||
@ -594,10 +614,16 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
|
||||
addMinAmountBox();
|
||||
|
||||
showPaymentButton = addButton(gridPane, ++gridRow, BSResources.get("createOffer.amountPriceBox.next"));
|
||||
GridPane.setMargin(showPaymentButton, new Insets(-35, 0, 0, 0));
|
||||
showPaymentButton.setId("show-details-button");
|
||||
showPaymentButton.setOnAction(e -> onShowFundsScreen());
|
||||
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, BSResources.get("createOffer.amountPriceBox.next"), BSResources.get("shared.cancel"));
|
||||
nextButton = tuple.first;
|
||||
UserThread.runAfter(() -> nextButton.requestFocus(), 100, TimeUnit.MILLISECONDS);
|
||||
cancelButton1 = tuple.second;
|
||||
cancelButton1.setDefaultButton(false);
|
||||
cancelButton1.setOnAction(e -> close());
|
||||
|
||||
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
|
||||
nextButton.setId("show-details-button");
|
||||
nextButton.setOnAction(e -> onShowFundsScreen());
|
||||
}
|
||||
|
||||
private void addFundingGroup() {
|
||||
@ -637,7 +663,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
balanceTextField = balanceTuple.second;
|
||||
balanceTextField.setVisible(false);
|
||||
|
||||
Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatus(gridPane, ++gridRow, BSResources.get("createOffer.fundsBox.placeOffer"));
|
||||
Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatus(gridPane, ++gridRow,
|
||||
BSResources.get("createOffer.fundsBox.placeOffer"));
|
||||
placeOfferButton = placeOfferTuple.first;
|
||||
placeOfferButton.setVisible(false);
|
||||
placeOfferButton.setOnAction(e -> onPlaceOffer());
|
||||
@ -645,6 +672,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
placeOfferSpinnerInfoLabel = placeOfferTuple.third;
|
||||
placeOfferSpinnerInfoLabel.setText(BSResources.get("createOffer.fundsBox.placeOfferSpinnerInfo"));
|
||||
placeOfferSpinnerInfoLabel.setVisible(false);
|
||||
|
||||
cancelButton2 = addButton(gridPane, ++gridRow, BSResources.get("shared.cancel"));
|
||||
cancelButton2.setOnAction(e -> close());
|
||||
cancelButton2.setDefaultButton(false);
|
||||
cancelButton2.setVisible(false);
|
||||
}
|
||||
|
||||
private void addAmountPriceFields() {
|
||||
@ -734,7 +766,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
infoGridPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
int i = 0;
|
||||
if (model.isSeller())
|
||||
if (model.isSellOffer())
|
||||
addPayInfoEntry(infoGridPane, i++, BSResources.get("createOffer.fundsBox.tradeAmount"), model.tradeAmount.get());
|
||||
|
||||
addPayInfoEntry(infoGridPane, i++, BSResources.get("createOffer.fundsBox.securityDeposit"), model.getSecurityDeposit());
|
||||
|
@ -92,6 +92,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
private ChangeListener<Fiat> priceAsFiatListener;
|
||||
private ChangeListener<Fiat> volumeAsFiatListener;
|
||||
private ChangeListener<Boolean> isWalletFundedListener;
|
||||
private ChangeListener<Coin> feeFromFundingTxListener;
|
||||
private ChangeListener<Boolean> requestPlaceOfferSuccessListener;
|
||||
private ChangeListener<String> requestPlaceOfferErrorMessageListener;
|
||||
private ChangeListener<String> errorMessageListener;
|
||||
@ -231,6 +232,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
volumeAsFiatListener = (ov, oldValue, newValue) -> volume.set(formatter.formatFiat(newValue));
|
||||
|
||||
isWalletFundedListener = (ov, oldValue, newValue) -> updateButtonDisableState();
|
||||
feeFromFundingTxListener = (ov, oldValue, newValue) -> updateButtonDisableState();
|
||||
requestPlaceOfferSuccessListener = (ov, oldValue, newValue) -> {
|
||||
isPlaceOfferButtonVisible.set(!newValue);
|
||||
isPlaceOfferSpinnerVisible.set(false);
|
||||
@ -254,7 +256,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
dataModel.minAmountAsCoin.addListener(minAmountAsCoinListener);
|
||||
dataModel.priceAsFiat.addListener(priceAsFiatListener);
|
||||
dataModel.volumeAsFiat.addListener(volumeAsFiatListener);
|
||||
|
||||
dataModel.feeFromFundingTxProperty.addListener(feeFromFundingTxListener);
|
||||
dataModel.isWalletFunded.addListener(isWalletFundedListener);
|
||||
requestPlaceOfferSuccess.addListener(requestPlaceOfferSuccessListener);
|
||||
errorMessage.addListener(requestPlaceOfferErrorMessageListener);
|
||||
@ -273,6 +275,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
dataModel.priceAsFiat.removeListener(priceAsFiatListener);
|
||||
dataModel.volumeAsFiat.removeListener(volumeAsFiatListener);
|
||||
|
||||
dataModel.feeFromFundingTxProperty.addListener(feeFromFundingTxListener);
|
||||
dataModel.isWalletFunded.removeListener(isWalletFundedListener);
|
||||
requestPlaceOfferSuccess.removeListener(requestPlaceOfferSuccessListener);
|
||||
errorMessage.removeListener(requestPlaceOfferErrorMessageListener);
|
||||
@ -432,7 +435,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
return dataModel.getDisplaySecurityDepositInfo();
|
||||
}
|
||||
|
||||
boolean isSeller() {
|
||||
boolean isSellOffer() {
|
||||
return dataModel.getDirection() == Offer.Direction.SELL;
|
||||
}
|
||||
|
||||
@ -549,13 +552,15 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||
}
|
||||
|
||||
private void updateButtonDisableState() {
|
||||
log.debug("updateButtonDisableState");
|
||||
isPlaceOfferButtonDisabled.set(
|
||||
!(isBtcInputValid(amount.get()).isValid &&
|
||||
isBtcInputValid(minAmount.get()).isValid &&
|
||||
isFiatInputValid(price.get()).isValid &&
|
||||
isFiatInputValid(volume.get()).isValid &&
|
||||
dataModel.isMinAmountLessOrEqualAmount() &&
|
||||
dataModel.isWalletFunded.get())
|
||||
dataModel.isWalletFunded.get() &&
|
||||
dataModel.isFeeFromFundingTxSufficient())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
paymentMethodComboBox.setConverter(new StringConverter<PaymentMethod>() {
|
||||
@Override
|
||||
public String toString(PaymentMethod paymentMethod) {
|
||||
return paymentMethod.getId();
|
||||
return BSResources.get(paymentMethod.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -189,7 +189,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
}
|
||||
|
||||
public void setDirection(Offer.Direction direction) {
|
||||
offerBookTitle.setText(direction == Offer.Direction.SELL ? "Buy-bitcoin offers" : "Sell-bitcoin offers");
|
||||
offerBookTitle.setText(direction == Offer.Direction.SELL ? "Offers for buying bitcoin " : "Offers for selling bitcoin ");
|
||||
model.setDirection(direction);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
private final OfferBook offerBook;
|
||||
private final Preferences preferences;
|
||||
private final P2PService p2PService;
|
||||
private final BSFormatter formatter;
|
||||
final BSFormatter formatter;
|
||||
|
||||
private final FilteredList<OfferBookListItem> filteredItems;
|
||||
private final SortedList<OfferBookListItem> sortedItems;
|
||||
|
@ -20,6 +20,7 @@ package io.bitsquare.gui.main.offer.takeoffer;
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
@ -56,6 +57,7 @@ import org.reactfx.util.FxTimer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
import static javafx.beans.binding.Bindings.createStringBinding;
|
||||
@ -74,7 +76,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
private BalanceTextField balanceTextField;
|
||||
private ProgressIndicator takeOfferSpinner;
|
||||
private TitledGroupBg payFundsPane;
|
||||
private Button showPaymentButton, takeOfferButton;
|
||||
private Button nextButton, takeOfferButton, cancelButton1, cancelButton2;
|
||||
private InputTextField amountTextField;
|
||||
private TextField paymentMethodTextField, currencyTextField, priceTextField, volumeTextField, amountRangeTextField;
|
||||
private Label buyLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel,
|
||||
@ -347,8 +349,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
}
|
||||
}
|
||||
|
||||
showPaymentButton.setVisible(false);
|
||||
nextButton.setVisible(false);
|
||||
cancelButton1.setVisible(false);
|
||||
cancelButton1.setOnAction(null);
|
||||
takeOfferButton.setVisible(true);
|
||||
cancelButton2.setVisible(true);
|
||||
|
||||
payFundsPane.setVisible(true);
|
||||
totalToPayLabel.setVisible(true);
|
||||
@ -458,10 +463,16 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
|
||||
addAmountRangeBox();
|
||||
|
||||
showPaymentButton = addButton(gridPane, ++gridRow, BSResources.get("takeOffer.amountPriceBox.next"));
|
||||
GridPane.setMargin(showPaymentButton, new Insets(-35, 0, 0, 0));
|
||||
showPaymentButton.setId("show-details-button");
|
||||
showPaymentButton.setOnAction(e -> onShowPayFundsScreen());
|
||||
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, BSResources.get("takeOffer.amountPriceBox.next"), BSResources.get("shared.cancel"));
|
||||
nextButton = tuple.first;
|
||||
UserThread.runAfter(() -> nextButton.requestFocus(), 100, TimeUnit.MILLISECONDS);
|
||||
cancelButton1 = tuple.second;
|
||||
cancelButton1.setDefaultButton(false);
|
||||
cancelButton1.setOnAction(e -> close());
|
||||
|
||||
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
|
||||
nextButton.setId("show-details-button");
|
||||
nextButton.setOnAction(e -> onShowPayFundsScreen());
|
||||
}
|
||||
|
||||
private void addFundingGroup() {
|
||||
@ -510,6 +521,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
takeOfferSpinnerInfoLabel = takeOfferTuple.third;
|
||||
takeOfferSpinnerInfoLabel.setText(BSResources.get("takeOffer.fundsBox.takeOfferSpinnerInfo"));
|
||||
takeOfferSpinnerInfoLabel.setVisible(false);
|
||||
|
||||
cancelButton2 = addButton(gridPane, ++gridRow, BSResources.get("shared.cancel"));
|
||||
cancelButton2.setOnAction(e -> close());
|
||||
cancelButton2.setDefaultButton(false);
|
||||
cancelButton2.setVisible(false);
|
||||
}
|
||||
|
||||
private void addAmountPriceFields() {
|
||||
|
@ -25,7 +25,7 @@
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" tabClosingPolicy="UNAVAILABLE"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
|
||||
<Tab fx:id="openOffersTab" text="My offers"/>
|
||||
<Tab fx:id="openOffersTab" text="My open offers"/>
|
||||
<Tab fx:id="pendingTradesTab" text="Open trades"/>
|
||||
<Tab fx:id="closedTradesTab" text="History"/>
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
<TableColumn text="Offer ID" fx:id="offerIdColumn" minWidth="100" sortable="false"/>
|
||||
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="130"/>
|
||||
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="130"/>
|
||||
<TableColumn text="Price" fx:id="priceColumn" minWidth="80"/>
|
||||
<TableColumn text="Price" fx:id="priceColumn" minWidth="100"/>
|
||||
<TableColumn text="Amount (Min.)" fx:id="volumeColumn" minWidth="130"/>
|
||||
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="70"/>
|
||||
<TableColumn text="" fx:id="removeItemColumn" minWidth="100" sortable="false"/>
|
||||
|
@ -58,7 +58,7 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
|
||||
}
|
||||
|
||||
String getPrice(OpenOfferListItem item) {
|
||||
return (item != null) ? formatter.formatFiat(item.getOffer().getPrice()) : "";
|
||||
return (item != null) ? formatter.formatPriceWithCode(item.getOffer().getPrice()) : "";
|
||||
}
|
||||
|
||||
String getVolume(OpenOfferListItem item) {
|
||||
|
@ -19,7 +19,6 @@ package io.bitsquare.gui.main.settings.preferences;
|
||||
|
||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.components.InputTextField;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.locale.LanguageUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
@ -46,7 +45,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||
private CheckBox useAnimationsCheckBox, useEffectsCheckBox, showPlaceOfferConfirmationCheckBox, showTakeOfferConfirmationCheckBox,
|
||||
autoSelectArbitratorsCheckBox;
|
||||
private int gridRow = 0;
|
||||
private InputTextField transactionFeeInputTextField;
|
||||
//private InputTextField transactionFeeInputTextField;
|
||||
private ChangeListener<Boolean> transactionFeeFocusedListener;
|
||||
|
||||
@Inject
|
||||
@ -56,15 +55,17 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
addTitledGroupBg(root, gridRow, 4, "Preferences");
|
||||
addTitledGroupBg(root, gridRow, 3, "Preferences");
|
||||
tradeCurrencyComboBox = addLabelComboBox(root, gridRow, "Preferred currency:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
languageComboBox = addLabelComboBox(root, ++gridRow, "Language:").second;
|
||||
// btcDenominationComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin denomination:").second;
|
||||
blockExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
|
||||
transactionFeeInputTextField = addLabelInputTextField(root, ++gridRow, "Transaction fee (satoshi/byte):").second;
|
||||
|
||||
// TODO need a bit extra work to separate trade and non trade tx fees before it can be used
|
||||
/*transactionFeeInputTextField = addLabelInputTextField(root, ++gridRow, "Transaction fee (satoshi/byte):").second;
|
||||
transactionFeeFocusedListener = (o, oldValue, newValue) -> {
|
||||
model.onFocusOutTransactionFeeTextField(oldValue, newValue);
|
||||
};
|
||||
};*/
|
||||
|
||||
addTitledGroupBg(root, ++gridRow, 5, "Display options", Layout.GROUP_DISTANCE);
|
||||
useAnimationsCheckBox = addLabelCheckBox(root, gridRow, "Use animations:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
@ -127,8 +128,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||
});
|
||||
blockExplorerComboBox.setOnAction(e -> model.onSelectBlockExplorer(blockExplorerComboBox.getSelectionModel().getSelectedItem()));
|
||||
|
||||
transactionFeeInputTextField.textProperty().bindBidirectional(model.transactionFeePerByte);
|
||||
transactionFeeInputTextField.focusedProperty().addListener(transactionFeeFocusedListener);
|
||||
// transactionFeeInputTextField.textProperty().bindBidirectional(model.transactionFeePerByte);
|
||||
// transactionFeeInputTextField.focusedProperty().addListener(transactionFeeFocusedListener);
|
||||
|
||||
useAnimationsCheckBox.setSelected(model.getUseAnimations());
|
||||
useAnimationsCheckBox.setOnAction(e -> model.onSelectUseAnimations(useAnimationsCheckBox.isSelected()));
|
||||
@ -152,8 +153,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||
languageComboBox.setOnAction(null);
|
||||
tradeCurrencyComboBox.setOnAction(null);
|
||||
blockExplorerComboBox.setOnAction(null);
|
||||
transactionFeeInputTextField.textProperty().unbind();
|
||||
transactionFeeInputTextField.focusedProperty().removeListener(transactionFeeFocusedListener);
|
||||
// transactionFeeInputTextField.textProperty().unbind();
|
||||
/// transactionFeeInputTextField.focusedProperty().removeListener(transactionFeeFocusedListener);
|
||||
useAnimationsCheckBox.setOnAction(null);
|
||||
useEffectsCheckBox.setOnAction(null);
|
||||
showPlaceOfferConfirmationCheckBox.setOnAction(null);
|
||||
|
@ -58,7 +58,7 @@ class PreferencesViewModel extends ActivatableViewModel {
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
transactionFeePerByte.set(String.valueOf(preferences.getTxFeePerKB() / 1024));
|
||||
transactionFeePerByte.set(String.valueOf(preferences.getTxFeePerKB() / 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -108,12 +108,12 @@ class PreferencesViewModel extends ActivatableViewModel {
|
||||
public void onFocusOutTransactionFeeTextField(Boolean oldValue, Boolean newValue) {
|
||||
if (oldValue && !newValue) {
|
||||
try {
|
||||
preferences.setTxFeePerKB(Long.parseLong(transactionFeePerByte.get()) * 1024);
|
||||
preferences.setTxFeePerKB(Long.parseLong(transactionFeePerByte.get()) * 1000);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error at onFocusOutTransactionFeeTextField: " + e.getMessage());
|
||||
new Popup().warning(e.getMessage())
|
||||
.onClose(() -> UserThread.runAfter(
|
||||
() -> transactionFeePerByte.set(String.valueOf(preferences.getTxFeePerKB() / 1024)),
|
||||
() -> transactionFeePerByte.set(String.valueOf(preferences.getTxFeePerKB() / 1000)),
|
||||
100, TimeUnit.MILLISECONDS))
|
||||
.show();
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ public class ContractPopup extends Popup {
|
||||
Layout.FIRST_ROW_DISTANCE).second.setMouseTransparent(false);
|
||||
addLabelTextField(gridPane, ++rowIndex, "Offer date:", formatter.formatDateTime(offer.getDate()));
|
||||
addLabelTextField(gridPane, ++rowIndex, "Trade date:", formatter.formatDateTime(dispute.getTradeDate()));
|
||||
addLabelTextField(gridPane, ++rowIndex, "Trade type:", formatter.getDirectionDescription(offer.getDirection()));
|
||||
addLabelTextField(gridPane, ++rowIndex, "Trade type:", formatter.getDirectionBothSides(offer.getDirection()));
|
||||
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
|
||||
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(contract.getTradeAmount()));
|
||||
addLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, "Buyer bitcoin address:",
|
||||
|
@ -130,7 +130,7 @@ public class OfferDetailsPopup extends Popup {
|
||||
rows++;
|
||||
|
||||
addTitledGroupBg(gridPane, ++rowIndex, rows, "Offer");
|
||||
addLabelTextField(gridPane, rowIndex, "Offer type:", formatter.getDirectionDescription(offer.getDirection()), Layout.FIRST_ROW_DISTANCE);
|
||||
addLabelTextField(gridPane, rowIndex, "Offer type:", formatter.getOfferDirection(offer.getDirection()), Layout.FIRST_ROW_DISTANCE);
|
||||
addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode());
|
||||
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode() + "/" + "BTC");
|
||||
if (takeOfferHandlerOptional.isPresent()) {
|
||||
|
@ -95,7 +95,7 @@ public class TradeDetailsPopup extends Popup {
|
||||
|
||||
int rows = 5;
|
||||
addTitledGroupBg(gridPane, ++rowIndex, rows, "Trade");
|
||||
addLabelTextField(gridPane, rowIndex, "Trade type:", formatter.getDirectionDescription(offer.getDirection()), Layout.FIRST_ROW_DISTANCE);
|
||||
addLabelTextField(gridPane, rowIndex, "Trade type:", formatter.getDirectionBothSides(offer.getDirection()), Layout.FIRST_ROW_DISTANCE);
|
||||
addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode());
|
||||
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
|
||||
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(trade.getTradeAmount()));
|
||||
|
@ -217,6 +217,10 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
public String formatPriceWithCode(Fiat fiat) {
|
||||
return formatFiatWithCode(fiat) + "/BTC";
|
||||
}
|
||||
|
||||
private Fiat parseToFiat(String input, String currencyCode) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
@ -264,7 +268,7 @@ public class BSFormatter {
|
||||
|
||||
|
||||
public String getDirection(Offer.Direction direction) {
|
||||
return getDirection(direction, true);
|
||||
return getDirection(direction, false) + " bitcoin";
|
||||
}
|
||||
|
||||
private String getDirection(Offer.Direction direction, boolean allUpperCase) {
|
||||
@ -338,13 +342,46 @@ public class BSFormatter {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String getDateFromBlocks(long blocks) {
|
||||
public Date addBlocksToNowDate(long blocks) {
|
||||
return new Date(new Date().getTime() + blocks * TimeUnit.MINUTES.toMillis(10));
|
||||
}
|
||||
|
||||
public String addBlocksToNowDateFormatted(long blocks) {
|
||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
|
||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
|
||||
Date date = new Date(new Date().getTime() + blocks * TimeUnit.MINUTES.toMillis(10));
|
||||
Date date = addBlocksToNowDate(blocks);
|
||||
return dateFormatter.format(date) + " " + timeFormatter.format(date);
|
||||
}
|
||||
|
||||
public String getPeriodBetweenBlockHeights(long startBlockHeight, long endBlockHeight) {
|
||||
return getDaysHoursMinutes(addBlocksToNowDate(startBlockHeight), addBlocksToNowDate(endBlockHeight));
|
||||
}
|
||||
|
||||
public String getDaysHoursMinutes(Date startDate, Date endDate) {
|
||||
long different = endDate.getTime() - startDate.getTime();
|
||||
long secondsInMilli = 1000;
|
||||
long minutesInMilli = secondsInMilli * 60;
|
||||
long hoursInMilli = minutesInMilli * 60;
|
||||
long daysInMilli = hoursInMilli * 24;
|
||||
long elapsedDays = different / daysInMilli;
|
||||
different = different % daysInMilli;
|
||||
long elapsedHours = different / hoursInMilli;
|
||||
different = different % hoursInMilli;
|
||||
long elapsedMinutes = different / minutesInMilli;
|
||||
String dayString = elapsedDays == 1 ? "day" : "days";
|
||||
String hourString = elapsedHours == 1 ? "hour" : "hours";
|
||||
String minuteString = elapsedMinutes == 1 ? "minute" : "minutes";
|
||||
if (elapsedDays > 0)
|
||||
return elapsedDays + " " + dayString + ", " + elapsedHours + " " + hourString + " and " + elapsedMinutes + " " + minuteString;
|
||||
else if (elapsedHours > 0)
|
||||
return elapsedHours + " " + hourString + " and " + elapsedMinutes + " " + minuteString;
|
||||
else if (elapsedMinutes > 0)
|
||||
return elapsedMinutes + " " + minuteString;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String booleanToYesNo(boolean value) {
|
||||
return value ? "Yes" : "No";
|
||||
}
|
||||
@ -362,10 +399,14 @@ public class BSFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
public String getDirectionDescription(Offer.Direction direction) {
|
||||
public String getDirectionBothSides(Offer.Direction direction) {
|
||||
return direction == Offer.Direction.BUY ? "Offerer as bitcoin buyer / Taker as bitcoin seller" : "Offerer as bitcoin seller / Taker as bitcoin buyer";
|
||||
}
|
||||
|
||||
public String getOfferDirection(Offer.Direction direction) {
|
||||
return direction == Offer.Direction.BUY ? "Offer for buying bitcoin" : "Offer for selling bitcoin";
|
||||
}
|
||||
|
||||
public String getRole(boolean isBuyerOffererAndSellerTaker, boolean isOfferer) {
|
||||
if (isBuyerOffererAndSellerTaker)
|
||||
return isOfferer ? "Buyer (offerer)" : "Seller (taker)";
|
||||
|
@ -602,18 +602,25 @@ public class FormBuilder {
|
||||
// Button + Button
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static Tuple2<Button, Button> add2ButtonsAfterGroup(GridPane gridPane,
|
||||
public static Tuple2<Button, Button> add2Buttons(GridPane gridPane,
|
||||
int rowIndex,
|
||||
String title1,
|
||||
String title2) {
|
||||
return add2ButtonsAfterGroup(gridPane, rowIndex, title1, title2, 15);
|
||||
return add2Buttons(gridPane, rowIndex, title1, title2, 0);
|
||||
}
|
||||
|
||||
public static Tuple2<Button, Button> add2ButtonsAfterGroup(GridPane gridPane,
|
||||
int rowIndex,
|
||||
String title1,
|
||||
String title2,
|
||||
double top) {
|
||||
String title2) {
|
||||
return add2Buttons(gridPane, rowIndex, title1, title2, 15);
|
||||
}
|
||||
|
||||
public static Tuple2<Button, Button> add2Buttons(GridPane gridPane,
|
||||
int rowIndex,
|
||||
String title1,
|
||||
String title2,
|
||||
double top) {
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(10);
|
||||
Button button1 = new Button(title1);
|
||||
|
@ -50,7 +50,7 @@ createOffer.validation.amountSmallerThanMinAmount=Amount cannot be smaller than
|
||||
createOffer.validation.minAmountLargerThanAmount=Minimum amount cannot be larger than amount.
|
||||
|
||||
createOffer.fundsBox.title=Fund your trade wallet
|
||||
createOffer.fundsBox.totalsNeeded=Funds needed for that trade:
|
||||
createOffer.fundsBox.totalsNeeded=Funds needed:
|
||||
createOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the bitcoin amount entered above
|
||||
createOffer.fundsBox.address=Trade wallet address:
|
||||
createOffer.fundsBox.balance=Trade wallet balance:
|
||||
@ -75,8 +75,8 @@ createOffer.advancedBox.currency=Currency:
|
||||
createOffer.advancedBox.county=Payments account country:
|
||||
createOffer.advancedBox.info=Your trading partners must fulfill your offer restrictions. You can edit the accepted countries, languages and arbitrators in the settings. The payments account details are used from your current selected payments account (if you have multiple payments accounts).
|
||||
|
||||
createOffer.success.headline=Your offer has been published to the P2P network.
|
||||
createOffer.success.info=You can manage your open offers in the \"Portfolio\" screen under \"My offers\".
|
||||
createOffer.success.headline=Your offer has been published.
|
||||
createOffer.success.info=You can manage your open offers in the \"Portfolio\" screen under \"My open offers\".
|
||||
|
||||
createOffer.error.message=An error occurred when placing the offer.\n\n{0}
|
||||
|
||||
@ -105,7 +105,7 @@ takeOffer.validation.amountLargerThanOfferAmountMinusFee=That input amount would
|
||||
|
||||
takeOffer.fundsBox.title=Fund your trade wallet
|
||||
takeOffer.fundsBox.isOfferAvailable=Check if offer is available...
|
||||
takeOffer.fundsBox.totalsNeeded=Funds needed for that trade:
|
||||
takeOffer.fundsBox.totalsNeeded=Funds needed:
|
||||
takeOffer.fundsBox.totalsNeeded.prompt=Will be calculated from the bitcoin amount entered above
|
||||
takeOffer.fundsBox.address=Trade wallet address:
|
||||
takeOffer.fundsBox.balance=Trade wallet balance:
|
||||
|
@ -10,11 +10,12 @@
|
||||
<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="TRACE"/>
|
||||
|
||||
<logger name="io.bitsquare.storage.Storage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
|
||||
|
||||
<logger name="io.bitsquare.p2p.P2PService" level="TRACE"/>
|
||||
<logger name="io.bitsquare.p2p.storage.ProtectedExpirableDataStorage" level="TRACE"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user