1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-03 16:56:07 +00:00

feat(eckhart): improve ActionBar content

- button content is moved towards the center a bit
- shrink left button at the last page of paginated component
- change the order of render in `TextScreen` to account for Header
overlay. If the main content reaches the Header area, we do not want to
overlay it during Hold to Confirm animation
This commit is contained in:
obrusvit 2025-03-01 13:05:44 +01:00
parent cea2d5f72f
commit 5edb72ebe9
3 changed files with 53 additions and 39 deletions

View File

@ -256,7 +256,7 @@ impl Button {
let y_offset = Offset::y(self.content_height() / 2); let y_offset = Offset::y(self.content_height() / 2);
let start_of_baseline = match self.text_align { let start_of_baseline = match self.text_align {
Alignment::Start => self.area.left_center() + self.content_offset, Alignment::Start => self.area.left_center() + self.content_offset,
Alignment::Center => self.area.center(), Alignment::Center => self.area.center() + self.content_offset,
Alignment::End => self.area.right_center() - self.content_offset, Alignment::End => self.area.right_center() - self.content_offset,
} + y_offset; } + y_offset;
text.map(|text| { text.map(|text| {
@ -273,7 +273,7 @@ impl Button {
let subtext_y_offset = Offset::y(self.content_height() / 2); let subtext_y_offset = Offset::y(self.content_height() / 2);
let start_of_baseline = match self.text_align { let start_of_baseline = match self.text_align {
Alignment::Start => self.area.left_center() + self.content_offset, Alignment::Start => self.area.left_center() + self.content_offset,
Alignment::Center => self.area.center(), Alignment::Center => self.area.center() + self.content_offset,
Alignment::End => self.area.right_center() - self.content_offset, Alignment::End => self.area.right_center() - self.content_offset,
}; };
let text_baseline = start_of_baseline - text_y_offset; let text_baseline = start_of_baseline - text_y_offset;
@ -296,7 +296,7 @@ impl Button {
}); });
} }
ButtonContent::Icon(icon) => { ButtonContent::Icon(icon) => {
shape::ToifImage::new(self.area.center(), icon.toif) shape::ToifImage::new(self.area.center() + self.content_offset, icon.toif)
.with_align(Alignment2D::CENTER) .with_align(Alignment2D::CENTER)
.with_fg(style.icon_color) .with_fg(style.icon_color)
.with_alpha(alpha) .with_alpha(alpha)

View File

@ -22,9 +22,8 @@ pub struct ActionBar {
/// Optional left button, can be shorter than the right one /// Optional left button, can be shorter than the right one
left_button: Option<Button>, left_button: Option<Button>,
area: Rect, area: Rect,
/// Whether the left button is short /// Whether the left button is short (default: true)
left_short: bool, left_short: bool,
// TODO: review cloning() of those fields
// Storage of original button content for paginated component // Storage of original button content for paginated component
left_original: Option<(ButtonContent, ButtonStyleSheet)>, left_original: Option<(ButtonContent, ButtonStyleSheet)>,
right_original: Option<(ButtonContent, ButtonStyleSheet)>, right_original: Option<(ButtonContent, ButtonStyleSheet)>,
@ -55,7 +54,6 @@ impl ActionBar {
pub const ACTION_BAR_HEIGHT: i16 = 90; // [px] pub const ACTION_BAR_HEIGHT: i16 = 90; // [px]
const SPACER_WIDTH: i16 = 4; // [px] const SPACER_WIDTH: i16 = 4; // [px]
const LEFT_SMALL_BUTTON_WIDTH: i16 = 120; // [px] const LEFT_SMALL_BUTTON_WIDTH: i16 = 120; // [px]
/// TODO: use this offset
/// offset for button content to move it towards center /// offset for button content to move it towards center
const BUTTON_CONTENT_OFFSET: Offset = Offset::x(12); // [px] const BUTTON_CONTENT_OFFSET: Offset = Offset::x(12); // [px]
const BUTTON_EXPAND_TOUCH: Insets = Insets::top(Self::ACTION_BAR_HEIGHT); const BUTTON_EXPAND_TOUCH: Insets = Insets::top(Self::ACTION_BAR_HEIGHT);
@ -81,8 +79,13 @@ impl ActionBar {
Mode::Double { Mode::Double {
pager: Pager::single_page(), pager: Pager::single_page(),
}, },
Some(left.with_expanded_touch_area(Self::BUTTON_EXPAND_TOUCH)), Some(
right.with_expanded_touch_area(Self::BUTTON_EXPAND_TOUCH), left.with_expanded_touch_area(Self::BUTTON_EXPAND_TOUCH)
.with_content_offset(Self::BUTTON_CONTENT_OFFSET),
),
right
.with_expanded_touch_area(Self::BUTTON_EXPAND_TOUCH)
.with_content_offset(Self::BUTTON_CONTENT_OFFSET * -1.0),
) )
} }
@ -99,8 +102,11 @@ impl ActionBar {
} }
pub fn update(&mut self, new_pager: Pager) { pub fn update(&mut self, new_pager: Pager) {
// TODO: review `clone()` of `left_content`/`right_content`
match &mut self.mode { match &mut self.mode {
Mode::Double { pager } => { Mode::Double { pager } => {
let old_is_last = pager.is_last();
let new_is_last = new_pager.is_last();
*pager = new_pager; *pager = new_pager;
// Update left button - show original content/style only on first page // Update left button - show original content/style only on first page
if let Some(btn) = &mut self.left_button { if let Some(btn) = &mut self.left_button {
@ -123,14 +129,17 @@ impl ActionBar {
self.right_button.set_content(Self::PAGINATE_RIGHT_CONTENT); self.right_button.set_content(Self::PAGINATE_RIGHT_CONTENT);
self.right_button.set_stylesheet(*Self::PAGINATE_STYLESHEET); self.right_button.set_stylesheet(*Self::PAGINATE_STYLESHEET);
} }
// If we're entering or leaving the last page and left_short is true,
// we need to update the button placement
if self.left_short && (old_is_last != new_is_last) {
self.place_buttons(self.area);
}
} }
_ => {} _ => {}
} }
} }
// TODO: changing the left button to short/equal on paginated last page?
// TODO: single button which is disabled for "Continue in the app" screen
fn new(mode: Mode, left_button: Option<Button>, right_button: Button) -> Self { fn new(mode: Mode, left_button: Option<Button>, right_button: Button) -> Self {
let (left_original, right_original) = match mode { let (left_original, right_original) = match mode {
Mode::Double { .. } => ( Mode::Double { .. } => (
@ -159,20 +168,20 @@ impl ActionBar {
right_button, right_button,
left_button, left_button,
area: Rect::zero(), area: Rect::zero(),
left_short: false, left_short: true,
left_original, left_original,
right_original, right_original,
htc_anim, htc_anim,
} }
} }
/// Handle right button at the last page, this includes: /// Handle event of the right button at the last page, this includes:
/// - Single button mode /// - Single button mode
/// - Double button mode at single page component /// - Double button mode at single page component
/// - Double button mode at last page of paginated component /// - Double button mode at last page of paginated component
/// The function takes care about triggering the correct action to /// The function takes care about triggering the correct action to
/// HoldToConfirm or returning the correct message out of the ActionBar. /// HoldToConfirm or returning the correct message out of the ActionBar.
fn right_button_at_last_page( fn event_right_button_at_last_page(
&mut self, &mut self,
ctx: &mut EventCtx, ctx: &mut EventCtx,
msg: ButtonMsg, msg: ButtonMsg,
@ -213,20 +222,15 @@ impl ActionBar {
} }
None None
} }
}
impl Component for ActionBar {
type Msg = ActionBarMsg;
fn place(&mut self, bounds: Rect) -> Rect {
debug_assert_eq!(bounds.height(), Self::ACTION_BAR_HEIGHT);
fn place_buttons(&mut self, bounds: Rect) {
match &self.mode { match &self.mode {
Mode::Single => { Mode::Single => {
self.right_button.place(bounds); self.right_button.place(bounds);
} }
Mode::Double { .. } => { Mode::Double { pager } => {
let (left, right) = if self.left_short { if self.left_short {
let (left, right) = if pager.is_last() {
let (left, rest) = bounds.split_left(Self::LEFT_SMALL_BUTTON_WIDTH); let (left, rest) = bounds.split_left(Self::LEFT_SMALL_BUTTON_WIDTH);
let (_, right) = rest.split_left(Self::SPACER_WIDTH); let (_, right) = rest.split_left(Self::SPACER_WIDTH);
(left, right) (left, right)
@ -234,13 +238,23 @@ impl Component for ActionBar {
let (left, _spacer, right) = bounds.split_center(Self::SPACER_WIDTH); let (left, _spacer, right) = bounds.split_center(Self::SPACER_WIDTH);
(left, right) (left, right)
}; };
if let Some(btn) = &mut self.left_button { if let Some(btn) = &mut self.left_button {
btn.place(left); btn.place(left);
} }
self.right_button.place(right); self.right_button.place(right);
} }
} }
}
}
}
impl Component for ActionBar {
type Msg = ActionBarMsg;
fn place(&mut self, bounds: Rect) -> Rect {
debug_assert_eq!(bounds.height(), Self::ACTION_BAR_HEIGHT);
self.place_buttons(bounds);
self.area = bounds; self.area = bounds;
bounds bounds
} }
@ -251,7 +265,7 @@ impl Component for ActionBar {
Mode::Single => { Mode::Single => {
// Only handle confirm button // Only handle confirm button
if let Some(msg) = self.right_button.event(ctx, event) { if let Some(msg) = self.right_button.event(ctx, event) {
return self.right_button_at_last_page(ctx, msg); return self.event_right_button_at_last_page(ctx, msg);
} }
} }
Mode::Double { pager } => { Mode::Double { pager } => {
@ -261,7 +275,7 @@ impl Component for ActionBar {
return Some(ActionBarMsg::Cancelled); return Some(ActionBarMsg::Cancelled);
} }
if let Some(msg) = self.right_button.event(ctx, event) { if let Some(msg) = self.right_button.event(ctx, event) {
return self.right_button_at_last_page(ctx, msg); return self.event_right_button_at_last_page(ctx, msg);
} }
} else if pager.is_first() && !pager.is_single() { } else if pager.is_first() && !pager.is_single() {
// First page of multiple - go back and next page // First page of multiple - go back and next page
@ -277,7 +291,7 @@ impl Component for ActionBar {
return Some(ActionBarMsg::Prev); return Some(ActionBarMsg::Prev);
} }
if let Some(msg) = self.right_button.event(ctx, event) { if let Some(msg) = self.right_button.event(ctx, event) {
return self.right_button_at_last_page(ctx, msg); return self.event_right_button_at_last_page(ctx, msg);
} }
} else { } else {
// Middle pages - navigations up/down // Middle pages - navigations up/down

View File

@ -124,9 +124,9 @@ where
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
self.header.render(target); self.header.render(target);
self.content.render(target);
self.hint.render(target); self.hint.render(target);
self.action_bar.render(target); self.action_bar.render(target);
self.content.render(target);
} }
} }