rename all packages and other names from bisq to haveno

This commit is contained in:
woodser 2023-03-06 19:14:00 -05:00
parent ab0b9e3b77
commit 1a1fb130c0
1775 changed files with 14575 additions and 16767 deletions

View file

@ -0,0 +1,857 @@
/*
* This file is part of Haveno.
*
* Haveno 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.
*
* Haveno 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 Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package haveno.desktop.main.settings.preferences;
import static haveno.desktop.util.FormBuilder.*;
import haveno.common.UserThread;
import haveno.common.app.DevEnv;
import haveno.common.config.Config;
import haveno.common.util.Tuple2;
import haveno.common.util.Tuple3;
import haveno.common.util.Utilities;
import haveno.core.btc.wallet.Restrictions;
import haveno.core.filter.Filter;
import haveno.core.filter.FilterManager;
import haveno.core.locale.Country;
import haveno.core.locale.CountryUtil;
import haveno.core.locale.CryptoCurrency;
import haveno.core.locale.CurrencyUtil;
import haveno.core.locale.FiatCurrency;
import haveno.core.locale.LanguageUtil;
import haveno.core.locale.Res;
import haveno.core.locale.TradeCurrency;
import haveno.core.payment.PaymentAccount;
import haveno.core.payment.payload.PaymentMethod;
import haveno.core.payment.validation.XmrValidator;
import haveno.core.trade.HavenoUtils;
import haveno.core.user.Preferences;
import haveno.core.user.User;
import haveno.core.util.FormattingUtils;
import haveno.core.util.ParsingUtils;
import haveno.core.util.coin.CoinFormatter;
import haveno.core.util.validation.IntegerValidator;
import haveno.core.util.validation.RegexValidator;
import haveno.core.util.validation.RegexValidatorFactory;
import haveno.desktop.common.view.ActivatableViewAndModel;
import haveno.desktop.common.view.FxmlView;
import haveno.desktop.components.AutoTooltipButton;
import haveno.desktop.components.AutoTooltipLabel;
import haveno.desktop.components.InputTextField;
import haveno.desktop.components.PasswordTextField;
import haveno.desktop.components.TitledGroupBg;
import haveno.desktop.main.overlays.popups.Popup;
import haveno.desktop.main.overlays.windows.EditCustomExplorerWindow;
import haveno.desktop.util.GUIUtil;
import haveno.desktop.util.ImageUtil;
import haveno.desktop.util.Layout;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.VPos;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.util.Callback;
import javafx.util.StringConverter;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
@FxmlView
public class PreferencesView extends ActivatableViewAndModel<GridPane, PreferencesViewModel> {
private final User user;
private final CoinFormatter formatter;
private TextField btcExplorerTextField;
private ComboBox<String> userLanguageComboBox;
private ComboBox<Country> userCountryComboBox;
private ComboBox<TradeCurrency> preferredTradeCurrencyComboBox;
private ToggleButton showOwnOffersInOfferBook, useAnimations, useDarkMode, sortMarketCurrenciesNumerically,
avoidStandbyMode, useCustomFee, autoConfirmXmrToggle, hideNonAccountPaymentMethodsToggle, denyApiTakerToggle,
notifyOnPreReleaseToggle;
private int gridRow = 0;
private int displayCurrenciesGridRowIndex = 0;
private InputTextField ignoreTradersListInputTextField, ignoreDustThresholdInputTextField,
autoConfRequiredConfirmationsTf, autoConfServiceAddressTf, autoConfTradeLimitTf, /*referralIdInputTextField,*/
rpcUserTextField, blockNotifyPortTextField;
private PasswordTextField rpcPwTextField;
private ChangeListener<Boolean> autoConfServiceAddressFocusOutListener, autoConfRequiredConfirmationsFocusOutListener;
private final Preferences preferences;
//private final ReferralIdService referralIdService;
private final FilterManager filterManager;
private final File storageDir;
private ListView<FiatCurrency> fiatCurrenciesListView;
private ComboBox<FiatCurrency> fiatCurrenciesComboBox;
private ListView<CryptoCurrency> cryptoCurrenciesListView;
private ComboBox<CryptoCurrency> cryptoCurrenciesComboBox;
private Button resetDontShowAgainButton, editCustomBtcExplorer;
private ObservableList<String> languageCodes;
private ObservableList<Country> countries;
private ObservableList<FiatCurrency> fiatCurrencies;
private ObservableList<FiatCurrency> allFiatCurrencies;
private ObservableList<CryptoCurrency> cryptoCurrencies;
private ObservableList<CryptoCurrency> allCryptoCurrencies;
private ObservableList<TradeCurrency> tradeCurrencies;
private InputTextField deviationInputTextField;
private ChangeListener<String> deviationListener, ignoreTradersListListener, ignoreDustThresholdListener,
rpcUserListener, rpcPwListener, blockNotifyPortListener,
autoConfTradeLimitListener, autoConfServiceAddressListener;
private ChangeListener<Boolean> deviationFocusedListener;
private final boolean displayStandbyModeFeature;
private ChangeListener<Filter> filterChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, initialisation
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PreferencesView(PreferencesViewModel model,
Preferences preferences,
FilterManager filterManager,
Config config,
User user,
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
@Named(Config.STORAGE_DIR) File storageDir) {
super(model);
this.user = user;
this.formatter = formatter;
this.preferences = preferences;
this.filterManager = filterManager;
this.storageDir = storageDir;
this.displayStandbyModeFeature = Utilities.isLinux() || Utilities.isOSX() || Utilities.isWindows();
}
@Override
public void initialize() {
languageCodes = FXCollections.observableArrayList(LanguageUtil.getUserLanguageCodes());
countries = FXCollections.observableArrayList(CountryUtil.getAllCountries());
fiatCurrencies = preferences.getFiatCurrenciesAsObservable();
cryptoCurrencies = preferences.getCryptoCurrenciesAsObservable();
tradeCurrencies = preferences.getTradeCurrenciesAsObservable();
allFiatCurrencies = FXCollections.observableArrayList(CurrencyUtil.getAllSortedFiatCurrencies());
allFiatCurrencies.removeAll(fiatCurrencies);
initializeGeneralOptions();
initializeDisplayOptions();
initializeSeparator();
initializeAutoConfirmOptions();
initializeDisplayCurrencies();
}
@Override
protected void activate() {
// We want to have it updated in case an asset got removed
allCryptoCurrencies = FXCollections.observableArrayList(CurrencyUtil.getActiveSortedCryptoCurrencies( filterManager));
allCryptoCurrencies.removeAll(cryptoCurrencies);
activateGeneralOptions();
activateDisplayCurrencies();
activateDisplayPreferences();
activateAutoConfirmPreferences();
}
@Override
protected void deactivate() {
deactivateGeneralOptions();
deactivateDisplayCurrencies();
deactivateDisplayPreferences();
deactivateAutoConfirmPreferences();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Initialize
///////////////////////////////////////////////////////////////////////////////////////////
private void initializeGeneralOptions() {
int titledGroupBgRowSpan = displayStandbyModeFeature ? 9 : 8;
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, titledGroupBgRowSpan, Res.get("setting.preferences.general"));
GridPane.setColumnSpan(titledGroupBg, 1);
userLanguageComboBox = addComboBox(root, gridRow,
Res.get("shared.language"), Layout.FIRST_ROW_DISTANCE);
userCountryComboBox = addComboBox(root, ++gridRow,
Res.get("shared.country"));
userCountryComboBox.setButtonCell(GUIUtil.getComboBoxButtonCell(Res.get("shared.country"), userCountryComboBox,
false));
Tuple2<TextField, Button> btcExp = addTextFieldWithEditButton(root, ++gridRow, Res.get("setting.preferences.explorer"));
btcExplorerTextField = btcExp.first;
editCustomBtcExplorer = btcExp.second;
// deviation
deviationInputTextField = addInputTextField(root, ++gridRow,
Res.get("setting.preferences.deviation"));
deviationListener = (observable, oldValue, newValue) -> {
try {
double value = ParsingUtils.parsePercentStringToDouble(newValue);
final double maxDeviation = 0.5;
if (value <= maxDeviation) {
preferences.setMaxPriceDistanceInPercent(value);
} else {
new Popup().warning(Res.get("setting.preferences.deviationToLarge", maxDeviation * 100)).show();
UserThread.runAfter(() -> deviationInputTextField.setText(FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS);
}
} catch (NumberFormatException t) {
log.error("Exception at parseDouble deviation: " + t.toString());
UserThread.runAfter(() -> deviationInputTextField.setText(FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS);
}
};
deviationFocusedListener = (observable1, oldValue1, newValue1) -> {
if (oldValue1 && !newValue1)
UserThread.runAfter(() -> deviationInputTextField.setText(FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS);
};
// ignoreTraders
ignoreTradersListInputTextField = addInputTextField(root, ++gridRow,
Res.get("setting.preferences.ignorePeers"));
RegexValidator regexValidator = RegexValidatorFactory.addressRegexValidator();
ignoreTradersListInputTextField.setValidator(regexValidator);
ignoreTradersListInputTextField.setErrorMessage(Res.get("validation.invalidAddressList"));
ignoreTradersListListener = (observable, oldValue, newValue) -> {
if (regexValidator.validate(newValue).isValid && !newValue.equals(oldValue)) {
preferences.setIgnoreTradersList(Arrays.asList(StringUtils.deleteWhitespace(newValue).split(",")));
}
};
// ignoreDustThreshold
ignoreDustThresholdInputTextField = addInputTextField(root, ++gridRow, Res.get("setting.preferences.ignoreDustThreshold"));
IntegerValidator validator = new IntegerValidator();
validator.setMinValue((int) Restrictions.getMinNonDustOutput().value);
validator.setMaxValue(2000);
ignoreDustThresholdInputTextField.setValidator(validator);
ignoreDustThresholdListener = (observable, oldValue, newValue) -> {
try {
int value = Integer.parseInt(newValue);
checkArgument(value >= Restrictions.getMinNonDustOutput().value,
"Input must be at least " + Restrictions.getMinNonDustOutput().value);
checkArgument(value <= 2000,
"Input must not be higher than 2000 Satoshis");
if (!newValue.equals(oldValue)) {
preferences.setIgnoreDustThreshold(value);
}
} catch (Throwable ignore) {
}
};
if (displayStandbyModeFeature) {
// AvoidStandbyModeService feature works only on OSX & Windows
avoidStandbyMode = addSlideToggleButton(root, ++gridRow,
Res.get("setting.preferences.avoidStandbyMode"));
}
}
private void initializeSeparator() {
final Separator separator = new Separator(Orientation.VERTICAL);
separator.setPadding(new Insets(0, 10, 0, 10));
GridPane.setColumnIndex(separator, 1);
GridPane.setHalignment(separator, HPos.CENTER);
GridPane.setRowIndex(separator, 0);
GridPane.setRowSpan(separator, GridPane.REMAINING);
root.getChildren().add(separator);
}
private void initializeDisplayCurrencies() {
TitledGroupBg titledGroupBg = addTitledGroupBg(root, displayCurrenciesGridRowIndex, 8,
Res.get("setting.preferences.currenciesInList"), Layout.GROUP_DISTANCE);
GridPane.setColumnIndex(titledGroupBg, 2);
GridPane.setColumnSpan(titledGroupBg, 2);
preferredTradeCurrencyComboBox = addComboBox(root, displayCurrenciesGridRowIndex++,
Res.get("setting.preferences.prefCurrency"),
Layout.FIRST_ROW_AND_GROUP_DISTANCE);
GridPane.setColumnIndex(preferredTradeCurrencyComboBox, 2);
preferredTradeCurrencyComboBox.setConverter(new StringConverter<>() {
@Override
public String toString(TradeCurrency object) {
return object.getCode() + " - " + object.getName();
}
@Override
public TradeCurrency fromString(String string) {
return null;
}
});
preferredTradeCurrencyComboBox.setButtonCell(GUIUtil.getTradeCurrencyButtonCell("", "",
FXCollections.emptyObservableMap()));
preferredTradeCurrencyComboBox.setCellFactory(GUIUtil.getTradeCurrencyCellFactory("", "",
FXCollections.emptyObservableMap()));
Tuple3<Label, ListView<FiatCurrency>, VBox> fiatTuple = addTopLabelListView(root, displayCurrenciesGridRowIndex,
Res.get("setting.preferences.displayFiat"));
int listRowSpan = 6;
GridPane.setColumnIndex(fiatTuple.third, 2);
GridPane.setRowSpan(fiatTuple.third, listRowSpan);
GridPane.setValignment(fiatTuple.third, VPos.TOP);
GridPane.setMargin(fiatTuple.third, new Insets(10, 0, 0, 0));
fiatCurrenciesListView = fiatTuple.second;
fiatCurrenciesListView.setMinHeight(9 * Layout.LIST_ROW_HEIGHT + 2);
fiatCurrenciesListView.setPrefHeight(10 * Layout.LIST_ROW_HEIGHT + 2);
Label placeholder = new AutoTooltipLabel(Res.get("setting.preferences.noFiat"));
placeholder.setWrapText(true);
fiatCurrenciesListView.setPlaceholder(placeholder);
fiatCurrenciesListView.setCellFactory(new Callback<>() {
@Override
public ListCell<FiatCurrency> call(ListView<FiatCurrency> list) {
return new ListCell<>() {
final Label label = new AutoTooltipLabel();
final ImageView icon = ImageUtil.getImageViewById(ImageUtil.REMOVE_ICON);
final Button removeButton = new AutoTooltipButton("", icon);
final AnchorPane pane = new AnchorPane(label, removeButton);
{
label.setLayoutY(5);
removeButton.setId("icon-button");
AnchorPane.setRightAnchor(removeButton, -30d);
}
@Override
public void updateItem(final FiatCurrency item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
label.setText(item.getNameAndCode());
removeButton.setOnAction(e -> {
if (item.equals(preferences.getPreferredTradeCurrency())) {
new Popup().warning(Res.get("setting.preferences.cannotRemovePrefCurrency")).show();
} else {
preferences.removeFiatCurrency(item);
if (!allFiatCurrencies.contains(item)) {
allFiatCurrencies.add(item);
allFiatCurrencies.sort(TradeCurrency::compareTo);
}
}
});
setGraphic(pane);
} else {
setGraphic(null);
removeButton.setOnAction(null);
}
}
};
}
});
Tuple3<Label, ListView<CryptoCurrency>, VBox> cryptoCurrenciesTuple = addTopLabelListView(root,
displayCurrenciesGridRowIndex, Res.get("setting.preferences.displayAltcoins"));
GridPane.setColumnIndex(cryptoCurrenciesTuple.third, 3);
GridPane.setRowSpan(cryptoCurrenciesTuple.third, listRowSpan);
GridPane.setValignment(cryptoCurrenciesTuple.third, VPos.TOP);
GridPane.setMargin(cryptoCurrenciesTuple.third, new Insets(0, 0, 0, 20));
cryptoCurrenciesListView = cryptoCurrenciesTuple.second;
cryptoCurrenciesListView.setMinHeight(9 * Layout.LIST_ROW_HEIGHT + 2);
cryptoCurrenciesListView.setPrefHeight(10 * Layout.LIST_ROW_HEIGHT + 2);
placeholder = new AutoTooltipLabel(Res.get("setting.preferences.noAltcoins"));
placeholder.setWrapText(true);
cryptoCurrenciesListView.setPlaceholder(placeholder);
cryptoCurrenciesListView.setCellFactory(new Callback<>() {
@Override
public ListCell<CryptoCurrency> call(ListView<CryptoCurrency> list) {
return new ListCell<>() {
final Label label = new AutoTooltipLabel();
final ImageView icon = ImageUtil.getImageViewById(ImageUtil.REMOVE_ICON);
final Button removeButton = new AutoTooltipButton("", icon);
final AnchorPane pane = new AnchorPane(label, removeButton);
{
label.setLayoutY(5);
removeButton.setId("icon-button");
AnchorPane.setRightAnchor(removeButton, -30d);
}
@Override
public void updateItem(final CryptoCurrency item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
label.setText(item.getNameAndCode());
removeButton.setOnAction(e -> {
if (item.equals(preferences.getPreferredTradeCurrency())) {
new Popup().warning(Res.get("setting.preferences.cannotRemovePrefCurrency")).show();
} else {
preferences.removeCryptoCurrency(item);
if (!allCryptoCurrencies.contains(item)) {
allCryptoCurrencies.add(item);
allCryptoCurrencies.sort(TradeCurrency::compareTo);
}
}
});
setGraphic(pane);
} else {
setGraphic(null);
removeButton.setOnAction(null);
}
}
};
}
});
fiatCurrenciesComboBox = addComboBox(root, displayCurrenciesGridRowIndex + listRowSpan);
GridPane.setColumnIndex(fiatCurrenciesComboBox, 2);
GridPane.setValignment(fiatCurrenciesComboBox, VPos.TOP);
fiatCurrenciesComboBox.setPromptText(Res.get("setting.preferences.addFiat"));
fiatCurrenciesComboBox.setButtonCell(new ListCell<>() {
@Override
protected void updateItem(final FiatCurrency item, boolean empty) {
super.updateItem(item, empty);
this.setVisible(item != null || !empty);
if (empty || item == null) {
setText(Res.get("setting.preferences.addFiat"));
} else {
setText(item.getNameAndCode());
}
}
});
fiatCurrenciesComboBox.setConverter(new StringConverter<>() {
@Override
public String toString(FiatCurrency tradeCurrency) {
return tradeCurrency.getNameAndCode();
}
@Override
public FiatCurrency fromString(String s) {
return null;
}
});
cryptoCurrenciesComboBox = addComboBox(root, displayCurrenciesGridRowIndex + listRowSpan);
GridPane.setColumnIndex(cryptoCurrenciesComboBox, 3);
GridPane.setValignment(cryptoCurrenciesComboBox, VPos.TOP);
GridPane.setMargin(cryptoCurrenciesComboBox, new Insets(Layout.FLOATING_LABEL_DISTANCE,
0, 0, 20));
cryptoCurrenciesComboBox.setPromptText(Res.get("setting.preferences.addAltcoin"));
cryptoCurrenciesComboBox.setButtonCell(new ListCell<>() {
@Override
protected void updateItem(final CryptoCurrency item, boolean empty) {
super.updateItem(item, empty);
this.setVisible(item != null || !empty);
if (empty || item == null) {
setText(Res.get("setting.preferences.addAltcoin"));
} else {
setText(item.getNameAndCode());
}
}
});
cryptoCurrenciesComboBox.setConverter(new StringConverter<>() {
@Override
public String toString(CryptoCurrency tradeCurrency) {
return tradeCurrency.getNameAndCode();
}
@Override
public CryptoCurrency fromString(String s) {
return null;
}
});
displayCurrenciesGridRowIndex += listRowSpan;
}
private void initializeDisplayOptions() {
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 7, Res.get("setting.preferences.displayOptions"), Layout.GROUP_DISTANCE);
GridPane.setColumnSpan(titledGroupBg, 1);
showOwnOffersInOfferBook = addSlideToggleButton(root, gridRow, Res.get("setting.preferences.showOwnOffers"), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
useAnimations = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.useAnimations"));
useDarkMode = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.useDarkMode"));
sortMarketCurrenciesNumerically = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.sortWithNumOffers"));
hideNonAccountPaymentMethodsToggle = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.onlyShowPaymentMethodsFromAccount"));
denyApiTakerToggle = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.denyApiTaker"));
notifyOnPreReleaseToggle = addSlideToggleButton(root, ++gridRow, Res.get("setting.preferences.notifyOnPreRelease"));
resetDontShowAgainButton = addButton(root, ++gridRow, Res.get("setting.preferences.resetAllFlags"), 0);
resetDontShowAgainButton.getStyleClass().add("compact-button");
resetDontShowAgainButton.setMaxWidth(Double.MAX_VALUE);
GridPane.setHgrow(resetDontShowAgainButton, Priority.ALWAYS);
GridPane.setColumnIndex(resetDontShowAgainButton, 0);
}
private void initializeAutoConfirmOptions() {
GridPane autoConfirmGridPane = new GridPane();
GridPane.setHgrow(autoConfirmGridPane, Priority.ALWAYS);
root.add(autoConfirmGridPane, 2, displayCurrenciesGridRowIndex, 2, 10);
addTitledGroupBg(autoConfirmGridPane, 0, 4, Res.get("setting.preferences.autoConfirmXMR"), 0);
int localRowIndex = 0;
autoConfirmXmrToggle = addSlideToggleButton(autoConfirmGridPane, localRowIndex, Res.get("setting.preferences.autoConfirmEnabled"), Layout.FIRST_ROW_DISTANCE);
autoConfRequiredConfirmationsTf = addInputTextField(autoConfirmGridPane, ++localRowIndex, Res.get("setting.preferences.autoConfirmRequiredConfirmations"));
autoConfRequiredConfirmationsTf.setValidator(new IntegerValidator(1, DevEnv.isDevMode() ? 100000000 : 1000));
autoConfTradeLimitTf = addInputTextField(autoConfirmGridPane, ++localRowIndex, Res.get("setting.preferences.autoConfirmMaxTradeSize"));
autoConfTradeLimitTf.setValidator(new XmrValidator());
autoConfServiceAddressTf = addInputTextField(autoConfirmGridPane, ++localRowIndex, Res.get("setting.preferences.autoConfirmServiceAddresses"));
GridPane.setHgrow(autoConfServiceAddressTf, Priority.ALWAYS);
displayCurrenciesGridRowIndex += 4;
autoConfServiceAddressListener = (observable, oldValue, newValue) -> {
if (!newValue.equals(oldValue)) {
RegexValidator onionRegex = RegexValidatorFactory.onionAddressRegexValidator();
RegexValidator localhostRegex = RegexValidatorFactory.localhostAddressRegexValidator();
RegexValidator localnetRegex = RegexValidatorFactory.localnetAddressRegexValidator();
List<String> serviceAddressesRaw = Arrays.asList(StringUtils.deleteWhitespace(newValue).split(","));
// revert to default service providers when user empties the list
if (serviceAddressesRaw.size() == 1 && serviceAddressesRaw.get(0).isEmpty()) {
serviceAddressesRaw = preferences.getDefaultXmrTxProofServices();
}
// we must always communicate with XMR explorer API securely
// if *.onion hostname, we use Tor normally
// if localhost, LAN address, or *.local FQDN we use HTTP without Tor
// otherwise we enforce https:// for any clearnet FQDN hostname
List<String> serviceAddressesParsed = new ArrayList<String>();
serviceAddressesRaw.forEach((addr) -> {
addr = addr.replaceAll("http://", "").replaceAll("https://", "");
if (onionRegex.validate(addr).isValid) {
log.info("Using Tor for onion hostname: {}", addr);
serviceAddressesParsed.add(addr);
} else if (localhostRegex.validate(addr).isValid) {
log.info("Using HTTP without Tor for Loopback address: {}", addr);
serviceAddressesParsed.add("http://" + addr);
} else if (localnetRegex.validate(addr).isValid) {
log.info("Using HTTP without Tor for LAN address: {}", addr);
serviceAddressesParsed.add("http://" + addr);
} else {
log.info("Using HTTPS with Tor for Clearnet address: {}", addr);
serviceAddressesParsed.add("https://" + addr);
}
});
preferences.setAutoConfServiceAddresses("XMR", serviceAddressesParsed);
}
};
autoConfTradeLimitListener = (observable, oldValue, newValue) -> {
if (!newValue.equals(oldValue) && autoConfTradeLimitTf.getValidator().validate(newValue).isValid) {
BigInteger amount = HavenoUtils.parseXmr(newValue);
preferences.setAutoConfTradeLimit("XMR", amount.longValueExact());
}
};
autoConfServiceAddressFocusOutListener = (observable, oldValue, newValue) -> {
if (oldValue && !newValue) {
log.info("Service address focus out, check and re-display default option");
if (autoConfServiceAddressTf.getText().isEmpty()) {
preferences.findAutoConfirmSettings("XMR").ifPresent(autoConfirmSettings -> {
List<String> serviceAddresses = autoConfirmSettings.getServiceAddresses();
autoConfServiceAddressTf.setText(String.join(", ", serviceAddresses));
});
}
}
};
// We use a focus out handler to not update the data during entering text as that might lead to lower than
// intended numbers which could be lead in the worst case to auto completion as number of confirmations is
// reached. E.g. user had value 10 and wants to change it to 15 and deletes the 0, so current value would be 1.
// If the service result just comes in at that moment the service might be considered complete as 1 is at that
// moment used. We read the data just in time to make changes more flexible, otherwise user would need to
// restart to apply changes from the number of confirmations settings.
// Other fields like service addresses and limits are not affected and are taken at service start and cannot be
// changed for already started services.
autoConfRequiredConfirmationsFocusOutListener = (observable, oldValue, newValue) -> {
if (oldValue && !newValue) {
String txt = autoConfRequiredConfirmationsTf.getText();
if (autoConfRequiredConfirmationsTf.getValidator().validate(txt).isValid) {
int requiredConfirmations = Integer.parseInt(txt);
preferences.setAutoConfRequiredConfirmations("XMR", requiredConfirmations);
} else {
preferences.findAutoConfirmSettings("XMR")
.ifPresent(e -> autoConfRequiredConfirmationsTf
.setText(String.valueOf(e.getRequiredConfirmations())));
}
}
};
filterChangeListener = (observable, oldValue, newValue) -> {
autoConfirmGridPane.setDisable(newValue != null && newValue.isDisableAutoConf());
};
autoConfirmGridPane.setDisable(filterManager.getFilter() != null && filterManager.getFilter().isDisableAutoConf());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Activate
///////////////////////////////////////////////////////////////////////////////////////////
private void activateGeneralOptions() {
ignoreTradersListInputTextField.setText(String.join(", ", preferences.getIgnoreTradersList()));
/* referralIdService.getOptionalReferralId().ifPresent(referralId -> referralIdInputTextField.setText(referralId));
referralIdInputTextField.setPromptText(Res.get("setting.preferences.refererId.prompt"));*/
ignoreDustThresholdInputTextField.setText(String.valueOf(preferences.getIgnoreDustThreshold()));
userLanguageComboBox.setItems(languageCodes);
userLanguageComboBox.getSelectionModel().select(preferences.getUserLanguage());
userLanguageComboBox.setConverter(new StringConverter<>() {
@Override
public String toString(String code) {
return LanguageUtil.getDisplayName(code);
}
@Override
public String fromString(String string) {
return null;
}
});
userLanguageComboBox.setOnAction(e -> {
String selectedItem = userLanguageComboBox.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
preferences.setUserLanguage(selectedItem);
new Popup().information(Res.get("settings.preferences.languageChange"))
.closeButtonText(Res.get("shared.ok"))
.show();
if (model.needsSupportLanguageWarning()) {
new Popup().warning(Res.get("settings.preferences.supportLanguageWarning",
model.getMediationLanguages(),
model.getArbitrationLanguages()))
.closeButtonText(Res.get("shared.ok"))
.show();
}
}
});
userCountryComboBox.setItems(countries);
userCountryComboBox.getSelectionModel().select(preferences.getUserCountry());
userCountryComboBox.setConverter(new StringConverter<>() {
@Override
public String toString(Country country) {
return CountryUtil.getNameByCode(country.code);
}
@Override
public Country fromString(String string) {
return null;
}
});
userCountryComboBox.setOnAction(e -> {
Country country = userCountryComboBox.getSelectionModel().getSelectedItem();
if (country != null) {
preferences.setUserCountry(country);
}
});
btcExplorerTextField.setText(preferences.getBlockChainExplorer().name);
deviationInputTextField.setText(FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent()));
deviationInputTextField.textProperty().addListener(deviationListener);
deviationInputTextField.focusedProperty().addListener(deviationFocusedListener);
ignoreTradersListInputTextField.textProperty().addListener(ignoreTradersListListener);
//referralIdInputTextField.textProperty().addListener(referralIdListener);
ignoreDustThresholdInputTextField.textProperty().addListener(ignoreDustThresholdListener);
}
private void activateDisplayCurrencies() {
preferredTradeCurrencyComboBox.setItems(tradeCurrencies);
preferredTradeCurrencyComboBox.getSelectionModel().select(preferences.getPreferredTradeCurrency());
preferredTradeCurrencyComboBox.setVisibleRowCount(12);
preferredTradeCurrencyComboBox.setOnAction(e -> {
TradeCurrency selectedItem = preferredTradeCurrencyComboBox.getSelectionModel().getSelectedItem();
if (selectedItem != null)
preferences.setPreferredTradeCurrency(selectedItem);
});
fiatCurrenciesComboBox.setItems(allFiatCurrencies);
fiatCurrenciesListView.setItems(fiatCurrencies);
fiatCurrenciesComboBox.setOnHiding(e -> {
FiatCurrency selectedItem = fiatCurrenciesComboBox.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
preferences.addFiatCurrency(selectedItem);
if (allFiatCurrencies.contains(selectedItem)) {
UserThread.execute(() -> {
fiatCurrenciesComboBox.getSelectionModel().clearSelection();
allFiatCurrencies.remove(selectedItem);
});
}
}
});
cryptoCurrenciesComboBox.setItems(allCryptoCurrencies);
cryptoCurrenciesListView.setItems(cryptoCurrencies);
cryptoCurrenciesComboBox.setOnHiding(e -> {
CryptoCurrency selectedItem = cryptoCurrenciesComboBox.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
preferences.addCryptoCurrency(selectedItem);
if (allCryptoCurrencies.contains(selectedItem)) {
UserThread.execute(() -> {
cryptoCurrenciesComboBox.getSelectionModel().clearSelection();
allCryptoCurrencies.remove(selectedItem);
});
}
}
});
}
private void activateDisplayPreferences() {
showOwnOffersInOfferBook.setSelected(preferences.isShowOwnOffersInOfferBook());
showOwnOffersInOfferBook.setOnAction(e -> preferences.setShowOwnOffersInOfferBook(showOwnOffersInOfferBook.isSelected()));
useAnimations.setSelected(preferences.isUseAnimations());
useAnimations.setOnAction(e -> preferences.setUseAnimations(useAnimations.isSelected()));
useDarkMode.setSelected(preferences.getCssTheme() == 1);
useDarkMode.setOnAction(e -> preferences.setCssTheme(useDarkMode.isSelected()));
sortMarketCurrenciesNumerically.setSelected(preferences.isSortMarketCurrenciesNumerically());
sortMarketCurrenciesNumerically.setOnAction(e -> preferences.setSortMarketCurrenciesNumerically(sortMarketCurrenciesNumerically.isSelected()));
boolean disableToggle = false;
if (user.getPaymentAccounts() != null) {
Set<PaymentMethod> supportedPaymentMethods = user.getPaymentAccounts().stream()
.map(PaymentAccount::getPaymentMethod).collect(Collectors.toSet());
disableToggle = supportedPaymentMethods.isEmpty();
}
hideNonAccountPaymentMethodsToggle.setSelected(preferences.isHideNonAccountPaymentMethods() && !disableToggle);
hideNonAccountPaymentMethodsToggle.setOnAction(e -> preferences.setHideNonAccountPaymentMethods(hideNonAccountPaymentMethodsToggle.isSelected()));
hideNonAccountPaymentMethodsToggle.setDisable(disableToggle);
denyApiTakerToggle.setSelected(preferences.isDenyApiTaker());
denyApiTakerToggle.setOnAction(e -> preferences.setDenyApiTaker(denyApiTakerToggle.isSelected()));
notifyOnPreReleaseToggle.setSelected(preferences.isNotifyOnPreRelease());
notifyOnPreReleaseToggle.setOnAction(e -> preferences.setNotifyOnPreRelease(notifyOnPreReleaseToggle.isSelected()));
resetDontShowAgainButton.setOnAction(e -> preferences.resetDontShowAgain());
editCustomBtcExplorer.setOnAction(e -> {
EditCustomExplorerWindow urlWindow = new EditCustomExplorerWindow("BTC",
preferences.getBlockChainExplorer(), preferences.getBlockChainExplorers());
urlWindow
.actionButtonText(Res.get("shared.save"))
.onAction(() -> {
preferences.setBlockChainExplorer(urlWindow.getEditedBlockChainExplorer());
btcExplorerTextField.setText(preferences.getBlockChainExplorer().name);
})
.closeButtonText(Res.get("shared.cancel"))
.onClose(urlWindow::hide)
.show();
});
}
private void activateAutoConfirmPreferences() {
preferences.findAutoConfirmSettings("XMR").ifPresent(autoConfirmSettings -> {
autoConfirmXmrToggle.setSelected(autoConfirmSettings.isEnabled());
autoConfRequiredConfirmationsTf.setText(String.valueOf(autoConfirmSettings.getRequiredConfirmations()));
autoConfTradeLimitTf.setText(formatter.formatCoin(Coin.valueOf(autoConfirmSettings.getTradeLimit())));
autoConfServiceAddressTf.setText(String.join(", ", autoConfirmSettings.getServiceAddresses()));
autoConfRequiredConfirmationsTf.focusedProperty().addListener(autoConfRequiredConfirmationsFocusOutListener);
autoConfTradeLimitTf.textProperty().addListener(autoConfTradeLimitListener);
autoConfServiceAddressTf.textProperty().addListener(autoConfServiceAddressListener);
autoConfServiceAddressTf.focusedProperty().addListener(autoConfServiceAddressFocusOutListener);
autoConfirmXmrToggle.setOnAction(e -> {
preferences.setAutoConfEnabled(autoConfirmSettings.getCurrencyCode(), autoConfirmXmrToggle.isSelected());
});
filterManager.filterProperty().addListener(filterChangeListener);
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// Deactivate
///////////////////////////////////////////////////////////////////////////////////////////
private void deactivateGeneralOptions() {
//selectBaseCurrencyNetworkComboBox.setOnAction(null);
userLanguageComboBox.setOnAction(null);
userCountryComboBox.setOnAction(null);
editCustomBtcExplorer.setOnAction(null);
deviationInputTextField.textProperty().removeListener(deviationListener);
deviationInputTextField.focusedProperty().removeListener(deviationFocusedListener);
ignoreTradersListInputTextField.textProperty().removeListener(ignoreTradersListListener);
//referralIdInputTextField.textProperty().removeListener(referralIdListener);
ignoreDustThresholdInputTextField.textProperty().removeListener(ignoreDustThresholdListener);
}
private void deactivateDisplayCurrencies() {
preferredTradeCurrencyComboBox.setOnAction(null);
}
private void deactivateDisplayPreferences() {
useAnimations.setOnAction(null);
useDarkMode.setOnAction(null);
sortMarketCurrenciesNumerically.setOnAction(null);
hideNonAccountPaymentMethodsToggle.setOnAction(null);
denyApiTakerToggle.setOnAction(null);
notifyOnPreReleaseToggle.setOnAction(null);
showOwnOffersInOfferBook.setOnAction(null);
resetDontShowAgainButton.setOnAction(null);
if (displayStandbyModeFeature) {
avoidStandbyMode.setOnAction(null);
}
}
private void deactivateAutoConfirmPreferences() {
preferences.findAutoConfirmSettings("XMR").ifPresent(autoConfirmSettings -> {
autoConfirmXmrToggle.setOnAction(null);
autoConfTradeLimitTf.textProperty().removeListener(autoConfTradeLimitListener);
autoConfServiceAddressTf.textProperty().removeListener(autoConfServiceAddressListener);
autoConfServiceAddressTf.focusedProperty().removeListener(autoConfServiceAddressFocusOutListener);
autoConfRequiredConfirmationsTf.focusedProperty().removeListener(autoConfRequiredConfirmationsFocusOutListener);
filterManager.filterProperty().removeListener(filterChangeListener);
});
}
}