mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-24 15:38:22 +00:00
fix(core/eckhart): fix passphrase keyboard bug
- when multi tab key timer expires, the buttons are resetted only if the passphrase reached the max length - when the passphrase keyboard layout is swapped, the buttons are resetted [no changelog]
This commit is contained in:
parent
26a52a5ed4
commit
9494ba8896
@ -139,6 +139,7 @@ pub(crate) enum DisplayStyle {
|
||||
Hidden,
|
||||
Shown,
|
||||
LastOnly,
|
||||
LastWithMarker,
|
||||
}
|
||||
|
||||
/// The number and colors of fading icons to display.
|
||||
|
@ -362,9 +362,14 @@ impl Component for Keypad {
|
||||
self.pressed = None;
|
||||
return Some(KeypadMsg::EraseLong);
|
||||
}
|
||||
// Detect press of all special buttons for rendering purposes
|
||||
// Detect press/release of all special buttons for rendering purposes
|
||||
Some(ButtonMsg::Pressed) => {
|
||||
self.pressed = Some(button);
|
||||
return None;
|
||||
}
|
||||
Some(ButtonMsg::Released) => {
|
||||
self.pressed = None;
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -377,9 +382,14 @@ impl Component for Keypad {
|
||||
self.pressed = None;
|
||||
return Some(KeypadMsg::Key(idx));
|
||||
}
|
||||
// Detect press of all key buttons for rendering purposes
|
||||
// Detect press/release of all key buttons for rendering purposes
|
||||
Some(ButtonMsg::Pressed) => {
|
||||
self.pressed = Some(KeypadButton::Key(idx));
|
||||
return None;
|
||||
}
|
||||
Some(ButtonMsg::Released) => {
|
||||
self.pressed = None;
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ const KEYBOARD: [[&str; KEY_COUNT]; PAGE_COUNT] = [
|
||||
|
||||
const MAX_LENGTH: usize = 50; // max length of the passphrase
|
||||
const MAX_SHOWN_LEN: usize = 14; // max number of icons per line
|
||||
const LAST_DIGIT_TIMEOUT_S: u32 = 1;
|
||||
const LAST_DIGIT_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
|
||||
const NEXT_BTN_WIDTH: i16 = 103;
|
||||
const NEXT_BTN_PADDING: i16 = 14;
|
||||
@ -176,14 +176,13 @@ impl PassphraseKeyboard {
|
||||
if self.multi_tap.pending_key().is_some() {
|
||||
// Clear the pending state.
|
||||
self.multi_tap.clear_pending_state(ctx);
|
||||
self.input.marker = false;
|
||||
self.input.display_style = DisplayStyle::LastOnly;
|
||||
// the character has been added, show it for a bit and then hide it
|
||||
self.input
|
||||
.last_char_timer
|
||||
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
|
||||
self.input.last_char_timer.start(ctx, LAST_DIGIT_TIMEOUT);
|
||||
}
|
||||
// Update keys.
|
||||
self.replace_keys_contents();
|
||||
self.update_keypad_state(ctx);
|
||||
}
|
||||
|
||||
fn replace_keys_contents(&mut self) {
|
||||
@ -200,6 +199,8 @@ impl PassphraseKeyboard {
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the keypad state based on the current passphrase and input state
|
||||
/// Can be used only when no key is pressed
|
||||
fn update_keypad_state(&mut self, ctx: &mut EventCtx) {
|
||||
let keypad_state = match self.input.display_style {
|
||||
DisplayStyle::Shown => {
|
||||
@ -304,21 +305,45 @@ impl Component for PassphraseKeyboard {
|
||||
}
|
||||
Event::Timer(_) if self.multi_tap.timeout_event(event) => {
|
||||
self.multi_tap.clear_pending_state(ctx);
|
||||
self.input
|
||||
.last_char_timer
|
||||
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
|
||||
self.input.marker = false;
|
||||
self.update_keypad_state(ctx);
|
||||
self.input.last_char_timer.start(ctx, LAST_DIGIT_TIMEOUT);
|
||||
self.input.display_style = DisplayStyle::LastOnly;
|
||||
// Disable keypad when the passphrase reached the max length
|
||||
if self.passphrase().len() == MAX_LENGTH {
|
||||
self.update_keypad_state(ctx);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Input event has to be handled before the swipe so that swipe in the input
|
||||
// area is not processed
|
||||
match self.input.event(ctx, event) {
|
||||
Some(PassphraseInputMsg::TouchStart) => {
|
||||
self.multi_tap.clear_pending_state(ctx);
|
||||
// Disable keypad.
|
||||
self.update_keypad_state(ctx);
|
||||
return None;
|
||||
}
|
||||
Some(PassphraseInputMsg::TouchEnd) => {
|
||||
// Enable keypad.
|
||||
self.update_keypad_state(ctx);
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Swipe event has to be handled before the individual button events
|
||||
if let Some(swipe) = self.page_swipe.event(ctx, event) {
|
||||
// We have detected a horizontal swipe. Change the keyboard page.
|
||||
self.on_page_change(ctx, swipe);
|
||||
return None;
|
||||
match swipe {
|
||||
Direction::Left | Direction::Right => {
|
||||
// We have detected a horizontal swipe. Change the keyboard page.
|
||||
self.on_page_change(ctx, swipe);
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ButtonMsg::Clicked) = self.next_btn.event(ctx, event) {
|
||||
@ -333,16 +358,13 @@ impl Component for PassphraseKeyboard {
|
||||
if text.len() == 1 {
|
||||
// If the key has just one character, it is immediately applied and the last
|
||||
// digit timer should be started
|
||||
self.input.marker = false;
|
||||
self.input
|
||||
.last_char_timer
|
||||
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
|
||||
self.input.display_style = DisplayStyle::LastOnly;
|
||||
self.input.last_char_timer.start(ctx, LAST_DIGIT_TIMEOUT);
|
||||
} else {
|
||||
// multi tap timer is runnig, the last digit timer should be stopped
|
||||
self.input.last_char_timer.stop();
|
||||
self.input.marker = true;
|
||||
self.input.display_style = DisplayStyle::LastWithMarker;
|
||||
}
|
||||
self.input.display_style = DisplayStyle::LastOnly;
|
||||
self.update_keypad_state(ctx);
|
||||
}
|
||||
return None;
|
||||
@ -372,21 +394,6 @@ impl Component for PassphraseKeyboard {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match self.input.event(ctx, event) {
|
||||
Some(PassphraseInputMsg::TouchStart) => {
|
||||
self.multi_tap.clear_pending_state(ctx);
|
||||
// Disable keypad.
|
||||
self.update_keypad_state(ctx);
|
||||
return None;
|
||||
}
|
||||
Some(PassphraseInputMsg::TouchEnd) => {
|
||||
// Enable keypad.
|
||||
self.update_keypad_state(ctx);
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@ -433,7 +440,6 @@ struct PassphraseInput {
|
||||
area: Rect,
|
||||
textbox: TextBox,
|
||||
display_style: DisplayStyle,
|
||||
marker: bool,
|
||||
last_char_timer: Timer,
|
||||
shown_area: Rect,
|
||||
}
|
||||
@ -451,8 +457,7 @@ impl PassphraseInput {
|
||||
Self {
|
||||
area: Rect::zero(),
|
||||
textbox: TextBox::empty(MAX_LENGTH),
|
||||
display_style: DisplayStyle::LastOnly,
|
||||
marker: false,
|
||||
display_style: DisplayStyle::Hidden,
|
||||
last_char_timer: Timer::new(),
|
||||
shown_area: Rect::zero(),
|
||||
}
|
||||
@ -503,7 +508,7 @@ impl PassphraseInput {
|
||||
let hidden_area: Rect = self.area.inset(KEYBOARD_INPUT_INSETS);
|
||||
let style = theme::TEXT_MEDIUM;
|
||||
let pp_len = self.passphrase().len();
|
||||
let last_char = self.display_style == DisplayStyle::LastOnly;
|
||||
let last_char = self.display_style != DisplayStyle::Hidden;
|
||||
|
||||
let mut cursor = hidden_area.left_center().ofs(Offset::x(12));
|
||||
|
||||
@ -560,7 +565,7 @@ impl PassphraseInput {
|
||||
.render(target);
|
||||
|
||||
// Paint the pending marker.
|
||||
if self.marker {
|
||||
if self.display_style == DisplayStyle::LastWithMarker {
|
||||
render_pending_marker(target, cursor, last, style.text_font, style.text_color);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user