Merge branch 'master' of github.com:bisq-network/bisq into add-xmr-tx-key-service-3

# Conflicts:
#	desktop/src/main/java/bisq/desktop/main/MainView.java
#	desktop/src/main/java/bisq/desktop/main/MainViewModel.java
This commit is contained in:
Christoph Atteneder 2020-09-03 17:10:05 +02:00
commit 77c7629478
No known key found for this signature in database
GPG key ID: CD5DC1C529CDFD3B
29 changed files with 300 additions and 304 deletions

View file

@ -14,10 +14,3 @@ install:
before_install: before_install:
grep -v '^#' assets/src/main/resources/META-INF/services/bisq.asset.Asset | sort --check --dictionary-order --ignore-case grep -v '^#' assets/src/main/resources/META-INF/services/bisq.asset.Asset | sort --check --dictionary-order --ignore-case
notifications:
slack:
on_success: change
on_failure: always
rooms:
- secure: EzlqWTBuhb3FCfApjUXaShWgsWOVDwMXI7ISMiVBkcl2VFISYs/lc/7Qjr7rdy4iqQOQXMcUPHdwMUp0diX+GxiSjLARjUpKIvNOPswZWBL+3Z1h28jyOwtHRviZbM1EU0BZROrr+ODyTNz2lf+L1iXTkpSvk50o5JAnAkumsPw=

View file

@ -51,7 +51,7 @@ configure(subprojects) {
javaxAnnotationVersion = '1.2' javaxAnnotationVersion = '1.2'
jcsvVersion = '1.4.0' jcsvVersion = '1.4.0'
jetbrainsAnnotationsVersion = '13.0' jetbrainsAnnotationsVersion = '13.0'
jfoenixVersion = '9.0.10' jfoenixVersion = '9.0.6'
joptVersion = '5.0.4' joptVersion = '5.0.4'
jsonsimpleVersion = '1.1.1' jsonsimpleVersion = '1.1.1'
junitVersion = '4.12' junitVersion = '4.12'

View file

@ -4,6 +4,8 @@ import joptsimple.ArgumentAcceptingOptionSpec;
import joptsimple.OptionSet; import joptsimple.OptionSet;
import joptsimple.OptionSpec; import joptsimple.OptionSpec;
import com.google.common.annotations.VisibleForTesting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -17,6 +19,7 @@ import java.util.List;
* the command line with those provided via config file, such that those provided at the * the command line with those provided via config file, such that those provided at the
* command line take precedence over those provided in the config file. * command line take precedence over those provided in the config file.
*/ */
@VisibleForTesting
public class CompositeOptionSet { public class CompositeOptionSet {
private final List<OptionSet> optionSets = new ArrayList<>(); private final List<OptionSet> optionSets = new ArrayList<>();

View file

@ -68,6 +68,7 @@ public class Config {
public static final String BASE_CURRENCY_NETWORK = "baseCurrencyNetwork"; public static final String BASE_CURRENCY_NETWORK = "baseCurrencyNetwork";
public static final String REFERRAL_ID = "referralId"; public static final String REFERRAL_ID = "referralId";
public static final String USE_DEV_MODE = "useDevMode"; public static final String USE_DEV_MODE = "useDevMode";
public static final String USE_DEV_MODE_HEADER = "useDevModeHeader";
public static final String TOR_DIR = "torDir"; public static final String TOR_DIR = "torDir";
public static final String STORAGE_DIR = "storageDir"; public static final String STORAGE_DIR = "storageDir";
public static final String KEY_STORAGE_DIR = "keyStorageDir"; public static final String KEY_STORAGE_DIR = "keyStorageDir";
@ -159,6 +160,7 @@ public class Config {
public final boolean daoActivated; public final boolean daoActivated;
public final String referralId; public final String referralId;
public final boolean useDevMode; public final boolean useDevMode;
public final boolean useDevModeHeader;
public final boolean useDevPrivilegeKeys; public final boolean useDevPrivilegeKeys;
public final boolean dumpStatistics; public final boolean dumpStatistics;
public final boolean ignoreDevMsg; public final boolean ignoreDevMsg;
@ -356,6 +358,13 @@ public class Config {
.ofType(boolean.class) .ofType(boolean.class)
.defaultsTo(false); .defaultsTo(false);
ArgumentAcceptingOptionSpec<Boolean> useDevModeHeaderOpt =
parser.accepts(USE_DEV_MODE_HEADER,
"Use dev mode css scheme to distinguish dev instances.")
.withRequiredArg()
.ofType(boolean.class)
.defaultsTo(false);
ArgumentAcceptingOptionSpec<Boolean> useDevPrivilegeKeysOpt = ArgumentAcceptingOptionSpec<Boolean> useDevPrivilegeKeysOpt =
parser.accepts(USE_DEV_PRIVILEGE_KEYS, "If set to true all privileged features requiring a private " + parser.accepts(USE_DEV_PRIVILEGE_KEYS, "If set to true all privileged features requiring a private " +
"key to be enabled are overridden by a dev key pair (This is for developers only!)") "key to be enabled are overridden by a dev key pair (This is for developers only!)")
@ -706,6 +715,7 @@ public class Config {
this.torStreamIsolation = options.has(torStreamIsolationOpt); this.torStreamIsolation = options.has(torStreamIsolationOpt);
this.referralId = options.valueOf(referralIdOpt); this.referralId = options.valueOf(referralIdOpt);
this.useDevMode = options.valueOf(useDevModeOpt); this.useDevMode = options.valueOf(useDevModeOpt);
this.useDevModeHeader = options.valueOf(useDevModeHeaderOpt);
this.useDevPrivilegeKeys = options.valueOf(useDevPrivilegeKeysOpt); this.useDevPrivilegeKeys = options.valueOf(useDevPrivilegeKeysOpt);
this.dumpStatistics = options.valueOf(dumpStatisticsOpt); this.dumpStatistics = options.valueOf(dumpStatisticsOpt);
this.ignoreDevMsg = options.valueOf(ignoreDevMsgOpt); this.ignoreDevMsg = options.valueOf(ignoreDevMsgOpt);

View file

@ -0,0 +1,24 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.common.util;
public class InvalidVersionException extends Exception {
public InvalidVersionException(String msg) {
super(msg);
}
}

View file

@ -17,8 +17,6 @@
package bisq.common.util; package bisq.common.util;
import bisq.common.crypto.LimitedKeyStrengthException;
import org.bitcoinj.core.Utils; import org.bitcoinj.core.Utils;
import com.google.gson.ExclusionStrategy; import com.google.gson.ExclusionStrategy;
@ -71,6 +69,7 @@ import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static java.awt.Desktop.Action; import static java.awt.Desktop.Action;
import static java.awt.Desktop.getDesktop; import static java.awt.Desktop.getDesktop;
@ -182,6 +181,34 @@ public class Utilities {
return System.getProperty("os.name").toLowerCase(Locale.US); return System.getProperty("os.name").toLowerCase(Locale.US);
} }
public static String getOSVersion() {
return System.getProperty("os.version").toLowerCase(Locale.US);
}
public static int getMinorVersion() throws InvalidVersionException {
String version = getOSVersion();
String[] tokens = version.split("\\.");
try {
checkArgument(tokens.length > 1);
return Integer.parseInt(tokens[1]);
} catch (IllegalArgumentException e) {
printSysInfo();
throw new InvalidVersionException("Version is not in expected format. Version=" + version);
}
}
public static int getMajorVersion() throws InvalidVersionException {
String version = getOSVersion();
String[] tokens = version.split("\\.");
try {
checkArgument(tokens.length > 0);
return Integer.parseInt(tokens[0]);
} catch (IllegalArgumentException e) {
printSysInfo();
throw new InvalidVersionException("Version is not in expected format. Version=" + version);
}
}
public static String getOSArchitecture() { public static String getOSArchitecture() {
String osArch = System.getProperty("os.arch"); String osArch = System.getProperty("os.arch");
if (isWindows()) { if (isWindows()) {
@ -462,4 +489,5 @@ public class Utilities {
Map<Object, Boolean> map = new ConcurrentHashMap<>(); Map<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
} }
} }

View file

@ -31,6 +31,7 @@ import bisq.common.app.Version;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -42,6 +43,7 @@ import lombok.extern.slf4j.Slf4j;
* Provides high level interface to functionality of core Bisq features. * Provides high level interface to functionality of core Bisq features.
* E.g. useful for different APIs to access data of different domains of Bisq. * E.g. useful for different APIs to access data of different domains of Bisq.
*/ */
@Singleton
@Slf4j @Slf4j
public class CoreApi { public class CoreApi {

View file

@ -164,6 +164,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
protected void setupDevEnv() { protected void setupDevEnv() {
DevEnv.setDevMode(config.useDevMode); DevEnv.setDevMode(config.useDevMode);
DevEnv.setDevMode(config.useDevModeHeader);
DevEnv.setDaoActivated(config.daoActivated); DevEnv.setDaoActivated(config.daoActivated);
} }

View file

@ -97,6 +97,7 @@ public class BisqHeadlessApp implements HeadlessApp {
bisqSetup.setRejectedTxErrorMessageHandler(errorMessage -> log.warn("setRejectedTxErrorMessageHandler. errorMessage={}", errorMessage)); bisqSetup.setRejectedTxErrorMessageHandler(errorMessage -> log.warn("setRejectedTxErrorMessageHandler. errorMessage={}", errorMessage));
bisqSetup.setShowPopupIfInvalidBtcConfigHandler(() -> log.error("onShowPopupIfInvalidBtcConfigHandler")); bisqSetup.setShowPopupIfInvalidBtcConfigHandler(() -> log.error("onShowPopupIfInvalidBtcConfigHandler"));
bisqSetup.setRevolutAccountsUpdateHandler(revolutAccountList -> log.info("setRevolutAccountsUpdateHandler: revolutAccountList={}", revolutAccountList)); bisqSetup.setRevolutAccountsUpdateHandler(revolutAccountList -> log.info("setRevolutAccountsUpdateHandler: revolutAccountList={}", revolutAccountList));
bisqSetup.setOsxKeyLoggerWarningHandler(() -> log.info("setOsxKeyLoggerWarningHandler"));
//TODO move to bisqSetup //TODO move to bisqSetup
corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> log.warn("getCorruptedDatabaseFiles. files={}", files)); corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> log.warn("getCorruptedDatabaseFiles. files={}", files));

View file

@ -80,6 +80,7 @@ import bisq.common.crypto.CryptoException;
import bisq.common.crypto.KeyRing; import bisq.common.crypto.KeyRing;
import bisq.common.crypto.SealedAndSigned; import bisq.common.crypto.SealedAndSigned;
import bisq.common.proto.ProtobufferException; import bisq.common.proto.ProtobufferException;
import bisq.common.util.InvalidVersionException;
import bisq.common.util.Utilities; import bisq.common.util.Utilities;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
@ -225,6 +226,9 @@ public class BisqSetup {
@Setter @Setter
@Nullable @Nullable
private Consumer<List<RevolutAccount>> revolutAccountsUpdateHandler; private Consumer<List<RevolutAccount>> revolutAccountsUpdateHandler;
@Setter
@Nullable
private Runnable osxKeyLoggerWarningHandler;
@Getter @Getter
final BooleanProperty newVersionAvailableProperty = new SimpleBooleanProperty(false); final BooleanProperty newVersionAvailableProperty = new SimpleBooleanProperty(false);
@ -347,6 +351,7 @@ public class BisqSetup {
readMapsFromResources(this::step3); readMapsFromResources(this::step3);
checkCryptoSetup(); checkCryptoSetup();
checkForCorrectOSArchitecture(); checkForCorrectOSArchitecture();
checkOSXVersion();
} }
private void step3() { private void step3() {
@ -655,6 +660,19 @@ public class BisqSetup {
} }
} }
private void checkOSXVersion() {
if (Utilities.isOSX() && osxKeyLoggerWarningHandler != null) {
try {
// Seems it was introduced at 10.14: https://github.com/wesnoth/wesnoth/issues/4109
if (Utilities.getMajorVersion() >= 10 && Utilities.getMinorVersion() >= 14) {
osxKeyLoggerWarningHandler.run();
}
} catch (InvalidVersionException | NumberFormatException e) {
log.warn(e.getMessage());
}
}
}
private void initDomainServices() { private void initDomainServices() {
log.info("initDomainServices"); log.info("initDomainServices");

View file

@ -75,6 +75,7 @@ public class CoreModule extends AppModule {
bindConstant().annotatedWith(named(USE_DEV_PRIVILEGE_KEYS)).to(config.useDevPrivilegeKeys); bindConstant().annotatedWith(named(USE_DEV_PRIVILEGE_KEYS)).to(config.useDevPrivilegeKeys);
bindConstant().annotatedWith(named(USE_DEV_MODE)).to(config.useDevMode); bindConstant().annotatedWith(named(USE_DEV_MODE)).to(config.useDevMode);
bindConstant().annotatedWith(named(USE_DEV_MODE_HEADER)).to(config.useDevModeHeader);
bindConstant().annotatedWith(named(REFERRAL_ID)).to(config.referralId); bindConstant().annotatedWith(named(REFERRAL_ID)).to(config.referralId);
// ordering is used for shut down sequence // ordering is used for shut down sequence

View file

@ -79,6 +79,7 @@ public class ModuleForAppWithP2p extends AppModule {
bindConstant().annotatedWith(named(USE_DEV_PRIVILEGE_KEYS)).to(config.useDevPrivilegeKeys); bindConstant().annotatedWith(named(USE_DEV_PRIVILEGE_KEYS)).to(config.useDevPrivilegeKeys);
bindConstant().annotatedWith(named(USE_DEV_MODE)).to(config.useDevMode); bindConstant().annotatedWith(named(USE_DEV_MODE)).to(config.useDevMode);
bindConstant().annotatedWith(named(USE_DEV_MODE_HEADER)).to(config.useDevModeHeader);
bindConstant().annotatedWith(named(REFERRAL_ID)).to(config.referralId); bindConstant().annotatedWith(named(REFERRAL_ID)).to(config.referralId);
// ordering is used for shut down sequence // ordering is used for shut down sequence

View file

@ -61,7 +61,6 @@ import com.google.common.util.concurrent.ListenableFuture;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Proxy; import java.net.Proxy;
import java.net.UnknownHostException;
import java.nio.channels.FileLock; import java.nio.channels.FileLock;
@ -482,14 +481,7 @@ public class WalletConfig extends AbstractIdleService {
} }
void setPeerNodesForLocalHost() { void setPeerNodesForLocalHost() {
try { setPeerNodes(new PeerAddress(InetAddress.getLoopbackAddress(), params.getPort()));
setPeerNodes(new PeerAddress(InetAddress.getLocalHost(), params.getPort()));
} catch (UnknownHostException e) {
log.error(e.toString());
e.printStackTrace();
// Borked machine with no loopback adapter configured properly.
throw new RuntimeException(e);
}
} }
private Wallet createOrLoadWallet(File walletFile, private Wallet createOrLoadWallet(File walletFile,

View file

@ -1003,7 +1003,7 @@ support.tab.legacyArbitration.support=Legacy Arbitration
support.tab.ArbitratorsSupportTickets={0}'s tickets support.tab.ArbitratorsSupportTickets={0}'s tickets
support.filter=Search disputes support.filter=Search disputes
support.filter.prompt=Enter trade ID, date, onion address or account data support.filter.prompt=Enter trade ID, date, onion address or account data
support.reOpenByTrader.prompt=Are you sure you want to re-open the dispute? support.reOpenByTrader.prompt=Are you sure you want to re-open the dispute?
support.reOpenButton.label=Re-open dispute support.reOpenButton.label=Re-open dispute
support.sendNotificationButton.label=Send private notification support.sendNotificationButton.label=Send private notification
support.reportButton.label=Generate report support.reportButton.label=Generate report
@ -1290,6 +1290,7 @@ setting.info.msg=When selling BTC for XMR you can use the auto-confirm feature t
account.tab.arbitratorRegistration=Arbitrator registration account.tab.arbitratorRegistration=Arbitrator registration
account.tab.mediatorRegistration=Mediator registration account.tab.mediatorRegistration=Mediator registration
account.tab.refundAgentRegistration=Refund agent registration account.tab.refundAgentRegistration=Refund agent registration
account.tab.signing=Signing
account.tab.account=Account account.tab.account=Account
account.info.headline=Welcome to your Bisq Account account.info.headline=Welcome to your Bisq Account
account.info.msg=Here you can add trading accounts for national currencies & altcoins and create a backup of your wallet & account data.\n\n\ account.info.msg=Here you can add trading accounts for national currencies & altcoins and create a backup of your wallet & account data.\n\n\
@ -2637,6 +2638,12 @@ error.closedTradeWithNoDepositTx=The deposit transaction of the closed trade wit
Please restart the application to clean up the closed trades list. Please restart the application to clean up the closed trades list.
popup.warning.walletNotInitialized=The wallet is not initialized yet popup.warning.walletNotInitialized=The wallet is not initialized yet
popup.warning.osxKeyLoggerWarning=Due to stricter security measures in macOS 10.14 and above, launching a Java application \
(Bisq uses Java) causes a popup warning in macOS ('Bisq would like to receive keystrokes from any application').\n\n\
To avoid that issue please open your 'macOS Settings' and go to 'Security & Privacy' -> 'Privacy' -> \
'Input Monitoring' and Remove 'Bisq' from the list on the right side.\n\n\
Bisq will upgrade to a newer Java version to avoid that issue as soon the technical limitations \
(Java packager for the required Java version is not shipped yet) are resolved.
popup.warning.wrongVersion=You probably have the wrong Bisq version for this computer.\n\ popup.warning.wrongVersion=You probably have the wrong Bisq version for this computer.\n\
Your computer''s architecture is: {0}.\n\ Your computer''s architecture is: {0}.\n\
The Bisq binary you installed is: {1}.\n\ The Bisq binary you installed is: {1}.\n\

View file

@ -169,7 +169,7 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
if (scene == null) { if (scene == null) {
log.warn("Scene not available yet, we create a new scene. The bug might be caused by an exception in a constructor or by a circular dependency in Guice. throwable=" + throwable.toString()); log.warn("Scene not available yet, we create a new scene. The bug might be caused by an exception in a constructor or by a circular dependency in Guice. throwable=" + throwable.toString());
scene = new Scene(new StackPane(), 1000, 650); scene = new Scene(new StackPane(), 1000, 650);
CssTheme.loadSceneStyles(scene, CssTheme.CSS_THEME_LIGHT); CssTheme.loadSceneStyles(scene, CssTheme.CSS_THEME_LIGHT, false);
stage.setScene(scene); stage.setScene(scene);
stage.show(); stage.show();
} }
@ -221,10 +221,11 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
addSceneKeyEventHandler(scene, injector); addSceneKeyEventHandler(scene, injector);
Preferences preferences = injector.getInstance(Preferences.class); Preferences preferences = injector.getInstance(Preferences.class);
var config = injector.getInstance(Config.class);
preferences.getCssThemeProperty().addListener((ov) -> { preferences.getCssThemeProperty().addListener((ov) -> {
CssTheme.loadSceneStyles(scene, preferences.getCssTheme()); CssTheme.loadSceneStyles(scene, preferences.getCssTheme(), config.useDevModeHeader);
}); });
CssTheme.loadSceneStyles(scene, preferences.getCssTheme()); CssTheme.loadSceneStyles(scene, preferences.getCssTheme(), config.useDevModeHeader);
return scene; return scene;
} }

View file

@ -62,7 +62,6 @@ public class BisqAppMain extends BisqExecutable {
log.debug("onSetupComplete"); log.debug("onSetupComplete");
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// First synchronous execution tasks // First synchronous execution tasks
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -87,7 +86,6 @@ public class BisqAppMain extends BisqExecutable {
Application.launch(BisqApp.class); Application.launch(BisqApp.class);
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// As application is a JavaFX application we need to wait for onApplicationLaunched // As application is a JavaFX application we need to wait for onApplicationLaunched
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -123,21 +121,13 @@ public class BisqAppMain extends BisqExecutable {
@Override @Override
protected void startApplication() { protected void startApplication() {
// We need to be in user thread! We mapped at launchApplication already... // We need to be in user thread! We mapped at launchApplication already. Once
// the UI is ready we get onApplicationStarted called and start the setup there.
// Once the UI is ready we get onApplicationStarted called and start the setup there
application.startApplication(this::onApplicationStarted); application.startApplication(this::onApplicationStarted);
} }
@Override @Override
protected void onApplicationStarted() { protected void onApplicationStarted() {
super.onApplicationStarted(); super.onApplicationStarted();
/*
if (runWithGrpcApi()) {
CoreApi coreApi = injector.getInstance(CoreApi.class);
bisqGrpcServer = new BisqGrpcServer(coreApi);
}
*/
} }
} }

View file

@ -100,7 +100,7 @@ public class RevolutForm extends PaymentMethodForm {
@Override @Override
public void addFormForDisplayAccount() { public void addFormForDisplayAccount() {
gridRowFrom = gridRow; gridRowFrom = gridRow;
addTopLabelTextField(gridPane, gridRow, Res.get("payment.account.userName"), addTopLabelTextField(gridPane, gridRow, Res.get("payment.account.name"),
account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE); account.getAccountName(), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.paymentMethod"), addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("shared.paymentMethod"),
Res.get(account.getPaymentMethod().getId())); Res.get(account.getPaymentMethod().getId()));

View file

@ -77,6 +77,7 @@ import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority; import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment; import javafx.scene.text.TextAlignment;
@ -190,10 +191,6 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
JFXBadge portfolioButtonWithBadge = new JFXBadge(portfolioButton); JFXBadge portfolioButtonWithBadge = new JFXBadge(portfolioButton);
JFXBadge supportButtonWithBadge = new JFXBadge(supportButton); JFXBadge supportButtonWithBadge = new JFXBadge(supportButton);
JFXBadge daoButtonWithBadge = new JFXBadge(daoButton);
daoButtonWithBadge.getStyleClass().add("new");
JFXBadge accountButtonWithBadge = new JFXBadge(accountButton);
accountButtonWithBadge.getStyleClass().add("new");
JFXBadge settingsButtonWithBadge = new JFXBadge(settingsButton); JFXBadge settingsButtonWithBadge = new JFXBadge(settingsButton);
settingsButtonWithBadge.getStyleClass().add("new"); settingsButtonWithBadge.getStyleClass().add("new");
@ -326,9 +323,8 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
primaryNav.getStyleClass().add("nav-primary"); primaryNav.getStyleClass().add("nav-primary");
HBox.setHgrow(primaryNav, Priority.SOMETIMES); HBox.setHgrow(primaryNav, Priority.SOMETIMES);
HBox secondaryNav = new HBox(supportButtonWithBadge, getNavigationSeparator(), HBox secondaryNav = new HBox(supportButtonWithBadge, getNavigationSpacer(), settingsButtonWithBadge,
settingsButtonWithBadge, getNavigationSeparator(), accountButtonWithBadge, getNavigationSpacer(), accountButton, getNavigationSpacer(), daoButton);
getNavigationSeparator(), daoButtonWithBadge);
secondaryNav.getStyleClass().add("nav-secondary"); secondaryNav.getStyleClass().add("nav-secondary");
HBox.setHgrow(secondaryNav, Priority.SOMETIMES); HBox.setHgrow(secondaryNav, Priority.SOMETIMES);
@ -371,8 +367,6 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
setupBadge(portfolioButtonWithBadge, model.getNumPendingTrades(), model.getShowPendingTradesNotification()); setupBadge(portfolioButtonWithBadge, model.getNumPendingTrades(), model.getShowPendingTradesNotification());
setupBadge(supportButtonWithBadge, model.getNumOpenSupportTickets(), model.getShowOpenSupportTicketsNotification()); setupBadge(supportButtonWithBadge, model.getNumOpenSupportTickets(), model.getShowOpenSupportTicketsNotification());
setupBadge(daoButtonWithBadge, new SimpleStringProperty(Res.get("shared.new")), model.getShowDaoUpdatesNotification());
setupBadge(accountButtonWithBadge, new SimpleStringProperty(Res.get("shared.new")), model.getShowAccountUpdatesNotification());
setupBadge(settingsButtonWithBadge, new SimpleStringProperty(Res.get("shared.new")), model.getShowSettingsUpdatesNotification()); setupBadge(settingsButtonWithBadge, new SimpleStringProperty(Res.get("shared.new")), model.getShowSettingsUpdatesNotification());
navigation.addListener(viewPath -> { navigation.addListener(viewPath -> {
@ -443,6 +437,13 @@ public class MainView extends InitializableView<StackPane, MainViewModel>
return separator; return separator;
} }
@NotNull
private Region getNavigationSpacer() {
final Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
return spacer;
}
private Tuple2<Label, VBox> getBalanceBox(String text) { private Tuple2<Label, VBox> getBalanceBox(String text) {
Label balanceDisplay = new Label(); Label balanceDisplay = new Label();
balanceDisplay.getStyleClass().add("nav-balance-display"); balanceDisplay.getStyleClass().add("nav-balance-display");

View file

@ -25,7 +25,6 @@ import bisq.desktop.main.overlays.Overlay;
import bisq.desktop.main.overlays.notifications.NotificationCenter; import bisq.desktop.main.overlays.notifications.NotificationCenter;
import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.DisplayAlertMessageWindow; import bisq.desktop.main.overlays.windows.DisplayAlertMessageWindow;
import bisq.desktop.main.overlays.windows.NewTradeProtocolLaunchWindow;
import bisq.desktop.main.overlays.windows.TacWindow; import bisq.desktop.main.overlays.windows.TacWindow;
import bisq.desktop.main.overlays.windows.TorNetworkSettingsWindow; import bisq.desktop.main.overlays.windows.TorNetworkSettingsWindow;
import bisq.desktop.main.overlays.windows.UpdateRevolutAccountWindow; import bisq.desktop.main.overlays.windows.UpdateRevolutAccountWindow;
@ -282,7 +281,6 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
// in MainView showAppScreen handler // in MainView showAppScreen handler
notificationCenter.onAllServicesAndViewsInitialized(); notificationCenter.onAllServicesAndViewsInitialized();
maybeAddNewTradeProtocolLaunchWindowToQueue();
maybeShowPopupsFromQueue(); maybeShowPopupsFromQueue();
} }
@ -390,7 +388,11 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
// We copy the array as we will mutate it later // We copy the array as we will mutate it later
showRevolutAccountUpdateWindow(new ArrayList<>(revolutAccountList)); showRevolutAccountUpdateWindow(new ArrayList<>(revolutAccountList));
}); });
bisqSetup.setOsxKeyLoggerWarningHandler(() -> {
new Popup().warning(Res.get("popup.warning.osxKeyLoggerWarning"))
.closeButtonText(Res.get("shared.iUnderstand"))
.show();
});
corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> new Popup() corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> new Popup()
.warning(Res.get("popup.warning.incompatibleDB", files.toString(), config.appDataDir)) .warning(Res.get("popup.warning.incompatibleDB", files.toString(), config.appDataDir))
@ -683,26 +685,10 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
return daoPresentation.getShowDaoUpdatesNotification(); return daoPresentation.getShowDaoUpdatesNotification();
} }
public BooleanProperty getShowAccountUpdatesNotification() {
return accountPresentation.getShowAccountUpdatesNotification();
}
public BooleanProperty getShowSettingsUpdatesNotification() { public BooleanProperty getShowSettingsUpdatesNotification() {
return settingsPresentation.getShowSettingsUpdatesNotification(); return settingsPresentation.getShowSettingsUpdatesNotification();
} }
private void maybeAddNewTradeProtocolLaunchWindowToQueue() {
String newTradeProtocolWithAccountSigningLaunchPopupKey = "newTradeProtocolWithAccountSigningLaunchPopup";
if (DontShowAgainLookup.showAgain(newTradeProtocolWithAccountSigningLaunchPopupKey)) {
NewTradeProtocolLaunchWindow newTradeProtocolLaunchWindow = new NewTradeProtocolLaunchWindow()
.headLine(Res.get("popup.news.launch.headline"));
newTradeProtocolLaunchWindow.setDisplayOrderPriority(1);
popupQueue.add(newTradeProtocolLaunchWindow);
DontShowAgainLookup.dontShowAgain(newTradeProtocolWithAccountSigningLaunchPopupKey, true);
}
}
private void maybeShowPopupsFromQueue() { private void maybeShowPopupsFromQueue() {
if (!popupQueue.isEmpty()) { if (!popupQueue.isEmpty()) {
Overlay<?> overlay = popupQueue.poll(); Overlay<?> overlay = popupQueue.poll();

View file

@ -33,6 +33,7 @@ import bisq.desktop.main.account.content.seedwords.SeedWordsView;
import bisq.desktop.main.account.register.arbitrator.ArbitratorRegistrationView; import bisq.desktop.main.account.register.arbitrator.ArbitratorRegistrationView;
import bisq.desktop.main.account.register.mediator.MediatorRegistrationView; import bisq.desktop.main.account.register.mediator.MediatorRegistrationView;
import bisq.desktop.main.account.register.refundagent.RefundAgentRegistrationView; import bisq.desktop.main.account.register.refundagent.RefundAgentRegistrationView;
import bisq.desktop.main.account.register.signing.SigningView;
import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.presentation.AccountPresentation; import bisq.desktop.main.presentation.AccountPresentation;
@ -77,6 +78,7 @@ public class AccountView extends ActivatableView<TabPane, Void> {
private Tab arbitratorRegistrationTab; private Tab arbitratorRegistrationTab;
private Tab mediatorRegistrationTab; private Tab mediatorRegistrationTab;
private Tab refundAgentRegistrationTab; private Tab refundAgentRegistrationTab;
private Tab signingTab;
private ArbitratorRegistrationView arbitratorRegistrationView; private ArbitratorRegistrationView arbitratorRegistrationView;
private MediatorRegistrationView mediatorRegistrationView; private MediatorRegistrationView mediatorRegistrationView;
private RefundAgentRegistrationView refundAgentRegistrationView; private RefundAgentRegistrationView refundAgentRegistrationView;
@ -110,6 +112,8 @@ public class AccountView extends ActivatableView<TabPane, Void> {
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
} else if (refundAgentRegistrationTab == null && viewPath.get(2).equals(RefundAgentRegistrationView.class)) { } else if (refundAgentRegistrationTab == null && viewPath.get(2).equals(RefundAgentRegistrationView.class)) {
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
} else if (signingTab == null && viewPath.get(2).equals(SigningView.class)) {
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
} else { } else {
loadView(viewPath.tip()); loadView(viewPath.tip());
} }
@ -120,27 +124,23 @@ public class AccountView extends ActivatableView<TabPane, Void> {
keyEventEventHandler = event -> { keyEventEventHandler = event -> {
if (Utilities.isAltOrCtrlPressed(KeyCode.D, event) && mediatorRegistrationTab == null) { if (Utilities.isAltOrCtrlPressed(KeyCode.D, event) && mediatorRegistrationTab == null) {
if (arbitratorRegistrationTab != null) { closeOtherExtraTabs(mediatorRegistrationTab);
root.getTabs().remove(arbitratorRegistrationTab);
}
if (refundAgentRegistrationTab != null) {
root.getTabs().remove(refundAgentRegistrationTab);
}
mediatorRegistrationTab = new Tab(Res.get("account.tab.mediatorRegistration").toUpperCase()); mediatorRegistrationTab = new Tab(Res.get("account.tab.mediatorRegistration").toUpperCase());
mediatorRegistrationTab.setClosable(true); mediatorRegistrationTab.setClosable(true);
root.getTabs().add(mediatorRegistrationTab); root.getTabs().add(mediatorRegistrationTab);
navigation.navigateTo(MainView.class, AccountView.class, MediatorRegistrationView.class); navigation.navigateTo(MainView.class, AccountView.class, MediatorRegistrationView.class);
} else if (Utilities.isAltOrCtrlPressed(KeyCode.N, event) && refundAgentRegistrationTab == null) { } else if (Utilities.isAltOrCtrlPressed(KeyCode.N, event) && refundAgentRegistrationTab == null) {
if (arbitratorRegistrationTab != null) { closeOtherExtraTabs(refundAgentRegistrationTab);
root.getTabs().remove(arbitratorRegistrationTab);
}
if (mediatorRegistrationTab != null) {
root.getTabs().remove(mediatorRegistrationTab);
}
refundAgentRegistrationTab = new Tab(Res.get("account.tab.refundAgentRegistration").toUpperCase()); refundAgentRegistrationTab = new Tab(Res.get("account.tab.refundAgentRegistration").toUpperCase());
refundAgentRegistrationTab.setClosable(true); refundAgentRegistrationTab.setClosable(true);
root.getTabs().add(refundAgentRegistrationTab); root.getTabs().add(refundAgentRegistrationTab);
navigation.navigateTo(MainView.class, AccountView.class, RefundAgentRegistrationView.class); navigation.navigateTo(MainView.class, AccountView.class, RefundAgentRegistrationView.class);
} else if (Utilities.isAltOrCtrlPressed(KeyCode.I, event) && signingTab == null) {
closeOtherExtraTabs(signingTab);
signingTab = new Tab(Res.get("account.tab.signing").toUpperCase());
signingTab.setClosable(true);
root.getTabs().add(signingTab);
navigation.navigateTo(MainView.class, AccountView.class, SigningView.class);
} }
}; };
@ -151,6 +151,8 @@ public class AccountView extends ActivatableView<TabPane, Void> {
navigation.navigateTo(MainView.class, AccountView.class, MediatorRegistrationView.class); navigation.navigateTo(MainView.class, AccountView.class, MediatorRegistrationView.class);
} else if (refundAgentRegistrationTab != null && selectedTab != refundAgentRegistrationTab) { } else if (refundAgentRegistrationTab != null && selectedTab != refundAgentRegistrationTab) {
navigation.navigateTo(MainView.class, AccountView.class, RefundAgentRegistrationView.class); navigation.navigateTo(MainView.class, AccountView.class, RefundAgentRegistrationView.class);
} else if (signingTab != null && !selectedTab.equals(signingTab)) {
navigation.navigateTo(MainView.class, AccountView.class, SigningView.class);
} else if (newValue == fiatAccountsTab && selectedTab != fiatAccountsTab) { } else if (newValue == fiatAccountsTab && selectedTab != fiatAccountsTab) {
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
} else if (newValue == altcoinAccountsTab && selectedTab != altcoinAccountsTab) { } else if (newValue == altcoinAccountsTab && selectedTab != altcoinAccountsTab) {
@ -177,9 +179,27 @@ public class AccountView extends ActivatableView<TabPane, Void> {
if (removedTabs.size() == 1 && removedTabs.get(0).equals(refundAgentRegistrationTab)) if (removedTabs.size() == 1 && removedTabs.get(0).equals(refundAgentRegistrationTab))
onRefundAgentRegistrationTabRemoved(); onRefundAgentRegistrationTabRemoved();
if (removedTabs.size() == 1 && removedTabs.get(0).equals(signingTab))
onSigningTabRemoved();
}; };
} }
private void closeOtherExtraTabs(Tab newTab) {
if (arbitratorRegistrationTab != null && !arbitratorRegistrationTab.equals(newTab)) {
root.getTabs().remove(arbitratorRegistrationTab);
}
if (mediatorRegistrationTab != null && !mediatorRegistrationTab.equals(newTab)) {
root.getTabs().remove(mediatorRegistrationTab);
}
if (refundAgentRegistrationTab != null && !refundAgentRegistrationTab.equals(newTab)) {
root.getTabs().remove(refundAgentRegistrationTab);
}
if (signingTab != null && !signingTab.equals(newTab)) {
root.getTabs().remove(signingTab);
}
}
private void onArbitratorRegistrationTabRemoved() { private void onArbitratorRegistrationTabRemoved() {
arbitratorRegistrationTab = null; arbitratorRegistrationTab = null;
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
@ -195,6 +215,11 @@ public class AccountView extends ActivatableView<TabPane, Void> {
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
} }
private void onSigningTabRemoved() {
signingTab = null;
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
}
@Override @Override
protected void activate() { protected void activate() {
// Hide account new badge if user saw this section // Hide account new badge if user saw this section
@ -216,6 +241,8 @@ public class AccountView extends ActivatableView<TabPane, Void> {
navigation.navigateTo(MainView.class, AccountView.class, MediatorRegistrationView.class); navigation.navigateTo(MainView.class, AccountView.class, MediatorRegistrationView.class);
else if (refundAgentRegistrationTab != null) else if (refundAgentRegistrationTab != null)
navigation.navigateTo(MainView.class, AccountView.class, RefundAgentRegistrationView.class); navigation.navigateTo(MainView.class, AccountView.class, RefundAgentRegistrationView.class);
else if (signingTab != null)
navigation.navigateTo(MainView.class, AccountView.class, SigningView.class);
else if (root.getSelectionModel().getSelectedItem() == fiatAccountsTab) else if (root.getSelectionModel().getSelectedItem() == fiatAccountsTab)
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class); navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
else if (root.getSelectionModel().getSelectedItem() == altcoinAccountsTab) else if (root.getSelectionModel().getSelectedItem() == altcoinAccountsTab)
@ -274,6 +301,10 @@ public class AccountView extends ActivatableView<TabPane, Void> {
refundAgentRegistrationView = (RefundAgentRegistrationView) view; refundAgentRegistrationView = (RefundAgentRegistrationView) view;
refundAgentRegistrationView.onTabSelection(true); refundAgentRegistrationView.onTabSelection(true);
} }
} else if (view instanceof SigningView) {
if (signingTab != null) {
selectedTab = signingTab;
}
} else if (view instanceof FiatAccountsView) { } else if (view instanceof FiatAccountsView) {
selectedTab = fiatAccountsTab; selectedTab = fiatAccountsTab;
} else if (view instanceof AltCoinAccountsView) { } else if (view instanceof AltCoinAccountsView) {

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ This file is part of Bisq.
~
~ Bisq is free software: you can redistribute it and/or modify it
~ under the terms of the GNU Affero General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or (at
~ your option) any later version.
~
~ Bisq is distributed in the hope that it will be useful, but WITHOUT
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
~ License for more details.
~
~ You should have received a copy of the GNU Affero General Public License
~ along with Bisq. If not, see <http://www.gnu.org/licenses/>.
-->
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.geometry.Insets?>
<AnchorPane fx:id="root" fx:controller="bisq.desktop.main.account.register.signing.SigningView"
xmlns:fx="http://javafx.com/fxml">
<padding>
<Insets left="10.0" right="10.0"/>
</padding>
</AnchorPane>

View file

@ -0,0 +1,79 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.desktop.main.account.register.signing;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.main.overlays.windows.SignPaymentAccountsWindow;
import bisq.desktop.main.overlays.windows.SignSpecificWitnessWindow;
import bisq.desktop.main.overlays.windows.SignUnsignedPubKeysWindow;
import bisq.common.util.Utilities;
import javax.inject.Inject;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.event.EventHandler;
@FxmlView
public class SigningView extends ActivatableView<AnchorPane, Void> {
private final SignPaymentAccountsWindow signPaymentAccountsWindow;
private final SignSpecificWitnessWindow signSpecificWitnessWindow;
private final SignUnsignedPubKeysWindow signUnsignedPubKeysWindow;
private EventHandler<KeyEvent> keyEventEventHandler;
private Scene scene;
@Inject
public SigningView(SignPaymentAccountsWindow signPaymentAccountsWindow,
SignSpecificWitnessWindow signSpecificWitnessWindow,
SignUnsignedPubKeysWindow signUnsignedPubKeysWindow) {
this.signPaymentAccountsWindow = signPaymentAccountsWindow;
this.signSpecificWitnessWindow = signSpecificWitnessWindow;
this.signUnsignedPubKeysWindow = signUnsignedPubKeysWindow;
keyEventEventHandler = this::handleKeyPressed;
}
@Override
protected void activate() {
scene = root.getScene();
if (scene != null)
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
}
@Override
protected void deactivate() {
if (scene != null)
scene.removeEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
}
protected void handleKeyPressed(KeyEvent event) {
if (Utilities.isAltOrCtrlPressed(KeyCode.S, event)) {
signPaymentAccountsWindow.show();
} else if (Utilities.isAltOrCtrlPressed(KeyCode.P, event)) {
signSpecificWitnessWindow.show();
} else if (Utilities.isAltOrCtrlPressed(KeyCode.O, event)) {
signUnsignedPubKeysWindow.show();
}
}
}

View file

@ -1,191 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.desktop.main.overlays.windows;
import bisq.desktop.app.BisqAppMain;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.ExternalHyperlink;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.main.overlays.Overlay;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.GUIUtil;
import bisq.core.locale.Res;
import bisq.core.user.DontShowAgainLookup;
import de.jensd.fx.fontawesome.AwesomeIcon;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import static bisq.desktop.util.FormBuilder.addLabel;
@Slf4j
public class NewTradeProtocolLaunchWindow extends Overlay<NewTradeProtocolLaunchWindow> {
///////////////////////////////////////////////////////////////////////////////////////////
// Public API
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void show() {
width = 680;
hideCloseButton();
super.show();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Protected
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void createGridPane() {
super.createGridPane();
gridPane.setVgap(10);
gridPane.getColumnConstraints().get(0).setHalignment(HPos.CENTER);
gridPane.setPadding(new Insets(84));
}
@Override
protected void addHeadLine() {
Label versionNumber = new AutoTooltipLabel(BisqAppMain.DEFAULT_APP_NAME + " v1.2");
versionNumber.getStyleClass().add("news-version");
HBox.setHgrow(versionNumber, Priority.ALWAYS);
versionNumber.setMaxWidth(Double.MAX_VALUE);
Button closeButton = FormBuilder.getIconButton(MaterialDesignIcon.CLOSE,
"close-icon", "1.231em");
closeButton.setOnAction(event -> hide());
HBox.setHgrow(closeButton, Priority.NEVER);
HBox header = new HBox(versionNumber, closeButton);
GridPane.setRowIndex(header, ++rowIndex);
GridPane.setColumnSpan(header, 2);
gridPane.getChildren().add(header);
headLineLabel = addLabel(gridPane, ++rowIndex, headLine);
headLineLabel.getStyleClass().add("popup-headline-information");
headlineIcon = new Label();
headlineIcon.getStyleClass().add("popup-icon-information");
headlineIcon.setManaged(true);
headlineIcon.setVisible(true);
FormBuilder.getIconForLabel(AwesomeIcon.INFO_SIGN, headlineIcon, "1em");
headLineLabel.setGraphic(headlineIcon);
GridPane.setHalignment(headLineLabel, HPos.LEFT);
GridPane.setColumnSpan(headLineLabel, 2);
}
@Override
protected void addMessage() {
createContent();
}
@Override
protected void onShow() {
display();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void createContent() {
HBox content = new HBox();
content.setMinWidth(680);
content.setAlignment(Pos.TOP_LEFT);
content.setSpacing(40);
VBox accountSigning = getFeatureBox(Res.get("popup.news.launch.accountSigning.headline"),
Res.get("popup.news.launch.accountSigning.description"),
"image-account-signing-screenshot",
"https://docs.bisq.network/payment-methods#account-signing");
VBox newTradeProtocol = getFeatureBox(Res.get("popup.news.launch.ntp.headline"),
Res.get("popup.news.launch.ntp.description"),
"image-new-trade-protocol-screenshot",
"https://docs.bisq.network/trading-rules");
content.getChildren().addAll(accountSigning, new Separator(Orientation.VERTICAL), newTradeProtocol);
GridPane.setMargin(content, new Insets(10, 0, 0, 0));
GridPane.setRowIndex(content, ++rowIndex);
GridPane.setColumnSpan(content, 2);
GridPane.setHgrow(content, Priority.ALWAYS);
gridPane.getChildren().add(content);
}
@NotNull
private VBox getFeatureBox(String title, String description, String imageId, String url) {
Label featureTitle = new Label(title);
featureTitle.setTextAlignment(TextAlignment.LEFT);
featureTitle.getStyleClass().add("news-feature-headline");
ImageView sectionScreenshot = new ImageView();
sectionScreenshot.setId(imageId);
HBox imageContainer = new HBox(sectionScreenshot);
imageContainer.getStyleClass().add("news-feature-image");
Label featureDescription = new Label(description);
featureDescription.setTextAlignment(TextAlignment.LEFT);
featureDescription.getStyleClass().add("news-feature-description");
featureDescription.setWrapText(true);
HyperlinkWithIcon learnMore = new ExternalHyperlink(Res.get("shared.learnMore"), "highlight");
learnMore.setOnAction(event -> {
if (DontShowAgainLookup.showAgain(GUIUtil.OPEN_WEB_PAGE_KEY)) {
hide();
GUIUtil.openWebPage(url, true, () -> {
this.rowIndex = -1;
this.show();
});
} else {
GUIUtil.openWebPage(url);
}
});
VBox vBox = new VBox(featureTitle, imageContainer, featureDescription, learnMore);
vBox.setAlignment(Pos.CENTER_LEFT);
vBox.setSpacing(20);
vBox.setMaxWidth(300);
return vBox;
}
}

View file

@ -29,6 +29,7 @@ import bisq.core.support.dispute.Dispute;
import bisq.core.support.dispute.arbitration.ArbitrationManager; import bisq.core.support.dispute.arbitration.ArbitrationManager;
import bisq.core.support.dispute.arbitration.TraderDataItem; import bisq.core.support.dispute.arbitration.TraderDataItem;
import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import bisq.core.support.dispute.mediation.MediationManager;
import bisq.core.util.FormattingUtils; import bisq.core.util.FormattingUtils;
import bisq.common.config.Config; import bisq.common.config.Config;
@ -88,18 +89,24 @@ public class SignPaymentAccountsWindow extends Overlay<SignPaymentAccountsWindow
private final AccountAgeWitnessService accountAgeWitnessService; private final AccountAgeWitnessService accountAgeWitnessService;
private final ArbitratorManager arbitratorManager; private final ArbitratorManager arbitratorManager;
private final ArbitrationManager arbitrationManager; private final ArbitrationManager arbitrationManager;
private final MediationManager mediationManager;
private final String appName; private final String appName;
private final boolean useDevPrivilegeKeys;
@Inject @Inject
public SignPaymentAccountsWindow(AccountAgeWitnessService accountAgeWitnessService, public SignPaymentAccountsWindow(AccountAgeWitnessService accountAgeWitnessService,
ArbitratorManager arbitratorManager, ArbitratorManager arbitratorManager,
ArbitrationManager arbitrationManager, ArbitrationManager arbitrationManager,
@Named(Config.APP_NAME) String appName) { MediationManager mediationManager,
@Named(Config.APP_NAME) String appName,
@Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
this.accountAgeWitnessService = accountAgeWitnessService; this.accountAgeWitnessService = accountAgeWitnessService;
this.arbitratorManager = arbitratorManager; this.arbitratorManager = arbitratorManager;
this.arbitrationManager = arbitrationManager; this.arbitrationManager = arbitrationManager;
this.mediationManager = mediationManager;
this.appName = appName; this.appName = appName;
this.useDevPrivilegeKeys = useDevPrivilegeKeys;
} }
@Override @Override
@ -193,7 +200,9 @@ public class SignPaymentAccountsWindow extends Overlay<SignPaymentAccountsWindow
++rowIndex, Res.get("popup.accountSigning.confirmSelectedAccounts.headline")); ++rowIndex, Res.get("popup.accountSigning.confirmSelectedAccounts.headline"));
GridPane.setRowSpan(selectedPaymentAccountsTuple.third, 2); GridPane.setRowSpan(selectedPaymentAccountsTuple.third, 2);
selectedPaymentAccountsList = selectedPaymentAccountsTuple.second; selectedPaymentAccountsList = selectedPaymentAccountsTuple.second;
ObservableList<Dispute> disputesAsObservableList = arbitrationManager.getDisputesAsObservableList(); ObservableList<Dispute> disputesAsObservableList = useDevPrivilegeKeys ?
mediationManager.getDisputesAsObservableList()
: arbitrationManager.getDisputesAsObservableList();
long safeDate = datePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000; long safeDate = datePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
List<TraderDataItem> traderDataItemList; List<TraderDataItem> traderDataItemList;
StringBuilder sb = new StringBuilder("Summary for ").append(appName).append("\n"); StringBuilder sb = new StringBuilder("Summary for ").append(appName).append("\n");

View file

@ -102,6 +102,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
private final CoinFormatter formatter; private final CoinFormatter formatter;
private final PrivateNotificationManager privateNotificationManager; private final PrivateNotificationManager privateNotificationManager;
private final boolean useDevPrivilegeKeys; private final boolean useDevPrivilegeKeys;
private final boolean useDevModeHeader;
private final Preferences preferences; private final Preferences preferences;
@FXML @FXML
TableView<PendingTradesListItem> tableView; TableView<PendingTradesListItem> tableView;
@ -141,13 +142,15 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
PrivateNotificationManager privateNotificationManager, PrivateNotificationManager privateNotificationManager,
Preferences preferences, Preferences preferences,
@Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys,
@Named(Config.USE_DEV_MODE_HEADER) boolean useDevModeHeader) {
super(model); super(model);
this.tradeDetailsWindow = tradeDetailsWindow; this.tradeDetailsWindow = tradeDetailsWindow;
this.formatter = formatter; this.formatter = formatter;
this.privateNotificationManager = privateNotificationManager; this.privateNotificationManager = privateNotificationManager;
this.preferences = preferences; this.preferences = preferences;
this.useDevPrivilegeKeys = useDevPrivilegeKeys; this.useDevPrivilegeKeys = useDevPrivilegeKeys;
this.useDevModeHeader = useDevModeHeader;
} }
@Override @Override
@ -412,7 +415,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
}); });
Scene scene = new Scene(pane); Scene scene = new Scene(pane);
CssTheme.loadSceneStyles(scene, preferences.getCssTheme()); CssTheme.loadSceneStyles(scene, preferences.getCssTheme(), useDevModeHeader);
scene.addEventHandler(KeyEvent.KEY_RELEASED, ev -> { scene.addEventHandler(KeyEvent.KEY_RELEASED, ev -> {
if (ev.getCode() == KeyCode.ESCAPE) { if (ev.getCode() == KeyCode.ESCAPE) {
ev.consume(); ev.consume();

View file

@ -17,14 +17,9 @@
package bisq.desktop.main.support.dispute.agent.arbitration; package bisq.desktop.main.support.dispute.agent.arbitration;
import bisq.common.config.Config;
import bisq.common.util.Utilities;
import bisq.desktop.common.view.FxmlView; import bisq.desktop.common.view.FxmlView;
import bisq.desktop.main.overlays.windows.ContractWindow; import bisq.desktop.main.overlays.windows.ContractWindow;
import bisq.desktop.main.overlays.windows.DisputeSummaryWindow; import bisq.desktop.main.overlays.windows.DisputeSummaryWindow;
import bisq.desktop.main.overlays.windows.SignPaymentAccountsWindow;
import bisq.desktop.main.overlays.windows.SignSpecificWitnessWindow;
import bisq.desktop.main.overlays.windows.SignUnsignedPubKeysWindow;
import bisq.desktop.main.overlays.windows.TradeDetailsWindow; import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
import bisq.desktop.main.support.dispute.agent.DisputeAgentView; import bisq.desktop.main.support.dispute.agent.DisputeAgentView;
@ -39,21 +34,15 @@ import bisq.core.trade.TradeManager;
import bisq.core.util.FormattingUtils; import bisq.core.util.FormattingUtils;
import bisq.core.util.coin.CoinFormatter; import bisq.core.util.coin.CoinFormatter;
import bisq.common.config.Config;
import bisq.common.crypto.KeyRing; import bisq.common.crypto.KeyRing;
import javax.inject.Named;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
@FxmlView @FxmlView
public class ArbitratorView extends DisputeAgentView { public class ArbitratorView extends DisputeAgentView {
private final SignPaymentAccountsWindow signPaymentAccountsWindow;
private final SignSpecificWitnessWindow signSpecificWitnessWindow;
private final SignUnsignedPubKeysWindow signUnsignedPubKeysWindow;
@Inject @Inject
public ArbitratorView(ArbitrationManager arbitrationManager, public ArbitratorView(ArbitrationManager arbitrationManager,
KeyRing keyRing, KeyRing keyRing,
@ -64,10 +53,7 @@ public class ArbitratorView extends DisputeAgentView {
ContractWindow contractWindow, ContractWindow contractWindow,
TradeDetailsWindow tradeDetailsWindow, TradeDetailsWindow tradeDetailsWindow,
AccountAgeWitnessService accountAgeWitnessService, AccountAgeWitnessService accountAgeWitnessService,
@Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys, @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
SignPaymentAccountsWindow signPaymentAccountsWindow,
SignSpecificWitnessWindow signSpecificWitnessWindow,
SignUnsignedPubKeysWindow signUnsignedPubKeysWindow) {
super(arbitrationManager, super(arbitrationManager,
keyRing, keyRing,
tradeManager, tradeManager,
@ -78,9 +64,6 @@ public class ArbitratorView extends DisputeAgentView {
tradeDetailsWindow, tradeDetailsWindow,
accountAgeWitnessService, accountAgeWitnessService,
useDevPrivilegeKeys); useDevPrivilegeKeys);
this.signPaymentAccountsWindow = signPaymentAccountsWindow;
this.signSpecificWitnessWindow = signSpecificWitnessWindow;
this.signUnsignedPubKeysWindow = signUnsignedPubKeysWindow;
} }
@Override @Override
@ -92,15 +75,4 @@ public class ArbitratorView extends DisputeAgentView {
protected DisputeSession getConcreteDisputeChatSession(Dispute dispute) { protected DisputeSession getConcreteDisputeChatSession(Dispute dispute) {
return new ArbitrationSession(dispute, disputeManager.isTrader(dispute)); return new ArbitrationSession(dispute, disputeManager.isTrader(dispute));
} }
@Override
protected void handleKeyPressed(KeyEvent event) {
if (Utilities.isAltOrCtrlPressed(KeyCode.S, event)) {
signPaymentAccountsWindow.show();
} else if (Utilities.isAltOrCtrlPressed(KeyCode.P, event)) {
signSpecificWitnessWindow.show();
} else if (Utilities.isAltOrCtrlPressed(KeyCode.O, event)) {
signUnsignedPubKeysWindow.show();
}
}
} }

View file

@ -0,0 +1,4 @@
.root {
-bs-rd-nav-background: #841413;
-bs-rd-nav-primary-background: #841413;
}

View file

@ -24,12 +24,14 @@ public class CssTheme {
public static final int CSS_THEME_DARK = 1; public static final int CSS_THEME_DARK = 1;
private static int currentCSSTheme; private static int currentCSSTheme;
private static boolean useDevHeader;
public static void loadSceneStyles(Scene scene, int cssTheme) { public static void loadSceneStyles(Scene scene, int cssTheme, boolean devHeader) {
String cssThemeFolder = "/bisq/desktop/"; String cssThemeFolder = "/bisq/desktop/";
String cssThemeFile = ""; String cssThemeFile = "";
currentCSSTheme = cssTheme; currentCSSTheme = cssTheme;
useDevHeader = devHeader;
switch (cssTheme) { switch (cssTheme) {
@ -52,6 +54,8 @@ public class CssTheme {
// load theme last to allow override // load theme last to allow override
cssThemeFolder + cssThemeFile cssThemeFolder + cssThemeFile
); );
if (useDevHeader)
scene.getStylesheets().add(cssThemeFolder + "theme-dev.css");
} }
public static boolean isDarkTheme() { public static boolean isDarkTheme() {

View file

@ -42,7 +42,7 @@ dependencyVerification {
'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729', 'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729',
'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9', 'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9',
'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2', 'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2',
'com.jfoenix:jfoenix:8060235fec5eb49617ec8d81d379e8c945f6cc722d0645e97190045100de2084', 'com.jfoenix:jfoenix:4739e37a05e67c3bc9d5b391a1b93717b5a48fa872992616b0964d3f827f8fe6',
'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4', 'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf', 'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf',