From dab0b7f3cc0231a32ca84f8d9a599e09994000fe Mon Sep 17 00:00:00 2001 From: obrusvit Date: Tue, 22 Oct 2024 22:24:40 +0200 Subject: [PATCH] refactor(core): move keyboards to UiFeatures Make layouts utilizing keyboards a part of UiFeaturesFirmware --- core/embed/rust/librust_qstr.h | 1 - core/embed/rust/src/ui/api/firmware_upy.rs | 84 ++++++++++++ .../embed/rust/src/ui/model_mercury/layout.rs | 93 -------------- .../src/ui/model_mercury/ui_features_fw.rs | 56 +++++++- core/embed/rust/src/ui/model_tr/layout.rs | 96 -------------- core/embed/rust/src/ui/model_tr/mod.rs | 2 + .../rust/src/ui/model_tr/ui_features_fw.rs | 59 ++++++++- core/embed/rust/src/ui/model_tt/layout.rs | 93 -------------- core/embed/rust/src/ui/model_tt/mod.rs | 2 + .../rust/src/ui/model_tt/ui_features_fw.rs | 62 ++++++++- core/embed/rust/src/ui/ui_features_fw.rs | 24 ++++ core/mocks/generated/trezorui2.pyi | 120 ------------------ core/mocks/generated/trezorui_api.pyi | 40 ++++++ .../src/trezor/ui/layouts/mercury/__init__.py | 4 +- .../src/trezor/ui/layouts/mercury/recovery.py | 4 +- core/src/trezor/ui/layouts/tr/__init__.py | 4 +- core/src/trezor/ui/layouts/tr/recovery.py | 4 +- core/src/trezor/ui/layouts/tt/__init__.py | 6 +- core/src/trezor/ui/layouts/tt/recovery.py | 4 +- 19 files changed, 335 insertions(+), 423 deletions(-) diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index c93786615d..f400326e9b 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -258,7 +258,6 @@ static void _librust_qstrs(void) { MP_QSTR_flow_get_address; MP_QSTR_flow_prompt_backup; MP_QSTR_flow_request_number; - MP_QSTR_flow_request_passphrase; MP_QSTR_flow_show_share_words; MP_QSTR_flow_warning_hi_prio; MP_QSTR_get_language; diff --git a/core/embed/rust/src/ui/api/firmware_upy.rs b/core/embed/rust/src/ui/api/firmware_upy.rs index 86e49a6676..0353a1c662 100644 --- a/core/embed/rust/src/ui/api/firmware_upy.rs +++ b/core/embed/rust/src/ui/api/firmware_upy.rs @@ -23,6 +23,54 @@ use crate::{ // free-standing functions exported to MicroPython mirror `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| { + let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; + let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; + let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; + + let layout = ModelUI::request_bip39(prompt, prefill_word, can_go_back)?; + Ok(LayoutObj::new_root(layout)?.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = |_args: &[Obj], kwargs: &Map| { + let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; + let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; + let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; + + let layout = ModelUI::request_slip39(prompt, prefill_word, can_go_back)?; + Ok(LayoutObj::new_root(layout)?.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; + let subprompt: TString = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?; + let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?; + let warning: bool = kwargs.get_or(Qstr::MP_QSTR_wrong_pin, false)?; + + let layout = ModelUI::request_pin(prompt, subprompt, allow_cancel, warning)?; + Ok(LayoutObj::new_root(layout)?.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; + let max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?; + + let layout = ModelUI::request_passphrase(prompt, max_len)?; + Ok(LayoutObj::new_root(layout)?.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn show_info(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()?; @@ -134,6 +182,42 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// INFO: UiResult Qstr::MP_QSTR_INFO => INFO.as_obj(), + /// def request_bip39( + /// *, + /// prompt: str, + /// prefill_word: str, + /// can_go_back: bool, + /// ) -> LayoutObj[str]: + /// """BIP39 word input keyboard.""" + Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(), + + /// def request_slip39( + /// *, + /// prompt: str, + /// prefill_word: str, + /// can_go_back: bool, + /// ) -> LayoutObj[str]: + /// """SLIP39 word input keyboard.""" + Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(), + + /// def request_pin( + /// *, + /// prompt: str, + /// subprompt: str, + /// allow_cancel: bool = True, + /// wrong_pin: bool = False, + /// ) -> LayoutObj[str | UiResult]: + /// """Request pin on device.""" + Qstr::MP_QSTR_request_pin => obj_fn_kw!(0, new_request_pin).as_obj(), + + /// def request_passphrase( + /// *, + /// prompt: str, + /// max_len: int, + /// ) -> LayoutObj[str | UiResult]: + /// """Passphrase input keyboard.""" + Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(), + /// def show_info( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index c7fdda14da..bdd09e7274 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -1196,63 +1196,6 @@ extern "C" fn new_request_number(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_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let _max_len: usize = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?; - - let flow = flow::request_passphrase::new_request_passphrase()?; - Ok(LayoutObj::new_root(flow)?.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let subprompt: TString = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?; - let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?; - let warning: bool = kwargs.get_or(Qstr::MP_QSTR_wrong_pin, false)?; - let warning = if warning { - Some(TR::pin__wrong_pin.into()) - } else { - None - }; - Ok(LayoutObj::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel))?.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; - let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; - let obj = LayoutObj::new(MnemonicKeyboard::new( - prefill_word.map(Bip39Input::prefilled_word), - prompt, - can_go_back, - ))?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; - let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; - let obj = LayoutObj::new(MnemonicKeyboard::new( - prefill_word.map(Slip39Input::prefilled_word), - prompt, - can_go_back, - ))?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_select_word(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()?; @@ -1742,42 +1685,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Confirm coinjoin authorization.""" Qstr::MP_QSTR_confirm_coinjoin => obj_fn_kw!(0, new_confirm_coinjoin).as_obj(), - /// def request_pin( - /// *, - /// prompt: str, - /// subprompt: str, - /// allow_cancel: bool = True, - /// wrong_pin: bool = False, - /// ) -> LayoutObj[str | UiResult]: - /// """Request pin on device.""" - Qstr::MP_QSTR_request_pin => obj_fn_kw!(0, new_request_pin).as_obj(), - - /// def flow_request_passphrase( - /// *, - /// prompt: str, - /// max_len: int, - /// ) -> LayoutObj[str | UiResult]: - /// """Passphrase input keyboard.""" - Qstr::MP_QSTR_flow_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(), - - /// def request_bip39( - /// *, - /// prompt: str, - /// prefill_word: str, - /// can_go_back: bool, - /// ) -> LayoutObj[str]: - /// """BIP39 word input keyboard.""" - Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(), - - /// def request_slip39( - /// *, - /// prompt: str, - /// prefill_word: str, - /// can_go_back: bool, - /// ) -> LayoutObj[str]: - /// """SLIP39 word input keyboard.""" - Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(), - /// def select_word( /// *, /// 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 e4bb653400..7bd61d50b8 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 @@ -15,11 +15,63 @@ use crate::{ }; use super::{ - component::{Frame, SwipeContent, SwipeUpScreen}, - theme, ModelMercuryFeatures, + component::{ + Bip39Input, Frame, MnemonicKeyboard, PinKeyboard, Slip39Input, SwipeContent, SwipeUpScreen, + }, flow, theme, ModelMercuryFeatures }; impl UIFeaturesFirmware for ModelMercuryFeatures { + fn request_bip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result { + let layout = RootComponent::new(MnemonicKeyboard::new( + prefill_word.map(Bip39Input::prefilled_word), + prompt, + can_go_back, + )); + Ok(layout) + } + + fn request_slip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result { + let layout = RootComponent::new(MnemonicKeyboard::new( + prefill_word.map(Slip39Input::prefilled_word), + prompt, + can_go_back, + )); + + Ok(layout) + } + + fn request_pin( + prompt: TString<'static>, + subprompt: TString<'static>, + allow_cancel: bool, + warning: bool, + ) -> Result { + let warning = if warning { + Some(TR::pin__wrong_pin.into()) + } else { + None + }; + + let layout = RootComponent::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel)); + Ok(layout) + } + + fn request_passphrase( + prompt: TString<'static>, + max_len: u32, + ) -> Result { + let flow = flow::request_passphrase::new_request_passphrase()?; + Ok(flow) + } + fn show_info( title: TString<'static>, description: 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 730958b74e..c9ace4e23e 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -1234,66 +1234,6 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let subprompt: TString = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?; - - let obj = LayoutObj::new(PinEntry::new(prompt, subprompt))?; - - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - - let obj = LayoutObj::new(Frame::new(prompt, PassphraseEntry::new()).with_title_centered())?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; - let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; - - let obj = LayoutObj::new( - Frame::new( - prompt, - prefill_word - .map(|s| WordlistEntry::prefilled_word(s, WordlistType::Bip39, can_go_back)), - ) - .with_title_centered(), - )?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; - let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; - - let obj = LayoutObj::new( - Frame::new( - prompt, - prefill_word - .map(|s| WordlistEntry::prefilled_word(s, WordlistType::Slip39, can_go_back)), - ) - .with_title_centered(), - )?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = |_args: &[Obj], kwargs: &Map| { // we ignore passed in `title` and use `description` in its place @@ -1884,42 +1824,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Confirm coinjoin authorization.""" Qstr::MP_QSTR_confirm_coinjoin => obj_fn_kw!(0, new_confirm_coinjoin).as_obj(), - /// def request_pin( - /// *, - /// prompt: str, - /// subprompt: str, - /// allow_cancel: bool = True, # unused on TR - /// wrong_pin: bool = False, # unused on TR - /// ) -> LayoutObj[str | UiResult]: - /// """Request pin on device.""" - Qstr::MP_QSTR_request_pin => obj_fn_kw!(0, new_request_pin).as_obj(), - - /// def request_passphrase( - /// *, - /// prompt: str, - /// max_len: int, # unused on TR - /// ) -> LayoutObj[str | UiResult]: - /// """Get passphrase.""" - Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(), - - /// def request_bip39( - /// *, - /// prompt: str, - /// prefill_word: str, - /// can_go_back: bool, - /// ) -> LayoutObj[str]: - /// """Get recovery word for BIP39.""" - Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(), - - /// def request_slip39( - /// *, - /// prompt: str, - /// prefill_word: str, - /// can_go_back: bool, - /// ) -> LayoutObj[str]: - /// """SLIP39 word input keyboard.""" - Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(), - /// def select_word( /// *, /// title: str, # unused on TR diff --git a/core/embed/rust/src/ui/model_tr/mod.rs b/core/embed/rust/src/ui/model_tr/mod.rs index 8ad9254362..d7369d81d3 100644 --- a/core/embed/rust/src/ui/model_tr/mod.rs +++ b/core/embed/rust/src/ui/model_tr/mod.rs @@ -12,6 +12,8 @@ mod screens; pub mod theme; pub struct ModelTRFeatures {} + +#[cfg(feature = "micropython")] pub mod ui_features_fw; impl UIFeaturesCommon for ModelTRFeatures { 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 c914a99e55..efa2de9eb6 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 @@ -4,16 +4,71 @@ use crate::{ strutil::TString, ui::{ component::{ - text::paragraphs::{Paragraph, Paragraphs}, ComponentExt, Timeout + text::paragraphs::{Paragraph, Paragraphs}, + ComponentExt, Timeout, }, layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, ui_features_fw::UIFeaturesFirmware, }, }; -use super::{component::Frame, theme, ModelTRFeatures}; +use super::{ + component::{Frame, PassphraseEntry, PinEntry, WordlistEntry, WordlistType}, + theme, ModelTRFeatures, +}; impl UIFeaturesFirmware for ModelTRFeatures { + fn request_bip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result { + let layout = RootComponent::new( + Frame::new( + prompt, + prefill_word + .map(|s| WordlistEntry::prefilled_word(s, WordlistType::Bip39, can_go_back)), + ) + .with_title_centered(), + ); + Ok(layout) + } + + fn request_slip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result { + let layout = RootComponent::new( + Frame::new( + prompt, + prefill_word + .map(|s| WordlistEntry::prefilled_word(s, WordlistType::Slip39, can_go_back)), + ) + .with_title_centered(), + ); + Ok(layout) + } + + fn request_pin( + prompt: TString<'static>, + subprompt: TString<'static>, + allow_cancel: bool, + warning: bool, + ) -> Result { + let layout = RootComponent::new(PinEntry::new(prompt, subprompt)); + Ok(layout) + } + + fn request_passphrase( + prompt: TString<'static>, + max_len: u32, + ) -> Result { + let layout = + RootComponent::new(Frame::new(prompt, PassphraseEntry::new()).with_title_centered()); + Ok(layout) + } + fn show_info( title: TString<'static>, description: 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 5624e0f8b4..46bde8f667 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -1198,63 +1198,6 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } -extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let subprompt: TString = kwargs.get(Qstr::MP_QSTR_subprompt)?.try_into()?; - let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?; - let warning: bool = kwargs.get_or(Qstr::MP_QSTR_wrong_pin, false)?; - let warning = if warning { - Some(TR::pin__wrong_pin.into()) - } else { - None - }; - let obj = LayoutObj::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel))?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let _max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?; - let obj = LayoutObj::new(PassphraseKeyboard::new())?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; - let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; - let obj = LayoutObj::new(MnemonicKeyboard::new( - prefill_word.map(Bip39Input::prefilled_word), - prompt, - can_go_back, - ))?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - -extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { - let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let prefill_word: TString = kwargs.get(Qstr::MP_QSTR_prefill_word)?.try_into()?; - let can_go_back: bool = kwargs.get(Qstr::MP_QSTR_can_go_back)?.try_into()?; - let obj = LayoutObj::new(MnemonicKeyboard::new( - prefill_word.map(Slip39Input::prefilled_word), - prompt, - can_go_back, - ))?; - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_select_word(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()?; @@ -1893,42 +1836,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Confirm coinjoin authorization.""" Qstr::MP_QSTR_confirm_coinjoin => obj_fn_kw!(0, new_confirm_coinjoin).as_obj(), - /// def request_pin( - /// *, - /// prompt: str, - /// subprompt: str, - /// allow_cancel: bool = True, - /// wrong_pin: bool = False, - /// ) -> LayoutObj[str | UiResult]: - /// """Request pin on device.""" - Qstr::MP_QSTR_request_pin => obj_fn_kw!(0, new_request_pin).as_obj(), - - /// def request_passphrase( - /// *, - /// prompt: str, - /// max_len: int, - /// ) -> LayoutObj[str | UiResult]: - /// """Passphrase input keyboard.""" - Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(), - - /// def request_bip39( - /// *, - /// prompt: str, - /// prefill_word: str, - /// can_go_back: bool, - /// ) -> LayoutObj[str]: - /// """BIP39 word input keyboard.""" - Qstr::MP_QSTR_request_bip39 => obj_fn_kw!(0, new_request_bip39).as_obj(), - - /// def request_slip39( - /// *, - /// prompt: str, - /// prefill_word: str, - /// can_go_back: bool, - /// ) -> LayoutObj[str]: - /// """SLIP39 word input keyboard.""" - Qstr::MP_QSTR_request_slip39 => obj_fn_kw!(0, new_request_slip39).as_obj(), - /// def select_word( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/model_tt/mod.rs b/core/embed/rust/src/ui/model_tt/mod.rs index e3570ac104..4554c422dc 100644 --- a/core/embed/rust/src/ui/model_tt/mod.rs +++ b/core/embed/rust/src/ui/model_tt/mod.rs @@ -19,6 +19,8 @@ use crate::ui::{ }; pub struct ModelTTFeatures; + +#[cfg(feature = "micropython")] pub mod ui_features_fw; impl UIFeaturesCommon for ModelTTFeatures { 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 129e207db3..afe5cd7d37 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 @@ -2,6 +2,7 @@ use crate::{ error::Error, micropython::gc::Gc, strutil::TString, + translations::TR, ui::{ component::{image::BlendedImage, ComponentExt, Empty, Timeout}, layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, @@ -10,11 +11,64 @@ use crate::{ }; use super::{ - component::{Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, IconDialog}, + component::{ + Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, IconDialog, + MnemonicKeyboard, PassphraseKeyboard, PinKeyboard, Slip39Input, + }, theme, ModelTTFeatures, }; impl UIFeaturesFirmware for ModelTTFeatures { + fn request_bip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result { + let layout = RootComponent::new(MnemonicKeyboard::new( + prefill_word.map(Bip39Input::prefilled_word), + prompt, + can_go_back, + )); + Ok(layout) + } + + fn request_slip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result { + let layout = RootComponent::new(MnemonicKeyboard::new( + prefill_word.map(Slip39Input::prefilled_word), + prompt, + can_go_back, + )); + + Ok(layout) + } + + fn request_pin( + prompt: TString<'static>, + subprompt: TString<'static>, + allow_cancel: bool, + warning: bool, + ) -> Result { + let warning = if warning { + Some(TR::pin__wrong_pin.into()) + } else { + None + }; + let layout = RootComponent::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel)); + Ok(layout) + } + + fn request_passphrase( + prompt: TString<'static>, + max_len: u32, + ) -> Result { + let layout = RootComponent::new(PassphraseKeyboard::new()); + Ok(layout) + } + fn show_info( title: TString<'static>, description: TString<'static>, @@ -33,17 +87,17 @@ impl UIFeaturesFirmware for ModelTTFeatures { theme::FG, theme::BG, ); - let res = new_show_modal( + let obj = new_show_modal( title, TString::empty(), description, - TString::empty(), + button, false, time_ms, icon, theme::button_info(), )?; - Ok(res) + Ok(obj) } } diff --git a/core/embed/rust/src/ui/ui_features_fw.rs b/core/embed/rust/src/ui/ui_features_fw.rs index f721394cb3..634b027a02 100644 --- a/core/embed/rust/src/ui/ui_features_fw.rs +++ b/core/embed/rust/src/ui/ui_features_fw.rs @@ -3,6 +3,30 @@ use crate::{error::Error, micropython::gc::Gc, strutil::TString}; use super::layout::obj::{LayoutMaybeTrace, LayoutObj}; pub trait UIFeaturesFirmware { + fn request_bip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result; + + fn request_slip39( + prompt: TString<'static>, + prefill_word: TString<'static>, + can_go_back: bool, + ) -> Result; + + fn request_pin( + prompt: TString<'static>, + subprompt: TString<'static>, + allow_cancel: bool, + warning: bool, + ) -> Result; + + fn request_passphrase( + prompt: TString<'static>, + max_len: u32, + ) -> Result; + fn show_info( title: TString<'static>, description: TString<'static>, diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index 8a594f1c9c..6e4fe379b3 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -270,46 +270,6 @@ def confirm_coinjoin( """Confirm coinjoin authorization.""" -# rust/src/ui/model_mercury/layout.rs -def request_pin( - *, - prompt: str, - subprompt: str, - allow_cancel: bool = True, - wrong_pin: bool = False, -) -> LayoutObj[str | UiResult]: - """Request pin on device.""" - - -# rust/src/ui/model_mercury/layout.rs -def flow_request_passphrase( - *, - prompt: str, - max_len: int, -) -> LayoutObj[str | UiResult]: - """Passphrase input keyboard.""" - - -# rust/src/ui/model_mercury/layout.rs -def request_bip39( - *, - prompt: str, - prefill_word: str, - can_go_back: bool, -) -> LayoutObj[str]: - """BIP39 word input keyboard.""" - - -# rust/src/ui/model_mercury/layout.rs -def request_slip39( - *, - prompt: str, - prefill_word: str, - can_go_back: bool, -) -> LayoutObj[str]: - """SLIP39 word input keyboard.""" - - # rust/src/ui/model_mercury/layout.rs def select_word( *, @@ -824,46 +784,6 @@ def confirm_coinjoin( """Confirm coinjoin authorization.""" -# rust/src/ui/model_tr/layout.rs -def request_pin( - *, - prompt: str, - subprompt: str, - allow_cancel: bool = True, # unused on TR - wrong_pin: bool = False, # unused on TR -) -> LayoutObj[str | UiResult]: - """Request pin on device.""" - - -# rust/src/ui/model_tr/layout.rs -def request_passphrase( - *, - prompt: str, - max_len: int, # unused on TR -) -> LayoutObj[str | UiResult]: - """Get passphrase.""" - - -# rust/src/ui/model_tr/layout.rs -def request_bip39( - *, - prompt: str, - prefill_word: str, - can_go_back: bool, -) -> LayoutObj[str]: - """Get recovery word for BIP39.""" - - -# rust/src/ui/model_tr/layout.rs -def request_slip39( - *, - prompt: str, - prefill_word: str, - can_go_back: bool, -) -> LayoutObj[str]: - """SLIP39 word input keyboard.""" - - # rust/src/ui/model_tr/layout.rs def select_word( *, @@ -1277,46 +1197,6 @@ def confirm_coinjoin( """Confirm coinjoin authorization.""" -# rust/src/ui/model_tt/layout.rs -def request_pin( - *, - prompt: str, - subprompt: str, - allow_cancel: bool = True, - wrong_pin: bool = False, -) -> LayoutObj[str | UiResult]: - """Request pin on device.""" - - -# rust/src/ui/model_tt/layout.rs -def request_passphrase( - *, - prompt: str, - max_len: int, -) -> LayoutObj[str | UiResult]: - """Passphrase input keyboard.""" - - -# rust/src/ui/model_tt/layout.rs -def request_bip39( - *, - prompt: str, - prefill_word: str, - can_go_back: bool, -) -> LayoutObj[str]: - """BIP39 word input keyboard.""" - - -# rust/src/ui/model_tt/layout.rs -def request_slip39( - *, - prompt: str, - prefill_word: str, - can_go_back: bool, -) -> LayoutObj[str]: - """SLIP39 word input keyboard.""" - - # rust/src/ui/model_tt/layout.rs def select_word( *, diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index 17f0c7f367..aea8b7edd0 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -68,6 +68,46 @@ CANCELLED: UiResult INFO: UiResult +# rust/src/ui/api/firmware_upy.rs +def request_bip39( + *, + prompt: str, + prefill_word: str, + can_go_back: bool, +) -> LayoutObj[str]: + """BIP39 word input keyboard.""" + + +# rust/src/ui/api/firmware_upy.rs +def request_slip39( + *, + prompt: str, + prefill_word: str, + can_go_back: bool, +) -> LayoutObj[str]: + """SLIP39 word input keyboard.""" + + +# rust/src/ui/api/firmware_upy.rs +def request_pin( + *, + prompt: str, + subprompt: str, + allow_cancel: bool = True, + wrong_pin: bool = False, +) -> LayoutObj[str | UiResult]: + """Request pin on device.""" + + +# rust/src/ui/api/firmware_upy.rs +def request_passphrase( + *, + prompt: str, + max_len: int, +) -> LayoutObj[str | UiResult]: + """Passphrase input keyboard.""" + + # rust/src/ui/api/firmware_upy.rs def show_info( *, diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py index 983cd156b5..32723b8ae6 100644 --- a/core/src/trezor/ui/layouts/mercury/__init__.py +++ b/core/src/trezor/ui/layouts/mercury/__init__.py @@ -1095,7 +1095,7 @@ def show_wait_text(message: str) -> None: def request_passphrase_on_device(max_len: int) -> Awaitable[str]: result = interact( - trezorui2.flow_request_passphrase( + trezorui_api.request_passphrase( prompt=TR.passphrase__title_enter, max_len=max_len ), "passphrase_device", @@ -1121,7 +1121,7 @@ def request_pin_on_device( subprompt = f"{attempts_remaining} {TR.pin__tries_left}" result = interact( - trezorui2.request_pin( + trezorui_api.request_pin( prompt=prompt, subprompt=subprompt, allow_cancel=allow_cancel, diff --git a/core/src/trezor/ui/layouts/mercury/recovery.py b/core/src/trezor/ui/layouts/mercury/recovery.py index 8f0b9c244b..71c45d7d1c 100644 --- a/core/src/trezor/ui/layouts/mercury/recovery.py +++ b/core/src/trezor/ui/layouts/mercury/recovery.py @@ -34,11 +34,11 @@ async def request_word( prompt = TR.recovery__word_x_of_y_template.format(word_index + 1, word_count) can_go_back = word_index > 0 if is_slip39: - keyboard = trezorui2.request_slip39( + keyboard = trezorui_api.request_slip39( prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back ) else: - keyboard = trezorui2.request_bip39( + keyboard = trezorui_api.request_bip39( prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back ) diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index f0d5c543a8..dbcc022b3a 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -1153,7 +1153,7 @@ def show_wait_text(message: str) -> None: async def request_passphrase_on_device(max_len: int) -> str: result = await interact( - trezorui2.request_passphrase( + trezorui_api.request_passphrase( prompt=TR.passphrase__title_enter, max_len=max_len, ), @@ -1183,7 +1183,7 @@ async def request_pin_on_device( subprompt = f"{attempts_remaining} {TR.pin__tries_left}" result = await interact( - trezorui2.request_pin( + trezorui_api.request_pin( prompt=prompt, subprompt=subprompt, allow_cancel=allow_cancel, diff --git a/core/src/trezor/ui/layouts/tr/recovery.py b/core/src/trezor/ui/layouts/tr/recovery.py index 82786672c0..1007e7d4b4 100644 --- a/core/src/trezor/ui/layouts/tr/recovery.py +++ b/core/src/trezor/ui/layouts/tr/recovery.py @@ -36,12 +36,12 @@ async def request_word( can_go_back = word_index > 0 if is_slip39: - keyboard = trezorui2.request_slip39( + keyboard = trezorui_api.request_slip39( prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back ) else: - keyboard = trezorui2.request_bip39( + keyboard = trezorui_api.request_bip39( prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back ) diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index 67dc1776b6..ff447deef0 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -1154,7 +1154,9 @@ def show_wait_text(message: str) -> None: async def request_passphrase_on_device(max_len: int) -> str: result = await interact( - trezorui2.request_passphrase(prompt="Enter passphrase", max_len=max_len), + trezorui_api.request_passphrase( + prompt=TR.passphrase__title_enter, max_len=max_len + ), "passphrase_device", ButtonRequestType.PassphraseEntry, raise_on_cancel=ActionCancelled("Passphrase entry cancelled"), @@ -1179,7 +1181,7 @@ async def request_pin_on_device( subprompt = f"{attempts_remaining} {TR.pin__tries_left}" result = await interact( - trezorui2.request_pin( + trezorui_api.request_pin( prompt=prompt, subprompt=subprompt, allow_cancel=allow_cancel, diff --git a/core/src/trezor/ui/layouts/tt/recovery.py b/core/src/trezor/ui/layouts/tt/recovery.py index 7de8e3be45..cf905352ba 100644 --- a/core/src/trezor/ui/layouts/tt/recovery.py +++ b/core/src/trezor/ui/layouts/tt/recovery.py @@ -34,12 +34,12 @@ async def request_word( prompt = TR.recovery__type_word_x_of_y_template.format(word_index + 1, word_count) can_go_back = word_index > 0 if is_slip39: - keyboard = trezorui2.request_slip39( + keyboard = trezorui_api.request_slip39( prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back ) else: - keyboard = trezorui2.request_bip39( + keyboard = trezorui_api.request_bip39( prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back )