1
0

handle gap limit warning when creating Request.

(using string error code for now, ideally should be properly defined
as an enum)

Also fix animation bug and work around broken ListView header implementation
This commit is contained in:
Sander van Grieken
2022-03-22 19:37:31 +01:00
parent 271f36d3b3
commit 03048d39b6
2 changed files with 110 additions and 81 deletions

View File

@@ -80,14 +80,12 @@ Pane {
Layout.columnSpan: 2 Layout.columnSpan: 2
text: qsTr('Create Request') text: qsTr('Create Request')
onClicked: { onClicked: {
var a = parseFloat(amount.text) createRequest()
Daemon.currentWallet.create_invoice(a, message.text, expires.currentValue)
} }
} }
} }
Frame { Frame {
clip: true
verticalPadding: 0 verticalPadding: 0
horizontalPadding: 0 horizontalPadding: 0
@@ -103,18 +101,15 @@ Pane {
color: Qt.darker(Material.background, 1.25) color: Qt.darker(Material.background, 1.25)
} }
ListView { ColumnLayout {
spacing: 0
anchors.fill: parent anchors.fill: parent
model: Daemon.currentWallet.requestModel Item {
headerPositioning: ListView.OverlayHeader Layout.preferredHeight: hitem.height
Layout.preferredWidth: parent.width
header: Item {
z: 1
height: hitem.height
width: ListView.view.width
Rectangle { Rectangle {
anchors.fill: hitem anchors.fill: parent
color: Qt.lighter(Material.background, 1.25) color: Qt.lighter(Material.background, 1.25)
} }
RowLayout { RowLayout {
@@ -127,76 +122,107 @@ Pane {
} }
} }
delegate: Item { ListView {
z: -1 Layout.fillHeight: true
height: item.height Layout.fillWidth: true
width: ListView.view.width clip: true
GridLayout {
id: item
columns: 5
Image {
Layout.rowSpan: 2
Layout.preferredWidth: 32
Layout.preferredHeight: 32
source: model.type == 0 ? "../../icons/bitcoin.png" : "../../icons/lightning.png"
}
Label {
Layout.fillWidth: true
Layout.columnSpan: 2
text: model.message
font.pixelSize: constants.fontSizeLarge
}
Label { model: Daemon.currentWallet.requestModel
text: qsTr('Amount: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.amount
font.pixelSize: constants.fontSizeSmall
}
Label { delegate: ItemDelegate {
text: qsTr('Timestamp: ') id: root
font.pixelSize: constants.fontSizeSmall height: item.height
} width: ListView.view.width
Label {
text: model.timestamp
font.pixelSize: constants.fontSizeSmall
}
Label { onClicked: console.log('Request ' + index + ' clicked')
text: qsTr('Status: ')
font.pixelSize: constants.fontSizeSmall GridLayout {
} id: item
Label {
text: model.status anchors {
font.pixelSize: constants.fontSizeSmall left: parent.left
right: parent.right
leftMargin: constants.paddingSmall
rightMargin: constants.paddingSmall
}
columns: 5
Image {
Layout.rowSpan: 2
Layout.preferredWidth: 32
Layout.preferredHeight: 32
source: model.type == 0 ? "../../icons/bitcoin.png" : "../../icons/lightning.png"
}
Label {
Layout.fillWidth: true
Layout.columnSpan: 2
text: model.message
font.pixelSize: constants.fontSizeLarge
}
Label {
text: qsTr('Amount: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.amount
font.pixelSize: constants.fontSizeSmall
}
Label {
text: qsTr('Timestamp: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.timestamp
font.pixelSize: constants.fontSizeSmall
}
Label {
text: qsTr('Status: ')
font.pixelSize: constants.fontSizeSmall
}
Label {
text: model.status
font.pixelSize: constants.fontSizeSmall
}
} }
} }
add: Transition {
NumberAnimation { properties: 'y'; from: -50; duration: 300 }
NumberAnimation { properties: 'opacity'; from: 0; to: 1.0; duration: 700 }
}
addDisplaced: Transition {
NumberAnimation { properties: 'y'; duration: 100 }
NumberAnimation { properties: 'opacity'; to: 1.0; duration: 700 * (1-from) }
}
} }
add: Transition {
NumberAnimation { properties: 'y'; from: -50; duration: 300 }
NumberAnimation { properties: 'opacity'; from: 0; to: 1.0; duration: 700 }
}
addDisplaced: Transition {
NumberAnimation { properties: 'y'; duration: 100 }
}
} }
} }
function createRequest(ignoreGaplimit = false) {
var a = parseFloat(amount.text)
Daemon.currentWallet.create_invoice(a, message.text, expires.currentValue, false, ignoreGaplimit)
}
Connections { Connections {
target: Daemon.currentWallet target: Daemon.currentWallet
function onRequestCreateSuccess() { function onRequestCreateSuccess() {
message.text = '' message.text = ''
amount.text = '' amount.text = ''
} }
function onRequestCreateError(error) { function onRequestCreateError(code, error) {
console.log(error) if (code == 'gaplimit') {
var dialog = app.messageDialog.createObject(app, {'text': error}) var dialog = app.messageDialog.createObject(app, {'text': error, 'yesno': true})
dialog.yesClicked.connect(function() {
createRequest(true)
})
} else {
console.log(error)
var dialog = app.messageDialog.createObject(app, {'text': error})
}
dialog.open() dialog.open()
} }
} }

View File

@@ -34,7 +34,7 @@ class QEWallet(QObject):
dataChanged = pyqtSignal() # dummy to silence warnings dataChanged = pyqtSignal() # dummy to silence warnings
requestCreateSuccess = pyqtSignal() requestCreateSuccess = pyqtSignal()
requestCreateError = pyqtSignal([str], arguments=['error']) requestCreateError = pyqtSignal([str,str], arguments=['code','error'])
requestStatus = pyqtSignal() requestStatus = pyqtSignal()
def on_request_status(self, event, *args): def on_request_status(self, event, *args):
@@ -122,12 +122,12 @@ class QEWallet(QObject):
tx = self.wallet.make_unsigned_transaction(coins=coins,outputs=outputs) tx = self.wallet.make_unsigned_transaction(coins=coins,outputs=outputs)
return True return True
def create_bitcoin_request(self, amount: int, message: str, expiration: int) -> Optional[str]: def create_bitcoin_request(self, amount: int, message: str, expiration: int, ignore_gap: bool) -> Optional[str]:
addr = self.wallet.get_unused_address() addr = self.wallet.get_unused_address()
if addr is None: if addr is None:
# TODO implement if not self.wallet.is_deterministic(): # imported wallet
return # TODO implement
#if not self.wallet.is_deterministic(): # imported wallet return
#msg = [ #msg = [
#_('No more addresses in your wallet.'), ' ', #_('No more addresses in your wallet.'), ' ',
#_('You are using a non-deterministic wallet, which cannot create new addresses.'), ' ', #_('You are using a non-deterministic wallet, which cannot create new addresses.'), ' ',
@@ -137,16 +137,18 @@ class QEWallet(QObject):
#if not self.question(''.join(msg)): #if not self.question(''.join(msg)):
#return #return
#addr = self.wallet.get_receiving_address() #addr = self.wallet.get_receiving_address()
#else: # deterministic wallet else: # deterministic wallet
#if not self.question(_("Warning: The next address will not be recovered automatically if you restore your wallet from seed; you may need to add it manually.\n\nThis occurs because you have too many unused addresses in your wallet. To avoid this situation, use the existing addresses first.\n\nCreate anyway?")): if not ignore_gap:
#return self.requestCreateError.emit('gaplimit',_("Warning: The next address will not be recovered automatically if you restore your wallet from seed; you may need to add it manually.\n\nThis occurs because you have too many unused addresses in your wallet. To avoid this situation, use the existing addresses first.\n\nCreate anyway?"))
#addr = self.wallet.create_new_address(False) return
addr = self.wallet.create_new_address(False)
req = self.wallet.make_payment_request(addr, amount, message, expiration) req = self.wallet.make_payment_request(addr, amount, message, expiration)
try: try:
self.wallet.add_payment_request(req) self.wallet.add_payment_request(req)
except Exception as e: except Exception as e:
self.logger.exception('Error adding payment request') self.logger.exception('Error adding payment request')
self.requestCreateError.emit(_('Error adding payment request') + ':\n' + repr(e)) self.requestCreateError.emit('fatal',_('Error adding payment request') + ':\n' + repr(e))
else: else:
# TODO: check this flow. Only if alias is defined in config. OpenAlias? # TODO: check this flow. Only if alias is defined in config. OpenAlias?
pass pass
@@ -155,24 +157,25 @@ class QEWallet(QObject):
return addr return addr
@pyqtSlot(int, 'QString', int) @pyqtSlot(int, 'QString', int)
def create_invoice(self, amount: int, message: str, expiration: int, is_lightning: bool = False): @pyqtSlot(int, 'QString', int, bool)
@pyqtSlot(int, 'QString', int, bool, bool)
def create_invoice(self, amount: int, message: str, expiration: int, is_lightning: bool = False, ignore_gap: bool = False):
expiry = expiration #TODO: self.config.get('request_expiry', PR_DEFAULT_EXPIRATION_WHEN_CREATING) expiry = expiration #TODO: self.config.get('request_expiry', PR_DEFAULT_EXPIRATION_WHEN_CREATING)
try: try:
if is_lightning: if is_lightning:
if not self.wallet.lnworker.channels: if not self.wallet.lnworker.channels:
#self.show_error(_("You need to open a Lightning channel first.")) self.requestCreateError.emit('fatal',_("You need to open a Lightning channel first."))
self.requestCreateError.emit(_("You need to open a Lightning channel first."))
return return
# TODO maybe show a warning if amount exceeds lnworker.num_sats_can_receive (as in kivy) # TODO maybe show a warning if amount exceeds lnworker.num_sats_can_receive (as in kivy)
key = self.wallet.lnworker.add_request(amount, message, expiry) key = self.wallet.lnworker.add_request(amount, message, expiry)
else: else:
key = self.create_bitcoin_request(amount, message, expiry) key = self.create_bitcoin_request(amount, message, expiry, ignore_gap)
if not key: if not key:
return return
#self.address_list.update() #self.address_list.update()
self._addressModel.init_model() self._addressModel.init_model()
except InvoiceError as e: except InvoiceError as e:
self.requestCreateError.emit(_('Error creating payment request') + ':\n' + str(e)) self.requestCreateError.emit('fatal',_('Error creating payment request') + ':\n' + str(e))
return return
assert key is not None assert key is not None