Skip to content

Commit

Permalink
chore(core): show the last pin digit for a while
Browse files Browse the repository at this point in the history
  • Loading branch information
bieleluk committed Nov 18, 2024
1 parent 5c8edfa commit b9f5e2b
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 278 deletions.
1 change: 1 addition & 0 deletions core/.changelog.d/3863.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Show last typed PIN number for short period of time
62 changes: 51 additions & 11 deletions core/embed/rust/src/ui/model_mercury/component/keyboard/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const HEADER_PADDING: Insets = Insets::new(
HEADER_PADDING_SIDE,
);

const LAST_DIGIT_TIMEOUT_S: u32 = 1;

#[derive(Default, Clone)]
struct AttachAnimation {
pub attach_top: bool,
Expand Down Expand Up @@ -260,6 +262,7 @@ pub struct PinKeyboard<'a> {
attach_animation: AttachAnimation,
close_animation: CloseAnimation,
close_confirm: bool,
timeout_timer: Timer,
}

impl<'a> PinKeyboard<'a> {
Expand Down Expand Up @@ -299,6 +302,7 @@ impl<'a> PinKeyboard<'a> {
attach_animation: AttachAnimation::default(),
close_animation: CloseAnimation::default(),
close_confirm: false,
timeout_timer: Timer::new(),
}
}

Expand Down Expand Up @@ -425,6 +429,12 @@ impl Component for PinKeyboard<'_> {
self.minor_prompt.request_complete_repaint(ctx);
ctx.request_paint();
}
// Timeout for showing the last digit.
Event::Timer(_) if self.timeout_timer.expire(event) => {
self.textbox.display_style = DisplayStyle::Dots;
self.textbox.request_complete_repaint(ctx);
ctx.request_paint();
}
_ => {}
}

Expand Down Expand Up @@ -470,6 +480,11 @@ impl Component for PinKeyboard<'_> {
self.textbox.push(ctx, text);
});
self.pin_modified(ctx);
self.timeout_timer
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
self.textbox.display_style = DisplayStyle::LastDigit;
self.textbox.request_complete_repaint(ctx);
ctx.request_paint();
return None;
}
}
Expand Down Expand Up @@ -524,7 +539,15 @@ struct PinDots {
pad: Pad,
style: TextStyle,
digits: ShortString,
display_digits: bool,
display_style: DisplayStyle,
}

#[derive(PartialEq, Debug, Copy, Clone)]
#[cfg_attr(feature = "ui_debug", derive(ufmt::derive::uDebug))]
enum DisplayStyle {
Dots,
Digits,
LastDigit,
}

impl PinDots {
Expand All @@ -538,7 +561,7 @@ impl PinDots {
pad: Pad::with_background(style.background_color),
style,
digits: ShortString::new(),
display_digits: false,
display_style: DisplayStyle::Dots,
}
}

Expand Down Expand Up @@ -600,7 +623,7 @@ impl PinDots {
}
}

fn render_dots<'s>(&self, area: Rect, target: &mut impl Renderer<'s>) {
fn render_dots<'s>(&self, last_digit: bool, area: Rect, target: &mut impl Renderer<'s>) {
let mut cursor = area.left_center();

let digits = self.digits.len();
Expand Down Expand Up @@ -634,13 +657,28 @@ impl PinDots {
}

// Draw a dot for each PIN digit.
for _ in digit_idx..dots_visible {
for _ in digit_idx..dots_visible - 1 {
shape::ToifImage::new(cursor, theme::ICON_PIN_BULLET.toif)
.with_align(Alignment2D::CENTER_LEFT)
.with_fg(self.style.text_color)
.render(target);
cursor.x += step;
}

if last_digit && digits > 0 {
let last = &self.digits[(digits - 1)..digits];
cursor.y = area.left_center().y + (Font::MONO.visible_text_height("1") / 2);
shape::Text::new(cursor, last)
.with_align(Alignment::Start)
.with_font(Font::MONO)
.with_fg(self.style.text_color)
.render(target);
} else {
shape::ToifImage::new(cursor, theme::ICON_PIN_BULLET.toif)
.with_align(Alignment2D::CENTER_LEFT)
.with_fg(self.style.text_color)
.render(target);
}
}
}

Expand All @@ -657,14 +695,15 @@ impl Component for PinDots {
match event {
Event::Touch(TouchEvent::TouchStart(pos)) => {
if self.area.contains(pos) {
self.display_digits = true;
self.display_style = DisplayStyle::Digits;
self.pad.clear();
ctx.request_paint();
};
None
}
Event::Touch(TouchEvent::TouchEnd(_)) => {
if mem::replace(&mut self.display_digits, false) {
if mem::replace(&mut self.display_style, DisplayStyle::Dots) == DisplayStyle::Digits
{
self.pad.clear();
ctx.request_paint();
};
Expand All @@ -677,10 +716,10 @@ impl Component for PinDots {
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
let dot_area = self.area.inset(HEADER_PADDING);
self.pad.render(target);
if self.display_digits {
self.render_digits(dot_area, target)
} else {
self.render_dots(dot_area, target)
match self.display_style {
DisplayStyle::Digits => self.render_digits(dot_area, target),
DisplayStyle::Dots => self.render_dots(false, dot_area, target),
DisplayStyle::LastDigit => self.render_dots(true, dot_area, target),
}
}
}
Expand All @@ -699,8 +738,9 @@ impl crate::trace::Trace for PinKeyboard<'_> {
});
}
}
let display_style = uformat!("{:?}", self.textbox.display_style);
t.string("digits_order", digits_order.as_str().into());
t.string("pin", self.textbox.pin().into());
t.bool("display_digits", self.textbox.display_digits);
t.string("display_style", display_style.as_str().into());
}
}
34 changes: 24 additions & 10 deletions core/embed/rust/src/ui/model_tr/component/input_methods/pin.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::{
strutil::{ShortString, TString},
time::Duration,
translations::TR,
trezorhal::random,
ui::{
component::{text::common::TextBox, Child, Component, ComponentExt, Event, EventCtx},
component::{
text::common::TextBox, Child, Component, ComponentExt, Event, EventCtx, Timer,
},
display::{Font, Icon},
geometry::Rect,
shape::Renderer,
Expand Down Expand Up @@ -52,6 +55,8 @@ const EMPTY_PIN_STR: &str = "_";
const CHOICE_LENGTH: usize = 13;
const NUMBER_START_INDEX: usize = 3;

const LAST_DIGIT_TIMEOUT_S: u32 = 1;

const CHOICES: [PinChoice; CHOICE_LENGTH] = [
// DELETE should be triggerable without release (after long-press)
PinChoice::new(
Expand Down Expand Up @@ -140,6 +145,7 @@ pub struct PinEntry<'a> {
show_real_pin: bool,
show_last_digit: bool,
textbox: TextBox,
timeout_timer: Timer,
}

impl<'a> PinEntry<'a> {
Expand Down Expand Up @@ -179,6 +185,7 @@ impl<'a> PinEntry<'a> {
show_real_pin: false,
show_last_digit: false,
textbox: TextBox::empty(MAX_PIN_LENGTH),
timeout_timer: Timer::new(),
}
}

Expand Down Expand Up @@ -262,17 +269,22 @@ impl Component for PinEntry<'_> {
}

fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
// Any non-timer event when showing real PIN should hide it
// Same with showing last digit
if !matches!(event, Event::Timer(_)) {
if self.show_real_pin {
self.show_real_pin = false;
self.update(ctx)
match event {
// Timeout for showing the last digit.
Event::Timer(_) if self.timeout_timer.expire(event) => {
if self.show_last_digit {
self.show_last_digit = false;
self.update(ctx)
}
}
if self.show_last_digit {
self.show_last_digit = false;
self.update(ctx)
// Other timers are ignored.
Event::Timer(_) => {}
// Any non-timer event when showing real PIN should hide it
_ if self.show_real_pin => {
self.show_real_pin = false;
self.update(ctx);
}
_ => {}
}

// Any button event will show the "real" prompt
Expand Down Expand Up @@ -308,6 +320,8 @@ impl Component for PinEntry<'_> {
self.choice_page
.set_page_counter(ctx, get_random_digit_position(), true);
self.show_last_digit = true;
self.timeout_timer
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
self.update(ctx);
}
_ => {}
Expand Down
Loading

0 comments on commit b9f5e2b

Please sign in to comment.