From b0296e28c488e1b5bcbcf121c105b87f68a05155 Mon Sep 17 00:00:00 2001 From: Christoph Atteneder Date: Mon, 13 Aug 2018 12:21:45 +0200 Subject: [PATCH 1/4] Show warning if user selects language where native speaking arbitration support is not available --- .../settings/preferences/PreferencesView.java | 14 +++-- .../preferences/PreferencesViewModel.java | 55 +++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java 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..cc80dd8667f --- /dev/null +++ b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java @@ -0,0 +1,55 @@ +/* + * 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.getArbitratorsObservableMap().values().stream().anyMatch( + arbitrator -> arbitrator.getLanguageCodes().stream().anyMatch( + languageCode -> languageCode.equals(preferences.getUserLanguage()))); + } + + String getArbitrationLanguages() { + return arbitratorManager.getArbitratorsObservableMap().values().stream() + .flatMap(arbitrator -> arbitrator.getLanguageCodes().stream()) + .distinct() + .map(languageCode -> LanguageUtil.getDisplayName(languageCode)) + .collect(Collectors.joining(", ")); + } +} From 6f110342bb8a692c36adbd0c1a8220294acecf0a Mon Sep 17 00:00:00 2001 From: Christoph Atteneder Date: Mon, 13 Aug 2018 12:55:40 +0200 Subject: [PATCH 2/4] Add tests for arbitration language warning --- .../preferences/PreferencesViewModelTest.java | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java 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..0b9f1e3f09d --- /dev/null +++ b/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java @@ -0,0 +1,135 @@ +/* + * 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.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +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()); + } + + @Test + public void testNeedsArbitrationLanguageWarning() { + Preferences preferences = PreferenceMakers.empty; + preferences.setUserLanguage("de"); + + 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); + + when(arbitratorManager.getArbitratorsObservableMap()).thenReturn(arbitrators); + + PreferencesViewModel model = new PreferencesViewModel(preferences, arbitratorManager); + + assertFalse(model.needsArbitrationLanguageWarning()); + + preferences.setUserLanguage("th"); + + assertTrue(model.needsArbitrationLanguageWarning()); + } +} From 686ab452532c0bebbbe151ee24d2a89c21a98895 Mon Sep 17 00:00:00 2001 From: Christoph Atteneder Date: Tue, 14 Aug 2018 12:06:07 +0200 Subject: [PATCH 3/4] Extract arbitrator language check into ArbitratorManager --- .../preferences/PreferencesViewModel.java | 4 +- .../preferences/PreferencesViewModelTest.java | 42 ------------------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java index cc80dd8667f..db7febe0923 100644 --- a/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java +++ b/src/main/java/bisq/desktop/main/settings/preferences/PreferencesViewModel.java @@ -40,9 +40,7 @@ public PreferencesViewModel(Preferences preferences, ArbitratorManager arbitrato } boolean needsArbitrationLanguageWarning() { - return !arbitratorManager.getArbitratorsObservableMap().values().stream().anyMatch( - arbitrator -> arbitrator.getLanguageCodes().stream().anyMatch( - languageCode -> languageCode.equals(preferences.getUserLanguage()))); + return !arbitratorManager.isArbitratorAvailableForLanguage(preferences.getUserLanguage()); } String getArbitrationLanguages() { diff --git a/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java b/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java index 0b9f1e3f09d..0e2ac430ed4 100644 --- a/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java +++ b/src/test/java/bisq/desktop/main/settings/preferences/PreferencesViewModelTest.java @@ -41,8 +41,6 @@ import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -92,44 +90,4 @@ public void testGetArbitrationLanguages() { assertEquals("English, Deutsch, español", model.getArbitrationLanguages()); } - @Test - public void testNeedsArbitrationLanguageWarning() { - Preferences preferences = PreferenceMakers.empty; - preferences.setUserLanguage("de"); - - 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); - - when(arbitratorManager.getArbitratorsObservableMap()).thenReturn(arbitrators); - - PreferencesViewModel model = new PreferencesViewModel(preferences, arbitratorManager); - - assertFalse(model.needsArbitrationLanguageWarning()); - - preferences.setUserLanguage("th"); - - assertTrue(model.needsArbitrationLanguageWarning()); - } } From 76cc2d55a06ae79556c4c42c62bffb4196ff90d5 Mon Sep 17 00:00:00 2001 From: Christoph Atteneder Date: Tue, 14 Aug 2018 13:29:06 +0200 Subject: [PATCH 4/4] Add warning if Offer is taken or created and user has set language that is not supported natively by arbitrators --- .../bisq/desktop/main/offer/BuyOfferView.java | 5 +- .../bisq/desktop/main/offer/OfferView.java | 59 ++++++++++++++++--- .../desktop/main/offer/SellOfferView.java | 5 +- 3 files changed, 56 insertions(+), 13 deletions(-) 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); } }