From 7f8303906c8e29818362a8d112732e3e1bfb36c6 Mon Sep 17 00:00:00 2001 From: Lukas Bielesch Date: Wed, 26 Mar 2025 09:39:36 +0100 Subject: [PATCH] chore(eckhart): text screen subtitle --- .../ui/layout_eckhart/firmware/text_screen.rs | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs b/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs index a25f9c16eb..88b84bcba7 100644 --- a/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs +++ b/core/embed/rust/src/ui/layout_eckhart/firmware/text_screen.rs @@ -1,16 +1,23 @@ -use crate::ui::{ - component::{ - swipe_detect::SwipeConfig, - text::paragraphs::{Checklist, ParagraphSource, Paragraphs}, - Component, Event, EventCtx, FormattedText, PaginateFull, +use crate::{ + strutil::TString, + ui::{ + component::{ + swipe_detect::SwipeConfig, + text::paragraphs::{Checklist, ParagraphSource, Paragraphs}, + Component, Event, EventCtx, FormattedText, Label, PaginateFull, + }, + flow::Swipable, + geometry::{Insets, Rect}, + shape::Renderer, + util::Pager, }, - flow::Swipable, - geometry::{Insets, Rect}, - shape::Renderer, - util::Pager, }; -use super::{action_bar::ActionBarMsg, theme::SIDE_INSETS, ActionBar, Header, HeaderMsg, Hint}; +use super::{ + action_bar::ActionBarMsg, + theme::{self, SIDE_INSETS}, + ActionBar, Header, HeaderMsg, Hint, +}; /// Full-screen component for rendering text. /// @@ -22,6 +29,7 @@ use super::{action_bar::ActionBarMsg, theme::SIDE_INSETS, ActionBar, Header, Hea /// - Action bar (Optional) pub struct TextScreen { header: Option
, + subtitle: Option>, content: T, hint: Option>, action_bar: Option, @@ -40,10 +48,12 @@ where T: AllowedTextContent, { const CONTENT_INSETS: Insets = SIDE_INSETS; + const SUBTITLE_HEIGHT: i16 = 44; pub fn new(content: T) -> Self { Self { header: None, + subtitle: None, content, hint: None, action_bar: None, @@ -55,6 +65,14 @@ where self } + pub fn with_subtitle(mut self, subtitle: TString<'static>) -> Self { + if !subtitle.is_empty() { + self.subtitle = + Some(Label::left_aligned(subtitle, theme::TEXT_MEDIUM_EXTRA_LIGHT).top_aligned()); + } + self + } + pub fn with_hint(mut self, hint: Hint<'static>) -> Self { self.hint = Some(hint); self @@ -86,6 +104,14 @@ where fn place(&mut self, bounds: Rect) -> Rect { let (header_area, rest) = bounds.split_top(Header::HEADER_HEIGHT); let (rest, action_bar_area) = rest.split_bottom(ActionBar::ACTION_BAR_HEIGHT); + let rest = if let Some(subtitle) = &mut self.subtitle { + let (subtitle_area, rest) = rest.split_top(Self::SUBTITLE_HEIGHT); + subtitle.place(subtitle_area.inset(SIDE_INSETS)); + rest + } else { + rest + }; + let content_area = if let Some(hint) = &mut self.hint { let (rest, hint_area) = rest.split_bottom(hint.height()); hint.place(hint_area); @@ -128,6 +154,7 @@ where fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.header.render(target); + self.subtitle.render(target); self.hint.render(target); self.action_bar.render(target); self.content.render(target); @@ -163,6 +190,9 @@ where if let Some(header) = self.header.as_ref() { header.trace(t); } + if let Some(subtitle) = self.subtitle.as_ref() { + subtitle.trace(t); + } self.content.trace(t); if let Some(hint) = self.hint.as_ref() { hint.trace(t);