mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Added all resources for MainView
This commit is contained in:
parent
aae59466d4
commit
1470fbb444
@ -40,9 +40,6 @@ public class Res {
|
||||
}
|
||||
|
||||
public static String get(String key) {
|
||||
if (key == null)
|
||||
return "";
|
||||
|
||||
try {
|
||||
return Res.getResourceBundle().getString(key);
|
||||
} catch (MissingResourceException e) {
|
||||
|
@ -19,6 +19,7 @@ package io.bitsquare.payment;
|
||||
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.common.persistance.Persistable;
|
||||
import io.bitsquare.locale.Res;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
@ -148,7 +149,7 @@ public final class PaymentMethod implements Persistable, Comparable {
|
||||
if (paymentMethodOptional.isPresent())
|
||||
return paymentMethodOptional.get();
|
||||
else
|
||||
return new PaymentMethod("N/A", 1, DAY, Coin.parseCoin("0"));
|
||||
return new PaymentMethod(Res.get("shared.na"), 1, DAY, Coin.parseCoin("0"));
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -38,7 +38,6 @@ import io.bitsquare.gui.common.view.View;
|
||||
import io.bitsquare.gui.common.view.ViewLoader;
|
||||
import io.bitsquare.gui.common.view.guice.InjectorViewFactory;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.MainViewModel;
|
||||
import io.bitsquare.gui.main.debug.DebugView;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.overlays.windows.*;
|
||||
@ -257,20 +256,13 @@ public class BitsquareApp extends Application {
|
||||
String osArchitecture = Utilities.getOSArchitecture();
|
||||
// We don't force a shutdown as the osArchitecture might in strange cases return a wrong value.
|
||||
// Needs at least more testing on different machines...
|
||||
new Popup<>().warning(Res.get("popup.warning.wrongVersion"))
|
||||
new Popup<>().warning(Res.get("popup.warning.wrongVersion", osArchitecture, Utilities.getJVMArchitecture(), osArchitecture))
|
||||
.show();
|
||||
}
|
||||
|
||||
UserThread.runPeriodically(() -> Profiler.printSystemLoad(log), LOG_MEMORY_PERIOD_MIN, TimeUnit.MINUTES);
|
||||
|
||||
} catch (
|
||||
Throwable throwable
|
||||
)
|
||||
|
||||
{
|
||||
} catch (Throwable throwable) {
|
||||
showErrorPopup(throwable, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void showSendAlertMessagePopup() {
|
||||
@ -327,7 +319,7 @@ public class BitsquareApp extends Application {
|
||||
//TODO check if Dialogs is still wanted?
|
||||
Dialogs.create()
|
||||
.owner(primaryStage)
|
||||
.title(Res.get("popup.error.title"))
|
||||
.title(Res.get("shared.error"))
|
||||
.message(throwable.toString())
|
||||
.masthead(Res.get("popup.error.fatalStartupException"))
|
||||
.showError();
|
||||
@ -379,14 +371,16 @@ public class BitsquareApp extends Application {
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@SuppressWarnings("CodeBlock2Expr")
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!shutDownRequested) {
|
||||
new Popup().headLine(Res.get("popup.shutDownInProgress.headline"))
|
||||
.backgroundInfo(Res.get("popup.shutDownInProgress.message"))
|
||||
.backgroundInfo(Res.get("popup.shutDownInProgress.msg"))
|
||||
.hideCloseButton()
|
||||
.useAnimation(false)
|
||||
.show();
|
||||
//noinspection CodeBlock2Expr
|
||||
UserThread.runAfter(() -> {
|
||||
gracefulShutDown(() -> {
|
||||
log.debug("App shutdown complete");
|
||||
@ -402,8 +396,8 @@ public class BitsquareApp extends Application {
|
||||
try {
|
||||
if (injector != null) {
|
||||
injector.getInstance(ArbitratorManager.class).shutDown();
|
||||
injector.getInstance(MainViewModel.class).shutDown();
|
||||
injector.getInstance(TradeManager.class).shutDown();
|
||||
//noinspection CodeBlock2Expr
|
||||
injector.getInstance(OpenOfferManager.class).shutDown(() -> {
|
||||
injector.getInstance(P2PService.class).shutDown(() -> {
|
||||
injector.getInstance(WalletsSetup.class).shutDownComplete.addListener((ov, o, n) -> {
|
||||
|
@ -26,7 +26,6 @@ import io.bitsquare.gui.common.view.CachingViewLoader;
|
||||
import io.bitsquare.gui.common.view.ViewFactory;
|
||||
import io.bitsquare.gui.common.view.ViewLoader;
|
||||
import io.bitsquare.gui.common.view.guice.InjectorViewFactory;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.offer.offerbook.OfferBook;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.BsqFormatter;
|
||||
@ -71,6 +70,6 @@ public class GuiModule extends AppModule {
|
||||
|
||||
bind(Stage.class).toInstance(primaryStage);
|
||||
|
||||
bindConstant().annotatedWith(Names.named(MainView.TITLE_KEY)).to(env.getRequiredProperty(AppOptionKeys.APP_NAME_KEY));
|
||||
bindConstant().annotatedWith(Names.named(AppOptionKeys.APP_NAME_KEY)).to(env.getRequiredProperty(AppOptionKeys.APP_NAME_KEY));
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,10 @@
|
||||
package io.bitsquare.gui.main;
|
||||
|
||||
import io.bitsquare.BitsquareException;
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.app.AppOptionKeys;
|
||||
import io.bitsquare.app.BitsquareEnvironment;
|
||||
import io.bitsquare.app.DevFlags;
|
||||
import io.bitsquare.app.Version;
|
||||
import io.bitsquare.btc.provider.price.PriceFeedService;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
@ -54,7 +56,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.util.List;
|
||||
|
||||
import static javafx.beans.binding.Bindings.createStringBinding;
|
||||
@ -64,8 +65,6 @@ import static javafx.scene.layout.AnchorPane.*;
|
||||
public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainView.class);
|
||||
|
||||
public static final String TITLE_KEY = "viewTitle";
|
||||
|
||||
public static StackPane getRootContainer() {
|
||||
return MainView.rootContainer;
|
||||
}
|
||||
@ -99,7 +98,8 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
private final ViewLoader viewLoader;
|
||||
private final Navigation navigation;
|
||||
private static Transitions transitions;
|
||||
private BSFormatter formatter;
|
||||
private final BitsquareEnvironment environment;
|
||||
private final BSFormatter formatter;
|
||||
private ChangeListener<String> walletServiceErrorMsgListener;
|
||||
private ChangeListener<String> btcSyncIconIdListener;
|
||||
private ChangeListener<String> splashP2PNetworkErrorMsgListener;
|
||||
@ -113,12 +113,14 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
private Popup<?> p2PNetworkWarnMsgPopup, btcNetworkWarnMsgPopup;
|
||||
private static StackPane rootContainer;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@Inject
|
||||
public MainView(MainViewModel model, CachingViewLoader viewLoader, Navigation navigation, Transitions transitions,
|
||||
BSFormatter formatter, @Named(MainView.TITLE_KEY) String title) {
|
||||
BitsquareEnvironment environment, BSFormatter formatter) {
|
||||
super(model);
|
||||
this.viewLoader = viewLoader;
|
||||
this.navigation = navigation;
|
||||
this.environment = environment;
|
||||
this.formatter = formatter;
|
||||
MainView.transitions = transitions;
|
||||
}
|
||||
@ -151,12 +153,12 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
priceComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
||||
model.setPriceFeedComboBoxItem(newValue);
|
||||
});
|
||||
ChangeListener<PriceFeedComboBoxItem> selectedPriceFeedItemListender = (observable, oldValue, newValue) -> {
|
||||
ChangeListener<PriceFeedComboBoxItem> selectedPriceFeedItemListener = (observable, oldValue, newValue) -> {
|
||||
if (newValue != null)
|
||||
priceComboBox.getSelectionModel().select(newValue);
|
||||
|
||||
};
|
||||
model.selectedPriceFeedComboBoxItemProperty.addListener(selectedPriceFeedItemListender);
|
||||
model.selectedPriceFeedComboBoxItemProperty.addListener(selectedPriceFeedItemListener);
|
||||
priceComboBox.setItems(model.priceFeedComboBoxItems);
|
||||
|
||||
marketPriceBox.second.textProperty().bind(createStringBinding(
|
||||
@ -239,17 +241,11 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
if (!persistedFilesCorrupted.isEmpty()) {
|
||||
if (persistedFilesCorrupted.size() > 1 || !persistedFilesCorrupted.get(0).equals("Navigation")) {
|
||||
// show warning that some files has been corrupted
|
||||
new Popup().warning("We detected incompatible data base files!\n\n" +
|
||||
"Those database file(s) are not compatible with our current code base:" +
|
||||
"\n" + persistedFilesCorrupted.toString() +
|
||||
"\n\nWe made a backup of the corrupted file(s) and applied the default values to a new " +
|
||||
"database version." +
|
||||
"\n\nThe backup is located at:\n[you local app data directory]/db/backup_of_corrupted_data.\n\n" +
|
||||
"Please check if you have the latest version of Bitsquare installed.\n" +
|
||||
"You can download it at:\nhttps://github.com/bitsquare/bitsquare/releases\n\n" +
|
||||
"Please restart the application.")
|
||||
.closeButtonText(Res.get("shared.shutDown"))
|
||||
.onClose(BitsquareApp.shutDownHandler::run)
|
||||
new Popup()
|
||||
.warning(Res.get("popup.warning.incompatibleDB",
|
||||
persistedFilesCorrupted.toString(),
|
||||
environment.getProperty(AppOptionKeys.APP_DATA_DIR_KEY)))
|
||||
.useShutDownButton()
|
||||
.show();
|
||||
} else {
|
||||
log.debug("We detected incompatible data base file for Navigation. That is a minor issue happening with refactoring of UI classes " +
|
||||
@ -328,9 +324,15 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
btcAverageIconButton.visibleProperty().bind(model.isFiatCurrencyPriceFeedSelected);
|
||||
btcAverageIconButton.managedProperty().bind(model.isFiatCurrencyPriceFeedSelected);
|
||||
btcAverageIconButton.setOnMouseEntered(e -> {
|
||||
btcAverageIconButton.setTooltip(new Tooltip("Market price is provided by https://bitcoinaverage.com\n" +
|
||||
"Last update: " + formatter.formatTime(model.priceFeedService.getLastRequestTimeStampBtcAverage())));
|
||||
});
|
||||
String res = Res.get("mainView.marketPrice.tooltip",
|
||||
"https://bitcoinaverage.com",
|
||||
"",
|
||||
formatter.formatTime(model.priceFeedService.getLastRequestTimeStampBtcAverage()));
|
||||
btcAverageIconButton.setTooltip(
|
||||
new Tooltip(res)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
final ImageView poloniexIcon = new ImageView();
|
||||
poloniexIcon.setId("poloniex");
|
||||
@ -345,9 +347,14 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
poloniexIconButton.visibleProperty().bind(model.isCryptoCurrencyPriceFeedSelected);
|
||||
poloniexIconButton.managedProperty().bind(model.isCryptoCurrencyPriceFeedSelected);
|
||||
poloniexIconButton.setOnMouseEntered(e -> {
|
||||
poloniexIconButton.setTooltip(new Tooltip("Market price is provided by https://poloniex.com.\n" +
|
||||
"If the altcoin is not available at Poloniex we use https://coinmarketcap.com\n" +
|
||||
"Last update: " + formatter.formatTime(model.priceFeedService.getLastRequestTimeStampPoloniex())));
|
||||
String altcoinExtra = Res.get("mainView.marketPrice.tooltip.altcoinExtra");
|
||||
String res = Res.get("mainView.marketPrice.tooltip",
|
||||
"https://poloniex.com",
|
||||
altcoinExtra,
|
||||
formatter.formatTime(model.priceFeedService.getLastRequestTimeStampPoloniex()));
|
||||
poloniexIconButton.setTooltip(
|
||||
new Tooltip(res)
|
||||
);
|
||||
});
|
||||
Pane spacer = new Pane();
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
@ -379,9 +386,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
// createBitcoinInfoBox
|
||||
btcSplashInfo = new Label();
|
||||
btcSplashInfo.textProperty().bind(model.btcInfo);
|
||||
walletServiceErrorMsgListener = (ov, oldValue, newValue) -> {
|
||||
btcSplashInfo.setId("splash-error-state-msg");
|
||||
};
|
||||
walletServiceErrorMsgListener = (ov, oldValue, newValue) -> btcSplashInfo.setId("splash-error-state-msg");
|
||||
model.walletServiceErrorMsg.addListener(walletServiceErrorMsgListener);
|
||||
|
||||
btcSyncIndicator = new ProgressBar();
|
||||
@ -526,7 +531,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
versionLabel.setId("footer-pane");
|
||||
versionLabel.setTextAlignment(TextAlignment.CENTER);
|
||||
versionLabel.setAlignment(Pos.BASELINE_CENTER);
|
||||
versionLabel.setText(model.version);
|
||||
versionLabel.setText("v" + Version.VERSION);
|
||||
root.widthProperty().addListener((ov, oldValue, newValue) -> {
|
||||
versionLabel.setLayoutX(((double) newValue - versionLabel.getWidth()) / 2);
|
||||
});
|
||||
|
@ -22,7 +22,6 @@ import io.bitsquare.alert.Alert;
|
||||
import io.bitsquare.alert.AlertManager;
|
||||
import io.bitsquare.alert.PrivateNotification;
|
||||
import io.bitsquare.alert.PrivateNotificationManager;
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.app.DevFlags;
|
||||
import io.bitsquare.app.Log;
|
||||
import io.bitsquare.app.Version;
|
||||
@ -44,19 +43,17 @@ import io.bitsquare.common.crypto.*;
|
||||
import io.bitsquare.dao.DaoManager;
|
||||
import io.bitsquare.dao.blockchain.BsqBlockchainException;
|
||||
import io.bitsquare.filter.FilterManager;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.ViewModel;
|
||||
import io.bitsquare.gui.components.BalanceWithConfirmationTextField;
|
||||
import io.bitsquare.gui.components.TxIdTextField;
|
||||
import io.bitsquare.gui.main.overlays.notifications.NotificationCenter;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.overlays.windows.AddBitcoinNodesWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.DisplayAlertMessageWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.TacWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.Res;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.P2PServiceListener;
|
||||
@ -110,20 +107,19 @@ public class MainViewModel implements ViewModel {
|
||||
private final Preferences preferences;
|
||||
private final AlertManager alertManager;
|
||||
private final PrivateNotificationManager privateNotificationManager;
|
||||
@SuppressWarnings("unused")
|
||||
private final FilterManager filterManager;
|
||||
private final WalletPasswordWindow walletPasswordWindow;
|
||||
private final AddBitcoinNodesWindow addBitcoinNodesWindow;
|
||||
private final NotificationCenter notificationCenter;
|
||||
private final TacWindow tacWindow;
|
||||
private final Clock clock;
|
||||
private final FeeService feeService;
|
||||
private final DaoManager daoManager;
|
||||
private final KeyRing keyRing;
|
||||
private final Navigation navigation;
|
||||
private final BSFormatter formatter;
|
||||
|
||||
// BTC network
|
||||
final StringProperty btcInfo = new SimpleStringProperty("Initializing");
|
||||
final StringProperty btcInfo = new SimpleStringProperty(Res.get("mainView.footer.btcInfo.initializing"));
|
||||
final DoubleProperty btcSyncProgress = new SimpleDoubleProperty(DevFlags.STRESS_TEST_MODE ? 0 : -1);
|
||||
final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
|
||||
final StringProperty btcSplashSyncIconId = new SimpleStringProperty();
|
||||
@ -137,7 +133,7 @@ public class MainViewModel implements ViewModel {
|
||||
final StringProperty lockedBalance = new SimpleStringProperty();
|
||||
private MonadicBinding<String> btcInfoBinding;
|
||||
|
||||
private final StringProperty marketPrice = new SimpleStringProperty("N/A");
|
||||
private final StringProperty marketPrice = new SimpleStringProperty(Res.get("shared.na"));
|
||||
|
||||
// P2P network
|
||||
final StringProperty p2PNetworkInfo = new SimpleStringProperty();
|
||||
@ -146,10 +142,6 @@ public class MainViewModel implements ViewModel {
|
||||
final StringProperty p2pNetworkWarnMsg = new SimpleStringProperty();
|
||||
final StringProperty p2PNetworkIconId = new SimpleStringProperty();
|
||||
final BooleanProperty bootstrapComplete = new SimpleBooleanProperty();
|
||||
|
||||
// software update
|
||||
final String version = "v" + Version.VERSION;
|
||||
|
||||
final BooleanProperty showAppScreen = new SimpleBooleanProperty();
|
||||
final StringProperty numPendingTradesAsString = new SimpleStringProperty();
|
||||
final BooleanProperty showPendingTradesNotification = new SimpleBooleanProperty();
|
||||
@ -168,6 +160,7 @@ public class MainViewModel implements ViewModel {
|
||||
private final Map<String, Subscription> disputeIsClosedSubscriptionsMap = new HashMap<>();
|
||||
final ObservableList<PriceFeedComboBoxItem> priceFeedComboBoxItems = FXCollections.observableArrayList();
|
||||
private MonadicBinding<String> marketPriceBinding;
|
||||
@SuppressWarnings("unused")
|
||||
private Subscription priceFeedAllLoadedSubscription;
|
||||
private Popup startupTimeoutPopup;
|
||||
private BooleanProperty p2pNetWorkReady;
|
||||
@ -178,16 +171,17 @@ public class MainViewModel implements ViewModel {
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@Inject
|
||||
public MainViewModel(WalletsManager walletsManager, WalletsSetup walletsSetup,
|
||||
BtcWalletService btcWalletService, PriceFeedService priceFeedService,
|
||||
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
|
||||
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
|
||||
User user, AlertManager alertManager, PrivateNotificationManager privateNotificationManager,
|
||||
FilterManager filterManager, WalletPasswordWindow walletPasswordWindow, AddBitcoinNodesWindow addBitcoinNodesWindow,
|
||||
FilterManager filterManager, WalletPasswordWindow walletPasswordWindow,
|
||||
NotificationCenter notificationCenter, TacWindow tacWindow, Clock clock, FeeService feeService,
|
||||
DaoManager daoManager,
|
||||
KeyRing keyRing, Navigation navigation,
|
||||
KeyRing keyRing,
|
||||
BSFormatter formatter) {
|
||||
this.walletsManager = walletsManager;
|
||||
this.walletsSetup = walletsSetup;
|
||||
@ -202,20 +196,18 @@ public class MainViewModel implements ViewModel {
|
||||
this.preferences = preferences;
|
||||
this.alertManager = alertManager;
|
||||
this.privateNotificationManager = privateNotificationManager;
|
||||
this.filterManager = filterManager; // Reference so it's initialized and eventlistener gets registered
|
||||
this.filterManager = filterManager; // Reference so it's initialized and eventListener gets registered
|
||||
this.walletPasswordWindow = walletPasswordWindow;
|
||||
this.addBitcoinNodesWindow = addBitcoinNodesWindow;
|
||||
this.notificationCenter = notificationCenter;
|
||||
this.tacWindow = tacWindow;
|
||||
this.clock = clock;
|
||||
this.feeService = feeService;
|
||||
this.daoManager = daoManager;
|
||||
this.keyRing = keyRing;
|
||||
this.navigation = navigation;
|
||||
this.formatter = formatter;
|
||||
|
||||
btcNetworkAsString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork()) +
|
||||
(preferences.getUseTorForBitcoinJ() ? " (using Tor)" : "");
|
||||
btcNetworkAsString = Res.get(preferences.getBitcoinNetwork().name()) +
|
||||
(preferences.getUseTorForBitcoinJ() ? (" " + Res.get("mainView.footer.usingTor")) : "");
|
||||
|
||||
TxIdTextField.setPreferences(preferences);
|
||||
|
||||
@ -265,29 +257,19 @@ public class MainViewModel implements ViewModel {
|
||||
MainView.blur();
|
||||
String details;
|
||||
if (!walletInitialized.get()) {
|
||||
details = "You still did not get connected to the bitcoin network.\n" +
|
||||
"If you use Tor for Bitcoin it might be that you got an unstable Tor path.\n" +
|
||||
"You can wait longer or try to restart.";
|
||||
details = Res.get("popup.warning.cannotConnectAtStartup", Res.get("shared.bitcoin"));
|
||||
} else if (!p2pNetWorkReady.get()) {
|
||||
details = "You still did not get connected to the P2P network.\n" +
|
||||
"That can happen sometimes when you got an unstable Tor path.\n" +
|
||||
"You can wait longer or try to restart.";
|
||||
details = Res.get("popup.warning.cannotConnectAtStartup", Res.get("shared.P2P"));
|
||||
} else {
|
||||
log.error("Startup timeout with unknown problem.");
|
||||
details = "There is an unknown problem at startup.\n" +
|
||||
"Please restart and if the problem continues file a bug report.";
|
||||
details = Res.get("popup.warning.unknownProblemAtStartup");
|
||||
}
|
||||
startupTimeoutPopup = new Popup();
|
||||
startupTimeoutPopup.warning("The application could not startup after 4 minutes.\n\n" +
|
||||
details)
|
||||
.actionButtonText("Shut down")
|
||||
.onAction(BitsquareApp.shutDownHandler::run)
|
||||
startupTimeoutPopup.warning(Res.get("popup.warning.startupFailed.timeout", details))
|
||||
.useShutDownButton()
|
||||
.show();
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Initialisation
|
||||
@ -307,12 +289,13 @@ public class MainViewModel implements ViewModel {
|
||||
if (warning != null && peers == 0) {
|
||||
result = warning;
|
||||
} else {
|
||||
if (dataReceived && hiddenService)
|
||||
result = "P2P network peers: " + numPeers;
|
||||
else if (peers == 0)
|
||||
String p2pInfo = Res.get("mainView.footer.p2pInfo", numPeers);
|
||||
if (dataReceived && hiddenService) {
|
||||
result = p2pInfo;
|
||||
} else if (peers == 0)
|
||||
result = state;
|
||||
else
|
||||
result = state + " / P2P network peers: " + numPeers;
|
||||
result = state + " / " + p2pInfo;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
@ -320,7 +303,7 @@ public class MainViewModel implements ViewModel {
|
||||
p2PNetworkInfo.set(newValue);
|
||||
});
|
||||
|
||||
bootstrapState.set("Connecting to Tor network...");
|
||||
bootstrapState.set(Res.get("mainView.bootstrapState.connectionToTorNetwork"));
|
||||
|
||||
p2PService.getNetworkNode().addConnectionListener(new ConnectionListener() {
|
||||
@Override
|
||||
@ -335,16 +318,6 @@ public class MainViewModel implements ViewModel {
|
||||
closeConnectionReason == CloseConnectionReason.RULE_VIOLATION) {
|
||||
log.warn("RULE_VIOLATION onDisconnect closeConnectionReason=" + closeConnectionReason);
|
||||
log.warn("RULE_VIOLATION onDisconnect connection=" + connection);
|
||||
//TODO
|
||||
/* new Popup()
|
||||
.warning("You got disconnected from a seed node.\n\n" +
|
||||
"Reason for getting disconnected: " + connection.getRuleViolation().name() + "\n\n" +
|
||||
"It might be that your installed version is not compatible with " +
|
||||
"the network.\n\n" +
|
||||
"Please check if you run the latest software version.\n" +
|
||||
"You can download the latest version of Bitsquare at:\n" +
|
||||
"https://github.com/bitsquare/bitsquare/releases")
|
||||
.show();*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,7 +330,7 @@ public class MainViewModel implements ViewModel {
|
||||
p2PService.start(new P2PServiceListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
bootstrapState.set("Tor node created");
|
||||
bootstrapState.set(Res.get("mainView.bootstrapState.torNodeCreated"));
|
||||
p2PNetworkIconId.set("image-connection-tor");
|
||||
|
||||
if (preferences.getUseTorForBitcoinJ())
|
||||
@ -367,13 +340,13 @@ public class MainViewModel implements ViewModel {
|
||||
@Override
|
||||
public void onHiddenServicePublished() {
|
||||
hiddenServicePublished.set(true);
|
||||
bootstrapState.set("Hidden Service published");
|
||||
bootstrapState.set(Res.get("mainView.bootstrapState.hiddenServicePublished"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
initialP2PNetworkDataReceived.set(true);
|
||||
bootstrapState.set("Initial data received");
|
||||
bootstrapState.set(Res.get("mainView.bootstrapState.initialDataReceived"));
|
||||
splashP2PNetworkAnimationVisible.set(false);
|
||||
p2pNetworkInitialized.set(true);
|
||||
}
|
||||
@ -381,7 +354,7 @@ public class MainViewModel implements ViewModel {
|
||||
@Override
|
||||
public void onNoSeedNodeAvailable() {
|
||||
if (p2PService.getNumConnectedPeers().get() == 0)
|
||||
bootstrapWarning.set("No seed nodes available");
|
||||
bootstrapWarning.set(Res.get("mainView.bootstrapWarning.noSeedNodesAvailable"));
|
||||
else
|
||||
bootstrapWarning.set(null);
|
||||
|
||||
@ -392,9 +365,8 @@ public class MainViewModel implements ViewModel {
|
||||
@Override
|
||||
public void onNoPeersAvailable() {
|
||||
if (p2PService.getNumConnectedPeers().get() == 0) {
|
||||
p2pNetworkWarnMsg.set("There are no seed nodes or persisted peers available for requesting data.\n" +
|
||||
"Please check your internet connection or try to restart the application.");
|
||||
bootstrapWarning.set("No seed nodes and peers available");
|
||||
p2pNetworkWarnMsg.set(Res.get("mainView.p2pNetworkWarnMsg.noNodesAvailable"));
|
||||
bootstrapWarning.set(Res.get("mainView.bootstrapWarning.noNodesAvailable"));
|
||||
p2pNetworkLabelId.set("splash-error-state-msg");
|
||||
} else {
|
||||
bootstrapWarning.set(null);
|
||||
@ -412,11 +384,9 @@ public class MainViewModel implements ViewModel {
|
||||
|
||||
@Override
|
||||
public void onSetupFailed(Throwable throwable) {
|
||||
p2pNetworkWarnMsg.set("Connecting to the P2P network failed (reported error: "
|
||||
+ throwable.getMessage() + ").\n" +
|
||||
"Please check your internet connection or try to restart the application.");
|
||||
p2pNetworkWarnMsg.set(Res.get("mainView.p2pNetworkWarnMsg.connectionToP2PFailed", throwable.getMessage()));
|
||||
splashP2PNetworkAnimationVisible.set(false);
|
||||
bootstrapWarning.set("Bootstrapping to P2P network failed");
|
||||
bootstrapWarning.set(Res.get("mainView.bootstrapWarning.bootstrappingToP2PFailed"));
|
||||
p2pNetworkLabelId.set("splash-error-state-msg");
|
||||
}
|
||||
});
|
||||
@ -442,36 +412,44 @@ public class MainViewModel implements ViewModel {
|
||||
if (exception == null) {
|
||||
double percentage = (double) downloadPercentage;
|
||||
int peers = (int) numPeers;
|
||||
String numPeersString = "Bitcoin network peers: " + peers;
|
||||
|
||||
btcSyncProgress.set(percentage);
|
||||
if (percentage == 1) {
|
||||
result = numPeersString + " / synchronized with " + btcNetworkAsString;
|
||||
result = Res.get("mainView.footer.btcInfo",
|
||||
peers,
|
||||
Res.get("mainView.footer.btcInfo.synchronizedWith"),
|
||||
btcNetworkAsString);
|
||||
btcSplashSyncIconId.set("image-connection-synced");
|
||||
} else if (percentage > 0.0) {
|
||||
result = numPeersString + " / synchronizing with " + btcNetworkAsString + ": " + formatter.formatToPercentWithSymbol(percentage);
|
||||
result = Res.get("mainView.footer.btcInfo", peers,
|
||||
Res.get("mainView.footer.btcInfo.synchronizedWith"),
|
||||
btcNetworkAsString + ": " + formatter.formatToPercentWithSymbol(percentage));
|
||||
} else {
|
||||
result = numPeersString + " / connecting to " + btcNetworkAsString;
|
||||
result = Res.get("mainView.footer.btcInfo",
|
||||
peers,
|
||||
Res.get("mainView.footer.btcInfo.connectingTo"),
|
||||
btcNetworkAsString);
|
||||
}
|
||||
} else {
|
||||
result = "Bitcoin network peers: " + numBtcPeers + " / connecting to " + btcNetworkAsString + " failed";
|
||||
result = Res.get("mainView.footer.btcInfo",
|
||||
numBtcPeers,
|
||||
Res.get("mainView.footer.btcInfo.connectionFailed"),
|
||||
btcNetworkAsString);
|
||||
if (exception instanceof TimeoutException) {
|
||||
walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout.");
|
||||
walletServiceErrorMsg.set(Res.get("mainView.walletServiceErrorMsg.timeout"));
|
||||
} else if (exception.getCause() instanceof BlockStoreException) {
|
||||
log.error(exception.getMessage());
|
||||
// Ugly, but no other way to cover that specific case
|
||||
if (exception.getMessage().equals("Store file is already locked by another process"))
|
||||
new Popup().warning("Bitsquare is already running. You cannot run two instances of Bitsquare.")
|
||||
.closeButtonText("Shut down")
|
||||
.onClose(BitsquareApp.shutDownHandler::run)
|
||||
if (exception.getMessage().equals("Store file is already locked by another process")) {
|
||||
new Popup().warning(Res.get("popup.warning.startupFailed.twoInstances"))
|
||||
.useShutDownButton()
|
||||
.show();
|
||||
else
|
||||
new Popup().error("Cannot open wallet because of an exception:\n" + exception.getMessage())
|
||||
} else {
|
||||
new Popup().error(Res.get("popup.error.walletException",
|
||||
exception.getMessage()))
|
||||
.show();
|
||||
} else if (exception.getMessage() != null) {
|
||||
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + exception.getMessage());
|
||||
}
|
||||
} else {
|
||||
walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + exception.toString());
|
||||
walletServiceErrorMsg.set(Res.get("mainView.walletServiceErrorMsg.connectionError", exception.toString()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -594,17 +572,11 @@ public class MainViewModel implements ViewModel {
|
||||
throw new CryptoException("Payload not correct after decryption");
|
||||
} catch (CryptoException e) {
|
||||
e.printStackTrace();
|
||||
String msg = "Seems that you use a self compiled binary and have not following the build " +
|
||||
"instructions in https://github.com/bitsquare/bitsquare/blob/master/doc/build.md#7-enable-unlimited-strength-for-cryptographic-keys.\n\n" +
|
||||
"If that is not the case and you use the official Bitsquare binary, " +
|
||||
"please file a bug report to the Github page.\n" +
|
||||
"Error=" + e.getMessage();
|
||||
String msg = Res.get("popup.warning.cryptoTestFailed", e.getMessage());
|
||||
log.error(msg);
|
||||
UserThread.execute(() -> new Popup<>().warning(msg)
|
||||
.actionButtonText("Shut down")
|
||||
.onAction(BitsquareApp.shutDownHandler::run)
|
||||
.closeButtonText("Report bug at Github issues")
|
||||
.onClose(() -> GUIUtil.openWebPage("https://github.com/bitsquare/bitsquare/issues"))
|
||||
.useShutDownButton()
|
||||
.useReportBugButton()
|
||||
.show());
|
||||
}
|
||||
}
|
||||
@ -612,23 +584,17 @@ public class MainViewModel implements ViewModel {
|
||||
checkCryptoThread.start();
|
||||
|
||||
if (Security.getProvider("BC") == null) {
|
||||
new Popup<>().warning("There is a problem with the crypto libraries. BountyCastle is not available.")
|
||||
.actionButtonText("Shut down")
|
||||
.onAction(BitsquareApp.shutDownHandler::run)
|
||||
.closeButtonText("Report bug at Github issues")
|
||||
.onClose(() -> GUIUtil.openWebPage("https://github.com/bitsquare/bitsquare/issues"))
|
||||
new Popup<>().warning(Res.get("popup.warning.noBountyCastle"))
|
||||
.useShutDownButton()
|
||||
.useReportBugButton()
|
||||
.show();
|
||||
}
|
||||
|
||||
String remindPasswordAndBackupKey = "remindPasswordAndBackup";
|
||||
user.getPaymentAccountsAsObservable().addListener((SetChangeListener<PaymentAccount>) change -> {
|
||||
if (!walletsManager.areWalletsEncrypted() && preferences.showAgain(remindPasswordAndBackupKey) && change.wasAdded()) {
|
||||
new Popup<>().headLine("Important security recommendation")
|
||||
.information("We would like to remind you to consider using password protection for your wallet if you have not already enabled that.\n\n" +
|
||||
"It is also highly recommended to write down the wallet seed words. Those seed words are like a master password for recovering your Bitcoin wallet.\n" +
|
||||
"At the \"Wallet Seed\" section you find more information.\n\n" +
|
||||
"Additionally you can backup the complete application data folder at the \"Backup\" section.\n" +
|
||||
"Please note, that this backup is not encrypted!")
|
||||
new Popup<>().headLine(Res.get("popup.securityRecommendation.headline"))
|
||||
.information(Res.get("popup.securityRecommendation.msg"))
|
||||
.dontShowAgainId(remindPasswordAndBackupKey, preferences)
|
||||
.show();
|
||||
}
|
||||
@ -643,18 +609,15 @@ public class MainViewModel implements ViewModel {
|
||||
.filter(e -> e.getOffer().getProtocolVersion() != Version.TRADE_PROTOCOL_VERSION)
|
||||
.collect(Collectors.toList());
|
||||
if (!outDatedOffers.isEmpty()) {
|
||||
String offers = outDatedOffers.stream()
|
||||
.map(e -> e.getId() + "\n")
|
||||
.collect(Collectors.toList()).toString()
|
||||
.replace("[", "").replace("]", "");
|
||||
new Popup<>()
|
||||
.warning("You have open offers which have been created with an older version of Bitsquare.\n" +
|
||||
"Please remove those offers as they are not valid anymore.\n\n" +
|
||||
"Offers (ID): " +
|
||||
outDatedOffers.stream()
|
||||
.map(e -> e.getId() + "\n")
|
||||
.collect(Collectors.toList()).toString()
|
||||
.replace("[", "").replace("]", ""))
|
||||
.actionButtonText("Remove outdated offer(s)")
|
||||
.warning(Res.get("popup.warning.oldOffers.msg", offers))
|
||||
.actionButtonText(Res.get("popup.warning.oldOffers.buttonText"))
|
||||
.onAction(() -> openOfferManager.removeOpenOffers(outDatedOffers, null))
|
||||
.closeButtonText("Shut down")
|
||||
.onClose(BitsquareApp.shutDownHandler::run)
|
||||
.useShutDownButton()
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@ -716,11 +679,9 @@ public class MainViewModel implements ViewModel {
|
||||
key = "displayHalfTradePeriodOver" + trade.getId();
|
||||
if (preferences.showAgain(key)) {
|
||||
preferences.dontShowAgain(key, true);
|
||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||
" has reached the half of the max. allowed trading period and " +
|
||||
"is still not completed.\n\n" +
|
||||
"The trade period ends on " + formatter.formatDateTime(maxTradePeriodDate) + "\n\n" +
|
||||
"Please check your trade state at \"Portfolio/Open trades\" for further information.")
|
||||
new Popup().warning(Res.get("popup.warning.tradePeriod.halfReached",
|
||||
trade.getShortId(),
|
||||
formatter.formatDateTime(maxTradePeriodDate)))
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
@ -728,12 +689,9 @@ public class MainViewModel implements ViewModel {
|
||||
key = "displayTradePeriodOver" + trade.getId();
|
||||
if (preferences.showAgain(key)) {
|
||||
preferences.dontShowAgain(key, true);
|
||||
new Popup().warning("Your trade with ID " + trade.getShortId() +
|
||||
" has reached the max. allowed trading period and is " +
|
||||
"not completed.\n\n" +
|
||||
"The trade period ended on " + formatter.formatDateTime(maxTradePeriodDate) + "\n\n" +
|
||||
"Please check your trade at \"Portfolio/Open trades\" for contacting " +
|
||||
"the arbitrator.")
|
||||
new Popup().warning(Res.get("popup.warning.tradePeriod.ended",
|
||||
trade.getShortId(),
|
||||
formatter.formatDateTime(maxTradePeriodDate)))
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
@ -759,8 +717,7 @@ public class MainViewModel implements ViewModel {
|
||||
checkNumberOfP2pNetworkPeersTimer = UserThread.runAfter(() -> {
|
||||
// check again numPeers
|
||||
if (p2PService.getNumConnectedPeers().get() == 0) {
|
||||
p2pNetworkWarnMsg.set("You lost the connection to all P2P network peers.\n" +
|
||||
"Maybe you lost your internet connection or your computer was in standby mode.");
|
||||
p2pNetworkWarnMsg.set(Res.get("mainView.networkWarning.allConnectionsLost", Res.get("shared.P2P")));
|
||||
p2pNetworkLabelId.set("splash-error-state-msg");
|
||||
} else {
|
||||
p2pNetworkWarnMsg.set(null);
|
||||
@ -787,8 +744,7 @@ public class MainViewModel implements ViewModel {
|
||||
checkNumberOfBtcPeersTimer = UserThread.runAfter(() -> {
|
||||
// check again numPeers
|
||||
if (walletsSetup.numPeersProperty().get() == 0) {
|
||||
walletServiceErrorMsg.set("You lost the connection to all bitcoin network peers.\n" +
|
||||
"Maybe you lost your internet connection or your computer was in standby mode.");
|
||||
walletServiceErrorMsg.set(Res.get("mainView.networkWarning.allConnectionsLost", Res.get("shared.bitcoin")));
|
||||
} else {
|
||||
walletServiceErrorMsg.set(null);
|
||||
}
|
||||
@ -807,7 +763,7 @@ public class MainViewModel implements ViewModel {
|
||||
if (priceFeedService.getType() == null)
|
||||
priceFeedService.setType(PriceFeedService.Type.LAST);
|
||||
priceFeedService.init(price -> marketPrice.set(formatter.formatMarketPrice(price, priceFeedService.getCurrencyCode())),
|
||||
(errorMessage, throwable) -> marketPrice.set("N/A"));
|
||||
(errorMessage, throwable) -> marketPrice.set(Res.get("shared.na")));
|
||||
marketPriceCurrencyCode.bind(priceFeedService.currencyCodeProperty());
|
||||
typeProperty.bind(priceFeedService.typeProperty());
|
||||
|
||||
@ -868,11 +824,11 @@ public class MainViewModel implements ViewModel {
|
||||
priceString = formatter.formatMarketPrice(price, currencyCode);
|
||||
item.setIsPriceAvailable(true);
|
||||
} else {
|
||||
priceString = "N/A";
|
||||
priceString = Res.get("shared.na");
|
||||
item.setIsPriceAvailable(false);
|
||||
}
|
||||
} else {
|
||||
priceString = "N/A";
|
||||
priceString = Res.get("shared.na");
|
||||
item.setIsPriceAvailable(false);
|
||||
}
|
||||
item.setDisplayString(formatter.getCurrencyPair(currencyCode) + ": " + priceString);
|
||||
@ -932,11 +888,11 @@ public class MainViewModel implements ViewModel {
|
||||
}
|
||||
|
||||
private void displayPrivateNotification(PrivateNotification privateNotification) {
|
||||
new Popup<>().headLine("Important private notification!")
|
||||
new Popup<>().headLine(Res.get("popup.privateNotification.headline"))
|
||||
.attention(privateNotification.message)
|
||||
.setHeadlineStyle("-fx-text-fill: -bs-error-red; -fx-font-weight: bold; -fx-font-size: 16;")
|
||||
.onClose(privateNotificationManager::removePrivateNotification)
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.show();
|
||||
}
|
||||
|
||||
@ -1033,12 +989,12 @@ public class MainViewModel implements ViewModel {
|
||||
private void setupDevDummyPaymentAccounts() {
|
||||
OKPayAccount okPayAccount = new OKPayAccount();
|
||||
okPayAccount.setAccountNr("dummy_" + new Random().nextInt(100));
|
||||
okPayAccount.setAccountName("OKPay dummy");
|
||||
okPayAccount.setAccountName("OKPay dummy");// Don't translate only for dev
|
||||
okPayAccount.setSelectedTradeCurrency(CurrencyUtil.getDefaultTradeCurrency());
|
||||
user.addPaymentAccount(okPayAccount);
|
||||
|
||||
CryptoCurrencyAccount cryptoCurrencyAccount = new CryptoCurrencyAccount();
|
||||
cryptoCurrencyAccount.setAccountName("ETH dummy");
|
||||
cryptoCurrencyAccount.setAccountName("ETH dummy");// Don't translate only for dev
|
||||
cryptoCurrencyAccount.setAddress("0x" + new Random().nextInt(1000000));
|
||||
cryptoCurrencyAccount.setSingleTradeCurrency(CurrencyUtil.getCryptoCurrency("ETH").get());
|
||||
user.addPaymentAccount(cryptoCurrencyAccount);
|
||||
|
@ -162,17 +162,17 @@ public class AltCoinAccountsView extends ActivatableViewAndModel<GridPane, AltCo
|
||||
"arbitrator in case of a dispute.\n\n" +
|
||||
"There is no payment ID required, just the normal public address.\n\n" +
|
||||
"If you are not sure about that process visit the Monero forum (https://forum.getmonero.org) to find more information.")
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.show();
|
||||
} else if (code.equals("ZEC")) {
|
||||
new Popup().information("When using ZEC you can only use the transparent addresses (starting with t) not " +
|
||||
"the z-addresses, because the arbitrator would not be able to verify the transaction with z-addresses.")
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.show();
|
||||
} else if (code.equals("XZC")) {
|
||||
new Popup().information("When using XZC you can only use the transparent transactions not " +
|
||||
"the private transactions, because the arbitrator would not be able to verify the private transactions.")
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.show();
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ package io.bitsquare.gui.main.account.content.seedwords;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.btc.wallet.BtcWalletService;
|
||||
import io.bitsquare.btc.wallet.WalletsManager;
|
||||
import io.bitsquare.common.UserThread;
|
||||
@ -260,8 +259,7 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
|
||||
new Popup()
|
||||
.feedback("Wallets restored successfully with the new seed words.\n\n" +
|
||||
"You need to shut down and restart the application.")
|
||||
.closeButtonText("Shut down")
|
||||
.onClose(BitsquareApp.shutDownHandler::run).show();
|
||||
.useShutDownButton();
|
||||
}),
|
||||
throwable -> UserThread.execute(() -> {
|
||||
log.error(throwable.getMessage());
|
||||
|
@ -46,6 +46,7 @@ import io.bitsquare.gui.main.overlays.windows.SendPrivateNotificationWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.Res;
|
||||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.network.Connection;
|
||||
@ -1116,9 +1117,9 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||
if (buyerNodeAddress != null)
|
||||
return buyerNodeAddress.getHostNameWithoutPostFix() + " (" + disputeManager.getNrOfDisputes(true, contract) + ")";
|
||||
else
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1129,9 +1130,9 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
|
||||
if (sellerNodeAddress != null)
|
||||
return sellerNodeAddress.getHostNameWithoutPostFix() + " (" + disputeManager.getNrOfDisputes(false, contract) + ")";
|
||||
else
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.CurrencyListItem;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.Res;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@ -318,7 +319,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||
if (offerListItem.offer.getPrice() == null) {
|
||||
this.offer = offerListItem.offer;
|
||||
model.priceFeedService.currenciesUpdateFlagProperty().addListener(listener);
|
||||
setText("N/A");
|
||||
setText(Res.get("shared.na"));
|
||||
} else {
|
||||
setText(formatter.formatPrice(offerListItem.offer.getPrice()));
|
||||
}
|
||||
@ -363,7 +364,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
||||
if (offer.getPrice() == null) {
|
||||
this.offer = offerListItem.offer;
|
||||
model.priceFeedService.currenciesUpdateFlagProperty().addListener(listener);
|
||||
setText("N/A");
|
||||
setText(Res.get("shared.na"));
|
||||
} else {
|
||||
setText(formatter.formatVolume(offer.getOfferVolume()));
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
"Be sure that you have standby mode deactivated as that would disconnect your client from the network (standby of the monitor is not a problem).")
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> GUIUtil.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
||||
|
@ -533,7 +533,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
if (item.getOffer().getPrice() == null) {
|
||||
this.offerBookListItem = item;
|
||||
model.priceFeedService.currenciesUpdateFlagProperty().addListener(listener);
|
||||
setText("N/A");
|
||||
setText(Res.get("shared.na"));
|
||||
} else {
|
||||
setText(model.getPrice(item));
|
||||
}
|
||||
@ -582,7 +582,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
||||
if (item.getOffer().getPrice() == null) {
|
||||
this.offerBookListItem = item;
|
||||
model.priceFeedService.currenciesUpdateFlagProperty().addListener(listener);
|
||||
setText("N/A");
|
||||
setText(Res.get("shared.na"));
|
||||
} else {
|
||||
setText(model.getVolume(item));
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
else
|
||||
return formatter.formatPrice(price) + postFix;
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +290,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||
else
|
||||
return formatter.formatMinVolumeAndVolume(offer) + postFix;
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
"It will be refunded to you after the trade has successfully completed.")
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> GUIUtil.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package io.bitsquare.gui.main.overlays;
|
||||
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.common.Timer;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
@ -221,7 +222,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T notification(String message) {
|
||||
type = Type.Notification;
|
||||
if (headLine == null)
|
||||
this.headLine = "Notification";
|
||||
this.headLine = Res.get("popup.headline.notification");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -230,7 +231,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T instruction(String message) {
|
||||
type = Type.Instruction;
|
||||
if (headLine == null)
|
||||
this.headLine = "Please note:";
|
||||
this.headLine = Res.get("popup.headline.instruction");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -239,7 +240,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T attention(String message) {
|
||||
type = Type.Attention;
|
||||
if (headLine == null)
|
||||
this.headLine = "Attention";
|
||||
this.headLine = Res.get("popup.headline.attention");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -248,7 +249,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T backgroundInfo(String message) {
|
||||
type = Type.BackgroundInfo;
|
||||
if (headLine == null)
|
||||
this.headLine = "Background information";
|
||||
this.headLine = Res.get("popup.headline.backgroundInfo");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -257,7 +258,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T feedback(String message) {
|
||||
type = Type.Feedback;
|
||||
if (headLine == null)
|
||||
this.headLine = "Completed";
|
||||
this.headLine = Res.get("popup.headline.feedback");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -266,7 +267,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T confirmation(String message) {
|
||||
type = Type.Confirmation;
|
||||
if (headLine == null)
|
||||
this.headLine = "Confirmation";
|
||||
this.headLine = Res.get("popup.headline.confirmation");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -275,7 +276,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
public T information(String message) {
|
||||
type = Type.Information;
|
||||
if (headLine == null)
|
||||
this.headLine = "Information";
|
||||
this.headLine = Res.get("popup.headline.information");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -285,7 +286,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
type = Type.Warning;
|
||||
|
||||
if (headLine == null)
|
||||
this.headLine = "Warning";
|
||||
this.headLine = Res.get("popup.headline.warning");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -295,7 +296,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
type = Type.Error;
|
||||
showReportErrorButtons();
|
||||
if (headLine == null)
|
||||
this.headLine = "Error";
|
||||
this.headLine = Res.get("popup.headline.error");
|
||||
this.message = message;
|
||||
setTruncatedMessage();
|
||||
return (T) this;
|
||||
@ -317,11 +318,29 @@ public abstract class Overlay<T extends Overlay> {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T useReportBugButton() {
|
||||
this.closeButtonText = Res.get("shared.reportBug");
|
||||
this.closeHandlerOptional = Optional.of(() -> GUIUtil.openWebPage("https://github.com/bitsquare/bitsquare/issues"));
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T useIUnderstandButton() {
|
||||
this.closeButtonText = Res.get("shared.iUnderstand");
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
public T actionButtonText(String actionButtonText) {
|
||||
this.actionButtonText = actionButtonText;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T useShutDownButton() {
|
||||
this.actionButtonText = Res.get("shared.shutDown");
|
||||
this.actionHandlerOptional = Optional.of(BitsquareApp.shutDownHandler::run);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T width(double width) {
|
||||
this.width = width;
|
||||
return (T) this;
|
||||
|
@ -18,7 +18,6 @@
|
||||
package io.bitsquare.gui.main.overlays.windows;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.btc.wallet.WalletsManager;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
@ -376,8 +375,7 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
|
||||
new Popup()
|
||||
.feedback("Wallet restored successfully with the new seed words.\n\n" +
|
||||
"You need to shut down and restart the application.")
|
||||
.closeButtonText("Shut down")
|
||||
.onClose(BitsquareApp.shutDownHandler::run)
|
||||
.useShutDownButton()
|
||||
.show();
|
||||
}),
|
||||
throwable -> UserThread.execute(() -> {
|
||||
|
@ -23,6 +23,7 @@ import io.bitsquare.common.handlers.ResultHandler;
|
||||
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
||||
import io.bitsquare.gui.common.model.ViewModel;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.locale.Res;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
import io.bitsquare.trade.offer.OpenOffer;
|
||||
@ -70,7 +71,7 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
|
||||
postFix = " (" + formatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")";
|
||||
return formatter.formatPrice(price) + postFix;
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.TradeSubView;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.locale.Res;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
@ -251,7 +252,7 @@ public abstract class TradeStepView extends AnchorPane {
|
||||
|
||||
protected void setWarningHeadline() {
|
||||
if (notificationGroup != null) {
|
||||
notificationGroup.titledGroupBg.setText("Warning");
|
||||
notificationGroup.titledGroupBg.setText(Res.get("shared.warning"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,10 @@
|
||||
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import io.bitsquare.btc.BitcoinNetwork;
|
||||
import io.bitsquare.common.util.MathUtils;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.LanguageUtil;
|
||||
import io.bitsquare.locale.Res;
|
||||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
import io.bitsquare.user.Preferences;
|
||||
@ -201,7 +201,7 @@ public class BSFormatter {
|
||||
return "N/A " + fiat.getCurrencyCode();
|
||||
}
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ public class BSFormatter {
|
||||
return "N/A " + fiat.getCurrencyCode();
|
||||
}
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,7 +312,7 @@ public class BSFormatter {
|
||||
} else
|
||||
return formatFiat(fiat);
|
||||
} else {
|
||||
return "N/A";
|
||||
return Res.get("shared.na");
|
||||
}
|
||||
}
|
||||
|
||||
@ -513,20 +513,7 @@ public class BSFormatter {
|
||||
|
||||
|
||||
public String booleanToYesNo(boolean value) {
|
||||
return value ? "Yes" : "No";
|
||||
}
|
||||
|
||||
public String formatBitcoinNetwork(BitcoinNetwork bitcoinNetwork) {
|
||||
switch (bitcoinNetwork) {
|
||||
case MAINNET:
|
||||
return "Mainnet";
|
||||
case TESTNET:
|
||||
return "Testnet";
|
||||
case REGTEST:
|
||||
return "Regtest";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
return value ? Res.get("shared.yes") : Res.get("shared.no");
|
||||
}
|
||||
|
||||
public String getDirectionBothSides(Offer.Direction direction, String currencyCode) {
|
||||
|
@ -81,7 +81,7 @@ public class GUIUtil {
|
||||
"You can check out the currently recommended fees at: https://bitcoinfees.21.co")
|
||||
.dontShowAgainId(key, Preferences.INSTANCE)
|
||||
.onClose(runnable::run)
|
||||
.closeButtonText("I understand")
|
||||
.useIUnderstandButton()
|
||||
.show();
|
||||
} else {
|
||||
runnable.run();
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Naming convention: We use camelCase and dot separated name spaces.
|
||||
# Use as many sub spaces as required to make the structure clear, but as little as possible.
|
||||
# E.g.: [main-view].[component].[description]
|
||||
|
||||
# In some cases we use enum values or constants to map to display strings
|
||||
|
||||
|
||||
####################################################################
|
||||
@ -24,25 +24,44 @@ mainView.menu.account=Account
|
||||
mainView.menu.dao=DAO
|
||||
|
||||
mainView.marketPrice=Market price ({0})
|
||||
mainView.marketPrice.tooltip=Market price is provided by {0}{1}\nLast update: {2}
|
||||
mainView.marketPrice.tooltip.altcoinExtra=If the altcoin is not available at Poloniex we use https://coinmarketcap.com
|
||||
mainView.balance.available=Available balance
|
||||
mainView.balance.reserved=Reserved in offers
|
||||
mainView.balance.locked=Locked in trades
|
||||
|
||||
mainView.footer.usingTor=(using Tor)
|
||||
mainView.footer.btcInfo=Bitcoin network peers: {0} / synchronized with {1} {2}
|
||||
|
||||
mainView.footer.btcInfo=Bitcoin network peers: {0} / {1} {2} {3}
|
||||
mainView.footer.btcInfo.initializing=Initializing
|
||||
mainView.footer.btcInfo.synchronizedWith=synchronized with
|
||||
mainView.footer.btcInfo.connectingTo=connecting to
|
||||
mainView.footer.btcInfo.connectionFailed=connection failed
|
||||
mainView.footer.p2pInfo= P2P network peers: {0}
|
||||
|
||||
mainView.bootstrapState.connectionToTorNetwork=Connecting to Tor network...
|
||||
mainView.bootstrapState.torNodeCreated=Tor node created
|
||||
mainView.bootstrapState.hiddenServicePublished=Hidden Service published
|
||||
mainView.bootstrapState.initialDataReceived=Initial data received
|
||||
|
||||
mainView.bootstrapWarning.noSeedNodesAvailable=No seed nodes available
|
||||
mainView.bootstrapWarning.noNodesAvailable=No seed nodes and peers available
|
||||
mainView.bootstrapWarning.bootstrappingToP2PFailed=Bootstrapping to P2P network failed
|
||||
|
||||
mainView.p2pNetworkWarnMsg.noNodesAvailable=There are no seed nodes or persisted peers available for requesting data.\nPlease check your internet connection or try to restart the application.
|
||||
mainView.p2pNetworkWarnMsg.connectionToP2PFailed=Connecting to the P2P network failed (reported error: {0}).\nPlease check your internet connection or try to restart the application.
|
||||
|
||||
mainView.walletServiceErrorMsg.timeout=Connecting to the bitcoin network failed because of a timeout.
|
||||
mainView.walletServiceErrorMsg.connectionError=Connection to the bitcoin network failed because of an error: {0}
|
||||
|
||||
mainView.networkWarning.allConnectionsLost=You lost the connection to all {0} network peers.\nMaybe you lost your internet connection or your computer was in standby mode.
|
||||
|
||||
marketPrice.ask=Ask
|
||||
marketPrice.bid=Bid
|
||||
marketPrice.last=Last
|
||||
|
||||
####################################################################
|
||||
# Market
|
||||
####################################################################
|
||||
|
||||
market.tabs.offerBook=Offer boook
|
||||
market.tabs.offerBook=Offer book
|
||||
market.tabs.spread=Spread
|
||||
market.tabs.trades=Trades
|
||||
|
||||
@ -88,14 +107,40 @@ market.tabs.trades=Trades
|
||||
# Popups
|
||||
####################################################################
|
||||
|
||||
popup.error.title=Error
|
||||
popup.headline.notification=Notification
|
||||
popup.headline.instruction=Please note:
|
||||
popup.headline.attention=Attention
|
||||
popup.headline.backgroundInfo=Background information
|
||||
popup.headline.feedback=Completed
|
||||
popup.headline.confirmation=Confirmation
|
||||
popup.headline.information=Information
|
||||
popup.headline.warning=Warning
|
||||
popup.headline.error=Error
|
||||
|
||||
popup.error.fatalStartupException=A fatal exception occurred at startup.
|
||||
popup.error.walletException=Cannot open wallet because of an exception:\n{0}
|
||||
|
||||
popup.warning.walletNotInitialized=The wallet is not initialized yet
|
||||
popup.warning.wrongVersion=You probably have the wrong Bitsquare version for this computer.\nYour computer's architecture is: {0}.\nThe Bitsquare binary you installed is: {1}.\nPlease shut down and re-install the correct version ({2}).
|
||||
popup.warning.incompatibleDB=We detected incompatible data base files!\n\nThose database file(s) are not compatible with our current code base:\n{0}\n\nWe made a backup of the corrupted file(s) and applied the default values to a newdatabase version.\n\nThe backup is located at:\n{1}/db/backup_of_corrupted_data.\n\nPlease check if you have the latest version of Bitsquare installed.\nYou can download it at:\nhttps://bitsquare.io/downloads\n\nPlease restart the application.
|
||||
popup.warning.cannotConnectAtStartup=You still did not get connected to the {0} network.\nIf you use Tor for Bitcoin it might be that you got an unstable Tor circuit.\nYou can wait longer or try to restart.
|
||||
popup.warning.unknownProblemAtStartup=There is an unknown problem at startup.\nPlease restart and if the problem continues file a bug report.
|
||||
popup.warning.startupFailed.timeout=The application could not startup after 4 minutes.\n\n{0}
|
||||
popup.warning.startupFailed.twoInstances=Bitsquare is already running. You cannot run two instances of Bitsquare.
|
||||
popup.warning.cryptoTestFailed=Seems that you use a self compiled binary and have not following the build instructions in https://github.com/bitsquare/bitsquare/blob/master/doc/build.md#7-enable-unlimited-strength-for-cryptographic-keys.\n\nIf that is not the case and you use the official Bitsquare binary, please file a bug report to the Github page.\nError={0}
|
||||
popup.warning.noBountyCastle=There is a problem with the crypto libraries. BountyCastle is not available.
|
||||
popup.warning.oldOffers.msg=You have open offers which have been created with an older version of Bitsquare.\nPlease remove those offers as they are not valid anymore.\n\nOffers (ID): {0}
|
||||
popup.warning.oldOffers.buttonText=Remove outdated offer(s)
|
||||
popup.warning.tradePeriod.halfReached=Your trade with ID {0} has reached the half of the max. allowed trading period and is still not completed.\n\nThe trade period ends on {1}\n\nPlease check your trade state at \"Portfolio/Open trades\" for further information.
|
||||
popup.warning.tradePeriod.ended=Your trade with ID {0} has reached the max. allowed trading period and is not completed.\n\nThe trade period ended on {1}\n\nPlease check your trade at \"Portfolio/Open trades\" for contacting the arbitrator.
|
||||
|
||||
popup.privateNotification.headline=Important private notification!
|
||||
|
||||
popup.securityRecommendation.headline=Important security recommendation
|
||||
popup.securityRecommendation.msg=We would like to remind you to consider using password protection for your wallet if you have not already enabled that.\n\nIt is also highly recommended to write down the wallet seed words. Those seed words are like a master password for recovering your Bitcoin wallet.\nAt the \"Wallet Seed\" section you find more information.\n\nAdditionally you should backup the complete application data folder at the \"Backup\" section.
|
||||
|
||||
popup.shutDownInProgress.headline=Shut down in progress
|
||||
popup.shutDownInProgress.message=Shutting down application can take a few seconds.\nPlease don't interrupt this process.
|
||||
popup.shutDownInProgress.msg=Shutting down application can take a few seconds.\nPlease don't interrupt this process.
|
||||
|
||||
|
||||
####################################################################
|
||||
@ -234,8 +279,10 @@ shared.cancel=Cancel
|
||||
shared.ok=OK
|
||||
shared.yes=Yes
|
||||
shared.no=No
|
||||
shared.notAvailable=N/A
|
||||
shared.iUnderstand=I understand
|
||||
shared.na=N/A
|
||||
shared.shutDown=Shut down
|
||||
shared.reportBug=Report bug at Github issues
|
||||
|
||||
shared.openSettings=Open settings for editing
|
||||
shared.buyBitcoin=Buy bitcoin
|
||||
@ -244,11 +291,24 @@ shared.buy=buy
|
||||
shared.sell=sell
|
||||
shared.spend=spend
|
||||
|
||||
shared.bitcoin=bitcoin
|
||||
shared.P2P=P2P
|
||||
|
||||
|
||||
####################################################################
|
||||
# Domain specific
|
||||
####################################################################
|
||||
|
||||
marketPrice.ask=Ask
|
||||
marketPrice.bid=Bid
|
||||
marketPrice.last=Last
|
||||
|
||||
# we use enum values here
|
||||
MAINNET=Mainnet
|
||||
TESTNET=Testnet
|
||||
REGTEST=Regtest
|
||||
|
||||
|
||||
|
||||
####################################################################
|
||||
# Payment methods
|
||||
|
Loading…
Reference in New Issue
Block a user