diff --git a/core/embed/rust/src/ui/api/firmware_upy.rs b/core/embed/rust/src/ui/api/firmware_upy.rs index 0353a1c662..334244afc1 100644 --- a/core/embed/rust/src/ui/api/firmware_upy.rs +++ b/core/embed/rust/src/ui/api/firmware_upy.rs @@ -1,6 +1,6 @@ use crate::{ micropython::{ - macros::{obj_fn_kw, obj_module}, + macros::{obj_fn_1, obj_fn_kw, obj_module}, map::Map, module::Module, obj::Obj, @@ -13,7 +13,7 @@ use crate::{ layout::{ base::LAYOUT_STATE, obj::{LayoutObj, ATTACH_TYPE_OBJ}, - result::{CANCELLED, CONFIRMED, INFO}, + result::{CANCELLED, CONFIRMED, INFO}, util::upy_disable_animation, }, ui_features::ModelUI, ui_features_fw::UIFeaturesFirmware, @@ -22,6 +22,7 @@ use crate::{ // free-standing functions exported to MicroPython mirror `trait // UIFeaturesFirmware` +// NOTE: `disable_animation` not a part of trait UiFeaturesFirmware extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { @@ -86,6 +87,15 @@ extern "C" fn show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Ob unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj { + let block = || { + let buffer = data.try_into()?; + Ok(ModelUI::check_homescreen_format(buffer, false).into()) + }; + + unsafe { util::try_or_raise(block) } +} + #[no_mangle] pub static mp_module_trezorui_api: Module = obj_module! { /// from trezor import utils @@ -182,6 +192,14 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// INFO: UiResult Qstr::MP_QSTR_INFO => INFO.as_obj(), + /// def check_homescreen_format(data: bytes) -> bool: + /// """Check homescreen format and dimensions.""" + Qstr::MP_QSTR_check_homescreen_format => obj_fn_1!(upy_check_homescreen_format).as_obj(), + + /// def disable_animation(disable: bool) -> None: + /// """Disable animations, debug builds only.""" + Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(), + /// def request_bip39( /// *, /// prompt: str, diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index bdd09e7274..2703df9e8e 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -48,7 +48,7 @@ use crate::{ base::LAYOUT_STATE, obj::{ComponentMsgObj, LayoutObj, ATTACH_TYPE_OBJ}, result::{CANCELLED, CONFIRMED, INFO}, - util::{upy_disable_animation, ConfirmBlob, PropsList, RecoveryType}, + util::{ConfirmBlob, PropsList, RecoveryType}, }, model_mercury::{ component::{check_homescreen_format, SwipeContent}, @@ -1391,15 +1391,6 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj { - let block = || { - let buffer = data.try_into()?; - Ok(check_homescreen_format(buffer).into()) - }; - - unsafe { util::try_or_raise(block) } -} - extern "C" fn new_show_wait_text(message: Obj) -> Obj { let block = || { let message: TString<'static> = message.try_into()?; @@ -1440,31 +1431,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(), - /// def disable_animation(disable: bool) -> None: - /// """Disable animations, debug builds only.""" - Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(), - - /// def check_homescreen_format(data: bytes) -> bool: - /// """Check homescreen format and dimensions.""" - Qstr::MP_QSTR_check_homescreen_format => obj_fn_1!(upy_check_homescreen_format).as_obj(), - - /// def confirm_action( - /// *, - /// title: str, - /// action: str | None, - /// description: str | None, - /// subtitle: str | None = None, - /// verb: str | None = None, - /// verb_cancel: str | None = None, - /// hold: bool = False, - /// hold_danger: bool = False, - /// reverse: bool = False, - /// prompt_screen: bool = False, - /// prompt_title: str | None = None, - /// ) -> LayoutObj[UiResult]: - /// """Confirm action.""" - Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(), - /// def confirm_emphasized( /// *, /// 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 7bd61d50b8..9fed76ed92 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 @@ -1,5 +1,6 @@ use crate::{ error::Error, + io::BinaryData, micropython::gc::Gc, strutil::TString, translations::TR, @@ -21,6 +22,37 @@ use super::{ }; impl UIFeaturesFirmware for ModelMercuryFeatures { + fn confirm_action( + title: TString<'static>, + action: Option>, + description: Option>, + subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + hold: bool, + hold_danger: bool, + reverse: bool, + prompt_screen: bool, + prompt_title: Option>, + ) -> Result { + let flow = flow::confirm_action::new_confirm_action( + title, + action, + description, + subtitle, + verb_cancel, + reverse, + hold, + prompt_screen, + prompt_title.unwrap_or(TString::empty()), + )?; + Ok(flow) + } + + fn check_homescreen_format(image: BinaryData, __accept_toif: bool) -> bool { + super::component::check_homescreen_format(image) + } + fn request_bip39( prompt: TString<'static>, prefill_word: TString<'static>, diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs index c9ace4e23e..ff6651bf7c 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -48,9 +48,8 @@ use crate::{ layout::{ obj::{ComponentMsgObj, LayoutObj}, result::{CANCELLED, CONFIRMED, INFO}, - util::{upy_disable_animation, ConfirmBlob, RecoveryType}, + util::{ConfirmBlob, RecoveryType}, }, - model_tr::component::check_homescreen_format, }, }; @@ -1543,15 +1542,6 @@ extern "C" fn new_confirm_firmware_update( unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj { - let block = || { - let image = data.try_into()?; - Ok(check_homescreen_format(image).into()) - }; - - unsafe { util::try_or_raise(block) } -} - extern "C" fn new_show_wait_text(message: Obj) -> Obj { let block = || { let message: TString<'static> = message.try_into()?; @@ -1569,31 +1559,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// Qstr::MP_QSTR___name__ => Qstr::MP_QSTR_trezorui2.to_obj(), - /// def disable_animation(disable: bool) -> None: - /// """Disable animations, debug builds only.""" - Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(), - - /// def check_homescreen_format(data: bytes) -> bool: - /// """Check homescreen format and dimensions.""" - Qstr::MP_QSTR_check_homescreen_format => obj_fn_1!(upy_check_homescreen_format).as_obj(), - - /// def confirm_action( - /// *, - /// title: str, - /// action: str | None, - /// description: str | None, - /// subtitle: str | None = None, - /// verb: str = "CONFIRM", - /// verb_cancel: str | None = None, - /// hold: bool = False, - /// hold_danger: bool = False, # unused on TR - /// reverse: bool = False, - /// prompt_screen: bool = False, - /// prompt_title: str | None = None, - /// ) -> LayoutObj[UiResult]: - /// """Confirm action.""" - Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(), - /// def confirm_homescreen( /// *, /// 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 efa2de9eb6..1c8946ad70 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 @@ -1,5 +1,7 @@ use crate::{ error::Error, + io::BinaryData, + maybe_trace::MaybeTrace, micropython::gc::Gc, strutil::TString, ui::{ @@ -18,6 +20,48 @@ use super::{ }; impl UIFeaturesFirmware for ModelTRFeatures { + fn confirm_action( + title: TString<'static>, + action: Option>, + description: Option>, + subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + hold: bool, + hold_danger: bool, + reverse: bool, + prompt_screen: bool, + prompt_title: Option>, + ) -> Result { + let paragraphs = { + let action = action.unwrap_or("".into()); + let description = description.unwrap_or("".into()); + let mut paragraphs = ParagraphVecShort::new(); + if !reverse { + paragraphs + .add(Paragraph::new(&theme::TEXT_BOLD, action)) + .add(Paragraph::new(&theme::TEXT_NORMAL, description)); + } else { + paragraphs + .add(Paragraph::new(&theme::TEXT_NORMAL, description)) + .add(Paragraph::new(&theme::TEXT_BOLD, action)); + } + paragraphs.into_paragraphs() + }; + + content_in_button_page( + title, + paragraphs, + verb.unwrap_or(TString::empty()), + verb_cancel, + hold, + ) + } + + fn check_homescreen_format(image: BinaryData, _accept_toif: bool) -> bool { + super::component::check_homescreen_format(image) + } + fn request_bip39( prompt: TString<'static>, prefill_word: TString<'static>, diff --git a/core/embed/rust/src/ui/model_tt/layout.rs b/core/embed/rust/src/ui/model_tt/layout.rs index 46bde8f667..c8dae062e5 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -51,7 +51,7 @@ use crate::{ layout::{ obj::{ComponentMsgObj, LayoutObj}, result::{CANCELLED, CONFIRMED, INFO}, - util::{upy_disable_animation, ConfirmBlob, PropsList, RecoveryType}, + util::{ConfirmBlob, PropsList, RecoveryType}, }, model_tt::component::check_homescreen_format, }, @@ -1528,15 +1528,6 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj { - let block = || { - let buffer = data.try_into()?; - Ok(check_homescreen_format(buffer, false).into()) - }; - - unsafe { util::try_or_raise(block) } -} - #[no_mangle] extern "C" fn new_confirm_firmware_update( n_args: usize, @@ -1582,13 +1573,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// from trezor import utils /// from trezorui_api import * /// - /// def disable_animation(disable: bool) -> None: - /// """Disable animations, debug builds only.""" - Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(), - - /// def check_homescreen_format(data: bytes) -> bool: - /// """Check homescreen format and dimensions.""" - Qstr::MP_QSTR_check_homescreen_format => obj_fn_1!(upy_check_homescreen_format).as_obj(), /// def confirm_action( /// *, 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 afe5cd7d37..c4bc5dad30 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 @@ -1,5 +1,6 @@ use crate::{ error::Error, + io::BinaryData, micropython::gc::Gc, strutil::TString, translations::TR, @@ -19,6 +20,51 @@ use super::{ }; impl UIFeaturesFirmware for ModelTTFeatures { + fn confirm_action( + title: TString<'static>, + action: Option>, + description: Option>, + subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + hold: bool, + hold_danger: bool, + reverse: bool, + prompt_screen: bool, + prompt_title: Option>, + ) -> Result { + let paragraphs = { + let action = action.unwrap_or("".into()); + let description = description.unwrap_or("".into()); + let mut paragraphs = ParagraphVecShort::new(); + if !reverse { + paragraphs + .add(Paragraph::new(&theme::TEXT_DEMIBOLD, action)) + .add(Paragraph::new(&theme::TEXT_NORMAL, description)); + } else { + paragraphs + .add(Paragraph::new(&theme::TEXT_NORMAL, description)) + .add(Paragraph::new(&theme::TEXT_DEMIBOLD, action)); + } + paragraphs.into_paragraphs() + }; + + let mut page = if hold { + ButtonPage::new(paragraphs, theme::BG).with_hold()? + } else { + ButtonPage::new(paragraphs, theme::BG).with_cancel_confirm(verb_cancel, verb) + }; + if hold && hold_danger { + page = page.with_confirm_style(theme::button_danger()) + } + let layout = RootComponent::new(Frame::left_aligned(theme::label_title(), title, page)); + Ok(layout) + } + + fn check_homescreen_format(image: BinaryData, accept_toif: bool) -> bool { + super::component::check_homescreen_format(image, false) + } + fn request_bip39( prompt: TString<'static>, prefill_word: TString<'static>, diff --git a/core/embed/rust/src/ui/ui_features_fw.rs b/core/embed/rust/src/ui/ui_features_fw.rs index 634b027a02..4a08fc7042 100644 --- a/core/embed/rust/src/ui/ui_features_fw.rs +++ b/core/embed/rust/src/ui/ui_features_fw.rs @@ -1,8 +1,24 @@ -use crate::{error::Error, micropython::gc::Gc, strutil::TString}; +use crate::{error::Error, io::BinaryData, micropython::gc::Gc, strutil::TString}; use super::layout::obj::{LayoutMaybeTrace, LayoutObj}; pub trait UIFeaturesFirmware { + fn confirm_action( + title: TString<'static>, + action: Option>, + description: Option>, + subtitle: Option>, + verb: Option>, + verb_cancel: Option>, + hold: bool, + hold_danger: bool, + reverse: bool, + prompt_screen: bool, + prompt_title: Option>, + ) -> Result; + + fn check_homescreen_format(image: BinaryData, accept_toif: bool) -> bool; + fn request_bip39( prompt: TString<'static>, prefill_word: TString<'static>, diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index 6e4fe379b3..b8f9a955ea 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -3,34 +3,6 @@ from trezor import utils from trezorui_api import * -# rust/src/ui/model_mercury/layout.rs -def disable_animation(disable: bool) -> None: - """Disable animations, debug builds only.""" - - -# rust/src/ui/model_mercury/layout.rs -def check_homescreen_format(data: bytes) -> bool: - """Check homescreen format and dimensions.""" - - -# rust/src/ui/model_mercury/layout.rs -def confirm_action( - *, - title: str, - action: str | None, - description: str | None, - subtitle: str | None = None, - verb: str | None = None, - verb_cancel: str | None = None, - hold: bool = False, - hold_danger: bool = False, - reverse: bool = False, - prompt_screen: bool = False, - prompt_title: str | None = None, -) -> LayoutObj[UiResult]: - """Confirm action.""" - - # rust/src/ui/model_mercury/layout.rs def confirm_emphasized( *, @@ -504,34 +476,6 @@ from trezor import utils from trezorui_api import * -# rust/src/ui/model_tr/layout.rs -def disable_animation(disable: bool) -> None: - """Disable animations, debug builds only.""" - - -# rust/src/ui/model_tr/layout.rs -def check_homescreen_format(data: bytes) -> bool: - """Check homescreen format and dimensions.""" - - -# rust/src/ui/model_tr/layout.rs -def confirm_action( - *, - title: str, - action: str | None, - description: str | None, - subtitle: str | None = None, - verb: str = "CONFIRM", - verb_cancel: str | None = None, - hold: bool = False, - hold_danger: bool = False, # unused on TR - reverse: bool = False, - prompt_screen: bool = False, - prompt_title: str | None = None, -) -> LayoutObj[UiResult]: - """Confirm action.""" - - # rust/src/ui/model_tr/layout.rs def confirm_homescreen( *, @@ -920,34 +864,6 @@ from trezor import utils from trezorui_api import * -# rust/src/ui/model_tt/layout.rs -def disable_animation(disable: bool) -> None: - """Disable animations, debug builds only.""" - - -# rust/src/ui/model_tt/layout.rs -def check_homescreen_format(data: bytes) -> bool: - """Check homescreen format and dimensions.""" - - -# rust/src/ui/model_tt/layout.rs -def confirm_action( - *, - title: str, - action: str | None, - description: str | None, - subtitle: str | None = None, - verb: str | None = None, - verb_cancel: str | None = None, - hold: bool = False, - hold_danger: bool = False, - reverse: bool = False, - prompt_screen: bool = False, - prompt_title: str | None = None, -) -> LayoutObj[UiResult]: - """Confirm action.""" - - # rust/src/ui/model_tt/layout.rs def confirm_emphasized( *, diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index aea8b7edd0..a1f1647392 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -68,6 +68,16 @@ CANCELLED: UiResult INFO: UiResult +# rust/src/ui/api/firmware_upy.rs +def check_homescreen_format(data: bytes) -> bool: + """Check homescreen format and dimensions.""" + + +# rust/src/ui/api/firmware_upy.rs +def disable_animation(disable: bool) -> None: + """Disable animations, debug builds only.""" + + # rust/src/ui/api/firmware_upy.rs def request_bip39( *, diff --git a/core/src/apps/management/apply_settings.py b/core/src/apps/management/apply_settings.py index df00e51388..73242a49d2 100644 --- a/core/src/apps/management/apply_settings.py +++ b/core/src/apps/management/apply_settings.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING import storage.device as storage_device -import trezorui2 +import trezorui_api from trezor import TR, utils from trezor.enums import ButtonRequestType, DisplayRotation from trezor.ui.layouts import confirm_action @@ -25,7 +25,7 @@ def _validate_homescreen(homescreen: bytes) -> None: raise DataError( f"Homescreen is too large, maximum size is {storage_device.HOMESCREEN_MAXSIZE} bytes" ) - if not trezorui2.check_homescreen_format(homescreen): + if not trezorui_api.check_homescreen_format(homescreen): raise DataError("Wrong homescreen format") diff --git a/core/src/trezor/ui/__init__.py b/core/src/trezor/ui/__init__.py index 91e8e71c4d..81064b579d 100644 --- a/core/src/trezor/ui/__init__.py +++ b/core/src/trezor/ui/__init__.py @@ -23,7 +23,9 @@ else: if __debug__: - trezorui2.disable_animation(bool(utils.DISABLE_ANIMATION)) + from trezorui_api import disable_animation + + disable_animation(bool(utils.DISABLE_ANIMATION)) # all rendering is done through a singleton of `Display`