request_dialog.py (5262B)
1 from typing import TYPE_CHECKING 2 3 from kivy.factory import Factory 4 from kivy.lang import Builder 5 from kivy.core.clipboard import Clipboard 6 from kivy.app import App 7 from kivy.clock import Clock 8 9 from electrum.gui.kivy.i18n import _ 10 from electrum.invoices import pr_tooltips, pr_color 11 from electrum.invoices import PR_UNKNOWN, PR_UNPAID, PR_FAILED, PR_TYPE_LN 12 13 if TYPE_CHECKING: 14 from ...main_window import ElectrumWindow 15 16 17 Builder.load_string(''' 18 #:import KIVY_GUI_PATH electrum.gui.kivy.KIVY_GUI_PATH 19 20 <RequestDialog@Popup> 21 id: popup 22 amount_str: '' 23 title: '' 24 description:'' 25 is_lightning: False 26 key:'' 27 warning: '' 28 status_str: '' 29 status_color: 1,1,1,1 30 shaded: False 31 show_text: False 32 AnchorLayout: 33 anchor_x: 'center' 34 BoxLayout: 35 orientation: 'vertical' 36 size_hint: 1, 1 37 padding: '10dp' 38 spacing: '10dp' 39 QRCodeWidget: 40 id: qr 41 shaded: False 42 foreground_color: (0, 0, 0, 0.5) if self.shaded else (0, 0, 0, 0) 43 on_touch_down: 44 touch = args[1] 45 if self.collide_point(*touch.pos): self.shaded = not self.shaded 46 TopLabel: 47 text: _('Description') + ': ' + root.description or _('None') 48 TopLabel: 49 text: _('Amount') + ': ' + root.amount_str 50 TopLabel: 51 text: (_('Address') if not root.is_lightning else _('Payment hash')) + ': ' 52 RefLabel: 53 data: root.key 54 name: (_('Address') if not root.is_lightning else _('Payment hash')) 55 TopLabel: 56 text: _('Status') + ': ' + root.status_str 57 color: root.status_color 58 TopLabel: 59 text: root.warning 60 color: (0.9, 0.6, 0.3, 1) 61 Widget: 62 size_hint: 1, 0.2 63 BoxLayout: 64 size_hint: 1, None 65 height: '48dp' 66 Button: 67 size_hint: 1, None 68 height: '48dp' 69 text: _('Delete') 70 on_release: root.delete_dialog() 71 IconButton: 72 icon: f'atlas://{KIVY_GUI_PATH}/theming/light/copy' 73 size_hint: 0.5, None 74 height: '48dp' 75 on_release: root.copy_to_clipboard() 76 IconButton: 77 icon: f'atlas://{KIVY_GUI_PATH}/theming/light/share' 78 size_hint: 0.5, None 79 height: '48dp' 80 on_release: root.do_share() 81 Button: 82 size_hint: 1, None 83 height: '48dp' 84 text: _('Close') 85 on_release: popup.dismiss() 86 ''') 87 88 class RequestDialog(Factory.Popup): 89 90 def __init__(self, title, key): 91 self.status = PR_UNKNOWN 92 Factory.Popup.__init__(self) 93 self.app = App.get_running_app() # type: ElectrumWindow 94 self.title = title 95 self.key = key 96 r = self.app.wallet.get_request(key) 97 self.is_lightning = r.is_lightning() 98 self.data = r.invoice if self.is_lightning else self.app.wallet.get_request_URI(r) 99 self.amount_sat = r.get_amount_sat() 100 self.amount_str = self.app.format_amount_and_units(self.amount_sat) 101 self.description = r.message 102 self.update_status() 103 104 def on_open(self): 105 data = self.data 106 if self.is_lightning: 107 # encode lightning invoices as uppercase so QR encoding can use 108 # alphanumeric mode; resulting in smaller QR codes 109 data = data.upper() 110 self.ids.qr.set_data(data) 111 112 def update_status(self): 113 req = self.app.wallet.get_request(self.key) 114 self.status = self.app.wallet.get_request_status(self.key) 115 self.status_str = req.get_status_str(self.status) 116 self.status_color = pr_color[self.status] 117 if self.status == PR_UNPAID and self.is_lightning and self.app.wallet.lnworker: 118 if self.amount_sat and self.amount_sat > self.app.wallet.lnworker.num_sats_can_receive(): 119 self.warning = _('Warning') + ': ' + _('This amount exceeds the maximum you can currently receive with your channels') 120 if self.status == PR_UNPAID and not self.is_lightning: 121 address = req.get_address() 122 if self.app.wallet.is_used(address): 123 self.warning = _('Warning') + ': ' + _('This address is being reused') 124 125 def on_dismiss(self): 126 self.app.request_popup = None 127 128 def copy_to_clipboard(self): 129 Clipboard.copy(self.data) 130 msg = _('Text copied to clipboard.') 131 Clock.schedule_once(lambda dt: self.app.show_info(msg)) 132 133 def do_share(self): 134 self.app.do_share(self.data, _("Share Bitcoin Request")) 135 self.dismiss() 136 137 def delete_dialog(self): 138 from .question import Question 139 def cb(result): 140 if result: 141 self.app.wallet.delete_request(self.key) 142 self.dismiss() 143 self.app.receive_screen.update() 144 d = Question(_('Delete request?'), cb) 145 d.open()