system/ui: add password mask delay to InputBox (#35316)

add password mask delay to InputBox
pull/35318/head
Dean Lee 4 days ago committed by GitHub
parent b4d6b52edd
commit 4423b47b6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 29
      system/ui/lib/inputbox.py
  2. 2
      system/ui/widgets/keyboard.py

@ -1,8 +1,10 @@
import pyray as rl import pyray as rl
import time
from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.application import gui_app
PASSWORD_MASK_CHAR = "" PASSWORD_MASK_CHAR = ""
PASSWORD_MASK_DELAY = 1.5 # Seconds to show character before masking
class InputBox: class InputBox:
@ -19,6 +21,8 @@ class InputBox:
self._repeat_rate = 4 self._repeat_rate = 4
self._text_offset = 0 self._text_offset = 0
self._visible_width = 0 self._visible_width = 0
self._last_char_time = 0 # Track when last character was added
self._masked_length = 0 # How many characters are currently masked
@property @property
def text(self): def text(self):
@ -52,7 +56,7 @@ class InputBox:
return return
font = gui_app.font() font = gui_app.font()
display_text = PASSWORD_MASK_CHAR * len(self._input_text) if self._password_mode else self._input_text display_text = self._get_display_text()
padding = 10 padding = 10
if self._cursor_position > 0: if self._cursor_position > 0:
@ -73,6 +77,10 @@ class InputBox:
if len(self._input_text) < self._max_text_size: if len(self._input_text) < self._max_text_size:
self._input_text = self._input_text[: self._cursor_position] + char + self._input_text[self._cursor_position :] self._input_text = self._input_text[: self._cursor_position] + char + self._input_text[self._cursor_position :]
self.set_cursor_position(self._cursor_position + 1) self.set_cursor_position(self._cursor_position + 1)
if self._password_mode:
self._last_char_time = time.time()
return True return True
return False return False
@ -114,7 +122,7 @@ class InputBox:
# Display text # Display text
font = gui_app.font() font = gui_app.font()
display_text = PASSWORD_MASK_CHAR * len(self._input_text) if self._password_mode else self._input_text display_text = self._get_display_text()
padding = 10 padding = 10
# Clip text within input box bounds # Clip text within input box bounds
@ -144,6 +152,21 @@ class InputBox:
rl.end_scissor_mode() rl.end_scissor_mode()
def _get_display_text(self):
"""Get text to display, applying password masking with delay if needed."""
if not self._password_mode:
return self._input_text
# Show character at last edited position if within delay window
masked_text = PASSWORD_MASK_CHAR * len(self._input_text)
recent_edit = time.time() - self._last_char_time < PASSWORD_MASK_DELAY
if recent_edit and self._input_text:
last_pos = max(0, self._cursor_position - 1)
if last_pos < len(self._input_text):
return masked_text[:last_pos] + self._input_text[last_pos] + masked_text[last_pos + 1 :]
return masked_text
def _handle_mouse_input(self, rect, font_size): def _handle_mouse_input(self, rect, font_size):
"""Handle mouse clicks to position cursor.""" """Handle mouse clicks to position cursor."""
mouse_pos = rl.get_mouse_position() mouse_pos = rl.get_mouse_position()
@ -151,7 +174,7 @@ class InputBox:
# Calculate cursor position from click # Calculate cursor position from click
if len(self._input_text) > 0: if len(self._input_text) > 0:
font = gui_app.font() font = gui_app.font()
display_text = PASSWORD_MASK_CHAR * len(self._input_text) if self._password_mode else self._input_text display_text = self._get_display_text()
# Find the closest character position to the click # Find the closest character position to the click
relative_x = mouse_pos.x - (rect.x + 10) + self._text_offset relative_x = mouse_pos.x - (rect.x + 10) + self._text_offset

@ -221,7 +221,7 @@ class Keyboard:
if __name__ == "__main__": if __name__ == "__main__":
gui_app.init_window("Keyboard") gui_app.init_window("Keyboard")
keyboard = Keyboard(min_text_size=8) keyboard = Keyboard(min_text_size=8, show_password_toggle=True)
for _ in gui_app.render(): for _ in gui_app.render():
result = keyboard.render("Keyboard", "Type here") result = keyboard.render("Keyboard", "Type here")
if result == 1: if result == 1:

Loading…
Cancel
Save