fix(core/eckhart): viewing all data can be done via menu
What changed, and why it matters
This commit changes how users access the 'view all data' option on the Eckhart hardware wallet screen. Previously there was a dedicated left button in the bottom action bar; now that button is removed and users are told via an on-screen hint that they can view all data through the menu. The change is a UI consistency/cleanup fix with no obvious security vulnerability introduced or fixed.
No security action required; treat as normal UI/UX cleanup. If reviewing for release, verify that the menu path still reliably exposes 'view all data' and that accessibility/user confusion is acceptable.
Security signals we found
UI flow simplification: removes a non-standard Cancelled->Info state transition
No privilege, authentication, or cryptographic logic changed
No buffer/memory handling changed
No changelog entry requested by author
Evidence from the diff
The patch removes a special-case Cancelled->Info mapping in the Eckhart confirm_value_intro flow and replaces the dual-button action bar (View all data + Confirm) with a single confirm button plus a green instructional hint. The test flow is updated to look for the hint text rather than a button label. There is no cryptographic, authorization, or memory-safety change in the diff.
Changed components
core/embed/rust/src/ui/layout_eckhart/flow/confirm_value_intro.rstests/input_flows.pyInspect captured patch +17 / −15
diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_value_intro.rs b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_value_intro.rs
index 94fed24e..bfc4c458 100644
--- a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_value_intro.rs
+++ b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_value_intro.rs
@@ -1,7 +1,7 @@
use super::super::component::Button;
use super::super::firmware::{
- ActionBar, Header, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu, VerticalMenuScreen,
- VerticalMenuScreenMsg,
+ ActionBar, Header, Hint, ShortMenuVec, TextScreen, TextScreenMsg, VerticalMenu,
+ VerticalMenuScreen, VerticalMenuScreenMsg,
};
use super::super::theme;
use crate::error;
@@ -36,8 +36,6 @@ impl FlowController for ConfirmValueIntro {
fn handle_event(&'static self, msg: FlowMsg) -> Decision {
match (self, msg) {
(Self::Intro, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
- // special case for the "view all data" button
- (Self::Intro, FlowMsg::Cancelled) => self.return_msg(FlowMsg::Info),
(Self::Intro, FlowMsg::Info) => Self::Menu.goto(),
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Info),
(Self::Menu, FlowMsg::Choice(1)) => self.return_msg(FlowMsg::Cancelled),
@@ -87,18 +85,15 @@ pub fn new_confirm_value_intro(
.with_page_limit(1)
.with_header(Header::new(title).with_menu_button())
.with_subtitle(subtitle.unwrap_or(TString::empty()))
- .with_action_bar(
- ActionBar::new_double(
- Button::with_text(TR::buttons__view_all_data.into()),
- confirm_button,
- )
- .with_left_short(false),
- )
+ .with_hint(Hint::new_instruction_green(
+ TR::instructions__view_all_data,
+ Some(theme::ICON_INFO),
+ ))
+ .with_action_bar(ActionBar::new_single(confirm_button))
.map(|msg| match msg {
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
- // special case for the "view all data" button
- TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
TextScreenMsg::Menu => Some(FlowMsg::Info),
+ TextScreenMsg::Cancelled => None, // cancellation is done via menu
});
let menu_items = VerticalMenu::<ShortMenuVec>::empty()
diff --git a/tests/input_flows.py b/tests/input_flows.py
index 42843e62..a54884a1 100644
--- a/tests/input_flows.py
+++ b/tests/input_flows.py
@@ -1721,6 +1721,9 @@ class InputFlowEthereumSignTxData(InputFlowBase):
# First blob confirmation layout has different semantic on those models:
is_intro = self.client.layout_type in (LayoutType.Delizia, LayoutType.Eckhart)
+ if is_intro:
+ # make sure the translated string is not empty (i.e. blanked)
+ assert TR.instructions__view_all_data
while True:
br = yield
@@ -1735,12 +1738,16 @@ class InputFlowEthereumSignTxData(InputFlowBase):
# Only intro layout contains "view all" functionality:
if self.client.layout_type is LayoutType.Delizia:
+ # shown as the first paragraph
assert is_intro == (
TR.instructions__view_all_data in layout.text_content()
)
elif self.client.layout_type is LayoutType.Eckhart:
- assert is_intro == (
- TR.buttons__view_all_data in layout.button_contents()
+ # shown as a separate label
+ assert is_intro == bool(
+ layout.find_unique_object_with_key_and_value(
+ key="text", value=TR.instructions__view_all_data
+ )
)
if self.scroll:
Why this scored 18/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.