Add popups

This commit is contained in:
Manfred Karrer 2015-11-16 15:20:50 +01:00
parent 8bf207b656
commit cb8761b74e
32 changed files with 178 additions and 117 deletions

View File

@ -21,7 +21,9 @@ public class PopupId {
// We don't use an enum because it would break updates if we add a new item in a new version
public static String SEC_DEPOSIT = "SEC_DEPOSIT";
public static String TRADE_WALLET = "TRADE_WALLET";
public static String TRADE_WALLET = "tradeWallet";
public static String SEND_PAYMENT_INFO = "sendPaymentInfo";
public static String PAYMENT_SENT = "paymentSent";
public static String PAYMENT_RECEIVED = "paymentReceived";
}

View File

@ -143,8 +143,10 @@ public class Preferences implements Serializable {
showTakeOfferConfirmation = true;
showAgainMap = new HashMap<>();
showAgainMap.put(PopupId.SEC_DEPOSIT, true);
showAgainMap.put(PopupId.TRADE_WALLET, true);
showAgainMap.put(PopupId.SEND_PAYMENT_INFO, true);
showAgainMap.put(PopupId.PAYMENT_SENT, true);
showAgainMap.put(PopupId.PAYMENT_RECEIVED, true);
storage.queueUpForSave();
}
@ -345,6 +347,10 @@ public class Preferences implements Serializable {
return showAgainMap;
}
public boolean showAgain(String key) {
return getShowAgainMap().containsKey(key) && getShowAgainMap().get(key);
}
public boolean getTacAccepted() {
return tacAccepted;
}

View File

@ -269,7 +269,11 @@ public class User implements Serializable {
}*/
public Arbitrator getAcceptedArbitratorByAddress(Address address) {
return acceptedArbitrators.stream().filter(e -> e.getArbitratorAddress().equals(address)).findFirst().get();
Optional<Arbitrator> arbitratorOptional = acceptedArbitrators.stream().filter(e -> e.getArbitratorAddress().equals(address)).findFirst();
if (arbitratorOptional.isPresent())
return arbitratorOptional.get();
else
return null;
}

View File

@ -73,7 +73,7 @@ import static io.bitsquare.app.BitsquareEnvironment.APP_NAME_KEY;
public class BitsquareApp extends Application {
private static final Logger log = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(BitsquareApp.class);
public static final boolean DEV_MODE = true;
public static final boolean DEV_MODE = false;
private static Environment env;

View File

@ -31,6 +31,7 @@ import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
@ -94,6 +95,7 @@ public class OKPayForm extends PaymentMethodForm {
checkBox.setSelected(okPayAccount.getTradeCurrencies().contains(e));
checkBox.setMinWidth(60);
checkBox.setMaxWidth(checkBox.getMinWidth());
checkBox.setTooltip(new Tooltip(e.getName()));
checkBox.setOnAction(event -> {
if (checkBox.isSelected())
okPayAccount.addCurrency(e);

View File

@ -34,6 +34,7 @@ import javafx.geometry.VPos;
import javafx.scene.control.*;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.TextAlignment;
import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -98,9 +99,9 @@ public class SepaForm extends PaymentMethodForm {
});
Tuple2<Label, ComboBox> tuple2 = addLabelComboBox(gridPane, ++gridRow, "Country of Bank:");
Tuple2<Label, ComboBox> tuple2 = addLabelComboBox(gridPane, ++gridRow, "Country of your Bank:");
ComboBox<Country> countryComboBox = tuple2.second;
countryComboBox.setPromptText("Select country of Bank");
countryComboBox.setPromptText("Select country of your Bank");
countryComboBox.setConverter(new StringConverter<Country>() {
@Override
public String toString(Country country) {
@ -141,15 +142,18 @@ public class SepaForm extends PaymentMethodForm {
}
private void addEuroCountriesGrid(boolean isEditable) {
addCountriesGrid(isEditable, "Accept taker countries (Euro):", euroCountryCheckBoxes, CountryUtil.getAllSepaEuroCountries());
addCountriesGrid(isEditable, "Accept trades from those Euro countries:", euroCountryCheckBoxes, CountryUtil.getAllSepaEuroCountries());
}
private void addNonEuroCountriesGrid(boolean isEditable) {
addCountriesGrid(isEditable, "Accepted taker countries (non-Euro):", nonEuroCountryCheckBoxes, CountryUtil.getAllSepaNonEuroCountries());
addCountriesGrid(isEditable, "Accept trades from those non-Euro countries:", nonEuroCountryCheckBoxes, CountryUtil.getAllSepaNonEuroCountries());
}
private void addCountriesGrid(boolean isEditable, String title, List<CheckBox> checkBoxList, List<Country> dataProvider) {
Label label = addLabel(gridPane, ++gridRow, title, 0);
label.setWrapText(true);
label.setPrefWidth(200);
label.setTextAlignment(TextAlignment.RIGHT);
GridPane.setValignment(label, VPos.TOP);
FlowPane flowPane = new FlowPane();
flowPane.setPadding(new Insets(10, 10, 10, 10));
@ -169,7 +173,6 @@ public class SepaForm extends PaymentMethodForm {
checkBoxList.add(checkBox);
checkBox.setMouseTransparent(!isEditable);
checkBox.setMinWidth(45);
checkBox.setMaxWidth(checkBox.getMinWidth());
checkBox.setTooltip(new Tooltip(country.name));
checkBox.setOnAction(event -> {
if (checkBox.isSelected())

View File

@ -338,7 +338,7 @@ class MainViewModel implements ViewModel {
// tac
if (!preferences.getTacAccepted() && !BitsquareApp.DEV_MODE)
new TacPopup().url(WebViewPopup.getLocalUrl("tac.html")).onAgree(() -> preferences.setTacAccepted(true)).show();
new TacPopup().url(WebViewPopup.getLocalUrl("tac")).onAgree(() -> preferences.setTacAccepted(true)).show();
// update nr of peers in footer

View File

@ -196,8 +196,8 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel<VBox, Ar
addTitledGroupBg(gridPane, ++gridRow, 2, "Information", Layout.GROUP_DISTANCE);
Label infoLabel = addMultilineLabel(gridPane, gridRow);
GridPane.setMargin(infoLabel, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0));
infoLabel.setText("Please not that you need to stay available for 15 days after revoking as there might be trades which are using you as " +
"arbitrator. The max. allowed trader period is 8 days and the dispute process might take up to 7 days.");
infoLabel.setText("Please note that you need to stay available for 15 days after revoking as there might be trades which are using you as " +
"arbitrator. The max. allowed trade period is 8 days and the dispute process might take up to 7 days.");
}
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,6 @@ import io.bitsquare.gui.util.Layout;
import io.bitsquare.locale.LanguageUtil;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.ListChangeListener;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.control.*;
@ -192,12 +191,6 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel<GridPane, A
GridPane.setMargin(autoSelectAllMatchingCheckBox, new Insets(0, -10, 0, -10));
autoSelectAllMatchingCheckBox.setOnAction(event -> model.setAutoSelectArbitrators(autoSelectAllMatchingCheckBox.isSelected()));
Button reloadButton = addButton(root, gridRow, "Reload");
GridPane.setColumnIndex(reloadButton, 1);
GridPane.setHalignment(reloadButton, HPos.RIGHT);
GridPane.setMargin(reloadButton, new Insets(0, -10, 0, -10));
reloadButton.setOnAction(event -> model.reload());
TableColumn<ArbitratorListItem, String> dateColumn = new TableColumn("Registration date");
dateColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper(param.getValue().getRegistrationDate()));
dateColumn.setMinWidth(130);

View File

@ -130,10 +130,6 @@ class ArbitratorSelectionViewModel extends ActivatableDataModel {
return user.isMyOwnRegisteredArbitrator(arbitrator);
}
public void reload() {
arbitratorManager.applyArbitrators();
}
private void updateAutoSelectArbitrators() {
if (preferences.getAutoSelectArbitrators()) {
arbitratorListItems.stream().forEach(item -> {

View File

@ -25,7 +25,7 @@ import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.funds.reserved.ReservedView;
import io.bitsquare.gui.main.funds.transactions.TransactionsView;
import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView;
import io.bitsquare.gui.popups.FirstTimePopup;
import io.bitsquare.gui.popups.FirstTimeWebViewPopup;
import io.bitsquare.gui.popups.WebViewPopup;
import io.bitsquare.user.PopupId;
import io.bitsquare.user.Preferences;
@ -85,8 +85,9 @@ public class FundsView extends ActivatableViewAndModel<TabPane, Activatable> {
else if (root.getSelectionModel().getSelectedItem() == transactionsTab)
navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class);
if (preferences.getShowAgainMap().get(PopupId.TRADE_WALLET) && !BitsquareApp.DEV_MODE)
new FirstTimePopup(preferences).url(WebViewPopup.getLocalUrl("tradeWallet.html")).show();
String key = PopupId.TRADE_WALLET;
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE)
new FirstTimeWebViewPopup(preferences).id(key).url(WebViewPopup.getLocalUrl(key)).show();
}
@Override

View File

@ -21,19 +21,14 @@ import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.listeners.AddressConfidenceListener;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.BSFormatter;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.core.TransactionOutput;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.control.*;
import javafx.scene.control.Tooltip;
import org.bitcoinj.core.*;
public class TransactionsListItem {
private final StringProperty date = new SimpleStringProperty();
private final StringProperty amount = new SimpleStringProperty();
private final StringProperty type = new SimpleStringProperty();
@ -44,6 +39,7 @@ public class TransactionsListItem {
private final Tooltip tooltip;
private String addressString;
private boolean notAnAddress;
private AddressConfidenceListener confidenceListener;
public TransactionsListItem(Transaction transaction, WalletService walletService, BSFormatter formatter) {
@ -64,14 +60,13 @@ public class TransactionsListItem {
address =
transactionOutput.getScriptPubKey().getToAddress(walletService.getWallet().getParams());
addressString = address.toString();
}
else {
} else {
addressString = "No sent to address script used.";
notAnAddress = true;
}
}
}
}
else if (valueSentFromMe.isZero()) {
} else if (valueSentFromMe.isZero()) {
amount.set(formatter.formatCoin(valueSentToMe));
type.set("Received with");
@ -82,14 +77,13 @@ public class TransactionsListItem {
address =
transactionOutput.getScriptPubKey().getToAddress(walletService.getWallet().getParams());
addressString = address.toString();
}
else {
} else {
addressString = "No sent to address script used.";
notAnAddress = true;
}
}
}
}
else {
} else {
amount.set(formatter.formatCoin(valueSentToMe.subtract(valueSentFromMe)));
boolean outgoing = false;
for (TransactionOutput transactionOutput : transaction.getOutputs()) {
@ -100,19 +94,19 @@ public class TransactionsListItem {
address = transactionOutput.getScriptPubKey().getToAddress(walletService.getWallet().getParams
());
addressString = address.toString();
}
else {
} else {
addressString = "No sent to address script used.";
notAnAddress = true;
}
}
}
if (outgoing) {
type.set("Sent to");
}
else {
} else {
type.set("Internal (TX Fee)");
addressString = "Internal swap between addresses.";
notAnAddress = true;
}
}
@ -194,5 +188,9 @@ public class TransactionsListItem {
public String getAddressString() {
return addressString;
}
public boolean isNotAnAddress() {
return notAnAddress;
}
}

View File

@ -40,8 +40,10 @@ import java.util.stream.Collectors;
@FxmlView
public class TransactionsView extends ActivatableView<VBox, Void> {
@FXML TableView<TransactionsListItem> table;
@FXML TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn,
@FXML
TableView<TransactionsListItem> table;
@FXML
TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, addressColumn, amountColumn, typeColumn,
confidenceColumn;
private ObservableList<TransactionsListItem> transactionsListItems;
@ -85,12 +87,14 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
// TODO Open popup with details view
log.debug("openTxDetails " + item);
try {
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
} catch (Exception e) {
log.error(e.getMessage());
new Popup().warning("Opening browser failed. Please check your internet " +
"connection.").show();
if (!item.isNotAnAddress()) {
try {
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
} catch (Exception e) {
log.error(e.getMessage());
new Popup().warning("Opening browser failed. Please check your internet " +
"connection.").show();
}
}
}
@ -114,8 +118,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
hyperlink = new Hyperlink(item.getAddressString());
hyperlink.setOnAction(event -> openTxDetails(item));
setGraphic(hyperlink);
}
else {
} else {
setGraphic(null);
setId(null);
}
@ -143,8 +146,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
if (item != null && !empty) {
setGraphic(item.getProgressIndicator());
}
else {
} else {
setGraphic(null);
}
}

View File

@ -203,7 +203,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
formatter.formatCoinWithCode(FeePolicy.TX_FEE) + "\n" +
"Receivers amount: " +
formatter.formatCoinWithCode(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" +
"Are you sure you withdraw that amount?")
"Are you sure you want to withdraw that amount?")
.onAction(() -> {
doWithdraw(amount, callback);
})

View File

@ -56,8 +56,8 @@ public class BuyerSubView extends TradeSubView {
@Override
protected void addWizards() {
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
startPayment = new TradeWizardItem(StartPaymentView.class, "Start EUR payment");
waitPaymentReceived = new TradeWizardItem(WaitPaymentReceivedView.class, "Wait until EUR payment arrived");
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");

View File

@ -36,6 +36,7 @@ import io.bitsquare.gui.popups.WalletPasswordPopup;
import io.bitsquare.payment.PaymentAccountContractData;
import io.bitsquare.trade.*;
import io.bitsquare.trade.offer.Offer;
import io.bitsquare.user.Preferences;
import io.bitsquare.user.User;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
@ -69,6 +70,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
private final ObjectProperty<Trade> tradeProperty = new SimpleObjectProperty<>();
private final StringProperty txId = new SimpleStringProperty();
private Trade trade;
private Preferences preferences;
///////////////////////////////////////////////////////////////////////////////////////////
@ -77,7 +79,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
@Inject
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, TradeWalletService tradeWalletService,
User user, KeyRing keyRing, DisputeManager disputeManager,
User user, KeyRing keyRing, DisputeManager disputeManager, Preferences preferences,
Navigation navigation, WalletPasswordPopup walletPasswordPopup) {
this.tradeManager = tradeManager;
this.walletService = walletService;
@ -85,6 +87,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
this.user = user;
this.keyRing = keyRing;
this.disputeManager = disputeManager;
this.preferences = preferences;
this.navigation = navigation;
this.walletPasswordPopup = walletPasswordPopup;
@ -323,6 +326,10 @@ public class PendingTradesDataModel extends ActivatableDataModel {
return disputeManager;
}
public Preferences getPreferences() {
return preferences;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Utils

View File

@ -56,8 +56,8 @@ 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 EUR payment has started");
confirmPaymentReceived = new TradeWizardItem(ConfirmPaymentReceivedView.class, "Confirm EUR payment received");
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");
@ -110,11 +110,11 @@ public class SellerSubView extends TradeSubView {
showItem(confirmPaymentReceived);
if (model.isBlockChainMethod()) {
((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment." +
((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." +
((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()));
}

View File

@ -17,10 +17,13 @@
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
import io.bitsquare.app.BitsquareApp;
import io.bitsquare.gui.components.TxIdTextField;
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
import io.bitsquare.gui.popups.Popup;
import io.bitsquare.gui.util.Layout;
import io.bitsquare.user.PopupId;
import io.bitsquare.user.Preferences;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.geometry.HPos;
@ -105,13 +108,23 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView {
private void onPaymentReceived(ActionEvent actionEvent) {
log.debug("onPaymentReceived");
if (model.isAuthenticated()) {
confirmFiatReceivedButton.setDisable(true);
Preferences preferences = model.dataModel.getPreferences();
String key = PopupId.PAYMENT_RECEIVED;
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
new Popup().information("Please note that as soon you have confirmed that you have received the " +
"payment the locked Bitcoin will be released.\n" +
"There is no way to reverse a Bitcoin payment. Confirm only if you are sure.")
.onClose(() -> preferences.dontShowAgain(key))
.show();
} else {
confirmFiatReceivedButton.setDisable(true);
statusProgressIndicator.setVisible(true);
statusProgressIndicator.setProgress(-1);
statusLabel.setText("Sending message to trading partner...");
statusProgressIndicator.setVisible(true);
statusProgressIndicator.setProgress(-1);
statusLabel.setText("Sending message to trading partner...");
model.fiatPaymentReceived();
model.fiatPaymentReceived();
}
} else {
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
"That might take up to about 2 minutes at startup.").show();

View File

@ -17,6 +17,7 @@
package io.bitsquare.gui.main.portfolio.pendingtrades.steps;
import io.bitsquare.app.BitsquareApp;
import io.bitsquare.common.util.Tuple3;
import io.bitsquare.gui.components.TitledGroupBg;
import io.bitsquare.gui.components.TxIdTextField;
@ -26,6 +27,8 @@ import io.bitsquare.gui.popups.Popup;
import io.bitsquare.gui.util.Layout;
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;
@ -37,6 +40,7 @@ import javafx.scene.layout.GridPane;
import static io.bitsquare.gui.util.FormBuilder.*;
public class StartPaymentView extends TradeStepDetailsView {
private final Preferences preferences;
private TxIdTextField txIdTextField;
private Button paymentStartedButton;
@ -55,6 +59,7 @@ public class StartPaymentView extends TradeStepDetailsView {
public StartPaymentView(PendingTradesViewModel model) {
super(model);
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue);
preferences = model.dataModel.getPreferences();
}
@Override
@ -63,6 +68,16 @@ public class StartPaymentView extends TradeStepDetailsView {
model.getTxId().addListener(txIdChangeListener);
txIdTextField.setup(model.getTxId().get());
String key = PopupId.SEND_PAYMENT_INFO;
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
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 if you have before you have completed the transfer.\n" +
"Take care that you make the transfer soon to not miss the exceed trading period.")
.onClose(() -> preferences.dontShowAgain(key))
.show();
}
}
@Override
@ -126,13 +141,21 @@ public class StartPaymentView extends TradeStepDetailsView {
private void onPaymentStarted(ActionEvent actionEvent) {
log.debug("onPaymentStarted");
if (model.isAuthenticated()) {
paymentStartedButton.setDisable(true);
String key = PopupId.PAYMENT_SENT;
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
new Popup().information("You are confirming that you have transferred the payment to your trading partner.\n" +
"Please click the \"Payment started\" button only if you have completed the transfer.")
.onClose(() -> preferences.dontShowAgain(key))
.show();
} else {
paymentStartedButton.setDisable(true);
statusProgressIndicator.setVisible(true);
statusProgressIndicator.setProgress(-1);
statusLabel.setText("Sending message to trading partner...");
statusProgressIndicator.setVisible(true);
statusProgressIndicator.setProgress(-1);
statusLabel.setText("Sending message to trading partner...");
model.fiatPaymentStarted();
model.fiatPaymentStarted();
}
} else {
new Popup().warning("You need to wait until your client is authenticated in the network.\n" +
"That might take up to about 2 minutes at startup.").show();

View File

@ -29,8 +29,8 @@ import java.util.Optional;
import static io.bitsquare.gui.util.FormBuilder.addCheckBox;
public class FirstTimePopup extends WebViewPopup {
private static final Logger log = LoggerFactory.getLogger(FirstTimePopup.class);
public class FirstTimeWebViewPopup extends WebViewPopup {
private static final Logger log = LoggerFactory.getLogger(FirstTimeWebViewPopup.class);
private Preferences preferences;
private String id;
@ -39,22 +39,22 @@ public class FirstTimePopup extends WebViewPopup {
// Public API
///////////////////////////////////////////////////////////////////////////////////////////
public FirstTimePopup(Preferences preferences) {
public FirstTimeWebViewPopup(Preferences preferences) {
this.preferences = preferences;
}
@Override
public FirstTimePopup url(String url) {
public FirstTimeWebViewPopup url(String url) {
super.url(url);
return this;
}
public FirstTimePopup onClose(Runnable closeHandler) {
public FirstTimeWebViewPopup onClose(Runnable closeHandler) {
this.closeHandlerOptional = Optional.of(closeHandler);
return this;
}
public FirstTimePopup id(String id) {
public FirstTimeWebViewPopup id(String id) {
this.id = id;
return this;
}

View File

@ -110,7 +110,7 @@ public class OfferDetailsPopup extends Popup {
}
private void addContent() {
int rows = 9;
int rows = 11;
if (offer.getPaymentMethodCountryCode() != null)
rows++;
if (offer.getOfferFeePaymentTxID() != null)
@ -124,7 +124,8 @@ public class OfferDetailsPopup extends Popup {
addLabelTextField(gridPane, rowIndex, "Offer ID:", offer.getId(), Layout.FIRST_ROW_DISTANCE);
addLabelTextField(gridPane, ++rowIndex, "Creation date:", formatter.formatDateTime(offer.getDate()));
addLabelTextField(gridPane, ++rowIndex, "Offer direction:", Offer.Direction.BUY.name());
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode());
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode() + "/" + "BTC");
addLabelTextField(gridPane, ++rowIndex, "Amount:", formatter.formatCoinWithCode(offer.getAmount()));
addLabelTextField(gridPane, ++rowIndex, "Min. amount:", formatter.formatCoinWithCode(offer.getMinAmount()));
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(offer.getPaymentMethod().getId()));
@ -192,6 +193,7 @@ public class OfferDetailsPopup extends Popup {
});
CheckBox checkBox = addCheckBox(gridPane, ++rowIndex, "Don't show again", 5);
checkBox.setPadding(new Insets(10, 0, 15, 0));
checkBox.setSelected(!preferences.getShowTakeOfferConfirmation());
checkBox.setOnAction(e -> preferences.setShowTakeOfferConfirmation(!checkBox.isSelected()));
} else {

View File

@ -30,6 +30,7 @@ import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -126,15 +127,19 @@ public class TradeDetailsPopup extends Popup {
addLabelTextField(gridPane, ++rowIndex, "Offer direction:", direction);
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode());
addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(trade.getTradeAmount()));
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", formatter.arbitratorAddressToShortAddress(trade.getArbitratorAddress()));
addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", trade.getArbitratorAddress().getFullAddress());
if (contract != null) {
if (buyerPaymentAccountContractData != null)
addLabelTextField(gridPane, ++rowIndex, "Buyer payment details:", BSResources.get(buyerPaymentAccountContractData.getPaymentDetails()));
if (sellerPaymentAccountContractData != null)
addLabelTextField(gridPane, ++rowIndex, "Seller payment details:", BSResources.get(sellerPaymentAccountContractData.getPaymentDetails()));
if (buyerPaymentAccountContractData != null) {
TextField tf = addLabelTextField(gridPane, ++rowIndex, "Buyer payment details:", BSResources.get(buyerPaymentAccountContractData.getPaymentDetails())).second;
tf.setTooltip(new Tooltip(tf.getText()));
tf.setMouseTransparent(false);
}
if (sellerPaymentAccountContractData != null) {
TextField tf = addLabelTextField(gridPane, ++rowIndex, "Seller payment details:", BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second;
tf.setTooltip(new Tooltip(tf.getText()));
tf.setMouseTransparent(false);
}
if (buyerPaymentAccountContractData == null && sellerPaymentAccountContractData == null)
addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(contract.getPaymentMethodName()));
}

View File

@ -33,7 +33,7 @@ public class WebViewPopup extends Popup {
protected String url;
public static String getLocalUrl(String htmlFile) {
return WebViewPopup.class.getResource("/html/" + htmlFile).toExternalForm();
return WebViewPopup.class.getResource("/html/" + htmlFile + ".html").toExternalForm();
}
public WebViewPopup() {

View File

@ -308,14 +308,9 @@ public class BSFormatter {
public String arbitratorAddressesToString(List<Address> addresses) {
//return addresses.stream().map(e -> e.getFullAddress().substring(0, 8)).collect(Collectors.joining(", "));
return addresses.stream().map(e -> e.getFullAddress()).collect(Collectors.joining(", "));
}
public String arbitratorAddressToShortAddress(Address address) {
return address.getFullAddress().substring(0, 8);
}
public String languageCodesToString(List<String> languageLocales) {
return languageLocales.stream().map(LanguageUtil::getDisplayName).collect(Collectors.joining(", "));
}

View File

@ -18,7 +18,8 @@
body {
font-family: sans-serif;
color: #333;
font-size: 13px;
font-size: 14px;
line-height: 2;
}
a {

View File

@ -75,7 +75,7 @@ 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 successfully published to the distributed offerbook.
createOffer.success.headline=Your offer has been published to the offerbook.
createOffer.success.info=In the portfolio screen you can manage your open offers.
createOffer.error.message=An error occurred when placing the offer.\n\n{0}

View File

@ -186,7 +186,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
// We set connectionType to that connection to avoid that is get closed when
// we get too many connection attempts.
// That is used as protection against eclipse attacks.
connection.setConnectionType(ConnectionType.DIRECT_MSG);
connection.setConnectionType(ConnectionMode.DIRECT_MSG);
log.info("Received SealedAndSignedMessage and decrypted it: " + decryptedMsgWithPubKey);
decryptedMailListeners.stream().forEach(
@ -305,7 +305,8 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
Log.traceCall();
checkArgument(networkNode.getAddress() != null, "Address must be set when we have the hidden service ready");
if (myOnionAddress != null)
checkArgument(networkNode.getAddress() == myOnionAddress, "networkNode.getAddress() must be same as myOnionAddress");
checkArgument(networkNode.getAddress().equals(myOnionAddress),
"networkNode.getAddress() must be same as myOnionAddress.");
myOnionAddress = networkNode.getAddress();
dbStorage.queueUpForSave(myOnionAddress);
@ -709,7 +710,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
return blurredAddressHash != null &&
Arrays.equals(blurredAddressHash, sealedAndSignedMessage.addressPrefixHash);
} else {
log.warn("myOnionAddress must not be null at verifyAddressPrefixHash");
log.debug("myOnionAddress is null at verifyAddressPrefixHash. That is expected at startup.");
return false;
}
}

View File

@ -31,7 +31,7 @@ public class Connection implements MessageListener {
private static final Logger log = LoggerFactory.getLogger(Connection.class);
private static final int MAX_MSG_SIZE = 5 * 1024 * 1024; // 5 MB of compressed data
private static final int SOCKET_TIMEOUT = 30 * 60 * 1000; // 30 min.
private ConnectionType connectionType;
private ConnectionMode connectionType;
public static int getMaxMsgSize() {
return MAX_MSG_SIZE;
@ -123,7 +123,7 @@ public class Connection implements MessageListener {
connectionListener.onPeerAddressAuthenticated(peerAddress, connection);
}
public void setConnectionType(ConnectionType connectionType) {
public void setConnectionType(ConnectionMode connectionType) {
this.connectionType = connectionType;
}
@ -210,7 +210,7 @@ public class Connection implements MessageListener {
return stopped;
}
public ConnectionType getConnectionType() {
public ConnectionMode getConnectionType() {
return connectionType;
}

View File

@ -0,0 +1,8 @@
package io.bitsquare.p2p.network;
public enum ConnectionMode {
PASSIVE, // for connections initiated by other peer
ACTIVE, // for connections initiated by us
DIRECT_MSG, // for connections used for direct messaging
AUTH_REQUEST // for connections used for starting the authentication
}

View File

@ -8,7 +8,7 @@ import io.bitsquare.common.UserThread;
import io.bitsquare.p2p.Address;
import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.network.Connection;
import io.bitsquare.p2p.network.ConnectionType;
import io.bitsquare.p2p.network.ConnectionMode;
import io.bitsquare.p2p.network.MessageListener;
import io.bitsquare.p2p.network.NetworkNode;
import io.bitsquare.p2p.peers.messages.auth.*;
@ -72,7 +72,7 @@ public class AuthenticationHandshake implements MessageListener {
// We use the active connectionType if we started the authentication request to another peer
// That is used for protecting eclipse attacks
connection.setConnectionType(ConnectionType.ACTIVE);
connection.setConnectionType(ConnectionMode.ACTIVE);
AuthenticationResponse authenticationResponse = (AuthenticationResponse) message;
Address peerAddress = authenticationResponse.address;
@ -180,7 +180,7 @@ public class AuthenticationHandshake implements MessageListener {
log.trace("send AuthenticationRequest to " + peerAddress + " succeeded.");
connection.setPeerAddress(peerAddress);
// We protect that connection from getting closed by maintenance cleanup...
connection.setConnectionType(ConnectionType.AUTH_REQUEST);
connection.setConnectionType(ConnectionMode.AUTH_REQUEST);
}
@Override
@ -228,7 +228,7 @@ public class AuthenticationHandshake implements MessageListener {
connection.setPeerAddress(peerAddress);
// We use passive connectionType for connections created from received authentication requests from other peers
// That is used for protecting eclipse attacks
connection.setConnectionType(ConnectionType.PASSIVE);
connection.setConnectionType(ConnectionMode.PASSIVE);
}
@Override

View File

@ -168,7 +168,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
Address peerAddress = message.address;
if (!authenticationHandshakes.containsKey(peerAddress)) {
// We protect that connection from getting closed by maintenance cleanup...
connection.setConnectionType(ConnectionType.AUTH_REQUEST);
connection.setConnectionType(ConnectionMode.AUTH_REQUEST);
AuthenticationHandshake authenticationHandshake = new AuthenticationHandshake(networkNode, PeerGroup.this, getMyAddress());
authenticationHandshakes.put(peerAddress, authenticationHandshake);
SettableFuture<Connection> future = authenticationHandshake.respondToAuthenticationRequest(message, connection);
@ -186,8 +186,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
@Override
public void onFailure(@NotNull Throwable throwable) {
log.error("AuthenticationHandshake failed. " + throwable.getMessage());
throwable.printStackTrace();
log.info("AuthenticationHandshake failed. That is expected if peer went offline. " + throwable.getMessage());
removePeer(connection.getPeerAddress());
}
});
@ -468,7 +467,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
List<Connection> authenticatedConnections = allConnections.stream()
.filter(e -> e.isAuthenticated())
.filter(e -> e.getConnectionType() == ConnectionType.PASSIVE)
.filter(e -> e.getConnectionType() == ConnectionMode.PASSIVE)
.collect(Collectors.toList());
if (authenticatedConnections.size() == 0) {
@ -477,7 +476,7 @@ public class PeerGroup implements MessageListener, ConnectionListener {
if (size > MAX_CONNECTIONS_NORMAL_PRIO) {
authenticatedConnections = allConnections.stream()
.filter(e -> e.isAuthenticated())
.filter(e -> e.getConnectionType() == ConnectionType.PASSIVE || e.getConnectionType() == ConnectionType.ACTIVE)
.filter(e -> e.getConnectionType() == ConnectionMode.PASSIVE || e.getConnectionType() == ConnectionMode.ACTIVE)
.collect(Collectors.toList());
if (authenticatedConnections.size() == 0) {

View File

@ -285,7 +285,7 @@ public class ProtectedExpirableDataStorage implements MessageListener {
Log.traceCall();
int newSequenceNumber = data.sequenceNumber;
Integer storedSequenceNumber = sequenceNumberMap.get(hashOfData);
if (sequenceNumberMap.containsKey(hashOfData) && newSequenceNumber <= storedSequenceNumber) {
if (sequenceNumberMap.containsKey(hashOfData) && newSequenceNumber < storedSequenceNumber) {
log.trace("Sequence number is invalid. newSequenceNumber="
+ newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber);
return false;