1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-07 14:00:57 +00:00

refactor(core): move keyboards to UiFeatures

Make layouts utilizing keyboards a part of UiFeaturesFirmware
This commit is contained in:
obrusvit 2024-10-22 22:24:40 +02:00
parent 8683b0158a
commit 817dedcaf4
19 changed files with 335 additions and 423 deletions

View File

@ -260,7 +260,6 @@ static void _librust_qstrs(void) {
MP_QSTR_flow_get_address; MP_QSTR_flow_get_address;
MP_QSTR_flow_prompt_backup; MP_QSTR_flow_prompt_backup;
MP_QSTR_flow_request_number; MP_QSTR_flow_request_number;
MP_QSTR_flow_request_passphrase;
MP_QSTR_flow_show_share_words; MP_QSTR_flow_show_share_words;
MP_QSTR_flow_warning_hi_prio; MP_QSTR_flow_warning_hi_prio;
MP_QSTR_get_language; MP_QSTR_get_language;

View File

@ -23,6 +23,54 @@ use crate::{
// free-standing functions exported to MicroPython mirror `trait // free-standing functions exported to MicroPython mirror `trait
// UIFeaturesFirmware` // 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 { extern "C" fn show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; 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 /// INFO: UiResult
Qstr::MP_QSTR_INFO => INFO.as_obj(), 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( /// def show_info(
/// *, /// *,
/// title: str, /// title: str,

View File

@ -1211,63 +1211,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) } 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 { extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
@ -1762,42 +1705,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Confirm coinjoin authorization.""" /// """Confirm coinjoin authorization."""
Qstr::MP_QSTR_confirm_coinjoin => obj_fn_kw!(0, new_confirm_coinjoin).as_obj(), 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( /// def select_word(
/// *, /// *,
/// title: str, /// title: str,

View File

@ -15,11 +15,63 @@ use crate::{
}; };
use super::{ use super::{
component::{Frame, SwipeContent, SwipeUpScreen}, component::{
theme, ModelMercuryFeatures, Bip39Input, Frame, MnemonicKeyboard, PinKeyboard, Slip39Input, SwipeContent, SwipeUpScreen,
}, flow, theme, ModelMercuryFeatures
}; };
impl UIFeaturesFirmware for ModelMercuryFeatures { impl UIFeaturesFirmware for ModelMercuryFeatures {
fn request_bip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
let flow = flow::request_passphrase::new_request_passphrase()?;
Ok(flow)
}
fn show_info( fn show_info(
title: TString<'static>, title: TString<'static>,
description: TString<'static>, description: TString<'static>,

View File

@ -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) } 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 { extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| { let block = |_args: &[Obj], kwargs: &Map| {
// we ignore passed in `title` and use `description` in its place // we ignore passed in `title` and use `description` in its place
@ -1885,42 +1825,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Confirm coinjoin authorization.""" /// """Confirm coinjoin authorization."""
Qstr::MP_QSTR_confirm_coinjoin => obj_fn_kw!(0, new_confirm_coinjoin).as_obj(), 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( /// def select_word(
/// *, /// *,
/// title: str, # unused on TR /// title: str, # unused on TR

View File

@ -12,6 +12,8 @@ mod screens;
pub mod theme; pub mod theme;
pub struct ModelTRFeatures {} pub struct ModelTRFeatures {}
#[cfg(feature = "micropython")]
pub mod ui_features_fw; pub mod ui_features_fw;
impl UIFeaturesCommon for ModelTRFeatures { impl UIFeaturesCommon for ModelTRFeatures {

View File

@ -4,16 +4,71 @@ use crate::{
strutil::TString, strutil::TString,
ui::{ ui::{
component::{ component::{
text::paragraphs::{Paragraph, Paragraphs}, ComponentExt, Timeout text::paragraphs::{Paragraph, Paragraphs},
ComponentExt, Timeout,
}, },
layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
ui_features_fw::UIFeaturesFirmware, ui_features_fw::UIFeaturesFirmware,
}, },
}; };
use super::{component::Frame, theme, ModelTRFeatures}; use super::{
component::{Frame, PassphraseEntry, PinEntry, WordlistEntry, WordlistType},
theme, ModelTRFeatures,
};
impl UIFeaturesFirmware for ModelTRFeatures { impl UIFeaturesFirmware for ModelTRFeatures {
fn request_bip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
let layout = RootComponent::new(PinEntry::new(prompt, subprompt));
Ok(layout)
}
fn request_passphrase(
prompt: TString<'static>,
max_len: u32,
) -> Result<impl LayoutMaybeTrace, Error> {
let layout =
RootComponent::new(Frame::new(prompt, PassphraseEntry::new()).with_title_centered());
Ok(layout)
}
fn show_info( fn show_info(
title: TString<'static>, title: TString<'static>,
description: TString<'static>, description: TString<'static>,

View File

@ -1185,63 +1185,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) } 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 { extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
@ -1881,42 +1824,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Confirm coinjoin authorization.""" /// """Confirm coinjoin authorization."""
Qstr::MP_QSTR_confirm_coinjoin => obj_fn_kw!(0, new_confirm_coinjoin).as_obj(), 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( /// def select_word(
/// *, /// *,
/// title: str, /// title: str,

View File

@ -19,6 +19,8 @@ use crate::ui::{
}; };
pub struct ModelTTFeatures; pub struct ModelTTFeatures;
#[cfg(feature = "micropython")]
pub mod ui_features_fw; pub mod ui_features_fw;
impl UIFeaturesCommon for ModelTTFeatures { impl UIFeaturesCommon for ModelTTFeatures {

View File

@ -2,6 +2,7 @@ use crate::{
error::Error, error::Error,
micropython::gc::Gc, micropython::gc::Gc,
strutil::TString, strutil::TString,
translations::TR,
ui::{ ui::{
component::{image::BlendedImage, ComponentExt, Empty, Timeout}, component::{image::BlendedImage, ComponentExt, Empty, Timeout},
layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
@ -10,11 +11,64 @@ use crate::{
}; };
use super::{ use super::{
component::{Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, IconDialog}, component::{
Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, IconDialog,
MnemonicKeyboard, PassphraseKeyboard, PinKeyboard, Slip39Input,
},
theme, ModelTTFeatures, theme, ModelTTFeatures,
}; };
impl UIFeaturesFirmware for ModelTTFeatures { impl UIFeaturesFirmware for ModelTTFeatures {
fn request_bip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
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<impl LayoutMaybeTrace, Error> {
let layout = RootComponent::new(PassphraseKeyboard::new());
Ok(layout)
}
fn show_info( fn show_info(
title: TString<'static>, title: TString<'static>,
description: TString<'static>, description: TString<'static>,
@ -33,17 +87,17 @@ impl UIFeaturesFirmware for ModelTTFeatures {
theme::FG, theme::FG,
theme::BG, theme::BG,
); );
let res = new_show_modal( let obj = new_show_modal(
title, title,
TString::empty(), TString::empty(),
description, description,
TString::empty(), button,
false, false,
time_ms, time_ms,
icon, icon,
theme::button_info(), theme::button_info(),
)?; )?;
Ok(res) Ok(obj)
} }
} }

View File

@ -3,6 +3,30 @@ use crate::{error::Error, micropython::gc::Gc, strutil::TString};
use super::layout::obj::{LayoutMaybeTrace, LayoutObj}; use super::layout::obj::{LayoutMaybeTrace, LayoutObj};
pub trait UIFeaturesFirmware { pub trait UIFeaturesFirmware {
fn request_bip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_slip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_pin(
prompt: TString<'static>,
subprompt: TString<'static>,
allow_cancel: bool,
warning: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_passphrase(
prompt: TString<'static>,
max_len: u32,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_info( fn show_info(
title: TString<'static>, title: TString<'static>,
description: TString<'static>, description: TString<'static>,

View File

@ -275,46 +275,6 @@ def confirm_coinjoin(
"""Confirm coinjoin authorization.""" """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 # rust/src/ui/model_mercury/layout.rs
def select_word( def select_word(
*, *,
@ -830,46 +790,6 @@ def confirm_coinjoin(
"""Confirm coinjoin authorization.""" """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 # rust/src/ui/model_tr/layout.rs
def select_word( def select_word(
*, *,
@ -1284,46 +1204,6 @@ def confirm_coinjoin(
"""Confirm coinjoin authorization.""" """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 # rust/src/ui/model_tt/layout.rs
def select_word( def select_word(
*, *,

View File

@ -68,6 +68,46 @@ CANCELLED: UiResult
INFO: 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 # rust/src/ui/api/firmware_upy.rs
def show_info( def show_info(
*, *,

View File

@ -1095,7 +1095,7 @@ def show_wait_text(message: str) -> None:
def request_passphrase_on_device(max_len: int) -> Awaitable[str]: def request_passphrase_on_device(max_len: int) -> Awaitable[str]:
result = interact( result = interact(
trezorui2.flow_request_passphrase( trezorui_api.request_passphrase(
prompt=TR.passphrase__title_enter, max_len=max_len prompt=TR.passphrase__title_enter, max_len=max_len
), ),
"passphrase_device", "passphrase_device",
@ -1121,7 +1121,7 @@ def request_pin_on_device(
subprompt = f"{attempts_remaining} {TR.pin__tries_left}" subprompt = f"{attempts_remaining} {TR.pin__tries_left}"
result = interact( result = interact(
trezorui2.request_pin( trezorui_api.request_pin(
prompt=prompt, prompt=prompt,
subprompt=subprompt, subprompt=subprompt,
allow_cancel=allow_cancel, allow_cancel=allow_cancel,

View File

@ -34,11 +34,11 @@ async def request_word(
prompt = TR.recovery__word_x_of_y_template.format(word_index + 1, word_count) prompt = TR.recovery__word_x_of_y_template.format(word_index + 1, word_count)
can_go_back = word_index > 0 can_go_back = word_index > 0
if is_slip39: if is_slip39:
keyboard = trezorui2.request_slip39( keyboard = trezorui_api.request_slip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
else: else:
keyboard = trezorui2.request_bip39( keyboard = trezorui_api.request_bip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )

View File

@ -1158,7 +1158,7 @@ def show_wait_text(message: str) -> None:
async def request_passphrase_on_device(max_len: int) -> str: async def request_passphrase_on_device(max_len: int) -> str:
result = await interact( result = await interact(
trezorui2.request_passphrase( trezorui_api.request_passphrase(
prompt=TR.passphrase__title_enter, prompt=TR.passphrase__title_enter,
max_len=max_len, max_len=max_len,
), ),
@ -1188,7 +1188,7 @@ async def request_pin_on_device(
subprompt = f"{attempts_remaining} {TR.pin__tries_left}" subprompt = f"{attempts_remaining} {TR.pin__tries_left}"
result = await interact( result = await interact(
trezorui2.request_pin( trezorui_api.request_pin(
prompt=prompt, prompt=prompt,
subprompt=subprompt, subprompt=subprompt,
allow_cancel=allow_cancel, allow_cancel=allow_cancel,

View File

@ -36,12 +36,12 @@ async def request_word(
can_go_back = word_index > 0 can_go_back = word_index > 0
if is_slip39: if is_slip39:
keyboard = trezorui2.request_slip39( keyboard = trezorui_api.request_slip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
else: else:
keyboard = trezorui2.request_bip39( keyboard = trezorui_api.request_bip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )

View File

@ -1154,7 +1154,9 @@ def show_wait_text(message: str) -> None:
async def request_passphrase_on_device(max_len: int) -> str: async def request_passphrase_on_device(max_len: int) -> str:
result = await interact( 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", "passphrase_device",
ButtonRequestType.PassphraseEntry, ButtonRequestType.PassphraseEntry,
raise_on_cancel=ActionCancelled("Passphrase entry cancelled"), 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}" subprompt = f"{attempts_remaining} {TR.pin__tries_left}"
result = await interact( result = await interact(
trezorui2.request_pin( trezorui_api.request_pin(
prompt=prompt, prompt=prompt,
subprompt=subprompt, subprompt=subprompt,
allow_cancel=allow_cancel, allow_cancel=allow_cancel,

View File

@ -34,12 +34,12 @@ async def request_word(
prompt = TR.recovery__type_word_x_of_y_template.format(word_index + 1, word_count) prompt = TR.recovery__type_word_x_of_y_template.format(word_index + 1, word_count)
can_go_back = word_index > 0 can_go_back = word_index > 0
if is_slip39: if is_slip39:
keyboard = trezorui2.request_slip39( keyboard = trezorui_api.request_slip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
else: else:
keyboard = trezorui2.request_bip39( keyboard = trezorui_api.request_bip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )