diff --git a/electrum/gui/icons/nostr.png b/electrum/gui/icons/nostr.png new file mode 100644 index 000000000..3148343bc Binary files /dev/null and b/electrum/gui/icons/nostr.png differ diff --git a/electrum/gui/qml/components/NetworkOverview.qml b/electrum/gui/qml/components/NetworkOverview.qml index 9c41609a0..9d6bc4399 100644 --- a/electrum/gui/qml/components/NetworkOverview.qml +++ b/electrum/gui/qml/components/NetworkOverview.qml @@ -217,6 +217,22 @@ Pane { text: Daemon.currentWallet.lightningNumPeers } + Heading { + Layout.columnSpan: 2 + text: qsTr('Nostr') + } + + Label { + text: qsTr('Relays:') + color: Material.accentColor + } + + Label { + Layout.fillWidth: true + text: Config.nostrRelays.replace(/,/g, "\n") + wrapMode: Text.Wrap + } + Heading { Layout.columnSpan: 2 text: qsTr('Proxy') @@ -286,6 +302,16 @@ Pane { dialog.open() } } + FlatButton { + Layout.fillWidth: true + Layout.preferredWidth: 1 + text: qsTr('Nostr Settings'); + icon.source: '../../icons/nostr.png' + onClicked: { + var dialog = nostrConfig.createObject(root) + dialog.open() + } + } } } @@ -302,4 +328,11 @@ Pane { onClosed: destroy() } } + + Component { + id: nostrConfig + NostrConfigDialog { + onClosed: destroy() + } + } } diff --git a/electrum/gui/qml/components/NostrConfigDialog.qml b/electrum/gui/qml/components/NostrConfigDialog.qml new file mode 100644 index 000000000..3f754fa80 --- /dev/null +++ b/electrum/gui/qml/components/NostrConfigDialog.qml @@ -0,0 +1,118 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material + +import org.electrum 1.0 + +import "controls" + +ElDialog { + id: rootItem + + title: qsTr('Nostr relays') + iconSource: Qt.resolvedUrl('../../icons/nostr.png') + + width: parent.width + height: parent.height + + padding: 0 + + property bool valid: true + + function clean_array(text) { + var relays = [] + const fragments = text.split("\n") + fragments.forEach(function(fragment) { + fragment = fragment.trim() + if (fragment != "" && !relays.includes(fragment)) + relays.push(fragment) + }) + return relays + } + + function verify(text) { + const re=/^wss?:\/\/([a-zA-Z0-9\-]+\.)+[a-zA-Z]+(\/.*)?$/ + const relays = clean_array(text) + var isvalid = relays.every(function(relay) { + return re.test(relay) + }) + return isvalid + } + + ColumnLayout { + width: parent.width + height: parent.height + spacing: 0 + + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.leftMargin: constants.paddingLarge + Layout.rightMargin: constants.paddingLarge + + RowLayout { + Layout.fillWidth: true + TextHighlightPane { + Layout.fillWidth: true + Label { + text: qsTr('Enter the list of Nostr relays') + width: parent.width + wrapMode: Text.Wrap + } + } + HelpButton { + heading: Config.shortDescFor('NOSTR_RELAYS') + helptext: Config.longDescFor('NOSTR_RELAYS') + } + } + + RowLayout { + Layout.fillWidth: true + ElTextArea { + id: relays_ta + Layout.fillWidth: true + Layout.fillHeight: true + font.family: FixedFont + wrapMode: TextEdit.WrapAnywhere + onTextChanged: valid = verify(text) + inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText | Qt.ImhNoAutoUppercase + background: PaneInsetBackground { + baseColor: constants.darkerDialogBackground + } + } + ColumnLayout { + Layout.alignment: Qt.AlignTop + ToolButton { + icon.source: '../../icons/paste.png' + icon.height: constants.iconSizeMedium + icon.width: constants.iconSizeMedium + onClicked: { + if (verify(AppController.clipboardToText())) { + if (!relays_ta.text.endsWith('\n')) + relays_ta.text = relays_ta.text + '\n' + relays_ta.text = relays_ta.text + AppController.clipboardToText() + } + } + } + } + } + } + + FlatButton { + Layout.fillWidth: true + text: qsTr('Ok') + enabled: valid + icon.source: '../../icons/confirmed.png' + onClicked: { + Config.nostrRelays = clean_array(relays_ta.text).join(",") + rootItem.close() + } + } + } + + + Component.onCompleted: { + relays_ta.text = Config.nostrRelays.replace(/,/g, "\n") + } +} diff --git a/electrum/gui/qml/qeconfig.py b/electrum/gui/qml/qeconfig.py index 0f656dba2..61aac644d 100644 --- a/electrum/gui/qml/qeconfig.py +++ b/electrum/gui/qml/qeconfig.py @@ -294,6 +294,17 @@ class QEConfig(AuthMixin, QObject): self.config.LIGHTNING_PAYMENT_FEE_MAX_MILLIONTHS = lightningPaymentFeeMaxMillionths self.lightningPaymentFeeMaxMillionthsChanged.emit() + nostrRelaysChanged = pyqtSignal() + @pyqtProperty(str, notify=nostrRelaysChanged) + def nostrRelays(self): + return self.config.NOSTR_RELAYS + + @nostrRelays.setter + def nostrRelays(self, nostr_relays): + if nostr_relays != self.config.NOSTR_RELAYS: + self.config.NOSTR_RELAYS = nostr_relays + self.nostrRelaysChanged.emit() + swapServerNPubChanged = pyqtSignal() @pyqtProperty(str, notify=swapServerNPubChanged) def swapServerNPub(self):