Merge pull request #1515 from ManfredKarrer/app-startup

This will be a series of small scale and low risk changes for improving startup
This commit is contained in:
Chris Beams 2018-04-18 13:31:46 +02:00
commit 4e57a9ee55
No known key found for this signature in database
GPG key ID: 3D214F8F5BC5ED73
18 changed files with 250 additions and 383 deletions

View file

@ -27,6 +27,7 @@ import bisq.desktop.main.funds.transactions.TradableRepository;
import bisq.desktop.main.funds.transactions.TransactionAwareTradableFactory; import bisq.desktop.main.funds.transactions.TransactionAwareTradableFactory;
import bisq.desktop.main.funds.transactions.TransactionListItemFactory; import bisq.desktop.main.funds.transactions.TransactionListItemFactory;
import bisq.desktop.main.offer.offerbook.OfferBook; import bisq.desktop.main.offer.offerbook.OfferBook;
import bisq.desktop.main.overlays.notifications.NotificationCenter;
import bisq.desktop.main.overlays.windows.TorNetworkSettingsWindow; import bisq.desktop.main.overlays.windows.TorNetworkSettingsWindow;
import bisq.desktop.util.BSFormatter; import bisq.desktop.util.BSFormatter;
import bisq.desktop.util.BsqFormatter; import bisq.desktop.util.BsqFormatter;
@ -42,29 +43,27 @@ import org.springframework.core.env.Environment;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.google.inject.name.Names; import com.google.inject.name.Names;
import javafx.stage.Stage;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class DesktopModule extends AppModule { public class DesktopModule extends AppModule {
private final Stage primaryStage;
public DesktopModule(Environment environment, Stage primaryStage) { public DesktopModule(Environment environment) {
super(environment); super(environment);
this.primaryStage = primaryStage;
} }
@Override @Override
protected void configure() { protected void configure() {
bind(InjectorViewFactory.class).in(Singleton.class); bind(InjectorViewFactory.class).in(Singleton.class);
bind(ViewFactory.class).to(InjectorViewFactory.class); bind(ViewFactory.class).to(InjectorViewFactory.class);
bind(CachingViewLoader.class).in(Singleton.class);
bind(ResourceBundle.class).toInstance(Res.getResourceBundle()); bind(ResourceBundle.class).toInstance(Res.getResourceBundle());
bind(ViewLoader.class).to(FxmlViewLoader.class).in(Singleton.class); bind(ViewLoader.class).to(FxmlViewLoader.class).in(Singleton.class);
bind(CachingViewLoader.class).in(Singleton.class); bind(CachingViewLoader.class).in(Singleton.class);
bind(Navigation.class).in(Singleton.class); bind(Navigation.class).in(Singleton.class);
bind(NotificationCenter.class).in(Singleton.class);
bind(OfferBook.class).in(Singleton.class); bind(OfferBook.class).in(Singleton.class);
bind(BSFormatter.class).in(Singleton.class); bind(BSFormatter.class).in(Singleton.class);
@ -73,8 +72,6 @@ public class DesktopModule extends AppModule {
bind(Transitions.class).in(Singleton.class); bind(Transitions.class).in(Singleton.class);
bind(Stage.class).toInstance(primaryStage);
bind(TradableRepository.class).in(Singleton.class); bind(TradableRepository.class).in(Singleton.class);
bind(TransactionListItemFactory.class).in(Singleton.class); bind(TransactionListItemFactory.class).in(Singleton.class);
bind(TransactionAwareTradableFactory.class).in(Singleton.class); bind(TransactionAwareTradableFactory.class).in(Singleton.class);

View file

@ -18,11 +18,9 @@
package bisq.desktop.app; package bisq.desktop.app;
import bisq.desktop.SystemTray; import bisq.desktop.SystemTray;
import bisq.desktop.common.UITimer;
import bisq.desktop.common.view.CachingViewLoader; import bisq.desktop.common.view.CachingViewLoader;
import bisq.desktop.common.view.View; import bisq.desktop.common.view.View;
import bisq.desktop.common.view.ViewLoader; import bisq.desktop.common.view.ViewLoader;
import bisq.desktop.common.view.guice.InjectorViewFactory;
import bisq.desktop.components.AutoTooltipLabel; import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.main.MainView; import bisq.desktop.main.MainView;
import bisq.desktop.main.debug.DebugView; import bisq.desktop.main.debug.DebugView;
@ -32,38 +30,25 @@ import bisq.desktop.main.overlays.windows.FilterWindow;
import bisq.desktop.main.overlays.windows.ManualPayoutTxWindow; import bisq.desktop.main.overlays.windows.ManualPayoutTxWindow;
import bisq.desktop.main.overlays.windows.SendAlertMessageWindow; import bisq.desktop.main.overlays.windows.SendAlertMessageWindow;
import bisq.desktop.main.overlays.windows.ShowWalletDataWindow; import bisq.desktop.main.overlays.windows.ShowWalletDataWindow;
import bisq.desktop.setup.DesktopPersistedDataHost;
import bisq.desktop.util.ImageUtil; import bisq.desktop.util.ImageUtil;
import bisq.core.alert.AlertManager; import bisq.core.alert.AlertManager;
import bisq.core.app.AppOptionKeys; import bisq.core.app.AppOptionKeys;
import bisq.core.app.BisqEnvironment;
import bisq.core.arbitration.ArbitratorManager;
import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.WalletService; import bisq.core.btc.wallet.WalletService;
import bisq.core.btc.wallet.WalletsManager; import bisq.core.btc.wallet.WalletsManager;
import bisq.core.btc.wallet.WalletsSetup;
import bisq.core.dao.DaoSetup;
import bisq.core.filter.FilterManager; import bisq.core.filter.FilterManager;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.core.offer.OpenOfferManager;
import bisq.core.setup.CorePersistedDataHost;
import bisq.core.setup.CoreSetup;
import bisq.core.trade.TradeManager;
import bisq.network.p2p.P2PService;
import bisq.common.UserThread; import bisq.common.UserThread;
import bisq.common.app.DevEnv; import bisq.common.app.DevEnv;
import bisq.common.handlers.ResultHandler; import bisq.common.setup.GracefulShutDownHandler;
import bisq.common.proto.persistable.PersistedDataHost; import bisq.common.setup.UncaughtExceptionHandler;
import bisq.common.setup.CommonSetup;
import bisq.common.storage.Storage; import bisq.common.storage.Storage;
import bisq.common.util.Profiler; import bisq.common.util.Profiler;
import bisq.common.util.Utilities; import bisq.common.util.Utilities;
import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.name.Names; import com.google.inject.name.Names;
@ -71,7 +56,6 @@ import com.google.inject.name.Names;
import org.reactfx.EventStreams; import org.reactfx.EventStreams;
import javafx.application.Application; import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
@ -89,60 +73,56 @@ import javafx.scene.layout.StackPane;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import org.slf4j.LoggerFactory; import lombok.Getter;
import lombok.Setter;
import ch.qos.logback.classic.Logger; import lombok.extern.slf4j.Slf4j;
import static bisq.desktop.util.Layout.INITIAL_SCENE_HEIGHT; import static bisq.desktop.util.Layout.INITIAL_SCENE_HEIGHT;
import static bisq.desktop.util.Layout.INITIAL_SCENE_WIDTH; import static bisq.desktop.util.Layout.INITIAL_SCENE_WIDTH;
public class BisqApp extends Application { @Slf4j
private static final Logger log = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(BisqApp.class); public class BisqApp extends Application implements UncaughtExceptionHandler {
private static final long LOG_MEMORY_PERIOD_MIN = 10; private static final long LOG_MEMORY_PERIOD_MIN = 10;
@Setter
private static Consumer<Application> appLaunchedHandler;
@Getter
private static Runnable shutDownHandler;
private static BisqEnvironment bisqEnvironment; @Setter
public static Runnable shutDownHandler;
private static Stage primaryStage;
protected static void setEnvironment(BisqEnvironment bisqEnvironment) {
BisqApp.bisqEnvironment = bisqEnvironment;
}
private BisqAppModule bisqAppModule;
private Injector injector; private Injector injector;
@Setter
private GracefulShutDownHandler gracefulShutDownHandler;
private Stage stage;
private boolean popupOpened; private boolean popupOpened;
private Scene scene; private Scene scene;
private final List<String> corruptedDatabaseFiles = new ArrayList<>(); private final List<String> corruptedDatabaseFiles = new ArrayList<>();
private boolean shutDownRequested; private boolean shutDownRequested;
public BisqApp() {
shutDownHandler = this::stop;
}
///////////////////////////////////////////////////////////////////////////////////////////
// JavaFx Application implementation
///////////////////////////////////////////////////////////////////////////////////////////
// NOTE: This method is not called on the JavaFX Application Thread. // NOTE: This method is not called on the JavaFX Application Thread.
@Override @Override
public void init() { public void init() {
UserThread.setExecutor(Platform::runLater);
UserThread.setTimerClass(UITimer.class);
shutDownHandler = this::stop;
CommonSetup.setup(this::showErrorPopup);
CoreSetup.setup(bisqEnvironment);
} }
@SuppressWarnings("PointlessBooleanExpression")
@Override @Override
public void start(Stage stage) { public void start(Stage stage) {
BisqApp.primaryStage = stage; this.stage = stage;
appLaunchedHandler.accept(this);
}
public void startApplication() {
try { try {
bisqAppModule = new BisqAppModule(bisqEnvironment, primaryStage);
injector = Guice.createInjector(bisqAppModule);
injector.getInstance(InjectorViewFactory.class).setInjector(injector);
PersistedDataHost.apply(CorePersistedDataHost.getPersistedDataHosts(injector));
PersistedDataHost.apply(DesktopPersistedDataHost.getPersistedDataHosts(injector));
DevEnv.setup(injector);
MainView mainView = loadMainView(injector); MainView mainView = loadMainView(injector);
scene = createAndConfigScene(mainView, injector); scene = createAndConfigScene(mainView, injector);
setupStage(scene); setupStage(scene);
@ -154,10 +134,74 @@ public class BisqApp extends Application {
UserThread.runPeriodically(() -> Profiler.printSystemLoad(log), LOG_MEMORY_PERIOD_MIN, TimeUnit.MINUTES); UserThread.runPeriodically(() -> Profiler.printSystemLoad(log), LOG_MEMORY_PERIOD_MIN, TimeUnit.MINUTES);
} catch (Throwable throwable) { } catch (Throwable throwable) {
log.error("Error during app init", throwable); log.error("Error during app init", throwable);
showErrorPopup(throwable, false); handleUncaughtException(throwable, false);
} }
} }
@Override
public void stop() {
if (!shutDownRequested) {
new Popup<>().headLine(Res.get("popup.shutDownInProgress.headline"))
.backgroundInfo(Res.get("popup.shutDownInProgress.msg"))
.hideCloseButton()
.useAnimation(false)
.show();
UserThread.runAfter(() -> {
gracefulShutDownHandler.gracefulShutDown(() -> {
log.debug("App shutdown complete");
});
}, 200, TimeUnit.MILLISECONDS);
shutDownRequested = true;
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// UncaughtExceptionHandler implementation
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleUncaughtException(Throwable throwable, boolean doShutDown) {
if (!shutDownRequested) {
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());
scene = new Scene(new StackPane(), 1000, 650);
scene.getStylesheets().setAll(
"/bisq/desktop/bisq.css",
"/bisq/desktop/images.css");
stage.setScene(scene);
stage.show();
}
try {
try {
if (!popupOpened) {
String message = throwable.getMessage();
popupOpened = true;
if (message != null)
new Popup<>().error(message).onClose(() -> popupOpened = false).show();
else
new Popup<>().error(throwable.toString()).onClose(() -> popupOpened = false).show();
}
} catch (Throwable throwable3) {
log.error("Error at displaying Throwable.");
throwable3.printStackTrace();
}
if (doShutDown)
stop();
} catch (Throwable throwable2) {
// If printStackTrace cause a further exception we don't pass the throwable to the Popup.
log.error(throwable2.toString());
if (doShutDown)
stop();
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private Scene createAndConfigScene(MainView mainView, Injector injector) { private Scene createAndConfigScene(MainView mainView, Injector injector) {
Scene scene = new Scene(mainView.getRoot(), INITIAL_SCENE_WIDTH, INITIAL_SCENE_HEIGHT); Scene scene = new Scene(mainView.getRoot(), INITIAL_SCENE_WIDTH, INITIAL_SCENE_HEIGHT);
scene.getStylesheets().setAll( scene.getStylesheets().setAll(
@ -170,19 +214,19 @@ public class BisqApp extends Application {
private void setupStage(Scene scene) { private void setupStage(Scene scene) {
// configure the system tray // configure the system tray
SystemTray.create(primaryStage, shutDownHandler); SystemTray.create(stage, shutDownHandler);
primaryStage.setOnCloseRequest(event -> { stage.setOnCloseRequest(event -> {
event.consume(); event.consume();
stop(); stop();
}); });
// configure the primary stage // configure the primary stage
primaryStage.setTitle(bisqEnvironment.getRequiredProperty(AppOptionKeys.APP_NAME_KEY)); String appName = injector.getInstance(Key.get(String.class, Names.named(AppOptionKeys.APP_NAME_KEY)));
primaryStage.setScene(scene); stage.setTitle(appName);
primaryStage.setMinWidth(1020); stage.setScene(scene);
primaryStage.setMinHeight(620); stage.setMinWidth(1020);
stage.setMinHeight(620);
// on windows the title icon is also used as task bar icon in a larger size // on windows the title icon is also used as task bar icon in a larger size
// on Linux no title icon is supported but also a large task bar icon is derived from that title icon // on Linux no title icon is supported but also a large task bar icon is derived from that title icon
@ -194,10 +238,10 @@ public class BisqApp extends Application {
else else
iconPath = "/images/task_bar_icon_linux.png"; iconPath = "/images/task_bar_icon_linux.png";
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream(iconPath))); stage.getIcons().add(new Image(getClass().getResourceAsStream(iconPath)));
// make the UI visible // make the UI visible
primaryStage.show(); stage.show();
} }
private MainView loadMainView(Injector injector) { private MainView loadMainView(Injector injector) {
@ -278,42 +322,6 @@ public class BisqApp extends Application {
emptyWalletWindow.show(); emptyWalletWindow.show();
} }
private void showErrorPopup(Throwable throwable, boolean doShutDown) {
if (!shutDownRequested) {
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());
scene = new Scene(new StackPane(), 1000, 650);
scene.getStylesheets().setAll(
"/bisq/desktop/bisq.css",
"/bisq/desktop/images.css");
primaryStage.setScene(scene);
primaryStage.show();
}
try {
try {
if (!popupOpened) {
String message = throwable.getMessage();
popupOpened = true;
if (message != null)
new Popup<>().error(message).onClose(() -> popupOpened = false).show();
else
new Popup<>().error(throwable.toString()).onClose(() -> popupOpened = false).show();
}
} catch (Throwable throwable3) {
log.error("Error at displaying Throwable.");
throwable3.printStackTrace();
}
if (doShutDown)
stop();
} catch (Throwable throwable2) {
// If printStackTrace cause a further exception we don't pass the throwable to the Popup.
log.error(throwable2.toString());
if (doShutDown)
stop();
}
}
}
// Used for debugging trade process // Used for debugging trade process
private void showDebugWindow(Scene scene, Injector injector) { private void showDebugWindow(Scene scene, Injector injector) {
ViewLoader viewLoader = injector.getInstance(ViewLoader.class); ViewLoader viewLoader = injector.getInstance(ViewLoader.class);
@ -325,8 +333,8 @@ public class BisqApp extends Application {
stage.initModality(Modality.NONE); stage.initModality(Modality.NONE);
stage.initStyle(StageStyle.UTILITY); stage.initStyle(StageStyle.UTILITY);
stage.initOwner(scene.getWindow()); stage.initOwner(scene.getWindow());
stage.setX(primaryStage.getX() + primaryStage.getWidth() + 10); stage.setX(this.stage.getX() + this.stage.getWidth() + 10);
stage.setY(primaryStage.getY()); stage.setY(this.stage.getY());
stage.show(); stage.show();
} }
@ -349,8 +357,8 @@ public class BisqApp extends Application {
stage.initModality(Modality.NONE); stage.initModality(Modality.NONE);
stage.initStyle(StageStyle.UTILITY); stage.initStyle(StageStyle.UTILITY);
stage.initOwner(scene.getWindow()); stage.initOwner(scene.getWindow());
stage.setX(primaryStage.getX() + primaryStage.getWidth() + 10); stage.setX(this.stage.getX() + this.stage.getWidth() + 10);
stage.setY(primaryStage.getY()); stage.setY(this.stage.getY());
stage.setWidth(200); stage.setWidth(200);
stage.setHeight(100); stage.setHeight(100);
stage.show(); stage.show();
@ -368,59 +376,4 @@ public class BisqApp extends Application {
.show(); .show();
} }
} }
@SuppressWarnings("CodeBlock2Expr")
@Override
public void stop() {
if (!shutDownRequested) {
new Popup<>().headLine(Res.get("popup.shutDownInProgress.headline"))
.backgroundInfo(Res.get("popup.shutDownInProgress.msg"))
.hideCloseButton()
.useAnimation(false)
.show();
//noinspection CodeBlock2Expr
UserThread.runAfter(() -> {
gracefulShutDown(() -> {
log.debug("App shutdown complete");
System.exit(0);
});
}, 200, TimeUnit.MILLISECONDS);
shutDownRequested = true;
}
}
private void gracefulShutDown(ResultHandler resultHandler) {
try {
if (injector != null) {
injector.getInstance(ArbitratorManager.class).shutDown();
injector.getInstance(TradeManager.class).shutDown();
injector.getInstance(DaoSetup.class).shutDown();
//noinspection CodeBlock2Expr
injector.getInstance(OpenOfferManager.class).shutDown(() -> {
injector.getInstance(P2PService.class).shutDown(() -> {
injector.getInstance(WalletsSetup.class).shutDownComplete.addListener((ov, o, n) -> {
bisqAppModule.close(injector);
log.debug("Graceful shutdown completed");
resultHandler.handleResult();
});
injector.getInstance(WalletsSetup.class).shutDown();
injector.getInstance(BtcWalletService.class).shutDown();
injector.getInstance(BsqWalletService.class).shutDown();
});
});
// we wait max 20 sec.
UserThread.runAfter(() -> {
log.warn("Timeout triggered resultHandler");
resultHandler.handleResult();
}, 20);
} else {
log.warn("injector == null triggered resultHandler");
UserThread.runAfter(resultHandler::handleResult, 1);
}
} catch (Throwable t) {
log.error("App shutdown failed with exception");
t.printStackTrace();
System.exit(1);
}
}
} }

View file

@ -17,60 +17,99 @@
package bisq.desktop.app; package bisq.desktop.app;
import bisq.core.app.AppOptionKeys; import bisq.desktop.common.UITimer;
import bisq.core.app.BisqEnvironment; import bisq.desktop.common.view.guice.InjectorViewFactory;
import bisq.desktop.setup.DesktopPersistedDataHost;
import bisq.core.app.BisqExecutable; import bisq.core.app.BisqExecutable;
import bisq.common.util.Utilities; import bisq.common.UserThread;
import bisq.common.app.AppModule;
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.setup.CommonSetup;
import joptsimple.OptionException; import com.google.inject.Injector;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import static bisq.core.app.BisqEnvironment.DEFAULT_APP_NAME; import javafx.application.Application;
import static bisq.core.app.BisqEnvironment.DEFAULT_USER_DATA_DIR; import javafx.application.Platform;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BisqAppMain extends BisqExecutable { public class BisqAppMain extends BisqExecutable {
private BisqApp application;
static {
Utilities.removeCryptographyRestrictions();
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// We don't want to do the full argument parsing here as that might easily change in update versions if (BisqExecutable.setupInitialOptionParser(args)) {
// So we only handle the absolute minimum which is APP_NAME, APP_DATA_DIR_KEY and USER_DATA_DIR // For some reason the JavaFX launch process results in us losing the thread context class loader: reset it.
OptionParser parser = new OptionParser(); // In order to work around a bug in JavaFX 8u25 and below, you must include the following code as the first line of your realMain method:
parser.allowsUnrecognizedOptions(); Thread.currentThread().setContextClassLoader(BisqAppMain.class.getClassLoader());
parser.accepts(AppOptionKeys.USER_DATA_DIR_KEY, description("User data directory", DEFAULT_USER_DATA_DIR))
.withRequiredArg();
parser.accepts(AppOptionKeys.APP_NAME_KEY, description("Application name", DEFAULT_APP_NAME))
.withRequiredArg();
OptionSet options; new BisqAppMain().execute(args);
try {
options = parser.parse(args);
} catch (OptionException ex) {
System.out.println("error: " + ex.getMessage());
System.out.println();
parser.printHelpOn(System.out);
System.exit(EXIT_FAILURE);
return;
} }
BisqEnvironment bisqEnvironment = getBisqEnvironment(options); }
// need to call that before bisqAppMain().execute(args)
initAppDir(bisqEnvironment.getProperty(AppOptionKeys.APP_DATA_DIR_KEY));
// For some reason the JavaFX launch process results in us losing the thread context class loader: reset it. ///////////////////////////////////////////////////////////////////////////////////////////
// In order to work around a bug in JavaFX 8u25 and below, you must include the following code as the first line of your realMain method: // First synchronous execution tasks
Thread.currentThread().setContextClassLoader(BisqAppMain.class.getClassLoader()); ///////////////////////////////////////////////////////////////////////////////////////////
new BisqAppMain().execute(args); @Override
protected void configUserThread() {
UserThread.setExecutor(Platform::runLater);
UserThread.setTimerClass(UITimer.class);
} }
@Override @Override
protected void doExecute(OptionSet options) { protected void launchApplication() {
BisqApp.setEnvironment(getBisqEnvironment(options)); BisqApp.setAppLaunchedHandler(application -> {
javafx.application.Application.launch(BisqApp.class); BisqAppMain.this.application = (BisqApp) application;
// Map to user thread!
UserThread.execute(this::onApplicationLaunched);
});
Application.launch(BisqApp.class);
}
///////////////////////////////////////////////////////////////////////////////////////////
// As application is a JavaFX application we need to wait for onApplicationLaunched
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void onApplicationLaunched() {
super.onApplicationLaunched();
application.setGracefulShutDownHandler(this);
CommonSetup.setup(application);
}
///////////////////////////////////////////////////////////////////////////////////////////
// We continue with a series of synchronous execution tasks
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected AppModule getModule() {
return new BisqAppModule(bisqEnvironment);
}
@Override
protected void applyInjector() {
super.applyInjector();
application.setInjector(injector);
injector.getInstance(InjectorViewFactory.class).setInjector(injector);
}
@Override
protected void setupPersistedDataHosts(Injector injector) {
super.setupPersistedDataHosts(injector);
PersistedDataHost.apply(DesktopPersistedDataHost.getPersistedDataHosts(injector));
}
@Override
protected void startApplication() {
// We need to be in user thread! We mapped at launchApplication already...
application.startApplication();
} }
} }

View file

@ -18,140 +18,30 @@
package bisq.desktop.app; package bisq.desktop.app;
import bisq.desktop.DesktopModule; import bisq.desktop.DesktopModule;
import bisq.desktop.common.view.CachingViewLoader;
import bisq.desktop.main.overlays.notifications.NotificationCenter;
import bisq.core.alert.AlertModule; import bisq.core.app.CoreModule;
import bisq.core.app.AppOptionKeys;
import bisq.core.app.BisqEnvironment;
import bisq.core.arbitration.ArbitratorModule;
import bisq.core.btc.BitcoinModule;
import bisq.core.dao.DaoModule;
import bisq.core.filter.FilterModule;
import bisq.core.network.p2p.seed.DefaultSeedNodeRepository;
import bisq.core.network.p2p.seed.SeedNodeAddressLookup;
import bisq.core.offer.OfferModule;
import bisq.core.proto.network.CoreNetworkProtoResolver;
import bisq.core.proto.persistable.CorePersistenceProtoResolver;
import bisq.core.trade.TradeModule;
import bisq.core.user.Preferences;
import bisq.core.user.User;
import bisq.network.crypto.EncryptionServiceModule;
import bisq.network.p2p.P2PModule;
import bisq.network.p2p.network.BridgeAddressProvider;
import bisq.network.p2p.seed.SeedNodeRepository;
import bisq.common.Clock;
import bisq.common.CommonOptionKeys;
import bisq.common.app.AppModule; import bisq.common.app.AppModule;
import bisq.common.crypto.KeyRing;
import bisq.common.crypto.KeyStorage;
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.storage.Storage;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import com.google.inject.Singleton;
import com.google.inject.name.Names;
import javafx.stage.Stage;
import java.io.File;
import static com.google.inject.name.Names.named;
public class BisqAppModule extends AppModule { public class BisqAppModule extends AppModule {
private final Stage primaryStage; public BisqAppModule(Environment environment) {
public BisqAppModule(Environment environment, Stage primaryStage) {
super(environment); super(environment);
this.primaryStage = primaryStage;
} }
@Override @Override
protected void configure() { protected void configure() {
bind(BisqEnvironment.class).toInstance((BisqEnvironment) environment); install(coreModule());
install(desktopModule());
bind(CachingViewLoader.class).in(Singleton.class);
bind(KeyStorage.class).in(Singleton.class);
bind(KeyRing.class).in(Singleton.class);
bind(User.class).in(Singleton.class);
bind(NotificationCenter.class).in(Singleton.class);
bind(Clock.class).in(Singleton.class);
bind(Preferences.class).in(Singleton.class);
bind(BridgeAddressProvider.class).to(Preferences.class).in(Singleton.class);
bind(SeedNodeAddressLookup.class).in(Singleton.class);
bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class);
File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR));
bind(File.class).annotatedWith(named(Storage.STORAGE_DIR)).toInstance(storageDir);
File keyStorageDir = new File(environment.getRequiredProperty(KeyStorage.KEY_STORAGE_DIR));
bind(File.class).annotatedWith(named(KeyStorage.KEY_STORAGE_DIR)).toInstance(keyStorageDir);
bind(NetworkProtoResolver.class).to(CoreNetworkProtoResolver.class).in(Singleton.class);
bind(PersistenceProtoResolver.class).to(CorePersistenceProtoResolver.class).in(Singleton.class);
Boolean useDevPrivilegeKeys = environment.getProperty(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, Boolean.class, false);
bind(boolean.class).annotatedWith(Names.named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS)).toInstance(useDevPrivilegeKeys);
Boolean useDevMode = environment.getProperty(CommonOptionKeys.USE_DEV_MODE, Boolean.class, false);
bind(boolean.class).annotatedWith(Names.named(CommonOptionKeys.USE_DEV_MODE)).toInstance(useDevMode);
// ordering is used for shut down sequence
install(tradeModule());
install(encryptionServiceModule());
install(arbitratorModule());
install(offerModule());
install(p2pModule());
install(bitcoinModule());
install(daoModule());
install(guiModule());
install(alertModule());
install(filterModule());
} }
private TradeModule tradeModule() { private CoreModule coreModule() {
return new TradeModule(environment); return new CoreModule(environment);
} }
private EncryptionServiceModule encryptionServiceModule() { private DesktopModule desktopModule() {
return new EncryptionServiceModule(environment); return new DesktopModule(environment);
}
private ArbitratorModule arbitratorModule() {
return new ArbitratorModule(environment);
}
private AlertModule alertModule() {
return new AlertModule(environment);
}
private FilterModule filterModule() {
return new FilterModule(environment);
}
private OfferModule offerModule() {
return new OfferModule(environment);
}
private P2PModule p2pModule() {
return new P2PModule(environment);
}
private BitcoinModule bitcoinModule() {
return new BitcoinModule(environment);
}
private DaoModule daoModule() {
return new DaoModule(environment);
}
private DesktopModule guiModule() {
return new DesktopModule(environment, primaryStage);
} }
} }

View file

@ -53,7 +53,6 @@ class AltCoinAccountsDataModel extends ActivatableDataModel {
private final OpenOfferManager openOfferManager; private final OpenOfferManager openOfferManager;
private final TradeManager tradeManager; private final TradeManager tradeManager;
private final AccountAgeWitnessService accountAgeWitnessService; private final AccountAgeWitnessService accountAgeWitnessService;
private final Stage stage;
final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList(); final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
private final SetChangeListener<PaymentAccount> setChangeListener; private final SetChangeListener<PaymentAccount> setChangeListener;
private final String accountsFileName = "AltcoinPaymentAccounts"; private final String accountsFileName = "AltcoinPaymentAccounts";
@ -65,14 +64,12 @@ class AltCoinAccountsDataModel extends ActivatableDataModel {
OpenOfferManager openOfferManager, OpenOfferManager openOfferManager,
TradeManager tradeManager, TradeManager tradeManager,
AccountAgeWitnessService accountAgeWitnessService, AccountAgeWitnessService accountAgeWitnessService,
Stage stage,
PersistenceProtoResolver persistenceProtoResolver) { PersistenceProtoResolver persistenceProtoResolver) {
this.user = user; this.user = user;
this.preferences = preferences; this.preferences = preferences;
this.openOfferManager = openOfferManager; this.openOfferManager = openOfferManager;
this.tradeManager = tradeManager; this.tradeManager = tradeManager;
this.accountAgeWitnessService = accountAgeWitnessService; this.accountAgeWitnessService = accountAgeWitnessService;
this.stage = stage;
this.persistenceProtoResolver = persistenceProtoResolver; this.persistenceProtoResolver = persistenceProtoResolver;
setChangeListener = change -> fillAndSortPaymentAccounts(); setChangeListener = change -> fillAndSortPaymentAccounts();
} }
@ -143,7 +140,7 @@ class AltCoinAccountsDataModel extends ActivatableDataModel {
user.setCurrentPaymentAccount(paymentAccount); user.setCurrentPaymentAccount(paymentAccount);
} }
public void exportAccounts() { public void exportAccounts(Stage stage) {
if (user.getPaymentAccounts() != null) { if (user.getPaymentAccounts() != null) {
ArrayList<PaymentAccount> accounts = new ArrayList<>(user.getPaymentAccounts().stream() ArrayList<PaymentAccount> accounts = new ArrayList<>(user.getPaymentAccounts().stream()
.filter(paymentAccount -> paymentAccount instanceof CryptoCurrencyAccount) .filter(paymentAccount -> paymentAccount instanceof CryptoCurrencyAccount)
@ -152,7 +149,7 @@ class AltCoinAccountsDataModel extends ActivatableDataModel {
} }
} }
public void importAccounts() { public void importAccounts(Stage stage) {
GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver); GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver);
} }
} }

View file

@ -46,6 +46,8 @@ import bisq.common.util.Tuple3;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.stage.Stage;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ListCell; import javafx.scene.control.ListCell;
@ -114,8 +116,8 @@ public class AltCoinAccountsView extends ActivatableViewAndModel<GridPane, AltCo
paymentAccountsListView.setItems(model.getPaymentAccounts()); paymentAccountsListView.setItems(model.getPaymentAccounts());
paymentAccountsListView.getSelectionModel().selectedItemProperty().addListener(paymentAccountChangeListener); paymentAccountsListView.getSelectionModel().selectedItemProperty().addListener(paymentAccountChangeListener);
addAccountButton.setOnAction(event -> addNewAccount()); addAccountButton.setOnAction(event -> addNewAccount());
exportButton.setOnAction(event -> model.dataModel.exportAccounts()); exportButton.setOnAction(event -> model.dataModel.exportAccounts((Stage) root.getScene().getWindow()));
importButton.setOnAction(event -> model.dataModel.importAccounts()); importButton.setOnAction(event -> model.dataModel.importAccounts((Stage) root.getScene().getWindow()));
} }
@Override @Override

View file

@ -36,7 +36,6 @@ import bisq.common.util.Utilities;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
@ -60,7 +59,6 @@ import javax.annotation.Nullable;
public class BackupView extends ActivatableView<GridPane, Void> { public class BackupView extends ActivatableView<GridPane, Void> {
private final File dataDir, logFile; private final File dataDir, logFile;
private int gridRow = 0; private int gridRow = 0;
private final Stage stage;
private final Preferences preferences; private final Preferences preferences;
private Button selectBackupDir, backupNow; private Button selectBackupDir, backupNow;
private TextField backUpLocationTextField; private TextField backUpLocationTextField;
@ -73,9 +71,8 @@ public class BackupView extends ActivatableView<GridPane, Void> {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
private BackupView(Stage stage, Preferences preferences, BisqEnvironment environment) { private BackupView(Preferences preferences, BisqEnvironment environment) {
super(); super();
this.stage = stage;
this.preferences = preferences; this.preferences = preferences;
dataDir = new File(environment.getProperty(AppOptionKeys.APP_DATA_DIR_KEY)); dataDir = new File(environment.getProperty(AppOptionKeys.APP_DATA_DIR_KEY));
logFile = new File(Paths.get(dataDir.getPath(), "bisq.log").toString()); logFile = new File(Paths.get(dataDir.getPath(), "bisq.log").toString());
@ -124,7 +121,7 @@ public class BackupView extends ActivatableView<GridPane, Void> {
directoryChooser.setInitialDirectory(new File(path)); directoryChooser.setInitialDirectory(new File(path));
directoryChooser.setTitle(Res.get("account.backup.selectLocation")); directoryChooser.setTitle(Res.get("account.backup.selectLocation"));
try { try {
File dir = directoryChooser.showDialog(stage); File dir = directoryChooser.showDialog(root.getScene().getWindow());
if (dir != null) { if (dir != null) {
applyBackupDirectory(dir.getAbsolutePath()); applyBackupDirectory(dir.getAbsolutePath());
} }

View file

@ -54,7 +54,6 @@ class FiatAccountsDataModel extends ActivatableDataModel {
private final OpenOfferManager openOfferManager; private final OpenOfferManager openOfferManager;
private final TradeManager tradeManager; private final TradeManager tradeManager;
private final AccountAgeWitnessService accountAgeWitnessService; private final AccountAgeWitnessService accountAgeWitnessService;
private final Stage stage;
final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList(); final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
private final SetChangeListener<PaymentAccount> setChangeListener; private final SetChangeListener<PaymentAccount> setChangeListener;
private final String accountsFileName = "FiatPaymentAccounts"; private final String accountsFileName = "FiatPaymentAccounts";
@ -66,14 +65,12 @@ class FiatAccountsDataModel extends ActivatableDataModel {
OpenOfferManager openOfferManager, OpenOfferManager openOfferManager,
TradeManager tradeManager, TradeManager tradeManager,
AccountAgeWitnessService accountAgeWitnessService, AccountAgeWitnessService accountAgeWitnessService,
Stage stage,
PersistenceProtoResolver persistenceProtoResolver) { PersistenceProtoResolver persistenceProtoResolver) {
this.user = user; this.user = user;
this.preferences = preferences; this.preferences = preferences;
this.openOfferManager = openOfferManager; this.openOfferManager = openOfferManager;
this.tradeManager = tradeManager; this.tradeManager = tradeManager;
this.accountAgeWitnessService = accountAgeWitnessService; this.accountAgeWitnessService = accountAgeWitnessService;
this.stage = stage;
this.persistenceProtoResolver = persistenceProtoResolver; this.persistenceProtoResolver = persistenceProtoResolver;
setChangeListener = change -> fillAndSortPaymentAccounts(); setChangeListener = change -> fillAndSortPaymentAccounts();
} }
@ -149,7 +146,7 @@ class FiatAccountsDataModel extends ActivatableDataModel {
user.setCurrentPaymentAccount(paymentAccount); user.setCurrentPaymentAccount(paymentAccount);
} }
public void exportAccounts() { public void exportAccounts(Stage stage) {
if (user.getPaymentAccounts() != null) { if (user.getPaymentAccounts() != null) {
ArrayList<PaymentAccount> accounts = new ArrayList<>(user.getPaymentAccounts().stream() ArrayList<PaymentAccount> accounts = new ArrayList<>(user.getPaymentAccounts().stream()
.filter(paymentAccount -> !(paymentAccount instanceof CryptoCurrencyAccount)) .filter(paymentAccount -> !(paymentAccount instanceof CryptoCurrencyAccount))
@ -158,7 +155,7 @@ class FiatAccountsDataModel extends ActivatableDataModel {
} }
} }
public void importAccounts() { public void importAccounts(Stage stage) {
GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver); GUIUtil.importAccounts(user, accountsFileName, preferences, stage, persistenceProtoResolver);
} }
} }

View file

@ -17,18 +17,6 @@
package bisq.desktop.main.account.content.fiataccounts; package bisq.desktop.main.account.content.fiataccounts;
import bisq.common.UserThread;
import bisq.common.util.Tuple2;
import bisq.common.util.Tuple3;
import bisq.core.app.BisqEnvironment;
import bisq.core.locale.Res;
import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.payment.ClearXchangeAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.PaymentAccountFactory;
import bisq.core.payment.WesternUnionAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.util.validation.InputValidator;
import bisq.desktop.common.view.ActivatableViewAndModel; import bisq.desktop.common.view.ActivatableViewAndModel;
import bisq.desktop.common.view.FxmlView; import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.AutoTooltipButton; import bisq.desktop.components.AutoTooltipButton;
@ -80,9 +68,27 @@ import bisq.desktop.util.validation.USPostalMoneyOrderValidator;
import bisq.desktop.util.validation.UpholdValidator; import bisq.desktop.util.validation.UpholdValidator;
import bisq.desktop.util.validation.VenmoValidator; import bisq.desktop.util.validation.VenmoValidator;
import bisq.desktop.util.validation.WeChatPayValidator; import bisq.desktop.util.validation.WeChatPayValidator;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections; import bisq.core.app.BisqEnvironment;
import javafx.geometry.VPos; import bisq.core.locale.Res;
import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.payment.ClearXchangeAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.PaymentAccountFactory;
import bisq.core.payment.WesternUnionAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.util.validation.InputValidator;
import bisq.common.UserThread;
import bisq.common.util.Tuple2;
import bisq.common.util.Tuple3;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import javafx.stage.Stage;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.ComboBox; import javafx.scene.control.ComboBox;
import javafx.scene.control.Label; import javafx.scene.control.Label;
@ -92,20 +98,21 @@ import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import javafx.scene.text.TextAlignment; import javafx.scene.text.TextAlignment;
import javafx.geometry.VPos;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.util.Callback; import javafx.util.Callback;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static bisq.desktop.util.FormBuilder.add2ButtonsAfterGroup; import static bisq.desktop.util.FormBuilder.*;
import static bisq.desktop.util.FormBuilder.add3ButtonsAfterGroup;
import static bisq.desktop.util.FormBuilder.addLabelComboBox;
import static bisq.desktop.util.FormBuilder.addLabelListView;
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
@FxmlView @FxmlView
public class FiatAccountsView extends ActivatableViewAndModel<GridPane, FiatAccountsViewModel> { public class FiatAccountsView extends ActivatableViewAndModel<GridPane, FiatAccountsViewModel> {
@ -201,8 +208,8 @@ public class FiatAccountsView extends ActivatableViewAndModel<GridPane, FiatAcco
paymentAccountsListView.setItems(model.getPaymentAccounts()); paymentAccountsListView.setItems(model.getPaymentAccounts());
paymentAccountsListView.getSelectionModel().selectedItemProperty().addListener(paymentAccountChangeListener); paymentAccountsListView.getSelectionModel().selectedItemProperty().addListener(paymentAccountChangeListener);
addAccountButton.setOnAction(event -> addNewAccount()); addAccountButton.setOnAction(event -> addNewAccount());
exportButton.setOnAction(event -> model.dataModel.exportAccounts()); exportButton.setOnAction(event -> model.dataModel.exportAccounts((Stage) root.getScene().getWindow()));
importButton.setOnAction(event -> model.dataModel.importAccounts()); importButton.setOnAction(event -> model.dataModel.importAccounts((Stage) root.getScene().getWindow()));
} }
@Override @Override

View file

@ -37,18 +37,16 @@ import com.google.inject.name.Named;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.stage.Stage;
@FxmlView @FxmlView
public class ArbitratorDisputeView extends TraderDisputeView { public class ArbitratorDisputeView extends TraderDisputeView {
@Inject @Inject
public ArbitratorDisputeView(DisputeManager disputeManager, KeyRing keyRing, TradeManager tradeManager, Stage stage, public ArbitratorDisputeView(DisputeManager disputeManager, KeyRing keyRing, TradeManager tradeManager,
BSFormatter formatter, DisputeSummaryWindow disputeSummaryWindow, BSFormatter formatter, DisputeSummaryWindow disputeSummaryWindow,
PrivateNotificationManager privateNotificationManager, PrivateNotificationManager privateNotificationManager,
ContractWindow contractWindow, TradeDetailsWindow tradeDetailsWindow, ContractWindow contractWindow, TradeDetailsWindow tradeDetailsWindow,
P2PService p2PService, @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { P2PService p2PService, @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
super(disputeManager, keyRing, tradeManager, stage, formatter, super(disputeManager, keyRing, tradeManager, formatter,
disputeSummaryWindow, privateNotificationManager, contractWindow, disputeSummaryWindow, privateNotificationManager, contractWindow,
tradeDetailsWindow, p2PService, useDevPrivilegeKeys); tradeDetailsWindow, p2PService, useDevPrivilegeKeys);
} }

View file

@ -68,7 +68,6 @@ import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.fontawesome.AwesomeIcon;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -138,7 +137,6 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
private final DisputeManager disputeManager; private final DisputeManager disputeManager;
protected final KeyRing keyRing; protected final KeyRing keyRing;
private final TradeManager tradeManager; private final TradeManager tradeManager;
private final Stage stage;
protected final BSFormatter formatter; protected final BSFormatter formatter;
private final DisputeSummaryWindow disputeSummaryWindow; private final DisputeSummaryWindow disputeSummaryWindow;
private final PrivateNotificationManager privateNotificationManager; private final PrivateNotificationManager privateNotificationManager;
@ -186,7 +184,6 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
public TraderDisputeView(DisputeManager disputeManager, public TraderDisputeView(DisputeManager disputeManager,
KeyRing keyRing, KeyRing keyRing,
TradeManager tradeManager, TradeManager tradeManager,
Stage stage,
BSFormatter formatter, BSFormatter formatter,
DisputeSummaryWindow disputeSummaryWindow, DisputeSummaryWindow disputeSummaryWindow,
PrivateNotificationManager privateNotificationManager, PrivateNotificationManager privateNotificationManager,
@ -197,7 +194,6 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
this.disputeManager = disputeManager; this.disputeManager = disputeManager;
this.keyRing = keyRing; this.keyRing = keyRing;
this.tradeManager = tradeManager; this.tradeManager = tradeManager;
this.stage = stage;
this.formatter = formatter; this.formatter = formatter;
this.disputeSummaryWindow = disputeSummaryWindow; this.disputeSummaryWindow = disputeSummaryWindow;
this.privateNotificationManager = privateNotificationManager; this.privateNotificationManager = privateNotificationManager;
@ -560,7 +556,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
fileChooser.setTitle(Res.get("support.openFile", maxSizeInKB)); fileChooser.setTitle(Res.get("support.openFile", maxSizeInKB));
/* if (Utilities.isUnix()) /* if (Utilities.isUnix())
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/ fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/
File result = fileChooser.showOpenDialog(stage); File result = fileChooser.showOpenDialog(root.getScene().getWindow());
if (result != null) { if (result != null) {
try { try {
URL url = result.toURI().toURL(); URL url = result.toURI().toURL();
@ -596,7 +592,7 @@ public class TraderDisputeView extends ActivatableView<VBox, Void> {
fileChooser.setInitialFileName(attachment.getFileName()); fileChooser.setInitialFileName(attachment.getFileName());
/* if (Utilities.isUnix()) /* if (Utilities.isUnix())
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/ fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));*/
File file = fileChooser.showSaveDialog(stage); File file = fileChooser.showSaveDialog(root.getScene().getWindow());
if (file != null) { if (file != null) {
try (FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath())) { try (FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath())) {
fileOutputStream.write(attachment.getBytes()); fileOutputStream.write(attachment.getBytes());

View file

@ -112,7 +112,6 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
private final BSFormatter formatter; private final BSFormatter formatter;
private final Preferences preferences; private final Preferences preferences;
private final TradeDetailsWindow tradeDetailsWindow; private final TradeDetailsWindow tradeDetailsWindow;
private final Stage stage;
private final OfferDetailsWindow offerDetailsWindow; private final OfferDetailsWindow offerDetailsWindow;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private WalletEventListener walletEventListener; private WalletEventListener walletEventListener;
@ -130,7 +129,6 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
BSFormatter formatter, BSFormatter formatter,
Preferences preferences, Preferences preferences,
TradeDetailsWindow tradeDetailsWindow, TradeDetailsWindow tradeDetailsWindow,
Stage stage,
OfferDetailsWindow offerDetailsWindow, OfferDetailsWindow offerDetailsWindow,
DisplayedTransactionsFactory displayedTransactionsFactory) { DisplayedTransactionsFactory displayedTransactionsFactory) {
this.btcWalletService = btcWalletService; this.btcWalletService = btcWalletService;
@ -139,7 +137,6 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
this.formatter = formatter; this.formatter = formatter;
this.preferences = preferences; this.preferences = preferences;
this.tradeDetailsWindow = tradeDetailsWindow; this.tradeDetailsWindow = tradeDetailsWindow;
this.stage = stage;
this.offerDetailsWindow = offerDetailsWindow; this.offerDetailsWindow = offerDetailsWindow;
this.displayedTransactions = displayedTransactionsFactory.create(); this.displayedTransactions = displayedTransactionsFactory.create();
this.sortedDisplayedTransactions = displayedTransactions.asSortedList(); this.sortedDisplayedTransactions = displayedTransactions.asSortedList();
@ -260,7 +257,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
}; };
GUIUtil.exportCSV("transactions.csv", headerConverter, contentConverter, GUIUtil.exportCSV("transactions.csv", headerConverter, contentConverter,
new TransactionsListItem(), sortedDisplayedTransactions, stage); new TransactionsListItem(), sortedDisplayedTransactions, (Stage) root.getScene().getWindow());
}); });
} }

View file

@ -391,7 +391,7 @@ public abstract class Overlay<T extends Overlay> {
public T useShutDownButton() { public T useShutDownButton() {
this.actionButtonText = Res.get("shared.shutDown"); this.actionButtonText = Res.get("shared.shutDown");
this.actionHandlerOptional = Optional.of(BisqApp.shutDownHandler::run); this.actionHandlerOptional = Optional.of(BisqApp.getShutDownHandler()::run);
//noinspection unchecked //noinspection unchecked
return (T) this; return (T) this;
} }

View file

@ -96,7 +96,7 @@ public class TacWindow extends Overlay<TacWindow> {
message(text); message(text);
actionButtonText(Res.get("tacWindow.agree")); actionButtonText(Res.get("tacWindow.agree"));
closeButtonText(Res.get("tacWindow.disagree")); closeButtonText(Res.get("tacWindow.disagree"));
onClose(BisqApp.shutDownHandler::run); onClose(BisqApp.getShutDownHandler()::run);
super.show(); super.show();
} }

View file

@ -86,7 +86,6 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
private final BSFormatter formatter; private final BSFormatter formatter;
private final TradeDetailsWindow tradeDetailsWindow; private final TradeDetailsWindow tradeDetailsWindow;
private final PrivateNotificationManager privateNotificationManager; private final PrivateNotificationManager privateNotificationManager;
private final Stage stage;
private SortedList<ClosedTradableListItem> sortedList; private SortedList<ClosedTradableListItem> sortedList;
@Inject @Inject
@ -95,7 +94,6 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
Preferences preferences, Preferences preferences,
TradeDetailsWindow tradeDetailsWindow, TradeDetailsWindow tradeDetailsWindow,
PrivateNotificationManager privateNotificationManager, PrivateNotificationManager privateNotificationManager,
Stage stage,
BSFormatter formatter, BSFormatter formatter,
@Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
super(model); super(model);
@ -103,7 +101,6 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
this.preferences = preferences; this.preferences = preferences;
this.tradeDetailsWindow = tradeDetailsWindow; this.tradeDetailsWindow = tradeDetailsWindow;
this.privateNotificationManager = privateNotificationManager; this.privateNotificationManager = privateNotificationManager;
this.stage = stage;
this.preferences = preferences; this.preferences = preferences;
this.formatter = formatter; this.formatter = formatter;
this.useDevPrivilegeKeys = useDevPrivilegeKeys; this.useDevPrivilegeKeys = useDevPrivilegeKeys;
@ -211,7 +208,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
}; };
GUIUtil.exportCSV("tradeHistory.csv", headerConverter, contentConverter, GUIUtil.exportCSV("tradeHistory.csv", headerConverter, contentConverter,
new ClosedTradableListItem(null), sortedList, stage); new ClosedTradableListItem(null), sortedList, (Stage) root.getScene().getWindow());
}); });
} }

View file

@ -256,7 +256,7 @@ public class NetworkSettingsView extends ActivatableViewAndModel<GridPane, Activ
.actionButtonText(Res.get("shared.applyAndShutDown")) .actionButtonText(Res.get("shared.applyAndShutDown"))
.onAction(() -> { .onAction(() -> {
preferences.setUseTorForBitcoinJ(selected); preferences.setUseTorForBitcoinJ(selected);
UserThread.runAfter(BisqApp.shutDownHandler::run, 500, TimeUnit.MILLISECONDS); UserThread.runAfter(BisqApp.getShutDownHandler()::run, 500, TimeUnit.MILLISECONDS);
}) })
.closeButtonText(Res.get("shared.cancel")) .closeButtonText(Res.get("shared.cancel"))
.onClose(() -> useTorForBtcJCheckBox.setSelected(!selected)) .onClose(() -> useTorForBtcJCheckBox.setSelected(!selected))

View file

@ -655,7 +655,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
new Popup().warning(Res.get("settings.net.needRestart")) new Popup().warning(Res.get("settings.net.needRestart"))
.onAction(() -> { .onAction(() -> {
bisqEnvironment.saveBaseCryptoNetwork(selectBaseCurrencyNetworkComboBox.getSelectionModel().getSelectedItem()); bisqEnvironment.saveBaseCryptoNetwork(selectBaseCurrencyNetworkComboBox.getSelectionModel().getSelectedItem());
UserThread.runAfter(BisqApp.shutDownHandler::run, 500, TimeUnit.MILLISECONDS); UserThread.runAfter(BisqApp.getShutDownHandler()::run, 500, TimeUnit.MILLISECONDS);
}) })
.actionButtonText(Res.get("shared.shutDown")) .actionButtonText(Res.get("shared.shutDown"))
.closeButtonText(Res.get("shared.cancel")) .closeButtonText(Res.get("shared.cancel"))

View file

@ -462,7 +462,7 @@ public class GUIUtil {
.actionButtonText(Res.get("shared.shutDown")) .actionButtonText(Res.get("shared.shutDown"))
.onAction(() -> { .onAction(() -> {
preferences.setResyncSpvRequested(true); preferences.setResyncSpvRequested(true);
UserThread.runAfter(BisqApp.shutDownHandler::run, 100, TimeUnit.MILLISECONDS); UserThread.runAfter(BisqApp.getShutDownHandler()::run, 100, TimeUnit.MILLISECONDS);
}) })
.hideCloseButton() .hideCloseButton()
.show(); .show();