|
34 | 34 | from functools import partial
|
35 | 35 | import queue
|
36 | 36 | import asyncio
|
37 |
| -from typing import Optional, TYPE_CHECKING, Sequence, Union, Dict, Mapping |
| 37 | +from typing import Optional, TYPE_CHECKING, Sequence, Union, Dict, Mapping, Callable, List, Set |
38 | 38 | import concurrent.futures
|
39 | 39 |
|
40 | 40 | from PyQt6.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont, QFontMetrics, QAction, QShortcut
|
@@ -267,6 +267,8 @@ def add_optional_tab(tabs, tab, icon, description):
|
267 | 267 |
|
268 | 268 | # network callbacks
|
269 | 269 | self.register_callbacks()
|
| 270 | + # wallet closing warning callbacks |
| 271 | + self.closing_warning_callbacks = [] # type: List[Callable[[], Optional[str]]] |
270 | 272 | # banner may already be there
|
271 | 273 | if self.network and self.network.banner:
|
272 | 274 | self.console.showMessage(self.network.banner)
|
@@ -2612,8 +2614,52 @@ def settings_dialog(self):
|
2612 | 2614 | if d.need_restart:
|
2613 | 2615 | self.show_warning(_('Please restart Electrum to activate the new GUI settings'), title=_('Success'))
|
2614 | 2616 |
|
| 2617 | + def _show_closing_warnings(self) -> bool: |
| 2618 | + """Show any closing warnings and return True if the user chose to quit anyway.""" |
| 2619 | + |
| 2620 | + warnings: Set[str] = set() |
| 2621 | + for cb in self.closing_warning_callbacks: |
| 2622 | + if warning := cb(): |
| 2623 | + warnings.add(warning) |
| 2624 | + |
| 2625 | + for warning in list(warnings)[:3]: |
| 2626 | + warning = _("An ongoing operation prevents Electrum from closing:") + "\n\n" + warning |
| 2627 | + buttons = QMessageBox.StandardButton.Cancel | QMessageBox.StandardButton.Close |
| 2628 | + result = self.show_warning( |
| 2629 | + msg=warning, |
| 2630 | + title=_("Don't close Electrum yet!"), |
| 2631 | + buttons=buttons, |
| 2632 | + defaultButton=QMessageBox.StandardButton.Cancel, |
| 2633 | + ) |
| 2634 | + if result == QMessageBox.StandardButton.Cancel: |
| 2635 | + break |
| 2636 | + else: |
| 2637 | + # user chose to cancel all warnings or there were no warnings |
| 2638 | + return True |
| 2639 | + return False |
| 2640 | + |
| 2641 | + def register_closing_warning_callback(self, callback: Callable[[], Optional[str]]) -> None: |
| 2642 | + """ |
| 2643 | + Registers a callback that will be called when the wallet is closed. If the callback |
| 2644 | + returns a string it will be shown to the user as a warning to prevent them closing the wallet. |
| 2645 | + """ |
| 2646 | + assert not asyncio.iscoroutinefunction(callback) |
| 2647 | + if not self.config.get("cmd") == "gui": |
| 2648 | + return |
| 2649 | + def warning_callback() -> Optional[str]: |
| 2650 | + try: |
| 2651 | + return callback() |
| 2652 | + except Exception: |
| 2653 | + self.logger.exception("Error in closing warning callback") |
| 2654 | + return None |
| 2655 | + self.logger.debug(f"registering wallet closing warning callback") |
| 2656 | + self.closing_warning_callbacks.append(warning_callback) |
| 2657 | + |
2615 | 2658 | def closeEvent(self, event):
|
2616 | 2659 | # note that closeEvent is NOT called if the user quits with Ctrl-C
|
| 2660 | + if not self._show_closing_warnings(): |
| 2661 | + event.ignore() |
| 2662 | + return |
2617 | 2663 | self.clean_up()
|
2618 | 2664 | event.accept()
|
2619 | 2665 |
|
@@ -2797,7 +2843,16 @@ def on_swap_result(self, txid: Optional[str], *, is_reverse: bool):
|
2797 | 2843 | if is_reverse:
|
2798 | 2844 | msg += messages.MSG_REVERSE_SWAP_FUNDING_MEMPOOL
|
2799 | 2845 | else:
|
2800 |
| - msg += messages.MSG_FORWARD_SWAP_FUNDING_MEMPOOL |
| 2846 | + msg += messages.MSG_FORWARD_SWAP_FUNDING_MEMPOOL + messages.MSG_FORWARD_SWAP_HTLC_EXPIRY |
| 2847 | + |
| 2848 | + def wallet_closing_warning_callback() -> Optional[str]: |
| 2849 | + # gets called when the wallet GUI is closed |
| 2850 | + warning = messages.MSG_REVERSE_SWAP_FUNDING_MEMPOOL if is_reverse \ |
| 2851 | + else messages.MSG_FORWARD_SWAP_FUNDING_MEMPOOL |
| 2852 | + if self.wallet.adb.get_tx_height(txid).height < 1: |
| 2853 | + return _("Ongoing submarine swap") + ":\n" + warning |
| 2854 | + self.register_closing_warning_callback(wallet_closing_warning_callback) |
| 2855 | + |
2801 | 2856 | self.show_message_signal.emit(msg)
|
2802 | 2857 | else:
|
2803 | 2858 | msg += _("Lightning funds were not received.") # FIXME should this not depend on is_reverse?
|
|
0 commit comments