From ed213854bd42f63ce59e1810d01f7d44dc080664 Mon Sep 17 00:00:00 2001 From: obrusvit Date: Thu, 21 Nov 2024 12:52:04 +0100 Subject: [PATCH] refactor(core): move confirm_blob - model_t `ConfirmBlobParams` copied for now and the return type of `into_layout` changed to `Result>` --- core/embed/rust/librust_qstr.h | 1 + core/embed/rust/src/ui/api/firmware_upy.rs | 79 ++++++++++ .../embed/rust/src/ui/model_mercury/layout.rs | 81 ----------- .../src/ui/model_mercury/ui_features_fw.rs | 43 +++++- core/embed/rust/src/ui/model_tr/layout.rs | 71 --------- .../rust/src/ui/model_tr/ui_features_fw.rs | 46 +++++- core/embed/rust/src/ui/model_tt/layout.rs | 54 ------- .../rust/src/ui/model_tt/ui_features_fw.rs | 136 +++++++++++++++++- core/embed/rust/src/ui/ui_features_fw.rs | 18 +++ core/mocks/generated/trezorui2.pyi | 67 --------- core/mocks/generated/trezorui_api.pyi | 22 +++ .../src/trezor/ui/layouts/mercury/__init__.py | 8 +- core/src/trezor/ui/layouts/tr/__init__.py | 8 +- core/src/trezor/ui/layouts/tt/__init__.py | 6 +- 14 files changed, 352 insertions(+), 288 deletions(-) diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index 09357b4db4..0ccd95cbd1 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -282,6 +282,7 @@ static void _librust_qstrs(void) { MP_QSTR_icon_name; MP_QSTR_image; MP_QSTR_indeterminate; + MP_QSTR_info; MP_QSTR_info_button; MP_QSTR_init; MP_QSTR_inputs__back; diff --git a/core/embed/rust/src/ui/api/firmware_upy.rs b/core/embed/rust/src/ui/api/firmware_upy.rs index 20abf14858..b235a99337 100644 --- a/core/embed/rust/src/ui/api/firmware_upy.rs +++ b/core/embed/rust/src/ui/api/firmware_upy.rs @@ -85,6 +85,64 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_confirm_blob(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()?; + let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; + let description: Option = kwargs + .get(Qstr::MP_QSTR_description) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; + let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?; + let extra: Option = kwargs + .get(Qstr::MP_QSTR_extra) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; + let subtitle: Option = kwargs + .get(Qstr::MP_QSTR_subtitle) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; + let verb: Option = kwargs + .get(Qstr::MP_QSTR_verb) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; + let verb_cancel: Option = kwargs + .get(Qstr::MP_QSTR_verb_cancel) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; + let verb_info: Option = kwargs + .get(Qstr::MP_QSTR_verb_info) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; + let info: bool = kwargs.get_or(Qstr::MP_QSTR_info, false)?; // FIXME: mercury has true + let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; + let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; + let page_counter: bool = kwargs.get_or(Qstr::MP_QSTR_page_counter, false)?; + let prompt_screen: bool = kwargs.get_or(Qstr::MP_QSTR_prompt_screen, false)?; + let cancel: bool = kwargs.get_or(Qstr::MP_QSTR_cancel, false)?; + + let layout_obj = ModelUI::confirm_blob( + title, + data, + description, + text_mono, + extra, + subtitle, + verb, + verb_cancel, + verb_info, + info, + hold, + chunkify, + page_counter, + prompt_screen, + cancel, + )?; + Ok(layout_obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let max_rounds: TString = kwargs.get(Qstr::MP_QSTR_max_rounds)?.try_into()?; @@ -763,6 +821,27 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// """Confirm action.""" Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(), + /// def confirm_blob( + /// *, + /// title: str, + /// data: str | bytes, + /// description: str | None, + /// text_mono: bool = True, + /// extra: str | None = None, + /// subtitle: str | None = None, + /// verb: str | None = None, + /// verb_cancel: str | None = None, + /// verb_info: str | None = None, + /// info: bool = True, + /// hold: bool = False, + /// chunkify: bool = False, + /// page_counter: bool = False, + /// prompt_screen: bool = False, + /// cancel: bool = False, + /// ) -> LayoutObj[UiResult]: + /// """Confirm byte sequence data.""" + Qstr::MP_QSTR_confirm_blob => obj_fn_kw!(0, new_confirm_blob).as_obj(), + /// def confirm_coinjoin( /// *, /// max_rounds: str, diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index 0f2f948b6a..c2faa52e06 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -261,66 +261,6 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -extern "C" fn new_confirm_blob(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()?; - let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; - let description: Option = kwargs - .get(Qstr::MP_QSTR_description) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?; - let extra: Option = kwargs - .get(Qstr::MP_QSTR_extra) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let subtitle: Option = kwargs - .get(Qstr::MP_QSTR_subtitle) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb: Option = kwargs - .get(Qstr::MP_QSTR_verb) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb_cancel: Option = kwargs - .get(Qstr::MP_QSTR_verb_cancel) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb_info: Option = kwargs - .get(Qstr::MP_QSTR_verb_info) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let info: bool = kwargs.get_or(Qstr::MP_QSTR_info, true)?; - let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; - let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; - let page_counter: bool = kwargs.get_or(Qstr::MP_QSTR_page_counter, false)?; - let prompt_screen: bool = kwargs.get_or(Qstr::MP_QSTR_prompt_screen, true)?; - let cancel: bool = kwargs.get_or(Qstr::MP_QSTR_cancel, false)?; - - ConfirmBlobParams::new(title, data, description) - .with_description_font(&theme::TEXT_SUB_GREY) - .with_text_mono(text_mono) - .with_subtitle(subtitle) - .with_verb(verb) - .with_verb_cancel(verb_cancel) - .with_verb_info(if info { - Some(verb_info.unwrap_or(TR::words__title_information.into())) - } else { - None - }) - .with_extra(extra) - .with_chunkify(chunkify) - .with_page_counter(page_counter) - .with_cancel(cancel) - .with_prompt(prompt_screen) - .with_hold(hold) - .into_flow() - .and_then(LayoutObj::new_root) - .map(Into::into) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_confirm_blob_intro(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()?; @@ -740,27 +680,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// the first component is a bool indicating whether this part is emphasized.""" Qstr::MP_QSTR_confirm_emphasized => obj_fn_kw!(0, new_confirm_emphasized).as_obj(), - /// def confirm_blob( - /// *, - /// title: str, - /// data: str | bytes, - /// description: str | None, - /// text_mono: bool = True, - /// extra: str | None = None, - /// subtitle: str | None = None, - /// verb: str | None = None, - /// verb_cancel: str | None = None, - /// verb_info: str | None = None, - /// info: bool = True, - /// hold: bool = False, - /// chunkify: bool = False, - /// page_counter: bool = False, - /// prompt_screen: bool = False, - /// cancel: bool = False, - /// ) -> LayoutObj[UiResult]: - /// """Confirm byte sequence data.""" - Qstr::MP_QSTR_confirm_blob => obj_fn_kw!(0, new_confirm_blob).as_obj(), - /// def confirm_blob_intro( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs b/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs index 48edc713d0..99c176e2d6 100644 --- a/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs +++ b/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs @@ -35,8 +35,8 @@ use super::{ SwipeContent, SwipeUpScreen, VerticalMenu, }, flow::{ - self, new_confirm_action_simple, ConfirmActionExtra, ConfirmActionMenuStrings, - ConfirmActionStrings, + self, confirm_with_info, new_confirm_action_simple, ConfirmActionExtra, + ConfirmActionMenuStrings, ConfirmActionStrings, ConfirmBlobParams, }, theme, ModelMercuryFeatures, }; @@ -69,6 +69,45 @@ impl UIFeaturesFirmware for ModelMercuryFeatures { Ok(flow) } + fn confirm_blob( + title: TString<'static>, + data: Obj, + description: Option>, + text_mono: bool, + extra: Option>, + subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + verb_info: Option>, + info: bool, + hold: bool, + chunkify: bool, + page_counter: bool, + prompt_screen: bool, + cancel: bool, + ) -> Result, Error> { + ConfirmBlobParams::new(title, data, description) + .with_description_font(&theme::TEXT_SUB_GREY) + .with_text_mono(text_mono) + .with_subtitle(subtitle) + .with_verb(verb) + .with_verb_cancel(verb_cancel) + .with_verb_info(if info { + Some(verb_info.unwrap_or(TR::words__title_information.into())) + } else { + None + }) + .with_extra(extra) + .with_chunkify(chunkify) + .with_page_counter(page_counter) + .with_cancel(cancel) + .with_prompt(prompt_screen) + .with_hold(hold) + .into_flow() + .and_then(LayoutObj::new_root) + .map(Into::into) + } + fn confirm_homescreen( title: TString<'static>, image: BinaryData<'static>, diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs index 2f68b77f79..d5c2bec352 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -270,55 +270,6 @@ fn content_in_button_page( Ok(obj.into()) } -extern "C" fn new_confirm_blob(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()?; - let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; - let description: Option = - kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; - let extra: Option = kwargs - .get(Qstr::MP_QSTR_extra) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb: Option = kwargs - .get(Qstr::MP_QSTR_verb) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb_cancel: Option = kwargs - .get(Qstr::MP_QSTR_verb_cancel) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; - let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; - - let style = if chunkify { - // Chunkifying the address into smaller pieces when requested - &theme::TEXT_MONO_ADDRESS_CHUNKS - } else { - &theme::TEXT_MONO_DATA - }; - - let paragraphs = ConfirmBlob { - description: description.unwrap_or("".into()), - extra: extra.unwrap_or("".into()), - data: data.try_into()?, - description_font: &theme::TEXT_BOLD, - extra_font: &theme::TEXT_NORMAL, - data_font: style, - } - .into_paragraphs(); - - content_in_button_page( - title, - paragraphs, - verb.unwrap_or(TR::buttons__confirm.into()), - verb_cancel, - hold, - ) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_confirm_properties(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()?; @@ -811,27 +762,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(), - /// def confirm_blob( - /// *, - /// title: str, - /// data: str | bytes, - /// description: str | None, - /// text_mono: bool = True, - /// extra: str | None = None, - /// subtitle: str | None = None, - /// verb: str = "CONFIRM", - /// verb_cancel: str | None = None, - /// verb_info: str | None = None, - /// info: bool = True, - /// hold: bool = False, - /// chunkify: bool = False, - /// page_counter: bool = False, - /// prompt_screen: bool = False, - /// cancel: bool = False, - /// ) -> LayoutObj[UiResult]: - /// """Confirm byte sequence data.""" - Qstr::MP_QSTR_confirm_blob => obj_fn_kw!(0, new_confirm_blob).as_obj(), - /// def confirm_address( /// *, /// title: str, @@ -844,7 +774,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Confirm address.""" Qstr::MP_QSTR_confirm_address => obj_fn_kw!(0, new_confirm_address).as_obj(), - /// def confirm_properties( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/model_tr/ui_features_fw.rs b/core/embed/rust/src/ui/model_tr/ui_features_fw.rs index 6e0a6b13cb..168823a148 100644 --- a/core/embed/rust/src/ui/model_tr/ui_features_fw.rs +++ b/core/embed/rust/src/ui/model_tr/ui_features_fw.rs @@ -23,7 +23,7 @@ use crate::{ geometry, layout::{ obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, - util::RecoveryType, + util::{ConfirmBlob, RecoveryType}, }, model_tr::{ component::{ButtonActions, ButtonLayout, Page}, @@ -83,6 +83,50 @@ impl UIFeaturesFirmware for ModelTRFeatures { ) } + fn confirm_blob( + title: TString<'static>, + data: Obj, + description: Option>, + _text_mono: bool, + extra: Option>, + _subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + _verb_info: Option>, + _info: bool, + hold: bool, + chunkify: bool, + _page_counter: bool, + _prompt_screen: bool, + _cancel: bool, + ) -> Result, Error> { + let style = if chunkify { + // Chunkifying the address into smaller pieces when requested + &theme::TEXT_MONO_ADDRESS_CHUNKS + } else { + &theme::TEXT_MONO_DATA + }; + + let paragraphs = ConfirmBlob { + description: description.unwrap_or("".into()), + extra: extra.unwrap_or("".into()), + data: data.try_into()?, + description_font: &theme::TEXT_BOLD, + extra_font: &theme::TEXT_NORMAL, + data_font: style, + } + .into_paragraphs(); + + let layout = content_in_button_page( + title, + paragraphs, + verb.unwrap_or(TR::buttons__confirm.into()), + verb_cancel, + hold, + )?; + LayoutObj::new_root(layout) + } + fn confirm_homescreen( title: TString<'static>, image: BinaryData<'static>, diff --git a/core/embed/rust/src/ui/model_tt/layout.rs b/core/embed/rust/src/ui/model_tt/layout.rs index ffd39cd864..622346b950 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -453,39 +453,6 @@ impl ConfirmBlobParams { } } -extern "C" fn new_confirm_blob(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()?; - let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?; - let description: Option = - kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; - let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?; - let extra: Option = kwargs - .get(Qstr::MP_QSTR_extra) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb: Option = kwargs - .get(Qstr::MP_QSTR_verb) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let verb_cancel: Option = kwargs - .get(Qstr::MP_QSTR_verb_cancel) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let info: bool = kwargs.get_or(Qstr::MP_QSTR_info, false)?; - let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; - let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; - - ConfirmBlobParams::new(title, data, description, verb, verb_cancel, hold) - .with_text_mono(text_mono) - .with_extra(extra) - .with_chunkify(chunkify) - .with_info_button(info) - .into_layout() - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_confirm_address(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()?; @@ -696,27 +663,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// the first component is a bool indicating whether this part is emphasized.""" Qstr::MP_QSTR_confirm_emphasized => obj_fn_kw!(0, new_confirm_emphasized).as_obj(), - /// def confirm_blob( - /// *, - /// title: str, - /// data: str | bytes, - /// description: str | None, - /// text_mono: bool = True, - /// extra: str | None = None, - /// subtitle: str | None = None, - /// verb: str | None = None, - /// verb_cancel: str | None = None, - /// verb_info: str | None = None, - /// info: bool = True, - /// hold: bool = False, - /// chunkify: bool = False, - /// page_counter: bool = False, - /// prompt_screen: bool = False, - /// cancel: bool = False, - /// ) -> LayoutObj[UiResult]: - /// """Confirm byte sequence data.""" - Qstr::MP_QSTR_confirm_blob => obj_fn_kw!(0, new_confirm_blob).as_obj(), - /// def confirm_address( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/model_tt/ui_features_fw.rs b/core/embed/rust/src/ui/model_tt/ui_features_fw.rs index 2c22472427..2058a60432 100644 --- a/core/embed/rust/src/ui/model_tt/ui_features_fw.rs +++ b/core/embed/rust/src/ui/model_tt/ui_features_fw.rs @@ -22,7 +22,7 @@ use crate::{ geometry, layout::{ obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, - util::RecoveryType, + util::{ConfirmBlob, RecoveryType}, }, ui_features_fw::UIFeaturesFirmware, }, @@ -80,6 +80,31 @@ impl UIFeaturesFirmware for ModelTTFeatures { Ok(layout) } + fn confirm_blob( + title: TString<'static>, + data: Obj, + description: Option>, + text_mono: bool, + extra: Option>, + _subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + _verb_info: Option>, + info: bool, + hold: bool, + chunkify: bool, + _page_counter: bool, + _prompt_screen: bool, + _cancel: bool, + ) -> Result, Error> { + ConfirmBlobParams::new(title, data, description, verb, verb_cancel, hold) + .with_text_mono(text_mono) + .with_extra(extra) + .with_chunkify(chunkify) + .with_info_button(info) + .into_layout() + } + fn confirm_homescreen( title: TString<'static>, mut image: BinaryData<'static>, @@ -923,3 +948,112 @@ fn new_show_modal( Ok(obj) } + +// TODO: move to some util.rs? +struct ConfirmBlobParams { + title: TString<'static>, + subtitle: Option>, + data: Obj, + description: Option>, + extra: Option>, + verb: Option>, + verb_cancel: Option>, + info_button: bool, + hold: bool, + chunkify: bool, + text_mono: bool, + page_limit: Option, +} + +impl ConfirmBlobParams { + fn new( + title: TString<'static>, + data: Obj, + description: Option>, + verb: Option>, + verb_cancel: Option>, + hold: bool, + ) -> Self { + Self { + title, + subtitle: None, + data, + description, + extra: None, + verb, + verb_cancel, + info_button: false, + hold, + chunkify: false, + text_mono: true, + page_limit: None, + } + } + + fn with_extra(mut self, extra: Option>) -> Self { + self.extra = extra; + self + } + + fn with_subtitle(mut self, subtitle: Option>) -> Self { + self.subtitle = subtitle; + self + } + + fn with_info_button(mut self, info_button: bool) -> Self { + self.info_button = info_button; + self + } + + fn with_chunkify(mut self, chunkify: bool) -> Self { + self.chunkify = chunkify; + self + } + + fn with_text_mono(mut self, text_mono: bool) -> Self { + self.text_mono = text_mono; + self + } + + fn with_page_limit(mut self, page_limit: Option) -> Self { + self.page_limit = page_limit; + self + } + + fn into_layout(self) -> Result, Error> { + let paragraphs = ConfirmBlob { + description: self.description.unwrap_or("".into()), + extra: self.extra.unwrap_or("".into()), + data: self.data.try_into()?, + description_font: &theme::TEXT_NORMAL, + extra_font: &theme::TEXT_DEMIBOLD, + data_font: if self.chunkify { + let data: TString = self.data.try_into()?; + theme::get_chunkified_text_style(data.len()) + } else if self.text_mono { + &theme::TEXT_MONO + } else { + &theme::TEXT_NORMAL + }, + } + .into_paragraphs(); + + let mut page = ButtonPage::new(paragraphs, theme::BG); + if let Some(verb) = self.verb { + page = page.with_cancel_confirm(self.verb_cancel, Some(verb)) + } + if self.hold { + page = page.with_hold()? + } + page = page.with_page_limit(self.page_limit); + let mut frame = Frame::left_aligned(theme::label_title(), self.title, page); + if let Some(subtitle) = self.subtitle { + frame = frame.with_subtitle(theme::label_subtitle(), subtitle); + } + + if self.info_button { + frame = frame.with_info_button(); + } + LayoutObj::new(frame) + } +} diff --git a/core/embed/rust/src/ui/ui_features_fw.rs b/core/embed/rust/src/ui/ui_features_fw.rs index f5c41ed57b..4fdab31b23 100644 --- a/core/embed/rust/src/ui/ui_features_fw.rs +++ b/core/embed/rust/src/ui/ui_features_fw.rs @@ -26,6 +26,24 @@ pub trait UIFeaturesFirmware { prompt_title: Option>, ) -> Result; + fn confirm_blob( + title: TString<'static>, + data: Obj, // TODO: replace Obj + description: Option>, + text_mono: bool, + extra: Option>, + subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + verb_info: Option>, + info: bool, + hold: bool, + chunkify: bool, + page_counter: bool, + prompt_screen: bool, + cancel: bool, + ) -> Result, Error>; // TODO: return LayoutMaybeTrace + fn confirm_homescreen( title: TString<'static>, image: BinaryData<'static>, diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index 1f5a1b8b73..832a1e8859 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -13,29 +13,6 @@ def confirm_emphasized( """Confirm formatted text that has been pre-split in python. For tuples the first component is a bool indicating whether this part is emphasized.""" - -# rust/src/ui/model_mercury/layout.rs -def confirm_blob( - *, - title: str, - data: str | bytes, - description: str | None, - text_mono: bool = True, - extra: str | None = None, - subtitle: str | None = None, - verb: str | None = None, - verb_cancel: str | None = None, - verb_info: str | None = None, - info: bool = True, - hold: bool = False, - chunkify: bool = False, - page_counter: bool = False, - prompt_screen: bool = False, - cancel: bool = False, -) -> LayoutObj[UiResult]: - """Confirm byte sequence data.""" - - # rust/src/ui/model_mercury/layout.rs def confirm_blob_intro( *, @@ -191,28 +168,6 @@ from trezor import utils from trezorui_api import * -# rust/src/ui/model_tr/layout.rs -def confirm_blob( - *, - title: str, - data: str | bytes, - description: str | None, - text_mono: bool = True, - extra: str | None = None, - subtitle: str | None = None, - verb: str = "CONFIRM", - verb_cancel: str | None = None, - verb_info: str | None = None, - info: bool = True, - hold: bool = False, - chunkify: bool = False, - page_counter: bool = False, - prompt_screen: bool = False, - cancel: bool = False, -) -> LayoutObj[UiResult]: - """Confirm byte sequence data.""" - - # rust/src/ui/model_tr/layout.rs def confirm_address( *, @@ -357,28 +312,6 @@ def confirm_emphasized( the first component is a bool indicating whether this part is emphasized.""" -# rust/src/ui/model_tt/layout.rs -def confirm_blob( - *, - title: str, - data: str | bytes, - description: str | None, - text_mono: bool = True, - extra: str | None = None, - subtitle: str | None = None, - verb: str | None = None, - verb_cancel: str | None = None, - verb_info: str | None = None, - info: bool = True, - hold: bool = False, - chunkify: bool = False, - page_counter: bool = False, - prompt_screen: bool = False, - cancel: bool = False, -) -> LayoutObj[UiResult]: - """Confirm byte sequence data.""" - - # rust/src/ui/model_tt/layout.rs def confirm_address( *, diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index 1c3c64ff69..1d2f8a1178 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -96,6 +96,28 @@ def confirm_action( """Confirm action.""" +# rust/src/ui/api/firmware_upy.rs +def confirm_blob( + *, + title: str, + data: str | bytes, + description: str | None, + text_mono: bool = True, + extra: str | None = None, + subtitle: str | None = None, + verb: str | None = None, + verb_cancel: str | None = None, + verb_info: str | None = None, + info: bool = True, + hold: bool = False, + chunkify: bool = False, + page_counter: bool = False, + prompt_screen: bool = False, + cancel: bool = False, +) -> LayoutObj[UiResult]: + """Confirm byte sequence data.""" + + # rust/src/ui/api/firmware_upy.rs def confirm_coinjoin( *, diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py index 1d4e26f36e..e77c749ffb 100644 --- a/core/src/trezor/ui/layouts/mercury/__init__.py +++ b/core/src/trezor/ui/layouts/mercury/__init__.py @@ -475,7 +475,7 @@ def confirm_blob( verb_cancel=verb_cancel, chunkify=chunkify, ) - info_layout = trezorui2.confirm_blob( + info_layout = trezorui_api.confirm_blob( title=title, data=data, subtitle=description, @@ -499,7 +499,7 @@ def confirm_blob( info_layout_can_confirm=True, ) else: - layout = trezorui2.confirm_blob( + layout = trezorui_api.confirm_blob( title=title, data=data, description=description, @@ -908,7 +908,7 @@ async def confirm_modify_output( amount_change: str, amount_new: str, ) -> None: - address_layout = trezorui2.confirm_blob( + address_layout = trezorui_api.confirm_blob( title=TR.modify_amount__title, data=address, verb=TR.buttons__continue, @@ -1030,7 +1030,7 @@ async def confirm_signverify( horizontal=True, ) - message_layout = trezorui2.confirm_blob( + message_layout = trezorui_api.confirm_blob( title=TR.sign_message__confirm_message, description=None, data=message, diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index 56670d2fce..3645d932ae 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -561,7 +561,7 @@ def confirm_blob( prompt_screen: bool = True, ) -> Awaitable[None]: verb = verb or TR.buttons__confirm # def_arg - layout = trezorui2.confirm_blob( + layout = trezorui_api.confirm_blob( title=title, description=description, data=data, @@ -751,7 +751,7 @@ async def confirm_value( elif result is INFO: info_title, info_value = info_items_list[0] await interact( - trezorui2.confirm_blob( + trezorui_api.confirm_blob( title=info_title, data=info_value, description=description, @@ -998,7 +998,7 @@ async def confirm_modify_output( amount_change: str, amount_new: str, ) -> None: - address_layout = trezorui2.confirm_blob( + address_layout = trezorui_api.confirm_blob( title=TR.modify_amount__title, data=address, verb=TR.buttons__continue, @@ -1100,7 +1100,7 @@ async def confirm_signverify( ) try: await raise_if_not_confirmed( - trezorui2.confirm_blob( + trezorui_api.confirm_blob( title=TR.sign_message__confirm_message, description=None, data=message, diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index df207c9f37..3f245c1021 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -560,7 +560,7 @@ def confirm_blob( prompt_screen: bool = True, ) -> Awaitable[None]: verb = verb or TR.buttons__confirm # def_arg - layout = trezorui2.confirm_blob( + layout = trezorui_api.confirm_blob( title=title, description=description, text_mono=text_mono, @@ -957,7 +957,7 @@ async def confirm_modify_output( while True: # if the user cancels here, raise ActionCancelled (by default) await interact( - trezorui2.confirm_blob( + trezorui_api.confirm_blob( title="MODIFY AMOUNT", data=address, verb="CONTINUE", @@ -1076,7 +1076,7 @@ async def confirm_signverify( horizontal=True, ) - message_layout = trezorui2.confirm_blob( + message_layout = trezorui_api.confirm_blob( title=TR.sign_message__confirm_message, description=None, data=message,