From 85ceca950976d6505a9c3ee8b4fd2fb6b236284f Mon Sep 17 00:00:00 2001 From: obrusvit Date: Sun, 16 Mar 2025 01:27:44 +0100 Subject: [PATCH] feat(eckhart): implement confirm_set_new_pin - add1: make `show_success` not render empty action bar button - add2: top aligned confirm action --- .../flow/confirm_set_new_pin.rs | 93 +++++++++++++++++++ .../rust/src/ui/layout_eckhart/flow/mod.rs | 2 + .../src/ui/layout_eckhart/theme/firmware.rs | 3 + .../rust/src/ui/layout_eckhart/ui_firmware.rs | 9 +- core/src/trezor/ui/layouts/bolt/__init__.py | 2 +- .../src/trezor/ui/layouts/eckhart/__init__.py | 9 +- .../src/trezor/ui/layouts/eckhart/recovery.py | 2 +- 7 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs new file mode 100644 index 0000000000..640a90faf7 --- /dev/null +++ b/core/embed/rust/src/ui/layout_eckhart/flow/confirm_set_new_pin.rs @@ -0,0 +1,93 @@ +use crate::{ + error, + strutil::TString, + translations::TR, + ui::{ + component::{ + text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs}, + ComponentExt as _, + }, + flow::{ + base::{Decision, DecisionBuilder as _}, + FlowController, FlowMsg, SwipeFlow, + }, + geometry::{Direction, LinearPlacement}, + layout_eckhart::firmware::TextScreenMsg, + }, +}; + +use super::super::{ + component::Button, + firmware::{ActionBar, Header, TextScreen}, + theme, +}; + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum SetNewPin { + Intro, + CancelPin, +} + +impl FlowController for SetNewPin { + #[inline] + fn index(&'static self) -> usize { + *self as usize + } + + fn handle_swipe(&'static self, _direction: Direction) -> Decision { + self.do_nothing() + } + + fn handle_event(&'static self, msg: FlowMsg) -> Decision { + match (self, msg) { + (Self::Intro, FlowMsg::Cancelled) => Self::CancelPin.goto(), + (Self::Intro, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed), + (Self::CancelPin, FlowMsg::Cancelled) => Self::Intro.goto(), + (Self::CancelPin, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed), + _ => self.do_nothing(), + } + } +} + +pub fn new_set_new_pin( + title: TString<'static>, + description: TString<'static>, +) -> Result { + let paragraphs = Paragraphs::new(Paragraph::new(&theme::firmware::TEXT_REGULAR, description)) + .with_placement(LinearPlacement::vertical()); + let content_intro = TextScreen::new(paragraphs) + .with_header(Header::new(title)) + .with_action_bar(ActionBar::new_cancel_confirm()) + .map(|msg| match msg { + TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled), + TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed), + _ => None, + }); + + let paragraphs_cancel_intro = ParagraphVecShort::from_iter([ + Paragraph::new( + &theme::firmware::TEXT_REGULAR_WARNING, + TR::words__not_recommended, + ), + Paragraph::new(&theme::firmware::TEXT_REGULAR, TR::pin__cancel_info), + ]) + .into_paragraphs() + .with_placement(LinearPlacement::vertical()); + + let content_cancel_pin = TextScreen::new(paragraphs_cancel_intro) + .with_header(Header::new(title)) + .with_action_bar(ActionBar::new_double( + Button::with_icon(theme::ICON_CHEVRON_LEFT), + Button::with_text(TR::buttons__continue.into()), + )) + .map(|msg| match msg { + TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled), + TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed), + _ => None, + }); + + let mut res = SwipeFlow::new(&SetNewPin::Intro)?; + res.add_page(&SetNewPin::Intro, content_intro)? + .add_page(&SetNewPin::CancelPin, content_cancel_pin)?; + Ok(res) +} diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs b/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs index 78d5d34eb8..8172bf6978 100644 --- a/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs +++ b/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs @@ -1,4 +1,5 @@ pub mod confirm_reset; +pub mod confirm_set_new_pin; pub mod get_address; pub mod prompt_backup; pub mod request_passphrase; @@ -6,6 +7,7 @@ pub mod show_danger; pub mod show_share_words; pub use confirm_reset::new_confirm_reset; +pub use confirm_set_new_pin::new_set_new_pin; pub use get_address::GetAddress; pub use prompt_backup::PromptBackup; pub use request_passphrase::RequestPassphrase; diff --git a/core/embed/rust/src/ui/layout_eckhart/theme/firmware.rs b/core/embed/rust/src/ui/layout_eckhart/theme/firmware.rs index b94a74b8cc..2484b71d17 100644 --- a/core/embed/rust/src/ui/layout_eckhart/theme/firmware.rs +++ b/core/embed/rust/src/ui/layout_eckhart/theme/firmware.rs @@ -73,6 +73,9 @@ pub const TEXT_MONO_LIGHT: TextStyle = TextStyle::new( GREY_LIGHT, ); +pub const TEXT_REGULAR_WARNING: TextStyle = + TextStyle::new(fonts::FONT_SATOSHI_REGULAR_38, RED, BG, GREY, GREY); + pub const TEXT_MEDIUM_EXTRA_LIGHT: TextStyle = TextStyle::new( fonts::FONT_SATOSHI_MEDIUM_26, GREY_EXTRA_LIGHT, diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs index d83208e60e..00dd65cf6b 100644 --- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs @@ -72,7 +72,7 @@ impl FirmwareUI for UIEckhart { .color(theme::GREY_LIGHT) .text(action, fonts::FONT_SATOSHI_REGULAR_38); }; - FormattedText::new(ops).vertically_centered() + FormattedText::new(ops) }; let verb = verb.unwrap_or(TR::buttons__confirm.into()); @@ -359,10 +359,11 @@ impl FirmwareUI for UIEckhart { } fn flow_confirm_set_new_pin( - _title: TString<'static>, - _description: TString<'static>, + title: TString<'static>, + description: TString<'static>, ) -> Result { - Err::, Error>(Error::ValueError(c"not implemented")) + let flow = flow::confirm_set_new_pin::new_set_new_pin(title, description)?; + Ok(flow) } fn flow_get_address( diff --git a/core/src/trezor/ui/layouts/bolt/__init__.py b/core/src/trezor/ui/layouts/bolt/__init__.py index ece5f36402..070505125e 100644 --- a/core/src/trezor/ui/layouts/bolt/__init__.py +++ b/core/src/trezor/ui/layouts/bolt/__init__.py @@ -1353,7 +1353,7 @@ async def request_pin_on_device( async def confirm_reenter_pin(is_wipe_code: bool = False) -> None: - """Not supported for TT.""" + """Not supported for Bolt.""" pass diff --git a/core/src/trezor/ui/layouts/eckhart/__init__.py b/core/src/trezor/ui/layouts/eckhart/__init__.py index 8491b04271..251614bb03 100644 --- a/core/src/trezor/ui/layouts/eckhart/__init__.py +++ b/core/src/trezor/ui/layouts/eckhart/__init__.py @@ -365,11 +365,13 @@ def show_success( subheader: str | None = None, button: str | None = None, ) -> Awaitable[None]: + button = button or TR.buttons__continue # def_arg return raise_if_not_confirmed( trezorui_api.show_success( title=subheader if subheader else "", - button=button if button else "", + button=button, description=content, + allow_cancel=False, ), br_name, ButtonRequestType.Success, @@ -1000,9 +1002,8 @@ def request_pin_on_device( async def confirm_reenter_pin(is_wipe_code: bool = False) -> None: - # FIXME: not implemented - # not supported on mercury either? - raise NotImplementedError + """Not supported for Eckhart.""" + pass def pin_mismatch_popup(is_wipe_code: bool = False) -> Awaitable[ui.UiResult]: diff --git a/core/src/trezor/ui/layouts/eckhart/recovery.py b/core/src/trezor/ui/layouts/eckhart/recovery.py index 371a635d03..1f2ddfa267 100644 --- a/core/src/trezor/ui/layouts/eckhart/recovery.py +++ b/core/src/trezor/ui/layouts/eckhart/recovery.py @@ -99,7 +99,7 @@ async def show_group_share_success(share_index: int, group_index: int) -> None: async def continue_recovery( - _button_label: str, # unused on mercury + _button_label: str, # unused on delizia text: str, subtext: str | None, recovery_type: RecoveryType,