qt: ReceiveTab: fix flickering zeroconf message
What changed, and why it matters
This commit fixes a user-interface flickering bug in Electrum's 'Receive' tab. When the wallet synced new blockchain headers, the zeroconf (zero-confirmation) warning overlay would briefly disappear and reappear, and after a user clicked 'Accept' the warning could come back again. The patch remembers whether the user already accepted the warning for the current payment request and reorders widget updates to stop the flicker. There is no security vulnerability here.
No security action needed; this is a normal UI bugfix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change is purely a Qt UI state-management fix in electrum/gui/qt/receive_tab.py. It adds two instance variables (previous_request and confirmed_zeroconf_for_this_request) to track per-request user acceptance of zeroconf, passes a show_help flag into ReceiveWidget.update_visibility(), and reorders setText calls so the help text is set before the invoice text. No cryptographic, network, wallet, or permission logic is modified.
Changed components
electrum/gui/qt/receive_tab.pyInspect captured patch +17 / −9
diff --git a/electrum/gui/qt/receive_tab.py b/electrum/gui/qt/receive_tab.py
index 74377b3..fe60c56 100644
--- a/electrum/gui/qt/receive_tab.py
+++ b/electrum/gui/qt/receive_tab.py
@@ -20,6 +20,7 @@ from .util import read_QIcon, WWLabel, MessageBoxMixin, MONOSPACE_FONT, get_icon
if TYPE_CHECKING:
from .main_window import ElectrumWindow
+ from electrum.wallet import Request
class ReceiveTab(QWidget, MessageBoxMixin, Logger):
@@ -101,6 +102,9 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
self.receive_zeroconf_button = QPushButton(_('Accept'))
self.receive_zeroconf_button.clicked.connect(self.on_accept_zeroconf)
+ self.previous_request = None # type: Optional['Request']
+ self.confirmed_zeroconf_for_this_request = False # type: bool
+
def on_receive_rebalance():
if self.receive_rebalance_button.suggestion:
chan1, chan2, delta = self.receive_rebalance_button.suggestion
@@ -221,7 +225,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
def update_receive_widgets(self):
b = self.config.GUI_QT_RECEIVE_TAB_QR_VISIBLE
- self.receive_widget.update_visibility(b)
+ self.receive_widget.update_visibility(b, bool(self.receive_help_text.text()))
def update_current_request(self):
if len(self.request_list.selectionModel().selectedRows(0)) > 1:
@@ -229,6 +233,9 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
else:
key = self.request_list.get_current_key()
req = self.wallet.get_request(key) if key else None
+ if req != self.previous_request:
+ self.previous_request = req
+ self.confirmed_zeroconf_for_this_request = False
if req is None:
self.receive_e.setText('')
self.addr = self.URI = self.lnaddr = ''
@@ -243,7 +250,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
self.ln_help = help_texts.ln_help
can_rebalance = help_texts.can_rebalance()
can_swap = help_texts.can_swap()
- can_zeroconf = help_texts.can_zeroconf()
+ can_zeroconf = help_texts.can_zeroconf() if not self.confirmed_zeroconf_for_this_request else False
self.receive_rebalance_button.suggestion = help_texts.ln_rebalance_suggestion
self.receive_swap_button.suggestion = help_texts.ln_swap_suggestion
self.receive_rebalance_button.setVisible(can_rebalance)
@@ -253,25 +260,26 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
self.receive_zeroconf_button.setVisible(can_zeroconf)
self.receive_zeroconf_button.setEnabled(can_zeroconf)
text, data, help_text, title = self.get_tab_data()
+ if self.confirmed_zeroconf_for_this_request and help_texts.can_zeroconf():
+ help_text = ''
+ # set help before receive_e so we don't flicker from qr to help
+ self.receive_help_text.setText(help_text)
self.receive_e.setText(text)
self.receive_qr.setData(data)
- self.receive_help_text.setText(help_text)
for w in [self.receive_e, self.receive_qr]:
w.setEnabled(bool(text) and (not help_text or can_zeroconf))
w.setToolTip(help_text)
# macOS hack (similar to #4777)
self.receive_e.repaint()
# always show
- if can_zeroconf:
- # show the help message if zeroconf so user can first accept it and still sees the invoice
- # after accepting
- self.receive_widget.show_help()
self.receive_widget.setVisible(True)
self.toggle_qr_button.setEnabled(True)
self.update_receive_qr_window()
def on_accept_zeroconf(self):
self.receive_zeroconf_button.setVisible(False)
+ self.confirmed_zeroconf_for_this_request = True
+ self.receive_help_text.setText('')
self.update_receive_widgets()
def get_tab_data(self):
@@ -386,8 +394,8 @@ class ReceiveWidget(QWidget):
self.setLayout(vbox)
- def update_visibility(self, is_qr):
- if str(self.textedit.toPlainText()):
+ def update_visibility(self, is_qr: bool, show_help: bool):
+ if str(self.textedit.toPlainText()) and not show_help:
self.help_widget.setVisible(False)
self.textedit.setVisible(not is_qr)
self.qr.setVisible(is_qr)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.