From 63965ea07fc7353906a0e63ca12de1d14168f453 Mon Sep 17 00:00:00 2001 From: obrusvit Date: Thu, 25 Apr 2024 15:26:58 +0200 Subject: [PATCH] feat(core/ui): T3T1 mnemonic keyboard These are initial changes to the mnemonic keyboard designs. The designs themselves from Figma are still WIP. --- .../model_mercury/component/keyboard/bip39.rs | 9 +-- .../component/keyboard/mnemonic.rs | 57 ++++++++++-------- .../component/keyboard/slip39.rs | 6 +- .../src/ui/model_mercury/res/autofill30.png | Bin 542 -> 534 bytes .../src/ui/model_mercury/res/autofill30.toif | Bin 150 -> 158 bytes .../ui/model_mercury/res/confirm_input30.png | Bin 0 -> 526 bytes .../ui/model_mercury/res/confirm_input30.toif | Bin 0 -> 169 bytes .../src/ui/model_mercury/res/delete30.png | Bin 484 -> 389 bytes .../src/ui/model_mercury/res/delete30.toif | Bin 139 -> 117 bytes .../rust/src/ui/model_mercury/theme/mod.rs | 25 ++++---- 10 files changed, 54 insertions(+), 43 deletions(-) create mode 100644 core/embed/rust/src/ui/model_mercury/res/confirm_input30.png create mode 100644 core/embed/rust/src/ui/model_mercury/res/confirm_input30.toif diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs index 8aba67d34..81e01c2fc 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs @@ -196,7 +196,7 @@ impl Component for Bip39Input { let icon_center = area.top_right().center(area.bottom_right()) - Offset::new(16 + 8, 0); shape::ToifImage::new(icon_center, icon.toif) .with_align(Alignment2D::CENTER) - .with_fg(style.text_color) + .with_fg(style.icon_color) .render(target); } } @@ -227,7 +227,8 @@ impl Bip39Input { // Styling the input to reflect already filled word Self { - button: Button::with_icon(theme::ICON_LIST_CHECK).styled(theme::button_pin_confirm()), + button: Button::with_icon(theme::ICON_CONFIRM_INPUT) + .styled(theme::button_pin_confirm()), textbox: TextBox::new(unwrap!(String::try_from(word))), multi_tap: MultiTapKeyboard::new(), options_num: bip39::options_num(word), @@ -293,7 +294,7 @@ impl Bip39Input { self.button.enable(ctx); self.button.set_stylesheet(ctx, theme::button_pin_confirm()); self.button - .set_content(ctx, ButtonContent::Icon(theme::ICON_LIST_CHECK)); + .set_content(ctx, ButtonContent::Icon(theme::ICON_CONFIRM_INPUT)); self.button_suggestion .set_stylesheet(ctx, theme::button_suggestion_confirm()); } else { @@ -302,7 +303,7 @@ impl Bip39Input { self.button .set_stylesheet(ctx, theme::button_pin_autocomplete()); self.button - .set_content(ctx, ButtonContent::Icon(theme::ICON_CLICK)); + .set_content(ctx, ButtonContent::Icon(theme::ICON_AUTOFILL)); self.button_suggestion .set_stylesheet(ctx, theme::button_suggestion_autocomplete()); } diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs index def0f6897..839dbbcd9 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs @@ -2,7 +2,7 @@ use crate::{ strutil::TString, ui::{ component::{maybe::paint_overlapping, Child, Component, Event, EventCtx, Label, Maybe}, - geometry::{Alignment2D, Grid, Offset, Rect}, + geometry::{Alignment, Grid, Rect}, model_mercury::{ component::{Button, ButtonMsg, Swipe, SwipeDirection}, theme, @@ -44,23 +44,23 @@ where Self { prompt: Child::new(Maybe::new( theme::BG, - Label::centered(prompt, theme::label_keyboard_prompt()), + Label::centered(prompt, theme::TEXT_MAIN_GREY_LIGHT), prompt_visible, )), back: Child::new(Maybe::new( theme::BG, - Button::with_icon_blend( - theme::IMAGE_BG_BACK_BTN_TALL, - theme::ICON_BACK, - Offset::new(30, 17), - ) - .styled(theme::button_reset()) - .with_long_press(theme::ERASE_HOLD_DURATION), + Button::with_icon(theme::ICON_DELETE) + .styled(theme::button_default()) + .with_long_press(theme::ERASE_HOLD_DURATION), !prompt_visible, )), input: Child::new(Maybe::new(theme::BG, input, !prompt_visible)), keys: T::keys() - .map(|t| Button::with_text(t.into()).styled(theme::button_pin())) + .map(|t| { + Button::with_text(t.into()) + .styled(theme::button_pin()) + .with_text_align(Alignment::Center) + }) .map(Child::new), swipe: Swipe::new().right(), can_go_back, @@ -109,23 +109,27 @@ where type Msg = MnemonicKeyboardMsg; fn place(&mut self, bounds: Rect) -> Rect { - let (_, bounds) = bounds - .inset(theme::borders()) - .split_bottom(4 * theme::MNEMONIC_BUTTON_HEIGHT + 3 * theme::KEYBOARD_SPACING); - let grid = Grid::new(bounds, 4, 3).with_spacing(theme::KEYBOARD_SPACING); - let back_area = grid.row_col(0, 0); - let input_area = grid.row_col(0, 1).union(grid.row_col(0, 3)); - - let prompt_center = grid.row_col(0, 0).union(grid.row_col(0, 3)).center(); - let prompt_size = self.prompt.inner().inner().max_size(); - let prompt_area = Rect::snap(prompt_center, prompt_size, Alignment2D::CENTER); + let height_input_area: i16 = 30; + let space_top: i16 = 8; + let (remaining, keyboard_area) = + bounds.split_bottom(3 * theme::BUTTON_HEIGHT + 2 * theme::KEYBOARD_SPACING); + let prompt_area = remaining + .split_top(space_top) + .1 + .split_top(height_input_area) + .0; + assert!(prompt_area.height() == height_input_area); + + let (back_btn_area, input_area) = prompt_area.split_left(30); + let keyboard_grid = Grid::new(keyboard_area, 3, 3).with_spacing(theme::KEYBOARD_SPACING); self.swipe.place(bounds); self.prompt.place(prompt_area); - self.back.place(back_area); + self.back.place(back_btn_area); self.input.place(input_area); + for (key, btn) in self.keys.iter_mut().enumerate() { - btn.place(grid.cell(key + grid.cols)); // Start in the second row. + btn.place(keyboard_grid.cell(key)); } bounds } @@ -185,9 +189,12 @@ where } fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { - self.prompt.render(target); - self.input.render(target); - self.back.render(target); + if self.input.inner().inner().is_empty() { + self.prompt.render(target); + } else { + self.input.render(target); + self.back.render(target); + } for btn in &self.keys { btn.render(target); diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs index 2aba48275..5160e7ddc 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs @@ -181,7 +181,7 @@ impl Component for Slip39Input { icon.draw( icon_center, Alignment2D::CENTER, - style.text_color, + style.icon_color, style.button_color, ); } @@ -247,7 +247,7 @@ impl Component for Slip39Input { let icon_center = area.top_right().center(area.bottom_right()) - Offset::new(16 + 8, 0); shape::ToifImage::new(icon_center, icon.toif) .with_align(Alignment2D::CENTER) - .with_fg(style.text_color) + .with_fg(style.icon_color) .render(target); } } @@ -356,7 +356,7 @@ impl Slip39Input { // Confirm button. self.button.enable(ctx); self.button - .set_content(ctx, ButtonContent::Icon(theme::ICON_LIST_CHECK)); + .set_content(ctx, ButtonContent::Icon(theme::ICON_CONFIRM_INPUT)); } else { // Disabled button. self.button.disable(ctx); diff --git a/core/embed/rust/src/ui/model_mercury/res/autofill30.png b/core/embed/rust/src/ui/model_mercury/res/autofill30.png index 16cd93f3aad96f9335cac1ec45721598e13f22e5..67c67a7b7a1c218a560dfda11de97da751390b86 100644 GIT binary patch literal 534 zcmV+x0_pvUP)D9KhX2`EP=*t@bar58CloyF8Kg`0P2(A5aBu(uuK!8%7w-&s$Z3MIrs7m~lLZX*chF+* zxY5p7qDJ-SYm*5(ZR#PHDKSS6H7wRzc+jHWzaEvV$5Z!6^N`aw%rh(&@;21YqGU&d zdMr-`xJu5XNuu+R(=Oe_w_eA<$dpTz;(5wjBGy^fbrZ5809b-5YWLrkGB$hE>T5V{ z9nS8Rv7JMt*z;#f_qpu?iQzrF5Qk-?r(k({n@6TRgx@x)ZiglzEBw@HTm^>h={o4V z94KQObIS#QzDXZZQYbL(5WwK99b;!9YQ&C9ZWXuvHFPnx8)+1fa|JfWT9sQJ3K#(# z-EC*7dBvWr_#%m7YBv?l05xU$VQ|_R$%2Bq;b(MImWM9RiSFqh#0oDqHPS911+`;u zUYTmKsvU8cxl07zY-L@f7T}2c9ePTWa?Kjai>qC|BQEQ*PDPl2+{2?48@I$+j$A_g Y0S!urym_a7t^fc407*qoM6N<$fG*lJ~1#b>Up|2hG?8`owTs{kby|M{iP!Jqb|zZcKiA?I5Zr&Ce}DNA+PL@ zZNwRt$+I0w$~zRpIg^^WTqdmaIa)S5!`tXa-uWl7`=`FU(5V0b diff --git a/core/embed/rust/src/ui/model_mercury/res/autofill30.toif b/core/embed/rust/src/ui/model_mercury/res/autofill30.toif index 5551d07fe6bcd8545ed1882ac51ff61596a80bc0..712fb68e25660d9a15a1ab494adf9a493f1151c4 100644 GIT binary patch literal 158 zcmV;P0Ac@BPf14}03HC60001EU?3GZlyzhX!+D7vARr3m8FWAZGlbg$<$9nBu57W0Pd|ZTL1t6 literal 150 zcmV;H0BQeJPf14_02%;_0001EU_b*7WgQv9PrL!Z5`<>=;6lz E073jTQvd(} diff --git a/core/embed/rust/src/ui/model_mercury/res/confirm_input30.png b/core/embed/rust/src/ui/model_mercury/res/confirm_input30.png new file mode 100644 index 0000000000000000000000000000000000000000..dc7148c8c6447b2897a02379ed7ea884ccc10c4e GIT binary patch literal 526 zcmV+p0`dKcP)3I94N=Z5u}n`*EIlQ7+@s+|jp~g*1jWpG+7qhF;OH~`Mtp&~0OA_GntZ2^;$0ZxX=0f5{nT(+B#-kxq_(p@-! z$x#W;(*d$_`ch{4PF>m4RDGis>L41boHaHYER*@c0xD@96TUeqDA-60I>(BHGAt7lk*zvA0sAtTZE{B Q2LJ#707*qoM6N<$f}eWceEl!Guoo+T!kOite0uJp8@ zzSRhx@qeMDVx5x`i2JXcoBgYqfH#5vPV}JVS{DMm3H$>uj|JO!bp-D>D5xApa25I= zBec+ptjjX3D7q{f$*w|mARL~q6+pe<4OnUeP}||EH-$o(0%*hXhPui?{1gh{Ez*6T z)d^;-%L9;6Xv{8=(f07~U2XbN3eU-Pj=6|zd)Myn5}aK`JZl|JoOo>pgBy$4hE^U` zg6XXjM!A!G@)kIgMF$UVLn?v2~60+H?6_pOIhvlP4g=zpPu~v`@h{CdyjGMoh8-r$NBs* zkFEWzrxv$gWOVX>!XXozlGsmPsx?{~(?sxNi&t2zn;BQ&j zXqw4aC#9OD>e;D%;2vYZ@!*SXXMb@ViTWni%CKNt_~8aK%ZBXr*8X3AizV!2sSbWr zHa*sM-}CqLLKBQ)Sv;kp(HamwYVfPw*XC#iMf@b0mPD- T`m^GJdKf%i{an^LB{Ts5DgUyS diff --git a/core/embed/rust/src/ui/model_mercury/res/delete30.toif b/core/embed/rust/src/ui/model_mercury/res/delete30.toif index 925396407b17a55886b1f3c832d5b2c3ae9b92d5..eea1cf0df2d0ae34ab434f6ce7ced7b2d81a6d42 100644 GIT binary patch literal 117 zcmV-*0E+)qPf14}03HBo0001EV4x{z=>P*W2rr=n3RuA0b{JO!#4CXDIx>Jf0idLZ zK}QEO&;%g25Gc&S&}_lb0OEoqJ1iIsm>HTu+(NJ}W(EeJ`VN?}77QRsOfH&YG^5Zg XLU#t5Baysd!GI#og5rHOS_Uxy^(-mU literal 139 zcmV;60CfLUPf14`02Ba!0000@&#?*uF%SgMAtu`T34)-OK^tqU^jf5}yi%}9?V&fH z?ad}=rdb}dfh+)QP8J8{&YHdOXyBm-S3T$q=QoGvJPa9Q#*6f}w!{^YO!ZBGz#E%{ t^f6>$oQIzpqy%X|43al3BEwphR4(LhQf1x$zdsf9a-B-O`DpiVfiKp*K9>Lh diff --git a/core/embed/rust/src/ui/model_mercury/theme/mod.rs b/core/embed/rust/src/ui/model_mercury/theme/mod.rs index 48f28f81b..1aeb18bc6 100644 --- a/core/embed/rust/src/ui/model_mercury/theme/mod.rs +++ b/core/embed/rust/src/ui/model_mercury/theme/mod.rs @@ -88,6 +88,7 @@ include_icon!(ICON_WARNING, "model_mercury/res/warning24.toif"); // 30x30 include_icon!(ICON_AUTOFILL, "model_mercury/res/autofill30.toif"); include_icon!(ICON_CLOSE, "model_mercury/res/close30.toif"); +include_icon!(ICON_CONFIRM_INPUT, "model_mercury/res/confirm_input30.toif"); include_icon!(ICON_DELETE, "model_mercury/res/delete30.toif"); include_icon!(ICON_MENU, "model_mercury/res/menu30.toif"); include_icon!( @@ -411,27 +412,29 @@ pub const fn button_pin() -> ButtonStyleSheet { } } +// TODO: will button_pin_xyz styles be the same for PIN and Mnemonic keyboard? +// Wait for Figma pub const fn button_pin_confirm() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREEN, - icon_color: GREY_LIGHT, + button_color: BG, + icon_color: GREEN_LIGHT, background_color: BG, }, active: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREEN_DARK, - icon_color: GREY_LIGHT, + button_color: GREY_DARK, + icon_color: GREEN_LIGHT, background_color: BG, }, disabled: &ButtonStyle { font: Font::MONO, - text_color: GREY_LIGHT, - button_color: GREY_DARK, - icon_color: GREY_LIGHT, + text_color: FG, + button_color: BG, + icon_color: GREEN_LIGHT, background_color: BG, }, } @@ -442,20 +445,20 @@ pub const fn button_pin_autocomplete() -> ButtonStyleSheet { normal: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREY_DARK, // same as PIN buttons + button_color: BG, icon_color: GREY_LIGHT, background_color: BG, }, active: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREEN_DARK, + button_color: BG, icon_color: GREY_LIGHT, background_color: BG, }, disabled: &ButtonStyle { font: Font::MONO, - text_color: GREY_LIGHT, + text_color: FG, button_color: BG, icon_color: GREY_LIGHT, background_color: BG, @@ -467,7 +470,7 @@ pub const fn button_suggestion_confirm() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::MONO, - text_color: GREEN_DARK, + text_color: GREY_LIGHT, button_color: GREEN, icon_color: GREY_LIGHT, background_color: BG,