refactor(core): simplify FuelGauge Component
What changed, and why it matters
This commit is a routine user-interface cleanup for the Trezor hardware wallet's battery icon. It removes an older 'HomescreenBar' display mode and replaces it with a simpler 'AlwaysIconOnly' mode, while also dropping an alignment option. There is no indication in the commit that this fixes a security bug or changes security behavior.
No security action required; treat as normal UI refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors the FuelGauge component in the Rust UI layer for the Eckhart layout. It removes the HomescreenBar variant (which combined a timer with animation-disabled checks) and the with_alignment builder, adds AlwaysIconOnly, and updates the homescreen to use FuelGauge::always_icon_only(). It also removes PartialEq/Eq from ChargingState and replaces some equality checks with matches!. These are cosmetic/simplification changes with no security-relevant logic visible in the diff.
Changed components
core/embed/rust/src/ui/layout_eckhart/component/fuel_gauge.rscore/embed/rust/src/ui/layout_eckhart/firmware/homescreen.rscore/embed/rust/src/trezorhal/power_manager.rsInspect captured patch +31 / −65
diff --git a/core/embed/rust/src/trezorhal/power_manager.rs b/core/embed/rust/src/trezorhal/power_manager.rs
index 24077b7c..3d0bbf82 100644
--- a/core/embed/rust/src/trezorhal/power_manager.rs
+++ b/core/embed/rust/src/trezorhal/power_manager.rs
@@ -4,7 +4,7 @@ use core::ptr::null_mut;
#[cfg(feature = "ui")]
use crate::ui::event::PMEvent;
-#[derive(PartialEq, Eq, Copy, Clone)]
+#[derive(Copy, Clone)]
pub enum ChargingState {
Discharging,
Charging,
diff --git a/core/embed/rust/src/ui/layout_eckhart/component/fuel_gauge.rs b/core/embed/rust/src/ui/layout_eckhart/component/fuel_gauge.rs
index 08d6c6bc..8eed6656 100644
--- a/core/embed/rust/src/ui/layout_eckhart/component/fuel_gauge.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/component/fuel_gauge.rs
@@ -9,7 +9,7 @@ use crate::{
};
#[cfg(feature = "micropython")]
-use crate::ui::{component::Timer, util::animation_disabled};
+use crate::ui::component::Timer;
use super::super::{
fonts,
@@ -29,8 +29,6 @@ use super::super::theme::firmware::FUEL_GAUGE_DURATION;
pub struct FuelGauge {
/// Area where the fuel gauge is rendered
area: Rect,
- /// Alignment of the fuel gauge within its area
- alignment: Alignment,
/// Mode of the fuel gauge (Always or OnChrgStatusChange)
mode: FuelGaugeMode,
/// State of battery charging
@@ -43,21 +41,24 @@ pub struct FuelGauge {
#[derive(Clone)]
pub enum FuelGaugeMode {
- /// Always show the fuel gauge
- Always,
- /// Show only charging icon if the device is charging
+ /// Always show the fuel gauge, both icon and percentage
+ AlwaysFull,
+ /// Always show the fuel gauge, but only icon
+ AlwaysIconOnly,
+ /// Show only charging icon when the device is charging
ChargingIconOnly,
/// Show the fuel gauge only when charging state changes
#[cfg(feature = "micropython")]
OnChargingChange(Timer),
- /// Show only icon when charging state changes or when attached
- #[cfg(feature = "micropython")]
- HomescreenBar(Timer),
}
impl FuelGauge {
pub const fn always() -> Self {
- Self::new(FuelGaugeMode::Always)
+ Self::new(FuelGaugeMode::AlwaysFull)
+ }
+
+ pub const fn always_icon_only() -> Self {
+ Self::new(FuelGaugeMode::AlwaysIconOnly)
}
pub const fn charging_icon_only() -> Self {
@@ -69,21 +70,6 @@ impl FuelGauge {
Self::new(FuelGaugeMode::OnChargingChange(Timer::new()))
}
- #[cfg(feature = "micropython")]
- pub const fn homescreen_bar() -> Self {
- Self::new(FuelGaugeMode::HomescreenBar(Timer::new()))
- }
-
- pub const fn with_alignment(mut self, alignment: Alignment) -> Self {
- self.alignment = alignment;
- self
- }
-
- pub const fn with_font(mut self, font: Font) -> Self {
- self.font = font;
- self
- }
-
pub fn update_pm_state(&mut self) {
self.soc = Some(power_manager::soc());
self.charging_state = power_manager::charging_state();
@@ -91,12 +77,12 @@ impl FuelGauge {
pub fn should_be_shown(&self) -> bool {
match &self.mode {
- FuelGaugeMode::Always => true,
- FuelGaugeMode::ChargingIconOnly => self.charging_state == ChargingState::Charging,
- #[cfg(feature = "micropython")]
- FuelGaugeMode::OnChargingChange(timer) | FuelGaugeMode::HomescreenBar(timer) => {
- timer.is_running()
+ FuelGaugeMode::AlwaysFull | FuelGaugeMode::AlwaysIconOnly => true,
+ FuelGaugeMode::ChargingIconOnly => {
+ matches!(self.charging_state, ChargingState::Charging)
}
+ #[cfg(feature = "micropython")]
+ FuelGaugeMode::OnChargingChange(timer) => timer.is_running(),
}
}
@@ -107,7 +93,6 @@ impl FuelGauge {
let font = fonts::FONT_SATOSHI_MEDIUM_26;
Self {
area: Rect::zero(),
- alignment: Alignment::Start,
mode,
charging_state: ChargingState::Idle,
soc: None,
@@ -157,18 +142,12 @@ impl Component for FuelGauge {
if self.soc.is_none() {
self.update_pm_state();
}
- #[cfg(feature = "micropython")]
- if let FuelGaugeMode::HomescreenBar(timer) = &mut self.mode {
- if !animation_disabled() {
- timer.start(ctx, FUEL_GAUGE_DURATION.into());
- }
- }
ctx.request_paint();
}
Event::PM(_e) => {
self.update_pm_state();
match &mut self.mode {
- FuelGaugeMode::Always => {
+ FuelGaugeMode::AlwaysFull | FuelGaugeMode::AlwaysIconOnly => {
ctx.request_paint();
}
FuelGaugeMode::ChargingIconOnly => {
@@ -177,8 +156,7 @@ impl Component for FuelGauge {
}
}
#[cfg(feature = "micropython")]
- FuelGaugeMode::OnChargingChange(timer)
- | FuelGaugeMode::HomescreenBar(timer) => {
+ FuelGaugeMode::OnChargingChange(timer) => {
if _e.charging_status_changed {
timer.start(ctx, FUEL_GAUGE_DURATION.into());
ctx.request_paint();
@@ -188,7 +166,7 @@ impl Component for FuelGauge {
}
#[cfg(feature = "micropython")]
Event::Timer(_) => match &mut self.mode {
- FuelGaugeMode::OnChargingChange(timer) | FuelGaugeMode::HomescreenBar(timer) => {
+ FuelGaugeMode::OnChargingChange(timer) => {
if timer.expire(event) {
ctx.request_paint();
}
@@ -216,12 +194,7 @@ impl Component for FuelGauge {
let icon_width = icon.toif.width();
let icon_height = icon.toif.height();
- let (point, alignment) = match self.alignment {
- Alignment::Start => (self.area.left_center(), Alignment2D::CENTER_LEFT),
- Alignment::End => (self.area.right_center(), Alignment2D::CENTER_RIGHT),
- Alignment::Center => (self.area.center(), Alignment2D::CENTER),
- };
-
+ let (point, alignment) = (self.area.left_center(), Alignment2D::CENTER_LEFT);
let area = Rect::snap(
point,
Offset::new(
@@ -233,22 +206,22 @@ impl Component for FuelGauge {
let text_y_coord = self.font.vert_center(area.y0, area.y1, &soc_percent_fmt);
match self.mode {
+ FuelGaugeMode::AlwaysIconOnly => {
+ shape::ToifImage::new(area.left_center(), icon.toif)
+ .with_fg(color_icon)
+ .with_align(Alignment2D::CENTER_LEFT)
+ .render(target);
+ }
FuelGaugeMode::ChargingIconOnly => {
- if self.charging_state == ChargingState::Charging {
+ if matches!(self.charging_state, ChargingState::Charging) {
shape::ToifImage::new(area.left_center(), icon.toif)
.with_fg(color_icon)
.with_align(Alignment2D::CENTER_LEFT)
.render(target);
}
}
- #[cfg(feature = "micropython")]
- FuelGaugeMode::HomescreenBar(_) => {
- shape::ToifImage::new(area.center(), icon.toif)
- .with_fg(color_icon)
- .with_align(Alignment2D::CENTER)
- .render(target);
- }
_ => {
+ // both icon and percentage
shape::ToifImage::new(area.left_center(), icon.toif)
.with_fg(color_icon)
.with_align(Alignment2D::CENTER_LEFT)
diff --git a/core/embed/rust/src/ui/layout_eckhart/firmware/homescreen.rs b/core/embed/rust/src/ui/layout_eckhart/firmware/homescreen.rs
index c7651253..ddc759fd 100644
--- a/core/embed/rust/src/ui/layout_eckhart/firmware/homescreen.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/firmware/homescreen.rs
@@ -6,11 +6,10 @@ use crate::{
ui::{
component::{text::TextStyle, Component, Event, EventCtx, Label, Never, Swipe},
display::{image::ImageInfo, Color},
- geometry::{Alignment, Direction, Offset, Rect},
+ geometry::{Direction, Offset, Rect},
layout::util::get_user_custom_image,
notification::{Notification, NotificationLevel},
shape::{self, Renderer},
- util::animation_disabled,
},
};
@@ -97,9 +96,7 @@ impl Homescreen {
led_color,
locked,
bootscreen,
- fuel_gauge: FuelGauge::homescreen_bar()
- .with_alignment(Alignment::Center)
- .with_font(fonts::FONT_SATOSHI_MEDIUM_26),
+ fuel_gauge: FuelGauge::always_icon_only(),
swipe: Swipe::new().up(),
})
}
@@ -122,10 +119,6 @@ impl Homescreen {
}
fn event_fuel_gauge(&mut self, ctx: &mut EventCtx, event: Event) {
- if animation_disabled() {
- return;
- }
-
self.fuel_gauge.event(ctx, event);
let bar_content = if self.fuel_gauge.should_be_shown() {
ButtonContent::Empty
Why this scored 11/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.