qml: initial channel open progress dialog
This commit is contained in:
110
electrum/gui/qml/components/ChannelOpenProgressDialog.qml
Normal file
110
electrum/gui/qml/components/ChannelOpenProgressDialog.qml
Normal file
@@ -0,0 +1,110 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Controls.Material 2.0
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
import "controls"
|
||||
|
||||
ElDialog {
|
||||
id: dialog
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
title: qsTr('Opening Channel...')
|
||||
standardButtons: Dialog.Close
|
||||
footer.visible: allowClose // work around standardButtons not really mutable to/from zero buttons
|
||||
allowClose: false
|
||||
|
||||
modal: true
|
||||
parent: Overlay.overlay
|
||||
Overlay.modal: Rectangle {
|
||||
color: "#aa000000"
|
||||
}
|
||||
|
||||
property alias state: s.state
|
||||
property alias error: errorText.text
|
||||
property alias peer: peerText.text
|
||||
|
||||
Item {
|
||||
id: s
|
||||
state: ''
|
||||
states: [
|
||||
State {
|
||||
name: 'success'
|
||||
PropertyChanges { target: dialog; allowClose: true }
|
||||
PropertyChanges { target: stateText; text: qsTr('Success!') }
|
||||
PropertyChanges { target: infoText; visible: true }
|
||||
PropertyChanges { target: icon; source: '../../icons/confirmed.png' }
|
||||
},
|
||||
State {
|
||||
name: 'failed'
|
||||
PropertyChanges { target: dialog; allowClose: true }
|
||||
PropertyChanges { target: stateText; text: qsTr('Problem opening channel') }
|
||||
PropertyChanges { target: errorText; visible: true }
|
||||
PropertyChanges { target: icon; source: '../../icons/warning.png' }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Image {
|
||||
id: icon
|
||||
source: ''
|
||||
visible: source != ''
|
||||
Layout.preferredWidth: constants.iconSizeLarge
|
||||
Layout.preferredHeight: constants.iconSizeLarge
|
||||
}
|
||||
BusyIndicator {
|
||||
id: spinner
|
||||
running: visible
|
||||
visible: s.state == ''
|
||||
Layout.preferredWidth: constants.iconSizeLarge
|
||||
Layout.preferredHeight: constants.iconSizeLarge
|
||||
}
|
||||
|
||||
Label {
|
||||
id: stateText
|
||||
text: qsTr('Opening Channel...')
|
||||
font.pixelSize: constants.fontSizeXXLarge
|
||||
}
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: dialog.width * 3/4
|
||||
Label {
|
||||
id: peerText
|
||||
font.pixelSize: constants.fontSizeMedium
|
||||
width: parent.width
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: dialog.width * 2/3
|
||||
InfoTextArea {
|
||||
id: errorText
|
||||
visible: false
|
||||
iconStyle: InfoTextArea.IconStyle.Error
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
InfoTextArea {
|
||||
id: infoText
|
||||
visible: false
|
||||
text: qsTr('Channel will be open after 3 confirmations')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -157,10 +157,18 @@ Pane {
|
||||
}
|
||||
}
|
||||
|
||||
property var channelOpenProgressDialogInstance
|
||||
Component {
|
||||
id: channelOpenProgressDialog
|
||||
ChannelOpenProgressDialog { }
|
||||
}
|
||||
|
||||
ChannelOpener {
|
||||
id: channelopener
|
||||
wallet: Daemon.currentWallet
|
||||
onAuthRequired: {
|
||||
app.handleAuthRequired(channelopener, method)
|
||||
}
|
||||
onValidationError: {
|
||||
if (code == 'invalid_nodeid') {
|
||||
var dialog = app.messageDialog.createObject(root, { 'text': message })
|
||||
@@ -180,18 +188,23 @@ Pane {
|
||||
})
|
||||
dialog.open()
|
||||
}
|
||||
onChannelOpening: {
|
||||
console.log('Channel is opening')
|
||||
channelOpenProgressDialogInstance = channelOpenProgressDialog.createObject(app, {peer: peer})
|
||||
channelOpenProgressDialogInstance.open()
|
||||
}
|
||||
onChannelOpenError: {
|
||||
var dialog = app.messageDialog.createObject(root, { 'text': message })
|
||||
dialog.open()
|
||||
channelOpenProgressDialogInstance.state = 'failed'
|
||||
channelOpenProgressDialogInstance.error = message
|
||||
}
|
||||
onChannelOpenSuccess: {
|
||||
var message = 'success!'
|
||||
if (!has_backup)
|
||||
message = message + ' (but no backup. TODO: show QR)'
|
||||
var dialog = app.messageDialog.createObject(root, { 'text': message })
|
||||
dialog.open()
|
||||
channelOpenProgressDialogInstance.state = 'success'
|
||||
channelOpenProgressDialogInstance.error = message
|
||||
channelopener.wallet.channelModel.new_channel(cid)
|
||||
app.stack.pop()
|
||||
// app.stack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import threading
|
||||
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
|
||||
from electrum.i18n import _
|
||||
@@ -9,8 +11,9 @@ from electrum.gui import messages
|
||||
from .qewallet import QEWallet
|
||||
from .qetypes import QEAmount
|
||||
from .qetxfinalizer import QETxFinalizer
|
||||
from .auth import AuthMixin, auth_protect
|
||||
|
||||
class QEChannelOpener(QObject):
|
||||
class QEChannelOpener(QObject, AuthMixin):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
@@ -24,6 +27,7 @@ class QEChannelOpener(QObject):
|
||||
|
||||
validationError = pyqtSignal([str,str], arguments=['code','message'])
|
||||
conflictingBackup = pyqtSignal([str], arguments=['message'])
|
||||
channelOpening = pyqtSignal([str], arguments=['peer'])
|
||||
channelOpenError = pyqtSignal([str], arguments=['message'])
|
||||
channelOpenSuccess = pyqtSignal([str,bool], arguments=['cid','has_backup'])
|
||||
|
||||
@@ -156,25 +160,32 @@ class QEChannelOpener(QObject):
|
||||
self._finalizer.wallet = self._wallet
|
||||
self.finalizerChanged.emit()
|
||||
|
||||
@auth_protect
|
||||
def do_open_channel(self, funding_tx, conn_str, password):
|
||||
self._logger.debug('opening channel')
|
||||
# read funding_sat from tx; converts '!' to int value
|
||||
funding_sat = funding_tx.output_value_for_address(ln_dummy_address())
|
||||
lnworker = self._wallet.wallet.lnworker
|
||||
try:
|
||||
chan, funding_tx = lnworker.open_channel(
|
||||
connect_str=conn_str,
|
||||
funding_tx=funding_tx,
|
||||
funding_sat=funding_sat,
|
||||
push_amt_sat=0,
|
||||
password=password)
|
||||
except Exception as e:
|
||||
self._logger.exception("Problem opening channel")
|
||||
self.channelOpenError.emit(_('Problem opening channel: ') + '\n' + repr(e))
|
||||
return
|
||||
|
||||
self._logger.debug('opening channel succeeded')
|
||||
self.channelOpenSuccess.emit(chan.channel_id.hex(), chan.has_onchain_backup())
|
||||
def open_thread():
|
||||
try:
|
||||
chan, _funding_tx = lnworker.open_channel(
|
||||
connect_str=conn_str,
|
||||
funding_tx=funding_tx,
|
||||
funding_sat=funding_sat,
|
||||
push_amt_sat=0,
|
||||
password=password)
|
||||
except Exception as e:
|
||||
self._logger.exception("Problem opening channel: %s", repr(e))
|
||||
self.channelOpenError.emit(repr(e))
|
||||
return
|
||||
|
||||
self._logger.debug('opening channel succeeded')
|
||||
self.channelOpenSuccess.emit(chan.channel_id.hex(), chan.has_onchain_backup())
|
||||
|
||||
self._logger.debug('starting open thread')
|
||||
self.channelOpening.emit(conn_str)
|
||||
threading.Thread(target=open_thread).start()
|
||||
|
||||
# TODO: it would be nice to show this before broadcasting
|
||||
#if chan.has_onchain_backup():
|
||||
|
||||
Reference in New Issue
Block a user