kivy: store contacts as invoices
This commit is contained in:
parent
f5fcae7f11
commit
078cabd745
|
@ -258,8 +258,8 @@ class ElectrumWindow(App):
|
||||||
panel.switch_to(tab)
|
panel.switch_to(tab)
|
||||||
|
|
||||||
def show_request(self, addr):
|
def show_request(self, addr):
|
||||||
self.receive_screen.screen.address = addr
|
|
||||||
self.switch_to('receive')
|
self.switch_to('receive')
|
||||||
|
self.receive_screen.screen.address = addr
|
||||||
|
|
||||||
def scan_qr(self, on_complete):
|
def scan_qr(self, on_complete):
|
||||||
if platform != 'android':
|
if platform != 'android':
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 946 B |
|
@ -202,12 +202,32 @@ class SendScreen(CScreen):
|
||||||
self.screen.amount = self.app.format_amount_and_units(amount)
|
self.screen.amount = self.app.format_amount_and_units(amount)
|
||||||
self.screen.message = pr.get_memo()
|
self.screen.message = pr.get_memo()
|
||||||
|
|
||||||
|
def do_save(self):
|
||||||
|
if not self.screen.address:
|
||||||
|
return
|
||||||
|
if self.payment_request:
|
||||||
|
# it sould be already saved
|
||||||
|
return
|
||||||
|
# save address as invoice
|
||||||
|
from electrum.paymentrequest import make_unsigned_request, PaymentRequest
|
||||||
|
req = {'address':self.screen.address, 'memo':self.screen.message}
|
||||||
|
amount = self.app.get_amount(self.screen.amount) if self.screen.amount else 0
|
||||||
|
req['amount'] = amount
|
||||||
|
pr = make_unsigned_request(req).SerializeToString()
|
||||||
|
pr = PaymentRequest(pr)
|
||||||
|
self.app.invoices.add(pr)
|
||||||
|
self.app.update_tab('invoices')
|
||||||
|
self.app.show_info(_("Invoice saved"))
|
||||||
|
|
||||||
def do_paste(self):
|
def do_paste(self):
|
||||||
contents = unicode(self.app._clipboard.paste())
|
contents = unicode(self.app._clipboard.paste())
|
||||||
|
if not contents:
|
||||||
|
self.app.show_info(_("Clipboard is empty"))
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
uri = parse_URI(contents)
|
uri = parse_URI(contents)
|
||||||
except:
|
except:
|
||||||
self.app.show_info("Invalid URI", contents)
|
self.app.show_info(_("Clipboard content is not a Bitcoin URI"))
|
||||||
return
|
return
|
||||||
self.set_URI(uri)
|
self.set_URI(uri)
|
||||||
|
|
||||||
|
@ -324,20 +344,14 @@ class ReceiveScreen(CScreen):
|
||||||
self.app._clipboard.copy(uri)
|
self.app._clipboard.copy(uri)
|
||||||
self.app.show_info(_('Request copied to clipboard'))
|
self.app.show_info(_('Request copied to clipboard'))
|
||||||
|
|
||||||
def do_save(self):
|
def on_amount_or_message(self):
|
||||||
addr = str(self.screen.address)
|
addr = str(self.screen.address)
|
||||||
amount = str(self.screen.amount)
|
amount = str(self.screen.amount)
|
||||||
message = str(self.screen.message) #.ids.message_input.text)
|
message = str(self.screen.message) #.ids.message_input.text)
|
||||||
if not message and not amount:
|
|
||||||
return False
|
|
||||||
amount = self.app.get_amount(amount) if amount else 0
|
amount = self.app.get_amount(amount) if amount else 0
|
||||||
req = self.app.wallet.make_payment_request(addr, amount, message, None)
|
req = self.app.wallet.make_payment_request(addr, amount, message, None)
|
||||||
self.app.wallet.add_payment_request(req, self.app.electrum_config)
|
self.app.wallet.add_payment_request(req, self.app.electrum_config)
|
||||||
self.app.update_tab('requests')
|
self.app.update_tab('requests')
|
||||||
return True
|
|
||||||
|
|
||||||
def on_amount_or_message(self):
|
|
||||||
self.do_save()
|
|
||||||
Clock.schedule_once(lambda dt: self.update_qr())
|
Clock.schedule_once(lambda dt: self.update_qr())
|
||||||
|
|
||||||
def do_new(self):
|
def do_new(self):
|
||||||
|
@ -345,34 +359,6 @@ class ReceiveScreen(CScreen):
|
||||||
self.app.show_info(_('Please use the existing requests first.'))
|
self.app.show_info(_('Please use the existing requests first.'))
|
||||||
|
|
||||||
|
|
||||||
class ContactsScreen(CScreen):
|
|
||||||
kvname = 'contacts'
|
|
||||||
|
|
||||||
def add_new_contact(self):
|
|
||||||
dlg = Cache.get('electrum_widgets', 'NewContactDialog')
|
|
||||||
if not dlg:
|
|
||||||
dlg = NewContactDialog()
|
|
||||||
Cache.append('electrum_widgets', 'NewContactDialog', dlg)
|
|
||||||
dlg.open()
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
contact_list = self.screen.ids.contact_container
|
|
||||||
contact_list.clear_widgets()
|
|
||||||
child = -1
|
|
||||||
children = contact_list.children
|
|
||||||
for key in sorted(self.app.contacts.keys()):
|
|
||||||
_type, value = self.app.contacts[key]
|
|
||||||
child += 1
|
|
||||||
try:
|
|
||||||
if children[child].label == value:
|
|
||||||
continue
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
ci = Factory.ContactItem()
|
|
||||||
ci.address = key
|
|
||||||
ci.label = value
|
|
||||||
contact_list.add_widget(ci)
|
|
||||||
|
|
||||||
|
|
||||||
pr_text = {
|
pr_text = {
|
||||||
PR_UNPAID:_('Pending'),
|
PR_UNPAID:_('Pending'),
|
||||||
|
@ -401,11 +387,16 @@ class InvoicesScreen(CScreen):
|
||||||
ci = Factory.InvoiceItem()
|
ci = Factory.InvoiceItem()
|
||||||
ci.key = pr.get_id()
|
ci.key = pr.get_id()
|
||||||
ci.requestor = pr.get_requestor()
|
ci.requestor = pr.get_requestor()
|
||||||
ci.memo = pr.memo
|
ci.memo = pr.get_memo()
|
||||||
ci.amount = self.app.format_amount_and_units(pr.get_amount())
|
amount = pr.get_amount()
|
||||||
status = self.app.invoices.get_status(ci.key)
|
if amount:
|
||||||
ci.status = pr_text[status]
|
ci.amount = self.app.format_amount_and_units(amount)
|
||||||
ci.icon = pr_icon[status]
|
status = self.app.invoices.get_status(ci.key)
|
||||||
|
ci.status = pr_text[status]
|
||||||
|
ci.icon = pr_icon[status]
|
||||||
|
else:
|
||||||
|
ci.amount = _('No Amount')
|
||||||
|
ci.status = ''
|
||||||
exp = pr.get_expiration_date()
|
exp = pr.get_expiration_date()
|
||||||
ci.date = format_time(exp) if exp else _('Never')
|
ci.date = format_time(exp) if exp else _('Never')
|
||||||
ci.screen = self
|
ci.screen = self
|
||||||
|
@ -444,8 +435,9 @@ class RequestsScreen(CScreen):
|
||||||
expiration = req.get('exp', None)
|
expiration = req.get('exp', None)
|
||||||
status = req.get('status')
|
status = req.get('status')
|
||||||
signature = req.get('sig')
|
signature = req.get('sig')
|
||||||
|
|
||||||
ci = Factory.RequestItem()
|
ci = Factory.RequestItem()
|
||||||
ci.address = req['address']
|
ci.address = address
|
||||||
ci.memo = self.app.wallet.get_label(address)
|
ci.memo = self.app.wallet.get_label(address)
|
||||||
if amount:
|
if amount:
|
||||||
status = req.get('status')
|
status = req.get('status')
|
||||||
|
@ -476,22 +468,6 @@ class RequestsScreen(CScreen):
|
||||||
d.open()
|
d.open()
|
||||||
|
|
||||||
|
|
||||||
class CSpinner(Factory.Spinner):
|
|
||||||
'''CustomDropDown that allows fading out the dropdown
|
|
||||||
'''
|
|
||||||
|
|
||||||
def _update_dropdown(self, *largs):
|
|
||||||
dp = self._dropdown
|
|
||||||
cls = self.option_cls
|
|
||||||
if isinstance(cls, string_types):
|
|
||||||
cls = Factory.get(cls)
|
|
||||||
dp.clear_widgets()
|
|
||||||
def do_release(option):
|
|
||||||
Clock.schedule_once(lambda dt: dp.select(option.text), .25)
|
|
||||||
for value in self.values:
|
|
||||||
item = cls(text=value)
|
|
||||||
item.bind(on_release=do_release)
|
|
||||||
dp.add_widget(item)
|
|
||||||
|
|
||||||
|
|
||||||
class TabbedCarousel(Factory.TabbedPanel):
|
class TabbedCarousel(Factory.TabbedPanel):
|
||||||
|
|
|
@ -75,27 +75,27 @@ SendScreen:
|
||||||
height: '48dp'
|
height: '48dp'
|
||||||
IconButton:
|
IconButton:
|
||||||
id: qr
|
id: qr
|
||||||
size_hint: 0.5, 1
|
size_hint: 0.6, 1
|
||||||
on_release: app.scan_qr(on_complete=app.set_URI)
|
on_release: app.scan_qr(on_complete=app.set_URI)
|
||||||
icon: 'atlas://gui/kivy/theming/light/camera'
|
icon: 'atlas://gui/kivy/theming/light/camera'
|
||||||
Button:
|
Button:
|
||||||
id: paste_button
|
|
||||||
text: _('Paste')
|
text: _('Paste')
|
||||||
on_release: s.parent.do_paste()
|
on_release: s.parent.do_paste()
|
||||||
Button:
|
Button:
|
||||||
text: _('Clear')
|
text: _('Clear')
|
||||||
size_hint: 1, None
|
|
||||||
height: '48dp'
|
|
||||||
on_release: s.parent.do_clear()
|
on_release: s.parent.do_clear()
|
||||||
|
IconButton:
|
||||||
|
size_hint: 0.6, 1
|
||||||
|
on_release: s.parent.do_save()
|
||||||
|
icon: 'atlas://gui/kivy/theming/light/save'
|
||||||
BoxLayout:
|
BoxLayout:
|
||||||
size_hint: 1, None
|
size_hint: 1, None
|
||||||
height: '48dp'
|
height: '48dp'
|
||||||
Widget:
|
Widget:
|
||||||
size_hint: 1, 1
|
size_hint: 2, 1
|
||||||
Button:
|
Button:
|
||||||
text: _('Send')
|
text: _('Pay')
|
||||||
size_hint: 1, None
|
size_hint: 1, 1
|
||||||
height: '48dp'
|
|
||||||
on_release: s.parent.do_send()
|
on_release: s.parent.do_send()
|
||||||
Widget:
|
Widget:
|
||||||
size_hint: 1, 1
|
size_hint: 1, 1
|
||||||
|
|
|
@ -186,8 +186,13 @@ class PaymentRequest:
|
||||||
def get_amount(self):
|
def get_amount(self):
|
||||||
return sum(map(lambda x:x[2], self.outputs))
|
return sum(map(lambda x:x[2], self.outputs))
|
||||||
|
|
||||||
|
def get_address(self):
|
||||||
|
o = self.outputs[0]
|
||||||
|
assert o[0] == TYPE_ADDRESS
|
||||||
|
return o[1]
|
||||||
|
|
||||||
def get_requestor(self):
|
def get_requestor(self):
|
||||||
return self.requestor if self.requestor else 'unknown'
|
return self.requestor if self.requestor else self.get_address()
|
||||||
|
|
||||||
def get_verify_status(self):
|
def get_verify_status(self):
|
||||||
return self.error
|
return self.error
|
||||||
|
@ -196,7 +201,7 @@ class PaymentRequest:
|
||||||
return self.memo
|
return self.memo
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
return self.id
|
return self.id if self.requestor else self.get_address()
|
||||||
|
|
||||||
def get_outputs(self):
|
def get_outputs(self):
|
||||||
return self.outputs[:]
|
return self.outputs[:]
|
||||||
|
@ -421,7 +426,7 @@ class InvoiceStore(object):
|
||||||
for k, pr in self.invoices.items():
|
for k, pr in self.invoices.items():
|
||||||
l[k] = {
|
l[k] = {
|
||||||
'hex': str(pr).encode('hex'),
|
'hex': str(pr).encode('hex'),
|
||||||
'requestor': pr.get_requestor(),
|
'requestor': pr.requestor,
|
||||||
'txid': pr.tx
|
'txid': pr.tx
|
||||||
}
|
}
|
||||||
path = os.path.join(self.config.path, 'invoices')
|
path = os.path.join(self.config.path, 'invoices')
|
||||||
|
|
Loading…
Reference in New Issue