diff --git a/core/src/main/java/bisq/core/user/Preferences.java b/core/src/main/java/bisq/core/user/Preferences.java index 0f72d7676e..a1e1a314bc 100644 --- a/core/src/main/java/bisq/core/user/Preferences.java +++ b/core/src/main/java/bisq/core/user/Preferences.java @@ -830,6 +830,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid requestPersistence(); } + public void setUseBitcoinUrisInQrCodes(boolean value) { + prefPayload.setUseBitcoinUrisInQrCodes(value); + requestPersistence(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Getter @@ -1148,6 +1153,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid void setUseFullModeDaoMonitor(boolean value); + void setUseBitcoinUrisInQrCodes(boolean value); + void setClearDataAfterDays(int value); void setBuyScreenCryptoCurrencyCode(String buyScreenCurrencyCode); diff --git a/core/src/main/java/bisq/core/user/PreferencesPayload.java b/core/src/main/java/bisq/core/user/PreferencesPayload.java index 4544cbeba4..332c61cdd2 100644 --- a/core/src/main/java/bisq/core/user/PreferencesPayload.java +++ b/core/src/main/java/bisq/core/user/PreferencesPayload.java @@ -140,6 +140,7 @@ public final class PreferencesPayload implements PersistableEnvelope { private boolean denyApiTaker; private boolean notifyOnPreRelease; private boolean useFullModeDaoMonitor; + private boolean useBitcoinUrisInQrCodes = true; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -209,7 +210,8 @@ public final class PreferencesPayload implements PersistableEnvelope { .setShowOffersMatchingMyAccounts(showOffersMatchingMyAccounts) .setDenyApiTaker(denyApiTaker) .setNotifyOnPreRelease(notifyOnPreRelease) - .setUseFullModeDaoMonitor(useFullModeDaoMonitor); + .setUseFullModeDaoMonitor(useFullModeDaoMonitor) + .setUseBitcoinUrisInQrCodes(useBitcoinUrisInQrCodes); Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory); Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((protobuf.TradeCurrency) e.toProtoMessage())); @@ -313,7 +315,8 @@ public final class PreferencesPayload implements PersistableEnvelope { proto.getShowOffersMatchingMyAccounts(), proto.getDenyApiTaker(), proto.getNotifyOnPreRelease(), - proto.getUseFullModeDaoMonitor() + proto.getUseFullModeDaoMonitor(), + proto.getUseBitcoinUrisInQrCodes() ); } } diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 4fceb8a7b1..979d8b155f 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1327,6 +1327,11 @@ setting.preferences.txFeeTooLarge=Your input is above any reasonable value (>500 setting.preferences.ignorePeers=Ignored peers [onion address:port] setting.preferences.ignoreDustThreshold=Min. non-dust output value setting.preferences.clearDataAfterDays=Clear sensitive data after (days) +setting.preferences.useBitcoinUris=Use bitcoin URIs in QR codes +setting.preferences.useBitcoinUris.tooltip=Bisq's QR codes can either store bitcoin URIs containing the address along\n\ + with some extra parameters (amount & label) or plain bitcoin addresses\n\ + with no additional data. Disable this option if your external wallet's\n\ + scanner cannot handle the bitcoin URI scheme format. setting.preferences.currenciesInList=Currencies in market price feed list setting.preferences.prefCurrency=Preferred currency setting.preferences.displayFiat=Display national currencies diff --git a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java index 25f61debc3..31a11f21df 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java @@ -63,6 +63,7 @@ import javafx.scene.control.CheckBox; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; +import javafx.scene.control.TextFormatter; import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -89,6 +90,7 @@ import java.io.ByteArrayInputStream; import java.util.Comparator; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import org.jetbrains.annotations.NotNull; @@ -184,7 +186,7 @@ public class DepositView extends ActivatableView { Tooltip.install(qrCodeImageView, new Tooltip(Res.get("shared.openLargeQRWindow"))); qrCodeImageView.setOnMouseClicked(e -> GUIUtil.showFeeInfoBeforeExecute( () -> UserThread.runAfter( - () -> new QRCodeWindow(getBitcoinURI()).show(), + () -> new QRCodeWindow(getStringToEncode()).show(), 200, TimeUnit.MILLISECONDS))); GridPane.setRowIndex(qrCodeImageView, gridRow); GridPane.setRowSpan(qrCodeImageView, 4); @@ -201,6 +203,12 @@ public class DepositView extends ActivatableView { if (DevEnv.isDevMode()) amountTextField.setText("10"); + Pattern pattern = Pattern.compile("^\\d+\\.?\\d*"); + amountTextField.setTextFormatter(new TextFormatter<>(change -> { + String newText = change.getControlNewText(); + return newText.isEmpty() || pattern.matcher(newText).matches() ? change : null; + })); + titledGroupBg.setVisible(false); titledGroupBg.setManaged(false); qrCodeImageView.setVisible(false); @@ -263,6 +271,15 @@ public class DepositView extends ActivatableView { if (tableView.getSelectionModel().getSelectedItem() == null && !sortedList.isEmpty()) tableView.getSelectionModel().select(0); + + if (!GUIUtil.getPreferences().isUseBitcoinUrisInQrCodes()) { + if (!amountTextField.getText().isEmpty()) { + amountTextField.clear(); + } + amountTextField.setDisable(true); + } else { + amountTextField.setDisable(false); + } } @Override @@ -299,7 +316,7 @@ public class DepositView extends ActivatableView { private void updateQRCode() { if (addressTextField.getAddress() != null && !addressTextField.getAddress().isEmpty()) { final byte[] imageBytes = QRCode - .from(getBitcoinURI()) + .from(getStringToEncode()) .withSize(150, 150) // code has 41 elements 8 px is border with 150 we get 3x scale and min. border .to(ImageType.PNG) .stream() @@ -331,6 +348,14 @@ public class DepositView extends ActivatableView { paymentLabelString); } + @NotNull + private String getStringToEncode() { + String address = addressTextField.getAddress() != null ? + addressTextField.getAddress() : ""; + return GUIUtil.getPreferences().isUseBitcoinUrisInQrCodes() ? + getBitcoinURI() : address; + } + /////////////////////////////////////////////////////////////////////////////////////////// // ColumnCellFactories /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java index 8db54e794a..ebdcbd437b 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java @@ -847,7 +847,7 @@ public abstract class MutableOfferView> exten missingCoinListener = (observable, oldValue, newValue) -> { if (!newValue.toString().equals("")) { final byte[] imageBytes = QRCode - .from(getBitcoinURI()) + .from(getStringToEncode()) .withSize(98, 98) // code has 41 elements 8 px is border with 98 we get double scale and min. border .to(ImageType.PNG) .stream() @@ -1231,7 +1231,7 @@ public abstract class MutableOfferView> exten Tooltip.install(qrCodeImageView, new Tooltip(Res.get("shared.openLargeQRWindow"))); qrCodeImageView.setOnMouseClicked(e -> GUIUtil.showFeeInfoBeforeExecute( () -> UserThread.runAfter( - () -> new QRCodeWindow(getBitcoinURI()).show(), + () -> new QRCodeWindow(getStringToEncode()).show(), 200, TimeUnit.MILLISECONDS))); GridPane.setRowIndex(qrCodeImageView, gridRow); GridPane.setColumnIndex(qrCodeImageView, 1); @@ -1340,6 +1340,14 @@ public abstract class MutableOfferView> exten model.getPaymentLabel()); } + @NotNull + private String getStringToEncode() { + String address = addressTextField.getAddress() != null ? + addressTextField.getAddress() : ""; + return GUIUtil.getPreferences().isUseBitcoinUrisInQrCodes() ? + getBitcoinURI() : address; + } + private void addAmountPriceFields() { // amountBox Tuple3 amountValueCurrencyBoxTuple = getEditableValueBox(Res.get("createOffer.amount.prompt")); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java index 5f8e92fa26..9e94382aa7 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java @@ -555,7 +555,7 @@ public class TakeOfferView extends ActivatableViewAndModel GUIUtil.showFeeInfoBeforeExecute( () -> UserThread.runAfter( - () -> new QRCodeWindow(getBitcoinURI()).show(), + () -> new QRCodeWindow(getStringToEncode()).show(), 200, TimeUnit.MILLISECONDS))); GridPane.setRowIndex(qrCodeImageView, gridRow); GridPane.setColumnIndex(qrCodeImageView, 1); @@ -1079,6 +1079,14 @@ public class TakeOfferView extends ActivatableViewAndModel amountValueCurrencyBoxTuple = getEditableValueBox(Res.get("takeOffer.amount.prompt")); diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/QRCodeWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/QRCodeWindow.java index 092660f9eb..9d5ba8ff75 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/QRCodeWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/QRCodeWindow.java @@ -17,7 +17,6 @@ package bisq.desktop.main.overlays.windows; -import bisq.desktop.components.AutoTooltipLabel; import bisq.desktop.main.overlays.Overlay; import bisq.core.locale.Res; @@ -25,14 +24,11 @@ import bisq.core.locale.Res; import net.glxn.qrgen.QRCode; import net.glxn.qrgen.image.ImageType; -import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.GridPane; -import javafx.scene.layout.Priority; import javafx.geometry.HPos; -import javafx.geometry.Insets; import java.io.ByteArrayInputStream; @@ -42,12 +38,12 @@ import org.slf4j.LoggerFactory; public class QRCodeWindow extends Overlay { private static final Logger log = LoggerFactory.getLogger(QRCodeWindow.class); private final ImageView qrCodeImageView; - private final String bitcoinURI; + private final String bitcoinAddressOrURI; - public QRCodeWindow(String bitcoinURI) { - this.bitcoinURI = bitcoinURI; + public QRCodeWindow(String bitcoinAddressOrURI) { + this.bitcoinAddressOrURI = bitcoinAddressOrURI; final byte[] imageBytes = QRCode - .from(bitcoinURI) + .from(bitcoinAddressOrURI) .withSize(250, 250) .to(ImageType.PNG) .stream() @@ -71,10 +67,11 @@ public class QRCodeWindow extends Overlay { GridPane.setHalignment(qrCodeImageView, HPos.CENTER); gridPane.getChildren().add(qrCodeImageView); - message = bitcoinURI.replace("%20", " ").replace("?", "\n?").replace("&", "\n&"); + message = bitcoinAddressOrURI.replace("%20", " ").replace("?", "\n?").replace("&", "\n&"); setTruncatedMessage(); - addMessage(); + GridPane.setHalignment(messageLabel, HPos.CENTER); + addButtons(); applyStyles(); display(); diff --git a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java index f0345dbadd..cf369a0598 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java @@ -80,6 +80,7 @@ import javafx.scene.control.ListView; import javafx.scene.control.Separator; import javafx.scene.control.TextField; import javafx.scene.control.ToggleButton; +import javafx.scene.control.Tooltip; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; @@ -97,6 +98,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.util.Callback; +import javafx.util.Duration; import javafx.util.StringConverter; import java.io.File; @@ -122,7 +124,7 @@ public class PreferencesView extends ActivatableViewAndModel + preferences.setUseBitcoinUrisInQrCodes(useBitcoinUrisToggle.isSelected())); + btcExplorerTextField.setText(preferences.getBlockChainExplorer().name); bsqExplorerTextField.setText(preferences.getBsqBlockChainExplorer().name); @@ -1172,6 +1185,7 @@ public class PreferencesView extends ActivatableViewAndModel