1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-29 18:08:19 +00:00

feat(eckhart): show battery indication in BLD

- shown in bootloader menu
- shown in more info screen in wireless setup flow

[no changelog]
This commit is contained in:
obrusvit 2025-07-14 20:17:04 +02:00 committed by Vít Obrusník
parent ff310dd816
commit 5477acdfd4
3 changed files with 40 additions and 14 deletions

View File

@ -9,7 +9,7 @@ use crate::{
}; };
use super::super::{ use super::super::{
component::{Button, ButtonContent, ButtonMsg}, component::{Button, ButtonContent, ButtonMsg, FuelGauge},
constant, theme, constant, theme,
}; };
@ -28,6 +28,8 @@ pub struct BldHeader<'a> {
/// icon in the top-left corner (used instead of left button) /// icon in the top-left corner (used instead of left button)
icon: Option<Icon>, icon: Option<Icon>,
icon_color: Option<Color>, icon_color: Option<Color>,
/// Battery status indicator
fuel_gauge: Option<FuelGauge>,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -57,6 +59,7 @@ impl<'a> BldHeader<'a> {
left_button_msg: BldHeaderMsg::Cancelled, left_button_msg: BldHeaderMsg::Cancelled,
icon: None, icon: None,
icon_color: None, icon_color: None,
fuel_gauge: None,
} }
} }
@ -121,6 +124,11 @@ impl<'a> BldHeader<'a> {
} }
} }
#[inline(never)]
pub fn with_fuel_gauge(self, fuel_gauge: Option<FuelGauge>) -> Self {
Self { fuel_gauge, ..self }
}
/// Calculates the width needed for the left icon, be it a button with icon /// Calculates the width needed for the left icon, be it a button with icon
/// or just icon /// or just icon
fn left_icon_width(&self) -> i16 { fn left_icon_width(&self) -> i16 {
@ -147,23 +155,26 @@ impl<'a> Component for BldHeader<'a> {
let bounds = bounds.inset(Self::HEADER_INSETS); let bounds = bounds.inset(Self::HEADER_INSETS);
let rest = if let Some(b) = &mut self.right_button { let rest = if let Some(b) = &mut self.right_button {
let (rest, button_area) = bounds.split_right(Self::HEADER_BUTTON_WIDTH); let (rest, right_button_area) = bounds.split_right(Self::HEADER_BUTTON_WIDTH);
b.place(button_area); b.place(right_button_area);
rest rest
} else { } else {
bounds bounds
}; };
let icon_width = self.left_icon_width(); let icon_width = self.left_icon_width();
let (rest, title_area) = rest.split_left(icon_width); let (left_button_area, title_area) = rest.split_left(icon_width);
self.left_button.place(rest); self.left_button.place(left_button_area);
self.title.place(title_area); self.title.place(title_area);
self.fuel_gauge.place(title_area.union(left_button_area));
self.area = bounds; self.area = bounds;
bounds bounds
} }
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> { fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
self.fuel_gauge.event(ctx, event);
if let Some(ButtonMsg::Clicked) = self.left_button.event(ctx, event) { if let Some(ButtonMsg::Clicked) = self.left_button.event(ctx, event) {
return Some(self.left_button_msg); return Some(self.left_button_msg);
}; };
@ -175,6 +186,7 @@ impl<'a> Component for BldHeader<'a> {
} }
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
self.fuel_gauge.render(target);
self.right_button.render(target); self.right_button.render(target);
self.left_button.render(target); self.left_button.render(target);
if let Some(icon) = self.icon { if let Some(icon) = self.icon {

View File

@ -1,12 +1,18 @@
use crate::ui::{ use crate::{
component::{Component, Event, EventCtx}, strutil::TString,
geometry::{Alignment, Rect}, ui::{
layout_eckhart::component::Button, component::{Component, Event, EventCtx},
shape::Renderer, geometry::{Alignment, Rect},
shape::Renderer,
},
}; };
use super::{ use super::{
super::{cshape::ScreenBorder, theme}, super::{
component::{Button, FuelGauge},
cshape::ScreenBorder,
theme,
},
bld_menu::BldMenuSelectionMsg, bld_menu::BldMenuSelectionMsg,
BldHeader, BldHeaderMsg, BldMenu, BldHeader, BldHeaderMsg, BldMenu,
}; };
@ -51,7 +57,9 @@ impl BldMenuScreen {
.item(turnoff) .item(turnoff)
.item(reset); .item(reset);
Self { Self {
header: BldHeader::new("Bootloader".into()).with_close_button(), header: BldHeader::new(TString::empty())
.with_fuel_gauge(Some(FuelGauge::always()))
.with_close_button(),
menu, menu,
screen_border: None, screen_border: None,
} }

View File

@ -9,7 +9,11 @@ use crate::{
}; };
use super::{ use super::{
super::{component::Button, constant::SCREEN, theme}, super::{
component::{Button, FuelGauge},
constant::SCREEN,
theme,
},
pairing_mode::PairingMsg, pairing_mode::PairingMsg,
BldActionBar, BldActionBarMsg, BldHeader, BldHeaderMsg, BldActionBar, BldActionBarMsg, BldHeader, BldHeaderMsg,
}; };
@ -49,7 +53,9 @@ impl WirelessSetupScreen {
.styled(theme::button_default()) .styled(theme::button_default())
.initially_enabled(false); .initially_enabled(false);
let more_info = MoreInfo { let more_info = MoreInfo {
header: BldHeader::new("More info".into()).with_close_button(), header: BldHeader::new(TString::empty())
.with_fuel_gauge(Some(FuelGauge::always()))
.with_close_button(),
instruction_primary: Label::left_aligned( instruction_primary: Label::left_aligned(
"The Trezor Suite app is required to set up your Trezor.".into(), "The Trezor Suite app is required to set up your Trezor.".into(),
theme::TEXT_NORMAL, theme::TEXT_NORMAL,