From b5c0b3e7682b06496c1bc5bfece5ca6ddee8d2a2 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Sat, 31 Jul 2021 23:03:13 -0500 Subject: [PATCH] Interim commit --- README.md | 20 ++- requirements.txt | 1 + src/seedsigner/helpers/keyboard.py | 164 ++++++++++++++++----- src/seedsigner/views/seed_tools_view.py | 182 +++++++++++++++--------- 4 files changed, 262 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index ed89842a..e48bd50a 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Exit and reboot when prompted within the raspi-config interface. Install these dependencies: ``` -sudo apt-get update && sudo apt-get install -y wiringpi python3-pip python3-numpy python-pil libopenjp2-7 ttf-mscorefonts-installer git python3-opencv libzbar0 python3-picamera +sudo apt-get update && sudo apt-get install -y wiringpi python3-pip python3-numpy python-pil libopenjp2-7 ttf-mscorefonts-installer git python3-opencv libzbar0 python3-picamera libatlas-base-dev ``` Install the [C library for Broadcom BCM 2835](http://www.airspayce.com/mikem/bcm2835/): @@ -116,6 +116,24 @@ cd .. rm bcm2835-1.60.tar.gz ``` +Set up virtualenv +``` +pip3 install virtualenvwrapper +``` + +Edit your bash profile with `nano ~/.profile` and add the following to the end: +``` +export WORKON_HOME=$HOME/.envs +export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 +source /home/pi/.local/bin/virtualenvwrapper.sh +``` +Then `CTRL-X` and `y` to exit and save changes. + +Now create the python virtualenv for SeedSigner: +``` +mkvirtualenv --python=python3 seedsigner-env +``` + Download SeedSigner ``` git clone https://github.com/SeedSigner/seedsigner diff --git a/requirements.txt b/requirements.txt index 27f64fed..e726fe81 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ embit==0.4.3 +numpy==1.21.1 picamera==1.13 Pillow==8.2.0 pyzbar==0.1.8 diff --git a/src/seedsigner/helpers/keyboard.py b/src/seedsigner/helpers/keyboard.py index 880049ce..43c66bb4 100644 --- a/src/seedsigner/helpers/keyboard.py +++ b/src/seedsigner/helpers/keyboard.py @@ -25,16 +25,59 @@ class Keyboard: COMPACT_KEY_FONT = "compact" KEY_BACKSPACE = { + "code": "DEL", "letter": "del", "font": COMPACT_KEY_FONT, "size": 2, } + KEY_SPACE = { + "code": "SPACE", + "letter": "space", + "font": COMPACT_KEY_FONT, + "size": 1, + } + KEY_SPACE_3 = { + "code": "SPACE", + "letter": "space", + "font": COMPACT_KEY_FONT, + "size": 3, + } + KEY_SPACE_4 = { + "code": "SPACE", + "letter": "space", + "font": COMPACT_KEY_FONT, + "size": 4, + } + KEY_SPACE_5 = { + "code": "SPACE", + "letter": "space", + "font": COMPACT_KEY_FONT, + "size": 5, + } + KEY_CURSOR_LEFT = { + "code": "CURSOR_LEFT", + "letter": "<", + "font": REGULAR_KEY_FONT, + "size": 1, + } + KEY_CURSOR_RIGHT = { + "code": "CURSOR_RIGHT", + "letter": ">", + "font": REGULAR_KEY_FONT, + "size": 1, + } KEY_PREVIOUS_PAGE = { - "letter": "prev" + "code": "PREV", + "letter": "<", + "font": REGULAR_KEY_FONT, + "size": 1, } ADDITIONAL_KEYS = { - KEY_BACKSPACE["letter"]: KEY_BACKSPACE, - KEY_PREVIOUS_PAGE["letter"]: KEY_PREVIOUS_PAGE, + KEY_SPACE["code"]: KEY_SPACE, + KEY_BACKSPACE["code"]: KEY_BACKSPACE, + KEY_CURSOR_LEFT["code"]: KEY_CURSOR_LEFT, + KEY_CURSOR_RIGHT["code"]: KEY_CURSOR_RIGHT, + KEY_PREVIOUS_PAGE["code"]: KEY_PREVIOUS_PAGE, } @dataclass @@ -44,19 +87,24 @@ class Keyboard: individual key in the keyboard and its state. Attrs with defaults must be listed last. """ - letter: str + letter: str # display value screen_x: int screen_y: int keyboard: any + code: str = None # key/code returned on press (e.g. "x" or "cursor_left") size: int = 1 is_active: bool = True is_selected: bool = False is_additional_key: bool = False + def __post_init__(self): + if not self.code: + self.code = self.letter + def render_key(self): font = self.keyboard.font - if self.letter in Keyboard.ADDITIONAL_KEYS: - if Keyboard.ADDITIONAL_KEYS[self.letter]["font"] == Keyboard.COMPACT_KEY_FONT: + if self.is_additional_key: + if Keyboard.ADDITIONAL_KEYS[self.code]["font"] == Keyboard.COMPACT_KEY_FONT: font = self.keyboard.additonal_key_compact_font outline_color = "#333" @@ -70,10 +118,13 @@ class Keyboard: rect_color = self.keyboard.highlight_color # Render solid background with the UI's hero color font_color = self.keyboard.background_color else: - rect_color = self.keyboard.background_color + if self.is_additional_key: + rect_color = "#111" + else: + rect_color = self.keyboard.background_color font_color = self.keyboard.highlight_color - self.keyboard.draw.rectangle((self.screen_x, self.screen_y, self.screen_x + self.keyboard.x_width * self.size, self.screen_y + self.keyboard.y_height), outline=outline_color, fill=rect_color) + self.keyboard.draw.rounded_rectangle((self.screen_x, self.screen_y, self.screen_x + self.keyboard.x_width * self.size - 1, self.screen_y + self.keyboard.y_height), outline=outline_color, fill=rect_color, radius=4) tw, th = self.keyboard.draw.textsize(self.letter, font=font) self.keyboard.draw.text((self.screen_x + int((self.keyboard.x_width * self.size - tw) / 2), self.screen_y + int((self.keyboard.y_height - th)/2)), self.letter, fill=font_color, font=font) @@ -161,13 +212,14 @@ class Keyboard: for additional_key in additional_keys: self.keys[-1].append(self.Key( letter=additional_key["letter"], + code=additional_key["code"], screen_x=cur_x, screen_y=cur_y, keyboard=self, size=additional_key["size"], is_additional_key=True, )) - cur_x += self.x_width + self.x_gap + cur_x += self.x_width * additional_key["size"] + self.x_gap if render_now: # Render the keys @@ -181,7 +233,7 @@ class Keyboard: self.active_keys = active_keys for i, row_keys in enumerate(self.keys): for j, key in enumerate(row_keys): - if key.letter not in self.active_keys and key.letter not in Keyboard.ADDITIONAL_KEYS: + if key.code not in self.active_keys and not key.is_additional_key: # Note: ADDITIONAL_KEYS are never deactivated. key.is_active = False else: @@ -201,7 +253,7 @@ class Keyboard: for i, row_keys in enumerate(self.keys): for j, key in enumerate(row_keys): - if selected_letter and key.letter == selected_letter: + if selected_letter and key.code == selected_letter: key.is_selected = True self.selected_key["y"] = i self.selected_key["x"] = j @@ -343,7 +395,7 @@ class Keyboard: key.is_selected = True key.render_key() - return key.letter + return key.code def set_selected_key(self, selected_letter): @@ -353,7 +405,7 @@ class Keyboard: # Find the new selected_key for i, row_keys in enumerate(self.keys): for j, key in enumerate(row_keys): - if selected_letter and key.letter == selected_letter: + if selected_letter and key.code == selected_letter: key.is_selected = True self.selected_key["y"] = i self.selected_key["x"] = j @@ -380,21 +432,28 @@ class Keyboard: def get_selected_key(self): - return self.keys[self.selected_key["y"]][self.selected_key["x"]].letter + return self.keys[self.selected_key["y"]][self.selected_key["x"]].code + + +class TextEntryDisplayConstants: + CURSOR_MODE__BAR = "bar" + CURSOR_MODE__BLOCK = "block" + @dataclass -class TextEntryDisplay: +class TextEntryDisplay(TextEntryDisplayConstants): draw: any rect: (int,int,int,int) font: any font_color: any + cursor_mode: str = TextEntryDisplayConstants.CURSOR_MODE__BLOCK is_centered: bool = True has_outline: bool = False cur_text: str = " " - def render(self, cur_text=None): + def render(self, cur_text=None, cursor_position=None): """ Render the live text entry display """ if cur_text: self.cur_text = cur_text @@ -403,28 +462,63 @@ class TextEntryDisplay: else: self.draw.rectangle(self.rect, fill="black") - cursor_block_width = 18 - cursor_block_height = 33 + if self.cursor_mode == TextEntryDisplay.CURSOR_MODE__BLOCK: + cursor_block_width = 18 + cursor_block_height = 33 + + # Draw n-1 of the selected letters + tw, th = self.font.getsize(self.cur_text[:-1]) + if self.is_centered: + word_offset = self.rect[0] + int(self.rect[2] - self.rect[0] - tw - cursor_block_width)/2 + else: + word_offset = self.rect[0] + 3 + cursor_block_offset = word_offset + tw - 1 + if cursor_block_offset == self.rect[0]: + cursor_block_offset = self.rect[0] + 1 + + end_pos_x = cursor_block_offset + cursor_block_width + if end_pos_x >= self.rect[2]: + # Shift the display left + cursor_block_offset -= end_pos_x - self.rect[2] + 1 + word_offset -= end_pos_x - self.rect[2] + 1 + + self.draw.text((word_offset, self.rect[1] + 3), self.cur_text[:-1], fill=self.font_color, font=self.font) + + # Draw the highlighted cursor block + self.draw.rectangle((cursor_block_offset, self.rect[1] + 1, cursor_block_offset + cursor_block_width, self.rect[3] - 1), fill="#111") + self.draw.text((cursor_block_offset + 1, self.rect[1] + 3), self.cur_text[-1], fill=self.font_color, font=self.font) - # Draw n-1 of the selected letters - tw, th = self.font.getsize(self.cur_text[:-1]) - if self.is_centered: - word_offset = self.rect[0] + int(self.rect[2] - self.rect[0] - tw - cursor_block_width)/2 else: - word_offset = self.rect[0] + 3 - cursor_block_offset = word_offset + tw - 1 - if cursor_block_offset == self.rect[0]: - cursor_block_offset = self.rect[0] + 1 + cursor_bar_offset = 1 + cursor_bar_serif_half_width = 4 + tw, th = self.font.getsize(self.cur_text) + if self.is_centered: + word_offset = self.rect[0] + int(self.rect[2] - self.rect[0] - tw)/2 + else: + word_offset = self.rect[0] + 3 - end_pos_x = cursor_block_offset + cursor_block_width - if end_pos_x >= self.rect[2]: - # Shift the display left - cursor_block_offset -= end_pos_x - self.rect[2] + 1 - word_offset -= end_pos_x - self.rect[2] + 1 + end_pos_x = word_offset + tw + cursor_bar_serif_half_width + 3 + if end_pos_x >= self.rect[2]: + # Shift the display left + word_offset -= end_pos_x - self.rect[2] + 1 - self.draw.text((word_offset, self.rect[1] + 3), self.cur_text[:-1], fill=self.font_color, font=self.font) + # Draw the cursor bar + if cursor_position is None: + cursor_position = len(self.cur_text) + if cursor_position == 0: + cursor_bar_x = self.rect[0] + cursor_bar_offset + cursor_bar_serif_half_width + elif cursor_position >= len(self.cur_text): + cursor_bar_x = word_offset + tw + else: + tw, th = self.font.getsize(self.cur_text[:cursor_position]) + cursor_bar_x = word_offset + tw + cursor_bar_offset + + self.draw.text((word_offset, self.rect[1] + 3), self.cur_text, fill=self.font_color, font=self.font) + + # Render as an "I" bar + cursor_bar_color = "#ccc" + self.draw.line((cursor_bar_x, self.rect[1] + 3, cursor_bar_x, self.rect[3] - 3), fill=cursor_bar_color) + self.draw.line((cursor_bar_x - cursor_bar_serif_half_width, self.rect[1] + 3, cursor_bar_x + cursor_bar_serif_half_width, self.rect[1] + 3), fill=cursor_bar_color) + self.draw.line((cursor_bar_x - cursor_bar_serif_half_width, self.rect[3] - 3, cursor_bar_x + cursor_bar_serif_half_width, self.rect[3] - 3), fill=cursor_bar_color) - # Draw the highlighted cursor block - self.draw.rectangle((cursor_block_offset, self.rect[1] + 1, cursor_block_offset + cursor_block_width, self.rect[3] - 1), fill="#111") - self.draw.text((cursor_block_offset + 1, self.rect[1] + 3), self.cur_text[-1], fill=self.font_color, font=self.font) diff --git a/src/seedsigner/views/seed_tools_view.py b/src/seedsigner/views/seed_tools_view.py index 33fba4b4..e299a9d7 100644 --- a/src/seedsigner/views/seed_tools_view.py +++ b/src/seedsigner/views/seed_tools_view.py @@ -287,7 +287,7 @@ class SeedToolsView(View): previous_button_is_active = True elif ret_val in Keyboard.ADDITIONAL_KEYS: - if input == B.KEY_PRESS and ret_val == Keyboard.KEY_BACKSPACE["letter"]: + if input == B.KEY_PRESS and ret_val == Keyboard.KEY_BACKSPACE["code"]: self.letters = self.letters[:-2] self.letters.append(" ") @@ -299,7 +299,7 @@ class SeedToolsView(View): # Update the right-hand possible matches area render_possible_matches() - elif ret_val == Keyboard.KEY_BACKSPACE["letter"]: + elif ret_val == Keyboard.KEY_BACKSPACE["code"]: # We're just hovering over DEL but haven't clicked. Show blank (" ") # in the live text entry display at the top. self.letters = self.letters[:-1] @@ -464,7 +464,7 @@ class SeedToolsView(View): if existing_passphrase: self.passphrase = existing_passphrase else: - self.passphrase = " " + self.passphrase = "" # Set up the keyboard params right_panel_buttons_width = 60 @@ -491,42 +491,73 @@ class SeedToolsView(View): rect=(text_entry_side_padding,text_entry_top_y, View.canvas_width - right_panel_buttons_width - 1, text_entry_bottom_y), font=font, font_color=View.color, + cursor_mode=TextEntryDisplay.CURSOR_MODE__BAR, is_centered=False, has_outline=True, cur_text=''.join(self.passphrase) ) text_entry_display.render() + cursor_position = len(self.passphrase) keyboard_start_y = text_entry_bottom_y + text_entry_bottom_padding - keyboard_abc = Keyboard(View.draw, - charset="1234567890" + "".join(SeedToolsView.ALPHABET), - rows=4, - cols=10, - rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), - auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT]) - keyboard_ABC = Keyboard(View.draw, - charset="1234567890" + "".join(SeedToolsView.ALPHABET).upper(), - rows=4, - cols=10, - rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), - auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT], - render_now=False) - keyboard_symbol = Keyboard(View.draw, - charset="1234567890" + "!\"#$%&'()*+,=./;:<>?@[]|-_`~", - rows=4, - cols=10, - rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), - auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT], - render_now=False) + keyboard_abc = Keyboard( + View.draw, + charset="".join(SeedToolsView.ALPHABET), + # charset="1234567890" + "".join(SeedToolsView.ALPHABET), + rows=4, + cols=9, + rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), + additional_keys=[Keyboard.KEY_SPACE_5, Keyboard.KEY_CURSOR_LEFT, Keyboard.KEY_CURSOR_RIGHT, Keyboard.KEY_BACKSPACE], + auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT] + ) + + keyboard_ABC = Keyboard( + View.draw, + charset="".join(SeedToolsView.ALPHABET).upper(), + rows=4, + cols=9, + rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), + additional_keys=[Keyboard.KEY_SPACE_5, Keyboard.KEY_CURSOR_LEFT, Keyboard.KEY_CURSOR_RIGHT, Keyboard.KEY_BACKSPACE], + auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT], + render_now=False + ) + + keyboard_digits = Keyboard( + View.draw, + charset="1234567890", + rows=5, + cols=3, + rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), + additional_keys=[Keyboard.KEY_CURSOR_LEFT, Keyboard.KEY_CURSOR_RIGHT, Keyboard.KEY_BACKSPACE], + auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT], + render_now=False + ) + + keyboard_symbols = Keyboard( + View.draw, + charset="!@#$%^&*()-+_=[]{}\\|;:'\",.<>/?`~", + rows=4, + cols=10, + rect=(0, keyboard_start_y, View.canvas_width - right_panel_buttons_width, View.canvas_height), + additional_keys=[Keyboard.KEY_SPACE_4, Keyboard.KEY_CURSOR_LEFT, Keyboard.KEY_CURSOR_RIGHT, Keyboard.KEY_BACKSPACE], + auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT], + render_now=False + ) button1_is_active = False button2_is_active = False button3_is_active = False KEYBOARD__LOWERCASE = 0 KEYBOARD__UPPERCASE = 1 - KEYBOARD__SYMBOL = 2 - cur_keyboard_type = KEYBOARD__LOWERCASE + KEYBOARD__DIGITS = 2 + KEYBOARD__SYMBOLS = 3 + KEYBOARD__LOWERCASE_BUTTON_TEXT = "abc" + KEYBOARD__UPPERCASE_BUTTON_TEXT = "ABC" + KEYBOARD__DIGITS_BUTTON_TEXT = "123" + KEYBOARD__SYMBOLS_BUTTON_TEXT = "!@#" cur_keyboard = keyboard_abc + cur_button1_text = KEYBOARD__UPPERCASE_BUTTON_TEXT + cur_button2_text = KEYBOARD__DIGITS_BUTTON_TEXT render_right_panel() View.DispShowImage() @@ -544,7 +575,7 @@ class SeedToolsView(View): # Check our two possible exit conditions if input == B.KEY3: # Save! - if self.passphrase != "" and self.passphrase != " ": + if len(self.passphrase) > 0: return self.passphrase.strip() elif input == B.KEY_PRESS and previous_button_is_active: @@ -553,29 +584,40 @@ class SeedToolsView(View): # Check for keyboard swaps if input == B.KEY1: - if cur_keyboard_type == KEYBOARD__LOWERCASE: - keyboard_ABC.set_selected_key_indices(x=cur_keyboard.selected_key["x"], y=cur_keyboard.selected_key["y"]) - cur_keyboard_type = KEYBOARD__UPPERCASE - cur_keyboard = keyboard_ABC - render_right_panel(button1_text="abc", button2_text="!@#") - else: + if cur_button1_text == KEYBOARD__LOWERCASE_BUTTON_TEXT: keyboard_abc.set_selected_key_indices(x=cur_keyboard.selected_key["x"], y=cur_keyboard.selected_key["y"]) cur_keyboard_type = KEYBOARD__LOWERCASE cur_keyboard = keyboard_abc - render_right_panel(button1_text="ABC", button2_text="!@#") + cur_button1_text = KEYBOARD__UPPERCASE_BUTTON_TEXT + render_right_panel(button1_text=cur_button1_text, button2_text=cur_button2_text) + else: + keyboard_ABC.set_selected_key_indices(x=cur_keyboard.selected_key["x"], y=cur_keyboard.selected_key["y"]) + cur_keyboard_type = KEYBOARD__UPPERCASE + cur_keyboard = keyboard_ABC + cur_button1_text = KEYBOARD__LOWERCASE_BUTTON_TEXT + render_right_panel(button1_text=cur_button1_text, button2_text=cur_button2_text) cur_keyboard.render_keys() keyboard_swap = True ret_val = cur_keyboard.get_selected_key() elif input == B.KEY2: - if cur_keyboard_type in [KEYBOARD__LOWERCASE, KEYBOARD__UPPERCASE]: - keyboard_symbol.set_selected_key_indices(x=cur_keyboard.selected_key["x"], y=cur_keyboard.selected_key["y"]) - cur_keyboard_type = KEYBOARD__SYMBOL - cur_keyboard = keyboard_symbol + if cur_button2_text == KEYBOARD__DIGITS_BUTTON_TEXT: + keyboard_digits.set_selected_key_indices(x=cur_keyboard.selected_key["x"], y=cur_keyboard.selected_key["y"]) + cur_keyboard_type = KEYBOARD__DIGITS + cur_keyboard = keyboard_digits cur_keyboard.render_keys() - render_right_panel(button1_text="abc", button2_text="") - keyboard_swap = True - ret_val = cur_keyboard.get_selected_key() + cur_button2_text = KEYBOARD__SYMBOLS_BUTTON_TEXT + render_right_panel(button1_text=cur_button1_text, button2_text=cur_button2_text) + else: + keyboard_symbols.set_selected_key_indices(x=cur_keyboard.selected_key["x"], y=cur_keyboard.selected_key["y"]) + cur_keyboard_type = KEYBOARD__SYMBOLS + cur_keyboard = keyboard_symbols + cur_keyboard.render_keys() + cur_button2_text = KEYBOARD__DIGITS_BUTTON_TEXT + render_right_panel(button1_text=cur_button1_text, button2_text=cur_button2_text) + cur_keyboard.render_keys() + keyboard_swap = True + ret_val = cur_keyboard.get_selected_key() else: # Process normal input @@ -593,7 +635,6 @@ class SeedToolsView(View): # ignore continue - ret_val = cur_keyboard.update_from_input(input) # Now process the result from the keyboard @@ -601,38 +642,41 @@ class SeedToolsView(View): self.render_previous_button(highlight=True) previous_button_is_active = True - elif ret_val in Keyboard.ADDITIONAL_KEYS: - if input == B.KEY_PRESS and ret_val == Keyboard.KEY_BACKSPACE["letter"]: - self.passphrase = self.passphrase[:-2] - self.passphrase += " " + elif ret_val in Keyboard.ADDITIONAL_KEYS and input == B.KEY_PRESS: + if ret_val == Keyboard.KEY_BACKSPACE["code"]: + if cursor_position == 0: + pass + elif cursor_position == len(self.passphrase): + self.passphrase = self.passphrase[:-1] + else: + self.passphrase = self.passphrase[:cursor_position - 1] + self.passphrase[cursor_position:] - elif ret_val == Keyboard.KEY_BACKSPACE["letter"]: - # We're just hovering over DEL but haven't clicked. Show blank (" ") - # in the live text entry display at the top. - self.passphrase = self.passphrase[:-1] - self.passphrase += " " + cursor_position -= 1 + + elif ret_val == Keyboard.KEY_CURSOR_LEFT["code"]: + cursor_position -= 1 + if cursor_position < 0: + cursor_position = 0 + + elif ret_val == Keyboard.KEY_CURSOR_RIGHT["code"]: + cursor_position += 1 + if cursor_position > len(self.passphrase): + cursor_position = len(self.passphrase) + + elif ret_val == Keyboard.KEY_SPACE["code"]: + if cursor_position == len(self.passphrase): + self.passphrase += " " + else: + self.passphrase = self.passphrase[:cursor_position] + " " + self.passphrase[cursor_position:] + cursor_position += 1 elif input == B.KEY_PRESS and ret_val not in Keyboard.ADDITIONAL_KEYS: # User has locked in the current letter - if self.passphrase[-1] != " ": - # We'll save that locked in letter next but for now update the - # live text entry display with blank (" ") so that we don't try - # to autocalc matches against a second copy of the letter they - # just selected. e.g. They KEY_PRESS on "s" to build "mus". If - # we advance the live block cursor AND display "s" in it, the - # current word would then be "muss" with no matches. If "mus" - # can get us to our match, we don't want it to disappear right - # as we KEY_PRESS. - self.passphrase += " " - else: - # clicked same letter twice in a row. Because of the above, an - # immediate second click of the same letter would lock in "ap " - # (note the space) instead of "app". So we replace that trailing - # space with the correct repeated letter and then, as above, - # append a trailing blank. - self.passphrase = self.passphrase[:-1] + if cursor_position == len(self.passphrase): self.passphrase += ret_val - self.passphrase += " " + else: + self.passphrase = self.passphrase[:cursor_position] + ret_val + self.passphrase[cursor_position:] + cursor_position += 1 elif input in [B.KEY_RIGHT, B.KEY_LEFT, B.KEY_UP, B.KEY_DOWN] or keyboard_swap: # Live joystick movement; haven't locked this new letter in yet. @@ -641,7 +685,7 @@ class SeedToolsView(View): pass # Render the text entry display and cursor block - text_entry_display.render(self.passphrase) + text_entry_display.render(self.passphrase, cursor_position) View.DispShowImage()