diff --git a/core/src/main/java/haveno/core/api/CoreNotificationService.java b/core/src/main/java/haveno/core/api/CoreNotificationService.java index 6c40d7498b..484208d06d 100644 --- a/core/src/main/java/haveno/core/api/CoreNotificationService.java +++ b/core/src/main/java/haveno/core/api/CoreNotificationService.java @@ -3,7 +3,11 @@ package haveno.core.api; import com.google.inject.Singleton; import haveno.core.api.model.TradeInfo; import haveno.core.support.messages.ChatMessage; +import haveno.core.trade.HavenoUtils; +import haveno.core.trade.MakerTrade; +import haveno.core.trade.SellerTrade; import haveno.core.trade.Trade; +import haveno.core.trade.Trade.Phase; import haveno.proto.grpc.NotificationMessage; import haveno.proto.grpc.NotificationMessage.NotificationType; import java.util.Iterator; @@ -46,7 +50,15 @@ public class CoreNotificationService { .build()); } - public void sendTradeNotification(Trade trade, String title, String message) { + public void sendTradeNotification(Trade trade, Phase phase, String title, String message) { + + // play chime when maker's trade is taken + if (trade instanceof MakerTrade && phase == Trade.Phase.DEPOSITS_PUBLISHED) HavenoUtils.playChimeSound(); + + // play chime when seller sees buyer confirm payment sent + if (trade instanceof SellerTrade && phase == Trade.Phase.PAYMENT_SENT) HavenoUtils.playChimeSound(); + + // send notification sendNotification(NotificationMessage.newBuilder() .setType(NotificationType.TRADE_UPDATE) .setTrade(TradeInfo.toTradeInfo(trade).toProtoMessage()) @@ -57,6 +69,7 @@ public class CoreNotificationService { } public void sendChatNotification(ChatMessage chatMessage) { + HavenoUtils.playChimeSound(); sendNotification(NotificationMessage.newBuilder() .setType(NotificationType.CHAT_MESSAGE) .setTimestamp(System.currentTimeMillis()) diff --git a/core/src/main/java/haveno/core/api/model/XmrBalanceInfo.java b/core/src/main/java/haveno/core/api/model/XmrBalanceInfo.java index 2a9e23cd42..76e661aea6 100644 --- a/core/src/main/java/haveno/core/api/model/XmrBalanceInfo.java +++ b/core/src/main/java/haveno/core/api/model/XmrBalanceInfo.java @@ -98,7 +98,7 @@ public class XmrBalanceInfo implements Payload { public String toString() { return "XmrBalanceInfo{" + "balance=" + balance + - "unlockedBalance=" + availableBalance + + ", unlockedBalance=" + availableBalance + ", lockedBalance=" + pendingBalance + ", reservedOfferBalance=" + reservedOfferBalance + ", reservedTradeBalance=" + reservedTradeBalance + diff --git a/core/src/main/java/haveno/core/app/HavenoSetup.java b/core/src/main/java/haveno/core/app/HavenoSetup.java index 2c2e95fd3b..d80ca807cc 100644 --- a/core/src/main/java/haveno/core/app/HavenoSetup.java +++ b/core/src/main/java/haveno/core/app/HavenoSetup.java @@ -53,6 +53,7 @@ import haveno.core.alert.Alert; import haveno.core.alert.AlertManager; import haveno.core.alert.PrivateNotificationManager; import haveno.core.alert.PrivateNotificationPayload; +import haveno.core.api.CoreContext; import haveno.core.api.XmrConnectionService; import haveno.core.api.XmrLocalNode; import haveno.core.locale.Res; @@ -131,7 +132,10 @@ public class HavenoSetup { private final Preferences preferences; private final User user; private final AlertManager alertManager; + @Getter private final Config config; + @Getter + private final CoreContext coreContext; private final AccountAgeWitnessService accountAgeWitnessService; private final TorSetup torSetup; private final CoinFormatter formatter; @@ -228,6 +232,7 @@ public class HavenoSetup { User user, AlertManager alertManager, Config config, + CoreContext coreContext, AccountAgeWitnessService accountAgeWitnessService, TorSetup torSetup, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, @@ -253,6 +258,7 @@ public class HavenoSetup { this.user = user; this.alertManager = alertManager; this.config = config; + this.coreContext = coreContext; this.accountAgeWitnessService = accountAgeWitnessService; this.torSetup = torSetup; this.formatter = formatter; @@ -263,6 +269,7 @@ public class HavenoSetup { this.arbitrationManager = arbitrationManager; HavenoUtils.havenoSetup = this; + HavenoUtils.preferences = preferences; } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/haveno/core/trade/HavenoUtils.java b/core/src/main/java/haveno/core/trade/HavenoUtils.java index 065d587f5a..7b3821114e 100644 --- a/core/src/main/java/haveno/core/trade/HavenoUtils.java +++ b/core/src/main/java/haveno/core/trade/HavenoUtils.java @@ -27,7 +27,9 @@ import haveno.common.crypto.Hash; import haveno.common.crypto.KeyRing; import haveno.common.crypto.PubKeyRing; import haveno.common.crypto.Sig; +import haveno.common.file.FileUtil; import haveno.common.util.Utilities; +import haveno.core.api.CoreNotificationService; import haveno.core.api.XmrConnectionService; import haveno.core.app.HavenoSetup; import haveno.core.offer.OfferPayload; @@ -36,9 +38,12 @@ import haveno.core.support.dispute.arbitration.ArbitrationManager; import haveno.core.support.dispute.arbitration.arbitrator.Arbitrator; import haveno.core.trade.messages.PaymentReceivedMessage; import haveno.core.trade.messages.PaymentSentMessage; +import haveno.core.user.Preferences; import haveno.core.util.JsonUtil; import haveno.core.xmr.wallet.XmrWalletService; import haveno.network.p2p.NodeAddress; + +import java.io.File; import java.math.BigDecimal; import java.math.BigInteger; import java.net.InetAddress; @@ -53,6 +58,13 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.concurrent.CountDownLatch; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.SourceDataLine; + import lombok.extern.slf4j.Slf4j; import monero.common.MoneroRpcConnection; import monero.daemon.model.MoneroOutput; @@ -110,11 +122,18 @@ public class HavenoUtils { public static XmrWalletService xmrWalletService; public static XmrConnectionService xmrConnectionService; public static OpenOfferManager openOfferManager; + public static CoreNotificationService notificationService; + public static Preferences preferences; public static boolean isSeedNode() { return havenoSetup == null; } + public static boolean isDaemon() { + if (isSeedNode()) return true; + return havenoSetup.getCoreContext().isApiUser(); + } + @SuppressWarnings("unused") public static Date getReleaseDate() { if (RELEASE_DATE == null) return null; @@ -525,4 +544,60 @@ public class HavenoUtils { public static boolean isNotEnoughSigners(Exception e) { return e != null && e.getMessage().contains("Not enough signers"); } + + public static void playChimeSound() { + playAudioFile("chime.wav"); + } + + public static void playCashRegisterSound() { + playAudioFile("cash_register.wav"); + } + + private static void playAudioFile(String fileName) { + if (isDaemon()) return; // ignore if running as daemon + if (!preferences.getUseSoundForNotificationsProperty().get()) return; // ignore if sounds disabled + new Thread(() -> { + try { + + // get audio file + File wavFile = new File(havenoSetup.getConfig().appDataDir, fileName); + if (!wavFile.exists()) FileUtil.resourceToFile(fileName, wavFile); + AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(wavFile); + + // get original format + AudioFormat baseFormat = audioInputStream.getFormat(); + + // set target format: PCM_SIGNED, 16-bit + AudioFormat targetFormat = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + baseFormat.getSampleRate(), + 16, // 16-bit instead of 32-bit float + baseFormat.getChannels(), + baseFormat.getChannels() * 2, // Frame size: 2 bytes per channel (16-bit) + baseFormat.getSampleRate(), + false // Little-endian + ); + + // convert audio to target format + AudioInputStream convertedStream = AudioSystem.getAudioInputStream(targetFormat, audioInputStream); + + // play audio + DataLine.Info info = new DataLine.Info(SourceDataLine.class, targetFormat); + SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(info); + sourceLine.open(targetFormat); + sourceLine.start(); + byte[] buffer = new byte[1024]; + int bytesRead = 0; + while ((bytesRead = convertedStream.read(buffer, 0, buffer.length)) != -1) { + sourceLine.write(buffer, 0, bytesRead); + } + sourceLine.drain(); + sourceLine.close(); + convertedStream.close(); + audioInputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + } } diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index 12bbc5882b..9308a44fbf 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -649,6 +649,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model { ThreadUtils.submitToPool(() -> { if (newValue == Trade.Phase.DEPOSIT_REQUESTED) startPolling(); if (newValue == Trade.Phase.DEPOSITS_PUBLISHED) onDepositsPublished(); + if (newValue == Trade.Phase.PAYMENT_SENT) onPaymentSent(); if (isDepositsPublished() && !isPayoutUnlocked()) updatePollPeriod(); if (isPaymentReceived()) { UserThread.execute(() -> { @@ -2832,6 +2833,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model { // close open offer or reset address entries if (this instanceof MakerTrade) { processModel.getOpenOfferManager().closeOpenOffer(getOffer()); + HavenoUtils.notificationService.sendTradeNotification(this, Phase.DEPOSITS_PUBLISHED, "Offer Taken", "Your offer " + offer.getId() + " has been accepted"); // TODO (woodser): use language translation } else { getXmrWalletService().resetAddressEntriesForOpenOffer(getId()); } @@ -2840,6 +2842,12 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model { ThreadUtils.submitToPool(() -> xmrWalletService.freezeOutputs(getSelf().getReserveTxKeyImages())); } + private void onPaymentSent() { + if (this instanceof SellerTrade) { + HavenoUtils.notificationService.sendTradeNotification(this, Phase.PAYMENT_SENT, "Payment Sent", "The buyer has sent the payment"); // TODO (woodser): use language translation + } + } + /////////////////////////////////////////////////////////////////////////////////////////// // PROTO BUFFER /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/haveno/core/trade/TradeManager.java b/core/src/main/java/haveno/core/trade/TradeManager.java index 9959a73607..55acf63d87 100644 --- a/core/src/main/java/haveno/core/trade/TradeManager.java +++ b/core/src/main/java/haveno/core/trade/TradeManager.java @@ -68,7 +68,6 @@ import haveno.core.support.dispute.mediation.mediator.MediatorManager; import haveno.core.support.dispute.messages.DisputeClosedMessage; import haveno.core.support.dispute.messages.DisputeOpenedMessage; import haveno.core.trade.Trade.DisputeState; -import haveno.core.trade.Trade.Phase; import haveno.core.trade.failed.FailedTradesManager; import haveno.core.trade.handlers.TradeResultHandler; import haveno.core.trade.messages.DepositRequest; @@ -134,7 +133,6 @@ import lombok.Setter; import monero.daemon.model.MoneroTx; import org.bitcoinj.core.Coin; import org.bouncycastle.crypto.params.KeyParameter; -import org.fxmisc.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -258,7 +256,9 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi failedTradesManager.setUnFailTradeCallback(this::unFailTrade); - xmrWalletService.setTradeManager(this); + // TODO: better way to set references + xmrWalletService.setTradeManager(this); // TODO: set reference in HavenoUtils for consistency + HavenoUtils.notificationService = notificationService; } @@ -599,14 +599,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi initTradeAndProtocol(trade, createTradeProtocol(trade)); addTrade(trade); - // notify on phase changes - // TODO (woodser): save subscription, bind on startup - EasyBind.subscribe(trade.statePhaseProperty(), phase -> { - if (phase == Phase.DEPOSITS_PUBLISHED) { - notificationService.sendTradeNotification(trade, "Offer Taken", "Your offer " + offer.getId() + " has been accepted"); // TODO (woodser): use language translation - } - }); - // process with protocol ((MakerProtocol) getTradeProtocol(trade)).handleInitTradeRequest(request, sender, errorMessage -> { log.warn("Maker error during trade initialization: " + errorMessage); diff --git a/core/src/main/java/haveno/core/user/Preferences.java b/core/src/main/java/haveno/core/user/Preferences.java index 311bd3108b..b57b5708ee 100644 --- a/core/src/main/java/haveno/core/user/Preferences.java +++ b/core/src/main/java/haveno/core/user/Preferences.java @@ -132,6 +132,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid private final String xmrNodesFromOptions; @Getter private final BooleanProperty useStandbyModeProperty = new SimpleBooleanProperty(prefPayload.isUseStandbyMode()); + @Getter + private final BooleanProperty useSoundForNotificationsProperty = new SimpleBooleanProperty(prefPayload.isUseSoundForNotifications()); /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -162,6 +164,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid requestPersistence(); }); + useSoundForNotificationsProperty.addListener((ov) -> { + prefPayload.setUseSoundForNotifications(useSoundForNotificationsProperty.get()); + requestPersistence(); + }); + traditionalCurrenciesAsObservable.addListener((javafx.beans.Observable ov) -> { prefPayload.getTraditionalCurrencies().clear(); prefPayload.getTraditionalCurrencies().addAll(traditionalCurrenciesAsObservable); @@ -259,6 +266,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid // set all properties useAnimationsProperty.set(prefPayload.isUseAnimations()); useStandbyModeProperty.set(prefPayload.isUseStandbyMode()); + useSoundForNotificationsProperty.set(prefPayload.isUseSoundForNotifications()); cssThemeProperty.set(prefPayload.getCssTheme()); @@ -697,6 +705,10 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid this.useStandbyModeProperty.set(useStandbyMode); } + public void setUseSoundForNotifications(boolean useSoundForNotifications) { + this.useSoundForNotificationsProperty.set(useSoundForNotifications); + } + public void setTakeOfferSelectedPaymentAccountId(String value) { prefPayload.setTakeOfferSelectedPaymentAccountId(value); requestPersistence(); @@ -946,6 +958,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid void setUseStandbyMode(boolean useStandbyMode); + void setUseSoundForNotifications(boolean useSoundForNotifications); + void setTakeOfferSelectedPaymentAccountId(String value); void setIgnoreDustThreshold(int value); diff --git a/core/src/main/java/haveno/core/user/PreferencesPayload.java b/core/src/main/java/haveno/core/user/PreferencesPayload.java index b0a2fd7d4a..5484c514ea 100644 --- a/core/src/main/java/haveno/core/user/PreferencesPayload.java +++ b/core/src/main/java/haveno/core/user/PreferencesPayload.java @@ -108,6 +108,7 @@ public final class PreferencesPayload implements PersistableEnvelope { private boolean useMarketNotifications = true; private boolean usePriceNotifications = true; private boolean useStandbyMode = false; + private boolean useSoundForNotifications = true; @Nullable private String rpcUser; @Nullable @@ -185,6 +186,7 @@ public final class PreferencesPayload implements PersistableEnvelope { .setUseMarketNotifications(useMarketNotifications) .setUsePriceNotifications(usePriceNotifications) .setUseStandbyMode(useStandbyMode) + .setUseSoundForNotifications(useSoundForNotifications) .setBuyerSecurityDepositAsPercent(buyerSecurityDepositAsPercent) .setIgnoreDustThreshold(ignoreDustThreshold) .setClearDataAfterDays(clearDataAfterDays) @@ -280,6 +282,7 @@ public final class PreferencesPayload implements PersistableEnvelope { proto.getUseMarketNotifications(), proto.getUsePriceNotifications(), proto.getUseStandbyMode(), + proto.getUseSoundForNotifications(), proto.getRpcUser().isEmpty() ? null : proto.getRpcUser(), proto.getRpcPw().isEmpty() ? null : proto.getRpcPw(), proto.getTakeOfferSelectedPaymentAccountId().isEmpty() ? null : proto.getTakeOfferSelectedPaymentAccountId(), diff --git a/core/src/main/java/haveno/core/xmr/Balances.java b/core/src/main/java/haveno/core/xmr/Balances.java index 6958c8288c..fe49b941fd 100644 --- a/core/src/main/java/haveno/core/xmr/Balances.java +++ b/core/src/main/java/haveno/core/xmr/Balances.java @@ -111,6 +111,7 @@ public class Balances { public XmrBalanceInfo getBalances() { synchronized (this) { + if (availableBalance == null) return null; return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(), availableBalance.longValue(), pendingBalance.longValue(), @@ -127,6 +128,9 @@ public class Balances { synchronized (this) { synchronized (HavenoUtils.xmrWalletService.getWalletLock()) { + // get non-trade balance before + BigInteger balanceSumBefore = getNonTradeBalanceSum(); + // get wallet balances BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getBalance(); availableBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getAvailableBalance(); @@ -160,8 +164,25 @@ public class Balances { reservedBalance = reservedOfferBalance.add(reservedTradeBalance); // notify balance update - UserThread.execute(() -> updateCounter.set(updateCounter.get() + 1)); + UserThread.execute(() -> { + + // check if funds received + boolean fundsReceived = balanceSumBefore != null && getNonTradeBalanceSum().compareTo(balanceSumBefore) > 0; + if (fundsReceived) { + HavenoUtils.playCashRegisterSound(); + } + + // increase counter to notify listeners + updateCounter.set(updateCounter.get() + 1); + }); } } } + + private BigInteger getNonTradeBalanceSum() { + synchronized (this) { + if (availableBalance == null) return null; + return availableBalance.add(pendingBalance).add(reservedOfferBalance); + } + } } diff --git a/core/src/main/resources/cash_register.wav b/core/src/main/resources/cash_register.wav new file mode 100644 index 0000000000..c11d914655 Binary files /dev/null and b/core/src/main/resources/cash_register.wav differ diff --git a/core/src/main/resources/chime.wav b/core/src/main/resources/chime.wav new file mode 100644 index 0000000000..c2ba1ab089 Binary files /dev/null and b/core/src/main/resources/chime.wav differ diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index a38f13bfec..8601e3206e 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1266,6 +1266,7 @@ setting.preferences.general=General preferences setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Max. deviation from market price setting.preferences.avoidStandbyMode=Avoid standby mode +setting.preferences.useSoundForNotifications=Play sounds for notifications setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_cs.properties b/core/src/main/resources/i18n/displayStrings_cs.properties index 3849693d1b..a3edc2ec22 100644 --- a/core/src/main/resources/i18n/displayStrings_cs.properties +++ b/core/src/main/resources/i18n/displayStrings_cs.properties @@ -987,6 +987,7 @@ setting.preferences.general=Základní nastavení setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Max. odchylka od tržní ceny setting.preferences.avoidStandbyMode=Vyhněte se pohotovostnímu režimu +setting.preferences.useSoundForNotifications=Přehrávat zvuky pro upozornění setting.preferences.autoConfirmXMR=Automatické potvrzení XMR setting.preferences.autoConfirmEnabled=Povoleno setting.preferences.autoConfirmRequiredConfirmations=Požadovaná potvrzení diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index 93a8edb198..1dc5d74051 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -987,6 +987,7 @@ setting.preferences.general=Allgemeine Voreinstellungen setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Max. Abweichung vom Marktpreis setting.preferences.avoidStandbyMode=Standby Modus verhindern +setting.preferences.useSoundForNotifications=Spiele Geräusche für Benachrichtigungen setting.preferences.autoConfirmXMR=XMR automatische Bestätigung setting.preferences.autoConfirmEnabled=Aktiviert setting.preferences.autoConfirmRequiredConfirmations=Benötigte Bestätigungen diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index bd4ee417a2..a3af6a0fd1 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -988,6 +988,7 @@ setting.preferences.general=Preferencias generales setting.preferences.explorer=Explorador Monero setting.preferences.deviation=Desviación máxima del precio de mercado setting.preferences.setting.preferences.avoidStandbyMode=Evitar modo en espera +setting.preferences.useSoundForNotifications=Reproducir sonidos para notificaciones setting.preferences.autoConfirmXMR=Autoconfirmación XMR setting.preferences.autoConfirmEnabled=Habilitado setting.preferences.autoConfirmRequiredConfirmations=Confirmaciones requeridas diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index eaf7147ae2..b0dd076441 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -984,6 +984,7 @@ setting.preferences.general=اولویت‌های عمومی setting.preferences.explorer=Monero Explorer setting.preferences.deviation=حداکثر تفاوت از قیمت روز بازار setting.preferences.avoidStandbyMode=حالت «آماده باش» را نادیده بگیر +setting.preferences.useSoundForNotifications=پخش صداها برای اعلان‌ها setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index 8d3b4ce468..901d3a1956 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -989,6 +989,7 @@ setting.preferences.general=Préférences générales setting.preferences.explorer=Exploreur Monero setting.preferences.deviation=Ecart maximal par rapport au prix du marché setting.preferences.avoidStandbyMode=Éviter le mode veille +setting.preferences.useSoundForNotifications=Jouer des sons pour les notifications setting.preferences.autoConfirmXMR=Auto-confirmation XMR setting.preferences.autoConfirmEnabled=Activé setting.preferences.autoConfirmRequiredConfirmations=Confirmations requises diff --git a/core/src/main/resources/i18n/displayStrings_it.properties b/core/src/main/resources/i18n/displayStrings_it.properties index 044873db1a..8eb8e15938 100644 --- a/core/src/main/resources/i18n/displayStrings_it.properties +++ b/core/src/main/resources/i18n/displayStrings_it.properties @@ -986,6 +986,7 @@ setting.preferences.general=Preferenze generali setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Deviazione massima del prezzo di mercato setting.preferences.avoidStandbyMode=Evita modalità standby +setting.preferences.useSoundForNotifications=Riproduci suoni per le notifiche setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_ja.properties b/core/src/main/resources/i18n/displayStrings_ja.properties index a0a71e4c1d..8f187cff65 100644 --- a/core/src/main/resources/i18n/displayStrings_ja.properties +++ b/core/src/main/resources/i18n/displayStrings_ja.properties @@ -987,6 +987,7 @@ setting.preferences.general=一般設定 setting.preferences.explorer=ビットコインのエクスプローラ setting.preferences.deviation=市場価格からの最大偏差 setting.preferences.avoidStandbyMode=スタンバイモードを避ける +setting.preferences.useSoundForNotifications=通知音の再生 setting.preferences.autoConfirmXMR=XMR自動確認 setting.preferences.autoConfirmEnabled=有効されました setting.preferences.autoConfirmRequiredConfirmations=必要承認 diff --git a/core/src/main/resources/i18n/displayStrings_pt-br.properties b/core/src/main/resources/i18n/displayStrings_pt-br.properties index 177f3dc674..19d7498f42 100644 --- a/core/src/main/resources/i18n/displayStrings_pt-br.properties +++ b/core/src/main/resources/i18n/displayStrings_pt-br.properties @@ -988,6 +988,7 @@ setting.preferences.general=Preferências gerais setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Desvio máx. do preço do mercado setting.preferences.avoidStandbyMode=Impedir modo de economia de energia +setting.preferences.useSoundForNotifications=Reproduzir sons para notificações setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index 6841f97cbd..a14e3c7b68 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -985,6 +985,7 @@ setting.preferences.general=Preferências gerais setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Máx. desvio do preço de mercado setting.preferences.avoidStandbyMode=Evite o modo espera +setting.preferences.useSoundForNotifications=Reproduzir sons para notificações setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index ccdcd4d6fb..346053e103 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -984,6 +984,7 @@ setting.preferences.general=Основные настройки setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Макс. отклонение от рыночного курса setting.preferences.avoidStandbyMode=Избегать режима ожидания +setting.preferences.useSoundForNotifications=Воспроизводить звуки для уведомлений setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index b23765c34a..626916d17e 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -984,6 +984,7 @@ setting.preferences.general=การตั้งค่าทั่วไป setting.preferences.explorer=Monero Explorer setting.preferences.deviation=สูงสุด ส่วนเบี่ยงเบนจากราคาตลาด setting.preferences.avoidStandbyMode=หลีกเลี่ยงโหมดแสตนบายด์ +setting.preferences.useSoundForNotifications=เล่นเสียงสำหรับการแจ้งเตือน setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_tr.properties b/core/src/main/resources/i18n/displayStrings_tr.properties index f7732593ad..73304adac6 100644 --- a/core/src/main/resources/i18n/displayStrings_tr.properties +++ b/core/src/main/resources/i18n/displayStrings_tr.properties @@ -1261,6 +1261,7 @@ setting.preferences.general=Genel tercihler setting.preferences.explorer=Monero Gezgini setting.preferences.deviation=Piyasa fiyatından maksimum sapma setting.preferences.avoidStandbyMode=Bekleme modundan kaçın +setting.preferences.useSoundForNotifications=Bildirimler için sesleri çal setting.preferences.autoConfirmXMR=XMR otomatik onay setting.preferences.autoConfirmEnabled=Etkin setting.preferences.autoConfirmRequiredConfirmations=Gerekli onaylar diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index a1978b79cc..ca3f46aaeb 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -986,6 +986,7 @@ setting.preferences.general=Tham khảo chung setting.preferences.explorer=Monero Explorer setting.preferences.deviation=Sai lệch tối đa so với giá thị trường setting.preferences.avoidStandbyMode=Tránh để chế độ chờ +setting.preferences.useSoundForNotifications=Phát âm thanh cho thông báo setting.preferences.autoConfirmXMR=XMR auto-confirm setting.preferences.autoConfirmEnabled=Enabled setting.preferences.autoConfirmRequiredConfirmations=Required confirmations diff --git a/core/src/main/resources/i18n/displayStrings_zh-hans.properties b/core/src/main/resources/i18n/displayStrings_zh-hans.properties index e809a3104c..c9dce9d751 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hans.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hans.properties @@ -987,6 +987,7 @@ setting.preferences.general=通用偏好 setting.preferences.explorer=比特币区块浏览器 setting.preferences.deviation=与市场价格最大差价 setting.preferences.avoidStandbyMode=避免待机模式 +setting.preferences.useSoundForNotifications=播放通知声音 setting.preferences.autoConfirmXMR=XMR 自动确认 setting.preferences.autoConfirmEnabled=启用 setting.preferences.autoConfirmRequiredConfirmations=已要求确认 diff --git a/core/src/main/resources/i18n/displayStrings_zh-hant.properties b/core/src/main/resources/i18n/displayStrings_zh-hant.properties index 435da337a2..53ee27d269 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hant.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hant.properties @@ -987,6 +987,7 @@ setting.preferences.general=通用偏好 setting.preferences.explorer=比特幣區塊瀏覽器 setting.preferences.deviation=與市場價格最大差價 setting.preferences.avoidStandbyMode=避免待機模式 +setting.preferences.useSoundForNotifications=播放通知音效 setting.preferences.autoConfirmXMR=XMR 自動確認 setting.preferences.autoConfirmEnabled=啟用 setting.preferences.autoConfirmRequiredConfirmations=已要求確認 diff --git a/desktop/src/main/java/haveno/desktop/main/settings/preferences/PreferencesView.java b/desktop/src/main/java/haveno/desktop/main/settings/preferences/PreferencesView.java index 08e6a083b6..06331e5f1d 100644 --- a/desktop/src/main/java/haveno/desktop/main/settings/preferences/PreferencesView.java +++ b/desktop/src/main/java/haveno/desktop/main/settings/preferences/PreferencesView.java @@ -108,7 +108,7 @@ public class PreferencesView extends ActivatableViewAndModel preferredTradeCurrencyComboBox; private ToggleButton showOwnOffersInOfferBook, useAnimations, useDarkMode, sortMarketCurrenciesNumerically, - avoidStandbyMode, useCustomFee, autoConfirmXmrToggle, hideNonAccountPaymentMethodsToggle, denyApiTakerToggle, + avoidStandbyMode, useSoundForNotifications, useCustomFee, autoConfirmXmrToggle, hideNonAccountPaymentMethodsToggle, denyApiTakerToggle, notifyOnPreReleaseToggle; private int gridRow = 0; private int displayCurrenciesGridRowIndex = 0; @@ -209,7 +209,7 @@ public class PreferencesView extends ActivatableViewAndModel preferences.setUseSoundForNotifications(useSoundForNotifications.isSelected())); } private void activateAutoConfirmPreferences() { diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 03cc6b2305..eaafbfb68d 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1740,6 +1740,7 @@ message PreferencesPayload { string buy_screen_crypto_currency_code = 60; string sell_screen_crypto_currency_code = 61; bool split_offer_output = 62; + bool use_sound_for_notifications = 63; } message AutoConfirmSettings {