Skip to content

Commit b99df74

Browse files
authored
Merge pull request #664 from kdmukai/keyboard_space_del_icons
Add SPACE, DEL icons to `Keyboard`; various UI consistency tweaks
2 parents 5e806c2 + c0fe676 commit b99df74

File tree

12 files changed

+120
-101
lines changed

12 files changed

+120
-101
lines changed

l10n/messages.pot

+9-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ msgid ""
88
msgstr ""
99
"Project-Id-Version: seedsigner 0.8.5-rc1\n"
1010
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
11-
"POT-Creation-Date: 2025-01-15 10:45-0600\n"
11+
"POT-Creation-Date: 2025-01-19 10:20-0600\n"
1212
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414
"Language-Team: LANGUAGE <[email protected]>\n"
@@ -36,16 +36,6 @@ msgstr ""
3636
msgid "sats"
3737
msgstr ""
3838

39-
#. The abbreviated label for the special key <del> on a standard keyboard.
40-
#: src/seedsigner/gui/keyboard.py
41-
msgid "del"
42-
msgstr ""
43-
44-
#. The abbreviated label for the special key <space> on a standard keyboard.
45-
#: src/seedsigner/gui/keyboard.py
46-
msgid "space"
47-
msgstr ""
48-
4939
#: src/seedsigner/gui/toast.py
5040
msgid ""
5141
"You can remove\n"
@@ -215,7 +205,7 @@ msgstr ""
215205
msgid "OK"
216206
msgstr ""
217207

218-
#: src/seedsigner/gui/screens/screen.py src/seedsigner/views/psbt_views.py
208+
#: src/seedsigner/gui/screens/screen.py
219209
msgid "Caution"
220210
msgstr ""
221211

@@ -901,18 +891,16 @@ msgstr ""
901891

902892
#. Variable is either "change" or "self-transfer".
903893
#: src/seedsigner/views/psbt_views.py
904-
msgid ""
905-
"PSBT's {} address could not be verified with your multisig wallet "
906-
"descriptor."
894+
msgid "PSBT's {} address could not be verified from wallet descriptor."
907895
msgstr ""
908896

897+
#. Variable is either "change" or "self-transfer".
909898
#: src/seedsigner/views/psbt_views.py
910-
msgid "Suspicious PSBT"
899+
msgid "PSBT's {} address could not be generated from your seed."
911900
msgstr ""
912901

913-
#. Variable is either "change" or "self-transfer".
914902
#: src/seedsigner/views/psbt_views.py
915-
msgid "PSBT's {} address could not be generated from your seed."
903+
msgid "Suspicious PSBT"
916904
msgstr ""
917905

918906
#: src/seedsigner/views/psbt_views.py
@@ -1459,10 +1447,13 @@ msgstr ""
14591447
msgid "Back to Main Menu"
14601448
msgstr ""
14611449

1450+
#. The network setting (mainnet/testnet/regtest) doesn't match the provided
1451+
#. derivation path
14621452
#: src/seedsigner/views/view.py
14631453
msgid "Network Mismatch"
14641454
msgstr ""
14651455

1456+
#. Button option to alter a setting
14661457
#: src/seedsigner/views/view.py
14671458
msgid "Change Setting"
14681459
msgstr ""

src/seedsigner/gui/components.py

+5-15
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,9 @@ class SeedSignerIconConstants:
217217

218218
# Messaging icons
219219
INFO = "\ue912"
220-
ERROR = "\ue913"
221-
SUCCESS = "\ue914"
222-
WARNING = "\ue915"
220+
SUCCESS = "\ue913"
221+
WARNING = "\ue914"
222+
ERROR = "\ue915"
223223

224224
# Informational icons
225225
ADDRESS = "\ue916"
@@ -241,8 +241,9 @@ class SeedSignerIconConstants:
241241
DELETE = "\ue922"
242242
SPACE = "\ue923"
243243

244+
# Must be updated whenever new icons are added. See usage in `Icon` class below.
244245
MIN_VALUE = SCAN
245-
MAX_VALUE = QRCODE
246+
MAX_VALUE = SPACE
246247

247248

248249

@@ -280,17 +281,6 @@ def calc_text_centering(font: ImageFont,
280281

281282

282283

283-
def load_icon(icon_name: str, load_selected_variant: bool = False):
284-
icon_url = os.path.join(pathlib.Path(__file__).parent.resolve(), "..", "resources", "icons", icon_name)
285-
icon = Image.open(icon_url + ".png").convert("RGB")
286-
if not load_selected_variant:
287-
return icon
288-
else:
289-
icon_selected = Image.open(icon_url + "_selected.png").convert("RGB")
290-
return (icon, icon_selected)
291-
292-
293-
294284
def load_image(image_name: str) -> Image.Image:
295285
image_url = os.path.join(pathlib.Path(__file__).parent.resolve(), "..", "resources", "img", image_name)
296286
image = Image.open(image_url).convert("RGB")

src/seedsigner/gui/keyboard.py

+32-29
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Tuple
44
from gettext import gettext as _
55

6-
from seedsigner.gui.components import Fonts, GUIConstants
6+
from seedsigner.gui.components import Fonts, GUIConstants, SeedSignerIconConstants
77
from seedsigner.hardware.buttons import HardwareButtonsConstants
88

99

@@ -30,58 +30,55 @@ class Keyboard:
3030
ENTER_RIGHT = "enter_right"
3131

3232
REGULAR_KEY_FONT = "regular"
33-
COMPACT_KEY_FONT = "compact"
33+
ICON_KEY_FONT = GUIConstants.ICON_FONT_NAME__SEEDSIGNER
3434

35-
# TRANSLATOR_NOTE: The abbreviated label for the special key <del> on a standard keyboard.
36-
del_label = _("del")
3735
KEY_BACKSPACE = {
3836
"code": "DEL",
39-
"letter": del_label,
40-
"font": COMPACT_KEY_FONT,
37+
"letter": SeedSignerIconConstants.DELETE,
38+
"font": ICON_KEY_FONT,
4139
"size": 2,
4240
}
43-
# TRANSLATOR_NOTE: The abbreviated label for the special key <space> on a standard keyboard.
44-
space_label = _("space")
41+
4542
KEY_SPACE = {
4643
"code": "SPACE",
47-
"letter": space_label,
48-
"font": COMPACT_KEY_FONT,
44+
"letter": SeedSignerIconConstants.SPACE,
45+
"font": ICON_KEY_FONT,
4946
"size": 1,
5047
}
5148
KEY_SPACE_2 = {
5249
"code": "SPACE",
53-
"letter": space_label,
54-
"font": COMPACT_KEY_FONT,
50+
"letter": SeedSignerIconConstants.SPACE,
51+
"font": ICON_KEY_FONT,
5552
"size": 2,
5653
}
5754
KEY_SPACE_3 = {
5855
"code": "SPACE",
59-
"letter": space_label,
60-
"font": COMPACT_KEY_FONT,
56+
"letter": SeedSignerIconConstants.SPACE,
57+
"font": ICON_KEY_FONT,
6158
"size": 3,
6259
}
6360
KEY_SPACE_4 = {
6461
"code": "SPACE",
65-
"letter": space_label,
66-
"font": COMPACT_KEY_FONT,
62+
"letter": SeedSignerIconConstants.SPACE,
63+
"font": ICON_KEY_FONT,
6764
"size": 4,
6865
}
6966
KEY_SPACE_5 = {
7067
"code": "SPACE",
71-
"letter": space_label,
72-
"font": COMPACT_KEY_FONT,
68+
"letter": SeedSignerIconConstants.SPACE,
69+
"font": ICON_KEY_FONT,
7370
"size": 5,
7471
}
7572
KEY_CURSOR_LEFT = {
7673
"code": "CURSOR_LEFT",
77-
"letter": "<",
78-
"font": REGULAR_KEY_FONT,
74+
"letter": SeedSignerIconConstants.CHEVRON_LEFT,
75+
"font": ICON_KEY_FONT,
7976
"size": 1,
8077
}
8178
KEY_CURSOR_RIGHT = {
8279
"code": "CURSOR_RIGHT",
83-
"letter": ">",
84-
"font": REGULAR_KEY_FONT,
80+
"letter": SeedSignerIconConstants.CHEVRON_RIGHT,
81+
"font": ICON_KEY_FONT,
8582
"size": 1,
8683
}
8784
KEY_PREVIOUS_PAGE = {
@@ -123,9 +120,11 @@ def __post_init__(self):
123120

124121
def render_key(self):
125122
font = self.keyboard.font
123+
text_height = self.keyboard.text_height
126124
if self.is_additional_key:
127-
if Keyboard.ADDITIONAL_KEYS[self.code]["font"] == Keyboard.COMPACT_KEY_FONT:
128-
font = self.keyboard.additonal_key_compact_font
125+
if Keyboard.ADDITIONAL_KEYS[self.code]["font"] == Keyboard.ICON_KEY_FONT:
126+
font = self.keyboard.icon_key_font
127+
text_height = self.keyboard.icon_key_height
129128

130129
outline_color = "#333"
131130
if not self.is_active:
@@ -159,15 +158,12 @@ def render_key(self):
159158
radius=4
160159
)
161160

162-
# Fixed-width fonts will all have same height, ignoring below baseline (e.g. "Q" or "q")
163-
(left, top, right, bottom) = font.getbbox("X", anchor="ls")
164-
text_height = -1 * top
165161
self.keyboard.draw.text(
166162
(
167163
self.screen_x + int(self.keyboard.key_width * self.size / 2),
168164
self.screen_y + self.keyboard.key_height - int((self.keyboard.key_height - text_height)/2)
169165
),
170-
_(self.letter),
166+
self.letter,
171167
fill=font_color,
172168
font=font,
173169
anchor="ms"
@@ -217,8 +213,15 @@ def __init__(self,
217213

218214
# Set up the rendering and state params
219215
self.active_keys = list(self.charset)
216+
self.icon_key_font = Fonts.get_font(GUIConstants.ICON_FONT_NAME__SEEDSIGNER, 26)
217+
218+
# Fixed-width fonts will all have same height, ignoring below baseline (e.g. "Q" or "q")
219+
(left, top, right, bottom) = self.font.getbbox("X", anchor="ls")
220+
self.text_height = -1 * top
221+
222+
(left, top, right, bottom) = self.icon_key_font.getbbox(SeedSignerIconConstants.DELETE + SeedSignerIconConstants.SPACE, anchor="ls")
223+
self.icon_key_height = -1 * top
220224

221-
self.additonal_key_compact_font = Fonts.get_font("RobotoCondensed-Bold", 18)
222225
self.x_start = rect[0]
223226
self.y_start = rect[1]
224227
self.x_gap = 2

src/seedsigner/gui/screens/screen.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def __post_init__(self):
309309
if len(self.button_data) == 1:
310310
button_list_height = button_height
311311
else:
312-
button_list_height = (len(self.button_data) * button_height) + (GUIConstants.COMPONENT_PADDING * (len(self.button_data) - 1))
312+
button_list_height = (len(self.button_data) * button_height) + (GUIConstants.LIST_ITEM_PADDING * (len(self.button_data) - 1))
313313

314314
if self.is_bottom_list:
315315
button_list_y = self.canvas_height - (button_list_height + GUIConstants.EDGE_PADDING)
@@ -1013,21 +1013,38 @@ def __post_init__(self):
10131013

10141014
@dataclass
10151015
class WarningScreen(WarningEdgesMixin, LargeIconStatusScreen):
1016+
"""
1017+
Exclamation point icon + yellow WARNING color
1018+
"""
10161019
title: str = _mft("Caution")
10171020
status_icon_name: str = SeedSignerIconConstants.WARNING
1018-
status_color: str = "yellow"
1021+
status_color: str = GUIConstants.WARNING_COLOR
10191022
status_headline: str = _mft("Privacy Leak!") # The colored text under the alert icon
10201023
button_data: list = field(default_factory=lambda: [ButtonOption("I Understand")])
10211024

10221025

10231026

10241027
@dataclass
10251028
class DireWarningScreen(WarningScreen):
1029+
"""
1030+
Exclamation point icon + orange DIRE_WARNING color
1031+
"""
10261032
status_headline: str = _mft("Classified Info!") # The colored text under the alert icon
10271033
status_color: str = GUIConstants.DIRE_WARNING_COLOR
10281034

10291035

10301036

1037+
@dataclass
1038+
class ErrorScreen(WarningScreen):
1039+
"""
1040+
X icon + red ERROR color
1041+
"""
1042+
title: str = _mft("Error")
1043+
status_icon_name: str = SeedSignerIconConstants.ERROR
1044+
status_color: str = GUIConstants.ERROR_COLOR
1045+
1046+
1047+
10311048
@dataclass
10321049
class ResetScreen(BaseTopNavScreen):
10331050
def __post_init__(self):

src/seedsigner/gui/screens/settings_screens.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import List
77

88
from seedsigner.helpers.l10n import mark_for_translation as _mft
9-
from seedsigner.gui.components import Button, CheckboxButton, CheckedSelectionButton, FontAwesomeIconConstants, Fonts, GUIConstants, Icon, IconButton, IconTextLine, TextArea
9+
from seedsigner.gui.components import Button, CheckboxButton, CheckedSelectionButton, FontAwesomeIconConstants, Fonts, GUIConstants, Icon, IconButton, IconTextLine, SeedSignerIconConstants, TextArea
1010
from seedsigner.gui.screens.scan_screens import ScanScreen
1111
from seedsigner.gui.screens.screen import BaseScreen, BaseTopNavScreen, ButtonListScreen, ButtonOption
1212
from seedsigner.hardware.buttons import HardwareButtonsConstants
@@ -82,7 +82,7 @@ def __post_init__(self):
8282
self.components.append(self.joystick_click_button)
8383

8484
self.joystick_up_button = IconButton(
85-
icon_name=FontAwesomeIconConstants.ANGLE_UP,
85+
icon_name=SeedSignerIconConstants.CHEVRON_UP,
8686
icon_size=GUIConstants.ICON_INLINE_FONT_SIZE,
8787
width=input_button_width,
8888
height=input_button_height,
@@ -93,7 +93,7 @@ def __post_init__(self):
9393
self.components.append(self.joystick_up_button)
9494

9595
self.joystick_down_button = IconButton(
96-
icon_name=FontAwesomeIconConstants.ANGLE_DOWN,
96+
icon_name=SeedSignerIconConstants.CHEVRON_DOWN,
9797
icon_size=GUIConstants.ICON_INLINE_FONT_SIZE,
9898
width=input_button_width,
9999
height=input_button_height,
@@ -104,9 +104,8 @@ def __post_init__(self):
104104
self.components.append(self.joystick_down_button)
105105

106106
self.joystick_left_button = IconButton(
107-
text=FontAwesomeIconConstants.ANGLE_LEFT,
108-
font_name=GUIConstants.ICON_FONT_NAME__FONT_AWESOME,
109-
font_size=GUIConstants.ICON_INLINE_FONT_SIZE,
107+
icon_name=SeedSignerIconConstants.CHEVRON_LEFT,
108+
icon_size=GUIConstants.ICON_INLINE_FONT_SIZE,
110109
width=input_button_width,
111110
height=input_button_height,
112111
screen_x=dpad_center_x - input_button_width - GUIConstants.COMPONENT_PADDING,
@@ -116,7 +115,7 @@ def __post_init__(self):
116115
self.components.append(self.joystick_left_button)
117116

118117
self.joystick_right_button = IconButton(
119-
icon_name=FontAwesomeIconConstants.ANGLE_RIGHT,
118+
icon_name=SeedSignerIconConstants.CHEVRON_RIGHT,
120119
icon_size=GUIConstants.ICON_INLINE_FONT_SIZE,
121120
width=input_button_width,
122121
height=input_button_height,

src/seedsigner/gui/screens/tools_screens.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def __post_init__(self):
140140
self.rows = 3
141141
self.cols = 3
142142
self.keyboard_font_name = GUIConstants.ICON_FONT_NAME__FONT_AWESOME
143-
self.keyboard_font_size = None # Force auto-scaling to Key height
143+
self.keyboard_font_size = 36
144144
self.keys_charset = "".join([
145145
FontAwesomeIconConstants.DICE_ONE,
146146
FontAwesomeIconConstants.DICE_TWO,

src/seedsigner/views/psbt_views.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -460,16 +460,14 @@ def __init__(self, is_change: bool = True, is_multisig: bool = False):
460460

461461
def run(self):
462462
if self.is_multisig:
463-
title = _("Caution")
464463
# TRANSLATOR_NOTE: Variable is either "change" or "self-transfer".
465-
text = _("PSBT's {} address could not be verified with your multisig wallet descriptor.").format(_("change") if self.is_change else _("self-transfer"))
464+
text = _("PSBT's {} address could not be verified from wallet descriptor.").format(_("change") if self.is_change else _("self-transfer"))
466465
else:
467-
title = _("Suspicious PSBT")
468466
# TRANSLATOR_NOTE: Variable is either "change" or "self-transfer".
469467
text = _("PSBT's {} address could not be generated from your seed.").format(_("change") if self.is_change else _("self-transfer"))
470468

471469
DireWarningScreen(
472-
title=title,
470+
title=_("Suspicious PSBT"),
473471
status_headline=_("Address Verification Failed"),
474472
text=text,
475473
button_data=[ButtonOption("Discard PSBT")],

0 commit comments

Comments
 (0)