feat(core): create new design for PIN entry

pull/3580/head
grdddj 3 months ago
parent 736e6b003a
commit 51fb99d792

@ -13,11 +13,13 @@ use crate::{
event::TouchEvent, event::TouchEvent,
geometry::{Alignment, Alignment2D, Grid, Insets, Offset, Rect}, geometry::{Alignment, Alignment2D, Grid, Insets, Offset, Rect},
model_mercury::component::{ model_mercury::component::{
button::{Button, ButtonContent, ButtonMsg, ButtonMsg::Clicked}, button::{
Button, ButtonContent,
ButtonMsg::{self, Clicked},
},
theme, theme,
}, },
shape, shape::{self, Renderer},
shape::Renderer,
}, },
}; };
@ -31,11 +33,11 @@ const MAX_VISIBLE_DOTS: usize = 14;
const MAX_VISIBLE_DIGITS: usize = 16; const MAX_VISIBLE_DIGITS: usize = 16;
const DIGIT_COUNT: usize = 10; // 0..10 const DIGIT_COUNT: usize = 10; // 0..10
const HEADER_PADDING_SIDE: i16 = 5; const HEADER_PADDING_SIDE: i16 = 2;
const HEADER_PADDING_BOTTOM: i16 = 12; const HEADER_PADDING_BOTTOM: i16 = 2;
const HEADER_PADDING: Insets = Insets::new( const HEADER_PADDING: Insets = Insets::new(
theme::borders().top, 0,
HEADER_PADDING_SIDE, HEADER_PADDING_SIDE,
HEADER_PADDING_BOTTOM, HEADER_PADDING_BOTTOM,
HEADER_PADDING_SIDE, HEADER_PADDING_SIDE,
@ -60,8 +62,8 @@ where
T: AsRef<str>, T: AsRef<str>,
{ {
// Label position fine-tuning. // Label position fine-tuning.
const MAJOR_OFF: Offset = Offset::y(11); const MAJOR_OFF: Offset = Offset::y(0);
const MINOR_OFF: Offset = Offset::y(11); const MINOR_OFF: Offset = Offset::y(0);
pub fn new( pub fn new(
major_prompt: T, major_prompt: T,
@ -70,17 +72,13 @@ where
allow_cancel: bool, allow_cancel: bool,
) -> Self { ) -> Self {
// Control buttons. // Control buttons.
let erase_btn = Button::with_icon_blend( let erase_btn = Button::with_icon(theme::ICON_DELETE)
theme::IMAGE_BG_BACK_BTN, .styled(theme::button_pin_erase())
theme::ICON_BACK, .with_long_press(theme::ERASE_HOLD_DURATION)
Offset::new(30, 12), .initially_enabled(false);
)
.styled(theme::button_reset())
.with_long_press(theme::ERASE_HOLD_DURATION)
.initially_enabled(false);
let erase_btn = Maybe::hidden(theme::BG, erase_btn).into_child(); let erase_btn = Maybe::hidden(theme::BG, erase_btn).into_child();
let cancel_btn = Button::with_icon(theme::ICON_CANCEL).styled(theme::button_cancel()); let cancel_btn = Button::with_icon(theme::ICON_CANCEL).styled(theme::button_pin_cancel());
let cancel_btn = Maybe::new(theme::BG, cancel_btn, allow_cancel).into_child(); let cancel_btn = Maybe::new(theme::BG, cancel_btn, allow_cancel).into_child();
Self { Self {
@ -96,7 +94,7 @@ where
erase_btn, erase_btn,
cancel_btn, cancel_btn,
confirm_btn: Button::with_icon(theme::ICON_CONFIRM) confirm_btn: Button::with_icon(theme::ICON_CONFIRM)
.styled(theme::button_confirm()) .styled(theme::button_pin_confirm())
.initially_enabled(false) .initially_enabled(false)
.into_child(), .into_child(),
digit_btns: Self::generate_digit_buttons(), digit_btns: Self::generate_digit_buttons(),
@ -155,23 +153,16 @@ where
type Msg = PinKeyboardMsg; type Msg = PinKeyboardMsg;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
// Ignore the top padding for now, we need it to reliably register textbox touch
// events.
let borders_no_top = Insets {
top: 0,
..theme::borders()
};
// Prompts and PIN dots display. // Prompts and PIN dots display.
let (header, keypad) = bounds let (header, keypad) =
.inset(borders_no_top) bounds.split_bottom(4 * theme::PIN_BUTTON_HEIGHT + 3 * theme::PIN_BUTTON_SPACING);
.split_bottom(4 * theme::PIN_BUTTON_HEIGHT + 3 * theme::BUTTON_SPACING);
let prompt = header.inset(HEADER_PADDING); let prompt = header.inset(HEADER_PADDING);
// the inset -3 is a workaround for long text in "re-enter wipe code" // the inset -3 is a workaround for long text in "re-enter wipe code"
let major_area = prompt.translate(Self::MAJOR_OFF).inset(Insets::right(-3)); let major_area = prompt.translate(Self::MAJOR_OFF).inset(Insets::right(-3));
let minor_area = prompt.translate(Self::MINOR_OFF); let minor_area = prompt.translate(Self::MINOR_OFF);
// Control buttons. // Control buttons.
let grid = Grid::new(keypad, 4, 3).with_spacing(theme::BUTTON_SPACING); let grid = Grid::new(keypad, 4, 3).with_spacing(theme::PIN_BUTTON_SPACING);
// Prompts and PIN dots display. // Prompts and PIN dots display.
self.textbox_pad.place(header); self.textbox_pad.place(header);
@ -272,6 +263,7 @@ where
fn render(&mut self, target: &mut impl Renderer) { fn render(&mut self, target: &mut impl Renderer) {
self.erase_btn.render(target); self.erase_btn.render(target);
self.textbox_pad.render(target); self.textbox_pad.render(target);
if self.textbox.inner().is_empty() { if self.textbox.inner().is_empty() {
if let Some(ref mut w) = self.major_warning { if let Some(ref mut w) = self.major_warning {
w.render(target); w.render(target);
@ -283,7 +275,12 @@ where
} else { } else {
self.textbox.render(target); self.textbox.render(target);
} }
self.confirm_btn.render(target);
// Painting the confirm only if there is already a pin
if !self.textbox.inner().is_empty() {
self.confirm_btn.render(target);
}
for btn in &mut self.digit_btns { for btn in &mut self.digit_btns {
btn.render(target); btn.render(target);
} }
@ -390,13 +387,14 @@ impl PinDots {
} }
fn render_digits(&self, area: Rect, target: &mut impl Renderer) { fn render_digits(&self, area: Rect, target: &mut impl Renderer) {
let left = area.left_center() + Offset::y(Font::MONO.text_height() / 2);
let center = area.center() + Offset::y(Font::MONO.text_height() / 2); let center = area.center() + Offset::y(Font::MONO.text_height() / 2);
let right = center + Offset::x(Font::MONO.text_width("0") * (MAX_VISIBLE_DOTS as i16) / 2); let right = center + Offset::x(Font::MONO.text_width("0") * (MAX_VISIBLE_DOTS as i16) / 2);
let digits = self.digits.len(); let digits = self.digits.len();
if digits <= MAX_VISIBLE_DOTS { if digits <= MAX_VISIBLE_DOTS {
shape::Text::new(center, &self.digits) shape::Text::new(left, &self.digits)
.with_align(Alignment::Center) .with_align(Alignment::Start)
.with_font(Font::MONO) .with_font(Font::MONO)
.with_fg(self.style.text_color) .with_fg(self.style.text_color)
.render(target); .render(target);
@ -456,7 +454,7 @@ impl PinDots {
fn render_dots(&self, area: Rect, target: &mut impl Renderer) { fn render_dots(&self, area: Rect, target: &mut impl Renderer) {
// let mut cursor = self.size().snap(area.left_center(), Alignment2D::CENTER); // let mut cursor = self.size().snap(area.left_center(), Alignment2D::CENTER);
let cursor = area.bottom_left(); let mut cursor = area.bottom_left();
let digits = self.digits.len(); let digits = self.digits.len();
let dots_visible = digits.min(MAX_VISIBLE_DOTS); let dots_visible = digits.min(MAX_VISIBLE_DOTS);

@ -43,6 +43,7 @@ pub const GREY_LIGHT: Color = Color::rgb(0x90, 0x90, 0x90); // secondary text
pub const GREY_MEDIUM: Color = Color::rgb(0x4F, 0x4F, 0x4F); // button pressed pub const GREY_MEDIUM: Color = Color::rgb(0x4F, 0x4F, 0x4F); // button pressed
pub const GREY_DARK: Color = Color::rgb(0x35, 0x35, 0x35); // button pub const GREY_DARK: Color = Color::rgb(0x35, 0x35, 0x35); // button
pub const VIOLET: Color = Color::rgb(0x95, 0x00, 0xCA); pub const VIOLET: Color = Color::rgb(0x95, 0x00, 0xCA);
pub const PIN_BUTTON_COLOR: Color = Color::rgb(0x16, 0x1F, 0x24);
pub const FATAL_ERROR_COLOR: Color = Color::rgb(0xE7, 0x0E, 0x0E); pub const FATAL_ERROR_COLOR: Color = Color::rgb(0xE7, 0x0E, 0x0E);
pub const FATAL_ERROR_HIGHLIGHT_COLOR: Color = Color::rgb(0xFF, 0x41, 0x41); pub const FATAL_ERROR_HIGHLIGHT_COLOR: Color = Color::rgb(0xFF, 0x41, 0x41);
@ -373,10 +374,10 @@ pub const fn button_pin() -> ButtonStyleSheet {
normal: &ButtonStyle { normal: &ButtonStyle {
font: Font::MONO, font: Font::MONO,
text_color: FG, text_color: FG,
button_color: GREY_DARK, button_color: PIN_BUTTON_COLOR,
background_color: BG, background_color: BG,
border_color: BG, border_color: BG,
border_radius: RADIUS, border_radius: 0,
border_width: 0, border_width: 0,
}, },
active: &ButtonStyle { active: &ButtonStyle {
@ -385,7 +386,7 @@ pub const fn button_pin() -> ButtonStyleSheet {
button_color: GREY_MEDIUM, button_color: GREY_MEDIUM,
background_color: BG, background_color: BG,
border_color: FG, border_color: FG,
border_radius: RADIUS, border_radius: 0,
border_width: 0, border_width: 0,
}, },
disabled: &ButtonStyle { disabled: &ButtonStyle {
@ -394,39 +395,103 @@ pub const fn button_pin() -> ButtonStyleSheet {
button_color: BG, // so there is no "button" itself, just the text button_color: BG, // so there is no "button" itself, just the text
background_color: BG, background_color: BG,
border_color: BG, border_color: BG,
border_radius: RADIUS, border_radius: 0,
border_width: 0, border_width: 0,
}, },
} }
} }
pub const fn button_pin_confirm() -> ButtonStyleSheet { pub const fn button_pin_cancel() -> ButtonStyleSheet {
ButtonStyleSheet { ButtonStyleSheet {
normal: &ButtonStyle { normal: &ButtonStyle {
font: Font::MONO, font: Font::BOLD,
text_color: FG, text_color: RED,
button_color: GREEN, button_color: BG,
background_color: BG, background_color: BG,
border_color: BG, border_color: BG,
border_radius: RADIUS, border_radius: 0,
border_width: 0, border_width: 0,
}, },
active: &ButtonStyle { active: &ButtonStyle {
font: Font::MONO, font: Font::BOLD,
text_color: RED,
button_color: BG,
background_color: BG,
border_color: FG,
border_radius: 0,
border_width: 0,
},
disabled: &ButtonStyle {
font: Font::BOLD,
text_color: GREY_LIGHT,
button_color: BG,
background_color: BG,
border_color: BG,
border_radius: 0,
border_width: 0,
},
}
}
pub const fn button_pin_erase() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
font: Font::BOLD,
text_color: GREY_LIGHT,
button_color: BG,
background_color: BG,
border_color: BG,
border_radius: 0,
border_width: 0,
},
active: &ButtonStyle {
font: Font::BOLD,
text_color: FG, text_color: FG,
button_color: GREEN_DARK, button_color: BG,
background_color: BG, background_color: BG,
border_color: FG, border_color: FG,
border_radius: RADIUS, border_radius: 0,
border_width: 0, border_width: 0,
}, },
disabled: &ButtonStyle { disabled: &ButtonStyle {
font: Font::MONO, font: Font::BOLD,
text_color: FG,
button_color: BG,
background_color: BG,
border_color: BG,
border_radius: 0,
border_width: 0,
},
}
}
pub const fn button_pin_confirm() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
font: Font::BOLD,
text_color: GREEN,
button_color: BG,
background_color: BG,
border_color: BG,
border_radius: 0,
border_width: 0,
},
active: &ButtonStyle {
font: Font::BOLD,
text_color: GREEN,
button_color: BG,
background_color: BG,
border_color: GREEN,
border_radius: 0,
border_width: 0,
},
disabled: &ButtonStyle {
font: Font::BOLD,
text_color: GREY_LIGHT, text_color: GREY_LIGHT,
button_color: GREY_DARK, button_color: BG,
background_color: BG, background_color: BG,
border_color: BG, border_color: BG,
border_radius: RADIUS, border_radius: 0,
border_width: 0, border_width: 0,
}, },
} }
@ -657,7 +722,8 @@ pub const RECOVERY_SPACING: i16 = 18;
pub const CORNER_BUTTON_SIDE: i16 = 44; pub const CORNER_BUTTON_SIDE: i16 = 44;
pub const CORNER_BUTTON_SPACING: i16 = BUTTON_SPACING; pub const CORNER_BUTTON_SPACING: i16 = BUTTON_SPACING;
pub const INFO_BUTTON_HEIGHT: i16 = 44; pub const INFO_BUTTON_HEIGHT: i16 = 44;
pub const PIN_BUTTON_HEIGHT: i16 = 40; pub const PIN_BUTTON_HEIGHT: i16 = 52;
pub const PIN_BUTTON_SPACING: i16 = 2;
pub const MNEMONIC_BUTTON_HEIGHT: i16 = 52; pub const MNEMONIC_BUTTON_HEIGHT: i16 = 52;
pub const RESULT_PADDING: i16 = 6; pub const RESULT_PADDING: i16 = 6;
pub const RESULT_FOOTER_START: i16 = 171; pub const RESULT_FOOTER_START: i16 = 171;

@ -180,10 +180,11 @@ impl Loader {
let text_width = style.font.text_width(t); let text_width = style.font.text_width(t);
let text_height = style.font.text_max_height(); let text_height = style.font.text_max_height();
let pt = self.area.top_left() + Offset::new( let pt = self.area.top_left()
(self.area.width() - text_width) / 2, + Offset::new(
(self.area.height() - text_height) / 2, (self.area.width() - text_width) / 2,
); (self.area.height() - text_height) / 2,
);
shape::Text::new(pt, t) shape::Text::new(pt, t)
.with_baseline(false) .with_baseline(false)

Loading…
Cancel
Save