mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-25 07:27:18 +01:00
Add Notification and Instructions popups. Cleanup MainViewModel
This commit is contained in:
parent
cdccd57968
commit
6bf2adae7f
23 changed files with 637 additions and 514 deletions
|
@ -48,6 +48,7 @@ public class Dispute implements Serializable {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private final String tradeId;
|
private final String tradeId;
|
||||||
|
private final String id;
|
||||||
private final int traderId;
|
private final int traderId;
|
||||||
private final boolean disputeOpenerIsBuyer;
|
private final boolean disputeOpenerIsBuyer;
|
||||||
private final boolean disputeOpenerIsOfferer;
|
private final boolean disputeOpenerIsOfferer;
|
||||||
|
@ -123,6 +124,8 @@ public class Dispute implements Serializable {
|
||||||
this.arbitratorPubKeyRing = arbitratorPubKeyRing;
|
this.arbitratorPubKeyRing = arbitratorPubKeyRing;
|
||||||
this.isSupportTicket = isSupportTicket;
|
this.isSupportTicket = isSupportTicket;
|
||||||
this.openingDate = new Date().getTime();
|
this.openingDate = new Date().getTime();
|
||||||
|
|
||||||
|
id = tradeId + "_" + traderId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
|
@ -177,6 +180,10 @@ public class Dispute implements Serializable {
|
||||||
// Getters
|
// Getters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTradeId() {
|
public String getTradeId() {
|
||||||
return tradeId;
|
return tradeId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,8 +381,12 @@ public class TradeManager {
|
||||||
return offer.isMyOffer(keyRing);
|
return offer.isMyOffer(keyRing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMyOfferInBtcBuyerRole(Offer offer) {
|
public boolean isBuyer(Offer offer) {
|
||||||
return !(isMyOffer(offer) ^ offer.getDirection() == Offer.Direction.BUY);
|
// If I am the offerer, the offer direction is taken, otherwise the mirrored direction
|
||||||
|
if (isMyOffer(offer))
|
||||||
|
return offer.getDirection() == Offer.Direction.BUY;
|
||||||
|
else
|
||||||
|
return offer.getDirection() == Offer.Direction.SELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Trade> getTradeById(String tradeId) {
|
public Optional<Trade> getTradeById(String tradeId) {
|
||||||
|
|
|
@ -66,8 +66,7 @@ public class SetupDepositBalanceListener extends TradeTask {
|
||||||
|| newValue == Trade.State.DEPOSIT_SEEN_IN_NETWORK) {
|
|| newValue == Trade.State.DEPOSIT_SEEN_IN_NETWORK) {
|
||||||
|
|
||||||
walletService.removeBalanceListener(balanceListener);
|
walletService.removeBalanceListener(balanceListener);
|
||||||
log.debug(" UserThread.execute(this::unSubscribe);");
|
// hack to remove tradeStateSubscription at callback
|
||||||
// TODO is that allowed?
|
|
||||||
UserThread.execute(this::unSubscribe);
|
UserThread.execute(this::unSubscribe);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -81,8 +80,6 @@ public class SetupDepositBalanceListener extends TradeTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unSubscribe() {
|
private void unSubscribe() {
|
||||||
//TODO investigate, seems to not get called sometimes
|
|
||||||
log.debug("unSubscribe tradeStateSubscription");
|
|
||||||
tradeStateSubscription.unsubscribe();
|
tradeStateSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,8 @@ public class Preferences implements Serializable {
|
||||||
private final ArrayList<TradeCurrency> tradeCurrencies;
|
private final ArrayList<TradeCurrency> tradeCurrencies;
|
||||||
private BlockChainExplorer blockChainExplorerMainNet;
|
private BlockChainExplorer blockChainExplorerMainNet;
|
||||||
private BlockChainExplorer blockChainExplorerTestNet;
|
private BlockChainExplorer blockChainExplorerTestNet;
|
||||||
private boolean showPlaceOfferConfirmation;
|
private boolean showNotifications = true;
|
||||||
private boolean showTakeOfferConfirmation;
|
private boolean showInstructions = true;
|
||||||
private String backupDirectory;
|
private String backupDirectory;
|
||||||
private boolean autoSelectArbitrators = true;
|
private boolean autoSelectArbitrators = true;
|
||||||
private final Map<String, Boolean> showAgainMap;
|
private final Map<String, Boolean> showAgainMap;
|
||||||
|
@ -140,8 +140,8 @@ public class Preferences implements Serializable {
|
||||||
if (blockChainExplorerMainNet == null)
|
if (blockChainExplorerMainNet == null)
|
||||||
setBlockChainExplorerTestNet(blockChainExplorersMainNet.get(0));
|
setBlockChainExplorerTestNet(blockChainExplorersMainNet.get(0));
|
||||||
|
|
||||||
showPlaceOfferConfirmation = persisted.getShowPlaceOfferConfirmation();
|
showNotifications = persisted.getShowNotifications();
|
||||||
showTakeOfferConfirmation = persisted.getShowTakeOfferConfirmation();
|
showInstructions = persisted.getShowInstructions();
|
||||||
backupDirectory = persisted.getBackupDirectory();
|
backupDirectory = persisted.getBackupDirectory();
|
||||||
autoSelectArbitrators = persisted.getAutoSelectArbitrators();
|
autoSelectArbitrators = persisted.getAutoSelectArbitrators();
|
||||||
showAgainMap = persisted.getShowAgainMap();
|
showAgainMap = persisted.getShowAgainMap();
|
||||||
|
@ -163,8 +163,6 @@ public class Preferences implements Serializable {
|
||||||
tradeCurrencies = new ArrayList<>(tradeCurrenciesAsObservable);
|
tradeCurrencies = new ArrayList<>(tradeCurrenciesAsObservable);
|
||||||
setBlockChainExplorerTestNet(blockChainExplorersTestNet.get(0));
|
setBlockChainExplorerTestNet(blockChainExplorersTestNet.get(0));
|
||||||
setBlockChainExplorerMainNet(blockChainExplorersMainNet.get(0));
|
setBlockChainExplorerMainNet(blockChainExplorersMainNet.get(0));
|
||||||
showPlaceOfferConfirmation = true;
|
|
||||||
showTakeOfferConfirmation = true;
|
|
||||||
|
|
||||||
showAgainMap = new HashMap<>();
|
showAgainMap = new HashMap<>();
|
||||||
showAgainMap.put(PopupId.TRADE_WALLET, true);
|
showAgainMap.put(PopupId.TRADE_WALLET, true);
|
||||||
|
@ -253,13 +251,13 @@ public class Preferences implements Serializable {
|
||||||
setBlockChainExplorerTestNet(blockChainExplorer);
|
setBlockChainExplorerTestNet(blockChainExplorer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowPlaceOfferConfirmation(boolean showPlaceOfferConfirmation) {
|
public void setShowNotifications(boolean showNotifications) {
|
||||||
this.showPlaceOfferConfirmation = showPlaceOfferConfirmation;
|
this.showNotifications = showNotifications;
|
||||||
storage.queueUpForSave(2000);
|
storage.queueUpForSave(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowTakeOfferConfirmation(boolean showTakeOfferConfirmation) {
|
public void setShowInstructions(boolean showInstructions) {
|
||||||
this.showTakeOfferConfirmation = showTakeOfferConfirmation;
|
this.showInstructions = showInstructions;
|
||||||
storage.queueUpForSave(2000);
|
storage.queueUpForSave(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,13 +354,12 @@ public class Preferences implements Serializable {
|
||||||
return blockChainExplorersTestNet;
|
return blockChainExplorersTestNet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getShowPlaceOfferConfirmation() {
|
public boolean getShowNotifications() {
|
||||||
return showPlaceOfferConfirmation;
|
return showNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getShowInstructions() {
|
||||||
public boolean getShowTakeOfferConfirmation() {
|
return showInstructions;
|
||||||
return showTakeOfferConfirmation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBackupDirectory() {
|
public String getBackupDirectory() {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import io.bitsquare.common.crypto.KeyStorage;
|
||||||
import io.bitsquare.crypto.EncryptionServiceModule;
|
import io.bitsquare.crypto.EncryptionServiceModule;
|
||||||
import io.bitsquare.gui.GuiModule;
|
import io.bitsquare.gui.GuiModule;
|
||||||
import io.bitsquare.gui.common.view.CachingViewLoader;
|
import io.bitsquare.gui.common.view.CachingViewLoader;
|
||||||
|
import io.bitsquare.gui.main.intructions.InstructionCenter;
|
||||||
import io.bitsquare.gui.main.notifications.NotificationCenter;
|
import io.bitsquare.gui.main.notifications.NotificationCenter;
|
||||||
import io.bitsquare.p2p.P2PModule;
|
import io.bitsquare.p2p.P2PModule;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
|
@ -60,6 +61,7 @@ class BitsquareAppModule extends AppModule {
|
||||||
bind(User.class).in(Singleton.class);
|
bind(User.class).in(Singleton.class);
|
||||||
bind(Preferences.class).in(Singleton.class);
|
bind(Preferences.class).in(Singleton.class);
|
||||||
bind(NotificationCenter.class).in(Singleton.class);
|
bind(NotificationCenter.class).in(Singleton.class);
|
||||||
|
bind(InstructionCenter.class).in(Singleton.class);
|
||||||
|
|
||||||
File storageDir = new File(env.getRequiredProperty(Storage.DIR_KEY));
|
File storageDir = new File(env.getRequiredProperty(Storage.DIR_KEY));
|
||||||
bind(File.class).annotatedWith(named(Storage.DIR_KEY)).toInstance(storageDir);
|
bind(File.class).annotatedWith(named(Storage.DIR_KEY)).toInstance(storageDir);
|
||||||
|
|
|
@ -26,21 +26,23 @@ import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.arbitration.ArbitratorManager;
|
import io.bitsquare.arbitration.ArbitratorManager;
|
||||||
import io.bitsquare.arbitration.Dispute;
|
import io.bitsquare.arbitration.Dispute;
|
||||||
import io.bitsquare.arbitration.DisputeManager;
|
import io.bitsquare.arbitration.DisputeManager;
|
||||||
import io.bitsquare.btc.*;
|
import io.bitsquare.btc.AddressEntry;
|
||||||
|
import io.bitsquare.btc.FeePolicy;
|
||||||
|
import io.bitsquare.btc.TradeWalletService;
|
||||||
|
import io.bitsquare.btc.WalletService;
|
||||||
import io.bitsquare.btc.listeners.BalanceListener;
|
import io.bitsquare.btc.listeners.BalanceListener;
|
||||||
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
|
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.common.model.ViewModel;
|
import io.bitsquare.gui.common.model.ViewModel;
|
||||||
import io.bitsquare.gui.common.view.ViewPath;
|
|
||||||
import io.bitsquare.gui.components.BalanceTextField;
|
import io.bitsquare.gui.components.BalanceTextField;
|
||||||
import io.bitsquare.gui.components.BalanceWithConfirmationTextField;
|
import io.bitsquare.gui.components.BalanceWithConfirmationTextField;
|
||||||
import io.bitsquare.gui.components.TxIdTextField;
|
import io.bitsquare.gui.components.TxIdTextField;
|
||||||
|
import io.bitsquare.gui.main.notifications.NotificationCenter;
|
||||||
import io.bitsquare.gui.main.popups.DisplayAlertMessagePopup;
|
import io.bitsquare.gui.main.popups.DisplayAlertMessagePopup;
|
||||||
import io.bitsquare.gui.main.popups.Popup;
|
import io.bitsquare.gui.main.popups.Popup;
|
||||||
|
import io.bitsquare.gui.main.popups.TacPopup;
|
||||||
import io.bitsquare.gui.main.popups.WalletPasswordPopup;
|
import io.bitsquare.gui.main.popups.WalletPasswordPopup;
|
||||||
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
|
||||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesView;
|
|
||||||
import io.bitsquare.gui.util.BSFormatter;
|
import io.bitsquare.gui.util.BSFormatter;
|
||||||
import io.bitsquare.locale.CountryUtil;
|
import io.bitsquare.locale.CountryUtil;
|
||||||
import io.bitsquare.locale.CurrencyUtil;
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
|
@ -69,9 +71,9 @@ import org.reactfx.util.Timer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
@ -89,6 +91,8 @@ public class MainViewModel implements ViewModel {
|
||||||
private final Preferences preferences;
|
private final Preferences preferences;
|
||||||
private final AlertManager alertManager;
|
private final AlertManager alertManager;
|
||||||
private final WalletPasswordPopup walletPasswordPopup;
|
private final WalletPasswordPopup walletPasswordPopup;
|
||||||
|
private NotificationCenter notificationCenter;
|
||||||
|
private TacPopup tacPopup;
|
||||||
private Navigation navigation;
|
private Navigation navigation;
|
||||||
private final BSFormatter formatter;
|
private final BSFormatter formatter;
|
||||||
|
|
||||||
|
@ -133,8 +137,7 @@ public class MainViewModel implements ViewModel {
|
||||||
private java.util.Timer numberofBtcPeersTimer;
|
private java.util.Timer numberofBtcPeersTimer;
|
||||||
private java.util.Timer numberofP2PNetworkPeersTimer;
|
private java.util.Timer numberofP2PNetworkPeersTimer;
|
||||||
private Timer startupTimeout;
|
private Timer startupTimeout;
|
||||||
private Set<Subscription> tradeStateSubscriptions = new HashSet<>();
|
private final Map<String, Subscription> disputeIsClosedSubscriptionsMap = new HashMap<>();
|
||||||
private Set<Subscription> disputeStateSubscriptions = new HashSet<>();
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -147,6 +150,7 @@ public class MainViewModel implements ViewModel {
|
||||||
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
|
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
|
||||||
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
|
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
|
||||||
User user, AlertManager alertManager, WalletPasswordPopup walletPasswordPopup,
|
User user, AlertManager alertManager, WalletPasswordPopup walletPasswordPopup,
|
||||||
|
NotificationCenter notificationCenter, TacPopup tacPopup,
|
||||||
Navigation navigation, BSFormatter formatter) {
|
Navigation navigation, BSFormatter formatter) {
|
||||||
this.marketPriceFeed = marketPriceFeed;
|
this.marketPriceFeed = marketPriceFeed;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
@ -160,6 +164,8 @@ public class MainViewModel implements ViewModel {
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
this.alertManager = alertManager;
|
this.alertManager = alertManager;
|
||||||
this.walletPasswordPopup = walletPasswordPopup;
|
this.walletPasswordPopup = walletPasswordPopup;
|
||||||
|
this.notificationCenter = notificationCenter;
|
||||||
|
this.tacPopup = tacPopup;
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
|
||||||
|
@ -172,8 +178,6 @@ public class MainViewModel implements ViewModel {
|
||||||
BalanceWithConfirmationTextField.setWalletService(walletService);
|
BalanceWithConfirmationTextField.setWalletService(walletService);
|
||||||
|
|
||||||
if (BitsquareApp.DEV_MODE) {
|
if (BitsquareApp.DEV_MODE) {
|
||||||
preferences.setShowPlaceOfferConfirmation(false);
|
|
||||||
preferences.setShowTakeOfferConfirmation(false);
|
|
||||||
preferences.setUseAnimations(false);
|
preferences.setUseAnimations(false);
|
||||||
preferences.setUseEffects(false);
|
preferences.setUseEffects(false);
|
||||||
}
|
}
|
||||||
|
@ -221,6 +225,16 @@ public class MainViewModel implements ViewModel {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// UI handlers
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void onSplashScreenRemoved() {
|
||||||
|
isSplashScreenRemoved.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Initialisation
|
// Initialisation
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -360,33 +374,23 @@ public class MainViewModel implements ViewModel {
|
||||||
startupTimeout.stop();
|
startupTimeout.stop();
|
||||||
|
|
||||||
// disputeManager
|
// disputeManager
|
||||||
|
disputeManager.onAllServicesInitialized();
|
||||||
disputeManager.getDisputesAsObservableList().addListener((ListChangeListener<Dispute>) change -> {
|
disputeManager.getDisputesAsObservableList().addListener((ListChangeListener<Dispute>) change -> {
|
||||||
change.next();
|
change.next();
|
||||||
addDisputeClosedChangeListener(change.getAddedSubList());
|
onDisputesChangeListener(change.getAddedSubList(), change.getRemoved());
|
||||||
updateDisputeStates();
|
|
||||||
});
|
});
|
||||||
addDisputeClosedChangeListener(disputeManager.getDisputesAsObservableList());
|
onDisputesChangeListener(disputeManager.getDisputesAsObservableList(), null);
|
||||||
updateDisputeStates();
|
|
||||||
disputeManager.onAllServicesInitialized();
|
|
||||||
|
|
||||||
|
|
||||||
// tradeManager
|
// tradeManager
|
||||||
tradeManager.getTrades().addListener((ListChangeListener<Trade>) c -> updateBalance());
|
tradeManager.getTrades().addListener((ListChangeListener<Trade>) c -> updateBalance());
|
||||||
|
tradeManager.getTrades().addListener((ListChangeListener<Trade>) change -> onTradesChanged());
|
||||||
tradeManager.getTrades().addListener((ListChangeListener<Trade>) change -> {
|
onTradesChanged();
|
||||||
change.next();
|
// We handle the trade period here as we display a global popup if we reached dispute time
|
||||||
setDisputeStateSubscriptions();
|
tradesAndUIReady = EasyBind.combine(isSplashScreenRemoved, tradeManager.pendingTradesInitializedProperty(), (a, b) -> a && b);
|
||||||
setTradeStateSubscriptions();
|
tradesAndUIReady.subscribe((observable, oldValue, newValue) -> {
|
||||||
pendingTradesChanged();
|
if (newValue)
|
||||||
|
applyTradePeriodState();
|
||||||
});
|
});
|
||||||
pendingTradesChanged();
|
|
||||||
setDisputeStateSubscriptions();
|
|
||||||
setTradeStateSubscriptions();
|
|
||||||
|
|
||||||
|
|
||||||
// arbitratorManager
|
|
||||||
arbitratorManager.onAllServicesInitialized();
|
|
||||||
|
|
||||||
|
|
||||||
// walletService
|
// walletService
|
||||||
// In case we have any offers open or a pending trade we need to unlock our trading wallet so a trade can be executed automatically
|
// In case we have any offers open or a pending trade we need to unlock our trading wallet so a trade can be executed automatically
|
||||||
|
@ -398,77 +402,120 @@ public class MainViewModel implements ViewModel {
|
||||||
|| disputeManager.getDisputesAsObservableList().size() > 0)) {
|
|| disputeManager.getDisputesAsObservableList().size() > 0)) {
|
||||||
walletPasswordPopup.onAesKey(aesKey -> tradeWalletService.setAesKey(aesKey)).show();
|
walletPasswordPopup.onAesKey(aesKey -> tradeWalletService.setAesKey(aesKey)).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We handle the trade period here as we display a global popup if we reached dispute time
|
|
||||||
tradesAndUIReady = EasyBind.combine(isSplashScreenRemoved, tradeManager.pendingTradesInitializedProperty(), (a, b) -> a && b);
|
|
||||||
tradesAndUIReady.subscribe((observable, oldValue, newValue) -> {
|
|
||||||
if (newValue)
|
|
||||||
applyTradePeriodState();
|
|
||||||
});
|
|
||||||
|
|
||||||
walletService.addBalanceListener(new BalanceListener() {
|
walletService.addBalanceListener(new BalanceListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onBalanceChanged(Coin balance, Transaction tx) {
|
public void onBalanceChanged(Coin balance, Transaction tx) {
|
||||||
updateBalance();
|
updateBalance();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateBalance();
|
|
||||||
|
|
||||||
setBitcoinNetworkSyncProgress(walletService.downloadPercentageProperty().get());
|
setBitcoinNetworkSyncProgress(walletService.downloadPercentageProperty().get());
|
||||||
checkPeriodicallyForBtcSyncState();
|
checkPeriodicallyForBtcSyncState();
|
||||||
|
|
||||||
// openOfferManager
|
|
||||||
openOfferManager.getOpenOffers().addListener((ListChangeListener<OpenOffer>) c -> updateBalance());
|
openOfferManager.getOpenOffers().addListener((ListChangeListener<OpenOffer>) c -> updateBalance());
|
||||||
openOfferManager.onAllServicesInitialized();
|
openOfferManager.onAllServicesInitialized();
|
||||||
|
arbitratorManager.onAllServicesInitialized();
|
||||||
|
|
||||||
// alertManager
|
|
||||||
alertManager.alertMessageProperty().addListener((observable, oldValue, newValue) -> displayAlertIfPresent(newValue));
|
alertManager.alertMessageProperty().addListener((observable, oldValue, newValue) -> displayAlertIfPresent(newValue));
|
||||||
displayAlertIfPresent(alertManager.alertMessageProperty().get());
|
displayAlertIfPresent(alertManager.alertMessageProperty().get());
|
||||||
|
|
||||||
|
setupP2PPeersInfo();
|
||||||
|
updateBalance();
|
||||||
|
setupDevDummyPaymentAccount();
|
||||||
|
setupMarketPriceFeed();
|
||||||
|
|
||||||
// tac
|
tacPopup.showIfNeeded();
|
||||||
// TODO add link: https://bitsquare.io/arbitration_system.pdf
|
notificationCenter.onAllServicesInitialized();
|
||||||
String text = "1. This software is experimental and provided \"as is\", without warranty of any kind, " +
|
|
||||||
"express or implied, including but not limited to the warranties of " +
|
|
||||||
"merchantability, fitness for a particular purpose and non-infringement.\n" +
|
|
||||||
"In no event shall the authors or copyright holders be liable for any claim, damages or other " +
|
|
||||||
"liability, whether in an action of contract, tort or otherwise, " +
|
|
||||||
"arising from, out of or in connection with the software or the use or other dealings in the software.\n\n" +
|
|
||||||
"2. The user is responsible to use the software in compliance with local laws.\n\n" +
|
|
||||||
"3. The user confirms that he has read and agreed to the rules defined in our " +
|
|
||||||
"Wiki regrading the dispute process\n" +
|
|
||||||
"(https://github.com/bitsquare/bitsquare/wiki/Arbitration-system).";
|
|
||||||
if (!preferences.getTacAccepted() && !BitsquareApp.DEV_MODE) {
|
|
||||||
new Popup().headLine("USER AGREEMENT")
|
|
||||||
.message(text)
|
|
||||||
.actionButtonText("I agree")
|
|
||||||
.closeButtonText("I disagree and quit")
|
|
||||||
.onAction(() -> {
|
|
||||||
preferences.setTacAccepted(true);
|
|
||||||
if (preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET)
|
|
||||||
UserThread.runAfter(() -> new Popup()
|
|
||||||
.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 " +
|
|
||||||
"when using Mainnet.")
|
|
||||||
.headLine("Important information!")
|
|
||||||
.actionButtonText("I understand and want to use Mainnet")
|
|
||||||
.closeButtonText("Restart and use Testnet")
|
|
||||||
.onClose(() -> {
|
|
||||||
UserThread.execute(() -> preferences.setBitcoinNetwork(BitcoinNetwork.TESTNET));
|
|
||||||
UserThread.runAfter(BitsquareApp.shutDownHandler::run, 300, TimeUnit.MILLISECONDS);
|
|
||||||
})
|
|
||||||
.width(600)
|
|
||||||
.show(), 300, TimeUnit.MILLISECONDS);
|
|
||||||
})
|
|
||||||
.onClose(BitsquareApp.shutDownHandler::run)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// update nr of peers in footer
|
// now show app
|
||||||
|
showAppScreen.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// States
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void applyTradePeriodState() {
|
||||||
|
updateTradePeriodState();
|
||||||
|
tradeWalletService.addBlockChainListener(new BlockChainListener() {
|
||||||
|
@Override
|
||||||
|
public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
|
||||||
|
updateTradePeriodState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks)
|
||||||
|
throws VerificationException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveFromBlock(Transaction tx, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset)
|
||||||
|
throws VerificationException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, AbstractBlockChain.NewBlockType blockType,
|
||||||
|
int relativityOffset) throws VerificationException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTradePeriodState() {
|
||||||
|
tradeManager.getTrades().stream().forEach(trade -> {
|
||||||
|
int bestChainHeight = tradeWalletService.getBestChainHeight();
|
||||||
|
|
||||||
|
if (trade.getOpenDisputeTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getOpenDisputeTimeAsBlockHeight())
|
||||||
|
trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER);
|
||||||
|
else if (trade.getCheckPaymentTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getCheckPaymentTimeAsBlockHeight())
|
||||||
|
trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED);
|
||||||
|
|
||||||
|
String id;
|
||||||
|
String limitDate = formatter.addBlocksToNowDateFormatted(trade.getOpenDisputeTimeAsBlockHeight() - tradeWalletService.getBestChainHeight());
|
||||||
|
switch (trade.getTradePeriodState()) {
|
||||||
|
case NORMAL:
|
||||||
|
break;
|
||||||
|
case HALF_REACHED:
|
||||||
|
id = "displayHalfTradePeriodOver" + trade.getId();
|
||||||
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||||
|
preferences.dontShowAgain(id);
|
||||||
|
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||||
|
" has reached the half of the max. allowed trading period and " +
|
||||||
|
"is still not completed.\n\n" +
|
||||||
|
"The trade period ends on " + limitDate + "\n\n" +
|
||||||
|
"Please check your trade state at \"Portfolio/Open trades\" for further information.")
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TRADE_PERIOD_OVER:
|
||||||
|
id = "displayTradePeriodOver" + trade.getId();
|
||||||
|
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
||||||
|
preferences.dontShowAgain(id);
|
||||||
|
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||||
|
" has reached the max. allowed trading period and is " +
|
||||||
|
"not completed.\n\n" +
|
||||||
|
"The trade period ended on " + limitDate + "\n\n" +
|
||||||
|
"Please check your trade at \"Portfolio/Open trades\" for contacting " +
|
||||||
|
"the arbitrator.")
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void setupP2PPeersInfo() {
|
||||||
numConnectedPeersListener = (observable, oldValue, newValue) -> {
|
numConnectedPeersListener = (observable, oldValue, newValue) -> {
|
||||||
if ((int) oldValue > 0 && (int) newValue == 0) {
|
if ((int) oldValue > 0 && (int) newValue == 0) {
|
||||||
// give a bit of tolerance
|
// give a bit of tolerance
|
||||||
|
@ -492,19 +539,10 @@ public class MainViewModel implements ViewModel {
|
||||||
updateP2pNetworkInfoWithPeersChanged((int) newValue);
|
updateP2pNetworkInfoWithPeersChanged((int) newValue);
|
||||||
};
|
};
|
||||||
p2PService.getNumConnectedPeers().addListener(numConnectedPeersListener);
|
p2PService.getNumConnectedPeers().addListener(numConnectedPeersListener);
|
||||||
|
}
|
||||||
|
|
||||||
// now show app
|
|
||||||
showAppScreen.set(true);
|
|
||||||
|
|
||||||
if (BitsquareApp.DEV_MODE && user.getPaymentAccounts().isEmpty()) {
|
|
||||||
OKPayAccount okPayAccount = new OKPayAccount();
|
|
||||||
okPayAccount.setAccountNr("dummy");
|
|
||||||
okPayAccount.setAccountName("OKPay dummy");
|
|
||||||
okPayAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency());
|
|
||||||
okPayAccount.setCountry(CountryUtil.getDefaultCountry());
|
|
||||||
user.addPaymentAccount(okPayAccount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void setupMarketPriceFeed() {
|
||||||
if (marketPriceFeed.getCurrencyCode() == null)
|
if (marketPriceFeed.getCurrencyCode() == null)
|
||||||
marketPriceFeed.setCurrencyCode(preferences.getPreferredTradeCurrency().getCode());
|
marketPriceFeed.setCurrencyCode(preferences.getPreferredTradeCurrency().getCode());
|
||||||
if (marketPriceFeed.getType() == null)
|
if (marketPriceFeed.getType() == null)
|
||||||
|
@ -605,130 +643,39 @@ public class MainViewModel implements ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
private void onDisputesChangeListener(List<? extends Dispute> addedList, @Nullable List<? extends Dispute> removedList) {
|
||||||
// UI callbacks
|
if (removedList != null) {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
removedList.stream().forEach(dispute -> {
|
||||||
|
String id = dispute.getId();
|
||||||
void onSplashScreenRemoved() {
|
if (disputeIsClosedSubscriptionsMap.containsKey(id)) {
|
||||||
isSplashScreenRemoved.set(true);
|
disputeIsClosedSubscriptionsMap.get(id).unsubscribe();
|
||||||
}
|
disputeIsClosedSubscriptionsMap.remove(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Apply states
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void applyTradePeriodState() {
|
|
||||||
updateTradePeriodState();
|
|
||||||
tradeWalletService.addBlockChainListener(new BlockChainListener() {
|
|
||||||
@Override
|
|
||||||
public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
|
|
||||||
updateTradePeriodState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks)
|
|
||||||
throws VerificationException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void receiveFromBlock(Transaction tx, StoredBlock block, AbstractBlockChain.NewBlockType blockType, int relativityOffset)
|
|
||||||
throws VerificationException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, AbstractBlockChain.NewBlockType blockType,
|
|
||||||
int relativityOffset) throws VerificationException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setWalletServiceException(Throwable error) {
|
|
||||||
setBitcoinNetworkSyncProgress(0);
|
|
||||||
btcSplashInfo.set("Nr. of Bitcoin network peers: " + numBTCPeers + " / connecting to " + btcNetworkAsString + " failed");
|
|
||||||
btcFooterInfo.set(btcSplashInfo.get());
|
|
||||||
if (error instanceof TimeoutException) {
|
|
||||||
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
|
||||||
} else if (error.getCause() instanceof BlockStoreException) {
|
|
||||||
new Popup().warning("Bitsquare is already running. You cannot run 2 instances of Bitsquare.")
|
|
||||||
.closeButtonText("Shut down")
|
|
||||||
.onClose(BitsquareApp.shutDownHandler::run)
|
|
||||||
.show();
|
|
||||||
} else if (error.getMessage() != null) {
|
|
||||||
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.getMessage());
|
|
||||||
} else {
|
|
||||||
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.toString());
|
|
||||||
}
|
}
|
||||||
}
|
addedList.stream().forEach(dispute -> {
|
||||||
|
String id = dispute.getId();
|
||||||
|
if (disputeIsClosedSubscriptionsMap.containsKey(id)) {
|
||||||
|
log.warn("We have already an entry in disputeStateSubscriptionsMap. That should never happen.");
|
||||||
|
} else {
|
||||||
|
Subscription disputeStateSubscription = EasyBind.subscribe(dispute.isClosedProperty(),
|
||||||
|
disputeState -> {
|
||||||
|
int openDisputes = disputeManager.getDisputesAsObservableList().stream()
|
||||||
|
.filter(e -> !e.isClosed())
|
||||||
|
.collect(Collectors.toList()).size();
|
||||||
|
if (openDisputes > 0)
|
||||||
|
numOpenDisputesAsString.set(String.valueOf(openDisputes));
|
||||||
|
if (openDisputes > 9)
|
||||||
|
numOpenDisputesAsString.set("?");
|
||||||
|
|
||||||
private void updateTradePeriodState() {
|
showOpenDisputesNotification.set(openDisputes > 0);
|
||||||
tradeManager.getTrades().stream().forEach(trade -> {
|
});
|
||||||
int bestChainHeight = tradeWalletService.getBestChainHeight();
|
disputeIsClosedSubscriptionsMap.put(id, disputeStateSubscription);
|
||||||
|
|
||||||
if (trade.getOpenDisputeTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getOpenDisputeTimeAsBlockHeight())
|
|
||||||
trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER);
|
|
||||||
else if (trade.getCheckPaymentTimeAsBlockHeight() > 0 && bestChainHeight >= trade.getCheckPaymentTimeAsBlockHeight())
|
|
||||||
trade.setTradePeriodState(Trade.TradePeriodState.HALF_REACHED);
|
|
||||||
|
|
||||||
String id;
|
|
||||||
String limitDate = formatter.addBlocksToNowDateFormatted(trade.getOpenDisputeTimeAsBlockHeight() - tradeWalletService.getBestChainHeight());
|
|
||||||
switch (trade.getTradePeriodState()) {
|
|
||||||
case NORMAL:
|
|
||||||
break;
|
|
||||||
case HALF_REACHED:
|
|
||||||
id = "displayHalfTradePeriodOver" + trade.getId();
|
|
||||||
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
|
||||||
preferences.dontShowAgain(id);
|
|
||||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
|
||||||
" has reached the half of the max. allowed trading period and " +
|
|
||||||
"is still not completed.\n\n" +
|
|
||||||
"The trade period ends on " + limitDate + "\n\n" +
|
|
||||||
"Please check your trade state at \"Portfolio/Open trades\" for further information.")
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TRADE_PERIOD_OVER:
|
|
||||||
id = "displayTradePeriodOver" + trade.getId();
|
|
||||||
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE) {
|
|
||||||
preferences.dontShowAgain(id);
|
|
||||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
|
||||||
" has reached the max. allowed trading period and is " +
|
|
||||||
"not completed.\n\n" +
|
|
||||||
"The trade period ended on " + limitDate + "\n\n" +
|
|
||||||
"Please check your trade at \"Portfolio/Open trades\" for contacting " +
|
|
||||||
"the arbitrator.")
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDisputeClosedChangeListener(List<? extends Dispute> list) {
|
private void onTradesChanged() {
|
||||||
list.stream().forEach(e -> e.isClosedProperty().addListener((observable, oldValue, newValue) -> {
|
|
||||||
if (newValue)
|
|
||||||
updateDisputeStates();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisputeStates() {
|
|
||||||
int openDisputes = disputeManager.getDisputesAsObservableList().stream().filter(e -> !e.isClosed()).collect(Collectors.toList()).size();
|
|
||||||
if (openDisputes > 0)
|
|
||||||
numOpenDisputesAsString.set(String.valueOf(openDisputes));
|
|
||||||
if (openDisputes > 9)
|
|
||||||
numOpenDisputesAsString.set("?");
|
|
||||||
|
|
||||||
showOpenDisputesNotification.set(openDisputes > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pendingTradesChanged() {
|
|
||||||
long numPendingTrades = tradeManager.getTrades().size();
|
long numPendingTrades = tradeManager.getTrades().size();
|
||||||
if (numPendingTrades > 0)
|
if (numPendingTrades > 0)
|
||||||
numPendingTradesAsString.set(String.valueOf(numPendingTrades));
|
numPendingTradesAsString.set(String.valueOf(numPendingTrades));
|
||||||
|
@ -738,132 +685,6 @@ public class MainViewModel implements ViewModel {
|
||||||
showPendingTradesNotification.set(numPendingTrades > 0);
|
showPendingTradesNotification.set(numPendingTrades > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTradeStateSubscriptions() {
|
|
||||||
tradeStateSubscriptions.stream().forEach(Subscription::unsubscribe);
|
|
||||||
tradeStateSubscriptions.clear();
|
|
||||||
|
|
||||||
tradeManager.getTrades().stream().forEach(trade -> {
|
|
||||||
Subscription tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> {
|
|
||||||
if (newValue != null) {
|
|
||||||
applyTradeState(trade);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tradeStateSubscriptions.add(tradeStateSubscription);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyTradeState(Trade trade) {
|
|
||||||
Trade.State state = trade.getState();
|
|
||||||
log.debug("addTradeStateListeners " + state);
|
|
||||||
boolean isBtcBuyer = tradeManager.isMyOfferInBtcBuyerRole(trade.getOffer());
|
|
||||||
String headLine = "Notification for trade with ID " + trade.getShortId();
|
|
||||||
String message = null;
|
|
||||||
String id = "notificationPopup_" + state + trade.getId();
|
|
||||||
if (isBtcBuyer) {
|
|
||||||
switch (state) {
|
|
||||||
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
|
|
||||||
message = "Your offer has been accepted by a seller.\n" +
|
|
||||||
"You need to wait for one blockchain confirmation before starting the payment.";
|
|
||||||
break;
|
|
||||||
case DEPOSIT_CONFIRMED:
|
|
||||||
message = "The deposit transaction of your trade has got the first blockchain confirmation.\n" +
|
|
||||||
"You have to start the payment to the bitcoin seller now.";
|
|
||||||
|
|
||||||
break;
|
|
||||||
/* case FIAT_PAYMENT_RECEIPT_MSG_RECEIVED:
|
|
||||||
case PAYOUT_TX_COMMITTED:
|
|
||||||
case PAYOUT_TX_SENT:*/
|
|
||||||
case PAYOUT_BROAD_CASTED:
|
|
||||||
message = "The bitcoin seller has confirmed the receipt of your payment and the payout transaction has been published.\n" +
|
|
||||||
"The trade is now completed and you can withdraw your funds.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (state) {
|
|
||||||
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
|
|
||||||
message = "Your offer has been accepted by a buyer.\n" +
|
|
||||||
"You need to wait for one blockchain confirmation before starting the payment.";
|
|
||||||
break;
|
|
||||||
case FIAT_PAYMENT_STARTED_MSG_RECEIVED:
|
|
||||||
message = "The bitcoin buyer has started the payment.\n" +
|
|
||||||
"Please check your payment account if you have received his payment.";
|
|
||||||
break;
|
|
||||||
/* case FIAT_PAYMENT_RECEIPT_MSG_SENT:
|
|
||||||
case PAYOUT_TX_RECEIVED:
|
|
||||||
case PAYOUT_TX_COMMITTED:*/
|
|
||||||
case PAYOUT_BROAD_CASTED:
|
|
||||||
message = "The payout transaction has been published.\n" +
|
|
||||||
"The trade is now completed and you can withdraw your funds.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewPath currentPath = navigation.getCurrentPath();
|
|
||||||
boolean isPendingTradesViewCurrentView = currentPath != null &&
|
|
||||||
currentPath.size() == 3 &&
|
|
||||||
currentPath.get(2).equals(PendingTradesView.class);
|
|
||||||
if (message != null) {
|
|
||||||
//TODO we get that called initially before the navigation is inited
|
|
||||||
if (isPendingTradesViewCurrentView || currentPath == null) {
|
|
||||||
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE)
|
|
||||||
new Popup().headLine(headLine)
|
|
||||||
.message(message)
|
|
||||||
.show();
|
|
||||||
preferences.dontShowAgain(id);
|
|
||||||
} else {
|
|
||||||
if (preferences.showAgain(id) && !BitsquareApp.DEV_MODE)
|
|
||||||
new Popup().headLine(headLine)
|
|
||||||
.message(message)
|
|
||||||
.actionButtonText("Go to \"Portfolio/Open trades\"")
|
|
||||||
.onAction(() -> {
|
|
||||||
FxTimer.runLater(Duration.ofMillis(100),
|
|
||||||
() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class)
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
preferences.dontShowAgain(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDisputeStateSubscriptions() {
|
|
||||||
disputeStateSubscriptions.stream().forEach(Subscription::unsubscribe);
|
|
||||||
disputeStateSubscriptions.clear();
|
|
||||||
|
|
||||||
tradeManager.getTrades().stream().forEach(trade -> {
|
|
||||||
Subscription disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), disputeState -> {
|
|
||||||
if (disputeState != null) {
|
|
||||||
applyDisputeState(trade, disputeState);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
disputeStateSubscriptions.add(disputeStateSubscription);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyDisputeState(Trade trade, Trade.DisputeState disputeState) {
|
|
||||||
switch (disputeState) {
|
|
||||||
case NONE:
|
|
||||||
break;
|
|
||||||
case DISPUTE_REQUESTED:
|
|
||||||
break;
|
|
||||||
case DISPUTE_STARTED_BY_PEER:
|
|
||||||
disputeManager.findOwnDispute(trade.getId()).ifPresent(dispute -> {
|
|
||||||
String msg;
|
|
||||||
if (dispute.isSupportTicket())
|
|
||||||
msg = "Your trading peer has encountered technical problems and requested support for trade with ID " + trade.getShortId() + ".\n" +
|
|
||||||
"Please await further instructions from the arbitrator.\n" +
|
|
||||||
"Your funds are safe and will be refunded as soon the problem is resolved.";
|
|
||||||
else
|
|
||||||
msg = "Your trading peer has requested a dispute for trade with ID " + trade.getShortId() + ".";
|
|
||||||
|
|
||||||
new Popup().information(msg).show();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case DISPUTE_CLOSED:
|
|
||||||
new Popup().information("A support ticket for trade with ID " + trade.getShortId() + " has been closed.").show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBitcoinNetworkSyncProgress(double value) {
|
private void setBitcoinNetworkSyncProgress(double value) {
|
||||||
btcSyncProgress.set(value);
|
btcSyncProgress.set(value);
|
||||||
String numPeers = "Nr. of Bitcoin network peers: " + numBTCPeers;
|
String numPeers = "Nr. of Bitcoin network peers: " + numBTCPeers;
|
||||||
|
@ -885,10 +706,39 @@ public class MainViewModel implements ViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setWalletServiceException(Throwable error) {
|
||||||
|
setBitcoinNetworkSyncProgress(0);
|
||||||
|
btcSplashInfo.set("Nr. of Bitcoin network peers: " + numBTCPeers + " / connecting to " + btcNetworkAsString + " failed");
|
||||||
|
btcFooterInfo.set(btcSplashInfo.get());
|
||||||
|
if (error instanceof TimeoutException) {
|
||||||
|
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
||||||
|
} else if (error.getCause() instanceof BlockStoreException) {
|
||||||
|
new Popup().warning("Bitsquare is already running. You cannot run 2 instances of Bitsquare.")
|
||||||
|
.closeButtonText("Shut down")
|
||||||
|
.onClose(BitsquareApp.shutDownHandler::run)
|
||||||
|
.show();
|
||||||
|
} else if (error.getMessage() != null) {
|
||||||
|
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.getMessage());
|
||||||
|
} else {
|
||||||
|
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void stopCheckForBtcSyncStateTimer() {
|
private void stopCheckForBtcSyncStateTimer() {
|
||||||
if (checkForBtcSyncStateTimer != null) {
|
if (checkForBtcSyncStateTimer != null) {
|
||||||
checkForBtcSyncStateTimer.stop();
|
checkForBtcSyncStateTimer.stop();
|
||||||
checkForBtcSyncStateTimer = null;
|
checkForBtcSyncStateTimer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupDevDummyPaymentAccount() {
|
||||||
|
if (BitsquareApp.DEV_MODE && user.getPaymentAccounts().isEmpty()) {
|
||||||
|
OKPayAccount okPayAccount = new OKPayAccount();
|
||||||
|
okPayAccount.setAccountNr("dummy");
|
||||||
|
okPayAccount.setAccountName("OKPay dummy");
|
||||||
|
okPayAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency());
|
||||||
|
okPayAccount.setCountry(CountryUtil.getDefaultCountry());
|
||||||
|
user.addPaymentAccount(okPayAccount);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -575,7 +575,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||||
// TODO There are still some cell rendering issues on updates
|
// TODO There are still some cell rendering issues on updates
|
||||||
setGraphic(messageAnchorPane);
|
setGraphic(messageAnchorPane);
|
||||||
} else {
|
} else {
|
||||||
if (sendMsgProgressIndicator != null)
|
if (sendMsgProgressIndicator != null && sendMsgProgressIndicatorListener != null)
|
||||||
sendMsgProgressIndicator.progressProperty().removeListener(sendMsgProgressIndicatorListener);
|
sendMsgProgressIndicator.progressProperty().removeListener(sendMsgProgressIndicatorListener);
|
||||||
|
|
||||||
messageAnchorPane.prefWidthProperty().unbind();
|
messageAnchorPane.prefWidthProperty().unbind();
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package io.bitsquare.gui.main.intructions;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.gui.main.popups.Popup;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Instruction extends Popup {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(Instruction.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public Instruction() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package io.bitsquare.gui.main.intructions;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.gui.main.notifications.Notification;
|
||||||
|
import io.bitsquare.trade.TradeManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
public class InstructionCenter {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(InstructionCenter.class);
|
||||||
|
private Queue<io.bitsquare.gui.main.notifications.Notification> notifications = new LinkedBlockingQueue<>(3);
|
||||||
|
private io.bitsquare.gui.main.notifications.Notification displayedNotification;
|
||||||
|
private TradeManager tradeManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public InstructionCenter(TradeManager tradeManager) {
|
||||||
|
this.tradeManager = tradeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queueForDisplay(io.bitsquare.gui.main.notifications.Notification notification) {
|
||||||
|
boolean result = notifications.offer(notification);
|
||||||
|
if (!result)
|
||||||
|
log.warn("The capacity is full with popups in the queue.\n\t" +
|
||||||
|
"Not added new notification=" + notification);
|
||||||
|
displayNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void isHidden(Notification notification) {
|
||||||
|
if (displayedNotification == null || displayedNotification == notification) {
|
||||||
|
displayedNotification = null;
|
||||||
|
displayNext();
|
||||||
|
} else {
|
||||||
|
log.warn("We got a isHidden called with a wrong notification.\n\t" +
|
||||||
|
"notification (argument)=" + notification + "\n\tdisplayedPopup=" + displayedNotification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayNext() {
|
||||||
|
if (displayedNotification == null) {
|
||||||
|
if (!notifications.isEmpty()) {
|
||||||
|
displayedNotification = notifications.poll();
|
||||||
|
displayedNotification.display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.bitsquare.gui.main.notifications;
|
||||||
|
|
||||||
|
import io.bitsquare.gui.main.popups.Popup;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Notification extends Popup {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(Notification.class);
|
||||||
|
private boolean hasBeenDisplayed;
|
||||||
|
|
||||||
|
public Notification() {
|
||||||
|
NotificationCenter.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification headLine(String headLine) {
|
||||||
|
return (Notification) super.headLine(headLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification tradeHeadLine(String tradeId) {
|
||||||
|
return headLine("Notification for trade with ID " + tradeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification disputeHeadLine(String tradeId) {
|
||||||
|
return headLine("Support ticket for trade with ID " + tradeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Notification message(String message) {
|
||||||
|
return (Notification) super.message(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
super.show();
|
||||||
|
hasBeenDisplayed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
super.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasBeenDisplayed() {
|
||||||
|
return hasBeenDisplayed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,195 @@
|
||||||
package io.bitsquare.gui.main.notifications;
|
package io.bitsquare.gui.main.notifications;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.app.Log;
|
||||||
|
import io.bitsquare.arbitration.DisputeManager;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.TradeManager;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
import org.fxmisc.easybind.Subscription;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class NotificationCenter {
|
public class NotificationCenter {
|
||||||
private static final Logger log = LoggerFactory.getLogger(NotificationCenter.class);
|
private static final Logger log = LoggerFactory.getLogger(NotificationCenter.class);
|
||||||
|
|
||||||
@Inject
|
|
||||||
public NotificationCenter() {
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Static
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private final static List<Notification> notifications = new ArrayList<>();
|
||||||
|
|
||||||
|
static void add(Notification notification) {
|
||||||
|
notifications.add(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Instance fields
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private TradeManager tradeManager;
|
||||||
|
private DisputeManager disputeManager;
|
||||||
|
|
||||||
|
private final Map<String, Subscription> disputeStateSubscriptionsMap = new HashMap<>();
|
||||||
|
private final Map<String, Subscription> tradeStateSubscriptionsMap = new HashMap<>();
|
||||||
|
private String selectedTradeId;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor, initialisation
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NotificationCenter(TradeManager tradeManager, DisputeManager disputeManager) {
|
||||||
|
this.tradeManager = tradeManager;
|
||||||
|
this.disputeManager = disputeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAllServicesInitialized() {
|
||||||
|
tradeManager.getTrades().addListener((ListChangeListener<Trade>) change -> {
|
||||||
|
change.next();
|
||||||
|
log.error("change getRemoved " + change.getRemoved());
|
||||||
|
log.error("change getAddedSubList " + change.getAddedSubList());
|
||||||
|
if (change.wasRemoved()) {
|
||||||
|
change.getRemoved().stream().forEach(trade -> {
|
||||||
|
String tradeId = trade.getId();
|
||||||
|
if (disputeStateSubscriptionsMap.containsKey(tradeId)) {
|
||||||
|
disputeStateSubscriptionsMap.get(tradeId).unsubscribe();
|
||||||
|
disputeStateSubscriptionsMap.remove(tradeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tradeStateSubscriptionsMap.containsKey(tradeId)) {
|
||||||
|
tradeStateSubscriptionsMap.get(tradeId).unsubscribe();
|
||||||
|
tradeStateSubscriptionsMap.remove(tradeId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (change.wasAdded()) {
|
||||||
|
change.getAddedSubList().stream().forEach(trade -> {
|
||||||
|
String tradeId = trade.getId();
|
||||||
|
if (disputeStateSubscriptionsMap.containsKey(tradeId)) {
|
||||||
|
log.warn("We have already an entry in disputeStateSubscriptionsMap. That should never happen.");
|
||||||
|
} else {
|
||||||
|
Subscription disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), disputeState -> onDisputeStateChanged(trade, disputeState));
|
||||||
|
disputeStateSubscriptionsMap.put(tradeId, disputeStateSubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tradeStateSubscriptionsMap.containsKey(tradeId)) {
|
||||||
|
log.warn("We have already an entry in tradeStateSubscriptionsMap. That should never happen.");
|
||||||
|
} else {
|
||||||
|
Subscription tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), tradeState -> onTradeStateChanged(trade, tradeState));
|
||||||
|
tradeStateSubscriptionsMap.put(tradeId, tradeStateSubscription);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tradeManager.getTrades().stream()
|
||||||
|
.forEach(trade -> {
|
||||||
|
String tradeId = trade.getId();
|
||||||
|
Subscription disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), disputeState -> onDisputeStateChanged(trade, disputeState));
|
||||||
|
disputeStateSubscriptionsMap.put(tradeId, disputeStateSubscription);
|
||||||
|
|
||||||
|
Subscription tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), tradeState -> onTradeStateChanged(trade, tradeState));
|
||||||
|
tradeStateSubscriptionsMap.put(tradeId, tradeStateSubscription);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Setter/Getter
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getSelectedTradeId() {
|
||||||
|
return selectedTradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedTradeId(String selectedTradeId) {
|
||||||
|
this.selectedTradeId = selectedTradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void onTradeStateChanged(Trade trade, Trade.State tradeState) {
|
||||||
|
Log.traceCall(tradeState.toString());
|
||||||
|
String message = null;
|
||||||
|
if (tradeManager.isBuyer(trade.getOffer())) {
|
||||||
|
switch (tradeState) {
|
||||||
|
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
|
||||||
|
message = "Your offer has been accepted by a seller.\n" +
|
||||||
|
"You need to wait for one blockchain confirmation before starting the payment.";
|
||||||
|
break;
|
||||||
|
case DEPOSIT_CONFIRMED:
|
||||||
|
message = "The deposit transaction of your trade has got the first blockchain confirmation.\n" +
|
||||||
|
"You have to start the payment to the bitcoin seller now.";
|
||||||
|
|
||||||
|
break;
|
||||||
|
/* case FIAT_PAYMENT_RECEIPT_MSG_RECEIVED:
|
||||||
|
case PAYOUT_TX_COMMITTED:
|
||||||
|
case PAYOUT_TX_SENT:*/
|
||||||
|
case PAYOUT_BROAD_CASTED:
|
||||||
|
message = "The bitcoin seller has confirmed the receipt of your payment and the payout transaction has been published.\n" +
|
||||||
|
"The trade is now completed and you can withdraw your funds.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (tradeState) {
|
||||||
|
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
|
||||||
|
message = "Your offer has been accepted by a buyer.\n" +
|
||||||
|
"You need to wait for one blockchain confirmation before starting the payment.";
|
||||||
|
break;
|
||||||
|
case FIAT_PAYMENT_STARTED_MSG_RECEIVED:
|
||||||
|
message = "The bitcoin buyer has started the payment.\n" +
|
||||||
|
"Please check your payment account if you have received his payment.";
|
||||||
|
break;
|
||||||
|
/* case FIAT_PAYMENT_RECEIPT_MSG_SENT:
|
||||||
|
case PAYOUT_TX_RECEIVED:
|
||||||
|
case PAYOUT_TX_COMMITTED:*/
|
||||||
|
case PAYOUT_BROAD_CASTED:
|
||||||
|
message = "The payout transaction has been published.\n" +
|
||||||
|
"The trade is now completed and you can withdraw your funds.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message != null && !trade.getId().equals(selectedTradeId))
|
||||||
|
new Notification().tradeHeadLine(trade.getShortId()).message(message).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDisputeStateChanged(Trade trade, Trade.DisputeState disputeState) {
|
||||||
|
Log.traceCall(disputeState.toString());
|
||||||
|
String message = null;
|
||||||
|
switch (disputeState) {
|
||||||
|
case NONE:
|
||||||
|
break;
|
||||||
|
case DISPUTE_REQUESTED:
|
||||||
|
break;
|
||||||
|
case DISPUTE_STARTED_BY_PEER:
|
||||||
|
if (disputeManager.findOwnDispute(trade.getId()).isPresent()) {
|
||||||
|
if (disputeManager.findOwnDispute(trade.getId()).get().isSupportTicket())
|
||||||
|
message = "Your trading peer has encountered technical problems and requested support for trade with ID " + trade.getShortId() + ".\n" +
|
||||||
|
"Please await further instructions from the arbitrator.\n" +
|
||||||
|
"Your funds are safe and will be refunded as soon the problem is resolved.";
|
||||||
|
else
|
||||||
|
message = "Your trading peer has requested a dispute for trade with ID " + trade.getShortId() + ".";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DISPUTE_CLOSED:
|
||||||
|
message = "A support ticket for trade with ID " + trade.getShortId() + " has been closed.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (message != null)
|
||||||
|
new Notification().tradeHeadLine(trade.getShortId()).message(message).show();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,14 +391,6 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
return user.getAcceptedArbitrators();
|
return user.getAcceptedArbitrators();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowPlaceOfferConfirmation(boolean selected) {
|
|
||||||
preferences.setShowPlaceOfferConfirmation(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getShowPlaceOfferConfirmation() {
|
|
||||||
return preferences.getShowPlaceOfferConfirmation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Preferences getPreferences() {
|
public Preferences getPreferences() {
|
||||||
return preferences;
|
return preferences;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ import io.bitsquare.locale.BSResources;
|
||||||
import io.bitsquare.locale.TradeCurrency;
|
import io.bitsquare.locale.TradeCurrency;
|
||||||
import io.bitsquare.payment.PaymentAccount;
|
import io.bitsquare.payment.PaymentAccount;
|
||||||
import io.bitsquare.trade.offer.Offer;
|
import io.bitsquare.trade.offer.Offer;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
|
@ -109,6 +110,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
|
|
||||||
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
|
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
|
||||||
private int gridRow = 0;
|
private int gridRow = 0;
|
||||||
|
private Preferences preferences;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -116,11 +118,12 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CreateOfferView(CreateOfferViewModel model, Navigation navigation, OfferDetailsPopup offerDetailsPopup) {
|
private CreateOfferView(CreateOfferViewModel model, Navigation navigation, OfferDetailsPopup offerDetailsPopup, Preferences preferences) {
|
||||||
super(model);
|
super(model);
|
||||||
|
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.offerDetailsPopup = offerDetailsPopup;
|
this.offerDetailsPopup = offerDetailsPopup;
|
||||||
|
this.preferences = preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -210,8 +213,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
private void onPlaceOffer() {
|
private void onPlaceOffer() {
|
||||||
if (model.isBootstrapped()) {
|
if (model.isBootstrapped()) {
|
||||||
Offer offer = model.createAndGetOffer();
|
Offer offer = model.createAndGetOffer();
|
||||||
if (model.getShowPlaceOfferConfirmation()) {
|
String id = "CreatOfferConfirmation";
|
||||||
offerDetailsPopup.onPlaceOffer(o -> model.onPlaceOffer(o)).show(offer);
|
if (preferences.showAgain(id)) {
|
||||||
|
offerDetailsPopup.onPlaceOffer(model::onPlaceOffer)
|
||||||
|
.dontShowAgainId(id)
|
||||||
|
.show(offer);
|
||||||
} else {
|
} else {
|
||||||
if (model.hasAcceptedArbitrators()) {
|
if (model.hasAcceptedArbitrators()) {
|
||||||
model.onPlaceOffer(offer);
|
model.onPlaceOffer(offer);
|
||||||
|
|
|
@ -577,13 +577,4 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
public List<Arbitrator> getArbitrators() {
|
public List<Arbitrator> getArbitrators() {
|
||||||
return dataModel.getArbitrators();
|
return dataModel.getArbitrators();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowPlaceOfferConfirmation(boolean selected) {
|
|
||||||
dataModel.setShowPlaceOfferConfirmation(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getShowPlaceOfferConfirmation() {
|
|
||||||
return dataModel.getShowPlaceOfferConfirmation();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,14 +377,6 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||||
return addressEntry;
|
return addressEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getShowTakeOfferConfirmation() {
|
|
||||||
return preferences.getShowTakeOfferConfirmation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShowTakeOfferConfirmation(boolean selected) {
|
|
||||||
preferences.setShowTakeOfferConfirmation(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Arbitrator> getArbitrators() {
|
public List<Arbitrator> getArbitrators() {
|
||||||
return user.getAcceptedArbitrators();
|
return user.getAcceptedArbitrators();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import io.bitsquare.gui.util.Layout;
|
||||||
import io.bitsquare.locale.BSResources;
|
import io.bitsquare.locale.BSResources;
|
||||||
import io.bitsquare.payment.PaymentAccount;
|
import io.bitsquare.payment.PaymentAccount;
|
||||||
import io.bitsquare.trade.offer.Offer;
|
import io.bitsquare.trade.offer.Offer;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.geometry.*;
|
import javafx.geometry.*;
|
||||||
|
@ -71,6 +72,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private final BSFormatter formatter;
|
private final BSFormatter formatter;
|
||||||
private final OfferDetailsPopup offerDetailsPopup;
|
private final OfferDetailsPopup offerDetailsPopup;
|
||||||
|
private Preferences preferences;
|
||||||
private ScrollPane scrollPane;
|
private ScrollPane scrollPane;
|
||||||
private GridPane gridPane;
|
private GridPane gridPane;
|
||||||
private ImageView imageView;
|
private ImageView imageView;
|
||||||
|
@ -108,12 +110,14 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private TakeOfferView(TakeOfferViewModel model, Navigation navigation, BSFormatter formatter, OfferDetailsPopup offerDetailsPopup) {
|
private TakeOfferView(TakeOfferViewModel model, Navigation navigation, BSFormatter formatter,
|
||||||
|
OfferDetailsPopup offerDetailsPopup, Preferences preferences) {
|
||||||
super(model);
|
super(model);
|
||||||
|
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
this.offerDetailsPopup = offerDetailsPopup;
|
this.offerDetailsPopup = offerDetailsPopup;
|
||||||
|
this.preferences = preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -349,8 +353,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
|
|
||||||
private void onTakeOffer() {
|
private void onTakeOffer() {
|
||||||
Offer offer = model.getOffer();
|
Offer offer = model.getOffer();
|
||||||
if (model.getShowTakeOfferConfirmation()) {
|
String id = "TakeOfferConfirmation";
|
||||||
offerDetailsPopup.onTakeOffer(() -> model.onTakeOffer()).show(offer, model.dataModel.amountAsCoin.get());
|
if (preferences.showAgain(id)) {
|
||||||
|
offerDetailsPopup.onTakeOffer(() -> model.onTakeOffer())
|
||||||
|
.dontShowAgainId(id)
|
||||||
|
.show(offer, model.dataModel.amountAsCoin.get());
|
||||||
} else {
|
} else {
|
||||||
if (model.hasAcceptedArbitrators()) {
|
if (model.hasAcceptedArbitrators()) {
|
||||||
model.onTakeOffer();
|
model.onTakeOffer();
|
||||||
|
|
|
@ -543,10 +543,6 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||||
return dataModel.getTradeCurrency();
|
return dataModel.getTradeCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getShowTakeOfferConfirmation() {
|
|
||||||
return dataModel.getShowTakeOfferConfirmation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Arbitrator> getArbitrators() {
|
public List<Arbitrator> getArbitrators() {
|
||||||
return dataModel.getArbitrators();
|
return dataModel.getArbitrators();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import io.bitsquare.user.Preferences;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.CheckBox;
|
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
|
@ -51,7 +50,7 @@ public class OfferDetailsPopup extends Popup {
|
||||||
protected static final Logger log = LoggerFactory.getLogger(OfferDetailsPopup.class);
|
protected static final Logger log = LoggerFactory.getLogger(OfferDetailsPopup.class);
|
||||||
|
|
||||||
private final BSFormatter formatter;
|
private final BSFormatter formatter;
|
||||||
private final Preferences preferences;
|
protected final Preferences preferences;
|
||||||
private final User user;
|
private final User user;
|
||||||
private KeyRing keyRing;
|
private KeyRing keyRing;
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
|
@ -97,6 +96,11 @@ public class OfferDetailsPopup extends Popup {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OfferDetailsPopup dontShowAgainId(String dontShowAgainId) {
|
||||||
|
this.dontShowAgainId = dontShowAgainId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public OfferDetailsPopup onPlaceOffer(Consumer<Offer> placeOfferHandler) {
|
public OfferDetailsPopup onPlaceOffer(Consumer<Offer> placeOfferHandler) {
|
||||||
this.placeOfferHandlerOptional = Optional.of(placeOfferHandler);
|
this.placeOfferHandlerOptional = Optional.of(placeOfferHandler);
|
||||||
return this;
|
return this;
|
||||||
|
@ -189,13 +193,13 @@ public class OfferDetailsPopup extends Popup {
|
||||||
addLabelTextField(gridPane, rowIndex, "Please note:", Offer.TAC_OFFERER, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextField(gridPane, rowIndex, "Please note:", Offer.TAC_OFFERER, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
|
||||||
Button cancelButton = addConfirmButton(true);
|
Button cancelButton = addConfirmButton(true);
|
||||||
addCancelButton(cancelButton, true);
|
addCancelButton(cancelButton);
|
||||||
} else if (takeOfferHandlerOptional.isPresent()) {
|
} else if (takeOfferHandlerOptional.isPresent()) {
|
||||||
addTitledGroupBg(gridPane, ++rowIndex, 1, "Contract", Layout.GROUP_DISTANCE);
|
addTitledGroupBg(gridPane, ++rowIndex, 1, "Contract", Layout.GROUP_DISTANCE);
|
||||||
addLabelTextField(gridPane, rowIndex, "Terms and conditions:", Offer.TAC_TAKER, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
addLabelTextField(gridPane, rowIndex, "Terms and conditions:", Offer.TAC_TAKER, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
|
||||||
Button cancelButton = addConfirmButton(false);
|
Button cancelButton = addConfirmButton(false);
|
||||||
addCancelButton(cancelButton, false);
|
addCancelButton(cancelButton);
|
||||||
} else {
|
} else {
|
||||||
Button cancelButton = addButtonAfterGroup(gridPane, ++rowIndex, "Close");
|
Button cancelButton = addButtonAfterGroup(gridPane, ++rowIndex, "Close");
|
||||||
cancelButton.setOnAction(e -> {
|
cancelButton.setOnAction(e -> {
|
||||||
|
@ -229,19 +233,10 @@ public class OfferDetailsPopup extends Popup {
|
||||||
return tuple.second;
|
return tuple.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCancelButton(Button cancelButton, boolean isPlaceOffer) {
|
private void addCancelButton(Button cancelButton) {
|
||||||
cancelButton.setOnAction(e -> {
|
cancelButton.setOnAction(e -> {
|
||||||
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
||||||
hide();
|
hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
CheckBox checkBox = addCheckBox(gridPane, ++rowIndex, "Don't show again", 5);
|
|
||||||
if (isPlaceOffer) {
|
|
||||||
checkBox.setSelected(!preferences.getShowPlaceOfferConfirmation());
|
|
||||||
checkBox.setOnAction(e -> preferences.setShowPlaceOfferConfirmation(!checkBox.isSelected()));
|
|
||||||
} else {
|
|
||||||
checkBox.setSelected(!preferences.getShowTakeOfferConfirmation());
|
|
||||||
checkBox.setOnAction(e -> preferences.setShowTakeOfferConfirmation(!checkBox.isSelected()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class Popup {
|
||||||
private boolean showProgressIndicator;
|
private boolean showProgressIndicator;
|
||||||
private Button actionButton;
|
private Button actionButton;
|
||||||
protected Label headLineLabel;
|
protected Label headLineLabel;
|
||||||
private String dontShowAgainId;
|
protected String dontShowAgainId;
|
||||||
private Preferences preferences;
|
private Preferences preferences;
|
||||||
private ChangeListener<Number> positionListener;
|
private ChangeListener<Number> positionListener;
|
||||||
private Timer centerTime;
|
private Timer centerTime;
|
||||||
|
|
63
gui/src/main/java/io/bitsquare/gui/main/popups/TacPopup.java
Normal file
63
gui/src/main/java/io/bitsquare/gui/main/popups/TacPopup.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package io.bitsquare.gui.main.popups;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.app.BitsquareApp;
|
||||||
|
import io.bitsquare.btc.BitcoinNetwork;
|
||||||
|
import io.bitsquare.common.UserThread;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class TacPopup extends Popup {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TacPopup.class);
|
||||||
|
private Preferences preferences;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TacPopup(Preferences preferences) {
|
||||||
|
this.preferences = preferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showIfNeeded() {
|
||||||
|
if (!preferences.getTacAccepted() && !BitsquareApp.DEV_MODE) {
|
||||||
|
// TODO add link: https://bitsquare.io/arbitration_system.pdf
|
||||||
|
headLine("USER AGREEMENT");
|
||||||
|
String text = "1. This software is experimental and provided \"as is\", without warranty of any kind, " +
|
||||||
|
"express or implied, including but not limited to the warranties of " +
|
||||||
|
"merchantability, fitness for a particular purpose and non-infringement.\n" +
|
||||||
|
"In no event shall the authors or copyright holders be liable for any claim, damages or other " +
|
||||||
|
"liability, whether in an action of contract, tort or otherwise, " +
|
||||||
|
"arising from, out of or in connection with the software or the use or other dealings in the software.\n\n" +
|
||||||
|
"2. The user is responsible to use the software in compliance with local laws.\n\n" +
|
||||||
|
"3. The user confirms that he has read and agreed to the rules defined in our " +
|
||||||
|
"Wiki regrading the dispute process\n" +
|
||||||
|
"(https://github.com/bitsquare/bitsquare/wiki/Arbitration-system).";
|
||||||
|
message(text);
|
||||||
|
actionButtonText("I agree");
|
||||||
|
closeButtonText("I disagree and quit");
|
||||||
|
onAction(() -> {
|
||||||
|
preferences.setTacAccepted(true);
|
||||||
|
if (preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET)
|
||||||
|
UserThread.runAfter(() -> new Popup()
|
||||||
|
.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 " +
|
||||||
|
"when using Mainnet.")
|
||||||
|
.headLine("Important information!")
|
||||||
|
.actionButtonText("I understand and want to use Mainnet")
|
||||||
|
.closeButtonText("Restart and use Testnet")
|
||||||
|
.onClose(() -> {
|
||||||
|
UserThread.execute(() -> preferences.setBitcoinNetwork(BitcoinNetwork.TESTNET));
|
||||||
|
UserThread.runAfter(BitsquareApp.shutDownHandler::run, 300, TimeUnit.MILLISECONDS);
|
||||||
|
})
|
||||||
|
.width(600)
|
||||||
|
.show(), 300, TimeUnit.MILLISECONDS);
|
||||||
|
});
|
||||||
|
onClose(BitsquareApp.shutDownHandler::run);
|
||||||
|
super.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -127,12 +127,8 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||||
selectedSubView.deactivate();
|
selectedSubView.deactivate();
|
||||||
|
|
||||||
if (selectedItem.getTrade() != null) {
|
if (selectedItem.getTrade() != null) {
|
||||||
// If we are the offerer the direction is like expected
|
selectedSubView = model.dataModel.tradeManager.isBuyer(model.dataModel.getOffer()) ?
|
||||||
// If we are the taker the direction is mirrored
|
new BuyerSubView(model) : new SellerSubView(model);
|
||||||
if (model.dataModel.isOfferer())
|
|
||||||
selectedSubView = model.dataModel.isBuyOffer() ? new BuyerSubView(model) : new SellerSubView(model);
|
|
||||||
else
|
|
||||||
selectedSubView = model.dataModel.isBuyOffer() ? new SellerSubView(model) : new BuyerSubView(model);
|
|
||||||
|
|
||||||
selectedSubView.setMinHeight(430);
|
selectedSubView.setMinHeight(430);
|
||||||
VBox.setVgrow(selectedSubView, Priority.ALWAYS);
|
VBox.setVgrow(selectedSubView, Priority.ALWAYS);
|
||||||
|
|
|
@ -23,6 +23,7 @@ import io.bitsquare.gui.util.Layout;
|
||||||
import io.bitsquare.locale.LanguageUtil;
|
import io.bitsquare.locale.LanguageUtil;
|
||||||
import io.bitsquare.locale.TradeCurrency;
|
import io.bitsquare.locale.TradeCurrency;
|
||||||
import io.bitsquare.user.BlockChainExplorer;
|
import io.bitsquare.user.BlockChainExplorer;
|
||||||
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
import javafx.scene.control.ComboBox;
|
import javafx.scene.control.ComboBox;
|
||||||
|
@ -38,28 +39,30 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
|
|
||||||
// not supported yet
|
// not supported yet
|
||||||
//private ComboBox<String> btcDenominationComboBox;
|
//private ComboBox<String> btcDenominationComboBox;
|
||||||
private ComboBox<BlockChainExplorer> blockExplorerComboBox;
|
private ComboBox<BlockChainExplorer> blockChainExplorerComboBox;
|
||||||
private ComboBox<String> languageComboBox;
|
private ComboBox<String> languageComboBox;
|
||||||
private ComboBox<TradeCurrency> tradeCurrencyComboBox;
|
private ComboBox<TradeCurrency> preferredTradeCurrencyComboBox;
|
||||||
|
|
||||||
private CheckBox useAnimationsCheckBox, useEffectsCheckBox, showPlaceOfferConfirmationCheckBox, showTakeOfferConfirmationCheckBox,
|
private CheckBox useAnimationsCheckBox, useEffectsCheckBox, showNotificationsCheckBox, showInstructionsCheckBox,
|
||||||
autoSelectArbitratorsCheckBox;
|
autoSelectArbitratorsCheckBox;
|
||||||
private int gridRow = 0;
|
private int gridRow = 0;
|
||||||
//private InputTextField transactionFeeInputTextField;
|
//private InputTextField transactionFeeInputTextField;
|
||||||
private ChangeListener<Boolean> transactionFeeFocusedListener;
|
private ChangeListener<Boolean> transactionFeeFocusedListener;
|
||||||
|
private Preferences preferences;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PreferencesView(PreferencesViewModel model) {
|
public PreferencesView(PreferencesViewModel model, Preferences preferences) {
|
||||||
super(model);
|
super(model);
|
||||||
|
this.preferences = preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
addTitledGroupBg(root, gridRow, 4, "Preferences");
|
addTitledGroupBg(root, gridRow, 4, "Preferences");
|
||||||
tradeCurrencyComboBox = addLabelComboBox(root, gridRow, "Preferred currency:", Layout.FIRST_ROW_DISTANCE).second;
|
preferredTradeCurrencyComboBox = addLabelComboBox(root, gridRow, "Preferred currency:", Layout.FIRST_ROW_DISTANCE).second;
|
||||||
languageComboBox = addLabelComboBox(root, ++gridRow, "Language:").second;
|
languageComboBox = addLabelComboBox(root, ++gridRow, "Language:").second;
|
||||||
// btcDenominationComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin denomination:").second;
|
// btcDenominationComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin denomination:").second;
|
||||||
blockExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
|
blockChainExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
|
||||||
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators by language:", "").second;
|
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators by language:", "").second;
|
||||||
|
|
||||||
// TODO need a bit extra work to separate trade and non trade tx fees before it can be used
|
// TODO need a bit extra work to separate trade and non trade tx fees before it can be used
|
||||||
|
@ -71,8 +74,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
addTitledGroupBg(root, ++gridRow, 4, "Display options", Layout.GROUP_DISTANCE);
|
addTitledGroupBg(root, ++gridRow, 4, "Display options", Layout.GROUP_DISTANCE);
|
||||||
useAnimationsCheckBox = addLabelCheckBox(root, gridRow, "Use animations:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
useAnimationsCheckBox = addLabelCheckBox(root, gridRow, "Use animations:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||||
useEffectsCheckBox = addLabelCheckBox(root, ++gridRow, "Use effects:", "").second;
|
useEffectsCheckBox = addLabelCheckBox(root, ++gridRow, "Use effects:", "").second;
|
||||||
showPlaceOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at place offer:", "").second;
|
showNotificationsCheckBox = addLabelCheckBox(root, ++gridRow, "Show notifications:", "").second;
|
||||||
showTakeOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at take offer:", "").second;
|
showInstructionsCheckBox = addLabelCheckBox(root, ++gridRow, "Show instruction popups:", "").second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,9 +85,9 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
btcDenominationComboBox.getSelectionModel().select(model.getBtcDenomination());
|
btcDenominationComboBox.getSelectionModel().select(model.getBtcDenomination());
|
||||||
btcDenominationComboBox.setOnAction(e -> model.onSelectBtcDenomination(btcDenominationComboBox.getSelectionModel().getSelectedItem()));*/
|
btcDenominationComboBox.setOnAction(e -> model.onSelectBtcDenomination(btcDenominationComboBox.getSelectionModel().getSelectedItem()));*/
|
||||||
|
|
||||||
tradeCurrencyComboBox.setItems(model.tradeCurrencies);
|
preferredTradeCurrencyComboBox.setItems(model.tradeCurrencies);
|
||||||
tradeCurrencyComboBox.getSelectionModel().select(model.getTradeCurrency());
|
preferredTradeCurrencyComboBox.getSelectionModel().select(preferences.getPreferredTradeCurrency());
|
||||||
tradeCurrencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
preferredTradeCurrencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(TradeCurrency tradeCurrency) {
|
public String toString(TradeCurrency tradeCurrency) {
|
||||||
return tradeCurrency.getNameAndCode();
|
return tradeCurrency.getNameAndCode();
|
||||||
|
@ -95,7 +98,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tradeCurrencyComboBox.setOnAction(e -> model.onSelectTradeCurrency(tradeCurrencyComboBox.getSelectionModel().getSelectedItem()));
|
preferredTradeCurrencyComboBox.setOnAction(e -> preferences.setPreferredTradeCurrency(preferredTradeCurrencyComboBox.getSelectionModel().getSelectedItem()));
|
||||||
|
|
||||||
languageComboBox.setItems(model.languageCodes);
|
languageComboBox.setItems(model.languageCodes);
|
||||||
languageComboBox.getSelectionModel().select(model.getLanguageCode());
|
languageComboBox.getSelectionModel().select(model.getLanguageCode());
|
||||||
|
@ -113,9 +116,9 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
languageComboBox.setOnAction(e -> model.onSelectLanguageCode(languageComboBox.getSelectionModel().getSelectedItem()));
|
languageComboBox.setOnAction(e -> model.onSelectLanguageCode(languageComboBox.getSelectionModel().getSelectedItem()));
|
||||||
|
|
||||||
|
|
||||||
blockExplorerComboBox.setItems(model.blockExplorers);
|
blockChainExplorerComboBox.setItems(model.blockExplorers);
|
||||||
blockExplorerComboBox.getSelectionModel().select(model.getBlockExplorer());
|
blockChainExplorerComboBox.getSelectionModel().select(preferences.getBlockChainExplorer());
|
||||||
blockExplorerComboBox.setConverter(new StringConverter<BlockChainExplorer>() {
|
blockChainExplorerComboBox.setConverter(new StringConverter<BlockChainExplorer>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(BlockChainExplorer blockChainExplorer) {
|
public String toString(BlockChainExplorer blockChainExplorer) {
|
||||||
return blockChainExplorer.name;
|
return blockChainExplorer.name;
|
||||||
|
@ -126,39 +129,39 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
blockExplorerComboBox.setOnAction(e -> model.onSelectBlockExplorer(blockExplorerComboBox.getSelectionModel().getSelectedItem()));
|
blockChainExplorerComboBox.setOnAction(e -> preferences.setBlockChainExplorer(blockChainExplorerComboBox.getSelectionModel().getSelectedItem()));
|
||||||
|
|
||||||
// transactionFeeInputTextField.textProperty().bindBidirectional(model.transactionFeePerByte);
|
// transactionFeeInputTextField.textProperty().bindBidirectional(model.transactionFeePerByte);
|
||||||
// transactionFeeInputTextField.focusedProperty().addListener(transactionFeeFocusedListener);
|
// transactionFeeInputTextField.focusedProperty().addListener(transactionFeeFocusedListener);
|
||||||
|
|
||||||
useAnimationsCheckBox.setSelected(model.getUseAnimations());
|
useAnimationsCheckBox.setSelected(preferences.getUseAnimations());
|
||||||
useAnimationsCheckBox.setOnAction(e -> model.onSelectUseAnimations(useAnimationsCheckBox.isSelected()));
|
useAnimationsCheckBox.setOnAction(e -> preferences.setUseAnimations(useAnimationsCheckBox.isSelected()));
|
||||||
|
|
||||||
useEffectsCheckBox.setSelected(model.getUseEffects());
|
useEffectsCheckBox.setSelected(preferences.getUseEffects());
|
||||||
useEffectsCheckBox.setOnAction(e -> model.onSelectUseEffects(useEffectsCheckBox.isSelected()));
|
useEffectsCheckBox.setOnAction(e -> preferences.setUseEffects(useEffectsCheckBox.isSelected()));
|
||||||
|
|
||||||
showPlaceOfferConfirmationCheckBox.setSelected(model.getShowPlaceOfferConfirmation());
|
showNotificationsCheckBox.setSelected(preferences.getShowNotifications());
|
||||||
showPlaceOfferConfirmationCheckBox.setOnAction(e -> model.onSelectShowPlaceOfferConfirmation(showPlaceOfferConfirmationCheckBox.isSelected()));
|
showNotificationsCheckBox.setOnAction(e -> preferences.setShowNotifications(showNotificationsCheckBox.isSelected()));
|
||||||
|
|
||||||
showTakeOfferConfirmationCheckBox.setSelected(model.getShowTakeOfferConfirmation());
|
showInstructionsCheckBox.setSelected(preferences.getShowInstructions());
|
||||||
showTakeOfferConfirmationCheckBox.setOnAction(e -> model.onSelectShowTakeOfferConfirmation(showTakeOfferConfirmationCheckBox.isSelected()));
|
showInstructionsCheckBox.setOnAction(e -> preferences.setShowInstructions(showInstructionsCheckBox.isSelected()));
|
||||||
|
|
||||||
autoSelectArbitratorsCheckBox.setSelected(model.getAutoSelectArbitrators());
|
autoSelectArbitratorsCheckBox.setSelected(preferences.getAutoSelectArbitrators());
|
||||||
autoSelectArbitratorsCheckBox.setOnAction(e -> model.onSelectAutoSelectArbitratorsCheckBox(autoSelectArbitratorsCheckBox.isSelected()));
|
autoSelectArbitratorsCheckBox.setOnAction(e -> preferences.setAutoSelectArbitrators(autoSelectArbitratorsCheckBox.isSelected()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void deactivate() {
|
protected void deactivate() {
|
||||||
//btcDenominationComboBox.setOnAction(null);
|
//btcDenominationComboBox.setOnAction(null);
|
||||||
languageComboBox.setOnAction(null);
|
languageComboBox.setOnAction(null);
|
||||||
tradeCurrencyComboBox.setOnAction(null);
|
preferredTradeCurrencyComboBox.setOnAction(null);
|
||||||
blockExplorerComboBox.setOnAction(null);
|
blockChainExplorerComboBox.setOnAction(null);
|
||||||
|
showNotificationsCheckBox.setOnAction(null);
|
||||||
|
showInstructionsCheckBox.setOnAction(null);
|
||||||
// transactionFeeInputTextField.textProperty().unbind();
|
// transactionFeeInputTextField.textProperty().unbind();
|
||||||
/// transactionFeeInputTextField.focusedProperty().removeListener(transactionFeeFocusedListener);
|
/// transactionFeeInputTextField.focusedProperty().removeListener(transactionFeeFocusedListener);
|
||||||
useAnimationsCheckBox.setOnAction(null);
|
useAnimationsCheckBox.setOnAction(null);
|
||||||
useEffectsCheckBox.setOnAction(null);
|
useEffectsCheckBox.setOnAction(null);
|
||||||
showPlaceOfferConfirmationCheckBox.setOnAction(null);
|
|
||||||
showTakeOfferConfirmationCheckBox.setOnAction(null);
|
|
||||||
autoSelectArbitratorsCheckBox.setOnAction(null);
|
autoSelectArbitratorsCheckBox.setOnAction(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,42 +65,11 @@ class PreferencesViewModel extends ActivatableViewModel {
|
||||||
protected void deactivate() {
|
protected void deactivate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// UI actions
|
// UI actions
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onSelectBtcDenomination(String selectedItem) {
|
|
||||||
preferences.setBtcDenomination(selectedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectUseEffects(boolean selected) {
|
|
||||||
preferences.setUseEffects(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectUseAnimations(boolean selected) {
|
|
||||||
preferences.setUseAnimations(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectShowPlaceOfferConfirmation(boolean selected) {
|
|
||||||
preferences.setShowPlaceOfferConfirmation(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectShowTakeOfferConfirmation(boolean selected) {
|
|
||||||
preferences.setShowTakeOfferConfirmation(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectAutoSelectArbitratorsCheckBox(boolean selected) {
|
|
||||||
preferences.setAutoSelectArbitrators(selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectBlockExplorer(BlockChainExplorer selectedItem) {
|
|
||||||
preferences.setBlockChainExplorer(selectedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectTradeCurrency(TradeCurrency selectedItem) {
|
|
||||||
preferences.setPreferredTradeCurrency(selectedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSelectLanguageCode(String code) {
|
public void onSelectLanguageCode(String code) {
|
||||||
preferences.setPreferredLocale(new Locale(code, preferences.getPreferredLocale().getCountry()));
|
preferences.setPreferredLocale(new Locale(code, preferences.getPreferredLocale().getCountry()));
|
||||||
}
|
}
|
||||||
|
@ -124,40 +93,8 @@ class PreferencesViewModel extends ActivatableViewModel {
|
||||||
// Getters
|
// Getters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public String getBtcDenomination() {
|
|
||||||
return preferences.getBtcDenomination();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getUseAnimations() {
|
|
||||||
return preferences.getUseAnimations();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getUseEffects() {
|
|
||||||
return preferences.getUseEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getShowPlaceOfferConfirmation() {
|
|
||||||
return preferences.getShowPlaceOfferConfirmation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getShowTakeOfferConfirmation() {
|
|
||||||
return preferences.getShowTakeOfferConfirmation();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getAutoSelectArbitrators() {
|
|
||||||
return preferences.getAutoSelectArbitrators();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockChainExplorer getBlockExplorer() {
|
|
||||||
return preferences.getBlockChainExplorer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguageCode() {
|
public String getLanguageCode() {
|
||||||
return preferences.getPreferredLocale().getLanguage();
|
return preferences.getPreferredLocale().getLanguage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TradeCurrency getTradeCurrency() {
|
|
||||||
return preferences.getPreferredTradeCurrency();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue