diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index d9b0cadd..e2fbe495 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -703,6 +703,17 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe return offer.isMyOffer(keyRing); } + public boolean hasOpenOffers() { + synchronized (openOffers) { + for (OpenOffer openOffer : getOpenOffers()) { + if (openOffer.getState() == OpenOffer.State.AVAILABLE) { + return true; + } + } + return false; + } + } + public List getOpenOffers() { synchronized (openOffers) { return new ArrayList<>(getObservableList()); diff --git a/desktop/src/main/java/haveno/desktop/app/HavenoApp.java b/desktop/src/main/java/haveno/desktop/app/HavenoApp.java index d2d8d60c..e2937f79 100644 --- a/desktop/src/main/java/haveno/desktop/app/HavenoApp.java +++ b/desktop/src/main/java/haveno/desktop/app/HavenoApp.java @@ -36,7 +36,6 @@ import haveno.common.setup.GracefulShutDownHandler; import haveno.common.setup.UncaughtExceptionHandler; import haveno.common.util.Utilities; import haveno.core.locale.Res; -import haveno.core.offer.OpenOffer; import haveno.core.offer.OpenOfferManager; import haveno.core.support.dispute.arbitration.ArbitrationManager; import haveno.core.support.dispute.mediation.MediationManager; @@ -336,14 +335,64 @@ public class HavenoApp extends Application implements UncaughtExceptionHandler { } private void shutDownByUser() { - String potentialIssues = checkTradesAtShutdown() + checkDisputesAtShutdown() + checkOffersAtShutdown(); - promptUserAtShutdown(potentialIssues).thenAccept(asyncOkToShutDown -> { - if (asyncOkToShutDown) { + promptUserAtShutdown().thenAccept(okToShutDown -> { + if (okToShutDown) { stop(); } }); } + private CompletableFuture promptUserAtShutdown() { + final CompletableFuture resp = new CompletableFuture<>(); + + // check for trade or dispute issues + String issues = checkTradesAtShutdown() + checkDisputesAtShutdown(); + if (issues.length() > 0) { + String key = Utilities.encodeToHex(Hash.getSha256Hash(issues)); + if (injector.getInstance(Preferences.class).showAgain(key) && !DevEnv.isDevMode()) { + new Popup().warning(issues) + .actionButtonText(Res.get("shared.okWait")) + .onAction(() -> resp.complete(false)) + .closeButtonText(Res.get("shared.closeAnywayDanger")) + .onClose(() -> resp.complete(true)) + .dontShowAgainId(key) + .width(800) + .show(); + return resp; + } + } + + // check for open offers + if (injector.getInstance(OpenOfferManager.class).hasOpenOffers()) { + String key = "showOpenOfferWarnPopupAtShutDown"; + if (injector.getInstance(Preferences.class).showAgain(key) && !DevEnv.isDevMode()) { + new Popup().warning(Res.get("popup.info.shutDownWithOpenOffers")) + .actionButtonText(Res.get("shared.shutDown")) + .onAction(() -> resp.complete(true)) + .closeButtonText(Res.get("shared.cancel")) + .onClose(() -> resp.complete(false)) + .dontShowAgainId(key) + .show(); + return resp; + } + } + + // if no warning popup has been shown yet, prompt user if they really intend to shut down + String key = "popup.info.shutDownQuery"; + if (injector.getInstance(Preferences.class).showAgain(key) && !DevEnv.isDevMode()) { + new Popup().headLine(Res.get("popup.info.shutDownQuery")) + .actionButtonText(Res.get("shared.yes")) + .onAction(() -> resp.complete(true)) + .closeButtonText(Res.get("shared.no")) + .onClose(() -> resp.complete(false)) + .dontShowAgainId(key) + .show(); + } else { + resp.complete(true); + } + return resp; + } + private String checkTradesAtShutdown() { log.info("Checking trades at shutdown"); Instant fiveMinutesAgo = Instant.ofEpochSecond(Instant.now().getEpochSecond() - TimeUnit.MINUTES.toSeconds(5)); @@ -369,49 +418,6 @@ public class HavenoApp extends Application implements UncaughtExceptionHandler { return ""; } - private String checkOffersAtShutdown() { - log.info("Checking offers at shutdown"); - for (OpenOffer openOffer : injector.getInstance(OpenOfferManager.class).getObservableList()) { - if (openOffer.getState().equals(OpenOffer.State.AVAILABLE)) { - return Res.get("popup.info.shutDownWithOpenOffers") + System.lineSeparator() + System.lineSeparator(); - } - } - return ""; - } - - private CompletableFuture promptUserAtShutdown(String issueInfo) { - final CompletableFuture asyncStatus = new CompletableFuture<>(); - if (issueInfo.length() > 0) { - // We maybe show a popup to inform user that some issues are pending - String key = Utilities.encodeToHex(Hash.getSha256Hash(issueInfo)); - if (injector.getInstance(Preferences.class).showAgain(key) && !DevEnv.isDevMode()) { - new Popup().warning(issueInfo) - .actionButtonText(Res.get("shared.okWait")) - .onAction(() -> asyncStatus.complete(false)) - .closeButtonText(Res.get("shared.closeAnywayDanger")) - .onClose(() -> asyncStatus.complete(true)) - .dontShowAgainId(key) - .width(800) - .show(); - return asyncStatus; - } - } - // if no warning popup has been shown yet, prompt user if they really intend to shut down - String key = "popup.info.shutDownQuery"; - if (injector.getInstance(Preferences.class).showAgain(key) && !DevEnv.isDevMode()) { - new Popup().headLine(Res.get("popup.info.shutDownQuery")) - .actionButtonText(Res.get("shared.yes")) - .onAction(() -> asyncStatus.complete(true)) - .closeButtonText(Res.get("shared.no")) - .onClose(() -> asyncStatus.complete(false)) - .dontShowAgainId(key) - .show(); - } else { - asyncStatus.complete(true); - } - return asyncStatus; - } - // Used for debugging trade process private void showDebugWindow(Scene scene, Injector injector) { ViewLoader viewLoader = injector.getInstance(ViewLoader.class);