mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-10-05 15:08:25 +00:00
Large refactor to add ButtonOption and mark_for_translation
This commit is contained in:
+6
-23
@@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: seedsigner 0.8.5\n"
|
"Project-Id-Version: seedsigner 0.8.5\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2024-11-02 12:38-0500\n"
|
"POT-Creation-Date: 2024-11-02 16:48-0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -151,9 +151,6 @@ msgstr[1] ""
|
|||||||
msgid "{} change"
|
msgid "{} change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. First variable is either "Multisig" or the fingerprint for single sig;
|
|
||||||
#. Second is "Change" or "Addr" (change vs receive addr); Third is the address
|
|
||||||
#. index number (e.g. your #4 receive addr).
|
|
||||||
#: src/seedsigner/gui/screens/psbt_screens.py
|
#: src/seedsigner/gui/screens/psbt_screens.py
|
||||||
#: src/seedsigner/models/settings_definition.py
|
#: src/seedsigner/models/settings_definition.py
|
||||||
#: src/seedsigner/views/seed_views.py
|
#: src/seedsigner/views/seed_views.py
|
||||||
@@ -164,6 +161,7 @@ msgstr ""
|
|||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Abbreviation for receive address
|
||||||
#: src/seedsigner/gui/screens/psbt_screens.py
|
#: src/seedsigner/gui/screens/psbt_screens.py
|
||||||
msgid "Addr"
|
msgid "Addr"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -263,6 +261,7 @@ msgstr ""
|
|||||||
#. a label for the shortened Key-id of a BIP-32 master HD wallet
|
#. a label for the shortened Key-id of a BIP-32 master HD wallet
|
||||||
#: src/seedsigner/gui/screens/seed_screens.py
|
#: src/seedsigner/gui/screens/seed_screens.py
|
||||||
#: src/seedsigner/gui/screens/tools_screens.py
|
#: src/seedsigner/gui/screens/tools_screens.py
|
||||||
|
#: src/seedsigner/views/seed_views.py
|
||||||
msgid "fingerprint"
|
msgid "fingerprint"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -817,7 +816,7 @@ msgid ""
|
|||||||
"addresses."
|
"addresses."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/seedsigner/views/psbt_views.py src/seedsigner/views/view.py
|
#: src/seedsigner/views/psbt_views.py
|
||||||
msgid "Continue"
|
msgid "Continue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1295,11 +1294,6 @@ msgstr ""
|
|||||||
msgid "Return to PSBT"
|
msgid "Return to PSBT"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Inserts mainnet/testnet/regtest and derivation path
|
|
||||||
#: src/seedsigner/views/seed_views.py
|
|
||||||
msgid "Current network setting ({}) doesn't match {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/seedsigner/views/seed_views.py
|
#: src/seedsigner/views/seed_views.py
|
||||||
msgid "Signing messages for custom derivation paths not supported"
|
msgid "Signing messages for custom derivation paths not supported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1470,9 +1464,9 @@ msgstr ""
|
|||||||
msgid "Change Setting"
|
msgid "Change Setting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Inserts mainnet/testnet/regtest
|
#. Inserts mainnet/testnet/regtest and derivation path
|
||||||
#: src/seedsigner/views/view.py
|
#: src/seedsigner/views/view.py
|
||||||
msgid "Current network setting ({}) doesn't match current action."
|
msgid "Current network setting ({}) doesn't match {}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/seedsigner/views/view.py
|
#: src/seedsigner/views/view.py
|
||||||
@@ -1493,14 +1487,3 @@ msgstr ""
|
|||||||
msgid "Option Disabled"
|
msgid "Option Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/seedsigner/views/view.py
|
|
||||||
msgid "Security Tip"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/seedsigner/views/view.py
|
|
||||||
msgid ""
|
|
||||||
"For maximum security,\n"
|
|
||||||
"remove the MicroSD card\n"
|
|
||||||
"before continuing."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
[extract_messages]
|
[extract_messages]
|
||||||
|
keywords = _ _mft mark_for_translation ButtonOption
|
||||||
add_comments = TRANSLATOR_NOTE:
|
add_comments = TRANSLATOR_NOTE:
|
||||||
strip_comments = yes
|
strip_comments = yes
|
||||||
add_location = file
|
add_location = file
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from seedsigner.gui.components import (BtcAmount, Icon, FontAwesomeIconConstants
|
|||||||
from seedsigner.gui.renderer import Renderer
|
from seedsigner.gui.renderer import Renderer
|
||||||
from seedsigner.models.threads import BaseThread
|
from seedsigner.models.threads import BaseThread
|
||||||
|
|
||||||
from .screen import ButtonListScreen
|
from .screen import ButtonListScreen, ButtonOption
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class PSBTOverviewScreen(ButtonListScreen):
|
|||||||
# Customize defaults
|
# Customize defaults
|
||||||
self.title = _("Review PSBT")
|
self.title = _("Review PSBT")
|
||||||
self.is_bottom_list = True
|
self.is_bottom_list = True
|
||||||
self.button_data = [_("Review Details")]
|
self.button_data = [ButtonOption("Review Details")]
|
||||||
|
|
||||||
# This screen can take a while to load while parsing the PSBT
|
# This screen can take a while to load while parsing the PSBT
|
||||||
self.show_loading_screen = True
|
self.show_loading_screen = True
|
||||||
@@ -479,7 +479,7 @@ class PSBTMathScreen(ButtonListScreen):
|
|||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
# Customize defaults
|
# Customize defaults
|
||||||
self.title = _("PSBT Math")
|
self.title = _("PSBT Math")
|
||||||
self.button_data = [_("Review Recipients")]
|
self.button_data = [ButtonOption("Review Recipients")]
|
||||||
self.is_bottom_list = True
|
self.is_bottom_list = True
|
||||||
|
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
@@ -675,9 +675,18 @@ class PSBTChangeDetailsScreen(ButtonListScreen):
|
|||||||
))
|
))
|
||||||
|
|
||||||
screen_y = self.components[-1].screen_y + self.components[-1].height + 2*GUIConstants.COMPONENT_PADDING
|
screen_y = self.components[-1].screen_y + self.components[-1].height + 2*GUIConstants.COMPONENT_PADDING
|
||||||
|
|
||||||
|
change_type = _("Multisig") if self.is_multisig else self.fingerprint
|
||||||
|
|
||||||
|
if self.is_change_derivation_path :
|
||||||
|
addr_type = _("Change")
|
||||||
|
else:
|
||||||
|
# TRANSLATOR_NOTE: Abbreviation for receive address
|
||||||
|
addr_type = _("Addr")
|
||||||
|
|
||||||
|
value_text = "{}: {} #{}".format(change_type, addr_type, self.derivation_path_addr_index)
|
||||||
self.components.append(IconTextLine(
|
self.components.append(IconTextLine(
|
||||||
# TRANSLATOR_NOTE: First variable is either "Multisig" or the fingerprint for single sig; Second is "Change" or "Addr" (change vs receive addr); Third is the address index number (e.g. your #4 receive addr).
|
value_text=value_text,
|
||||||
value_text="""{}: {} #{}""".format(_("Multisig") if self.is_multisig else self.fingerprint, _("Change") if self.is_change_derivation_path else _("Addr"), self.derivation_path_addr_index),
|
|
||||||
icon_name=SeedSignerIconConstants.FINGERPRINT,
|
icon_name=SeedSignerIconConstants.FINGERPRINT,
|
||||||
icon_color=GUIConstants.INFO_COLOR,
|
icon_color=GUIConstants.INFO_COLOR,
|
||||||
is_text_centered=False,
|
is_text_centered=False,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from gettext import gettext as _
|
|||||||
from PIL import Image, ImageDraw, ImageColor
|
from PIL import Image, ImageDraw, ImageColor
|
||||||
from typing import Any, List, Tuple
|
from typing import Any, List, Tuple
|
||||||
|
|
||||||
|
from seedsigner.helpers.l10n import mark_for_translation as _mft
|
||||||
from seedsigner.gui.components import (GUIConstants,
|
from seedsigner.gui.components import (GUIConstants,
|
||||||
BaseComponent, Button, Icon, IconButton, LargeIconButton,
|
BaseComponent, Button, Icon, IconButton, LargeIconButton,
|
||||||
SeedSignerIconConstants, TopNav, TextArea, load_image)
|
SeedSignerIconConstants, TopNav, TextArea, load_image)
|
||||||
@@ -252,9 +253,23 @@ class BaseTopNavScreen(BaseScreen):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ButtonOption:
|
||||||
|
"""
|
||||||
|
Note: The babel config in setup.cfg will extract the `button_label` string for translation
|
||||||
|
"""
|
||||||
|
button_label: str
|
||||||
|
icon_name: str = None
|
||||||
|
icon_color: str = None
|
||||||
|
right_icon_name: str = None
|
||||||
|
button_label_color: str = None
|
||||||
|
return_data: Any = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ButtonListScreen(BaseTopNavScreen):
|
class ButtonListScreen(BaseTopNavScreen):
|
||||||
button_data: list = None # list can be a mix of str or tuple(label: str, icon_name: str)
|
button_data: list[ButtonOption] = None
|
||||||
selected_button: int = 0
|
selected_button: int = 0
|
||||||
is_button_text_centered: bool = True
|
is_button_text_centered: bool = True
|
||||||
is_bottom_list: bool = False
|
is_bottom_list: bool = False
|
||||||
@@ -295,26 +310,38 @@ class ButtonListScreen(BaseTopNavScreen):
|
|||||||
self.has_scroll_arrows = True
|
self.has_scroll_arrows = True
|
||||||
|
|
||||||
self.buttons: List[Button] = []
|
self.buttons: List[Button] = []
|
||||||
for i, button_label in enumerate(self.button_data):
|
for i, button_option in enumerate(self.button_data):
|
||||||
icon_name = None
|
icon_name = None
|
||||||
icon_color = None
|
icon_color = None
|
||||||
right_icon_name = None
|
right_icon_name = None
|
||||||
button_label_color = None
|
button_label_color = None
|
||||||
|
|
||||||
# TODO: Define an actual class for button_data?
|
if type(button_option) == ButtonOption:
|
||||||
if type(button_label) == tuple:
|
button_label = button_option.button_label
|
||||||
if len(button_label) == 2:
|
icon_name = button_option.icon_name
|
||||||
(button_label, icon_name) = button_label
|
icon_color = button_option.icon_color
|
||||||
icon_color = GUIConstants.BUTTON_FONT_COLOR
|
right_icon_name = button_option.right_icon_name
|
||||||
|
button_label_color = button_option.button_label_color
|
||||||
|
|
||||||
elif len(button_label) == 3:
|
else:
|
||||||
(button_label, icon_name, icon_color) = button_label
|
raise Exception("Refactor needed!")
|
||||||
|
|
||||||
elif len(button_label) == 4:
|
# # TODO: Complete refactor away from str|tuple to ButtonOption
|
||||||
(button_label, icon_name, icon_color, button_label_color) = button_label
|
# elif type(button_option) == str:
|
||||||
|
# button_label = button_option
|
||||||
|
# elif type(button_option) == tuple:
|
||||||
|
# if len(button_option) == 2:
|
||||||
|
# (button_label, icon_name) = button_option
|
||||||
|
# icon_color = GUIConstants.BUTTON_FONT_COLOR
|
||||||
|
|
||||||
elif len(button_label) == 5:
|
# elif len(button_option) == 3:
|
||||||
(button_label, icon_name, icon_color, button_label_color, right_icon_name) = button_label
|
# (button_label, icon_name, icon_color) = button_option
|
||||||
|
|
||||||
|
# elif len(button_option) == 4:
|
||||||
|
# (button_label, icon_name, icon_color, button_label_color) = button_option
|
||||||
|
|
||||||
|
# elif len(button_option) == 5:
|
||||||
|
# (button_label, icon_name, icon_color, button_label_color, right_icon_name) = button_option
|
||||||
|
|
||||||
button_kwargs = dict(
|
button_kwargs = dict(
|
||||||
text=_(button_label), # Wrap here for just-in-time translations
|
text=_(button_label), # Wrap here for just-in-time translations
|
||||||
@@ -547,11 +574,20 @@ class LargeButtonScreen(BaseTopNavScreen):
|
|||||||
button_start_y = self.top_nav.height + int((self.canvas_height - (self.top_nav.height + GUIConstants.COMPONENT_PADDING) - (2 * button_height) - GUIConstants.COMPONENT_PADDING) / 2)
|
button_start_y = self.top_nav.height + int((self.canvas_height - (self.top_nav.height + GUIConstants.COMPONENT_PADDING) - (2 * button_height) - GUIConstants.COMPONENT_PADDING) / 2)
|
||||||
|
|
||||||
self.buttons = []
|
self.buttons = []
|
||||||
for i, button_label in enumerate(self.button_data):
|
for i, button_option in enumerate(self.button_data):
|
||||||
if type(button_label) == tuple:
|
if type(button_option) == ButtonOption:
|
||||||
(button_label, icon_name) = button_label
|
button_label = button_option.button_label
|
||||||
|
icon_name = button_option.icon_name
|
||||||
else:
|
else:
|
||||||
icon_name = None
|
raise Exception("Refactor needed!")
|
||||||
|
|
||||||
|
# elif type(button_option) == str:
|
||||||
|
# button_label = button_option
|
||||||
|
# icon_name = None
|
||||||
|
# elif type(button_option) == tuple:
|
||||||
|
# (button_label, icon_name) = button_option
|
||||||
|
# else:
|
||||||
|
# print(type(button_option))
|
||||||
|
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
button_start_x = GUIConstants.EDGE_PADDING
|
button_start_x = GUIConstants.EDGE_PADDING
|
||||||
@@ -848,18 +884,20 @@ class QRDisplayScreen(BaseScreen):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LargeIconStatusScreen(ButtonListScreen):
|
class LargeIconStatusScreen(ButtonListScreen):
|
||||||
title: str = _("Success!")
|
title: str = _mft("Success!")
|
||||||
status_icon_name: str = SeedSignerIconConstants.SUCCESS
|
status_icon_name: str = SeedSignerIconConstants.SUCCESS
|
||||||
status_icon_size: int = GUIConstants.ICON_PRIMARY_SCREEN_SIZE
|
status_icon_size: int = GUIConstants.ICON_PRIMARY_SCREEN_SIZE
|
||||||
status_color: str = GUIConstants.SUCCESS_COLOR
|
status_color: str = GUIConstants.SUCCESS_COLOR
|
||||||
status_headline: str = None
|
status_headline: str = None
|
||||||
text: str = "" # The body text of the screen
|
text: str = "" # The body text of the screen
|
||||||
text_edge_padding: int = GUIConstants.EDGE_PADDING
|
text_edge_padding: int = GUIConstants.EDGE_PADDING
|
||||||
button_data: list = field(default_factory=lambda: [_("OK")])
|
button_data: list = None
|
||||||
allow_text_overflow: bool = False
|
allow_text_overflow: bool = False
|
||||||
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
|
if not self.button_data:
|
||||||
|
self.button_data = [ButtonOption("OK")]
|
||||||
self.is_bottom_list = True
|
self.is_bottom_list = True
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
|
|
||||||
@@ -971,17 +1009,17 @@ class WarningEdgesMixin:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class WarningScreen(WarningEdgesMixin, LargeIconStatusScreen):
|
class WarningScreen(WarningEdgesMixin, LargeIconStatusScreen):
|
||||||
title: str = _("Caution")
|
title: str = _mft("Caution")
|
||||||
status_icon_name: str = SeedSignerIconConstants.WARNING
|
status_icon_name: str = SeedSignerIconConstants.WARNING
|
||||||
status_color: str = "yellow"
|
status_color: str = "yellow"
|
||||||
status_headline: str = _("Privacy Leak!") # The colored text under the alert icon
|
status_headline: str = _mft("Privacy Leak!") # The colored text under the alert icon
|
||||||
button_data: list = field(default_factory=lambda: [_("I Understand")])
|
button_data: list = field(default_factory=lambda: [ButtonOption("I Understand")])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DireWarningScreen(WarningScreen):
|
class DireWarningScreen(WarningScreen):
|
||||||
status_headline: str = _("Classified Info!") # The colored text under the alert icon
|
status_headline: str = _mft("Classified Info!") # The colored text under the alert icon
|
||||||
status_color: str = GUIConstants.DIRE_WARNING_COLOR
|
status_color: str = GUIConstants.DIRE_WARNING_COLOR
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from seedsigner.gui.renderer import Renderer
|
|||||||
from seedsigner.helpers.qr import QR
|
from seedsigner.helpers.qr import QR
|
||||||
from seedsigner.models.threads import BaseThread, ThreadsafeCounter
|
from seedsigner.models.threads import BaseThread, ThreadsafeCounter
|
||||||
|
|
||||||
from .screen import RET_CODE__BACK_BUTTON, BaseScreen, BaseTopNavScreen, ButtonListScreen, KeyboardScreen, WarningEdgesMixin
|
from .screen import RET_CODE__BACK_BUTTON, BaseScreen, BaseTopNavScreen, ButtonListScreen, ButtonOption, KeyboardScreen, WarningEdgesMixin
|
||||||
from ..components import (Button, FontAwesomeIconConstants, Fonts, FormattedAddress, IconButton,
|
from ..components import (Button, FontAwesomeIconConstants, Fonts, FormattedAddress, IconButton,
|
||||||
IconTextLine, SeedSignerIconConstants, TextArea, GUIConstants, reflow_text_into_pages)
|
IconTextLine, SeedSignerIconConstants, TextArea, GUIConstants, reflow_text_into_pages)
|
||||||
|
|
||||||
@@ -607,7 +607,7 @@ class SeedExportXpubDetailsScreen(WarningEdgesMixin, ButtonListScreen):
|
|||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
# Programmatically set up other args
|
# Programmatically set up other args
|
||||||
self.button_data = [_("Export Xpub")]
|
self.button_data = [ButtonOption("Export Xpub")]
|
||||||
self.title = _("Xpub Details")
|
self.title = _("Xpub Details")
|
||||||
|
|
||||||
# Initialize the base class
|
# Initialize the base class
|
||||||
@@ -1138,7 +1138,8 @@ class SeedTranscribeSeedQRWholeQRScreen(WarningEdgesMixin, ButtonListScreen):
|
|||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.title = _("Transcribe SeedQR")
|
self.title = _("Transcribe SeedQR")
|
||||||
# TRANSLATOR_NOTE: Refers to the QR code size: 21x21, 25x25, or 29x29
|
# TRANSLATOR_NOTE: Refers to the QR code size: 21x21, 25x25, or 29x29
|
||||||
self.button_data = [_("Begin {}x{}").format(self.num_modules, self.num_modules)]
|
button_label = _("Begin {}x{}").format(self.num_modules, self.num_modules)
|
||||||
|
self.button_data = [ButtonOption(button_label)]
|
||||||
self.is_bottom_list = True
|
self.is_bottom_list = True
|
||||||
self.status_color = GUIConstants.DIRE_WARNING_COLOR
|
self.status_color = GUIConstants.DIRE_WARNING_COLOR
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
@@ -1564,7 +1565,7 @@ class SeedSignMessageConfirmMessageScreen(ButtonListScreen):
|
|||||||
self.title = f"""Message (pt {self.page_num + 1}/{len(self.sign_message_data["paged_message"])})"""
|
self.title = f"""Message (pt {self.page_num + 1}/{len(self.sign_message_data["paged_message"])})"""
|
||||||
self.is_bottom_list = True
|
self.is_bottom_list = True
|
||||||
self.is_button_text_centered = True
|
self.is_button_text_centered = True
|
||||||
self.button_data = [_("Next")]
|
self.button_data = [ButtonOption("Next")]
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
|
|
||||||
message_display = TextArea(
|
message_display = TextArea(
|
||||||
@@ -1586,7 +1587,7 @@ class SeedSignMessageConfirmAddressScreen(ButtonListScreen):
|
|||||||
self.title = _("Confirm Address")
|
self.title = _("Confirm Address")
|
||||||
self.is_bottom_list = True
|
self.is_bottom_list = True
|
||||||
self.is_button_text_centered = True
|
self.is_button_text_centered = True
|
||||||
self.button_data = [_("Sign Message")]
|
self.button_data = [ButtonOption("Sign Message")]
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
|
|
||||||
derivation_path_display = IconTextLine(
|
derivation_path_display = IconTextLine(
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ from gettext import gettext as _
|
|||||||
from PIL.ImageOps import autocontrast
|
from PIL.ImageOps import autocontrast
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from seedsigner.helpers.l10n import mark_for_translation as _mft
|
||||||
from seedsigner.gui.components import Button, CheckboxButton, CheckedSelectionButton, FontAwesomeIconConstants, Fonts, GUIConstants, Icon, IconButton, IconTextLine, TextArea
|
from seedsigner.gui.components import Button, CheckboxButton, CheckedSelectionButton, FontAwesomeIconConstants, Fonts, GUIConstants, Icon, IconButton, IconTextLine, TextArea
|
||||||
from seedsigner.gui.screens.scan_screens import ScanScreen
|
from seedsigner.gui.screens.scan_screens import ScanScreen
|
||||||
from seedsigner.gui.screens.screen import BaseScreen, BaseTopNavScreen, ButtonListScreen
|
from seedsigner.gui.screens.screen import BaseScreen, BaseTopNavScreen, ButtonListScreen, ButtonOption
|
||||||
from seedsigner.hardware.buttons import HardwareButtonsConstants
|
from seedsigner.hardware.buttons import HardwareButtonsConstants
|
||||||
from seedsigner.hardware.camera import Camera
|
from seedsigner.hardware.camera import Camera
|
||||||
from seedsigner.models.settings import SettingsConstants
|
from seedsigner.models.settings import SettingsConstants
|
||||||
@@ -309,13 +310,13 @@ class DonateScreen(BaseTopNavScreen):
|
|||||||
@dataclass
|
@dataclass
|
||||||
class SettingsQRConfirmationScreen(ButtonListScreen):
|
class SettingsQRConfirmationScreen(ButtonListScreen):
|
||||||
config_name: str = None
|
config_name: str = None
|
||||||
title: str = _("Settings QR")
|
title: str = _mft("Settings QR")
|
||||||
status_message: str = _("Settings updated...")
|
status_message: str = _mft("Settings updated...")
|
||||||
is_bottom_list: bool = True
|
is_bottom_list: bool = True
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
# Customize defaults
|
# Customize defaults
|
||||||
self.button_data = [_("Home")]
|
self.button_data = [ButtonOption("Home")]
|
||||||
self.show_back_button = False
|
self.show_back_button = False
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ def get_standard_derivation_path(network: str = SettingsConstants.MAINNET, walle
|
|||||||
elif script_type == SettingsConstants.NATIVE_SEGWIT:
|
elif script_type == SettingsConstants.NATIVE_SEGWIT:
|
||||||
return f"m/48'/{network_path}/0'/2'"
|
return f"m/48'/{network_path}/0'/2'"
|
||||||
elif script_type == SettingsConstants.TAPROOT:
|
elif script_type == SettingsConstants.TAPROOT:
|
||||||
raise Exception("Taproot multisig/musig not yet supported")
|
raise Exception("Taproot multisig not yet supported")
|
||||||
else:
|
else:
|
||||||
raise Exception("Unexpected script type")
|
raise Exception("Unexpected script type")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
def mark_for_translation(message: str) -> str:
|
||||||
|
# Wraps the target string literal for translation but does NOT return the translated string.
|
||||||
|
return message
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
|
|
||||||
from gettext import gettext as _
|
from seedsigner.helpers.l10n import mark_for_translation as _mft
|
||||||
|
|
||||||
|
|
||||||
class SettingsConstants:
|
class SettingsConstants:
|
||||||
@@ -11,25 +11,25 @@ class SettingsConstants:
|
|||||||
OPTION__PROMPT = "P"
|
OPTION__PROMPT = "P"
|
||||||
OPTION__REQUIRED = "R"
|
OPTION__REQUIRED = "R"
|
||||||
OPTIONS__ENABLED_DISABLED = [
|
OPTIONS__ENABLED_DISABLED = [
|
||||||
(OPTION__ENABLED, _("Enabled")),
|
(OPTION__ENABLED, _mft("Enabled")),
|
||||||
(OPTION__DISABLED, _("Disabled")),
|
(OPTION__DISABLED, _mft("Disabled")),
|
||||||
]
|
]
|
||||||
OPTIONS__ONLY_DISABLED = [
|
OPTIONS__ONLY_DISABLED = [
|
||||||
(OPTION__DISABLED, _("Disabled")),
|
(OPTION__DISABLED, _mft("Disabled")),
|
||||||
]
|
]
|
||||||
OPTIONS__PROMPT_REQUIRED_DISABLED = [
|
OPTIONS__PROMPT_REQUIRED_DISABLED = [
|
||||||
(OPTION__PROMPT, _("Prompt")),
|
(OPTION__PROMPT, _mft("Prompt")),
|
||||||
(OPTION__REQUIRED, _("Required")),
|
(OPTION__REQUIRED, _mft("Required")),
|
||||||
(OPTION__DISABLED, _("Disabled")),
|
(OPTION__DISABLED, _mft("Disabled")),
|
||||||
]
|
]
|
||||||
OPTIONS__ENABLED_DISABLED_REQUIRED = OPTIONS__ENABLED_DISABLED +[
|
OPTIONS__ENABLED_DISABLED_REQUIRED = OPTIONS__ENABLED_DISABLED +[
|
||||||
(OPTION__REQUIRED, _("Required")),
|
(OPTION__REQUIRED, _mft("Required")),
|
||||||
]
|
]
|
||||||
OPTIONS__ENABLED_DISABLED_PROMPT = OPTIONS__ENABLED_DISABLED + [
|
OPTIONS__ENABLED_DISABLED_PROMPT = OPTIONS__ENABLED_DISABLED + [
|
||||||
(OPTION__PROMPT, _("Prompt")),
|
(OPTION__PROMPT, _mft("Prompt")),
|
||||||
]
|
]
|
||||||
ALL_OPTIONS = OPTIONS__ENABLED_DISABLED_PROMPT + [
|
ALL_OPTIONS = OPTIONS__ENABLED_DISABLED_PROMPT + [
|
||||||
(OPTION__REQUIRED, _("Required")),
|
(OPTION__REQUIRED, _mft("Required")),
|
||||||
]
|
]
|
||||||
|
|
||||||
# User-facing selection options
|
# User-facing selection options
|
||||||
@@ -77,10 +77,10 @@ class SettingsConstants:
|
|||||||
BTC_DENOMINATION__THRESHOLD = "thr"
|
BTC_DENOMINATION__THRESHOLD = "thr"
|
||||||
BTC_DENOMINATION__BTCSATSHYBRID = "hyb"
|
BTC_DENOMINATION__BTCSATSHYBRID = "hyb"
|
||||||
ALL_BTC_DENOMINATIONS = [
|
ALL_BTC_DENOMINATIONS = [
|
||||||
(BTC_DENOMINATION__BTC, _("BTC")),
|
(BTC_DENOMINATION__BTC, _mft("BTC")),
|
||||||
(BTC_DENOMINATION__SATS, _("sats")),
|
(BTC_DENOMINATION__SATS, _mft("sats")),
|
||||||
(BTC_DENOMINATION__THRESHOLD, _("Threshold at 0.01")),
|
(BTC_DENOMINATION__THRESHOLD, _mft("Threshold at 0.01")),
|
||||||
(BTC_DENOMINATION__BTCSATSHYBRID, _("BTC | sats hybrid")),
|
(BTC_DENOMINATION__BTCSATSHYBRID, _mft("BTC | sats hybrid")),
|
||||||
]
|
]
|
||||||
|
|
||||||
CAMERA_ROTATION__0 = 0
|
CAMERA_ROTATION__0 = 0
|
||||||
@@ -88,10 +88,10 @@ class SettingsConstants:
|
|||||||
CAMERA_ROTATION__180 = 180
|
CAMERA_ROTATION__180 = 180
|
||||||
CAMERA_ROTATION__270 = 270
|
CAMERA_ROTATION__270 = 270
|
||||||
ALL_CAMERA_ROTATIONS = [
|
ALL_CAMERA_ROTATIONS = [
|
||||||
(CAMERA_ROTATION__0, _("0°")),
|
(CAMERA_ROTATION__0, _mft("0°")),
|
||||||
(CAMERA_ROTATION__90, _("90°")),
|
(CAMERA_ROTATION__90, _mft("90°")),
|
||||||
(CAMERA_ROTATION__180, _("180°")),
|
(CAMERA_ROTATION__180, _mft("180°")),
|
||||||
(CAMERA_ROTATION__270, _("270°")),
|
(CAMERA_ROTATION__270, _mft("270°")),
|
||||||
]
|
]
|
||||||
|
|
||||||
# QR code constants
|
# QR code constants
|
||||||
@@ -99,11 +99,11 @@ class SettingsConstants:
|
|||||||
DENSITY__MEDIUM = "M"
|
DENSITY__MEDIUM = "M"
|
||||||
DENSITY__HIGH = "H"
|
DENSITY__HIGH = "H"
|
||||||
# TRANSLATOR_NOTE: QR code density option: Low, Medium, High
|
# TRANSLATOR_NOTE: QR code density option: Low, Medium, High
|
||||||
density_low = _("Low")
|
density_low = _mft("Low")
|
||||||
# TRANSLATOR_NOTE: QR code density option: Low, Medium, High
|
# TRANSLATOR_NOTE: QR code density option: Low, Medium, High
|
||||||
density_medium = _("Medium")
|
density_medium = _mft("Medium")
|
||||||
# TRANSLATOR_NOTE: QR code density option: Low, Medium, High
|
# TRANSLATOR_NOTE: QR code density option: Low, Medium, High
|
||||||
density_high = _("High")
|
density_high = _mft("High")
|
||||||
ALL_DENSITIES = [
|
ALL_DENSITIES = [
|
||||||
(DENSITY__LOW, density_low),
|
(DENSITY__LOW, density_low),
|
||||||
(DENSITY__MEDIUM, density_medium),
|
(DENSITY__MEDIUM, density_medium),
|
||||||
@@ -115,9 +115,9 @@ class SettingsConstants:
|
|||||||
TESTNET = "T"
|
TESTNET = "T"
|
||||||
REGTEST = "R"
|
REGTEST = "R"
|
||||||
ALL_NETWORKS = [
|
ALL_NETWORKS = [
|
||||||
(MAINNET, _("Mainnet")),
|
(MAINNET, _mft("Mainnet")),
|
||||||
(TESTNET, _("Testnet")),
|
(TESTNET, _mft("Testnet")),
|
||||||
(REGTEST, _("Regtest"))
|
(REGTEST, _mft("Regtest"))
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -130,14 +130,14 @@ class SettingsConstants:
|
|||||||
if network == SettingsConstants.REGTEST:
|
if network == SettingsConstants.REGTEST:
|
||||||
return "regtest"
|
return "regtest"
|
||||||
|
|
||||||
PERSISTENT_SETTINGS__SD_INSERTED__HELP_TEXT = _("Store Settings on SD card")
|
PERSISTENT_SETTINGS__SD_INSERTED__HELP_TEXT = _mft("Store Settings on SD card")
|
||||||
PERSISTENT_SETTINGS__SD_REMOVED__HELP_TEXT = _("Insert SD card to enable")
|
PERSISTENT_SETTINGS__SD_REMOVED__HELP_TEXT = _mft("Insert SD card to enable")
|
||||||
|
|
||||||
SINGLE_SIG = "ss"
|
SINGLE_SIG = "ss"
|
||||||
MULTISIG = "ms"
|
MULTISIG = "ms"
|
||||||
ALL_SIG_TYPES = [
|
ALL_SIG_TYPES = [
|
||||||
(SINGLE_SIG, _("Single Sig")),
|
(SINGLE_SIG, _mft("Single Sig")),
|
||||||
(MULTISIG, _("Multisig")),
|
(MULTISIG, _mft("Multisig")),
|
||||||
]
|
]
|
||||||
|
|
||||||
LEGACY_P2PKH = "leg"
|
LEGACY_P2PKH = "leg"
|
||||||
@@ -146,11 +146,11 @@ class SettingsConstants:
|
|||||||
TAPROOT = "tr"
|
TAPROOT = "tr"
|
||||||
CUSTOM_DERIVATION = "cus"
|
CUSTOM_DERIVATION = "cus"
|
||||||
ALL_SCRIPT_TYPES = [
|
ALL_SCRIPT_TYPES = [
|
||||||
(NATIVE_SEGWIT, _("Native Segwit")),
|
(NATIVE_SEGWIT, _mft("Native Segwit")),
|
||||||
(NESTED_SEGWIT, _("Nested Segwit")),
|
(NESTED_SEGWIT, _mft("Nested Segwit")),
|
||||||
(LEGACY_P2PKH, _("Legacy")),
|
(LEGACY_P2PKH, _mft("Legacy")),
|
||||||
(TAPROOT, _("Taproot")),
|
(TAPROOT, _mft("Taproot")),
|
||||||
(CUSTOM_DERIVATION, _("Custom Derivation")),
|
(CUSTOM_DERIVATION, _mft("Custom Derivation")),
|
||||||
]
|
]
|
||||||
|
|
||||||
WORDLIST_LANGUAGE__ENGLISH = "en"
|
WORDLIST_LANGUAGE__ENGLISH = "en"
|
||||||
@@ -237,9 +237,9 @@ class SettingsConstants:
|
|||||||
ELECTRUM_PBKDF2_ROUNDS=2048
|
ELECTRUM_PBKDF2_ROUNDS=2048
|
||||||
|
|
||||||
# Label strings
|
# Label strings
|
||||||
LABEL__BIP39_PASSPHRASE = _("BIP-39 Passphrase")
|
LABEL__BIP39_PASSPHRASE = _mft("BIP-39 Passphrase")
|
||||||
# TRANSLATOR_NOTE: Terminology used by Electrum seeds; equivalent to bip39 passphrase
|
# TRANSLATOR_NOTE: Terminology used by Electrum seeds; equivalent to bip39 passphrase
|
||||||
custom_extension = _("Custom Extension")
|
custom_extension = _mft("Custom Extension")
|
||||||
LABEL__CUSTOM_EXTENSION = custom_extension
|
LABEL__CUSTOM_EXTENSION = custom_extension
|
||||||
|
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ class SettingsEntry:
|
|||||||
option_value = option
|
option_value = option
|
||||||
display_name = option
|
display_name = option
|
||||||
if option_value == value:
|
if option_value == value:
|
||||||
return _(display_name)
|
return _mft(display_name)
|
||||||
|
|
||||||
|
|
||||||
def get_selection_option_value_by_display_name(self, display_name: str):
|
def get_selection_option_value_by_display_name(self, display_name: str):
|
||||||
@@ -380,7 +380,7 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
||||||
attr_name=SettingsConstants.SETTING__LOCALE,
|
attr_name=SettingsConstants.SETTING__LOCALE,
|
||||||
abbreviated_name="lang",
|
abbreviated_name="lang",
|
||||||
display_name=_("Language"),
|
display_name=_mft("Language"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
selection_options=SettingsConstants.ALL_LOCALES,
|
selection_options=SettingsConstants.ALL_LOCALES,
|
||||||
default_value=SettingsConstants.LOCALE__ENGLISH),
|
default_value=SettingsConstants.LOCALE__ENGLISH),
|
||||||
@@ -389,7 +389,7 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
||||||
attr_name=SettingsConstants.SETTING__WORDLIST_LANGUAGE,
|
attr_name=SettingsConstants.SETTING__WORDLIST_LANGUAGE,
|
||||||
abbreviated_name="wordlist_lang",
|
abbreviated_name="wordlist_lang",
|
||||||
display_name=_("Mnemonic language"),
|
display_name=_mft("Mnemonic language"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
visibility=SettingsConstants.VISIBILITY__HIDDEN,
|
visibility=SettingsConstants.VISIBILITY__HIDDEN,
|
||||||
selection_options=SettingsConstants.ALL_WORDLIST_LANGUAGES,
|
selection_options=SettingsConstants.ALL_WORDLIST_LANGUAGES,
|
||||||
@@ -398,14 +398,14 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
||||||
attr_name=SettingsConstants.SETTING__PERSISTENT_SETTINGS,
|
attr_name=SettingsConstants.SETTING__PERSISTENT_SETTINGS,
|
||||||
abbreviated_name="persistent",
|
abbreviated_name="persistent",
|
||||||
display_name=_("Persistent settings"),
|
display_name=_mft("Persistent settings"),
|
||||||
help_text=SettingsConstants.PERSISTENT_SETTINGS__SD_INSERTED__HELP_TEXT,
|
help_text=SettingsConstants.PERSISTENT_SETTINGS__SD_INSERTED__HELP_TEXT,
|
||||||
default_value=SettingsConstants.OPTION__DISABLED),
|
default_value=SettingsConstants.OPTION__DISABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__WALLET,
|
SettingsEntry(category=SettingsConstants.CATEGORY__WALLET,
|
||||||
attr_name=SettingsConstants.SETTING__COORDINATORS,
|
attr_name=SettingsConstants.SETTING__COORDINATORS,
|
||||||
abbreviated_name="coords",
|
abbreviated_name="coords",
|
||||||
display_name=_("Coordinator software"),
|
display_name=_mft("Coordinator software"),
|
||||||
type=SettingsConstants.TYPE__MULTISELECT,
|
type=SettingsConstants.TYPE__MULTISELECT,
|
||||||
selection_options=SettingsConstants.ALL_COORDINATORS,
|
selection_options=SettingsConstants.ALL_COORDINATORS,
|
||||||
default_value=[
|
default_value=[
|
||||||
@@ -418,7 +418,7 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
||||||
attr_name=SettingsConstants.SETTING__BTC_DENOMINATION,
|
attr_name=SettingsConstants.SETTING__BTC_DENOMINATION,
|
||||||
abbreviated_name="denom",
|
abbreviated_name="denom",
|
||||||
display_name=_("Denomination display"),
|
display_name=_mft("Denomination display"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
selection_options=SettingsConstants.ALL_BTC_DENOMINATIONS,
|
selection_options=SettingsConstants.ALL_BTC_DENOMINATIONS,
|
||||||
default_value=SettingsConstants.BTC_DENOMINATION__THRESHOLD),
|
default_value=SettingsConstants.BTC_DENOMINATION__THRESHOLD),
|
||||||
@@ -427,7 +427,7 @@ class SettingsDefinition:
|
|||||||
# Advanced options
|
# Advanced options
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__NETWORK,
|
attr_name=SettingsConstants.SETTING__NETWORK,
|
||||||
display_name=_("Bitcoin network"),
|
display_name=_mft("Bitcoin network"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
selection_options=SettingsConstants.ALL_NETWORKS,
|
selection_options=SettingsConstants.ALL_NETWORKS,
|
||||||
@@ -435,7 +435,7 @@ class SettingsDefinition:
|
|||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__QR_DENSITY,
|
attr_name=SettingsConstants.SETTING__QR_DENSITY,
|
||||||
display_name=_("QR code density"),
|
display_name=_mft("QR code density"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
selection_options=SettingsConstants.ALL_DENSITIES,
|
selection_options=SettingsConstants.ALL_DENSITIES,
|
||||||
@@ -443,14 +443,14 @@ class SettingsDefinition:
|
|||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__XPUB_EXPORT,
|
attr_name=SettingsConstants.SETTING__XPUB_EXPORT,
|
||||||
display_name=_("Xpub export"),
|
display_name=_mft("Xpub export"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__SIG_TYPES,
|
attr_name=SettingsConstants.SETTING__SIG_TYPES,
|
||||||
abbreviated_name="sigs",
|
abbreviated_name="sigs",
|
||||||
display_name=_("Sig types"),
|
display_name=_mft("Sig types"),
|
||||||
type=SettingsConstants.TYPE__MULTISELECT,
|
type=SettingsConstants.TYPE__MULTISELECT,
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
selection_options=SettingsConstants.ALL_SIG_TYPES,
|
selection_options=SettingsConstants.ALL_SIG_TYPES,
|
||||||
@@ -459,7 +459,7 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__SCRIPT_TYPES,
|
attr_name=SettingsConstants.SETTING__SCRIPT_TYPES,
|
||||||
abbreviated_name="scripts",
|
abbreviated_name="scripts",
|
||||||
display_name=_("Script types"),
|
display_name=_mft("Script types"),
|
||||||
type=SettingsConstants.TYPE__MULTISELECT,
|
type=SettingsConstants.TYPE__MULTISELECT,
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
selection_options=SettingsConstants.ALL_SCRIPT_TYPES,
|
selection_options=SettingsConstants.ALL_SCRIPT_TYPES,
|
||||||
@@ -467,13 +467,13 @@ class SettingsDefinition:
|
|||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__XPUB_DETAILS,
|
attr_name=SettingsConstants.SETTING__XPUB_DETAILS,
|
||||||
display_name=_("Show xpub details"),
|
display_name=_mft("Show xpub details"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__PASSPHRASE,
|
attr_name=SettingsConstants.SETTING__PASSPHRASE,
|
||||||
display_name=_("BIP-39 passphrase"),
|
display_name=_mft("BIP-39 passphrase"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
selection_options=SettingsConstants.OPTIONS__ENABLED_DISABLED_REQUIRED,
|
selection_options=SettingsConstants.OPTIONS__ENABLED_DISABLED_REQUIRED,
|
||||||
@@ -482,7 +482,7 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__CAMERA_ROTATION,
|
attr_name=SettingsConstants.SETTING__CAMERA_ROTATION,
|
||||||
abbreviated_name="camera",
|
abbreviated_name="camera",
|
||||||
display_name=_("Camera rotation"),
|
display_name=_mft("Camera rotation"),
|
||||||
type=SettingsConstants.TYPE__SELECT_1,
|
type=SettingsConstants.TYPE__SELECT_1,
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
selection_options=SettingsConstants.ALL_CAMERA_ROTATIONS,
|
selection_options=SettingsConstants.ALL_CAMERA_ROTATIONS,
|
||||||
@@ -490,14 +490,14 @@ class SettingsDefinition:
|
|||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__COMPACT_SEEDQR,
|
attr_name=SettingsConstants.SETTING__COMPACT_SEEDQR,
|
||||||
display_name=_("Compact SeedQR"),
|
display_name=_mft("Compact SeedQR"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__BIP85_CHILD_SEEDS,
|
attr_name=SettingsConstants.SETTING__BIP85_CHILD_SEEDS,
|
||||||
abbreviated_name="bip85",
|
abbreviated_name="bip85",
|
||||||
display_name=_("BIP-85 child seeds"),
|
display_name=_mft("BIP-85 child seeds"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__DISABLED),
|
default_value=SettingsConstants.OPTION__DISABLED),
|
||||||
|
|
||||||
@@ -505,40 +505,40 @@ class SettingsDefinition:
|
|||||||
attr_name=SettingsConstants.SETTING__ELECTRUM_SEEDS,
|
attr_name=SettingsConstants.SETTING__ELECTRUM_SEEDS,
|
||||||
abbreviated_name="electrum",
|
abbreviated_name="electrum",
|
||||||
display_name="Electrum seeds",
|
display_name="Electrum seeds",
|
||||||
help_text=_("Native Segwit only"),
|
help_text=_mft("Native Segwit only"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__DISABLED),
|
default_value=SettingsConstants.OPTION__DISABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__MESSAGE_SIGNING,
|
attr_name=SettingsConstants.SETTING__MESSAGE_SIGNING,
|
||||||
display_name=_("Message signing"),
|
display_name=_mft("Message signing"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__DISABLED),
|
default_value=SettingsConstants.OPTION__DISABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__PRIVACY_WARNINGS,
|
attr_name=SettingsConstants.SETTING__PRIVACY_WARNINGS,
|
||||||
abbreviated_name="priv_warn",
|
abbreviated_name="priv_warn",
|
||||||
display_name=_("Show privacy warnings"),
|
display_name=_mft("Show privacy warnings"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__DIRE_WARNINGS,
|
attr_name=SettingsConstants.SETTING__DIRE_WARNINGS,
|
||||||
abbreviated_name="dire_warn",
|
abbreviated_name="dire_warn",
|
||||||
display_name=_("Show dire warnings"),
|
display_name=_mft("Show dire warnings"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__QR_BRIGHTNESS_TIPS,
|
attr_name=SettingsConstants.SETTING__QR_BRIGHTNESS_TIPS,
|
||||||
display_name=_("Show QR brightness tips"),
|
display_name=_mft("Show QR brightness tips"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
SettingsEntry(category=SettingsConstants.CATEGORY__FEATURES,
|
||||||
attr_name=SettingsConstants.SETTING__PARTNER_LOGOS,
|
attr_name=SettingsConstants.SETTING__PARTNER_LOGOS,
|
||||||
abbreviated_name="partners",
|
abbreviated_name="partners",
|
||||||
display_name=_("Show partner logos"),
|
display_name=_mft("Show partner logos"),
|
||||||
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
visibility=SettingsConstants.VISIBILITY__ADVANCED,
|
||||||
default_value=SettingsConstants.OPTION__ENABLED),
|
default_value=SettingsConstants.OPTION__ENABLED),
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ class SettingsDefinition:
|
|||||||
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
SettingsEntry(category=SettingsConstants.CATEGORY__SYSTEM,
|
||||||
attr_name=SettingsConstants.SETTING__QR_BRIGHTNESS,
|
attr_name=SettingsConstants.SETTING__QR_BRIGHTNESS,
|
||||||
abbreviated_name="qr_brightness",
|
abbreviated_name="qr_brightness",
|
||||||
display_name=_("QR background color"),
|
display_name=_mft("QR background color"),
|
||||||
type=SettingsConstants.TYPE__FREE_ENTRY,
|
type=SettingsConstants.TYPE__FREE_ENTRY,
|
||||||
visibility=SettingsConstants.VISIBILITY__HIDDEN,
|
visibility=SettingsConstants.VISIBILITY__HIDDEN,
|
||||||
default_value=62),
|
default_value=62),
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ from gettext import gettext as _
|
|||||||
from seedsigner.models.psbt_parser import PSBTParser
|
from seedsigner.models.psbt_parser import PSBTParser
|
||||||
from seedsigner.models.settings import SettingsConstants
|
from seedsigner.models.settings import SettingsConstants
|
||||||
from seedsigner.gui.components import FontAwesomeIconConstants, SeedSignerIconConstants
|
from seedsigner.gui.components import FontAwesomeIconConstants, SeedSignerIconConstants
|
||||||
from seedsigner.gui.screens.screen import (RET_CODE__BACK_BUTTON, ButtonListScreen, WarningScreen, DireWarningScreen, QRDisplayScreen)
|
from seedsigner.gui.screens.screen import (RET_CODE__BACK_BUTTON, ButtonListScreen, ButtonOption, WarningScreen, DireWarningScreen, QRDisplayScreen)
|
||||||
from seedsigner.views.view import BackStackView, MainMenuView, NotYetImplementedView, View, Destination
|
from seedsigner.views.view import BackStackView, MainMenuView, NotYetImplementedView, View, Destination
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PSBTSelectSeedView(View):
|
class PSBTSelectSeedView(View):
|
||||||
SCAN_SEED = (_("Scan a seed"), SeedSignerIconConstants.QRCODE)
|
SCAN_SEED = ButtonOption("Scan a seed", SeedSignerIconConstants.QRCODE)
|
||||||
TYPE_12WORD = (_("Enter 12-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_12WORD = ButtonOption("Enter 12-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
TYPE_24WORD = (_("Enter 24-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_24WORD = ButtonOption("Enter 24-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
TYPE_ELECTRUM = (_("Enter Electrum seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_ELECTRUM = ButtonOption("Enter Electrum seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -38,7 +38,7 @@ class PSBTSelectSeedView(View):
|
|||||||
# TRANSLATOR_NOTE: Inserts fingerprint w/"?" to indicate that this seed can't sign the current PSBT
|
# TRANSLATOR_NOTE: Inserts fingerprint w/"?" to indicate that this seed can't sign the current PSBT
|
||||||
button_str = _("{} (?)").format(button_str)
|
button_str = _("{} (?)").format(button_str)
|
||||||
|
|
||||||
button_data.append((button_str, SeedSignerIconConstants.FINGERPRINT))
|
button_data.append(ButtonOption(button_str, SeedSignerIconConstants.FINGERPRINT))
|
||||||
|
|
||||||
button_data.append(self.SCAN_SEED)
|
button_data.append(self.SCAN_SEED)
|
||||||
button_data.append(self.TYPE_12WORD)
|
button_data.append(self.TYPE_12WORD)
|
||||||
@@ -169,7 +169,7 @@ class PSBTUnsupportedScriptTypeWarningView(View):
|
|||||||
selected_menu_num = WarningScreen(
|
selected_menu_num = WarningScreen(
|
||||||
status_headline=_("Unsupported Script Type!"),
|
status_headline=_("Unsupported Script Type!"),
|
||||||
text=_("PSBT has unsupported input script type, please verify your change addresses."),
|
text=_("PSBT has unsupported input script type, please verify your change addresses."),
|
||||||
button_data=[_("Continue")],
|
button_data=[ButtonOption("Continue")],
|
||||||
).display()
|
).display()
|
||||||
|
|
||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
@@ -190,7 +190,7 @@ class PSBTNoChangeWarningView(View):
|
|||||||
# TRANSLATOR_NOTE: User will receive no change back; the inputs to this transaction are fully spent
|
# TRANSLATOR_NOTE: User will receive no change back; the inputs to this transaction are fully spent
|
||||||
status_headline=_("Full Spend!"),
|
status_headline=_("Full Spend!"),
|
||||||
text=_("This PSBT spends its entire input value. No change is coming back to your wallet."),
|
text=_("This PSBT spends its entire input value. No change is coming back to your wallet."),
|
||||||
button_data=[_("Continue")],
|
button_data=[ButtonOption("Continue")],
|
||||||
).display()
|
).display()
|
||||||
|
|
||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
@@ -265,10 +265,10 @@ class PSBTAddressDetailsView(View):
|
|||||||
|
|
||||||
button_data = []
|
button_data = []
|
||||||
if self.address_num < psbt_parser.num_destinations - 1:
|
if self.address_num < psbt_parser.num_destinations - 1:
|
||||||
button_data.append(_("Next Recipient"))
|
button_data.append(ButtonOption("Next Recipient"))
|
||||||
else:
|
else:
|
||||||
# TRANSLATOR_NOTE: Short for "Next step"
|
# TRANSLATOR_NOTE: Short for "Next step"
|
||||||
button_data.append(_("Next"))
|
button_data.append(ButtonOption("Next"))
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
PSBTAddressDetailsScreen,
|
PSBTAddressDetailsScreen,
|
||||||
@@ -299,10 +299,9 @@ class PSBTAddressDetailsView(View):
|
|||||||
|
|
||||||
|
|
||||||
class PSBTChangeDetailsView(View):
|
class PSBTChangeDetailsView(View):
|
||||||
NEXT = _("Next")
|
NEXT = ButtonOption("Next")
|
||||||
SKIP_VERIFICATION = _("Skip Verification")
|
SKIP_VERIFICATION = ButtonOption("Skip Verification")
|
||||||
VERIFY_MULTISIG = _("Verify Multisig Change")
|
VERIFY_MULTISIG = ButtonOption("Verify Multisig Change")
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, change_address_num):
|
def __init__(self, change_address_num):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -349,7 +348,7 @@ class PSBTChangeDetailsView(View):
|
|||||||
title = _("Your Change")
|
title = _("Your Change")
|
||||||
else:
|
else:
|
||||||
title = _("Self-Transfer")
|
title = _("Self-Transfer")
|
||||||
self.VERIFY_MULTISIG = _("Verify Multisig Addr")
|
self.VERIFY_MULTISIG.button_label = _("Verify Multisig Addr")
|
||||||
# if psbt_parser.num_change_outputs > 1:
|
# if psbt_parser.num_change_outputs > 1:
|
||||||
# title += f" (#{self.change_address_num + 1})"
|
# title += f" (#{self.change_address_num + 1})"
|
||||||
|
|
||||||
@@ -473,7 +472,7 @@ class PSBTAddressVerificationFailedView(View):
|
|||||||
title=title,
|
title=title,
|
||||||
status_headline=_("Address Verification Failed"),
|
status_headline=_("Address Verification Failed"),
|
||||||
text=text,
|
text=text,
|
||||||
button_data=[_("Discard PSBT")],
|
button_data=[ButtonOption("Discard PSBT")],
|
||||||
show_back_button=False,
|
show_back_button=False,
|
||||||
).display()
|
).display()
|
||||||
|
|
||||||
@@ -495,8 +494,8 @@ class PSBTOpReturnView(View):
|
|||||||
# Should not be able to get here
|
# Should not be able to get here
|
||||||
raise Exception("Routing error")
|
raise Exception("Routing error")
|
||||||
|
|
||||||
title = "OP_RETURN"
|
title = _("OP_RETURN")
|
||||||
button_data = ["Next"]
|
button_data = [ButtonOption("Next")]
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
PSBTOpReturnScreen,
|
PSBTOpReturnScreen,
|
||||||
@@ -515,7 +514,7 @@ class PSBTOpReturnView(View):
|
|||||||
class PSBTFinalizeView(View):
|
class PSBTFinalizeView(View):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
APPROVE_PSBT = "Approve PSBT"
|
APPROVE_PSBT = ButtonOption("Approve PSBT")
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -524,7 +523,6 @@ class PSBTFinalizeView(View):
|
|||||||
|
|
||||||
psbt_parser: PSBTParser = self.controller.psbt_parser
|
psbt_parser: PSBTParser = self.controller.psbt_parser
|
||||||
psbt: PSBT = self.controller.psbt
|
psbt: PSBT = self.controller.psbt
|
||||||
self.APPROVE_PSBT = _("Approve PSBT")
|
|
||||||
|
|
||||||
if not psbt_parser:
|
if not psbt_parser:
|
||||||
# Should not be able to get here
|
# Should not be able to get here
|
||||||
@@ -573,7 +571,7 @@ class PSBTSignedQRDisplayView(View):
|
|||||||
|
|
||||||
|
|
||||||
class PSBTSigningErrorView(View):
|
class PSBTSigningErrorView(View):
|
||||||
SELECT_DIFF_SEED = _("Select Diff Seed")
|
SELECT_DIFF_SEED = ButtonOption("Select Diff Seed")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
psbt_parser: PSBTParser = self.controller.psbt_parser
|
psbt_parser: PSBTParser = self.controller.psbt_parser
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
from seedsigner.helpers.l10n import mark_for_translation as _mft
|
||||||
from seedsigner.models.settings import SettingsConstants
|
from seedsigner.models.settings import SettingsConstants
|
||||||
from seedsigner.views.view import BackStackView, ErrorView, MainMenuView, NotYetImplementedView, View, Destination
|
from seedsigner.views.view import BackStackView, ErrorView, MainMenuView, NotYetImplementedView, View, Destination
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ class ScanView(View):
|
|||||||
dedicated errors when an unexpected QR type is scanned (e.g. Scan PSBT was
|
dedicated errors when an unexpected QR type is scanned (e.g. Scan PSBT was
|
||||||
selected but a SeedQR was scanned).
|
selected but a SeedQR was scanned).
|
||||||
"""
|
"""
|
||||||
instructions_text = _("Scan a QR code")
|
instructions_text = _mft("Scan a QR code")
|
||||||
invalid_qr_type_message = _("QRCode not recognized or not yet supported.")
|
invalid_qr_type_message = _mft("QRCode not recognized or not yet supported.")
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -176,8 +176,8 @@ class ScanView(View):
|
|||||||
|
|
||||||
|
|
||||||
class ScanPSBTView(ScanView):
|
class ScanPSBTView(ScanView):
|
||||||
instructions_text = _("Scan PSBT")
|
instructions_text = _mft("Scan PSBT")
|
||||||
invalid_qr_type_message = _("Expected a PSBT")
|
invalid_qr_type_message = _mft("Expected a PSBT")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid_qr_type(self):
|
def is_valid_qr_type(self):
|
||||||
@@ -186,8 +186,8 @@ class ScanPSBTView(ScanView):
|
|||||||
|
|
||||||
|
|
||||||
class ScanSeedQRView(ScanView):
|
class ScanSeedQRView(ScanView):
|
||||||
instructions_text = _("Scan SeedQR")
|
instructions_text = _mft("Scan SeedQR")
|
||||||
invalid_qr_type_message = _("Expected a SeedQR")
|
invalid_qr_type_message = _mft("Expected a SeedQR")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid_qr_type(self):
|
def is_valid_qr_type(self):
|
||||||
@@ -196,8 +196,8 @@ class ScanSeedQRView(ScanView):
|
|||||||
|
|
||||||
|
|
||||||
class ScanWalletDescriptorView(ScanView):
|
class ScanWalletDescriptorView(ScanView):
|
||||||
instructions_text = _("Scan descriptor")
|
instructions_text = _mft("Scan descriptor")
|
||||||
invalid_qr_type_message = _("Expected a wallet descriptor QR")
|
invalid_qr_type_message = _mft("Expected a wallet descriptor QR")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid_qr_type(self):
|
def is_valid_qr_type(self):
|
||||||
@@ -206,8 +206,8 @@ class ScanWalletDescriptorView(ScanView):
|
|||||||
|
|
||||||
|
|
||||||
class ScanAddressView(ScanView):
|
class ScanAddressView(ScanView):
|
||||||
instructions_text = _("Scan address QR")
|
instructions_text = _mft("Scan address QR")
|
||||||
invalid_qr_type_message = _("Expected an address QR")
|
invalid_qr_type_message = _mft("Expected an address QR")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid_qr_type(self):
|
def is_valid_qr_type(self):
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from embit.descriptor import Descriptor
|
|||||||
from seedsigner.gui.components import FontAwesomeIconConstants, SeedSignerIconConstants
|
from seedsigner.gui.components import FontAwesomeIconConstants, SeedSignerIconConstants
|
||||||
from seedsigner.gui.screens import (RET_CODE__BACK_BUTTON, ButtonListScreen,
|
from seedsigner.gui.screens import (RET_CODE__BACK_BUTTON, ButtonListScreen,
|
||||||
WarningScreen, DireWarningScreen, seed_screens)
|
WarningScreen, DireWarningScreen, seed_screens)
|
||||||
|
from seedsigner.gui.screens.screen import ButtonOption
|
||||||
from seedsigner.models.encode_qr import CompactSeedQrEncoder, GenericStaticQrEncoder, SeedQrEncoder, SpecterXPubQrEncoder, StaticXpubQrEncoder, UrXpubQrEncoder
|
from seedsigner.models.encode_qr import CompactSeedQrEncoder, GenericStaticQrEncoder, SeedQrEncoder, SpecterXPubQrEncoder, StaticXpubQrEncoder, UrXpubQrEncoder
|
||||||
from seedsigner.models.qr_type import QRType
|
from seedsigner.models.qr_type import QRType
|
||||||
from seedsigner.models.seed import Seed
|
from seedsigner.models.seed import Seed
|
||||||
@@ -23,7 +24,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class SeedsMenuView(View):
|
class SeedsMenuView(View):
|
||||||
LOAD = "Load a seed"
|
LOAD = ButtonOption("Load a seed")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -41,8 +42,8 @@ class SeedsMenuView(View):
|
|||||||
|
|
||||||
button_data = []
|
button_data = []
|
||||||
for seed in self.seeds:
|
for seed in self.seeds:
|
||||||
button_data.append((seed["fingerprint"], SeedSignerIconConstants.FINGERPRINT))
|
button_data.append(ButtonOption(seed["fingerprint"], SeedSignerIconConstants.FINGERPRINT))
|
||||||
button_data.append(_("Load a seed"))
|
button_data.append(self.LOAD)
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
ButtonListScreen,
|
ButtonListScreen,
|
||||||
@@ -54,7 +55,7 @@ class SeedsMenuView(View):
|
|||||||
if len(self.seeds) > 0 and selected_menu_num < len(self.seeds):
|
if len(self.seeds) > 0 and selected_menu_num < len(self.seeds):
|
||||||
return Destination(SeedOptionsView, view_args={"seed_num": selected_menu_num})
|
return Destination(SeedOptionsView, view_args={"seed_num": selected_menu_num})
|
||||||
|
|
||||||
elif selected_menu_num == len(self.seeds):
|
elif button_data[selected_menu_num] == self.LOAD:
|
||||||
return Destination(LoadSeedView)
|
return Destination(LoadSeedView)
|
||||||
|
|
||||||
elif selected_menu_num == RET_CODE__BACK_BUTTON:
|
elif selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
@@ -70,10 +71,10 @@ class SeedSelectSeedView(View):
|
|||||||
* `flow`: indicates which user flow is in progress during seed selection (e.g.
|
* `flow`: indicates which user flow is in progress during seed selection (e.g.
|
||||||
verify single sig addr or sign message).
|
verify single sig addr or sign message).
|
||||||
"""
|
"""
|
||||||
SCAN_SEED = (_("Scan a seed"), SeedSignerIconConstants.QRCODE)
|
SCAN_SEED = ButtonOption("Scan a seed", SeedSignerIconConstants.QRCODE)
|
||||||
TYPE_12WORD = (_("Enter 12-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_12WORD = ButtonOption("Enter 12-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
TYPE_24WORD = (_("Enter 24-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_24WORD = ButtonOption("Enter 24-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
TYPE_ELECTRUM = (_("Enter Electrum seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_ELECTRUM = ButtonOption("Enter Electrum seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, flow: str = None):
|
def __init__(self, flow: str = None):
|
||||||
@@ -108,11 +109,7 @@ class SeedSelectSeedView(View):
|
|||||||
button_data = []
|
button_data = []
|
||||||
for seed in seeds:
|
for seed in seeds:
|
||||||
button_str = seed.get_fingerprint(self.settings.get_value(SettingsConstants.SETTING__NETWORK))
|
button_str = seed.get_fingerprint(self.settings.get_value(SettingsConstants.SETTING__NETWORK))
|
||||||
|
button_data.append(ButtonOption(button_str, SeedSignerIconConstants.FINGERPRINT, icon_color="blue"))
|
||||||
if seed.passphrase is not None:
|
|
||||||
# TODO: Include lock icon on right side of button
|
|
||||||
pass
|
|
||||||
button_data.append((button_str, SeedSignerIconConstants.FINGERPRINT, "blue"))
|
|
||||||
|
|
||||||
button_data.append(self.SCAN_SEED)
|
button_data.append(self.SCAN_SEED)
|
||||||
button_data.append(self.TYPE_12WORD)
|
button_data.append(self.TYPE_12WORD)
|
||||||
@@ -165,11 +162,11 @@ class SeedSelectSeedView(View):
|
|||||||
Loading seeds, passphrases, etc
|
Loading seeds, passphrases, etc
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class LoadSeedView(View):
|
class LoadSeedView(View):
|
||||||
SEED_QR = (_("Scan a SeedQR"), SeedSignerIconConstants.QRCODE)
|
SEED_QR = ButtonOption("Scan a SeedQR", SeedSignerIconConstants.QRCODE)
|
||||||
TYPE_12WORD = (_("Enter 12-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_12WORD = ButtonOption("Enter 12-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
TYPE_24WORD = (_("Enter 24-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_24WORD = ButtonOption("Enter 24-word seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
TYPE_ELECTRUM = (_("Enter Electrum seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_ELECTRUM = ButtonOption("Enter Electrum seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
CREATE = (_(" Create a seed"), SeedSignerIconConstants.PLUS)
|
CREATE = ButtonOption(" Create a seed", SeedSignerIconConstants.PLUS)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [
|
button_data = [
|
||||||
@@ -274,8 +271,8 @@ class SeedMnemonicEntryView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedMnemonicInvalidView(View):
|
class SeedMnemonicInvalidView(View):
|
||||||
EDIT = _("Review & Edit")
|
EDIT = ButtonOption("Review & Edit")
|
||||||
DISCARD = (_("Discard"), None, None, "red")
|
DISCARD = ButtonOption("Discard", button_label_color="red")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -303,8 +300,8 @@ class SeedMnemonicInvalidView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedFinalizeView(View):
|
class SeedFinalizeView(View):
|
||||||
FINALIZE = _("Done")
|
FINALIZE = ButtonOption("Done")
|
||||||
PASSPHRASE = _("BIP-39 Passphrase")
|
PASSPHRASE = ButtonOption("BIP-39 Passphrase")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -327,9 +324,9 @@ class SeedFinalizeView(View):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.FINALIZE]
|
button_data = [self.FINALIZE]
|
||||||
passphrase_button = self.seed.passphrase_label
|
self.PASSPHRASE.button_label = self.seed.passphrase_label
|
||||||
if self.settings.get_value(SettingsConstants.SETTING__PASSPHRASE) != SettingsConstants.OPTION__DISABLED:
|
if self.settings.get_value(SettingsConstants.SETTING__PASSPHRASE) != SettingsConstants.OPTION__DISABLED:
|
||||||
button_data.append(passphrase_button)
|
button_data.append(self.PASSPHRASE)
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
seed_screens.SeedFinalizeScreen,
|
seed_screens.SeedFinalizeScreen,
|
||||||
@@ -341,7 +338,7 @@ class SeedFinalizeView(View):
|
|||||||
seed_num = self.controller.storage.finalize_pending_seed()
|
seed_num = self.controller.storage.finalize_pending_seed()
|
||||||
return Destination(SeedOptionsView, view_args={"seed_num": seed_num}, clear_history=True)
|
return Destination(SeedOptionsView, view_args={"seed_num": seed_num}, clear_history=True)
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == passphrase_button:
|
elif button_data[selected_menu_num] == self.PASSPHRASE:
|
||||||
return Destination(SeedAddPassphraseView)
|
return Destination(SeedAddPassphraseView)
|
||||||
|
|
||||||
elif selected_menu_num == RET_CODE__BACK_BUTTON:
|
elif selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
@@ -377,8 +374,8 @@ class SeedAddPassphraseView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedAddPassphraseExitDialogView(View):
|
class SeedAddPassphraseExitDialogView(View):
|
||||||
EDIT = _("Edit passphrase")
|
EDIT = ButtonOption("Edit passphrase")
|
||||||
DISCARD = (_("Discard passphrase"), None, None, "red")
|
DISCARD = ButtonOption("Discard passphrase", button_label_color="red")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -410,8 +407,8 @@ class SeedReviewPassphraseView(View):
|
|||||||
"""
|
"""
|
||||||
Display the completed passphrase back to the user.
|
Display the completed passphrase back to the user.
|
||||||
"""
|
"""
|
||||||
EDIT = _("Edit passphrase")
|
EDIT = ButtonOption("Edit passphrase")
|
||||||
DONE = _("Done")
|
DONE = ButtonOption("Done")
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -450,8 +447,8 @@ class SeedReviewPassphraseView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedDiscardView(View):
|
class SeedDiscardView(View):
|
||||||
KEEP = _("Keep Seed")
|
KEEP = ButtonOption("Keep Seed")
|
||||||
DISCARD = (_("Discard"), None, None, "red")
|
DISCARD = ButtonOption("Discard", button_label_color="red")
|
||||||
|
|
||||||
def __init__(self, seed_num: int = None):
|
def __init__(self, seed_num: int = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -518,14 +515,14 @@ class SeedElectrumMnemonicStartView(View):
|
|||||||
Views for actions on individual seeds:
|
Views for actions on individual seeds:
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class SeedOptionsView(View):
|
class SeedOptionsView(View):
|
||||||
SCAN_PSBT = (_("Scan PSBT"), SeedSignerIconConstants.QRCODE)
|
SCAN_PSBT = ButtonOption("Scan PSBT", SeedSignerIconConstants.QRCODE)
|
||||||
VERIFY_ADDRESS = _("Verify Addr")
|
VERIFY_ADDRESS = ButtonOption("Verify Addr")
|
||||||
EXPORT_XPUB = _("Export Xpub")
|
EXPORT_XPUB = ButtonOption("Export Xpub")
|
||||||
EXPLORER = _("Address Explorer")
|
EXPLORER = ButtonOption("Address Explorer")
|
||||||
SIGN_MESSAGE = _("Sign Message")
|
SIGN_MESSAGE = ButtonOption("Sign Message")
|
||||||
BACKUP = (_("Backup Seed"), None, None, None, SeedSignerIconConstants.CHEVRON_RIGHT)
|
BACKUP = ButtonOption("Backup Seed", right_icon_name=SeedSignerIconConstants.CHEVRON_RIGHT)
|
||||||
BIP85_CHILD_SEED = _("BIP-85 Child Seed")
|
BIP85_CHILD_SEED = ButtonOption("BIP-85 Child Seed")
|
||||||
DISCARD = (_("Discard Seed"), None, None, "red")
|
DISCARD = ButtonOption("Discard Seed", button_label_color="red")
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, seed_num: int):
|
def __init__(self, seed_num: int):
|
||||||
@@ -630,8 +627,8 @@ class SeedOptionsView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedBackupView(View):
|
class SeedBackupView(View):
|
||||||
VIEW_WORDS = _("View Seed Words")
|
VIEW_WORDS = ButtonOption("View Seed Words")
|
||||||
EXPORT_SEEDQR = _("Export as SeedQR")
|
EXPORT_SEEDQR = ButtonOption("Export as SeedQR")
|
||||||
|
|
||||||
def __init__(self, seed_num):
|
def __init__(self, seed_num):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -667,8 +664,8 @@ class SeedBackupView(View):
|
|||||||
Export Xpub flow
|
Export Xpub flow
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class SeedExportXpubSigTypeView(View):
|
class SeedExportXpubSigTypeView(View):
|
||||||
SINGLE_SIG = _("Single Sig")
|
SINGLE_SIG = ButtonOption("Single Sig", return_data=SettingsConstants.SINGLE_SIG)
|
||||||
MULTISIG = _("Multisig")
|
MULTISIG = ButtonOption("Multisig", return_data=SettingsConstants.MULTISIG)
|
||||||
|
|
||||||
def __init__(self, seed_num: int):
|
def __init__(self, seed_num: int):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -680,7 +677,7 @@ class SeedExportXpubSigTypeView(View):
|
|||||||
# Nothing to select; skip this screen
|
# Nothing to select; skip this screen
|
||||||
return Destination(SeedExportXpubScriptTypeView, view_args={"seed_num": self.seed_num, "sig_type": self.settings.get_value(SettingsConstants.SETTING__SIG_TYPES)[0]}, skip_current_view=True)
|
return Destination(SeedExportXpubScriptTypeView, view_args={"seed_num": self.seed_num, "sig_type": self.settings.get_value(SettingsConstants.SETTING__SIG_TYPES)[0]}, skip_current_view=True)
|
||||||
|
|
||||||
button_data=[self.SINGLE_SIG, self.MULTISIG]
|
button_data = [self.SINGLE_SIG, self.MULTISIG]
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
ButtonListScreen,
|
ButtonListScreen,
|
||||||
@@ -691,11 +688,7 @@ class SeedExportXpubSigTypeView(View):
|
|||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
return Destination(BackStackView)
|
return Destination(BackStackView)
|
||||||
|
|
||||||
if button_data[selected_menu_num] == self.SINGLE_SIG:
|
return Destination(SeedExportXpubScriptTypeView, view_args={"seed_num": self.seed_num, "sig_type": button_data[selected_menu_num].return_data})
|
||||||
return Destination(SeedExportXpubScriptTypeView, view_args={"seed_num": self.seed_num, "sig_type": SettingsConstants.SINGLE_SIG})
|
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == self.MULTISIG:
|
|
||||||
return Destination(SeedExportXpubScriptTypeView, view_args={"seed_num": self.seed_num, "sig_type": SettingsConstants.MULTISIG})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -737,13 +730,13 @@ class SeedExportXpubScriptTypeView(View):
|
|||||||
button_data = []
|
button_data = []
|
||||||
for script_type, display_name in SettingsConstants.ALL_SCRIPT_TYPES:
|
for script_type, display_name in SettingsConstants.ALL_SCRIPT_TYPES:
|
||||||
if script_type in self.settings.get_value(SettingsConstants.SETTING__SCRIPT_TYPES):
|
if script_type in self.settings.get_value(SettingsConstants.SETTING__SCRIPT_TYPES):
|
||||||
button_data.append((script_type, display_name))
|
button_data.append(ButtonOption(display_name, return_data=script_type))
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
ButtonListScreen,
|
ButtonListScreen,
|
||||||
title=title,
|
title=title,
|
||||||
is_button_text_centered=False,
|
is_button_text_centered=False,
|
||||||
button_data=[x[1] for x in button_data],
|
button_data=button_data,
|
||||||
is_bottom_list=True,
|
is_bottom_list=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -754,7 +747,7 @@ class SeedExportXpubScriptTypeView(View):
|
|||||||
return Destination(BackStackView)
|
return Destination(BackStackView)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
args["script_type"] = button_data[selected_menu_num][0]
|
args["script_type"] = button_data[selected_menu_num].return_data
|
||||||
|
|
||||||
if args["script_type"] == SettingsConstants.CUSTOM_DERIVATION:
|
if args["script_type"] == SettingsConstants.CUSTOM_DERIVATION:
|
||||||
return Destination(SeedExportXpubCustomDerivationView, view_args=args)
|
return Destination(SeedExportXpubCustomDerivationView, view_args=args)
|
||||||
@@ -826,7 +819,9 @@ class SeedExportXpubCoordinatorView(View):
|
|||||||
args["coordinator"] = self.settings.get_value(SettingsConstants.SETTING__COORDINATORS)[0]
|
args["coordinator"] = self.settings.get_value(SettingsConstants.SETTING__COORDINATORS)[0]
|
||||||
return Destination(SeedExportXpubWarningView, view_args=args, skip_current_view=True)
|
return Destination(SeedExportXpubWarningView, view_args=args, skip_current_view=True)
|
||||||
|
|
||||||
button_data = self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__COORDINATORS)
|
button_data = []
|
||||||
|
for display_name, setting_option in zip(self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__COORDINATORS), self.settings.get_value(SettingsConstants.SETTING__COORDINATORS)):
|
||||||
|
button_data.append(ButtonOption(display_name, return_data=setting_option))
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
ButtonListScreen,
|
ButtonListScreen,
|
||||||
@@ -838,9 +833,10 @@ class SeedExportXpubCoordinatorView(View):
|
|||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
return Destination(BackStackView)
|
return Destination(BackStackView)
|
||||||
|
|
||||||
coordinators_settings_entry = SettingsDefinition.get_settings_entry(SettingsConstants.SETTING__COORDINATORS)
|
# coordinators_settings_entry = SettingsDefinition.get_settings_entry(SettingsConstants.SETTING__COORDINATORS)
|
||||||
selected_display_name = button_data[selected_menu_num]
|
# selected_display_name = button_data[selected_menu_num]
|
||||||
args["coordinator"] = coordinators_settings_entry.get_selection_option_value_by_display_name(selected_display_name)
|
# args["coordinator"] = coordinators_settings_entry.get_selection_option_value_by_display_name(selected_display_name)
|
||||||
|
args["coordinator"] = button_data[selected_menu_num].return_data
|
||||||
|
|
||||||
return Destination(SeedExportXpubWarningView, view_args=args)
|
return Destination(SeedExportXpubWarningView, view_args=args)
|
||||||
|
|
||||||
@@ -1048,8 +1044,8 @@ class SeedWordsWarningView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedWordsView(View):
|
class SeedWordsView(View):
|
||||||
NEXT = _("Next")
|
NEXT = ButtonOption("Next")
|
||||||
DONE = _("Done")
|
DONE = ButtonOption("Done")
|
||||||
|
|
||||||
def __init__(self, seed_num: int, bip85_data: dict = None, page_index: int = 0):
|
def __init__(self, seed_num: int, bip85_data: dict = None, page_index: int = 0):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -1126,14 +1122,14 @@ class SeedBIP85ApplicationModeView(View):
|
|||||||
* XPRV (BIP32)
|
* XPRV (BIP32)
|
||||||
"""
|
"""
|
||||||
# TODO: Future enhancement to display WIF (HD-SEED) and XPRV (Bip32)?
|
# TODO: Future enhancement to display WIF (HD-SEED) and XPRV (Bip32)?
|
||||||
WORDS_12 = _("12 Words")
|
WORDS_12 = ButtonOption("12 Words")
|
||||||
WORDS_24 = _("24 Words")
|
WORDS_24 = ButtonOption("24 Words")
|
||||||
|
|
||||||
def __init__(self, seed_num: int):
|
def __init__(self, seed_num: int):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.seed_num = seed_num
|
self.seed_num = seed_num
|
||||||
self.num_words = 0
|
self.num_words = 0
|
||||||
self.bip85_app_num = 39 # TODO: Support other Application numbers
|
self.bip85_app_num = 39 # TODO: Support other Application numbers; TODO: Define this as a constant
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -1159,8 +1155,8 @@ class SeedBIP85ApplicationModeView(View):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# View to retrieve the derived seed index
|
|
||||||
class SeedBIP85SelectChildIndexView(View):
|
class SeedBIP85SelectChildIndexView(View):
|
||||||
|
# View to retrieve the derived seed index
|
||||||
def __init__(self, seed_num: int, num_words: int):
|
def __init__(self, seed_num: int, num_words: int):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.seed_num = seed_num
|
self.seed_num = seed_num
|
||||||
@@ -1168,7 +1164,7 @@ class SeedBIP85SelectChildIndexView(View):
|
|||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# Change this later to use the generic Screen input keyboard
|
# TODO: Change this later to use the generic Screen input keyboard
|
||||||
ret = seed_screens.SeedBIP85SelectChildIndexScreen().display()
|
ret = seed_screens.SeedBIP85SelectChildIndexScreen().display()
|
||||||
|
|
||||||
if ret == RET_CODE__BACK_BUTTON:
|
if ret == RET_CODE__BACK_BUTTON:
|
||||||
@@ -1206,7 +1202,7 @@ class SeedBIP85InvalidChildIndexView(View):
|
|||||||
show_back_button=False,
|
show_back_button=False,
|
||||||
status_headline=_("Invalid Child Index"),
|
status_headline=_("Invalid Child Index"),
|
||||||
text=_("BIP-85 Child Index must be between 0 and 2^31-1."),
|
text=_("BIP-85 Child Index must be between 0 and 2^31-1."),
|
||||||
button_data=[_("Try Again")]
|
button_data=[ButtonOption("Try Again")]
|
||||||
).display()
|
).display()
|
||||||
|
|
||||||
return Destination(
|
return Destination(
|
||||||
@@ -1224,8 +1220,8 @@ class SeedBIP85InvalidChildIndexView(View):
|
|||||||
Seed Words Backup Test
|
Seed Words Backup Test
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class SeedWordsBackupTestPromptView(View):
|
class SeedWordsBackupTestPromptView(View):
|
||||||
VERIFY = _("Verify")
|
VERIFY = ButtonOption("Verify")
|
||||||
SKIP = _("Skip")
|
SKIP = ButtonOption("Skip")
|
||||||
|
|
||||||
def __init__(self, seed_num: int, bip85_data: dict = None):
|
def __init__(self, seed_num: int, bip85_data: dict = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -1283,10 +1279,10 @@ class SeedWordsBackupTestView(View):
|
|||||||
while self.cur_index in self.confirmed_list:
|
while self.cur_index in self.confirmed_list:
|
||||||
self.cur_index = int(random.random() * len(self.mnemonic_list))
|
self.cur_index = int(random.random() * len(self.mnemonic_list))
|
||||||
|
|
||||||
real_word = self.mnemonic_list[self.cur_index]
|
real_word = ButtonOption(self.mnemonic_list[self.cur_index])
|
||||||
fake_word1 = bip39.WORDLIST[int(random.random() * 2047)]
|
fake_word1 = ButtonOption(bip39.WORDLIST[int(random.random() * 2047)])
|
||||||
fake_word2 = bip39.WORDLIST[int(random.random() * 2047)]
|
fake_word2 = ButtonOption(bip39.WORDLIST[int(random.random() * 2047)])
|
||||||
fake_word3 = bip39.WORDLIST[int(random.random() * 2047)]
|
fake_word3 = ButtonOption(bip39.WORDLIST[int(random.random() * 2047)])
|
||||||
|
|
||||||
button_data = [real_word, fake_word1, fake_word2, fake_word3]
|
button_data = [real_word, fake_word1, fake_word2, fake_word3]
|
||||||
random.shuffle(button_data)
|
random.shuffle(button_data)
|
||||||
@@ -1332,8 +1328,8 @@ class SeedWordsBackupTestView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedWordsBackupTestMistakeView(View):
|
class SeedWordsBackupTestMistakeView(View):
|
||||||
REVIEW = _("Review Seed Words")
|
REVIEW = ButtonOption("Review Seed Words")
|
||||||
RETRY = _("Try Again")
|
RETRY = ButtonOption("Try Again")
|
||||||
|
|
||||||
def __init__(self, seed_num: int, bip85_data: dict = None, cur_index: int = None, wrong_word: str = None, confirmed_list: list[bool] = None):
|
def __init__(self, seed_num: int, bip85_data: dict = None, cur_index: int = None, wrong_word: str = None, confirmed_list: list[bool] = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -1392,7 +1388,7 @@ class SeedWordsBackupTestSuccessView(View):
|
|||||||
show_back_button=False,
|
show_back_button=False,
|
||||||
status_headline=_("Success!"),
|
status_headline=_("Success!"),
|
||||||
text=_("All mnemonic backup words were successfully verified!"),
|
text=_("All mnemonic backup words were successfully verified!"),
|
||||||
button_data=[_("OK")]
|
button_data=[ButtonOption("OK")]
|
||||||
).display()
|
).display()
|
||||||
|
|
||||||
if self.seed_num is not None:
|
if self.seed_num is not None:
|
||||||
@@ -1414,15 +1410,11 @@ class SeedTranscribeSeedQRFormatView(View):
|
|||||||
def run(self):
|
def run(self):
|
||||||
seed = self.controller.get_seed(self.seed_num)
|
seed = self.controller.get_seed(self.seed_num)
|
||||||
if len(seed.mnemonic_list) == 12:
|
if len(seed.mnemonic_list) == 12:
|
||||||
STANDARD = _("Standard: 25x25")
|
STANDARD = ButtonOption("Standard: 25x25", return_data=25)
|
||||||
COMPACT = _("Compact: 21x21")
|
COMPACT = ButtonOption("Compact: 21x21", return_data=21)
|
||||||
num_modules_standard = 25
|
|
||||||
num_modules_compact = 21
|
|
||||||
else:
|
else:
|
||||||
STANDARD = _("Standard: 29x29")
|
STANDARD = ButtonOption("Standard: 29x29", return_data=29)
|
||||||
COMPACT = _("Compact: 25x25")
|
COMPACT = ButtonOption("Compact: 25x25", return_data=25)
|
||||||
num_modules_standard = 29
|
|
||||||
num_modules_compact = 25
|
|
||||||
|
|
||||||
if self.settings.get_value(SettingsConstants.SETTING__COMPACT_SEEDQR) != SettingsConstants.OPTION__ENABLED:
|
if self.settings.get_value(SettingsConstants.SETTING__COMPACT_SEEDQR) != SettingsConstants.OPTION__ENABLED:
|
||||||
# Only configured for standard SeedQR
|
# Only configured for standard SeedQR
|
||||||
@@ -1431,7 +1423,7 @@ class SeedTranscribeSeedQRFormatView(View):
|
|||||||
view_args={
|
view_args={
|
||||||
"seed_num": self.seed_num,
|
"seed_num": self.seed_num,
|
||||||
"seedqr_format": QRType.SEED__SEEDQR,
|
"seedqr_format": QRType.SEED__SEEDQR,
|
||||||
"num_modules": num_modules_standard,
|
"num_modules": STANDARD.return_data,
|
||||||
},
|
},
|
||||||
skip_current_view=True,
|
skip_current_view=True,
|
||||||
)
|
)
|
||||||
@@ -1450,10 +1442,10 @@ class SeedTranscribeSeedQRFormatView(View):
|
|||||||
|
|
||||||
if button_data[selected_menu_num] == STANDARD:
|
if button_data[selected_menu_num] == STANDARD:
|
||||||
seedqr_format = QRType.SEED__SEEDQR
|
seedqr_format = QRType.SEED__SEEDQR
|
||||||
num_modules = num_modules_standard
|
|
||||||
else:
|
else:
|
||||||
seedqr_format = QRType.SEED__COMPACTSEEDQR
|
seedqr_format = QRType.SEED__COMPACTSEEDQR
|
||||||
num_modules = num_modules_compact
|
|
||||||
|
num_modules = button_data[selected_menu_num].return_data
|
||||||
|
|
||||||
return Destination(
|
return Destination(
|
||||||
SeedTranscribeSeedQRWarningView,
|
SeedTranscribeSeedQRWarningView,
|
||||||
@@ -1580,8 +1572,8 @@ class SeedTranscribeSeedQRZoomedInView(View):
|
|||||||
|
|
||||||
|
|
||||||
class SeedTranscribeSeedQRConfirmQRPromptView(View):
|
class SeedTranscribeSeedQRConfirmQRPromptView(View):
|
||||||
SCAN = (_("Confirm SeedQR"), SeedSignerIconConstants.QRCODE)
|
SCAN = ButtonOption("Confirm SeedQR", SeedSignerIconConstants.QRCODE)
|
||||||
DONE = _("Done")
|
DONE = ButtonOption("Done")
|
||||||
|
|
||||||
def __init__(self, seed_num: int):
|
def __init__(self, seed_num: int):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -1726,8 +1718,8 @@ class AddressVerificationStartView(View):
|
|||||||
|
|
||||||
|
|
||||||
class AddressVerificationSigTypeView(View):
|
class AddressVerificationSigTypeView(View):
|
||||||
SINGLE_SIG = _("Single Sig")
|
SINGLE_SIG = ButtonOption("Single Sig")
|
||||||
MULTISIG = _("Multisig")
|
MULTISIG = ButtonOption("Multisig")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from seedsigner.helpers import embit_utils
|
from seedsigner.helpers import embit_utils
|
||||||
@@ -1781,8 +1773,8 @@ class SeedAddressVerificationView(View):
|
|||||||
multisig.
|
multisig.
|
||||||
"""
|
"""
|
||||||
# TRANSLATOR_NOTE: Option when scanning for a matching address; skips ten addresses ahead
|
# TRANSLATOR_NOTE: Option when scanning for a matching address; skips ten addresses ahead
|
||||||
SKIP_10 = _("Skip 10")
|
SKIP_10 = ButtonOption("Skip 10")
|
||||||
CANCEL = _("Cancel")
|
CANCEL = ButtonOption("Cancel")
|
||||||
|
|
||||||
def __init__(self, seed_num: int = None):
|
def __init__(self, seed_num: int = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -2000,8 +1992,8 @@ class AddressVerificationSuccessView(View):
|
|||||||
|
|
||||||
|
|
||||||
class LoadMultisigWalletDescriptorView(View):
|
class LoadMultisigWalletDescriptorView(View):
|
||||||
SCAN = (_("Scan Descriptor"), SeedSignerIconConstants.QRCODE)
|
SCAN = ButtonOption("Scan Descriptor", SeedSignerIconConstants.QRCODE)
|
||||||
CANCEL = _("Cancel")
|
CANCEL = ButtonOption("Cancel")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.SCAN, self.CANCEL]
|
button_data = [self.SCAN, self.CANCEL]
|
||||||
@@ -2025,10 +2017,10 @@ class LoadMultisigWalletDescriptorView(View):
|
|||||||
|
|
||||||
|
|
||||||
class MultisigWalletDescriptorView(View):
|
class MultisigWalletDescriptorView(View):
|
||||||
RETURN = _("Return to PSBT")
|
RETURN = ButtonOption("Return to PSBT")
|
||||||
VERIFY_ADDR = _("Verify Addr")
|
VERIFY_ADDR = ButtonOption("Verify Addr")
|
||||||
ADDRESS_EXPLORER = _("Address Explorer")
|
ADDRESS_EXPLORER = ButtonOption("Address Explorer")
|
||||||
OK = _("OK")
|
OK = ButtonOption("OK")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
descriptor = self.controller.multisig_wallet_descriptor
|
descriptor = self.controller.multisig_wallet_descriptor
|
||||||
@@ -2047,8 +2039,8 @@ class MultisigWalletDescriptorView(View):
|
|||||||
if self.controller.resume_main_flow == Controller.FLOW__PSBT:
|
if self.controller.resume_main_flow == Controller.FLOW__PSBT:
|
||||||
button_data = [self.RETURN]
|
button_data = [self.RETURN]
|
||||||
elif self.controller.resume_main_flow == Controller.FLOW__VERIFY_MULTISIG_ADDR and self.controller.unverified_address:
|
elif self.controller.resume_main_flow == Controller.FLOW__VERIFY_MULTISIG_ADDR and self.controller.unverified_address:
|
||||||
verify_addr_display = f"""{self.VERIFY_ADDR} {self.controller.unverified_address["address"][:7]}"""
|
verify_addr_display = f"""{_(self.VERIFY_ADDR.button_label)} {self.controller.unverified_address["address"][:7]}"""
|
||||||
button_data = [verify_addr_display]
|
button_data = [ButtonOption(verify_addr_display)]
|
||||||
elif self.controller.resume_main_flow == Controller.FLOW__ADDRESS_EXPLORER:
|
elif self.controller.resume_main_flow == Controller.FLOW__ADDRESS_EXPLORER:
|
||||||
button_data = [self.ADDRESS_EXPLORER]
|
button_data = [self.ADDRESS_EXPLORER]
|
||||||
|
|
||||||
@@ -2069,7 +2061,7 @@ class MultisigWalletDescriptorView(View):
|
|||||||
self.controller.resume_main_flow = None
|
self.controller.resume_main_flow = None
|
||||||
return Destination(PSBTChangeDetailsView, view_args=dict(change_address_num=0))
|
return Destination(PSBTChangeDetailsView, view_args=dict(change_address_num=0))
|
||||||
|
|
||||||
elif button_data[selected_menu_num].startswith(self.VERIFY_ADDR):
|
elif button_data[selected_menu_num].button_label.startswith(_(self.VERIFY_ADDR.button_label)):
|
||||||
self.controller.resume_main_flow = None
|
self.controller.resume_main_flow = None
|
||||||
return Destination(SeedAddressVerificationView)
|
return Destination(SeedAddressVerificationView)
|
||||||
|
|
||||||
@@ -2111,12 +2103,7 @@ class SeedSignMessageStartView(View):
|
|||||||
# Note: addr_format["network"] can be MAINNET or [TESTNET, REGTEST]
|
# Note: addr_format["network"] can be MAINNET or [TESTNET, REGTEST]
|
||||||
if self.settings.get_value(SettingsConstants.SETTING__NETWORK) not in addr_format["network"]:
|
if self.settings.get_value(SettingsConstants.SETTING__NETWORK) not in addr_format["network"]:
|
||||||
from seedsigner.views.view import NetworkMismatchErrorView
|
from seedsigner.views.view import NetworkMismatchErrorView
|
||||||
# TRANSLATOR_NOTE: Inserts mainnet/testnet/regtest and derivation path
|
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(derivation_path=self.derivation_path)))
|
||||||
text = _("Current network setting ({}) doesn't match {}").format(
|
|
||||||
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
|
||||||
self.derivation_path,
|
|
||||||
)
|
|
||||||
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(text=text)))
|
|
||||||
|
|
||||||
# cleanup. Note: We could leave this in place so the user can resume the
|
# cleanup. Note: We could leave this in place so the user can resume the
|
||||||
# flow, but for now we avoid complications and keep things simple.
|
# flow, but for now we avoid complications and keep things simple.
|
||||||
@@ -2203,11 +2190,7 @@ class SeedSignMessageConfirmAddressView(View):
|
|||||||
addr_format["network"] = self.settings.get_value(SettingsConstants.SETTING__NETWORK)
|
addr_format["network"] = self.settings.get_value(SettingsConstants.SETTING__NETWORK)
|
||||||
else:
|
else:
|
||||||
from seedsigner.views.view import NetworkMismatchErrorView
|
from seedsigner.views.view import NetworkMismatchErrorView
|
||||||
text = _("Current network setting ({}) doesn't match {}").format(
|
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(derivation_path=self.derivation_path)))
|
||||||
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
|
||||||
self.derivation_path,
|
|
||||||
)
|
|
||||||
self.set_redirect(Destination(NetworkMismatchErrorView, view_args=dict(text=text)))
|
|
||||||
|
|
||||||
# cleanup. Note: We could leave this in place so the user can resume the
|
# cleanup. Note: We could leave this in place so the user can resume the
|
||||||
# flow, but for now we avoid complications and keep things simple.
|
# flow, but for now we avoid complications and keep things simple.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from gettext import gettext as _
|
|||||||
|
|
||||||
from seedsigner.gui.components import SeedSignerIconConstants
|
from seedsigner.gui.components import SeedSignerIconConstants
|
||||||
from seedsigner.gui.screens import (RET_CODE__BACK_BUTTON, ButtonListScreen, settings_screens)
|
from seedsigner.gui.screens import (RET_CODE__BACK_BUTTON, ButtonListScreen, settings_screens)
|
||||||
|
from seedsigner.gui.screens.screen import ButtonOption
|
||||||
from seedsigner.models.settings import Settings, SettingsConstants, SettingsDefinition
|
from seedsigner.models.settings import Settings, SettingsConstants, SettingsDefinition
|
||||||
|
|
||||||
from .view import View, Destination, MainMenuView
|
from .view import View, Destination, MainMenuView
|
||||||
@@ -12,8 +13,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class SettingsMenuView(View):
|
class SettingsMenuView(View):
|
||||||
IO_TEST = _("I/O test")
|
IO_TEST = ButtonOption("I/O test")
|
||||||
DONATE = _("Donate")
|
DONATE = ButtonOption("Donate")
|
||||||
|
|
||||||
def __init__(self, visibility: str = SettingsConstants.VISIBILITY__GENERAL, selected_attr: str = None, initial_scroll: int = 0):
|
def __init__(self, visibility: str = SettingsConstants.VISIBILITY__GENERAL, selected_attr: str = None, initial_scroll: int = 0):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -28,7 +29,7 @@ class SettingsMenuView(View):
|
|||||||
settings_entries = SettingsDefinition.get_settings_entries(
|
settings_entries = SettingsDefinition.get_settings_entries(
|
||||||
visibility=self.visibility
|
visibility=self.visibility
|
||||||
)
|
)
|
||||||
button_data=[e.display_name for e in settings_entries]
|
button_data=[ButtonOption(e.display_name) for e in settings_entries]
|
||||||
|
|
||||||
selected_button = 0
|
selected_button = 0
|
||||||
if self.selected_attr:
|
if self.selected_attr:
|
||||||
@@ -41,7 +42,7 @@ class SettingsMenuView(View):
|
|||||||
title = _("Settings")
|
title = _("Settings")
|
||||||
|
|
||||||
# Set up the next nested level of menuing
|
# Set up the next nested level of menuing
|
||||||
button_data.append((_("Advanced"), None, None, None, SeedSignerIconConstants.CHEVRON_RIGHT))
|
button_data.append(ButtonOption("Advanced", right_icon_name=SeedSignerIconConstants.CHEVRON_RIGHT))
|
||||||
next_destination = Destination(SettingsMenuView, view_args={"visibility": SettingsConstants.VISIBILITY__ADVANCED})
|
next_destination = Destination(SettingsMenuView, view_args={"visibility": SettingsConstants.VISIBILITY__ADVANCED})
|
||||||
|
|
||||||
button_data.append(self.IO_TEST)
|
button_data.append(self.IO_TEST)
|
||||||
@@ -114,7 +115,7 @@ class SettingsEntryUpdateSelectionView(View):
|
|||||||
value, display_name = value
|
value, display_name = value
|
||||||
else:
|
else:
|
||||||
display_name = value
|
display_name = value
|
||||||
button_data.append(display_name)
|
button_data.append(ButtonOption(display_name))
|
||||||
|
|
||||||
if (type(initial_value) == list and value in initial_value) or value == initial_value:
|
if (type(initial_value) == list and value in initial_value) or value == initial_value:
|
||||||
checked_buttons.append(i)
|
checked_buttons.append(i)
|
||||||
@@ -211,7 +212,6 @@ class SettingsIngestSettingsQRView(View):
|
|||||||
SettingsQRConfirmationScreen,
|
SettingsQRConfirmationScreen,
|
||||||
title=_("Settings QR"),
|
title=_("Settings QR"),
|
||||||
config_name=self.config_name,
|
config_name=self.config_name,
|
||||||
button_data=[_("Home")],
|
|
||||||
status_message=self.status_message,
|
status_message=self.status_message,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from gettext import gettext as _
|
|||||||
|
|
||||||
from seedsigner.gui.components import FontAwesomeIconConstants, GUIConstants, SeedSignerIconConstants
|
from seedsigner.gui.components import FontAwesomeIconConstants, GUIConstants, SeedSignerIconConstants
|
||||||
from seedsigner.gui.screens import RET_CODE__BACK_BUTTON, ButtonListScreen
|
from seedsigner.gui.screens import RET_CODE__BACK_BUTTON, ButtonListScreen
|
||||||
|
from seedsigner.gui.screens.screen import ButtonOption
|
||||||
from seedsigner.helpers import mnemonic_generation
|
from seedsigner.helpers import mnemonic_generation
|
||||||
from seedsigner.models.seed import Seed
|
from seedsigner.models.seed import Seed
|
||||||
from seedsigner.models.settings_definition import SettingsConstants
|
from seedsigner.models.settings_definition import SettingsConstants
|
||||||
@@ -19,11 +20,11 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class ToolsMenuView(View):
|
class ToolsMenuView(View):
|
||||||
IMAGE = (_("New seed"), FontAwesomeIconConstants.CAMERA)
|
IMAGE = ButtonOption("New seed", FontAwesomeIconConstants.CAMERA)
|
||||||
DICE = (_("New seed"), FontAwesomeIconConstants.DICE)
|
DICE = ButtonOption("New seed", FontAwesomeIconConstants.DICE)
|
||||||
KEYBOARD = (_("Calc 12th/24th word"), FontAwesomeIconConstants.KEYBOARD)
|
KEYBOARD = ButtonOption("Calc 12th/24th word", FontAwesomeIconConstants.KEYBOARD)
|
||||||
ADDRESS_EXPLORER = _("Address Explorer")
|
ADDRESS_EXPLORER = ButtonOption("Address Explorer")
|
||||||
VERIFY_ADDRESS = _("Verify Address")
|
VERIFY_ADDRESS = ButtonOption("Verify Address")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.IMAGE, self.DICE, self.KEYBOARD, self.ADDRESS_EXPLORER, self.VERIFY_ADDRESS]
|
button_data = [self.IMAGE, self.DICE, self.KEYBOARD, self.ADDRESS_EXPLORER, self.VERIFY_ADDRESS]
|
||||||
@@ -113,8 +114,8 @@ class ToolsImageEntropyFinalImageView(View):
|
|||||||
|
|
||||||
|
|
||||||
class ToolsImageEntropyMnemonicLengthView(View):
|
class ToolsImageEntropyMnemonicLengthView(View):
|
||||||
TWELVE_WORDS = _("12 words")
|
TWELVE_WORDS = ButtonOption("12 words", return_data=12)
|
||||||
TWENTYFOUR_WORDS = _("24 words")
|
TWENTYFOUR_WORDS = ButtonOption("24 words", return_data=24)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.TWELVE_WORDS, self.TWENTYFOUR_WORDS]
|
button_data = [self.TWELVE_WORDS, self.TWENTYFOUR_WORDS]
|
||||||
@@ -127,10 +128,7 @@ class ToolsImageEntropyMnemonicLengthView(View):
|
|||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
return Destination(BackStackView)
|
return Destination(BackStackView)
|
||||||
|
|
||||||
if button_data[selected_menu_num] == self.TWELVE_WORDS:
|
mnemonic_length = button_data[selected_menu_num].return_data
|
||||||
mnemonic_length = 12
|
|
||||||
else:
|
|
||||||
mnemonic_length = 24
|
|
||||||
|
|
||||||
preview_images = self.controller.image_entropy_preview_frames
|
preview_images = self.controller.image_entropy_preview_frames
|
||||||
seed_entropy_image = self.controller.image_entropy_final_image
|
seed_entropy_image = self.controller.image_entropy_final_image
|
||||||
@@ -186,15 +184,19 @@ class ToolsImageEntropyMnemonicLengthView(View):
|
|||||||
Dice rolls Views
|
Dice rolls Views
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class ToolsDiceEntropyMnemonicLengthView(View):
|
class ToolsDiceEntropyMnemonicLengthView(View):
|
||||||
# TRANSLATOR_NOTE: Inserts the number of dice rolls needed for a 12-word mnemonic
|
|
||||||
TWELVE = _("12 words ({} rolls)").format(mnemonic_generation.DICE__NUM_ROLLS__12WORD)
|
|
||||||
|
|
||||||
# TRANSLATOR_NOTE: Inserts the number of dice rolls needed for a 24-word mnemonic
|
|
||||||
TWENTY_FOUR = _("24 words ({} rolls)").format(mnemonic_generation.DICE__NUM_ROLLS__24WORD)
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.TWELVE, self.TWENTY_FOUR]
|
# Since we're dynamically building the ButtonOption button_labels here, it's too
|
||||||
|
# awkward to use the usual class-level attr approach.
|
||||||
|
|
||||||
|
# TRANSLATOR_NOTE: Inserts the number of dice rolls needed for a 12-word mnemonic
|
||||||
|
twelve = _("12 words ({} rolls)").format(mnemonic_generation.DICE__NUM_ROLLS__12WORD)
|
||||||
|
TWELVE = ButtonOption(twelve, return_data=mnemonic_generation.DICE__NUM_ROLLS__12WORD)
|
||||||
|
|
||||||
|
# TRANSLATOR_NOTE: Inserts the number of dice rolls needed for a 24-word mnemonic
|
||||||
|
twenty_four = _("24 words ({} rolls)").format(mnemonic_generation.DICE__NUM_ROLLS__24WORD)
|
||||||
|
TWENTY_FOUR = ButtonOption(twenty_four, return_data=mnemonic_generation.DICE__NUM_ROLLS__24WORD)
|
||||||
|
|
||||||
|
button_data = [TWELVE, TWENTY_FOUR]
|
||||||
selected_menu_num = ButtonListScreen(
|
selected_menu_num = ButtonListScreen(
|
||||||
title=_("Mnemonic Length"),
|
title=_("Mnemonic Length"),
|
||||||
is_bottom_list=True,
|
is_bottom_list=True,
|
||||||
@@ -205,10 +207,10 @@ class ToolsDiceEntropyMnemonicLengthView(View):
|
|||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
return Destination(BackStackView)
|
return Destination(BackStackView)
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == self.TWELVE:
|
elif button_data[selected_menu_num] == TWELVE:
|
||||||
return Destination(ToolsDiceEntropyEntryView, view_args=dict(total_rolls=mnemonic_generation.DICE__NUM_ROLLS__12WORD))
|
return Destination(ToolsDiceEntropyEntryView, view_args=dict(total_rolls=mnemonic_generation.DICE__NUM_ROLLS__12WORD))
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == self.TWENTY_FOUR:
|
elif button_data[selected_menu_num] == TWENTY_FOUR:
|
||||||
return Destination(ToolsDiceEntropyEntryView, view_args=dict(total_rolls=mnemonic_generation.DICE__NUM_ROLLS__24WORD))
|
return Destination(ToolsDiceEntropyEntryView, view_args=dict(total_rolls=mnemonic_generation.DICE__NUM_ROLLS__24WORD))
|
||||||
|
|
||||||
|
|
||||||
@@ -243,8 +245,8 @@ class ToolsDiceEntropyEntryView(View):
|
|||||||
Calc final word Views
|
Calc final word Views
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class ToolsCalcFinalWordNumWordsView(View):
|
class ToolsCalcFinalWordNumWordsView(View):
|
||||||
TWELVE = _("12 words")
|
TWELVE = ButtonOption("12 words", return_data=12)
|
||||||
TWENTY_FOUR = _("24 words")
|
TWENTY_FOUR = ButtonOption("24 words", return_data=24)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.TWELVE, self.TWENTY_FOUR]
|
button_data = [self.TWELVE, self.TWENTY_FOUR]
|
||||||
@@ -260,29 +262,21 @@ class ToolsCalcFinalWordNumWordsView(View):
|
|||||||
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
if selected_menu_num == RET_CODE__BACK_BUTTON:
|
||||||
return Destination(BackStackView)
|
return Destination(BackStackView)
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == self.TWELVE:
|
self.controller.storage.init_pending_mnemonic(button_data[selected_menu_num].return_data)
|
||||||
self.controller.storage.init_pending_mnemonic(12)
|
|
||||||
|
|
||||||
# return Destination(SeedMnemonicEntryView, view_args=dict(is_calc_final_word=True))
|
return Destination(SeedMnemonicEntryView, view_args=dict(is_calc_final_word=True))
|
||||||
return Destination(SeedMnemonicEntryView, view_args=dict(is_calc_final_word=True))
|
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == self.TWENTY_FOUR:
|
|
||||||
self.controller.storage.init_pending_mnemonic(24)
|
|
||||||
|
|
||||||
# return Destination(SeedMnemonicEntryView, view_args=dict(is_calc_final_word=True))
|
|
||||||
return Destination(SeedMnemonicEntryView, view_args=dict(is_calc_final_word=True))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ToolsCalcFinalWordFinalizePromptView(View):
|
class ToolsCalcFinalWordFinalizePromptView(View):
|
||||||
# TRANSLATOR_NOTE: Label to gather entropy through coin tosses
|
# TRANSLATOR_NOTE: Label to gather entropy through coin tosses
|
||||||
COIN_FLIPS = _("Coin flip entropy")
|
COIN_FLIPS = ButtonOption("Coin flip entropy")
|
||||||
|
|
||||||
# TRANSLATOR_NOTE: Label to gather entropy through user specified BIP-39 word
|
# TRANSLATOR_NOTE: Label to gather entropy through user specified BIP-39 word
|
||||||
SELECT_WORD = _("Word selection entropy")
|
SELECT_WORD = ButtonOption("Word selection entropy")
|
||||||
|
|
||||||
# TRANSLATOR_NOTE: Label to allow user to default entropy as all-zeros
|
# TRANSLATOR_NOTE: Label to allow user to default entropy as all-zeros
|
||||||
ZEROS = _("Finalize with zeros")
|
ZEROS = ButtonOption("Finalize with zeros")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from seedsigner.gui.screens.tools_screens import ToolsCalcFinalWordFinalizePromptScreen
|
from seedsigner.gui.screens.tools_screens import ToolsCalcFinalWordFinalizePromptScreen
|
||||||
@@ -343,7 +337,7 @@ class ToolsCalcFinalWordCoinFlipsView(View):
|
|||||||
|
|
||||||
|
|
||||||
class ToolsCalcFinalWordShowFinalWordView(View):
|
class ToolsCalcFinalWordShowFinalWordView(View):
|
||||||
NEXT = _("Next")
|
NEXT = ButtonOption("Next")
|
||||||
|
|
||||||
def __init__(self, coin_flips: str = None):
|
def __init__(self, coin_flips: str = None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -399,10 +393,13 @@ class ToolsCalcFinalWordShowFinalWordView(View):
|
|||||||
def run(self):
|
def run(self):
|
||||||
from seedsigner.gui.screens.tools_screens import ToolsCalcFinalWordScreen
|
from seedsigner.gui.screens.tools_screens import ToolsCalcFinalWordScreen
|
||||||
button_data = [self.NEXT]
|
button_data = [self.NEXT]
|
||||||
|
|
||||||
|
# TRANSLATOR_NOTE: label to calculate the last word of a BIP-39 mnemonic seed phrase
|
||||||
|
title = _("Final Word Calc")
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
ToolsCalcFinalWordScreen,
|
ToolsCalcFinalWordScreen,
|
||||||
# TRANSLATOR_NOTE: label to calculate the last word of a BIP-39 mnemonic seed phrase
|
title=title,
|
||||||
title=_("Final Word Calc"),
|
|
||||||
button_data=button_data,
|
button_data=button_data,
|
||||||
selected_final_word=self.selected_final_word,
|
selected_final_word=self.selected_final_word,
|
||||||
selected_final_bits=self.selected_final_bits,
|
selected_final_bits=self.selected_final_bits,
|
||||||
@@ -419,8 +416,8 @@ class ToolsCalcFinalWordShowFinalWordView(View):
|
|||||||
|
|
||||||
|
|
||||||
class ToolsCalcFinalWordDoneView(View):
|
class ToolsCalcFinalWordDoneView(View):
|
||||||
LOAD = _("Load seed")
|
LOAD = ButtonOption("Load seed")
|
||||||
DISCARD = (_("Discard"), None, None, "red")
|
DISCARD = ButtonOption("Discard", button_label_color="red")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from seedsigner.gui.screens.tools_screens import ToolsCalcFinalWordDoneScreen
|
from seedsigner.gui.screens.tools_screens import ToolsCalcFinalWordDoneScreen
|
||||||
@@ -454,11 +451,11 @@ class ToolsCalcFinalWordDoneView(View):
|
|||||||
Address Explorer Views
|
Address Explorer Views
|
||||||
****************************************************************************"""
|
****************************************************************************"""
|
||||||
class ToolsAddressExplorerSelectSourceView(View):
|
class ToolsAddressExplorerSelectSourceView(View):
|
||||||
SCAN_SEED = (_("Scan a seed"), SeedSignerIconConstants.QRCODE)
|
SCAN_SEED = ButtonOption("Scan a seed", SeedSignerIconConstants.QRCODE)
|
||||||
SCAN_DESCRIPTOR = (_("Scan wallet descriptor"), SeedSignerIconConstants.QRCODE)
|
SCAN_DESCRIPTOR = ButtonOption("Scan wallet descriptor", SeedSignerIconConstants.QRCODE)
|
||||||
TYPE_12WORD = (_("Enter 12-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_12WORD = ButtonOption("Enter 12-word seed", FontAwesomeIconConstants.KEYBOARD, return_data=12)
|
||||||
TYPE_24WORD = (_("Enter 24-word seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_24WORD = ButtonOption("Enter 24-word seed", FontAwesomeIconConstants.KEYBOARD, return_data=24)
|
||||||
TYPE_ELECTRUM = (_("Enter Electrum seed"), FontAwesomeIconConstants.KEYBOARD)
|
TYPE_ELECTRUM = ButtonOption("Enter Electrum seed", FontAwesomeIconConstants.KEYBOARD)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from seedsigner.controller import Controller
|
from seedsigner.controller import Controller
|
||||||
@@ -467,7 +464,7 @@ class ToolsAddressExplorerSelectSourceView(View):
|
|||||||
button_data = []
|
button_data = []
|
||||||
for seed in seeds:
|
for seed in seeds:
|
||||||
button_str = seed.get_fingerprint(self.settings.get_value(SettingsConstants.SETTING__NETWORK))
|
button_str = seed.get_fingerprint(self.settings.get_value(SettingsConstants.SETTING__NETWORK))
|
||||||
button_data.append((button_str, SeedSignerIconConstants.FINGERPRINT))
|
button_data.append(ButtonOption(button_str, SeedSignerIconConstants.FINGERPRINT))
|
||||||
button_data = button_data + [self.SCAN_SEED, self.SCAN_DESCRIPTOR, self.TYPE_12WORD, self.TYPE_24WORD]
|
button_data = button_data + [self.SCAN_SEED, self.SCAN_DESCRIPTOR, self.TYPE_12WORD, self.TYPE_24WORD]
|
||||||
if self.settings.get_value(SettingsConstants.SETTING__ELECTRUM_SEEDS) == SettingsConstants.OPTION__ENABLED:
|
if self.settings.get_value(SettingsConstants.SETTING__ELECTRUM_SEEDS) == SettingsConstants.OPTION__ENABLED:
|
||||||
button_data.append(self.TYPE_ELECTRUM)
|
button_data.append(self.TYPE_ELECTRUM)
|
||||||
@@ -508,10 +505,7 @@ class ToolsAddressExplorerSelectSourceView(View):
|
|||||||
|
|
||||||
elif button_data[selected_menu_num] in [self.TYPE_12WORD, self.TYPE_24WORD]:
|
elif button_data[selected_menu_num] in [self.TYPE_12WORD, self.TYPE_24WORD]:
|
||||||
from seedsigner.views.seed_views import SeedMnemonicEntryView
|
from seedsigner.views.seed_views import SeedMnemonicEntryView
|
||||||
if button_data[selected_menu_num] == self.TYPE_12WORD:
|
self.controller.storage.init_pending_mnemonic(num_words=button_data[selected_menu_num].return_data)
|
||||||
self.controller.storage.init_pending_mnemonic(num_words=12)
|
|
||||||
else:
|
|
||||||
self.controller.storage.init_pending_mnemonic(num_words=24)
|
|
||||||
return Destination(SeedMnemonicEntryView)
|
return Destination(SeedMnemonicEntryView)
|
||||||
|
|
||||||
elif button_data[selected_menu_num] == self.TYPE_ELECTRUM:
|
elif button_data[selected_menu_num] == self.TYPE_ELECTRUM:
|
||||||
@@ -522,10 +516,10 @@ class ToolsAddressExplorerSelectSourceView(View):
|
|||||||
|
|
||||||
class ToolsAddressExplorerAddressTypeView(View):
|
class ToolsAddressExplorerAddressTypeView(View):
|
||||||
# TRANSLATOR_NOTE: label for addresses where others send us incoming payments
|
# TRANSLATOR_NOTE: label for addresses where others send us incoming payments
|
||||||
RECEIVE = _("Receive Addresses")
|
RECEIVE = ButtonOption("Receive Addresses")
|
||||||
|
|
||||||
# TRANSLATOR_NOTE: label for addresses that collect the change from our own outgoing payments
|
# TRANSLATOR_NOTE: label for addresses that collect the change from our own outgoing payments
|
||||||
CHANGE = _("Change Addresses")
|
CHANGE = ButtonOption("Change Addresses")
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, seed_num: int = None, script_type: str = None, custom_derivation: str = None):
|
def __init__(self, seed_num: int = None, script_type: str = None, custom_derivation: str = None):
|
||||||
@@ -689,10 +683,11 @@ class ToolsAddressExplorerAddressListView(View):
|
|||||||
end_digits = -5
|
end_digits = -5
|
||||||
else:
|
else:
|
||||||
end_digits = -4
|
end_digits = -4
|
||||||
button_data.append(f"{cur_index}:{address[:8]}...{address[end_digits:]}")
|
button_data.append(ButtonOption(f"{cur_index}:{address[:8]}...{address[end_digits:]}"))
|
||||||
|
|
||||||
# TRANSLATOR_NOTE: Insert the number of addrs displayed per screen (e.g. "Next 10")
|
# TRANSLATOR_NOTE: Insert the number of addrs displayed per screen (e.g. "Next 10")
|
||||||
button_data.append((_("Next {}").format(addrs_per_screen), None, None, None, SeedSignerIconConstants.CHEVRON_RIGHT))
|
button_label = _("Next {}").format(addrs_per_screen)
|
||||||
|
button_data.append(ButtonOption(button_label, right_icon_name=SeedSignerIconConstants.CHEVRON_RIGHT))
|
||||||
|
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
ButtonListScreen,
|
ButtonListScreen,
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
from seedsigner.gui.components import FontAwesomeIconConstants, SeedSignerIconConstants
|
from seedsigner.helpers.l10n import mark_for_translation as _mft
|
||||||
|
from seedsigner.gui.components import SeedSignerIconConstants
|
||||||
from seedsigner.gui.screens import RET_CODE__POWER_BUTTON, RET_CODE__BACK_BUTTON
|
from seedsigner.gui.screens import RET_CODE__POWER_BUTTON, RET_CODE__BACK_BUTTON
|
||||||
from seedsigner.gui.screens.screen import BaseScreen, DireWarningScreen, LargeButtonScreen, PowerOffScreen, PowerOffNotRequiredScreen, ResetScreen, WarningScreen
|
from seedsigner.gui.screens.screen import BaseScreen, ButtonOption, DireWarningScreen, LargeButtonScreen, PowerOffScreen, PowerOffNotRequiredScreen, ResetScreen, WarningScreen
|
||||||
from seedsigner.models.settings import Settings, SettingsConstants
|
from seedsigner.models.settings import Settings, SettingsConstants
|
||||||
from seedsigner.models.settings_definition import SettingsDefinition
|
from seedsigner.models.settings_definition import SettingsDefinition
|
||||||
from seedsigner.models.threads import BaseThread
|
from seedsigner.models.threads import BaseThread
|
||||||
@@ -18,6 +19,7 @@ class BackStackView:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Views contain the biz logic to handle discrete tasks, exactly analogous to a Flask
|
Views contain the biz logic to handle discrete tasks, exactly analogous to a Flask
|
||||||
request/response function or a Django View. Each page/screen displayed to the user
|
request/response function or a Django View. Each page/screen displayed to the user
|
||||||
@@ -182,14 +184,13 @@ class Destination:
|
|||||||
#
|
#
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
class MainMenuView(View):
|
class MainMenuView(View):
|
||||||
SCAN = (_("Scan"), SeedSignerIconConstants.SCAN)
|
SCAN = ButtonOption("Scan", SeedSignerIconConstants.SCAN)
|
||||||
SEEDS = (_("Seeds"), SeedSignerIconConstants.SEEDS)
|
SEEDS = ButtonOption("Seeds", SeedSignerIconConstants.SEEDS)
|
||||||
TOOLS = (_("Tools"), SeedSignerIconConstants.TOOLS)
|
TOOLS = ButtonOption("Tools", SeedSignerIconConstants.TOOLS)
|
||||||
SETTINGS = (_("Settings"), SeedSignerIconConstants.SETTINGS)
|
SETTINGS = ButtonOption("Settings", SeedSignerIconConstants.SETTINGS)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from seedsigner.gui.screens.screen import MainMenuScreen
|
from seedsigner.gui.screens.screen import MainMenuScreen
|
||||||
|
|
||||||
button_data = [self.SCAN, self.SEEDS, self.TOOLS, self.SETTINGS]
|
button_data = [self.SCAN, self.SEEDS, self.TOOLS, self.SETTINGS]
|
||||||
selected_menu_num = self.run_screen(
|
selected_menu_num = self.run_screen(
|
||||||
MainMenuScreen,
|
MainMenuScreen,
|
||||||
@@ -219,8 +220,8 @@ class MainMenuView(View):
|
|||||||
|
|
||||||
|
|
||||||
class PowerOptionsView(View):
|
class PowerOptionsView(View):
|
||||||
RESET = (_("Restart"), SeedSignerIconConstants.RESTART)
|
RESET = ButtonOption("Restart", SeedSignerIconConstants.RESTART)
|
||||||
POWER_OFF = (_("Power Off"), SeedSignerIconConstants.POWER)
|
POWER_OFF = ButtonOption("Power Off", SeedSignerIconConstants.POWER)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
button_data = [self.RESET, self.POWER_OFF]
|
button_data = [self.RESET, self.POWER_OFF]
|
||||||
@@ -293,12 +294,7 @@ class NotYetImplementedView(View):
|
|||||||
"""
|
"""
|
||||||
Temporary View to use during dev.
|
Temporary View to use during dev.
|
||||||
"""
|
"""
|
||||||
text: str = None
|
text: str = _mft("This is still on our to-do list!")
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
if not self.text:
|
|
||||||
self.text = _("This is still on our to-do list!")
|
|
||||||
return super().__post_init__()
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@@ -307,7 +303,7 @@ class NotYetImplementedView(View):
|
|||||||
title=_("Work In Progress"),
|
title=_("Work In Progress"),
|
||||||
status_headline=_("Not Yet Implemented"),
|
status_headline=_("Not Yet Implemented"),
|
||||||
text=self.text,
|
text=self.text,
|
||||||
button_data=[_("Back to Main Menu")],
|
button_data=[ButtonOption("Back to Main Menu")],
|
||||||
)
|
)
|
||||||
|
|
||||||
return Destination(MainMenuView)
|
return Destination(MainMenuView)
|
||||||
@@ -316,13 +312,12 @@ class NotYetImplementedView(View):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ErrorView(View):
|
class ErrorView(View):
|
||||||
title: str = _("Error")
|
title: str = _mft("Error")
|
||||||
show_back_button: bool = True
|
show_back_button: bool = True
|
||||||
status_headline: str = None
|
status_headline: str = None
|
||||||
text: str = None
|
text: str = None
|
||||||
button_text: str = None
|
button_text: str = None
|
||||||
next_destination: Destination = field(default_factory=lambda: Destination(MainMenuView, clear_history=True))
|
next_destination: Destination = None
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.run_screen(
|
self.run_screen(
|
||||||
@@ -330,33 +325,30 @@ class ErrorView(View):
|
|||||||
title=self.title,
|
title=self.title,
|
||||||
status_headline=self.status_headline,
|
status_headline=self.status_headline,
|
||||||
text=self.text,
|
text=self.text,
|
||||||
button_data=[self.button_text],
|
button_data=[ButtonOption(self.button_text)],
|
||||||
show_back_button=self.show_back_button,
|
show_back_button=self.show_back_button,
|
||||||
)
|
)
|
||||||
|
return self.next_destination if self.next_destination else Destination(MainMenuView, clear_history=True)
|
||||||
return self.next_destination
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class NetworkMismatchErrorView(ErrorView):
|
class NetworkMismatchErrorView(ErrorView):
|
||||||
title: str = _("Network Mismatch")
|
derivation_path: str = None
|
||||||
show_back_button: bool = False
|
|
||||||
button_text: str = _("Change Setting")
|
|
||||||
next_destination: Destination = None
|
|
||||||
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
|
from seedsigner.views.settings_views import SettingsEntryUpdateSelectionView
|
||||||
|
self.title: str = _("Network Mismatch")
|
||||||
|
self.show_back_button: bool = False
|
||||||
|
self.button_text: str = _("Change Setting")
|
||||||
|
self.next_destination = Destination(SettingsEntryUpdateSelectionView, view_args=dict(attr_name=SettingsConstants.SETTING__NETWORK), clear_history=True)
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
if not self.text:
|
|
||||||
# TRANSLATOR_NOTE: Inserts mainnet/testnet/regtest
|
|
||||||
self.text = _("Current network setting ({}) doesn't match current action.").format(
|
|
||||||
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
|
||||||
)
|
|
||||||
|
|
||||||
if not self.next_destination:
|
# TRANSLATOR_NOTE: Inserts mainnet/testnet/regtest and derivation path
|
||||||
from seedsigner.views.settings_views import SettingsEntryUpdateSelectionView
|
self.text = _("Current network setting ({}) doesn't match {}.").format(
|
||||||
self.next_destination = Destination(SettingsEntryUpdateSelectionView, view_args=dict(attr_name=SettingsConstants.SETTING__NETWORK), clear_history=True)
|
self.settings.get_value_display_name(SettingsConstants.SETTING__NETWORK),
|
||||||
|
self.derivation_path,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -380,14 +372,12 @@ class UnhandledExceptionView(View):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class OptionDisabledView(View):
|
class OptionDisabledView(View):
|
||||||
UPDATE_SETTING = "Update Setting"
|
UPDATE_SETTING = ButtonOption("Update Setting")
|
||||||
DONE = "Done"
|
DONE = ButtonOption("Done")
|
||||||
settings_attr: str
|
settings_attr: str
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
self.UPDATE_SETTING = _("Update Setting")
|
|
||||||
self.DONE = _("Done")
|
|
||||||
self.settings_entry = SettingsDefinition.get_settings_entry(self.settings_attr)
|
self.settings_entry = SettingsDefinition.get_settings_entry(self.settings_attr)
|
||||||
|
|
||||||
# TRANSLATOR_NOTE: Inserts the name of a settings option (e.g. "Persistent Settings" is currently...)
|
# TRANSLATOR_NOTE: Inserts the name of a settings option (e.g. "Persistent Settings" is currently...)
|
||||||
@@ -413,26 +403,3 @@ class OptionDisabledView(View):
|
|||||||
return Destination(SettingsEntryUpdateSelectionView, view_args=dict(attr_name=self.settings_attr), clear_history=True)
|
return Destination(SettingsEntryUpdateSelectionView, view_args=dict(attr_name=self.settings_attr), clear_history=True)
|
||||||
else:
|
else:
|
||||||
return Destination(MainMenuView, clear_history=True)
|
return Destination(MainMenuView, clear_history=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveMicroSDWarningView(View):
|
|
||||||
"""
|
|
||||||
Warning to remove the microsd
|
|
||||||
"""
|
|
||||||
def __init__(self, next_view: View):
|
|
||||||
super().__init__()
|
|
||||||
self.next_view = next_view
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.run_screen(
|
|
||||||
WarningScreen,
|
|
||||||
title=_("Security Tip"),
|
|
||||||
status_icon_name=FontAwesomeIconConstants.SDCARD,
|
|
||||||
status_headline="",
|
|
||||||
text=_("For maximum security,\nremove the MicroSD card\nbefore continuing."),
|
|
||||||
show_back_button=False,
|
|
||||||
button_data=[_("Continue")],
|
|
||||||
)
|
|
||||||
|
|
||||||
return Destination(self.next_view, clear_history=True)
|
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ def test_generate_screenshots(target_locale):
|
|||||||
"Misc Error Views": [
|
"Misc Error Views": [
|
||||||
NotYetImplementedView,
|
NotYetImplementedView,
|
||||||
(UnhandledExceptionView, dict(error=["IndexError", "line 1, in some_buggy_code.py", "list index out of range"])),
|
(UnhandledExceptionView, dict(error=["IndexError", "line 1, in some_buggy_code.py", "list index out of range"])),
|
||||||
NetworkMismatchErrorView,
|
(NetworkMismatchErrorView, dict(derivation_path="m/84'/1'/0'")),
|
||||||
(OptionDisabledView, dict(settings_attr=SettingsConstants.SETTING__MESSAGE_SIGNING)),
|
(OptionDisabledView, dict(settings_attr=SettingsConstants.SETTING__MESSAGE_SIGNING)),
|
||||||
(ErrorView, dict(
|
(ErrorView, dict(
|
||||||
title="Error",
|
title="Error",
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class TestPSBTFlows(FlowTest):
|
|||||||
FlowStep(psbt_views.PSBTSigningErrorView, button_data_selection=psbt_views.PSBTSigningErrorView.SELECT_DIFF_SEED),
|
FlowStep(psbt_views.PSBTSigningErrorView, button_data_selection=psbt_views.PSBTSigningErrorView.SELECT_DIFF_SEED),
|
||||||
FlowStep(psbt_views.PSBTSelectSeedView, button_data_selection=psbt_views.PSBTSelectSeedView.SCAN_SEED),
|
FlowStep(psbt_views.PSBTSelectSeedView, button_data_selection=psbt_views.PSBTSelectSeedView.SCAN_SEED),
|
||||||
FlowStep(scan_views.ScanSeedQRView, before_run=load_seed_into_decoder),
|
FlowStep(scan_views.ScanSeedQRView, before_run=load_seed_into_decoder),
|
||||||
FlowStep(seed_views.SeedFinalizeView, button_data_selection=SettingsConstants.LABEL__BIP39_PASSPHRASE),
|
FlowStep(seed_views.SeedFinalizeView, button_data_selection=seed_views.SeedFinalizeView.PASSPHRASE),
|
||||||
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="abc")),
|
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="abc")),
|
||||||
FlowStep(seed_views.SeedReviewPassphraseView, button_data_selection=seed_views.SeedReviewPassphraseView.DONE),
|
FlowStep(seed_views.SeedReviewPassphraseView, button_data_selection=seed_views.SeedReviewPassphraseView.DONE),
|
||||||
FlowStep(seed_views.SeedOptionsView, is_redirect=True),
|
FlowStep(seed_views.SeedOptionsView, is_redirect=True),
|
||||||
|
|||||||
+23
-12
@@ -5,7 +5,7 @@ import pytest
|
|||||||
from base import BaseTest, FlowTest, FlowStep
|
from base import BaseTest, FlowTest, FlowStep
|
||||||
from base import FlowTestInvalidButtonDataSelectionException
|
from base import FlowTestInvalidButtonDataSelectionException
|
||||||
|
|
||||||
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON
|
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON, ButtonOption
|
||||||
from seedsigner.models.settings import Settings, SettingsConstants
|
from seedsigner.models.settings import Settings, SettingsConstants
|
||||||
from seedsigner.models.seed import ElectrumSeed, Seed
|
from seedsigner.models.seed import ElectrumSeed, Seed
|
||||||
from seedsigner.views.view import ErrorView, MainMenuView, OptionDisabledView, View, NetworkMismatchErrorView
|
from seedsigner.views.view import ErrorView, MainMenuView, OptionDisabledView, View, NetworkMismatchErrorView
|
||||||
@@ -40,10 +40,10 @@ class TestSeedFlows(FlowTest):
|
|||||||
self.run_sequence([
|
self.run_sequence([
|
||||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SCAN),
|
FlowStep(MainMenuView, button_data_selection=MainMenuView.SCAN),
|
||||||
FlowStep(scan_views.ScanView, before_run=load_seed_into_decoder), # simulate read SeedQR; ret val is ignored
|
FlowStep(scan_views.ScanView, before_run=load_seed_into_decoder), # simulate read SeedQR; ret val is ignored
|
||||||
FlowStep(seed_views.SeedFinalizeView, button_data_selection=SettingsConstants.LABEL__BIP39_PASSPHRASE),
|
FlowStep(seed_views.SeedFinalizeView, button_data_selection=seed_views.SeedFinalizeView.PASSPHRASE),
|
||||||
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="muhpassphrase", is_back_button=True)),
|
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="muhpassphrase", is_back_button=True)),
|
||||||
FlowStep(seed_views.SeedAddPassphraseExitDialogView, button_data_selection=seed_views.SeedAddPassphraseExitDialogView.DISCARD),
|
FlowStep(seed_views.SeedAddPassphraseExitDialogView, button_data_selection=seed_views.SeedAddPassphraseExitDialogView.DISCARD),
|
||||||
FlowStep(seed_views.SeedFinalizeView, button_data_selection=SettingsConstants.LABEL__BIP39_PASSPHRASE),
|
FlowStep(seed_views.SeedFinalizeView, button_data_selection=seed_views.SeedFinalizeView.PASSPHRASE),
|
||||||
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="muhpassphrase", is_back_button=True)),
|
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="muhpassphrase", is_back_button=True)),
|
||||||
FlowStep(seed_views.SeedAddPassphraseExitDialogView, button_data_selection=seed_views.SeedAddPassphraseExitDialogView.EDIT),
|
FlowStep(seed_views.SeedAddPassphraseExitDialogView, button_data_selection=seed_views.SeedAddPassphraseExitDialogView.EDIT),
|
||||||
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="muhpassphrase")),
|
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="muhpassphrase")),
|
||||||
@@ -183,15 +183,18 @@ class TestSeedFlows(FlowTest):
|
|||||||
"""
|
"""
|
||||||
Selecting "Export XPUB" from the SeedOptionsView should enter the Export XPUB flow and end at the MainMenuView
|
Selecting "Export XPUB" from the SeedOptionsView should enter the Export XPUB flow and end at the MainMenuView
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def flowtest_standard_xpub(sig_tuple, script_tuple, coord_tuple):
|
def flowtest_standard_xpub(sig_tuple, script_tuple, coord_tuple):
|
||||||
|
if sig_tuple[0] == SettingsConstants.SINGLE_SIG:
|
||||||
|
sig_selection = seed_views.SeedExportXpubSigTypeView.SINGLE_SIG
|
||||||
|
else:
|
||||||
|
sig_selection = seed_views.SeedExportXpubSigTypeView.MULTISIG
|
||||||
self.run_sequence(
|
self.run_sequence(
|
||||||
initial_destination_view_args=dict(seed_num=0),
|
initial_destination_view_args=dict(seed_num=0),
|
||||||
sequence=[
|
sequence=[
|
||||||
FlowStep(seed_views.SeedOptionsView, button_data_selection=seed_views.SeedOptionsView.EXPORT_XPUB),
|
FlowStep(seed_views.SeedOptionsView, button_data_selection=seed_views.SeedOptionsView.EXPORT_XPUB),
|
||||||
FlowStep(seed_views.SeedExportXpubSigTypeView, button_data_selection=sig_tuple[1]),
|
FlowStep(seed_views.SeedExportXpubSigTypeView, button_data_selection=sig_selection),
|
||||||
FlowStep(seed_views.SeedExportXpubScriptTypeView, button_data_selection=script_tuple[1]),
|
FlowStep(seed_views.SeedExportXpubScriptTypeView, button_data_selection=ButtonOption(script_tuple[1], return_data=script_tuple[0])),
|
||||||
FlowStep(seed_views.SeedExportXpubCoordinatorView, button_data_selection=coord_tuple[1]),
|
FlowStep(seed_views.SeedExportXpubCoordinatorView, button_data_selection=ButtonOption(coord_tuple[1], return_data=coord_tuple[0])),
|
||||||
FlowStep(seed_views.SeedExportXpubWarningView, screen_return_value=0),
|
FlowStep(seed_views.SeedExportXpubWarningView, screen_return_value=0),
|
||||||
FlowStep(seed_views.SeedExportXpubDetailsView, screen_return_value=0),
|
FlowStep(seed_views.SeedExportXpubDetailsView, screen_return_value=0),
|
||||||
FlowStep(seed_views.SeedExportXpubQRDisplayView, screen_return_value=0),
|
FlowStep(seed_views.SeedExportXpubQRDisplayView, screen_return_value=0),
|
||||||
@@ -303,10 +306,18 @@ class TestSeedFlows(FlowTest):
|
|||||||
SettingsConstants.CUSTOM_DERIVATION
|
SettingsConstants.CUSTOM_DERIVATION
|
||||||
])
|
])
|
||||||
|
|
||||||
# get display names to access button choices in the views (ugh: hardcoding, is there a better way?)
|
# Ensure that all coordinators are enabled
|
||||||
sig_type = self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__SIG_TYPES)[0] # single sig
|
self.settings.set_value(SettingsConstants.SETTING__COORDINATORS, [x for x, y in SettingsConstants.ALL_COORDINATORS])
|
||||||
script_type = self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__SCRIPT_TYPES)[2] # custom derivation
|
|
||||||
coordinator = self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__COORDINATORS)[3] # specter
|
# Set up button_data selections
|
||||||
|
sig_type = seed_views.SeedExportXpubSigTypeView.SINGLE_SIG
|
||||||
|
|
||||||
|
custom_derivation = SettingsConstants.CUSTOM_DERIVATION
|
||||||
|
script_type = ButtonOption(self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__SCRIPT_TYPES)[2], return_data=custom_derivation)
|
||||||
|
|
||||||
|
specter = SettingsConstants.COORDINATOR__SPECTER_DESKTOP
|
||||||
|
assert SettingsConstants.ALL_COORDINATORS[3][0] == specter
|
||||||
|
coordinator = ButtonOption(self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__COORDINATORS)[3], return_data=specter)
|
||||||
|
|
||||||
self.run_sequence(
|
self.run_sequence(
|
||||||
initial_destination_view_args=dict(seed_num=0),
|
initial_destination_view_args=dict(seed_num=0),
|
||||||
@@ -377,7 +388,7 @@ class TestSeedFlows(FlowTest):
|
|||||||
|
|
||||||
# Skips past the script type options via redirect
|
# Skips past the script type options via redirect
|
||||||
FlowStep(seed_views.SeedExportXpubScriptTypeView, is_redirect=True),
|
FlowStep(seed_views.SeedExportXpubScriptTypeView, is_redirect=True),
|
||||||
FlowStep(seed_views.SeedExportXpubCoordinatorView, button_data_selection=self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__COORDINATORS)[0]),
|
FlowStep(seed_views.SeedExportXpubCoordinatorView, button_data_selection=ButtonOption(self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__COORDINATORS)[0], return_data=SettingsConstants.ALL_COORDINATORS[0][0])),
|
||||||
FlowStep(seed_views.SeedExportXpubWarningView, screen_return_value=0),
|
FlowStep(seed_views.SeedExportXpubWarningView, screen_return_value=0),
|
||||||
FlowStep(seed_views.SeedExportXpubDetailsView, screen_return_value=0),
|
FlowStep(seed_views.SeedExportXpubDetailsView, screen_return_value=0),
|
||||||
FlowStep(seed_views.SeedExportXpubQRDisplayView, screen_return_value=0),
|
FlowStep(seed_views.SeedExportXpubQRDisplayView, screen_return_value=0),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from base import FlowTest, FlowStep
|
|||||||
|
|
||||||
from seedsigner.models.settings import Settings
|
from seedsigner.models.settings import Settings
|
||||||
from seedsigner.models.settings_definition import SettingsDefinition, SettingsConstants
|
from seedsigner.models.settings_definition import SettingsDefinition, SettingsConstants
|
||||||
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON
|
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON, ButtonOption
|
||||||
from seedsigner.hardware.microsd import MicroSD
|
from seedsigner.hardware.microsd import MicroSD
|
||||||
from seedsigner.views.view import MainMenuView
|
from seedsigner.views.view import MainMenuView
|
||||||
from seedsigner.views import scan_views, settings_views
|
from seedsigner.views import scan_views, settings_views
|
||||||
@@ -26,8 +26,8 @@ class TestSettingsFlows(FlowTest):
|
|||||||
|
|
||||||
self.run_sequence([
|
self.run_sequence([
|
||||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SETTINGS),
|
FlowStep(MainMenuView, button_data_selection=MainMenuView.SETTINGS),
|
||||||
FlowStep(settings_views.SettingsMenuView, button_data_selection=settings_entry.display_name),
|
FlowStep(settings_views.SettingsMenuView, button_data_selection=ButtonOption(settings_entry.display_name)),
|
||||||
FlowStep(settings_views.SettingsEntryUpdateSelectionView, button_data_selection=settings_entry.get_selection_option_display_name_by_value(SettingsConstants.OPTION__ENABLED)),
|
FlowStep(settings_views.SettingsEntryUpdateSelectionView, button_data_selection=ButtonOption(settings_entry.get_selection_option_display_name_by_value(SettingsConstants.OPTION__ENABLED))),
|
||||||
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=RET_CODE__BACK_BUTTON),
|
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=RET_CODE__BACK_BUTTON),
|
||||||
FlowStep(settings_views.SettingsMenuView),
|
FlowStep(settings_views.SettingsMenuView),
|
||||||
])
|
])
|
||||||
@@ -43,7 +43,7 @@ class TestSettingsFlows(FlowTest):
|
|||||||
|
|
||||||
self.run_sequence([
|
self.run_sequence([
|
||||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.SETTINGS),
|
FlowStep(MainMenuView, button_data_selection=MainMenuView.SETTINGS),
|
||||||
FlowStep(settings_views.SettingsMenuView, button_data_selection=settings_entry.display_name),
|
FlowStep(settings_views.SettingsMenuView, button_data_selection=ButtonOption(settings_entry.display_name)),
|
||||||
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=0), # select/deselect first option
|
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=0), # select/deselect first option
|
||||||
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=1), # select/deselect second option
|
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=1), # select/deselect second option
|
||||||
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=1), # select/deselect second option
|
FlowStep(settings_views.SettingsEntryUpdateSelectionView, screen_return_value=1), # select/deselect second option
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
from base import FlowTest, FlowStep
|
from base import FlowTest, FlowStep
|
||||||
|
|
||||||
from seedsigner.controller import Controller
|
from seedsigner.controller import Controller
|
||||||
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON
|
from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON, ButtonOption
|
||||||
from seedsigner.models.seed import Seed
|
from seedsigner.models.seed import Seed
|
||||||
from seedsigner.models.settings_definition import SettingsConstants, SettingsDefinition
|
from seedsigner.models.settings_definition import SettingsConstants, SettingsDefinition
|
||||||
from seedsigner.views.view import ErrorView, MainMenuView
|
from seedsigner.views.view import ErrorView, MainMenuView
|
||||||
@@ -25,7 +25,7 @@ class TestToolsFlows(FlowTest):
|
|||||||
FlowStep(MainMenuView, button_data_selection=MainMenuView.TOOLS),
|
FlowStep(MainMenuView, button_data_selection=MainMenuView.TOOLS),
|
||||||
FlowStep(tools_views.ToolsMenuView, button_data_selection=tools_views.ToolsMenuView.ADDRESS_EXPLORER),
|
FlowStep(tools_views.ToolsMenuView, button_data_selection=tools_views.ToolsMenuView.ADDRESS_EXPLORER),
|
||||||
FlowStep(tools_views.ToolsAddressExplorerSelectSourceView, screen_return_value=0), # ret 1st onboard seed
|
FlowStep(tools_views.ToolsAddressExplorerSelectSourceView, screen_return_value=0), # ret 1st onboard seed
|
||||||
FlowStep(seed_views.SeedExportXpubScriptTypeView, button_data_selection=SettingsDefinition.get_settings_entry(SettingsConstants.SETTING__SCRIPT_TYPES).get_selection_option_display_name_by_value(SettingsConstants.NATIVE_SEGWIT)),
|
FlowStep(seed_views.SeedExportXpubScriptTypeView, button_data_selection=ButtonOption(SettingsDefinition.get_settings_entry(SettingsConstants.SETTING__SCRIPT_TYPES).get_selection_option_display_name_by_value(SettingsConstants.NATIVE_SEGWIT), return_data=SettingsConstants.NATIVE_SEGWIT)),
|
||||||
FlowStep(tools_views.ToolsAddressExplorerAddressTypeView, button_data_selection=tools_views.ToolsAddressExplorerAddressTypeView.RECEIVE),
|
FlowStep(tools_views.ToolsAddressExplorerAddressTypeView, button_data_selection=tools_views.ToolsAddressExplorerAddressTypeView.RECEIVE),
|
||||||
FlowStep(tools_views.ToolsAddressExplorerAddressListView, screen_return_value=10), # ret NEXT page of addrs
|
FlowStep(tools_views.ToolsAddressExplorerAddressListView, screen_return_value=10), # ret NEXT page of addrs
|
||||||
FlowStep(tools_views.ToolsAddressExplorerAddressListView, screen_return_value=4), # ret a specific addr from the list
|
FlowStep(tools_views.ToolsAddressExplorerAddressListView, screen_return_value=4), # ret a specific addr from the list
|
||||||
@@ -62,7 +62,7 @@ class TestToolsFlows(FlowTest):
|
|||||||
# Finalize the new seed w/passphrase
|
# Finalize the new seed w/passphrase
|
||||||
self.run_sequence(
|
self.run_sequence(
|
||||||
sequence=[
|
sequence=[
|
||||||
FlowStep(seed_views.SeedFinalizeView, button_data_selection=SettingsConstants.LABEL__BIP39_PASSPHRASE),
|
FlowStep(seed_views.SeedFinalizeView, button_data_selection=seed_views.SeedFinalizeView.PASSPHRASE),
|
||||||
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="mypassphrase")),
|
FlowStep(seed_views.SeedAddPassphraseView, screen_return_value=dict(passphrase="mypassphrase")),
|
||||||
FlowStep(seed_views.SeedReviewPassphraseView, button_data_selection=seed_views.SeedReviewPassphraseView.DONE),
|
FlowStep(seed_views.SeedReviewPassphraseView, button_data_selection=seed_views.SeedReviewPassphraseView.DONE),
|
||||||
FlowStep(seed_views.SeedOptionsView, is_redirect=True),
|
FlowStep(seed_views.SeedOptionsView, is_redirect=True),
|
||||||
|
|||||||
Reference in New Issue
Block a user