diff --git a/src/main/java/bisq/desktop/main/offer/BuyOfferView.java b/src/main/java/bisq/desktop/main/offer/BuyOfferView.java index ed082446b3e..f722b3252c8 100644 --- a/src/main/java/bisq/desktop/main/offer/BuyOfferView.java +++ b/src/main/java/bisq/desktop/main/offer/BuyOfferView.java @@ -21,6 +21,7 @@ import bisq.desktop.common.view.FxmlView; import bisq.desktop.common.view.ViewLoader; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.user.Preferences; import javax.inject.Inject; @@ -29,8 +30,8 @@ public class BuyOfferView extends OfferView { @Inject - public BuyOfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences) { - super(viewLoader, navigation, preferences); + public BuyOfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences, ArbitratorManager arbitratorManager) { + super(viewLoader, navigation, preferences, arbitratorManager); } } diff --git a/src/main/java/bisq/desktop/main/offer/OfferView.java b/src/main/java/bisq/desktop/main/offer/OfferView.java index e124571fec1..b9541a17936 100644 --- a/src/main/java/bisq/desktop/main/offer/OfferView.java +++ b/src/main/java/bisq/desktop/main/offer/OfferView.java @@ -26,16 +26,21 @@ import bisq.desktop.main.offer.createoffer.CreateOfferView; import bisq.desktop.main.offer.offerbook.OfferBookView; import bisq.desktop.main.offer.takeoffer.TakeOfferView; +import bisq.desktop.main.overlays.popups.Popup; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.GlobalSettings; +import bisq.core.locale.LanguageUtil; import bisq.core.locale.Res; import bisq.core.locale.TradeCurrency; import bisq.core.offer.Offer; import bisq.core.offer.OfferPayload; import bisq.core.user.Preferences; +import bisq.core.user.User; import bisq.common.UserThread; +import bisq.common.handlers.ResultHandler; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; @@ -47,6 +52,7 @@ import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; public abstract class OfferView extends ActivatableView { @@ -60,6 +66,7 @@ public abstract class OfferView extends ActivatableView { private final Navigation navigation; private final Preferences preferences; private final OfferPayload.Direction direction; + private final ArbitratorManager arbitratorManager; private Offer offer; private TradeCurrency tradeCurrency; @@ -68,11 +75,12 @@ public abstract class OfferView extends ActivatableView { private ChangeListener tabChangeListener; private ListChangeListener tabListChangeListener; - protected OfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences) { + protected OfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences, ArbitratorManager arbitratorManager) { this.viewLoader = viewLoader; this.navigation = navigation; this.preferences = preferences; this.direction = (this instanceof BuyOfferView) ? OfferPayload.Direction.BUY : OfferPayload.Direction.SELL; + this.arbitratorManager = arbitratorManager; } @Override @@ -161,10 +169,11 @@ private void loadView(Class viewClass) { @Override public void onCreateOffer(TradeCurrency tradeCurrency) { if (!createOfferViewOpen) { - OfferView.this.createOfferViewOpen = true; - OfferView.this.tradeCurrency = tradeCurrency; - OfferView.this.navigation.navigateTo(MainView.class, OfferView.this.getClass(), - CreateOfferView.class); + if (!arbitratorManager.isArbitratorAvailableForLanguage(preferences.getUserLanguage())) { + showNoArbitratorForUserLocaleWarning(); + } + openCreateOffer(tradeCurrency); + } else { log.error("You have already a \"Create offer\" tab open."); } @@ -173,10 +182,11 @@ public void onCreateOffer(TradeCurrency tradeCurrency) { @Override public void onTakeOffer(Offer offer) { if (!takeOfferViewOpen) { - OfferView.this.takeOfferViewOpen = true; - OfferView.this.offer = offer; - OfferView.this.navigation.navigateTo(MainView.class, OfferView.this.getClass(), - TakeOfferView.class); + if (!arbitratorManager.getArbitratorLanguages(offer.getArbitratorNodeAddresses()).stream() + .anyMatch(languages -> languages.equals(preferences.getUserLanguage()))) { + showNoArbitratorForUserLocaleWarning(); + } + openTakeOffer(offer); } else { log.error("You have already a \"Take offer\" tab open."); } @@ -213,6 +223,37 @@ public void onTakeOffer(Offer offer) { } } + private void showNoArbitratorForUserLocaleWarning() { + String key = "NoArbitratorForUserLocaleWarning"; + new Popup<>().information(Res.get("offerbook.info.noArbitrationInUserLanguage", + getArbitrationLanguages(), LanguageUtil.getDisplayName(preferences.getUserLanguage()))) + .closeButtonText(Res.get("shared.ok")) + .dontShowAgainId(key) + .show(); + } + + private String getArbitrationLanguages() { + return arbitratorManager.getArbitratorsObservableMap().values().stream() + .flatMap(arbitrator -> arbitrator.getLanguageCodes().stream()) + .distinct() + .map(languageCode -> LanguageUtil.getDisplayName(languageCode)) + .collect(Collectors.joining(", ")); + } + + private void openTakeOffer(Offer offer) { + OfferView.this.takeOfferViewOpen = true; + OfferView.this.offer = offer; + OfferView.this.navigation.navigateTo(MainView.class, OfferView.this.getClass(), + TakeOfferView.class); + } + + private void openCreateOffer(TradeCurrency tradeCurrency) { + OfferView.this.createOfferViewOpen = true; + OfferView.this.tradeCurrency = tradeCurrency; + OfferView.this.navigation.navigateTo(MainView.class, OfferView.this.getClass(), + CreateOfferView.class); + } + private void onCreateOfferViewRemoved() { createOfferViewOpen = false; if (createOfferView != null) { diff --git a/src/main/java/bisq/desktop/main/offer/SellOfferView.java b/src/main/java/bisq/desktop/main/offer/SellOfferView.java index eb0bf00278c..4c79ba9b4ec 100644 --- a/src/main/java/bisq/desktop/main/offer/SellOfferView.java +++ b/src/main/java/bisq/desktop/main/offer/SellOfferView.java @@ -21,6 +21,7 @@ import bisq.desktop.common.view.FxmlView; import bisq.desktop.common.view.ViewLoader; +import bisq.core.arbitration.ArbitratorManager; import bisq.core.user.Preferences; import javax.inject.Inject; @@ -29,8 +30,8 @@ public class SellOfferView extends OfferView { @Inject - public SellOfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences) { - super(viewLoader, navigation, preferences); + public SellOfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences, ArbitratorManager arbitratorManager) { + super(viewLoader, navigation, preferences, arbitratorManager); } } diff --git a/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java index c2874da8374..c85ea33deb8 100644 --- a/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java +++ b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java @@ -17,7 +17,6 @@ package bisq.desktop.main.settings.preferences; -import bisq.desktop.common.model.Activatable; import bisq.desktop.common.view.ActivatableViewAndModel; import bisq.desktop.common.view.FxmlView; import bisq.desktop.components.AutoTooltipButton; @@ -85,7 +84,7 @@ import static bisq.desktop.util.FormBuilder.*; @FxmlView -public class PreferencesView extends ActivatableViewAndModel { +public class PreferencesView extends ActivatableViewAndModel { // not supported yet //private ComboBox btcDenominationComboBox; @@ -129,9 +128,9 @@ public class PreferencesView extends ActivatableViewAndModel().information(Res.get("settings.preferences.languageChange")) .closeButtonText(Res.get("shared.ok")) .show(); + + if (model.needsArbitrationLanguageWarning()) { + new Popup<>().warning(Res.get("settings.preferences.arbitrationLanguageWarning", + model.getArbitrationLanguages())) + .closeButtonText(Res.get("shared.ok")) + .show(); + } } // Should we apply the changed currency immediately to the language list? // If so and the user selects a unknown language he might get lost and it is hard to find diff --git a/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java new file mode 100644 index 00000000000..db7febe0923 --- /dev/null +++ b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java @@ -0,0 +1,53 @@ +/* + * 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.settings.preferences; + + +import bisq.desktop.common.model.ActivatableViewModel; + +import bisq.core.arbitration.ArbitratorManager; +import bisq.core.locale.LanguageUtil; +import bisq.core.user.Preferences; + +import com.google.inject.Inject; + +import java.util.stream.Collectors; + +public class PreferencesViewModel extends ActivatableViewModel { + + private final ArbitratorManager arbitratorManager; + private final Preferences preferences; + + @Inject + public PreferencesViewModel(Preferences preferences, ArbitratorManager arbitratorManager) { + this.preferences = preferences; + this.arbitratorManager = arbitratorManager; + } + + boolean needsArbitrationLanguageWarning() { + return !arbitratorManager.isArbitratorAvailableForLanguage(preferences.getUserLanguage()); + } + + String getArbitrationLanguages() { + return arbitratorManager.getArbitratorsObservableMap().values().stream() + .flatMap(arbitrator -> arbitrator.getLanguageCodes().stream()) + .distinct() + .map(languageCode -> LanguageUtil.getDisplayName(languageCode)) + .collect(Collectors.joining(", ")); + } +} diff --git a/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java b/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java new file mode 100644 index 00000000000..0e2ac430ed4 --- /dev/null +++ b/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java @@ -0,0 +1,93 @@ +/* + * 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.settings.preferences; + +import bisq.core.arbitration.Arbitrator; +import bisq.core.arbitration.ArbitratorManager; +import bisq.core.user.PreferenceMakers; +import bisq.core.user.Preferences; + +import bisq.network.p2p.NodeAddress; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableMap; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.security.Security; + +import java.util.ArrayList; + +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ArbitratorManager.class, Preferences.class}) +public class PreferencesViewModelTest { + + @Before + public void setUp() { + Security.addProvider(new BouncyCastleProvider()); + } + + @Test + public void testGetArbitrationLanguages() { + + ArbitratorManager arbitratorManager = mock(ArbitratorManager.class); + + final ObservableMap arbitrators = FXCollections.observableHashMap(); + + ArrayList languagesOne = new ArrayList() {{ + add("en"); + add("de"); + }}; + + ArrayList languagesTwo = new ArrayList() {{ + add("en"); + add("es"); + }}; + + Arbitrator one = new Arbitrator(new NodeAddress("arbitrator:1"), null, null, null, + languagesOne, 0L, null, "", null, + null, null); + + Arbitrator two = new Arbitrator(new NodeAddress("arbitrator:2"), null, null, null, + languagesTwo, 0L, null, "", null, + null, null); + + arbitrators.put(one.getNodeAddress(), one); + arbitrators.put(two.getNodeAddress(), two); + + Preferences preferences = PreferenceMakers.empty; + + when(arbitratorManager.getArbitratorsObservableMap()).thenReturn(arbitrators); + + PreferencesViewModel model = new PreferencesViewModel(preferences, arbitratorManager); + + assertEquals("English, Deutsch, espaƱol", model.getArbitrationLanguages()); + } + +}