diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index 47e9d42acc..92dfe91e1e 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -536,7 +536,6 @@ static void _librust_qstrs(void) { MP_QSTR_show_share_words; MP_QSTR_show_simple; MP_QSTR_show_success; - MP_QSTR_show_tx_context_menu; MP_QSTR_show_wait_text; MP_QSTR_show_warning; MP_QSTR_sign; diff --git a/core/embed/rust/src/ui/model_mercury/component/button.rs b/core/embed/rust/src/ui/model_mercury/component/button.rs index 8daa7129cb..9f66063666 100644 --- a/core/embed/rust/src/ui/model_mercury/component/button.rs +++ b/core/embed/rust/src/ui/model_mercury/component/button.rs @@ -503,7 +503,7 @@ pub enum CancelInfoConfirmMsg { #[derive(PartialEq, Eq, Clone)] pub struct IconText { - text: &'static str, + text: TString<'static>, icon: Icon, } @@ -512,12 +512,15 @@ impl IconText { const ICON_MARGIN: i16 = 4; const TEXT_MARGIN: i16 = 6; - pub fn new(text: &'static str, icon: Icon) -> Self { - Self { text, icon } + pub fn new(text: impl Into>, icon: Icon) -> Self { + Self { + text: text.into(), + icon, + } } pub fn paint(&self, area: Rect, style: &ButtonStyle, baseline_offset: Offset) { - let width = style.font.text_width(self.text); + let width = self.text.map(|t| style.font.text_width(t)); let height = style.font.text_height(); let mut use_icon = false; @@ -543,13 +546,15 @@ impl IconText { } if use_text { - display::text_left( - text_pos, - self.text, - style.font, - style.text_color, - style.button_color, - ); + self.text.map(|t| { + display::text_left( + text_pos, + t, + style.font, + style.text_color, + style.button_color, + ) + }); } if use_icon { @@ -568,7 +573,7 @@ impl IconText { style: &ButtonStyle, baseline_offset: Offset, ) { - let width = style.font.text_width(self.text.as_ref()); + let width = self.text.map(|t| style.font.text_width(t)); let mut use_icon = false; let mut use_text = false; @@ -593,10 +598,12 @@ impl IconText { } if use_text { - shape::Text::new(text_pos, self.text) - .with_font(style.font) - .with_fg(style.text_color) - .render(target); + self.text.map(|t| { + shape::Text::new(text_pos, t) + .with_font(style.font) + .with_fg(style.text_color) + .render(target) + }); } if use_icon { diff --git a/core/embed/rust/src/ui/model_mercury/component/vertical_menu.rs b/core/embed/rust/src/ui/model_mercury/component/vertical_menu.rs index cd9c4fa54d..c75f36b2b0 100644 --- a/core/embed/rust/src/ui/model_mercury/component/vertical_menu.rs +++ b/core/embed/rust/src/ui/model_mercury/component/vertical_menu.rs @@ -59,25 +59,23 @@ impl VerticalMenu { Self::new(buttons_vec) } - pub fn context_menu(options: Vec<(&'static str, Icon), N_ITEMS>) -> Self { - // FIXME: args should be TString when IconText has TString - let mut buttons_vec = VerticalMenuButtons::new(); - for opt in options { - let button_theme; - match opt.1 { - // FIXME: might not be applicable everywhere - theme::ICON_CANCEL => { - button_theme = theme::button_warning_high(); - } - _ => { - button_theme = theme::button_default(); - } - } - unwrap!(buttons_vec.push( - Button::with_icon_and_text(IconText::new(opt.0, opt.1)).styled(button_theme) - )); - } - Self::new(buttons_vec) + pub fn empty() -> Self { + Self::new(VerticalMenuButtons::new()) + } + + pub fn item(mut self, icon: Icon, text: TString<'static>) -> Self { + unwrap!(self.buttons.push( + Button::with_icon_and_text(IconText::new(text, icon)).styled(theme::button_default()) + )); + self + } + + pub fn danger(mut self, icon: Icon, text: TString<'static>) -> Self { + unwrap!(self.buttons.push( + Button::with_icon_and_text(IconText::new(text, icon)) + .styled(theme::button_warning_high()) + )); + self } } diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs index 66381204ee..9b84184fb9 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs @@ -11,7 +11,6 @@ use crate::{ flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow, SwipePage}, }, }; -use heapless::Vec; use super::super::{ component::{Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg}, @@ -91,10 +90,7 @@ impl ConfirmResetDevice { let content_menu = Frame::left_aligned( "".into(), - VerticalMenu::context_menu(unwrap!(Vec::from_slice(&[( - "Cancel", // FIXME: use TString - theme::ICON_CANCEL - )]))), + VerticalMenu::empty().danger(theme::ICON_CANCEL, "Cancel".into()), ) .with_cancel_button() .map(|msg| match msg { diff --git a/core/embed/rust/src/ui/model_mercury/flow/create_backup.rs b/core/embed/rust/src/ui/model_mercury/flow/create_backup.rs index 43608ec2f0..e15201deb8 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/create_backup.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/create_backup.rs @@ -10,7 +10,6 @@ use crate::{ flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow, SwipePage}, }, }; -use heapless::Vec; use super::super::{ component::{ @@ -95,10 +94,7 @@ impl CreateBackup { let content_menu = Frame::left_aligned( "".into(), - VerticalMenu::context_menu(unwrap!(Vec::from_slice(&[( - "Skip backup", // FIXME: use TString - theme::ICON_CANCEL - )]))), + VerticalMenu::empty().danger(theme::ICON_CANCEL, "Skip backup".into()), ) .with_cancel_button() .map(|msg| match msg { diff --git a/core/embed/rust/src/ui/model_mercury/flow/get_address.rs b/core/embed/rust/src/ui/model_mercury/flow/get_address.rs index 2feeffa3b7..477d458c2d 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/get_address.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/get_address.rs @@ -12,7 +12,6 @@ use crate::{ }, }, }; -use heapless::Vec; use super::super::{ component::{Frame, FrameMsg, IconDialog, VerticalMenu, VerticalMenuChoiceMsg}, @@ -121,11 +120,10 @@ impl GetAddress { .add( Frame::left_aligned( "".into(), - VerticalMenu::context_menu(unwrap!(Vec::from_slice(&[ - ("Address QR code", theme::ICON_QR_CODE), - ("Account info", theme::ICON_CHEVRON_RIGHT), - ("Cancel trans.", theme::ICON_CANCEL), - ]))), + VerticalMenu::empty() + .item(theme::ICON_QR_CODE, "Address QR code".into()) + .item(theme::ICON_CHEVRON_RIGHT, "Account info".into()) + .danger(theme::ICON_CANCEL, "Cancel operation".into()), ) .with_cancel_button() .map(|msg| match msg { diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index 145798bbcf..db626dbef0 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -1295,23 +1295,6 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -extern "C" fn new_show_tx_context_menu(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], _kwargs: &Map| { - // TODO: this is just POC - let title: TString = "".into(); - let options = unwrap!(Vec::from_slice(&[ - ("Address QR code", theme::ICON_QR_CODE), - ("Fee info", theme::ICON_CHEVRON_RIGHT), - ("Cancel transaction", theme::ICON_CANCEL), - ])); - let content = VerticalMenu::context_menu(options); - let frame_with_menu = Frame::left_aligned(title, content).with_cancel_button(); - let obj = LayoutObj::new(frame_with_menu)?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; @@ -2040,11 +2023,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// iterable must be of exact size. Returns index in range `0..3`.""" Qstr::MP_QSTR_select_word => obj_fn_kw!(0, new_select_word).as_obj(), - /// def show_tx_context_menu() -> LayoutObj[int]: - /// """Show transaction context menu with the options for 1) Address QR code, 2) Fee - /// information, 3) Cancel transaction""" - Qstr::MP_QSTR_show_tx_context_menu => obj_fn_kw!(0, new_show_tx_context_menu).as_obj(), - // TODO: This is just POC /// def create_backup_flow() -> LayoutObj[UiResult] /// """Start create backup or skip flow.""" diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index 9f5a2de495..e76fdea233 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -389,12 +389,6 @@ def select_word( iterable must be of exact size. Returns index in range `0..3`.""" -# rust/src/ui/model_mercury/layout.rs -def show_tx_context_menu() -> LayoutObj[int]: - """Show transaction context menu with the options for 1) Address QR code, 2) Fee - information, 3) Cancel transaction""" - - # rust/src/ui/model_mercury/layout.rs def create_backup_flow() -> LayoutObj[UiResult] """Start create backup or skip flow."""