From a8189d7bb3689bba06bee90f0b866568f0d18d2d Mon Sep 17 00:00:00 2001 From: Christoph Atteneder Date: Wed, 6 Apr 2022 18:00:59 +0200 Subject: [PATCH] Adapt create offer process to new navigation structure --- .../resources/i18n/displayStrings.properties | 9 +- .../{Closable.java => ClosableView.java} | 2 +- ...> InitializableViewWithTakeOfferData.java} | 2 +- .../bisq/desktop/main/offer/OfferView.java | 204 ++++++++---------- .../desktop/main/offer/SelectableView.java | 22 ++ .../offer/bisq_v1/MutableOfferDataModel.java | 21 +- .../main/offer/bisq_v1/MutableOfferView.java | 64 +++++- .../offer/bisq_v1/MutableOfferViewModel.java | 4 + .../main/offer/bisq_v1/OfferViewUtil.java | 11 +- .../bisq_v1/createoffer/CreateOfferView.java | 41 ++++ .../bisq_v1/takeoffer/TakeOfferView.java | 9 +- .../main/offer/bsq_swap/BsqSwapOfferView.java | 4 +- .../create_offer/BsqSwapCreateOfferView.java | 9 +- .../take_offer/BsqSwapTakeOfferView.java | 5 +- .../offer/offerbook/BsqOfferBookView.java | 9 +- .../offerbook/BsqOfferBookViewModel.java | 5 + .../offer/offerbook/BtcOfferBookView.java | 9 +- .../offerbook/BtcOfferBookViewModel.java | 6 + .../main/offer/offerbook/OfferBookView.java | 28 ++- .../offer/offerbook/OfferBookViewModel.java | 10 +- .../offer/offerbook/OtherOfferBookView.java | 9 +- .../offerbook/OtherOfferBookViewModel.java | 9 + .../offerbook/TopAltcoinOfferBookView.java | 9 +- .../TopAltcoinOfferBookViewModel.java | 5 + .../duplicateoffer/DuplicateOfferView.java | 18 +- .../portfolio/editoffer/EditOfferView.java | 8 + .../portfolio/presentation/PortfolioUtil.java | 8 +- 27 files changed, 362 insertions(+), 178 deletions(-) rename desktop/src/main/java/bisq/desktop/main/offer/{Closable.java => ClosableView.java} (96%) rename desktop/src/main/java/bisq/desktop/main/offer/{InitializableWithData.java => InitializableViewWithTakeOfferData.java} (93%) create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/SelectableView.java diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index bca58c669b5..1e556868a09 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -100,11 +100,10 @@ shared.dontRemoveOffer=Don't remove offer shared.editOffer=Edit offer shared.duplicateOffer=Duplicate offer shared.openLargeQRWindow=Open large QR code window -shared.tradingAccount=Trading account +shared.chooseTradingAccount=Choose trading account shared.faq=Visit FAQ page shared.yesCancel=Yes, cancel shared.nextStep=Next step -shared.selectTradingAccount=Select trading account shared.fundFromSavingsWalletButton=Transfer funds from Bisq wallet shared.fundFromExternalWalletButton=Open your external wallet for funding shared.openDefaultWalletFailed=Failed to open a Bitcoin wallet application. Are you sure you have one installed? @@ -198,6 +197,7 @@ shared.iConfirm=I confirm shared.openURL=Open {0} shared.fiat=Fiat shared.crypto=Crypto +shared.otherAssets=other assets shared.all=All shared.edit=Edit shared.advancedOptions=Advanced options @@ -379,7 +379,7 @@ offerbook.volume={0} (min - max) offerbook.deposit=Deposit BTC (%) offerbook.deposit.help=Deposit paid by each trader to guarantee the trade. Will be returned when the trade is completed. -offerbook.createNewOffer=Create new offer +offerbook.createNewOffer=Create new offer to {0} {1} offerbook.createOfferDisabled.tooltip=You can only create one offer at a time offerbook.takeOfferButton.tooltip=Take offer for {0} @@ -393,7 +393,7 @@ offerbook.withdrawFundsHint=Offer has been removed. Funds are not reserved for t You can send Available funds to an external wallet at the {0} screen. offerbook.warning.noTradingAccountForCurrency.headline=No payment account for selected currency -offerbook.warning.noTradingAccountForCurrency.msg=You don't have a payment account set up for the selected currency.\n\nWould you like to create an offer for another currency instead? +offerbook.warning.noTradingAccountForCurrency.msg=You don't have a payment account set up for the selected currency. offerbook.warning.noMatchingAccount.headline=No matching payment account. offerbook.warning.noMatchingAccount.msg=This offer uses a payment method you haven't set up yet. \n\nWould you like to set up a new payment account now? offerbook.warning.noMatchingBsqAccount.msg=This offer uses BSQ as a payment method you haven't set up yet. \n\nWould you like to automatically create an account now? @@ -490,6 +490,7 @@ createOffer.buyBsq.popupMessage=Trading fees are paid to fund the Bisq DAO. Fees # new entries createOffer.placeOfferButton=Review: Place offer to {0} bitcoin +createOffer.placeOfferButtonAltcoin=Review: Place offer to {0} {1} createOffer.createOfferFundWalletInfo.headline=Fund your offer # suppress inspection "TrailingSpacesInProperty" createOffer.createOfferFundWalletInfo.tradeAmount=- Trade amount: {0} \n diff --git a/desktop/src/main/java/bisq/desktop/main/offer/Closable.java b/desktop/src/main/java/bisq/desktop/main/offer/ClosableView.java similarity index 96% rename from desktop/src/main/java/bisq/desktop/main/offer/Closable.java rename to desktop/src/main/java/bisq/desktop/main/offer/ClosableView.java index 57c9a89a089..e1499e5fd4f 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/Closable.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/ClosableView.java @@ -17,6 +17,6 @@ package bisq.desktop.main.offer; -public interface Closable { +public interface ClosableView { public void setCloseHandler(OfferView.CloseHandler closeHandler); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/InitializableWithData.java b/desktop/src/main/java/bisq/desktop/main/offer/InitializableViewWithTakeOfferData.java similarity index 93% rename from desktop/src/main/java/bisq/desktop/main/offer/InitializableWithData.java rename to desktop/src/main/java/bisq/desktop/main/offer/InitializableViewWithTakeOfferData.java index 2a6cdeec773..4c4e2a2cf9a 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/InitializableWithData.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/InitializableViewWithTakeOfferData.java @@ -19,7 +19,7 @@ import bisq.core.offer.Offer; -public interface InitializableWithData { +public interface InitializableViewWithTakeOfferData { public void initWithData(Offer offer); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java index a85cfbca06c..46e2f912900 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java @@ -31,13 +31,13 @@ import bisq.desktop.main.offer.offerbook.BtcOfferBookView; import bisq.desktop.main.offer.offerbook.OfferBookView; import bisq.desktop.main.offer.offerbook.OtherOfferBookView; +import bisq.desktop.main.offer.offerbook.OtherOfferBookViewModel; import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookView; import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookViewModel; import bisq.desktop.util.GUIUtil; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.GlobalSettings; -import bisq.core.locale.Res; import bisq.core.locale.TradeCurrency; import bisq.core.offer.Offer; import bisq.core.offer.OfferDirection; @@ -50,25 +50,20 @@ import javafx.scene.control.Tab; import javafx.scene.control.TabPane; -import javafx.scene.layout.AnchorPane; import javafx.beans.value.ChangeListener; -import javafx.collections.ListChangeListener; - -import java.util.List; import java.util.Optional; +import org.jetbrains.annotations.NotNull; + import javax.annotation.Nullable; public abstract class OfferView extends ActivatableView { private OfferBookView btcOfferBookView, bsqOfferBookView, topAltcoinOfferBookView, otherOfferBookView; - private CreateOfferView createOfferView; - private BsqSwapCreateOfferView bsqSwapCreateOfferView; - private AnchorPane createOfferPane; - private Tab createOfferTab, btcOfferBookTab, bsqOfferBookTab, topAltcoinOfferBookTab, otherOfferBookTab; + private Tab btcOfferBookTab, bsqOfferBookTab, topAltcoinOfferBookTab, otherOfferBookTab; private final ViewLoader viewLoader; private final Navigation navigation; @@ -79,15 +74,10 @@ public abstract class OfferView extends ActivatableView { private Offer offer; private TradeCurrency tradeCurrency; - private boolean createOfferViewOpen; private Navigation.Listener navigationListener; private ChangeListener tabChangeListener; - private ListChangeListener tabListChangeListener; private OfferView.OfferActionHandler offerActionHandler; - private Class currentViewClass; - - protected OfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences, @@ -113,11 +103,7 @@ protected void initialize() { }; tabChangeListener = (observableValue, oldValue, newValue) -> { if (newValue != null) { - if (newValue.equals(createOfferTab) && createOfferView != null) { - createOfferView.onTabSelected(true); - } else if (newValue.equals(createOfferTab) && bsqSwapCreateOfferView != null) { - bsqSwapCreateOfferView.onTabSelected(true); - } else if (newValue.equals(btcOfferBookTab)) { + if (newValue.equals(btcOfferBookTab)) { if (btcOfferBookView != null) { btcOfferBookView.onTabSelected(true); } else { @@ -144,11 +130,7 @@ protected void initialize() { } } if (oldValue != null) { - if (oldValue.equals(createOfferTab) && createOfferView != null) { - createOfferView.onTabSelected(false); - } else if (oldValue.equals(createOfferTab) && bsqSwapCreateOfferView != null) { - bsqSwapCreateOfferView.onTabSelected(false); - } else if (oldValue.equals(btcOfferBookTab) && btcOfferBookView != null) { + if (oldValue.equals(btcOfferBookTab) && btcOfferBookView != null) { btcOfferBookView.onTabSelected(false); } else if (oldValue.equals(bsqOfferBookTab) && bsqOfferBookView != null) { bsqOfferBookView.onTabSelected(false); @@ -159,32 +141,20 @@ protected void initialize() { } } }; - tabListChangeListener = change -> { - change.next(); - List removedTabs = change.getRemoved(); - if (removedTabs.size() == 1) { - if (removedTabs.get(0).getContent().equals(createOfferPane)) - onCreateOfferViewRemoved(); - } - }; offerActionHandler = new OfferActionHandler() { @Override public void onCreateOffer(TradeCurrency tradeCurrency, PaymentMethod paymentMethod) { - if (createOfferViewOpen) { - root.getTabs().remove(createOfferTab); - } if (canCreateOrTakeOffer(tradeCurrency)) { - openCreateOffer(tradeCurrency, paymentMethod); + showCreateOffer(tradeCurrency, paymentMethod); } } @Override public void onTakeOffer(Offer offer) { - // can we have multiple take offer views open? Optional optionalTradeCurrency = CurrencyUtil.getTradeCurrency(offer.getCurrencyCode()); if (optionalTradeCurrency.isPresent() && canCreateOrTakeOffer(optionalTradeCurrency.get())) { - openTakeOffer(offer); + showTakeOffer(offer); } } }; @@ -198,7 +168,6 @@ protected void activate() { tradeCurrency = tradeCurrencyOptional.orElseGet(GlobalSettings::getDefaultTradeCurrency); root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); - root.getTabs().addListener(tabListChangeListener); navigation.addListener(navigationListener); if (btcOfferBookView == null) { navigation.navigateTo(MainView.class, this.getClass(), BtcOfferBookView.class); @@ -209,17 +178,6 @@ protected void activate() { protected void deactivate() { navigation.removeListener(navigationListener); root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener); - root.getTabs().removeListener(tabListChangeListener); - } - - private String getCreateOfferTabName(Class viewClass) { - return viewClass == BsqSwapCreateOfferView.class ? - Res.get("offerbook.bsqSwap.createOffer").toUpperCase() : - Res.get("offerbook.createOffer").toUpperCase(); - } - - private String getTakeOfferTabName() { - return Res.get("offerbook.takeOffer").toUpperCase(); } private void loadView(Class viewClass, @@ -227,41 +185,57 @@ private void loadView(Class viewClass, @Nullable Object data) { TabPane tabPane = root; tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); - currentViewClass = viewClass; - View view; if (OfferBookView.class.isAssignableFrom(viewClass)) { if (viewClass == BtcOfferBookView.class && btcOfferBookTab != null && btcOfferBookView != null) { if (childViewClass == null) { btcOfferBookTab.setContent(btcOfferBookView.getRoot()); - } else { + } else if (childViewClass == TakeOfferView.class) { loadTakeViewClass(viewClass, childViewClass, btcOfferBookTab); + } else { + loadCreateViewClass(btcOfferBookView, viewClass, childViewClass, btcOfferBookTab, (PaymentMethod) data, null); } tabPane.getSelectionModel().select(btcOfferBookTab); } else if (viewClass == BsqOfferBookView.class && bsqOfferBookTab != null && bsqOfferBookView != null) { if (childViewClass == null) { bsqOfferBookTab.setContent(bsqOfferBookView.getRoot()); - } else { + } else if (childViewClass == TakeOfferView.class) { loadTakeViewClass(viewClass, childViewClass, bsqOfferBookTab); + } else if (data instanceof BsqSwapOfferPayload) { + loadCreateViewClass(bsqOfferBookView, viewClass, childViewClass, bsqOfferBookTab, PaymentMethod.BSQ_SWAP, (BsqSwapOfferPayload) data); + } else { + loadCreateViewClass(bsqOfferBookView, viewClass, childViewClass, bsqOfferBookTab, (PaymentMethod) data, null); } tabPane.getSelectionModel().select(bsqOfferBookTab); } else if (viewClass == TopAltcoinOfferBookView.class && topAltcoinOfferBookTab != null && topAltcoinOfferBookView != null) { if (childViewClass == null) { topAltcoinOfferBookTab.setContent(topAltcoinOfferBookView.getRoot()); - } else { + } else if (childViewClass == TakeOfferView.class) { loadTakeViewClass(viewClass, childViewClass, topAltcoinOfferBookTab); + } else { + loadCreateViewClass(topAltcoinOfferBookView, viewClass, childViewClass, topAltcoinOfferBookTab, (PaymentMethod) data, null); } tabPane.getSelectionModel().select(topAltcoinOfferBookTab); } else if (viewClass == OtherOfferBookView.class && otherOfferBookTab != null && otherOfferBookView != null) { if (childViewClass == null) { otherOfferBookTab.setContent(otherOfferBookView.getRoot()); - } else { + } else if (childViewClass == TakeOfferView.class) { loadTakeViewClass(viewClass, childViewClass, otherOfferBookTab); + } else { + //add sanity check in case of app restart + if (CurrencyUtil.isFiatCurrency(tradeCurrency.getCode())) { + Optional tradeCurrencyOptional = (this.direction == OfferDirection.SELL) ? + CurrencyUtil.getTradeCurrency(preferences.getSellScreenCryptoCurrencyCode()) : + CurrencyUtil.getTradeCurrency(preferences.getBuyScreenCryptoCurrencyCode()); + tradeCurrency = tradeCurrencyOptional.isEmpty() ? OtherOfferBookViewModel.DEFAULT_ALTCOIN : tradeCurrencyOptional.get(); + } + loadCreateViewClass(otherOfferBookView, viewClass, childViewClass, otherOfferBookTab, (PaymentMethod) data, null); } - tabPane.getSelectionModel().select(topAltcoinOfferBookTab); + tabPane.getSelectionModel().select(otherOfferBookTab); } else { if (btcOfferBookTab == null) { + //TODO: use naming from currencies or from translations btcOfferBookTab = new Tab("BITCOIN"); btcOfferBookTab.setClosable(false); bsqOfferBookTab = new Tab("BSQ"); @@ -303,37 +277,41 @@ private void loadView(Class viewClass, otherOfferBookView.onTabSelected(true); } } - } else if (viewClass == CreateOfferView.class && createOfferView == null) { - view = viewLoader.load(viewClass); - // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times - // in different graphs - createOfferView = (CreateOfferView) view; - createOfferView.initWithData(direction, tradeCurrency, offerActionHandler); - createOfferPane = createOfferView.getRoot(); - createOfferTab = new Tab(getCreateOfferTabName(viewClass)); - createOfferTab.setClosable(true); - // close handler from close on create offer action - createOfferView.setCloseHandler(() -> tabPane.getTabs().remove(createOfferTab)); - createOfferTab.setContent(createOfferPane); - tabPane.getTabs().add(createOfferTab); - tabPane.getSelectionModel().select(createOfferTab); - createOfferViewOpen = true; - } else if (viewClass == BsqSwapCreateOfferView.class && bsqSwapCreateOfferView == null) { - view = viewLoader.load(viewClass); - bsqSwapCreateOfferView = (BsqSwapCreateOfferView) view; - bsqSwapCreateOfferView.initWithData(direction, offerActionHandler, (BsqSwapOfferPayload) data); - createOfferPane = bsqSwapCreateOfferView.getRoot(); - createOfferTab = new Tab(getCreateOfferTabName(viewClass)); - createOfferTab.setClosable(true); - // close handler from close on create offer action - bsqSwapCreateOfferView.setCloseHandler(() -> tabPane.getTabs().remove(createOfferTab)); - createOfferTab.setContent(createOfferPane); - tabPane.getTabs().add(createOfferTab); - tabPane.getSelectionModel().select(createOfferTab); - createOfferViewOpen = true; } } + private void loadCreateViewClass(OfferBookView offerBookView, + Class viewClass, + Class childViewClass, + Tab marketOfferBookTab, + @Nullable PaymentMethod paymentMethod, + @Nullable BsqSwapOfferPayload payload) { + if (tradeCurrency == null) { + return; + } + + View view = viewLoader.load(paymentMethod != null && paymentMethod.isBsqSwap() ? BsqSwapCreateOfferView.class : childViewClass); + // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times + // in different graphs + if (paymentMethod != null && paymentMethod.isBsqSwap()) { + ((BsqSwapCreateOfferView) view).initWithData(direction, offerActionHandler, payload); + } else { + ((CreateOfferView) view).initWithData(direction, tradeCurrency, offerActionHandler); + } + + ((SelectableView) view).onTabSelected(true); + + ((ClosableView) view).setCloseHandler(() -> { + offerBookView.enableCreateOfferButton(); + ((SelectableView) view).onTabSelected(false); + navigation.navigateTo(MainView.class, this.getClass(), viewClass); + }); + + + // close handler from close on create offer action + marketOfferBookTab.setContent(view.getRoot()); + } + private void loadTakeViewClass(Class viewClass, Class childViewClass, Tab marketOfferBookTab) { @@ -342,14 +320,15 @@ private void loadTakeViewClass(Class viewClass, return; } - View view; - view = viewLoader.load(offer.isBsqSwapOffer() ? BsqSwapTakeOfferView.class : childViewClass); + View view = viewLoader.load(offer.isBsqSwapOffer() ? BsqSwapTakeOfferView.class : childViewClass); // CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times // in different graphs + ((InitializableViewWithTakeOfferData) view).initWithData(offer); + ((SelectableView) view).onTabSelected(true); - ((InitializableWithData) view).initWithData(offer); // close handler from close on take offer action - ((Closable) view).setCloseHandler(() -> { + ((ClosableView) view).setCloseHandler(() -> { + ((SelectableView) view).onTabSelected(false); navigation.navigateTo(MainView.class, this.getClass(), viewClass); }); marketOfferBookTab.setContent(view.getRoot()); @@ -360,44 +339,33 @@ protected boolean canCreateOrTakeOffer(TradeCurrency tradeCurrency) { GUIUtil.canCreateOrTakeOfferOrShowPopup(user, navigation, tradeCurrency); } - private void openTakeOffer(Offer offer) { + private void showTakeOffer(Offer offer) { this.offer = offer; - Class> offerBookViewClass; - if (CurrencyUtil.isFiatCurrency(offer.getCurrencyCode())) { - offerBookViewClass = BtcOfferBookView.class; - } else if (offer.getCurrencyCode().equals(BsqOfferBookViewModel.BSQ.getCode())) { - offerBookViewClass = BsqOfferBookView.class; - } else if (offer.getCurrencyCode().equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode())) { - offerBookViewClass = TopAltcoinOfferBookView.class; - } else { - offerBookViewClass = OtherOfferBookView.class; - } + Class> offerBookViewClass = getOfferBookViewClassFor(offer.getCurrencyCode()); navigation.navigateTo(MainView.class, this.getClass(), offerBookViewClass, TakeOfferView.class); } - private void openCreateOffer(TradeCurrency tradeCurrency, PaymentMethod paymentMethod) { - createOfferViewOpen = true; + private void showCreateOffer(TradeCurrency tradeCurrency, PaymentMethod paymentMethod) { this.tradeCurrency = tradeCurrency; - if (tradeCurrency.getCode().equals("BSQ") && paymentMethod.isBsqSwap()) { - navigation.navigateTo(MainView.class, this.getClass(), BsqSwapCreateOfferView.class); - } else { - navigation.navigateTo(MainView.class, this.getClass(), CreateOfferView.class); - } + + Class> offerBookViewClass = getOfferBookViewClassFor(tradeCurrency.getCode()); + navigation.navigateToWithData(paymentMethod, MainView.class, this.getClass(), offerBookViewClass, CreateOfferView.class); } - private void onCreateOfferViewRemoved() { - createOfferViewOpen = false; - if (createOfferView != null) { - createOfferView.onClose(); - createOfferView = null; - } - if (bsqSwapCreateOfferView != null) { - bsqSwapCreateOfferView = null; + @NotNull + private Class> getOfferBookViewClassFor(String currencyCode) { + Class> offerBookViewClass; + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + offerBookViewClass = BtcOfferBookView.class; + } else if (currencyCode.equals(BsqOfferBookViewModel.BSQ.getCode())) { + offerBookViewClass = BsqOfferBookView.class; + } else if (currencyCode.equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode())) { + offerBookViewClass = TopAltcoinOfferBookView.class; + } else { + offerBookViewClass = OtherOfferBookView.class; } - btcOfferBookView.enableCreateOfferButton(); - //TODO: go to last selected tab - navigation.navigateTo(MainView.class, this.getClass(), BtcOfferBookView.class); + return offerBookViewClass; } public interface OfferActionHandler { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/SelectableView.java b/desktop/src/main/java/bisq/desktop/main/offer/SelectableView.java new file mode 100644 index 00000000000..7d7dfb2a6ff --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/SelectableView.java @@ -0,0 +1,22 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.desktop.main.offer; + +public interface SelectableView { + public void onTabSelected(boolean isSelected); +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferDataModel.java index 2389ebfb9eb..83477489fa4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferDataModel.java @@ -18,6 +18,8 @@ package bisq.desktop.main.offer.bisq_v1; import bisq.desktop.Navigation; +import bisq.desktop.main.offer.offerbook.BsqOfferBookViewModel; +import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookViewModel; import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; @@ -81,6 +83,7 @@ import java.util.Comparator; import java.util.Date; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; @@ -88,6 +91,8 @@ import lombok.Getter; +import org.jetbrains.annotations.NotNull; + import javax.annotation.Nullable; import static bisq.core.payment.payload.PaymentMethod.HAL_CASH_ID; @@ -247,7 +252,7 @@ public boolean initWithData(OfferDirection direction, TradeCurrency tradeCurrenc if (account != null) { this.paymentAccount = account; } else { - Optional paymentAccountOptional = paymentAccounts.stream().findAny(); + Optional paymentAccountOptional = getAnyPaymentAccount(); if (paymentAccountOptional.isPresent()) { this.paymentAccount = paymentAccountOptional.get(); @@ -277,6 +282,18 @@ public boolean initWithData(OfferDirection direction, TradeCurrency tradeCurrenc return true; } + @NotNull + private Optional getAnyPaymentAccount() { + if (CurrencyUtil.isFiatCurrency(tradeCurrency.getCode())) { + return paymentAccounts.stream().filter(paymentAccount1 -> !paymentAccount1.getPaymentMethod().isAltcoin()).findAny(); + } else { + return paymentAccounts.stream().filter(paymentAccount1 -> paymentAccount1.getPaymentMethod().isAltcoin() && + paymentAccount1.getTradeCurrency().isPresent() && + !Objects.equals(paymentAccount1.getTradeCurrency().get().getCode(), BsqOfferBookViewModel.BSQ.getCode()) && + !Objects.equals(paymentAccount1.getTradeCurrency().get().getCode(), TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode())).findAny(); + } + } + protected PaymentAccount getPreselectedPaymentAccount() { return preferences.getSelectedPaymentAccountForCreateOffer(); } @@ -405,7 +422,7 @@ void onCurrencySelected(TradeCurrency tradeCurrency) { Optional tradeCurrencyOptional = preferences.getTradeCurrenciesAsObservable() .stream().filter(e -> e.getCode().equals(code)).findAny(); - if (!tradeCurrencyOptional.isPresent()) { + if (tradeCurrencyOptional.isEmpty()) { if (CurrencyUtil.isCryptoCurrency(code)) { CurrencyUtil.getCryptoCurrency(code).ifPresent(preferences::addCryptoCurrency); } else { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java index e8f9c89842c..1a500404248 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java @@ -35,7 +35,9 @@ import bisq.desktop.main.dao.DaoView; import bisq.desktop.main.dao.wallet.BsqWalletView; import bisq.desktop.main.dao.wallet.receive.BsqReceiveView; +import bisq.desktop.main.offer.ClosableView; import bisq.desktop.main.offer.OfferView; +import bisq.desktop.main.offer.SelectableView; import bisq.desktop.main.overlays.notifications.Notification; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; @@ -104,6 +106,7 @@ import javafx.event.EventHandler; import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.util.StringConverter; @@ -125,7 +128,7 @@ import static bisq.desktop.util.FormBuilder.*; import static javafx.beans.binding.Bindings.createStringBinding; -public abstract class MutableOfferView> extends ActivatableViewAndModel { +public abstract class MutableOfferView> extends ActivatableViewAndModel implements ClosableView, SelectableView { protected final Navigation navigation; private final Preferences preferences; private final OfferDetailsWindow offerDetailsWindow; @@ -137,7 +140,7 @@ public abstract class MutableOfferView> exten private TitledGroupBg payFundsTitledGroupBg, setDepositTitledGroupBg, paymentTitledGroupBg; protected TitledGroupBg amountTitledGroupBg; private BusyAnimation waitingForFundsSpinner; - private AutoTooltipButton nextButton, cancelButton1, cancelButton2, placeOfferButton; + private AutoTooltipButton nextButton, cancelButton1, cancelButton2, placeOfferButton, fundFromSavingsWalletButton; private Button priceTypeToggleButton; private InputTextField fixedPriceTextField, marketBasedPriceTextField, triggerPriceInputTextField; protected InputTextField amountTextField, minAmountTextField, volumeTextField, buyerSecurityDepositInputTextField; @@ -217,7 +220,7 @@ protected void initialize() { balanceTextField.setFormatter(model.getBtcFormatter()); paymentAccountsComboBox.setConverter(GUIUtil.getPaymentAccountsComboBoxStringConverter()); - paymentAccountsComboBox.setButtonCell(GUIUtil.getComboBoxButtonCell(Res.get("shared.selectTradingAccount"), + paymentAccountsComboBox.setButtonCell(GUIUtil.getComboBoxButtonCell(Res.get("shared.chooseTradingAccount"), paymentAccountsComboBox, false)); paymentAccountsComboBox.setCellFactory(model.getPaymentAccountListCellFactory(paymentAccountsComboBox)); @@ -252,9 +255,9 @@ protected void doActivate() { addressTextField.setAddress(model.getAddressAsString()); addressTextField.setPaymentLabel(model.getPaymentLabel()); - paymentAccountsComboBox.setItems(model.getDataModel().getPaymentAccounts()); - paymentAccountsComboBox.getSelectionModel().select(model.getPaymentAccount()); currencyComboBox.getSelectionModel().select(model.getTradeCurrency()); + paymentAccountsComboBox.setItems(getPaymentAccounts()); + paymentAccountsComboBox.getSelectionModel().select(model.getPaymentAccount()); onPaymentAccountsComboBoxSelected(); @@ -327,14 +330,30 @@ public void initWithData(OfferDirection direction, TradeCurrency tradeCurrency, }).show(); } - if (direction == OfferDirection.BUY) { + String placeOfferButtonLabel; + + if (OfferViewUtil.isShownAsBuyOffer(direction, tradeCurrency)) { placeOfferButton.setId("buy-button-big"); - placeOfferButton.updateText(Res.get("createOffer.placeOfferButton", Res.get("shared.buy"))); + if (CurrencyUtil.isFiatCurrency(tradeCurrency.getCode())) { + placeOfferButtonLabel = Res.get("createOffer.placeOfferButton", Res.get("shared.buy")); + } else { + placeOfferButtonLabel = Res.get("createOffer.placeOfferButtonAltcoin", Res.get("shared.buy"), tradeCurrency.getName()); + } + placeOfferButton.updateText(placeOfferButtonLabel); + nextButton.setId("buy-button"); + fundFromSavingsWalletButton.setId("buy-button"); } else { placeOfferButton.setId("sell-button-big"); - placeOfferButton.updateText(Res.get("createOffer.placeOfferButton", Res.get("shared.sell"))); + if (CurrencyUtil.isFiatCurrency(tradeCurrency.getCode())) { + placeOfferButtonLabel = Res.get("createOffer.placeOfferButton", Res.get("shared.sell")); + } else { + placeOfferButtonLabel = Res.get("createOffer.placeOfferButtonAltcoin", Res.get("shared.sell"), tradeCurrency.getName()); + } + nextButton.setId("sell-button"); + fundFromSavingsWalletButton.setId("sell-button"); } + updatePriceToggle(); if (!model.getDataModel().isMakerFeeValid() && model.getDataModel().getMakerFee() != null) @@ -771,6 +790,15 @@ private void createListeners() { marketBasedPriceTextField.clear(); volumeTextField.clear(); triggerPriceInputTextField.clear(); + if (!CurrencyUtil.isFiatCurrency(newValue)) { + if (model.isShownAsBuyOffer()) { + placeOfferButton.updateText(Res.get("createOffer.placeOfferButtonAltcoin", Res.get("shared.buy"), + model.getTradeCurrency().getName())); + } else { + placeOfferButton.updateText(Res.get("createOffer.placeOfferButtonAltcoin", Res.get("shared.sell"), + model.getTradeCurrency().getName())); + } + } }; placeOfferCompletedListener = (o, oldValue, newValue) -> { @@ -1031,7 +1059,7 @@ private void addGridPane() { } private void addPaymentGroup() { - paymentTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, "Buy BTC with Fiat"); + paymentTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, Res.get("shared.chooseTradingAccount")); GridPane.setColumnSpan(paymentTitledGroupBg, 2); HBox paymentGroupBox = new HBox(); @@ -1040,7 +1068,7 @@ private void addPaymentGroup() { paymentGroupBox.setPadding(new Insets(10, 0, 18, 0)); final Tuple3> tradingAccountBoxTuple = addTopLabelComboBox( - Res.get("shared.tradingAccount"), Res.get("shared.selectTradingAccount")); + Res.get("shared.chooseTradingAccount"), Res.get("shared.chooseTradingAccount")); final Tuple3> currencyBoxTuple = addTopLabelComboBox( Res.get("shared.currency"), Res.get("list.currency.select")); @@ -1234,7 +1262,7 @@ private void addFundingGroup() { fundingHBox.setVisible(false); fundingHBox.setManaged(false); fundingHBox.setSpacing(10); - Button fundFromSavingsWalletButton = new AutoTooltipButton(Res.get("shared.fundFromSavingsWalletButton")); + fundFromSavingsWalletButton = new AutoTooltipButton(Res.get("shared.fundFromSavingsWalletButton")); fundFromSavingsWalletButton.setDefaultButton(true); fundFromSavingsWalletButton.getStyleClass().add("action-button"); fundFromSavingsWalletButton.setOnAction(e -> model.fundFromSavingsWallet()); @@ -1553,4 +1581,18 @@ private GridPane createInfoPopover() { model.getTotalToPayInfo()); return infoGridPane; } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Helpers + /////////////////////////////////////////////////////////////////////////////////////////// + + private ObservableList getPaymentAccounts() { + return filterPaymentAccounts(model.getDataModel().getPaymentAccounts()); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Abstract Methods + /////////////////////////////////////////////////////////////////////////////////////////// + + protected abstract ObservableList filterPaymentAccounts(ObservableList paymentAccounts); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferViewModel.java index a7f4c138ca4..b0e10fd42cd 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferViewModel.java @@ -981,6 +981,10 @@ CoinFormatter getBtcFormatter() { return btcFormatter; } + public boolean isShownAsBuyOffer() { + return OfferViewUtil.isShownAsBuyOffer(dataModel.getDirection(), dataModel.getTradeCurrency()); + } + public boolean isSellOffer() { return dataModel.getDirection() == OfferDirection.SELL; } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java index e059242cd78..2d7b37fae9e 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java @@ -28,6 +28,7 @@ import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; +import bisq.core.locale.TradeCurrency; import bisq.core.offer.Offer; import bisq.core.offer.OfferDirection; @@ -118,10 +119,18 @@ private static void openBuyBsqOfferBook(Navigation navigation) { } public static boolean isShownAsSellOffer(Offer offer) { - return CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) == (offer.getDirection() == OfferDirection.SELL); + return isShownAsSellOffer(offer.getCurrencyCode(), offer.getDirection()); + } + + public static boolean isShownAsSellOffer(String currencyCode, OfferDirection direction) { + return CurrencyUtil.isFiatCurrency(currencyCode) == (direction == OfferDirection.SELL); } public static boolean isShownAsBuyOffer(Offer offer) { return !isShownAsSellOffer(offer); } + + public static boolean isShownAsBuyOffer(OfferDirection direction, TradeCurrency tradeCurrency) { + return !isShownAsSellOffer(tradeCurrency.getCode(), direction); + } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/createoffer/CreateOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/createoffer/CreateOfferView.java index 0ad84c2c006..2f4d7995e2b 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/createoffer/CreateOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/createoffer/CreateOfferView.java @@ -19,9 +19,16 @@ import bisq.desktop.Navigation; import bisq.desktop.common.view.FxmlView; +import bisq.desktop.main.offer.OfferView; import bisq.desktop.main.offer.bisq_v1.MutableOfferView; +import bisq.desktop.main.offer.offerbook.BsqOfferBookViewModel; +import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookViewModel; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.TradeCurrency; +import bisq.core.offer.OfferDirection; +import bisq.core.payment.PaymentAccount; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; import bisq.core.util.coin.BsqFormatter; @@ -31,6 +38,12 @@ import javax.inject.Named; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.util.Objects; +import java.util.stream.Collectors; + @FxmlView public class CreateOfferView extends MutableOfferView { @Inject @@ -42,4 +55,32 @@ private CreateOfferView(CreateOfferViewModel model, BsqFormatter bsqFormatter) { super(model, navigation, preferences, offerDetailsWindow, btcFormatter, bsqFormatter); } + + @Override + public void initWithData(OfferDirection direction, + TradeCurrency tradeCurrency, + OfferView.OfferActionHandler offerActionHandler) { + // Invert direction for non-Fiat trade currencies -> BUY BSQ is to SELL Bitcoin + OfferDirection offerDirection = CurrencyUtil.isFiatCurrency(tradeCurrency.getCode()) ? direction : + direction == OfferDirection.BUY ? OfferDirection.SELL : OfferDirection.BUY; + super.initWithData(offerDirection, tradeCurrency, offerActionHandler); + } + + @Override + protected ObservableList filterPaymentAccounts(ObservableList paymentAccounts) { + return FXCollections.observableArrayList( + paymentAccounts.stream().filter(paymentAccount -> { + if (model.getTradeCurrency().equals(BsqOfferBookViewModel.BSQ)) { + return Objects.equals(paymentAccount.getSingleTradeCurrency(), BsqOfferBookViewModel.BSQ); + } else if (model.getTradeCurrency().equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN)) { + return Objects.equals(paymentAccount.getSingleTradeCurrency(), TopAltcoinOfferBookViewModel.TOP_ALTCOIN); + } else if (CurrencyUtil.isFiatCurrency(model.getTradeCurrency().getCode())) { + return !paymentAccount.getPaymentMethod().isAltcoin(); + } else { + return paymentAccount.getPaymentMethod().isAltcoin() && + !(Objects.equals(paymentAccount.getSingleTradeCurrency(), BsqOfferBookViewModel.BSQ) || + Objects.equals(paymentAccount.getSingleTradeCurrency(), TopAltcoinOfferBookViewModel.TOP_ALTCOIN)); + } + }).collect(Collectors.toList())); + } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java index e57354cf2c4..a507c073d8c 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java @@ -36,9 +36,10 @@ import bisq.desktop.main.dao.wallet.receive.BsqReceiveView; import bisq.desktop.main.funds.FundsView; import bisq.desktop.main.funds.withdrawal.WithdrawalView; -import bisq.desktop.main.offer.Closable; -import bisq.desktop.main.offer.InitializableWithData; +import bisq.desktop.main.offer.ClosableView; +import bisq.desktop.main.offer.InitializableViewWithTakeOfferData; import bisq.desktop.main.offer.OfferView; +import bisq.desktop.main.offer.SelectableView; import bisq.desktop.main.offer.bisq_v1.OfferViewUtil; import bisq.desktop.main.overlays.notifications.Notification; import bisq.desktop.main.overlays.popups.Popup; @@ -123,7 +124,7 @@ import static javafx.beans.binding.Bindings.createStringBinding; @FxmlView -public class TakeOfferView extends ActivatableViewAndModel implements Closable, InitializableWithData { +public class TakeOfferView extends ActivatableViewAndModel implements ClosableView, InitializableViewWithTakeOfferData, SelectableView { private final Navigation navigation; private final CoinFormatter formatter; private final BsqFormatter bsqFormatter; @@ -819,7 +820,7 @@ private void addPaymentGroup() { GridPane.setColumnSpan(paymentAccountTitledGroupBg, 2); final Tuple4, Label, TextField, HBox> paymentAccountTuple = addComboBoxTopLabelTextField(gridPane, - gridRow, Res.get("shared.selectTradingAccount"), + gridRow, Res.get("shared.chooseTradingAccount"), Res.get("shared.paymentMethod"), Layout.FIRST_ROW_DISTANCE); paymentAccountsComboBox = paymentAccountTuple.first; diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/BsqSwapOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/BsqSwapOfferView.java index 76a5154ca6c..79bc4645243 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/BsqSwapOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/BsqSwapOfferView.java @@ -24,7 +24,7 @@ import bisq.desktop.components.FundsTextField; import bisq.desktop.components.InputTextField; import bisq.desktop.components.TitledGroupBg; -import bisq.desktop.main.offer.Closable; +import bisq.desktop.main.offer.ClosableView; import bisq.desktop.main.offer.OfferView; import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; import bisq.desktop.util.GUIUtil; @@ -69,7 +69,7 @@ import static bisq.desktop.util.FormBuilder.addTitledGroupBg; import static javafx.scene.layout.Region.USE_COMPUTED_SIZE; -public abstract class BsqSwapOfferView> extends ActivatableViewAndModel implements Closable { +public abstract class BsqSwapOfferView> extends ActivatableViewAndModel implements ClosableView { protected final Navigation navigation; protected final BsqSwapOfferDetailsWindow bsqSwapOfferDetailsWindow; diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/create_offer/BsqSwapCreateOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/create_offer/BsqSwapCreateOfferView.java index ec4037eeb91..2e9c97a6af7 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/create_offer/BsqSwapCreateOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/create_offer/BsqSwapCreateOfferView.java @@ -26,6 +26,7 @@ import bisq.desktop.components.TitledGroupBg; import bisq.desktop.main.MainView; import bisq.desktop.main.offer.OfferView; +import bisq.desktop.main.offer.SelectableView; import bisq.desktop.main.offer.bsq_swap.BsqSwapOfferView; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; @@ -82,7 +83,7 @@ @FxmlView @Slf4j -public class BsqSwapCreateOfferView extends BsqSwapOfferView { +public class BsqSwapCreateOfferView extends BsqSwapOfferView implements SelectableView { private InputTextField minAmountTextField, priceTextField, volumeTextField; private Label miningPowLabel; private BusyAnimation miningPowBusyAnimation; @@ -431,7 +432,7 @@ protected void removeBindings() { @Override protected void addPaymentAccountGroup() { - paymentAccountTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, Res.get("shared.selectTradingAccount")); + paymentAccountTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, Res.get("shared.chooseTradingAccount")); GridPane.setColumnSpan(paymentAccountTitledGroupBg, 2); HBox paymentGroupBox = new HBox(); @@ -440,7 +441,7 @@ protected void addPaymentAccountGroup() { paymentGroupBox.setPadding(new Insets(10, 0, 18, 0)); Tuple3> paymentAccountBoxTuple = addTopLabelComboBox( - Res.get("shared.tradingAccount"), Res.get("shared.selectTradingAccount")); + Res.get("shared.chooseTradingAccount"), Res.get("shared.chooseTradingAccount")); Tuple3 currencyTextFieldTuple = addTopLabelTextField(gridPane, gridRow, Res.get("shared.currency"), BSQ, 5d); @@ -459,7 +460,7 @@ protected void addPaymentAccountGroup() { paymentAccountsComboBox.setMinWidth(paymentAccountVBox.getMinWidth()); paymentAccountsComboBox.setPrefWidth(paymentAccountVBox.getMinWidth()); paymentAccountsComboBox.setConverter(GUIUtil.getPaymentAccountsComboBoxStringConverter()); - paymentAccountsComboBox.setButtonCell(GUIUtil.getComboBoxButtonCell(Res.get("shared.selectTradingAccount"), + paymentAccountsComboBox.setButtonCell(GUIUtil.getComboBoxButtonCell(Res.get("shared.chooseTradingAccount"), paymentAccountsComboBox, false)); paymentAccountsComboBox.setCellFactory(getPaymentAccountListCellFactory(paymentAccountsComboBox)); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java index fd11db20a0e..d7d0c16f245 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java @@ -25,7 +25,8 @@ import bisq.desktop.components.InputTextField; import bisq.desktop.components.TitledGroupBg; import bisq.desktop.main.MainView; -import bisq.desktop.main.offer.InitializableWithData; +import bisq.desktop.main.offer.InitializableViewWithTakeOfferData; +import bisq.desktop.main.offer.SelectableView; import bisq.desktop.main.offer.bisq_v1.OfferViewUtil; import bisq.desktop.main.offer.bsq_swap.BsqSwapOfferView; import bisq.desktop.main.overlays.popups.Popup; @@ -74,7 +75,7 @@ import static bisq.desktop.util.FormBuilder.*; @FxmlView -public class BsqSwapTakeOfferView extends BsqSwapOfferView implements InitializableWithData { +public class BsqSwapTakeOfferView extends BsqSwapOfferView implements InitializableViewWithTakeOfferData, SelectableView { private HBox minAmountHBox; private Label offerAvailabilityLabel; private TextField paymentMethodTextField, currencyTextField, priceTextField, diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java index ef4d5d30c33..46c86fdadf4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java @@ -58,8 +58,8 @@ public class BsqOfferBookView extends OfferBookView getCurrencyAndMethodPredicate(OfferDirection direct }; } + @Override + TradeCurrency getDefaultTradeCurrency() { + return BSQ; + } + @Override String getCurrencyCodeFromPreferences(OfferDirection direction) { return BSQ.getCode(); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java index 480a7d0579e..ad04f538b0f 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java @@ -56,9 +56,14 @@ public class BtcOfferBookView extends OfferBookView getCurrencyAndMethodPredicate(OfferDirection direct }; } + @Override + TradeCurrency getDefaultTradeCurrency() { + return GlobalSettings.getDefaultTradeCurrency(); + } + @Override String getCurrencyCodeFromPreferences(OfferDirection direction) { return direction == OfferDirection.BUY ? preferences.getBuyScreenCurrencyCode() : preferences.getSellScreenCurrencyCode(); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index ce711627b16..c7ed1a5dc0d 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -210,7 +210,7 @@ public void initialize() { matchingOffersToggle.setText(Res.get("offerbook.matchingOffers")); HBox.setMargin(matchingOffersToggle, new Insets(7, 0, -9, -15)); - createOfferButton = new AutoTooltipButton(Res.get("offerbook.createNewOffer")); + createOfferButton = new AutoTooltipButton(""); createOfferButton.setMinHeight(40); createOfferButton.setGraphicTextGap(10); @@ -361,6 +361,7 @@ protected void activate() { model.updateSelectedPaymentMethod(); updatePaymentMethodComboBoxEditor(); model.onSetPaymentMethod(paymentMethodComboBox.getSelectionModel().getSelectedItem()); + updateCreateOfferButton(); }); updateCurrencyComboBoxFromModel(); @@ -587,7 +588,6 @@ private void disableCreateOfferButton() { public void setDirection(OfferDirection direction) { model.initWithDirection(direction); ImageView iconView = new ImageView(); - createOfferButton.setGraphic(iconView); iconView.setId(direction == OfferDirection.SELL ? "image-sell-white" : "image-buy-white"); createOfferButton.setId(direction == OfferDirection.SELL ? "sell-button-big" : "buy-button-big"); @@ -605,6 +605,7 @@ public void onTabSelected(boolean isSelected) { updateCurrencyComboBoxFromModel(); root.requestFocus(); } + updateCreateOfferButton(); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -616,12 +617,14 @@ private void onCreateOffer() { if (!model.hasPaymentAccountForCurrency()) { new Popup().headLine(Res.get("offerbook.warning.noTradingAccountForCurrency.headline")) .instruction(Res.get("offerbook.warning.noTradingAccountForCurrency.msg")) - .actionButtonText(Res.get("offerbook.yesCreateOffer")) - .onAction(this::disableCreateOfferButton) - .secondaryActionButtonText(Res.get("offerbook.setupNewAccount")) - .onSecondaryAction(() -> { + .actionButtonText(Res.get("offerbook.setupNewAccount")) + .onAction(() -> { navigation.setReturnPath(navigation.getCurrentPath()); - navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); + if (CurrencyUtil.isFiatCurrency(model.getSelectedTradeCurrency().getCode())) { + navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); + } else { + navigation.navigateTo(MainView.class, AccountView.class, AltCoinAccountsView.class); + } }) .width(725) .show(); @@ -1084,6 +1087,7 @@ public TableCell call(TableColumn call(TableColumn call(TableColumn getMostMaturePaymentAccountForOffer(Offer offer) { private void setMarketPriceFeedCurrency() { if (isTabSelected) { if (showAllTradeCurrenciesProperty.get()) - priceFeedService.setCurrencyCode(GlobalSettings.getDefaultTradeCurrency().getCode()); + priceFeedService.setCurrencyCode(getDefaultTradeCurrency().getCode()); else priceFeedService.setCurrencyCode(tradeCurrencyCode.get()); } @@ -697,11 +695,13 @@ private void updateSelectedTradeCurrency() { selectedTradeCurrency = CurrencyUtil.getTradeCurrency(code).get(); } else { showAllTradeCurrenciesProperty.set(true); - selectedTradeCurrency = GlobalSettings.getDefaultTradeCurrency(); + selectedTradeCurrency = getDefaultTradeCurrency(); } tradeCurrencyCode.set(selectedTradeCurrency.getCode()); } + abstract TradeCurrency getDefaultTradeCurrency(); + public void updateSelectedPaymentMethod() { showAllPaymentMethods = getPaymentMethods().stream().noneMatch(paymentMethod -> paymentMethod.equals(selectedPaymentMethod)); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java index 7ccb4f74978..b04719bb996 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java @@ -56,7 +56,12 @@ public class OtherOfferBookView extends OfferBookView getCurrencyAndMethodPredicate(OfferDirection direct }; } + @Override + TradeCurrency getDefaultTradeCurrency() { + // select first currency in list, otherwise if view is not initialized add Ether as default one + return !getTradeCurrencies().isEmpty() ? getTradeCurrencies().get(1) : + DEFAULT_ALTCOIN; + } + @Override String getCurrencyCodeFromPreferences(OfferDirection direction) { return direction == OfferDirection.BUY ? preferences.getBuyScreenCryptoCurrencyCode() : preferences.getSellScreenCryptoCurrencyCode(); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java index 076b83cad55..081f0caf6e1 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java @@ -56,8 +56,8 @@ public class TopAltcoinOfferBookView extends OfferBookView getCurrencyAndMethodPredicate(OfferDirection direct }; } + @Override + TradeCurrency getDefaultTradeCurrency() { + return TOP_ALTCOIN; + } + @Override String getCurrencyCodeFromPreferences(OfferDirection direction) { return TOP_ALTCOIN.getCode(); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferView.java index db6eb38ba19..b6850c27acb 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferView.java @@ -24,6 +24,7 @@ import bisq.core.locale.CurrencyUtil; import bisq.core.offer.bisq_v1.OfferPayload; +import bisq.core.payment.PaymentAccount; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; import bisq.core.util.coin.BsqFormatter; @@ -33,16 +34,18 @@ import javax.inject.Named; +import javafx.collections.ObservableList; + @FxmlView public class DuplicateOfferView extends MutableOfferView { @Inject private DuplicateOfferView(DuplicateOfferViewModel model, - Navigation navigation, - Preferences preferences, - OfferDetailsWindow offerDetailsWindow, - @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, - BsqFormatter bsqFormatter) { + Navigation navigation, + Preferences preferences, + OfferDetailsWindow offerDetailsWindow, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, + BsqFormatter bsqFormatter) { super(model, navigation, preferences, offerDetailsWindow, btcFormatter, bsqFormatter); } @@ -61,6 +64,11 @@ protected void doActivate() { onPaymentAccountsComboBoxSelected(); } + @Override + protected ObservableList filterPaymentAccounts(ObservableList paymentAccounts) { + return paymentAccounts; + } + public void initWithData(OfferPayload offerPayload) { initWithData(offerPayload.getDirection(), CurrencyUtil.getTradeCurrency(offerPayload.getCurrencyCode()).get(), diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java index 3fe8ae92383..59a9cd0bec9 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java @@ -28,6 +28,7 @@ import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.offer.OpenOffer; +import bisq.core.payment.PaymentAccount; import bisq.core.user.DontShowAgainLookup; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; @@ -50,6 +51,8 @@ import javafx.geometry.Insets; import javafx.geometry.Pos; +import javafx.collections.ObservableList; + import static bisq.desktop.util.FormBuilder.addButtonBusyAnimationLabelAfterGroup; @FxmlView @@ -174,6 +177,11 @@ private void removeBindings() { confirmButton.disableProperty().unbind(); } + @Override + protected ObservableList filterPaymentAccounts(ObservableList paymentAccounts) { + return paymentAccounts; + } + /////////////////////////////////////////////////////////////////////////////////////////// // Build UI elements /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/presentation/PortfolioUtil.java b/desktop/src/main/java/bisq/desktop/main/portfolio/presentation/PortfolioUtil.java index 22ef5712950..13e5966607e 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/presentation/PortfolioUtil.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/presentation/PortfolioUtil.java @@ -21,7 +21,8 @@ import bisq.desktop.main.MainView; import bisq.desktop.main.offer.BuyOfferView; import bisq.desktop.main.offer.SellOfferView; -import bisq.desktop.main.offer.bsq_swap.create_offer.BsqSwapCreateOfferView; +import bisq.desktop.main.offer.bisq_v1.createoffer.CreateOfferView; +import bisq.desktop.main.offer.offerbook.BsqOfferBookView; import bisq.desktop.main.portfolio.PortfolioView; import bisq.desktop.main.portfolio.duplicateoffer.DuplicateOfferView; @@ -33,8 +34,9 @@ public class PortfolioUtil { public static void duplicateOffer(Navigation navigation, OfferPayloadBase offerPayload) { if (offerPayload instanceof BsqSwapOfferPayload) { - var offerViewClass = offerPayload.getDirection() == OfferDirection.BUY ? BuyOfferView.class : SellOfferView.class; - navigation.navigateToWithData(offerPayload, MainView.class, offerViewClass, BsqSwapCreateOfferView.class); + // BUY Bitcoin means SELL BSQ + var offerViewClass = offerPayload.getDirection() == OfferDirection.BUY ? SellOfferView.class : BuyOfferView.class; + navigation.navigateToWithData(offerPayload, MainView.class, offerViewClass, BsqOfferBookView.class, CreateOfferView.class); } else { navigation.navigateToWithData(offerPayload, MainView.class, PortfolioView.class, DuplicateOfferView.class); }