From dc9958e5a6eb7c1db29d327740e200d589886f7b Mon Sep 17 00:00:00 2001 From: obrusvit Date: Sat, 15 Mar 2025 14:32:55 +0100 Subject: [PATCH] feat(eckhart): implement homescreen ButtonContent --- .../src/ui/layout_eckhart/component/button.rs | 44 ++++++++++++++++++ .../firmware/keyboard/passphrase.rs | 45 +++++++++---------- 2 files changed, 66 insertions(+), 23 deletions(-) diff --git a/core/embed/rust/src/ui/layout_eckhart/component/button.rs b/core/embed/rust/src/ui/layout_eckhart/component/button.rs index e02a1ffa9d..4eb73eccf1 100644 --- a/core/embed/rust/src/ui/layout_eckhart/component/button.rs +++ b/core/embed/rust/src/ui/layout_eckhart/component/button.rs @@ -75,6 +75,11 @@ impl Button { Self::new(ButtonContent::IconAndText(content)) } + #[cfg(feature = "micropython")] + pub const fn with_homebar_content(text: Option>) -> Self { + Self::new(ButtonContent::HomeBar(text)) + } + pub const fn empty() -> Self { Self::new(ButtonContent::Empty) } @@ -189,6 +194,8 @@ impl Button { + Self::LINE_SPACING + Self::SUBTEXT_STYLE.text_font.allcase_text_height() } + #[cfg(feature = "micropython")] + ButtonContent::HomeBar(_) => theme::ACTION_BAR_HEIGHT, } } @@ -305,6 +312,39 @@ impl Button { ButtonContent::IconAndText(child) => { child.render(target, self.area, self.style(), self.content_offset, alpha); } + #[cfg(feature = "micropython")] + ButtonContent::HomeBar(text) => { + let baseline = self.area.center(); + if let Some(text) = text { + const OFFSET_Y: Offset = Offset::y(25); + text.map(|text| { + shape::Text::new(baseline, text, style.font) + .with_fg(style.text_color) + .with_align(Alignment::Center) + .with_alpha(alpha) + .render(target); + }); + shape::ToifImage::new( + self.area.center() + OFFSET_Y, + theme::ICON_DASH_HORIZONTAL.toif, + ) + .with_fg(style.icon_color) + .with_align(Alignment2D::CENTER) + .render(target); + } else { + // double dash icon in the middle + const OFFSET_Y: Offset = Offset::y(5); + shape::ToifImage::new(baseline - OFFSET_Y, theme::ICON_DASH_HORIZONTAL.toif) + .with_fg(theme::GREY_LIGHT) + .with_align(Alignment2D::CENTER) + .render(target); + + shape::ToifImage::new(baseline + OFFSET_Y, theme::ICON_DASH_HORIZONTAL.toif) + .with_fg(theme::GREY_LIGHT) + .with_align(Alignment2D::CENTER) + .render(target); + } + } } } @@ -444,6 +484,8 @@ impl crate::trace::Trace for Button { ButtonContent::TextAndSubtext(text, _) => { t.string("text", *text); } + #[cfg(feature = "micropython")] + ButtonContent::HomeBar(text) => t.string("text", text.unwrap_or(TString::empty())), } } } @@ -463,6 +505,8 @@ pub enum ButtonContent { TextAndSubtext(TString<'static>, TString<'static>), Icon(Icon), IconAndText(IconText), + #[cfg(feature = "micropython")] + HomeBar(Option>), } #[derive(PartialEq, Eq, Clone, Copy)] diff --git a/core/embed/rust/src/ui/layout_eckhart/firmware/keyboard/passphrase.rs b/core/embed/rust/src/ui/layout_eckhart/firmware/keyboard/passphrase.rs index d5787b8fba..add4d638d6 100644 --- a/core/embed/rust/src/ui/layout_eckhart/firmware/keyboard/passphrase.rs +++ b/core/embed/rust/src/ui/layout_eckhart/firmware/keyboard/passphrase.rs @@ -142,14 +142,12 @@ impl PassphraseKeyboard { } } - fn key_text(content: &ButtonContent) -> TString<'static> { + fn key_text(content: &ButtonContent) -> Option> { match content { - ButtonContent::Text(text) => *text, - ButtonContent::TextAndSubtext(_, _) => "".into(), - ButtonContent::Icon(theme::ICON_SPECIAL_CHARS) => " *#".into(), - ButtonContent::Icon(_) => " ".into(), - ButtonContent::IconAndText(_) => " ".into(), - ButtonContent::Empty => "".into(), + ButtonContent::Text(text) => Some(*text), + ButtonContent::Icon(theme::ICON_SPECIAL_CHARS) => Some(" *#".into()), + ButtonContent::Icon(_) => Some(" ".into()), + _ => None, } } @@ -312,23 +310,24 @@ impl Component for PassphraseKeyboard { match self.keypad.event(ctx, event) { Some(KeypadMsg::Key(idx)) => { - let text = Self::key_text(self.keypad.get_key_content(idx)); - let edit = text.map(|c| self.multi_tap.click_key(ctx, idx, c)); - self.input.textbox.apply(ctx, edit); - 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)); - } else { - // multi tap timer is runnig, the last digit timer should be stopped - self.input.last_char_timer.stop(); - self.input.marker = true; + if let Some(text) = Self::key_text(self.keypad.get_key_content(idx)) { + let edit = text.map(|c| self.multi_tap.click_key(ctx, idx, c)); + self.input.textbox.apply(ctx, edit); + 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)); + } 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::LastOnly; + self.update_keypad_state(ctx); } - self.input.display_style = DisplayStyle::LastOnly; - self.update_keypad_state(ctx); return None; } Some(KeypadMsg::EraseShort) => {