Skip to content

Commit

Permalink
Merge branch 'develop' into tr_miniscript
Browse files Browse the repository at this point in the history
  • Loading branch information
odudex committed Feb 21, 2025
2 parents 844e19b + 2d2a0df commit 2a6181d
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 83 deletions.
3 changes: 0 additions & 3 deletions src/krux/pages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
UPPERCASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
NUM_SPECIAL_1 = "1234567890 !#$%&'()*"
NUM_SPECIAL_2 = '+,-./:;<=>?@[\\]^_"{|}~'
NUM_SPECIAL_3 = " !#$%&'()*" # NUM_SPECIAL_1 without numbers
DIGITS = "1234567890"

BATTERY_WIDTH = 22
Expand Down Expand Up @@ -171,8 +170,6 @@ def capture_from_keypad(
return ESC_KEY
else:
return ESC_KEY
# remap keypad touch array
pad.map_keys_array(pad.width, pad.height)
elif pad.cur_key_index == pad.go_index:
break
elif pad.cur_key_index == pad.more_index:
Expand Down
7 changes: 5 additions & 2 deletions src/krux/pages/encryption_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ..display import BOTTOM_PROMPT_LINE
from ..krux_settings import t, Settings
from ..encryption import AES_BLOCK_SIZE
from ..themes import theme
from . import (
Page,
Menu,
Expand Down Expand Up @@ -177,7 +178,7 @@ def store_mnemonic_on_memory(self, sd_card=False):

mnemonic_storage = MnemonicStorage()
if mnemonic_id in mnemonic_storage.list_mnemonics(sd_card):
self.flash_text(
self.flash_error(
t("ID already exists") + "\n" + t("Encrypted mnemonic was not stored")
)
del mnemonic_storage
Expand All @@ -193,7 +194,9 @@ def store_mnemonic_on_memory(self, sd_card=False):
)
else:
self.ctx.display.clear()
self.ctx.display.draw_centered_text(t("Failed to store mnemonic"))
self.ctx.display.draw_centered_text(
t("Failed to store mnemonic"), theme.error_color
)
self.ctx.input.wait_for_button()
del mnemonic_storage

Expand Down
128 changes: 59 additions & 69 deletions src/krux/pages/keypads.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,52 @@
)
from ..display import DEFAULT_PADDING, MINIMAL_PADDING, FONT_HEIGHT, FONT_WIDTH

FIXED_KEYS = 3 # 'More' key only appears when there are multiple keysets
FIXED_KEYS = 3 # 'More' key only appears when there are multiple keysets.

KEYPAD_OFFSET = DEFAULT_PADDING + FONT_HEIGHT * 3


class KeypadLayout:
"""Groups layout-related attributes for Keypad."""

def __init__(self, ctx, max_keys_count):
self.width = math.floor(math.sqrt(max_keys_count))
self.height = math.ceil(max_keys_count / self.width)
self.max_index = self.width * self.height

key_h_spacing = ctx.display.width() - DEFAULT_PADDING
key_h_spacing //= self.width
key_v_spacing = (
ctx.display.height() - DEFAULT_PADDING - (DEFAULT_PADDING + FONT_HEIGHT * 3)
)
key_v_spacing //= self.height
self.key_h_spacing, self.key_v_spacing = key_h_spacing, key_v_spacing

self.y_keypad_map = [
y * key_v_spacing + (DEFAULT_PADDING + FONT_HEIGHT * 3)
for y in range(self.height + 1)
]
self.x_keypad_map = [
x * key_h_spacing + MINIMAL_PADDING for x in range(self.width + 1)
]
if ctx.input.touch is not None:
ctx.input.touch.y_regions = self.y_keypad_map
ctx.input.touch.x_regions = self.x_keypad_map


class Keypad:
"""Controls keypad creation and management"""
"""Controls keypad creation and management."""

def __init__(self, ctx, keysets, possible_keys_fn=None):
self.ctx = ctx
self.keysets = keysets
self.keyset_index = 0
self.key_h_spacing, self.key_v_spacing = self.map_keys_array(
self.width, self.height
max_keys_count = (
max(len(keyset) for keyset in keysets)
+ FIXED_KEYS
+ (1 if len(keysets) > 1 else 0)
)
self.layout = KeypadLayout(ctx, max_keys_count)
self.cur_key_index = 0
self.moving_forward = True
self.possible_keys_fn = possible_keys_fn
Expand Down Expand Up @@ -87,62 +120,17 @@ def go_index(self):
"""Returns the index of the "Go" key"""
return self.esc_index + 1

@property
def width(self):
"""Returns the needed width for the current keyset"""
return math.floor(math.sqrt(self.total_keys))

@property
def height(self):
"""Returns the needed height for the current keyset"""
return math.ceil((self.total_keys) / self.width)

@property
def max_index(self):
"""Returns last possible key index"""
return self.width * self.height

@property
def empty_keys(self):
"""Returns dummy keys space needed to always position fixed keys at bottom right"""
return self.max_index - self.total_keys
return self.layout.max_index - self.total_keys

def reset(self):
"""Reset parameters when switching a multi-keypad"""
self.key_h_spacing, self.key_v_spacing = self.map_keys_array(
self.width, self.height
)
self.cur_key_index = 0
self.possible_keys = self.keys
self.moving_forward = True

def map_keys_array(self, width, height):
"""Maps an array of regions for keys to be placed in
Returns horizontal and vertical spacing of keys
"""
self.y_keypad_map = []
self.x_keypad_map = []
key_h_spacing = self.ctx.display.width() - DEFAULT_PADDING
key_h_spacing //= width
key_v_spacing = (
self.ctx.display.height() - DEFAULT_PADDING - self.keypad_offset()
)
key_v_spacing //= height
for y in range(height + 1):
region = y * key_v_spacing + self.keypad_offset()
self.y_keypad_map.append(region)
for x in range(width + 1):
region = x * key_h_spacing + MINIMAL_PADDING
self.x_keypad_map.append(region)
if self.ctx.input.touch is not None:
self.ctx.input.touch.y_regions = self.y_keypad_map
self.ctx.input.touch.x_regions = self.x_keypad_map
return key_h_spacing, key_v_spacing

def keypad_offset(self):
"""Returns keypad start position"""
return DEFAULT_PADDING + FONT_HEIGHT * 3

def compute_possible_keys(self, buffer):
"""Computes the possible keys for the current keypad"""
if self.possible_keys_fn is not None:
Expand All @@ -151,9 +139,9 @@ def compute_possible_keys(self, buffer):
def draw_keys(self):
"""Draws keypad on the screen"""
key_index = 0
for y in self.y_keypad_map[:-1]:
offset_y = y + (self.key_v_spacing - FONT_HEIGHT) // 2
for x in self.x_keypad_map[:-1]:
for y in self.layout.y_keypad_map[:-1]:
offset_y = y + (self.layout.key_v_spacing - FONT_HEIGHT) // 2
for x in self.layout.x_keypad_map[:-1]:
key = None
custom_color = None
if key_index < len(self.keys):
Expand All @@ -170,10 +158,12 @@ def draw_keys(self):
elif key_index == self.more_index and len(self.keysets) > 1:
key = "ABC"
custom_color = theme.toggle_color

if key is not None:
offset_x = x
key_offset_x = (self.key_h_spacing - lcd.string_width_px(key)) // 2
key_offset_x += offset_x
key_offset_x = (
self.layout.key_h_spacing - lcd.string_width_px(key)
) // 2 + offset_x
if (
key_index < len(self.keys)
and self.keys[key_index] not in self.possible_keys
Expand All @@ -187,8 +177,8 @@ def draw_keys(self):
self.ctx.display.outline(
offset_x + 1,
y + 1,
self.key_h_spacing - 2,
self.key_v_spacing - 2,
self.layout.key_h_spacing - 2,
self.layout.key_v_spacing - 2,
theme.frame_color,
)
if custom_color:
Expand All @@ -205,15 +195,15 @@ def draw_keys(self):
self.ctx.display.outline(
offset_x + 1,
y + 1,
self.key_h_spacing - 2,
self.key_v_spacing - 2,
self.layout.key_h_spacing - 2,
self.layout.key_v_spacing - 2,
)
else:
self.ctx.display.outline(
offset_x - 2,
y,
self.key_h_spacing + 1,
self.key_v_spacing - 1,
self.layout.key_h_spacing + 1,
self.layout.key_v_spacing - 1,
)
key_index += 1

Expand All @@ -231,7 +221,7 @@ def draw_keyset_index(self):
color = theme.fg_color if i == self.keyset_index else theme.frame_color
self.ctx.display.fill_rectangle(
x_offset + (bar_length + bar_padding) * i,
self.y_keypad_map[-1] + 2,
self.layout.y_keypad_map[-1] + 2,
bar_length,
bar_height,
color,
Expand All @@ -244,15 +234,15 @@ def get_valid_index(self):
and self.keys[self.cur_key_index] not in self.possible_keys
):
if self.moving_forward:
self.cur_key_index = (self.cur_key_index + 1) % self.max_index
self.cur_key_index = (self.cur_key_index + 1) % self.layout.max_index
# Jump over empty keys
if 0 <= (self.cur_key_index - len(self.keys)) < self.empty_keys:
self.cur_key_index += self.empty_keys
else:
if self.cur_key_index:
self.cur_key_index -= 1
else:
self.cur_key_index = self.max_index - 1
self.cur_key_index = self.layout.max_index - 1
return self.cur_key_index

def touch_to_physical(self):
Expand All @@ -262,7 +252,7 @@ def touch_to_physical(self):
if self.cur_key_index < len(self.keys):
if self.keys[self.cur_key_index] in self.possible_keys:
actual_button = BUTTON_ENTER
elif self.cur_key_index < self.max_index:
elif self.cur_key_index < self.layout.max_index:
actual_button = BUTTON_ENTER
else:
self.cur_key_index = 0
Expand Down Expand Up @@ -296,16 +286,16 @@ def navigate(self, btn):
def _clean_keypad_area(self):
self.ctx.display.fill_rectangle(
0,
self.keypad_offset(),
KEYPAD_OFFSET,
self.ctx.display.width(),
self.ctx.display.height() - self.keypad_offset(),
self.ctx.display.height() - KEYPAD_OFFSET,
theme.bg_color,
)

def _next_key(self):
"""Increments cursor when page button is pressed"""
self.moving_forward = True
self.cur_key_index = (self.cur_key_index + 1) % self.max_index
self.cur_key_index = (self.cur_key_index + 1) % self.layout.max_index
if self.cur_key_index == len(self.keys):
self.cur_key_index += self.empty_keys

Expand All @@ -315,7 +305,7 @@ def _previous_key(self):
if self.cur_key_index == len(self.keys) + self.empty_keys:
self.cur_key_index = len(self.keys) - 1
else:
self.cur_key_index = (self.cur_key_index - 1) % self.max_index
self.cur_key_index = (self.cur_key_index - 1) % self.layout.max_index

def next_keyset(self):
"""Change keys for the next keyset"""
Expand Down
6 changes: 3 additions & 3 deletions src/krux/pages/settings_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
DIGITS,
LETTERS,
UPPERCASE_LETTERS,
NUM_SPECIAL_1,
NUM_SPECIAL_2,
NUM_SPECIAL_3,
MENU_CONTINUE,
MENU_EXIT,
ESC_KEY,
Expand Down Expand Up @@ -159,14 +159,14 @@ def enter_modify_tc_code(self):
while len(tamper_check_code) < 6:
tamper_check_code = self.capture_from_keypad(
t("Tamper Check Code"),
[DIGITS, LETTERS, UPPERCASE_LETTERS, NUM_SPECIAL_2, NUM_SPECIAL_3],
[NUM_SPECIAL_1, LETTERS, UPPERCASE_LETTERS, NUM_SPECIAL_2],
)
if tamper_check_code == ESC_KEY:
return MENU_CONTINUE
while len(tc_code_confirm) < 6:
tc_code_confirm = self.capture_from_keypad(
t("Confirm Tamper Check Code"),
[DIGITS, LETTERS, UPPERCASE_LETTERS, NUM_SPECIAL_2, NUM_SPECIAL_3],
[NUM_SPECIAL_1, LETTERS, UPPERCASE_LETTERS, NUM_SPECIAL_2],
)
if tc_code_confirm == ESC_KEY:
return MENU_CONTINUE
Expand Down
5 changes: 2 additions & 3 deletions src/krux/pages/tc_code_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
from . import (
Page,
ESC_KEY,
DIGITS,
LETTERS,
UPPERCASE_LETTERS,
NUM_SPECIAL_1,
NUM_SPECIAL_2,
NUM_SPECIAL_3,
)
from ..krux_settings import t, TC_CODE_PATH, TC_CODE_PBKDF2_ITERATIONS

Expand All @@ -50,7 +49,7 @@ def capture(self, changing_tc_code=False, return_hash=False):
else t("Tamper Check Code")
)
tc_code = self.capture_from_keypad(
label, [DIGITS, LETTERS, UPPERCASE_LETTERS, NUM_SPECIAL_2, NUM_SPECIAL_3]
label, [NUM_SPECIAL_1, LETTERS, UPPERCASE_LETTERS, NUM_SPECIAL_2]
)
if tc_code == ESC_KEY:
return False
Expand Down
Loading

0 comments on commit 2a6181d

Please sign in to comment.