diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index 96dabb6b8c..0ea3dadf80 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -217,7 +217,7 @@ public class WalletService { // reduce for mainnet testing // TODO revert later when tested enough FeePolicy.setSecurityDeposit(Coin.parseCoin("0.01")); // 4 EUR @ 400 EUR/BTC - Restrictions.setMaxTradeAmount(Coin.parseCoin("0.01")); // 4 EUR @ 400 EUR/BTC + Restrictions.setMaxTradeAmount(Coin.parseCoin("0.1")); // 40 EUR @ 400 EUR/BTC // Checkpoints are block headers that ship inside our app: for a new user, we pick the last header // in the checkpoints file and then download the rest from the network. It makes things much faster. diff --git a/core/src/main/java/io/bitsquare/user/PopupId.java b/core/src/main/java/io/bitsquare/user/PopupId.java deleted file mode 100644 index 82543d7190..0000000000 --- a/core/src/main/java/io/bitsquare/user/PopupId.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package io.bitsquare.user; - -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 final String TRADE_WALLET = "tradeWallet"; - public static final String SEND_PAYMENT_INFO = "sendPaymentInfo"; - public static final String PAYMENT_SENT = "paymentSent"; - public static final String PAYMENT_RECEIVED = "paymentReceived"; - -} diff --git a/core/src/main/java/io/bitsquare/user/Preferences.java b/core/src/main/java/io/bitsquare/user/Preferences.java index e00308f401..ced3c706a7 100644 --- a/core/src/main/java/io/bitsquare/user/Preferences.java +++ b/core/src/main/java/io/bitsquare/user/Preferences.java @@ -96,8 +96,6 @@ public final class Preferences implements Persistable { private final ArrayList cryptoCurrencies; private BlockChainExplorer blockChainExplorerMainNet; private BlockChainExplorer blockChainExplorerTestNet; - private boolean showNotifications = true; - private boolean showInstructions = true; private String backupDirectory; private boolean autoSelectArbitrators = true; private final Map showAgainMap; @@ -146,8 +144,6 @@ public final class Preferences implements Persistable { if (blockChainExplorerMainNet == null) setBlockChainExplorerTestNet(blockChainExplorersMainNet.get(0)); - showNotifications = persisted.getShowNotifications(); - showInstructions = persisted.getShowInstructions(); backupDirectory = persisted.getBackupDirectory(); autoSelectArbitrators = persisted.getAutoSelectArbitrators(); showAgainMap = persisted.getShowAgainMap(); @@ -175,11 +171,6 @@ public final class Preferences implements Persistable { setBlockChainExplorerMainNet(blockChainExplorersMainNet.get(0)); showAgainMap = new HashMap<>(); - 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); - preferredLocale = getDefaultLocale(); preferredTradeCurrency = getDefaultTradeCurrency(); @@ -219,8 +210,22 @@ public final class Preferences implements Persistable { tradeCurrenciesAsObservable.addAll(cryptoCurrencies); } - public void dontShowAgain(String id) { - showAgainMap.put(id, false); + public void dontShowAgain(String key) { + showAgainMap.put(key, false); + storage.queueUpForSave(2000); + } + + public void resetDontShowAgainForType() { + showAgainMap.clear(); + storage.queueUpForSave(2000); + } + + public void removeDontShowAgainForType(String type) { + showAgainMap.keySet().stream().forEach(key -> { + if (key.startsWith(type + "_")) + showAgainMap.put(key, true); + }); + storage.queueUpForSave(2000); } @@ -317,16 +322,6 @@ public final class Preferences implements Persistable { setBlockChainExplorerTestNet(blockChainExplorer); } - public void setShowNotifications(boolean showNotifications) { - this.showNotifications = showNotifications; - storage.queueUpForSave(2000); - } - - public void setShowInstructions(boolean showInstructions) { - this.showInstructions = showInstructions; - storage.queueUpForSave(2000); - } - public void setTacAccepted(boolean tacAccepted) { this.tacAccepted = tacAccepted; storage.queueUpForSave(); @@ -430,14 +425,6 @@ public final class Preferences implements Persistable { return blockChainExplorersTestNet; } - public boolean getShowNotifications() { - return showNotifications; - } - - public boolean getShowInstructions() { - return showInstructions; - } - public String getBackupDirectory() { return backupDirectory; } diff --git a/gui/src/main/java/io/bitsquare/gui/bitsquare.css b/gui/src/main/java/io/bitsquare/gui/bitsquare.css index e90921af67..6a5abe16a7 100644 --- a/gui/src/main/java/io/bitsquare/gui/bitsquare.css +++ b/gui/src/main/java/io/bitsquare/gui/bitsquare.css @@ -973,5 +973,12 @@ textfield */ -fx-background-radius: 5 5 5 5; -fx-background-insets: 5 5 20 20; -fx-effect: dropshadow(gaussian, #000000, 15, 0, 2, 2); - } + +.popup-icon-information { + -fx-text-fill: #ddd; +} + +.popup-icon-warning { + -fx-text-fill: #dd6900; +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java index 7fc167baad..f781d27944 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java @@ -225,7 +225,7 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel new Popup().information("You have successfully removed your arbitrator from the P2P network.").show(), + () -> new Popup().feedback("You have successfully removed your arbitrator from the P2P network.").show(), (errorMessage) -> new Popup().error("Could not remove arbitrator.\nError message: " + errorMessage).show()); } else { new Popup().warning("You need to wait until your client is bootstrapped in the network.\n" + @@ -236,7 +236,7 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel new Popup().information("You have successfully registered your arbitrator to the P2P network.").show(), + () -> new Popup().feedback("You have successfully registered your arbitrator to the P2P network.").show(), (errorMessage) -> new Popup().error("Could not register arbitrator.\nError message: " + errorMessage).show()); } else { new Popup().warning("You need to wait until your client is bootstrapped in the network.\n" + diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/altcoinaccounts/AltCoinAccountsView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/altcoinaccounts/AltCoinAccountsView.java index 146e8937ed..3291e03849 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/altcoinaccounts/AltCoinAccountsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/altcoinaccounts/AltCoinAccountsView.java @@ -126,7 +126,8 @@ public class AltCoinAccountsView extends ActivatableViewAndModel { model.onDeleteAccount(paymentAccount); removeSelectAccountForm(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/backup/BackupView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/backup/BackupView.java index dbbe7b6b17..e336511478 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/backup/BackupView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/backup/BackupView.java @@ -104,7 +104,7 @@ public class BackupView extends ActivatableView { String destination = Paths.get(backupDirectory, "bitsquare_backup_" + dateString).toString(); FileUtils.copyDirectory(new File(environment.getProperty(BitsquareEnvironment.APP_DATA_DIR_KEY)), new File(destination)); - new Popup().information("Backup successfully saved at:\n" + destination).show(); + new Popup().feedback("Backup successfully saved at:\n" + destination).show(); } catch (IOException e1) { e1.printStackTrace(); log.error(e1.getMessage()); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/fiataccounts/FiatAccountsView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/fiataccounts/FiatAccountsView.java index 138a7b4098..a833b98e25 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/fiataccounts/FiatAccountsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/fiataccounts/FiatAccountsView.java @@ -128,7 +128,8 @@ public class FiatAccountsView extends ActivatableViewAndModel { model.onDeleteAccount(paymentAccount); removeSelectAccountForm(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java index 75068a1b0c..06c71accd1 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java @@ -113,14 +113,14 @@ public class PasswordView extends ActivatableView { wallet.decrypt(aesKey); tradeWalletService.setAesKey(null); new Popup() - .information("Wallet successfully decrypted and password protection removed.") + .feedback("Wallet successfully decrypted and password protection removed.") .show(); passwordField.setText(""); repeatedPasswordField.setText(""); } else { new Popup() - .headLine("Wrong password") - .message("Please try entering your password again, carefully checking for typos or spelling errors.") + .warning("You entered the wrong password.\n\n" + + "Please try entering your password again, carefully checking for typos or spelling errors.") .show(); } } else { @@ -128,7 +128,7 @@ public class PasswordView extends ActivatableView { // we save the key for the trade wallet as we don't require passwords here tradeWalletService.setAesKey(aesKey); new Popup() - .information("Wallet successfully encrypted and password protection enabled.") + .feedback("Wallet successfully encrypted and password protection enabled.") .show(); passwordField.setText(""); repeatedPasswordField.setText(""); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java index 89845b029c..74a172c70a 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java @@ -198,17 +198,17 @@ public class SeedWordsView extends ActivatableView { Wallet wallet = walletService.getWallet(); if (wallet.getBalance(Wallet.BalanceType.AVAILABLE).value > 0) { new Popup() - .headLine("Wallet is not empty") - .warning("You must empty this wallet out before attempting to restore an older one, as mixing wallets " + + .warning("Your bitcoin wallet is not empty.\n\n" + + "You must empty this wallet before attempting to restore an older one, as mixing wallets " + "together can lead to invalidated backups.\n\n" + "Please finalize your trades, close all your open offers and go to the Funds section to withdraw your bitcoin.\n" + "In case you cannot access your bitcoin you can use the emergency tool to empty the wallet.\n" + - "To open that emergency tool press cmd + e.") + "To open that emergency tool press \"cmd + e\".") .show(); } else if (wallet.isEncrypted()) { new Popup() - .headLine("Wallet is encrypted") - .information("After restore, the wallet will no longer be encrypted and you must set a new password.") + .warning("Your bitcoin wallet is encrypted.\n\n" + + "After restore, the wallet will no longer be encrypted and you must set a new password.") .closeButtonText("I understand") .onClose(() -> doRestore()).show(); } else { @@ -225,7 +225,7 @@ public class SeedWordsView extends ActivatableView { log.debug("Wallet restored with seed words"); new Popup() - .information("Wallet restored successfully with the new seed words.\n\n" + + .feedback("Wallet restored successfully with the new seed words.\n\n" + "You need to shut down and restart the application.") .closeButtonText("Shut down") .onClose(() -> BitsquareApp.shutDownHandler.run()).show(); @@ -239,8 +239,8 @@ public class SeedWordsView extends ActivatableView { throwable -> UserThread.execute(() -> { log.error(throwable.getMessage()); new Popup() - .headLine("Wrong password") - .warning("Please try entering your password again, carefully checking for typos or spelling errors.") + .warning("You entered the wrong password.\n\n" + + "Please try entering your password again, carefully checking for typos or spelling errors.") .show(); new Popup() diff --git a/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java b/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java index 1b589927ce..99919de7c3 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java @@ -289,7 +289,7 @@ public class TraderDisputeView extends ActivatableView { } } } else { - new Popup().error("You cannot send more then 3 attachments in one message.").show(); + new Popup().warning("You cannot send more then 3 attachments in one message.").show(); } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java index 887dbf1708..2a04a3a510 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java @@ -18,6 +18,7 @@ package io.bitsquare.gui.main.funds; import io.bitsquare.app.BitsquareApp; +import io.bitsquare.common.util.Utilities; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.common.model.Activatable; import io.bitsquare.gui.common.view.*; @@ -26,7 +27,6 @@ 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.main.popups.Popup; -import io.bitsquare.user.PopupId; import io.bitsquare.user.Preferences; import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; @@ -85,15 +85,20 @@ public class FundsView extends ActivatableViewAndModel { else if (root.getSelectionModel().getSelectedItem() == transactionsTab) navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class); - String key = PopupId.TRADE_WALLET; - String text = "Bitsquare does not use a single application wallet, but dedicated wallets for every trade.\n" + - "Funding of the wallet will be done when needed, for instance when you create or take an offer.\n" + - "Withdrawing funds can be done after a trade is completed.\n" + - "Dedicated wallets help protect user privacy and prevent leaking information of previous trades to other" + - "traders.\n\n" + - "For more background information please see the Bitsquare FAQ on our web page."; + String key = "tradeWalletInfoAtFunds"; if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) - new Popup().information(text).dontShowAgainId(key, preferences).show(); + new Popup().backgroundInfo("Bitsquare does not use a single application wallet, but dedicated wallets for every trade.\n\n" + + "Funding of the wallet will be done when needed, for instance when you create or take an offer.\n" + + "Withdrawing funds can be done after a trade is completed.\n\n" + + "Dedicated wallets help protect user privacy and prevent leaking information of previous trades to other" + + "traders.") + .closeButtonText("I want to learn more") + .onClose(() -> Utilities.openWebPage("https://bitsquare.io/faq")) + .actionButtonText("I understand") + .onAction(() -> { + }) + .dontShowAgainId(key, preferences) + .show(); } @Override diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java index 2d0726648e..f2ac7970f2 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java @@ -188,14 +188,16 @@ public class WithdrawalView extends ActivatableView { if (BitsquareApp.DEV_MODE) { doWithdraw(receiverAmount, callback); } else { - new Popup().headLine("Confirm your withdrawal request") - .message("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" + + new Popup().headLine("Confirm withdrawal request") + .confirmation("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" + "From address: " + withdrawFromTextField.getText() + "\n" + "To receiving address: " + withdrawToTextField.getText() + ".\n" + "Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" + "The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" + "Are you sure you want to withdraw that amount?") + .actionButtonText("Yes") .onAction(() -> doWithdraw(receiverAmount, callback)) + .closeButtonText("Cancel") .show(); } @@ -323,10 +325,10 @@ public class WithdrawalView extends ActivatableView { reset(); updateList(); } catch (AddressFormatException e) { - new Popup().error("The address is not correct. Please check the address format.").show(); + new Popup().warning("The address is not correct. Please check the address format.").show(); } catch (InsufficientMoneyException e) { log.warn(e.getMessage()); - new Popup().error("You don't have enough fund in your wallet.").show(); + new Popup().warning("You don't have enough fund in your wallet.").show(); } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/help/Help.java b/gui/src/main/java/io/bitsquare/gui/main/help/Help.java index d7ac8c23c6..e8ba0a27cb 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/help/Help.java +++ b/gui/src/main/java/io/bitsquare/gui/main/help/Help.java @@ -33,7 +33,9 @@ public class Help { public static void openWindow(HelpId id) { try { - Utilities.openWebPage("https://github.com/bitsquare/bitsquare/wiki/User-Guide"); + // TODO create user guide + Utilities.openWebPage("http://bitsquare.io/faq"); + // Utilities.openWebPage("https://github.com/bitsquare/bitsquare/wiki/User-Guide"); } catch (Exception e) { log.error(e.getMessage()); new Popup().warning("Opening browser failed. Please check your internet " + diff --git a/gui/src/main/java/io/bitsquare/gui/main/help/HelpId.java b/gui/src/main/java/io/bitsquare/gui/main/help/HelpId.java index bf820abca5..a29f4ddfde 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/help/HelpId.java +++ b/gui/src/main/java/io/bitsquare/gui/main/help/HelpId.java @@ -37,6 +37,4 @@ public enum HelpId { SETUP_FIAT_ACCOUNT, MANAGE_FIAT_ACCOUNT, PAY_ACCOUNT_FEE - - } diff --git a/gui/src/main/java/io/bitsquare/gui/main/notifications/Notification.java b/gui/src/main/java/io/bitsquare/gui/main/notifications/Notification.java index f67b6428b4..9a432491d2 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/notifications/Notification.java +++ b/gui/src/main/java/io/bitsquare/gui/main/notifications/Notification.java @@ -1,5 +1,7 @@ package io.bitsquare.gui.main.notifications; +import io.bitsquare.common.Timer; +import io.bitsquare.common.UserThread; import io.bitsquare.gui.main.popups.Popup; import javafx.animation.Interpolator; import javafx.animation.KeyFrame; @@ -19,6 +21,8 @@ import org.slf4j.LoggerFactory; public class Notification extends Popup { private static final Logger log = LoggerFactory.getLogger(Notification.class); private boolean hasBeenDisplayed; + private boolean autoClose; + private Timer autoCloseTimer; public Notification() { width = 345; // 320 visible bg because of insets @@ -33,6 +37,10 @@ public class Notification extends Popup { return headLine("Notification for trade with ID " + tradeId); } + public Notification notification(String message) { + return (Notification) super.notification(message); + } + public Notification disputeHeadLine(String tradeId) { return headLine("Support ticket for trade with ID " + tradeId); } @@ -52,13 +60,26 @@ public class Notification extends Popup { hasBeenDisplayed = true; } + public Notification autoClose() { + autoClose = true; + return this; + } + @Override public void display() { super.display(); + + if (autoClose && autoCloseTimer == null) + autoCloseTimer = UserThread.runAfter(this::hide, 5); } @Override protected void animateHide(Runnable onFinishedHandler) { + if (autoCloseTimer != null) { + autoCloseTimer.stop(); + autoCloseTimer = null; + } + if (NotificationCenter.useAnimations) { double duration = 400; Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1); diff --git a/gui/src/main/java/io/bitsquare/gui/main/notifications/NotificationCenter.java b/gui/src/main/java/io/bitsquare/gui/main/notifications/NotificationCenter.java index 0cabf64cee..d617629297 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/notifications/NotificationCenter.java +++ b/gui/src/main/java/io/bitsquare/gui/main/notifications/NotificationCenter.java @@ -50,7 +50,6 @@ public class NotificationCenter { private final TradeManager tradeManager; private final DisputeManager disputeManager; - private final Preferences preferences; private final Navigation navigation; private final Map disputeStateSubscriptionsMap = new HashMap<>(); @@ -67,7 +66,6 @@ public class NotificationCenter { public NotificationCenter(TradeManager tradeManager, DisputeManager disputeManager, Preferences preferences, Navigation navigation) { this.tradeManager = tradeManager; this.disputeManager = disputeManager; - this.preferences = preferences; this.navigation = navigation; EasyBind.subscribe(preferences.useAnimationsProperty(), useAnimations -> NotificationCenter.useAnimations = useAnimations); diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java index ef7a5ce1bc..26851366f0 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java @@ -29,6 +29,7 @@ import io.bitsquare.btc.pricefeed.PriceFeed; import io.bitsquare.common.UserThread; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.gui.common.model.ActivatableDataModel; +import io.bitsquare.gui.main.notifications.Notification; import io.bitsquare.gui.main.popups.Popup; import io.bitsquare.gui.main.popups.WalletPasswordPopup; import io.bitsquare.gui.util.BSFormatter; @@ -381,8 +382,15 @@ class CreateOfferDataModel extends ActivatableDataModel { private void updateBalance(Coin balance) { isWalletFunded.set(totalToPayAsCoin.get() != null && balance.compareTo(totalToPayAsCoin.get()) >= 0); - if (isWalletFunded.get()) + if (isWalletFunded.get()) { walletService.removeBalanceListener(balanceListener); + new Notification() + .headLine("Trading wallet update") + .notification("Your trading wallet is sufficiently funded.\n" + + "Amount: " + formatter.formatCoinWithCode(totalToPayAsCoin.get())) + .autoClose() + .show(); + } } public Coin getOfferFeeAsCoin() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java index 5400db274c..ce4c3d4b2f 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java @@ -23,6 +23,7 @@ import io.bitsquare.app.BitsquareApp; import io.bitsquare.btc.FeePolicy; import io.bitsquare.common.util.Tuple2; import io.bitsquare.common.util.Tuple3; +import io.bitsquare.common.util.Utilities; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.FxmlView; @@ -111,6 +112,7 @@ public class CreateOfferView extends ActivatableViewAndModel currencyComboBoxSelectionHandler; private int gridRow = 0; private final Preferences preferences; + private ChangeListener tradeCurrencyCodeListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -171,6 +173,8 @@ public class CreateOfferView extends ActivatableViewAndModel Utilities.openWebPage("https://bitsquare.io/faq#6")) + .actionButtonText("I understand") + .onAction(() -> { + }) + .dontShowAgainId(id, preferences) + .show(); + } + + id = "createOfferFundWalletInfo"; + if (model.dataModel.getPreferences().showAgain(id)) { + String tradeAmountText = model.isSellOffer() ? "the trade amount, " : ""; + new Popup().headLine("Fund your trading wallet").instruction("You need to pay in " + + model.totalToPay.get() + " to your local Bitsquare trading wallet.\n" + + "The amount is the sum of " + tradeAmountText + "the security deposit, the trading fee and " + + "the bitcoin mining fee.\n\n" + + "Please send from your external Bitcoin wallet the exact amount to the address: " + + model.getAddressAsString() + "\n" + + "(you can copy the address in the screen below after closing that popup)\n\n" + + "Make sure you use a sufficiently high mining fee of at least " + + model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + + " to avoid problems that your transaction does not get confirmed in the blockchain.\n\n" + + "You can see the status of your incoming payment and all the details in the screen below.") + .dontShowAgainId(id, preferences) .show(); - model.dataModel.getPreferences().dontShowAgain(id); } } @@ -283,12 +306,11 @@ public class CreateOfferView extends ActivatableViewAndModel onPaymentAccountsComboBoxSelected(); currencyComboBoxSelectionHandler = e -> onCurrencyComboBoxSelected(); + tradeCurrencyCodeListener = (observable, oldValue, newValue) -> { + priceTextField.clear(); + volumeTextField.clear(); + }; + showTransactionPublishedScreen = (o, oldValue, newValue) -> { if (BitsquareApp.DEV_MODE) { newValue = false; @@ -498,7 +523,7 @@ public class CreateOfferView extends ActivatableViewAndModel { new Popup().headLine(BSResources.get("createOffer.success.headline")) - .message(BSResources.get("createOffer.success.info")) + .feedback(BSResources.get("createOffer.success.info")) .actionButtonText("Go to \"My open offers\"") .onAction(() -> { close(); @@ -515,6 +540,8 @@ public class CreateOfferView extends ActivatableViewAndModel tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, BSResources.get("createOffer.amountPriceBox.next"), BSResources.get("shared.cancel")); nextButton = tuple.first; + nextButton.disableProperty().bind(model.isNextButtonDisabled); //UserThread.runAfter(() -> nextButton.requestFocus(), 100, TimeUnit.MILLISECONDS); cancelButton1 = tuple.second; cancelButton1.setDefaultButton(false); @@ -697,7 +727,7 @@ public class CreateOfferView extends ActivatableViewAndModel onPlaceOffer()); createOfferButton.setMinHeight(40); createOfferButton.setPadding(new Insets(0, 20, 0, 20)); - + placeOfferSpinner = placeOfferTuple.second; placeOfferSpinner.setPrefSize(18, 18); placeOfferSpinnerInfoLabel = placeOfferTuple.third; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferViewModel.java index 459bd1f684..5a7f53bf5c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferViewModel.java @@ -18,7 +18,6 @@ package io.bitsquare.gui.main.offer.createoffer; import io.bitsquare.app.BitsquareApp; -import io.bitsquare.arbitration.Arbitrator; import io.bitsquare.gui.common.model.ActivatableWithDataModel; import io.bitsquare.gui.common.model.ViewModel; import io.bitsquare.gui.util.BSFormatter; @@ -38,7 +37,6 @@ import org.bitcoinj.core.Coin; import org.bitcoinj.utils.Fiat; import javax.inject.Inject; -import java.util.List; import static javafx.beans.binding.Bindings.createStringBinding; @@ -66,8 +64,8 @@ class CreateOfferViewModel extends ActivatableWithDataModel { if (newValue) { - isPlaceOfferButtonVisible.set(!newValue); + isPlaceOfferButtonDisabled.set(newValue); isPlaceOfferSpinnerVisible.set(false); placeOfferSpinnerInfoText.set(""); } @@ -336,10 +334,6 @@ class CreateOfferViewModel extends ActivatableWithDataModel requestPlaceOfferSuccess.set(true)); } - void onShowPayFundsScreen() { - isPlaceOfferButtonVisible.set(true); - } - public void onPaymentAccountSelected(PaymentAccount paymentAccount) { dataModel.onPaymentAccountSelected(paymentAccount); } @@ -563,18 +557,15 @@ class CreateOfferViewModel extends ActivatableWithDataModel getArbitrators() { - return dataModel.getArbitrators(); - } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java index 0b7ef24ddd..5561f01848 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java @@ -253,17 +253,18 @@ public class OfferBookView extends ActivatableViewAndModel { log.debug("Remove offer was successful"); - new Popup().information("You can withdraw the funds you paid in from the funds screens.").show(); - navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class); + new Popup().instruction("You can withdraw the funds you paid in from the \"Fund/Available for withdrawal\" screen.") + .actionButtonText("Go to \"Funds/Available for withdrawal\"") + .onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class)) + .show(); }, (message) -> { log.error(message); @@ -324,8 +327,10 @@ public class OfferBookView extends ActivatableViewAndModel { navigation.setReturnPath(navigation.getCurrentPath()); navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, target); diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java index b9b10cfd4d..d4d6b92cdf 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java @@ -30,6 +30,7 @@ import io.bitsquare.btc.pricefeed.PriceFeed; import io.bitsquare.common.UserThread; import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.gui.common.model.ActivatableDataModel; +import io.bitsquare.gui.main.notifications.Notification; import io.bitsquare.gui.main.popups.Popup; import io.bitsquare.gui.main.popups.WalletPasswordPopup; import io.bitsquare.gui.util.BSFormatter; @@ -324,8 +325,15 @@ class TakeOfferDataModel extends ActivatableDataModel { private void updateBalance(@NotNull Coin balance) { isWalletFunded.set(totalToPayAsCoin.get() != null && balance.compareTo(totalToPayAsCoin.get()) >= 0); - if (isWalletFunded.get()) + if (isWalletFunded.get()) { walletService.removeBalanceListener(balanceListener); + new Notification() + .headLine("Trading wallet update") + .notification("Your trading wallet is sufficiently funded.\n" + + "Amount: " + formatter.formatCoinWithCode(totalToPayAsCoin.get())) + .autoClose() + .show(); + } } boolean isMinAmountLessOrEqualAmount() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java index 0eb3ee800b..cce9d5f61b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java @@ -23,6 +23,7 @@ import io.bitsquare.app.BitsquareApp; import io.bitsquare.btc.FeePolicy; import io.bitsquare.common.util.Tuple2; import io.bitsquare.common.util.Tuple3; +import io.bitsquare.common.util.Utilities; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.FxmlView; @@ -175,11 +176,14 @@ public class TakeOfferView extends ActivatableViewAndModel { if (newValue != null) { - new Popup().error(BSResources.get("takeOffer.error.message", newValue)).onClose(() -> { - errorPopupDisplayed.set(true); - model.resetErrorMessage(); - close(); - }).show(); + new Popup().error(BSResources.get("takeOffer.error.message", model.errorMessage.get()) + + "Please try to restart you application and check your network connection to see if you can resolve the issue.") + .onClose(() -> { + errorPopupDisplayed.set(true); + model.resetErrorMessage(); + close(); + }) + .show(); } }); @@ -220,15 +224,16 @@ public class TakeOfferView extends ActivatableViewAndModel { - new Popup().information(BSResources.get("takeOffer.success.info")) - .actionButtonText("Go to \"Portfolio/Open trades\"") + new Popup().headLine(BSResources.get("takeOffer.success.headline")) + .feedback(BSResources.get("takeOffer.success.info")) + .actionButtonText("Go to \"Open trades\"") .onAction(() -> { close(); FxTimer.runLater(Duration.ofMillis(100), () -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class) ); }) - .onClose(() -> close()) + .onClose(this::close) .show(); } ); @@ -293,6 +298,8 @@ public class TakeOfferView extends ActivatableViewAndModel Utilities.openWebPage("https://bitsquare.io/faq#6")) + .actionButtonText("I understand") + .onAction(() -> { + }) + .dontShowAgainId(id, preferences) + .show(); + } + + id = "takeOfferFundWalletInfo"; + if (model.dataModel.getPreferences().showAgain(id)) { + String tradeAmountText = model.isSeller() ? "the trade amount, " : ""; + new Popup().headLine("Fund your trading wallet").instruction("You need to pay in " + + model.totalToPay.get() + " to your local Bitsquare trading wallet.\n" + + "The amount is the sum of " + tradeAmountText + "the security deposit, the trading fee and " + + "the bitcoin mining fee.\n\n" + + "Please send from your external Bitcoin wallet the exact amount to the address: " + + model.getAddressAsString() + "\n(you can copy the address in the screen below after closing that popup)\n\n" + + "Make sure you use a sufficiently high mining fee of at least " + + model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + + " to avoid problems that your transaction does not get confirmed in the blockchain.\n\n" + + "You can see the status of your incoming payment and all the details in the screen below.") + .dontShowAgainId(id, preferences) .show(); - model.dataModel.getPreferences().dontShowAgain(id); } } @@ -526,6 +549,7 @@ public class TakeOfferView extends ActivatableViewAndModel tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, BSResources.get("takeOffer.amountPriceBox.next"), BSResources.get("shared.cancel")); nextButton = tuple.first; + nextButton.disableProperty().bind(model.isNextButtonDisabled); //UserThread.runAfter(() -> nextButton.requestFocus(), 100, TimeUnit.MILLISECONDS); cancelButton1 = tuple.second; cancelButton1.setDefaultButton(false); @@ -577,10 +601,13 @@ public class TakeOfferView extends ActivatableViewAndModel takeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, ""); takeOfferButton = takeOfferTuple.first; takeOfferButton.setVisible(false); - takeOfferButton.setOnAction(e -> onTakeOffer()); + takeOfferButton.setOnAction(e -> { + onTakeOffer(); + balanceTextField.cleanup(); + }); takeOfferButton.setMinHeight(40); takeOfferButton.setPadding(new Insets(0, 20, 0, 20)); - + takeOfferSpinner = takeOfferTuple.second; takeOfferSpinner.setPrefSize(18, 18); takeOfferSpinnerInfoLabel = takeOfferTuple.third; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java index 806618466f..90fd15336d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java @@ -71,6 +71,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel im final BooleanProperty isOfferAvailable = new SimpleBooleanProperty(); final BooleanProperty isTakeOfferButtonDisabled = new SimpleBooleanProperty(true); + final BooleanProperty isNextButtonDisabled = new SimpleBooleanProperty(true); final BooleanProperty isTakeOfferSpinnerVisible = new SimpleBooleanProperty(); final BooleanProperty showWarningInvalidBtcDecimalPlaces = new SimpleBooleanProperty(); final BooleanProperty showTransactionPublishedScreen = new SimpleBooleanProperty(); @@ -340,13 +341,14 @@ class TakeOfferViewModel extends ActivatableWithDataModel im } private void updateButtonDisableState() { - isTakeOfferButtonDisabled.set(!(isBtcInputValid(amount.get()).isValid - && dataModel.isMinAmountLessOrEqualAmount() - && !dataModel.isAmountLargerThanOfferAmount() - && dataModel.isWalletFunded.get() - && !takeOfferRequested - && dataModel.isFeeFromFundingTxSufficient()) - ); + boolean inputDataValid = isBtcInputValid(amount.get()).isValid + && dataModel.isMinAmountLessOrEqualAmount() + && !dataModel.isAmountLargerThanOfferAmount(); + isNextButtonDisabled.set(!inputDataValid); + isTakeOfferButtonDisabled.set(!(inputDataValid + && dataModel.isWalletFunded.get() + && !takeOfferRequested + && dataModel.isFeeFromFundingTxSufficient())); } @@ -401,8 +403,9 @@ class TakeOfferViewModel extends ActivatableWithDataModel im if (connection.getPeersNodeAddressOptional().isPresent() && connection.getPeersNodeAddressOptional().get().equals(offer.getOffererNodeAddress())) offerWarning.set("You lost connection to the offerer.\n" + - "He might have gone offline or has closed the connection to you because of " + - "many other connections."); + "He might have gone offline or has closed the connection to you because of too " + + "many open connections.\n\n" + + "If you can still see his offer in the offerbook you can try to take the offer again."); } @Override diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java index 7d7b7ce01d..7d4e0c140f 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/DisputeSummaryPopup.java @@ -392,8 +392,8 @@ public class DisputeSummaryPopup extends Popup { disputeManager.sendDisputeResultMessage(disputeResult, dispute, text); if (!finalPeersDispute.isClosed()) - FxTimer.runLater(Duration.ofMillis(Transitions.DEFAULT_DURATION), () -> new Popup().information( - "You need to close also the trading peers ticket!").show()); + FxTimer.runLater(Duration.ofMillis(Transitions.DEFAULT_DURATION), () -> + new Popup().instruction("You need to close also the trading peers ticket!").show()); hide(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/EmptyWalletPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/EmptyWalletPopup.java index 81a24c5334..68684dcd58 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/EmptyWalletPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/EmptyWalletPopup.java @@ -143,7 +143,7 @@ public class EmptyWalletPopup extends Popup { emptyWalletButton.setDisable(true); log.debug("wallet empty successful"); FxTimer.runLater(Duration.ofMillis(Transitions.DEFAULT_DURATION), () -> new Popup() - .information("The balance of your wallet was successfully transferred.") + .feedback("The balance of your wallet was successfully transferred.") .onClose(() -> blurAgain()).show()); }, (errorMessage) -> { diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/OfferDetailsPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/OfferDetailsPopup.java index 106b680f2d..cc7ef36efb 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/OfferDetailsPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/OfferDetailsPopup.java @@ -155,7 +155,7 @@ public class OfferDetailsPopup extends Popup { if (takeOfferHandlerOptional.isPresent()) addLabelTextField(gridPane, rowIndex, "Offer type:", formatter.getDirectionForTaker(offer.getDirection()), Layout.FIRST_ROW_DISTANCE); else - addLabelTextField(gridPane, rowIndex, "Offer type:", formatter.getOfferDirection(offer.getDirection()), Layout.FIRST_ROW_DISTANCE); + addLabelTextField(gridPane, rowIndex, "Offer type:", formatter.getOfferDirectionForOfferer(offer.getDirection()), Layout.FIRST_ROW_DISTANCE); if (takeOfferHandlerOptional.isPresent()) { addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(tradeAmount)); diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java index 5b6c069ea7..9bb61ac9fb 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/Popup.java @@ -17,6 +17,7 @@ package io.bitsquare.gui.main.popups; +import de.jensd.fx.fontawesome.AwesomeIcon; import io.bitsquare.common.Timer; import io.bitsquare.common.UserThread; import io.bitsquare.common.util.Utilities; @@ -74,6 +75,8 @@ public class Popup { private ChangeListener positionListener; private Timer centerTime; protected double buttonDistance = 20; + private String type; + private AwesomeIcon awesomeIcon; /////////////////////////////////////////////////////////////////////////////////////////// @@ -152,30 +155,75 @@ public class Popup { } public Popup notification(String message) { - // TODO use icons - this.headLine = "Notification"; + type = "notification"; + if (headLine == null) + this.headLine = "Notification"; + this.message = message; + setTruncatedMessage(); + return this; + } + + public Popup instruction(String message) { + type = "instruction"; + if (headLine == null) + this.headLine = "Instruction"; + this.message = message; + setTruncatedMessage(); + return this; + } + + public Popup backgroundInfo(String message) { + type = "backgroundInfo"; + if (headLine == null) + this.headLine = "Background information"; + this.message = message; + setTruncatedMessage(); + return this; + } + + public Popup feedback(String message) { + type = "feedback"; + if (headLine == null) + this.headLine = "Feedback"; + this.message = message; + setTruncatedMessage(); + return this; + } + + public Popup confirmation(String message) { + type = "confirmation"; + if (headLine == null) + this.headLine = "Confirmation"; this.message = message; setTruncatedMessage(); return this; } public Popup information(String message) { - this.headLine = "Information"; + type = "information"; + if (headLine == null) + this.headLine = "Information"; this.message = message; setTruncatedMessage(); return this; } public Popup warning(String message) { - this.headLine = "Warning"; + type = "warning"; + awesomeIcon = AwesomeIcon.LIGHTBULB; + + if (headLine == null) + this.headLine = "Warning"; this.message = message; setTruncatedMessage(); return this; } public Popup error(String message) { + type = "error"; showReportErrorButtons(); - this.headLine = "Error"; + if (headLine == null) + this.headLine = "Error"; this.message = message; setTruncatedMessage(); return this; @@ -186,11 +234,6 @@ public class Popup { return this; } - public Popup hideReportErrorButtons() { - this.showReportErrorButtons = false; - return this; - } - public Popup message(String message) { this.message = message; setTruncatedMessage(); @@ -218,7 +261,7 @@ public class Popup { } public Popup dontShowAgainId(String dontShowAgainId, Preferences preferences) { - this.dontShowAgainId = dontShowAgainId; + this.dontShowAgainId = type + "_" + dontShowAgainId; this.preferences = preferences; return this; } @@ -323,10 +366,21 @@ public class Popup { protected void addHeadLine() { if (headLine != null) { + ++rowIndex; + + /* Label icon = AwesomeDude.createIconLabel(awesomeIcon, "40.0"); + icon.getStyleClass().add("popup-icon-" + type); + + GridPane.setHalignment(icon, HPos.RIGHT); + GridPane.setRowIndex(icon, ++rowIndex); + GridPane.setColumnIndex(icon, 1); + GridPane.setMargin(icon, new Insets(0, 0, -10, 0)); + gridPane.getChildren().add(icon);*/ + headLineLabel = new Label(BSResources.get(headLine)); headLineLabel.setMouseTransparent(true); GridPane.setHalignment(headLineLabel, HPos.LEFT); - GridPane.setRowIndex(headLineLabel, ++rowIndex); + GridPane.setRowIndex(headLineLabel, rowIndex); GridPane.setColumnSpan(headLineLabel, 2); gridPane.getChildren().addAll(headLineLabel); } @@ -406,7 +460,7 @@ public class Popup { private void addDontShowAgainCheckBox() { if (dontShowAgainId != null && preferences != null) { - CheckBox dontShowAgainCheckBox = addCheckBox(gridPane, rowIndex, "Don't show again", 30); + CheckBox dontShowAgainCheckBox = addCheckBox(gridPane, rowIndex, "Don't show again", buttonDistance - 1); GridPane.setColumnIndex(dontShowAgainCheckBox, 0); GridPane.setHalignment(dontShowAgainCheckBox, HPos.LEFT); dontShowAgainCheckBox.setOnAction(e -> { diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/TacPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/TacPopup.java index fe1cca62d3..f7466e36c4 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/TacPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/TacPopup.java @@ -40,13 +40,13 @@ public class TacPopup extends Popup { preferences.setTacAccepted(true); if (preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET) UserThread.runAfter(() -> new Popup() + .headLine("Important information!") .warning("This software is still in alpha version.\n" + "Please be aware that using Mainnet comes with the risk to lose funds " + "in case of software bugs.\n" + "To limit the possible losses the maximum allowed trading amount and the " + - "security deposit have been reduced to 0.01 BTC for the alpha version " + + "security deposit have been reduced to 0.1 BTC for the alpha version " + "when using Mainnet.") - .headLine("Important information!") .actionButtonText("I understand and want to use Mainnet") .closeButtonText("Restart and use Testnet") .onClose(() -> { diff --git a/gui/src/main/java/io/bitsquare/gui/main/popups/WalletPasswordPopup.java b/gui/src/main/java/io/bitsquare/gui/main/popups/WalletPasswordPopup.java index 8690b68ec2..0e330a1507 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/popups/WalletPasswordPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/main/popups/WalletPasswordPopup.java @@ -156,8 +156,8 @@ public class WalletPasswordPopup extends Popup { hide(); } else { FxTimer.runLater(Duration.ofMillis(Transitions.DEFAULT_DURATION), () -> new Popup() - .headLine("Wrong password") - .message("Please try entering your password again, carefully checking for typos or spelling errors.") + .warning("You entered the wrong password.\n\n" + + "Please try entering your password again, carefully checking for typos or spelling errors.") .onClose(() -> blurAgain()).show()); } }); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java index 1eb162a14f..4a8310cd12 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java @@ -91,8 +91,9 @@ public class OpenOffersView extends ActivatableViewAndModel { log.debug("Remove offer was successful"); - new Popup().information("You can withdraw the funds you paid in from the funds screens.") - .onClose(() -> navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class)) + new Popup().instruction("You can withdraw the funds you paid in from the \"Fund/Available for withdrawal\" screen.") + .actionButtonText("Go to \"Funds/Available for withdrawal\"") + .onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class)) .show(); }, (message) -> { diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java index d2face162e..b7da4a389c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -70,7 +70,7 @@ public class PendingTradesDataModel extends ActivatableDataModel { private final User user; private final KeyRing keyRing; public final DisputeManager disputeManager; - private final Navigation navigation; + public final Navigation navigation; private final WalletPasswordPopup walletPasswordPopup; private final NotificationCenter notificationCenter; diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index 92bd8d0890..b87dd26ec8 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -32,7 +32,6 @@ import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentMethod; import io.bitsquare.trade.Trade; -import io.bitsquare.user.PopupId; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; @@ -70,26 +69,27 @@ public class BuyerStep2View extends TradeStepView { if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) { String message = ""; if (paymentAccountContractData instanceof BlockChainAccountContractData) - message = "Please transfer from your external " + + message = "Your trade has reached at least one blockchain confirmation.\n\n" + + "Please transfer from your external " + CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()) + " wallet\n" + model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" + "Here are the payment account details of the bitcoin seller:\n" + "" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" + - "You can copy & paste the receivers address from the main screen after closing that popup."; + "You can copy & paste the values from the main screen after closing that popup."; else if (paymentAccountContractData != null) - message = "Please go to your online banking web page and pay\n" + + message = "Your trade has reached at least one blockchain confirmation.\n\n" + + "Please go to your online banking web page and pay " + model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" + "Here are the payment account details of the bitcoin seller:\n" + - "" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" + - "Please don't forget to add the reference text " + trade.getShortId() + - " so the receiver can assign your payment to this trade.\n" + + "" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" + + "You can copy & paste the values from the main screen after closing that popup.\n\n" + + "Please don't forget to add the reference text \"" + trade.getShortId() + + "\" so the receiver can assign your payment to this trade.\n\n" + "DO NOT use any additional notice in the reference text like " + - "Bitcoin, Btc, Trade or Bitsquare.\n\n" + - "You can copy & paste the values from the main screen after closing that popup."; + "Bitcoin, Btc or Bitsquare."; - new Popup().headLine("Notification for trade with ID " + trade.getShortId()) - .message(message) - .closeButtonText("I understand") + new Popup().headLine("Attention required for trade with ID " + trade.getShortId()) + .instruction(message) .dontShowAgainId(id, preferences) .show(); } @@ -210,13 +210,15 @@ public class BuyerStep2View extends TradeStepView { private void onPaymentStarted() { if (model.p2PService.isBootstrapped()) { - String key = PopupId.PAYMENT_SENT; + String key = "confirmPaymentStarted"; if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) { - new Popup().headLine("Confirmation") - .message("Did you transfer the payment to your trading partner?") + new Popup() + .headLine("Confirm that you have started the payment") + .confirmation("Have you initiated the " + model.dataModel.getCurrencyCode() + + " payment to your trading partner?") .width(700) .dontShowAgainId(key, preferences) - .actionButtonText("Yes I have started the payment") + .actionButtonText("Yes, I have started the payment") .closeButtonText("No") .onAction(this::confirmPaymentStarted) .show(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep5View.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep5View.java index 4348935920..4df4d37fa7 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep5View.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/buyer/BuyerStep5View.java @@ -19,15 +19,23 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer; import io.bitsquare.app.BitsquareApp; import io.bitsquare.app.Log; +import io.bitsquare.btc.Restrictions; +import io.bitsquare.btc.WalletService; import io.bitsquare.common.util.Tuple2; +import io.bitsquare.gui.main.MainView; +import io.bitsquare.gui.main.funds.FundsView; +import io.bitsquare.gui.main.funds.transactions.TransactionsView; import io.bitsquare.gui.main.popups.Popup; import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel; import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView; +import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.Layout; import javafx.beans.value.ChangeListener; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; +import org.bitcoinj.core.AddressFormatException; +import org.bitcoinj.core.Coin; import static io.bitsquare.gui.util.FormBuilder.*; @@ -108,29 +116,81 @@ public class BuyerStep5View extends TradeStepView { withdrawButton = addButtonAfterGroup(gridPane, ++gridRow, "Withdraw to external wallet"); withdrawButton.setOnAction(e -> { withdrawButton.setDisable(true); - model.dataModel.onWithdrawRequest(withdrawAddressTextField.getText(), - () -> { - String id = "TradeCompletedInfoPopup"; - if (preferences.showAgain(id)) { - new Popup().information("You can review your completed trades under \"Portfolio/History\" or " + - "review your transactions under \"Funds/Transactions\"") - .dontShowAgainId(id, preferences) - .show(); - } - withdrawButton.setDisable(true); - }, - (errorMessage, throwable) -> { - withdrawButton.setDisable(false); - if (throwable == null) - new Popup().warning(errorMessage).show(); - else - new Popup().error("An error occurred:\n" + throwable.getMessage()).show(); - }); - + reviewWithdrawal(); }); + String id = "tradeCompleteInfo"; if (BitsquareApp.DEV_MODE) withdrawAddressTextField.setText("mi8k5f9L972VgDaT4LgjAhriC9hHEPL7EW"); + else + new Popup().headLine("Trade completed") + .instruction("You can withdraw your funds now to your external Bitcoin wallet.") + .dontShowAgainId(id, preferences) + .show(); + } + + private void doWithdrawal() { + model.dataModel.onWithdrawRequest(withdrawAddressTextField.getText(), + () -> { + String id = "tradeCompleteWithdrawCompletedInfo"; + if (preferences.showAgain(id)) { + new Popup().headLine("Withdrawal completed").instruction("Your completed trades are stored under \"Portfolio/History\".\n" + + "You can review all your bitcoin transactions under \"Funds/Transactions\"") + .actionButtonText("Go to \"Transactions\"") + .onAction(() -> model.dataModel.navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class)) + .dontShowAgainId(id, preferences) + .show(); + } + withdrawButton.setDisable(true); + }, + (errorMessage, throwable) -> { + withdrawButton.setDisable(false); + if (throwable != null && throwable.getMessage() != null) + new Popup().error(errorMessage + "\n\n" + throwable.getMessage()).show(); + else + new Popup().error(errorMessage).show(); + }); + } + + private void reviewWithdrawal() { + Coin senderAmount = trade.getPayoutAmount(); + WalletService walletService = model.dataModel.walletService; + String fromAddresses = walletService.getAddressEntryByOfferId(trade.getId()).getAddressString(); + String toAddresses = withdrawAddressTextField.getText(); + + if (Restrictions.isAboveFixedTxFeeAndDust(senderAmount)) { + try { + Coin requiredFee = walletService.getRequiredFee(fromAddresses, toAddresses, senderAmount, null); + Coin receiverAmount = senderAmount.subtract(requiredFee); + if (BitsquareApp.DEV_MODE) { + doWithdrawal(); + } else { + BSFormatter formatter = model.formatter; + String id = "reviewWithdrawalAtTradeComplete"; + new Popup().headLine("Confirm withdrawal request") + .confirmation("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" + + "From address: " + fromAddresses + "\n" + + "To receiving address: " + toAddresses + ".\n" + + "Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" + + "The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" + + "Are you sure you want to withdraw that amount?") + .actionButtonText("Yes") + .onAction(this::doWithdrawal) + .closeButtonText("Cancel") + .onClose(() -> withdrawButton.setDisable(false)) + .dontShowAgainId(id, preferences) + .show(); + + } + } catch (AddressFormatException e) { + e.printStackTrace(); + log.error(e.getMessage()); + } + } else { + new Popup() + .warning("The amount to transfer is lower than the transaction fee and the min. possible tx value (dust).") + .show(); + } } protected String getBtcTradeAmountLabel() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java index adf1344860..083663a15c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java @@ -30,7 +30,6 @@ import io.bitsquare.payment.BlockChainAccountContractData; import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.trade.Contract; import io.bitsquare.trade.Trade; -import io.bitsquare.user.PopupId; import io.bitsquare.user.Preferences; import javafx.scene.control.Button; import javafx.scene.control.Label; @@ -71,26 +70,25 @@ public class SellerStep3View extends TradeStepView { if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) { String message; String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume()); + String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()); if (paymentAccountContractData instanceof BlockChainAccountContractData) { - String nameByCode = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()); String address = ((BlockChainAccountContractData) paymentAccountContractData).getAddress(); - message = "Please check on your favorite " + - nameByCode + + message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" + + "Please check on your favorite " + currencyName + " blockchain explorer if the transaction to your receiving address\n" + "" + address + "\n" + - "has already " + - "sufficient blockchain confirmations.\n" + + "has already sufficient blockchain confirmations.\n" + "The payment amount has to be " + tradeAmountWithCode + "\n\n" + - "You can copy & paste your " + nameByCode + " address from the main screen after " + + "You can copy & paste your " + currencyName + " address from the main screen after " + "closing that popup."; } else { - message = "Please go to your online banking web page and check if you have received " + + message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" + + "Please go to your online banking web page and check if you have received " + tradeAmountWithCode + " from the bitcoin buyer.\n\n" + - "The reference text of the transaction is: " + trade.getShortId(); + "The reference text of the transaction is: \"" + trade.getShortId() + "\""; } - new Popup().headLine("Notification for trade with ID " + trade.getShortId()) - .message(message) - .closeButtonText("I understand") + new Popup().headLine("Attention required for trade with ID " + trade.getShortId()) + .instruction(message) .dontShowAgainId(id, preferences) .show(); @@ -220,16 +218,17 @@ public class SellerStep3View extends TradeStepView { log.debug("onPaymentReceived"); if (model.p2PService.isBootstrapped()) { Preferences preferences = model.dataModel.preferences; - String key = PopupId.PAYMENT_RECEIVED; + String key = "confirmPaymentReceived"; if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) { - new Popup().headLine("Confirmation") - .message("Did you receive the payment from your trading partner?\n\n" + - "Please note that as soon you have confirmed the locked bitcoin will be released.\n" + - "There is no way to reverse a bitcoin payment.") + new Popup() + .headLine("Confirm that you have received the payment") + .confirmation("Have you received the " + model.dataModel.getCurrencyCode() + " payment from your trading partner?\n\n" + + "Please note that as soon you have confirmed the receipt, the locked trade amount will be released " + + "to the bitcoin buyer and the security deposit will be refunded.") .width(700) .dontShowAgainId(key, preferences) - .actionButtonText("Yes I have received the payment") - .closeButtonText("No") + .actionButtonText("Yes, I have received the payment") + .closeButtonText("Cancel") .onAction(this::confirmPaymentReceived) .show(); } else { diff --git a/gui/src/main/java/io/bitsquare/gui/main/settings/preferences/PreferencesView.java b/gui/src/main/java/io/bitsquare/gui/main/settings/preferences/PreferencesView.java index f2b6420dd5..611905d23c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/settings/preferences/PreferencesView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/settings/preferences/PreferencesView.java @@ -57,8 +57,7 @@ public class PreferencesView extends ActivatableViewAndModel userLanguageComboBox; private ComboBox preferredTradeCurrencyComboBox; - private CheckBox useAnimationsCheckBox, useEffectsCheckBox, showNotificationsCheckBox, showInstructionsCheckBox, - autoSelectArbitratorsCheckBox; + private CheckBox useAnimationsCheckBox, useEffectsCheckBox, autoSelectArbitratorsCheckBox; private int gridRow = 0; //private InputTextField transactionFeeInputTextField; private ChangeListener transactionFeeFocusedListener; @@ -78,6 +77,7 @@ public class PreferencesView extends ActivatableViewAndModel cryptoCurrencies; public final ObservableList allCryptoCurrencies; public final ObservableList tradeCurrencies; + private Button resetDontShowAgainButton; /////////////////////////////////////////////////////////////////////////////////////////// @@ -293,16 +293,12 @@ public class PreferencesView extends ActivatableViewAndModel labelCheckBoxTuple2 = addLabelCheckBox(root, gridRow, "Show notifications:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE); - showNotificationsCheckBox = labelCheckBoxTuple2.second; - GridPane.setColumnIndex(labelCheckBoxTuple2.first, 2); - GridPane.setColumnIndex(showNotificationsCheckBox, 3); + Tuple2 labelButton = addLabelButton(root, gridRow, "Reset all don't show again flags:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE); + resetDontShowAgainButton = labelButton.second; + GridPane.setColumnIndex(labelButton.first, 2); + GridPane.setColumnIndex(resetDontShowAgainButton, 3); useEffectsCheckBox = addLabelCheckBox(root, ++gridRow, "Use effects:", "").second; - labelCheckBoxTuple2 = addLabelCheckBox(root, gridRow, "Show instruction popups:", ""); - showInstructionsCheckBox = labelCheckBoxTuple2.second; - GridPane.setColumnIndex(labelCheckBoxTuple2.first, 2); - GridPane.setColumnIndex(showInstructionsCheckBox, 3); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -406,11 +402,7 @@ public class PreferencesView extends ActivatableViewAndModel preferences.setUseEffects(useEffectsCheckBox.isSelected())); - showNotificationsCheckBox.setSelected(preferences.getShowNotifications()); - showNotificationsCheckBox.setOnAction(e -> preferences.setShowNotifications(showNotificationsCheckBox.isSelected())); - - showInstructionsCheckBox.setSelected(preferences.getShowInstructions()); - showInstructionsCheckBox.setOnAction(e -> preferences.setShowInstructions(showInstructionsCheckBox.isSelected())); + resetDontShowAgainButton.setOnAction(e -> preferences.resetDontShowAgainForType()); autoSelectArbitratorsCheckBox.setSelected(preferences.getAutoSelectArbitrators()); autoSelectArbitratorsCheckBox.setOnAction(e -> preferences.setAutoSelectArbitrators(autoSelectArbitratorsCheckBox.isSelected())); @@ -428,8 +420,6 @@ public class PreferencesView extends ActivatableViewAndModel