From 0e3314ce14bd2b02c4ab6e24bd3d7e500ee2efd2 Mon Sep 17 00:00:00 2001 From: jmacxx <47253594+jmacxx@users.noreply.github.com> Date: Fri, 2 Dec 2022 14:40:28 -0600 Subject: [PATCH] Prompt to confirm before shutting down. Has dont show again option. --- .../resources/i18n/displayStrings.properties | 5 +- .../main/java/bisq/desktop/app/BisqApp.java | 109 ++++++++---------- 2 files changed, 49 insertions(+), 65 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index b139dc8a196..1f1e41dc2e2 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -28,8 +28,8 @@ shared.readMore=Read more shared.openHelp=Open Help shared.warning=Warning shared.close=Close -shared.closeAnywayDanger=Shut down anyway (DANGER!) -shared.okWait=Ok I'll wait +shared.closeAnywayDanger=Shut down anyway +shared.okWait=Keep Bisq Open shared.cancel=Cancel shared.ok=OK shared.yes=Yes @@ -3151,6 +3151,7 @@ popup.info.shutDownWithTradeInit={0}\n\ popup.info.shutDownWithDisputeInit=Bisq is being shut down, but there is a Dispute system message still pending.\n\ Please wait a minute before shutting down.\n\ For further help please contact the Bisq support channel at the Bisq Matrix Space. +popup.info.shutDownQuery=Are you sure you want to exit Bisq? popup.info.qubesOSSetupInfo=It appears you are running Bisq on Qubes OS. \n\n\ Please make sure your Bisq qube is setup according to our Setup Guide at [HYPERLINK:https://bisq.wiki/Running_Bisq_on_Qubes]. popup.info.p2pStatusIndicator.red={0}\n\n\ diff --git a/desktop/src/main/java/bisq/desktop/app/BisqApp.java b/desktop/src/main/java/bisq/desktop/app/BisqApp.java index bd627c8b3c9..fe2d71b1433 100644 --- a/desktop/src/main/java/bisq/desktop/app/BisqApp.java +++ b/desktop/src/main/java/bisq/desktop/app/BisqApp.java @@ -97,6 +97,8 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import static bisq.common.crypto.Hash.getSha256Hash; +import static bisq.common.util.Utilities.encodeToHex; import static bisq.desktop.util.Layout.INITIAL_WINDOW_HEIGHT; import static bisq.desktop.util.Layout.INITIAL_WINDOW_WIDTH; import static bisq.desktop.util.Layout.MIN_WINDOW_HEIGHT; @@ -366,93 +368,74 @@ private void addSceneKeyEventHandler(Scene scene, Injector injector) { } private void shutDownByUser() { - // two potential popup prompts to user before shutting down, each step can possibly abort the shutdown - shutDownByUserCheckTrades().thenAccept(shutdownStage1 -> { - if (shutdownStage1) { - shutDownByUserCheckOffers().thenAccept(shutdownStage2 -> { - if (shutdownStage2) { - shutDownByUserCheckDisputes().thenAccept(shutdownStage3 -> { - if (shutdownStage3) { - stop(); - } - }); - } - }); + String potentialIssues = checkTradesAtShutdown() + checkDisputesAtShutdown() + checkOffersAtShutdown(); + promptUserAtShutdown(potentialIssues).thenAccept(asyncOkToShutDown -> { + if (asyncOkToShutDown) { + stop(); } }); } - private CompletableFuture shutDownByUserCheckTrades() { + private String checkTradesAtShutdown() { log.info("Checking trades at shutdown"); - final CompletableFuture asyncStatus = new CompletableFuture<>(); Instant fiveMinutesAgo = Instant.ofEpochSecond(Instant.now().getEpochSecond() - TimeUnit.MINUTES.toSeconds(5)); - String tradeIdsWithOperationsPending = ""; for (Trade trade : injector.getInstance(TradeManager.class).getObservableList()) { if (trade.getTradePhase().equals(Trade.Phase.TAKER_FEE_PUBLISHED) && new Date(trade.getTakeOfferDate()).toInstant().isAfter(fiveMinutesAgo)) { String tradeDateString = DisplayUtils.formatDateTime(new Date(trade.getTakeOfferDate())); - tradeIdsWithOperationsPending += Res.get("shared.tradeId") + ": " + trade.getShortId() + " " + - Res.get("shared.dateTime") + ": " + tradeDateString + System.lineSeparator(); - break; + String tradeInfo = Res.get("shared.tradeId") + ": " + trade.getShortId() + " " + + Res.get("shared.dateTime") + ": " + tradeDateString; + return Res.get("popup.info.shutDownWithTradeInit", tradeInfo) + System.lineSeparator() + System.lineSeparator(); } } - if (tradeIdsWithOperationsPending.length() > 0) { - // We show a popup to inform user that some trades are still being initialised. - new Popup().warning(Res.get("popup.info.shutDownWithTradeInit", tradeIdsWithOperationsPending)) - .actionButtonText(Res.get("shared.okWait")) - .onAction(() -> asyncStatus.complete(false)) - .closeButtonText(Res.get("shared.closeAnywayDanger")) - .onClose(() -> asyncStatus.complete(true)) - .show(); - } else { - asyncStatus.complete(true); + return ""; + } + + private String checkDisputesAtShutdown() { + log.info("Checking disputes at shutdown"); + if (injector.getInstance(MediationManager.class).hasPendingMessageAtShutdown() || + injector.getInstance(RefundManager.class).hasPendingMessageAtShutdown()) { + return Res.get("popup.info.shutDownWithDisputeInit") + System.lineSeparator() + System.lineSeparator(); } - return asyncStatus; + return ""; } - private CompletableFuture shutDownByUserCheckOffers() { + private String checkOffersAtShutdown() { log.info("Checking offers at shutdown"); - final CompletableFuture asyncStatus = new CompletableFuture<>(); - boolean hasOpenOffers = false; for (OpenOffer openOffer : injector.getInstance(OpenOfferManager.class).getObservableList()) { if (openOffer.getState().equals(OpenOffer.State.AVAILABLE)) { - hasOpenOffers = true; - break; + return Res.get("popup.info.shutDownWithOpenOffers") + System.lineSeparator() + System.lineSeparator(); } } - if (!hasOpenOffers) { - // No open offers, so no need to show the popup. - asyncStatus.complete(true); - return asyncStatus; - } + return ""; + } - // We show a popup to inform user that open offers will be removed if Bisq is not running. - String key = "showOpenOfferWarnPopupAtShutDown"; + 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 = encodeToHex(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().information(Res.get("popup.info.shutDownWithOpenOffers")) - .dontShowAgainId(key) - .useShutDownButton() + new Popup().headLine(Res.get("popup.info.shutDownQuery")) + .actionButtonText(Res.get("shared.yes")) .onAction(() -> asyncStatus.complete(true)) - .closeButtonText(Res.get("shared.cancel")) + .closeButtonText(Res.get("shared.no")) .onClose(() -> asyncStatus.complete(false)) - .show(); - } else { - asyncStatus.complete(true); - } - return asyncStatus; - } - - private CompletableFuture shutDownByUserCheckDisputes() { - log.info("Checking disputes at shutdown"); - final CompletableFuture asyncStatus = new CompletableFuture<>(); - if (injector.getInstance(MediationManager.class).hasPendingMessageAtShutdown() || - injector.getInstance(RefundManager.class).hasPendingMessageAtShutdown()) { - // We show a popup to inform user that some messages are still being sent. - new Popup().warning(Res.get("popup.info.shutDownWithDisputeInit")) - .actionButtonText(Res.get("shared.okWait")) - .onAction(() -> asyncStatus.complete(false)) - .closeButtonText(Res.get("shared.closeAnywayDanger")) - .onClose(() -> asyncStatus.complete(true)) + .dontShowAgainId(key) .show(); } else { asyncStatus.complete(true);