mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-16 17:42:02 +00:00
refactor(core): cleanup continue_recovery
- `confirm_recovery` of model_t and model_r merged with `flow_continue_recovery` of mercury into a `continue_recovery_homepage` trait function - parameters were renamed to be more descriptive - model_t has also the remaining shares info passed in, but not used
This commit is contained in:
parent
46a98b937e
commit
0bc5dfac6a
@ -205,7 +205,6 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_confirm_output_address;
|
MP_QSTR_confirm_output_address;
|
||||||
MP_QSTR_confirm_output_amount;
|
MP_QSTR_confirm_output_amount;
|
||||||
MP_QSTR_confirm_properties;
|
MP_QSTR_confirm_properties;
|
||||||
MP_QSTR_confirm_recovery;
|
|
||||||
MP_QSTR_confirm_reset_device;
|
MP_QSTR_confirm_reset_device;
|
||||||
MP_QSTR_confirm_total;
|
MP_QSTR_confirm_total;
|
||||||
MP_QSTR_confirm_total__fee_rate;
|
MP_QSTR_confirm_total__fee_rate;
|
||||||
@ -215,6 +214,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_confirm_total__title_sending_from;
|
MP_QSTR_confirm_total__title_sending_from;
|
||||||
MP_QSTR_confirm_value;
|
MP_QSTR_confirm_value;
|
||||||
MP_QSTR_confirm_with_info;
|
MP_QSTR_confirm_with_info;
|
||||||
|
MP_QSTR_continue_recovery_homepage;
|
||||||
MP_QSTR_count;
|
MP_QSTR_count;
|
||||||
MP_QSTR_current;
|
MP_QSTR_current;
|
||||||
MP_QSTR_danger;
|
MP_QSTR_danger;
|
||||||
@ -249,11 +249,9 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_fingerprint;
|
MP_QSTR_fingerprint;
|
||||||
MP_QSTR_firmware_update__title;
|
MP_QSTR_firmware_update__title;
|
||||||
MP_QSTR_firmware_update__title_fingerprint;
|
MP_QSTR_firmware_update__title_fingerprint;
|
||||||
MP_QSTR_first_screen;
|
|
||||||
MP_QSTR_flow_confirm_output;
|
MP_QSTR_flow_confirm_output;
|
||||||
MP_QSTR_flow_confirm_set_new_pin;
|
MP_QSTR_flow_confirm_set_new_pin;
|
||||||
MP_QSTR_flow_confirm_summary;
|
MP_QSTR_flow_confirm_summary;
|
||||||
MP_QSTR_flow_continue_recovery;
|
|
||||||
MP_QSTR_flow_get_address;
|
MP_QSTR_flow_get_address;
|
||||||
MP_QSTR_flow_prompt_backup;
|
MP_QSTR_flow_prompt_backup;
|
||||||
MP_QSTR_flow_show_share_words;
|
MP_QSTR_flow_show_share_words;
|
||||||
@ -484,6 +482,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_recovery__x_of_y_entered_template;
|
MP_QSTR_recovery__x_of_y_entered_template;
|
||||||
MP_QSTR_recovery__you_have_entered;
|
MP_QSTR_recovery__you_have_entered;
|
||||||
MP_QSTR_recovery_type;
|
MP_QSTR_recovery_type;
|
||||||
|
MP_QSTR_remaining_shares;
|
||||||
MP_QSTR_request_bip39;
|
MP_QSTR_request_bip39;
|
||||||
MP_QSTR_request_complete_repaint;
|
MP_QSTR_request_complete_repaint;
|
||||||
MP_QSTR_request_number;
|
MP_QSTR_request_number;
|
||||||
|
@ -167,6 +167,37 @@ extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs:
|
|||||||
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_continue_recovery_homepage(
|
||||||
|
n_args: usize,
|
||||||
|
args: *const Obj,
|
||||||
|
kwargs: *mut Map,
|
||||||
|
) -> Obj {
|
||||||
|
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||||
|
let text: TString = kwargs.get(Qstr::MP_QSTR_text)?.try_into()?; // #shares entered
|
||||||
|
let subtext: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtext)?.try_into_option()?; // #shares remaining
|
||||||
|
let button: Option<TString> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_button)
|
||||||
|
.and_then(Obj::try_into_option)
|
||||||
|
.unwrap_or(None);
|
||||||
|
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
||||||
|
let show_instructions: bool = kwargs.get_or(Qstr::MP_QSTR_show_instructions, false)?;
|
||||||
|
let remaining_shares: Option<Obj> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_remaining_shares)?
|
||||||
|
.try_into_option()?; // info about remaining shares
|
||||||
|
|
||||||
|
let obj = ModelUI::continue_recovery_homepage(
|
||||||
|
text,
|
||||||
|
subtext,
|
||||||
|
button,
|
||||||
|
recovery_type,
|
||||||
|
show_instructions,
|
||||||
|
remaining_shares,
|
||||||
|
)?;
|
||||||
|
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 {
|
extern "C" fn new_request_bip39(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 prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
||||||
@ -685,6 +716,18 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
|||||||
/// """Confirm TOS before creating wallet creation or wallet recovery."""
|
/// """Confirm TOS before creating wallet creation or wallet recovery."""
|
||||||
Qstr::MP_QSTR_confirm_reset_device => obj_fn_kw!(0, new_confirm_reset_device).as_obj(),
|
Qstr::MP_QSTR_confirm_reset_device => obj_fn_kw!(0, new_confirm_reset_device).as_obj(),
|
||||||
|
|
||||||
|
/// def continue_recovery_homepage(
|
||||||
|
/// *,
|
||||||
|
/// text: str,
|
||||||
|
/// subtext: str | None,
|
||||||
|
/// button: str | None,
|
||||||
|
/// recovery_type: RecoveryType,
|
||||||
|
/// show_instructions: bool = False, # unused on TT
|
||||||
|
/// remaining_shares: Iterable[tuple[str, str]] | None = None,
|
||||||
|
/// ) -> LayoutObj[UiResult]:
|
||||||
|
/// """Device recovery homescreen."""
|
||||||
|
Qstr::MP_QSTR_continue_recovery_homepage => obj_fn_kw!(0, new_continue_recovery_homepage).as_obj(),
|
||||||
|
|
||||||
/// def request_bip39(
|
/// def request_bip39(
|
||||||
/// *,
|
/// *,
|
||||||
/// prompt: str,
|
/// prompt: str,
|
||||||
|
@ -154,11 +154,11 @@ fn footer_update_fn(
|
|||||||
footer.update_page_counter(ctx, current_page, Some(total_pages));
|
footer.update_page_counter(ctx, current_page, Some(total_pages));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_continue_recovery(
|
pub fn new_continue_recovery_homepage(
|
||||||
first_screen: bool,
|
|
||||||
recovery_type: RecoveryType,
|
|
||||||
text: TString<'static>,
|
text: TString<'static>,
|
||||||
subtext: Option<TString<'static>>,
|
subtext: Option<TString<'static>>,
|
||||||
|
recovery_type: RecoveryType,
|
||||||
|
show_instructions: bool, // 1st screen of the recovery process
|
||||||
pages: Option<ParagraphVecLong<'static>>,
|
pages: Option<ParagraphVecLong<'static>>,
|
||||||
) -> Result<SwipeFlow, error::Error> {
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type {
|
let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type {
|
||||||
@ -179,7 +179,7 @@ pub fn new_continue_recovery(
|
|||||||
let mut pars_main = ParagraphVecShort::new();
|
let mut pars_main = ParagraphVecShort::new();
|
||||||
let footer_instruction;
|
let footer_instruction;
|
||||||
let footer_description;
|
let footer_description;
|
||||||
if first_screen {
|
if show_instructions {
|
||||||
pars_main.add(Paragraph::new(
|
pars_main.add(Paragraph::new(
|
||||||
&theme::TEXT_MAIN_GREY_EXTRA_LIGHT,
|
&theme::TEXT_MAIN_GREY_EXTRA_LIGHT,
|
||||||
TR::recovery__enter_each_word,
|
TR::recovery__enter_each_word,
|
||||||
@ -246,7 +246,7 @@ pub fn new_continue_recovery(
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let res = if first_screen {
|
let res = if show_instructions {
|
||||||
let content_menu = Frame::left_aligned(
|
let content_menu = Frame::left_aligned(
|
||||||
TString::empty(),
|
TString::empty(),
|
||||||
VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()),
|
VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()),
|
@ -8,7 +8,7 @@ pub mod confirm_reset;
|
|||||||
pub mod confirm_set_new_pin;
|
pub mod confirm_set_new_pin;
|
||||||
pub mod confirm_summary;
|
pub mod confirm_summary;
|
||||||
pub mod confirm_with_info;
|
pub mod confirm_with_info;
|
||||||
pub mod continue_recovery;
|
pub mod continue_recovery_homepage;
|
||||||
pub mod get_address;
|
pub mod get_address;
|
||||||
pub mod prompt_backup;
|
pub mod prompt_backup;
|
||||||
pub mod request_number;
|
pub mod request_number;
|
||||||
@ -31,7 +31,7 @@ pub use confirm_reset::new_confirm_reset;
|
|||||||
pub use confirm_set_new_pin::SetNewPin;
|
pub use confirm_set_new_pin::SetNewPin;
|
||||||
pub use confirm_summary::new_confirm_summary;
|
pub use confirm_summary::new_confirm_summary;
|
||||||
pub use confirm_with_info::new_confirm_with_info;
|
pub use confirm_with_info::new_confirm_with_info;
|
||||||
pub use continue_recovery::new_continue_recovery;
|
pub use continue_recovery_homepage::new_continue_recovery_homepage;
|
||||||
pub use get_address::GetAddress;
|
pub use get_address::GetAddress;
|
||||||
pub use prompt_backup::PromptBackup;
|
pub use prompt_backup::PromptBackup;
|
||||||
pub use request_number::RequestNumber;
|
pub use request_number::RequestNumber;
|
||||||
|
@ -741,38 +741,6 @@ extern "C" fn new_confirm_more(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
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_continue_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let first_screen: bool = kwargs.get(Qstr::MP_QSTR_first_screen)?.try_into()?;
|
|
||||||
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
|
||||||
let text: TString = kwargs.get(Qstr::MP_QSTR_text)?.try_into()?; // #shares entered
|
|
||||||
let subtext: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtext)?.try_into_option()?; // #shares remaining
|
|
||||||
let pages: Option<Obj> = kwargs.get(Qstr::MP_QSTR_pages)?.try_into_option()?; // info about remaining shares
|
|
||||||
|
|
||||||
let pages_vec = if let Some(pages_obj) = pages {
|
|
||||||
let mut vec = ParagraphVecLong::new();
|
|
||||||
for page in IterBuf::new().try_iterate(pages_obj)? {
|
|
||||||
let [title, description]: [TString; 2] = util::iter_into_array(page)?;
|
|
||||||
vec.add(Paragraph::new(&theme::TEXT_SUB_GREY, title))
|
|
||||||
.add(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, description).break_after());
|
|
||||||
}
|
|
||||||
Some(vec)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let flow = flow::continue_recovery::new_continue_recovery(
|
|
||||||
first_screen,
|
|
||||||
recovery_type,
|
|
||||||
text,
|
|
||||||
subtext,
|
|
||||||
pages_vec,
|
|
||||||
)?;
|
|
||||||
Ok(LayoutObj::new_root(flow)?.into())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_get_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
extern "C" fn new_get_address(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()?;
|
||||||
@ -997,17 +965,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// confirmation."""
|
/// confirmation."""
|
||||||
Qstr::MP_QSTR_flow_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
Qstr::MP_QSTR_flow_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
||||||
|
|
||||||
/// def flow_continue_recovery(
|
|
||||||
/// *,
|
|
||||||
/// first_screen: bool,
|
|
||||||
/// recovery_type: RecoveryType,
|
|
||||||
/// text: str,
|
|
||||||
/// subtext: str | None = None,
|
|
||||||
/// pages: Iterable[tuple[str, str]] | None = None,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Device recovery homescreen."""
|
|
||||||
Qstr::MP_QSTR_flow_continue_recovery => obj_fn_kw!(0, new_continue_recovery).as_obj(),
|
|
||||||
|
|
||||||
/// def flow_get_address(
|
/// def flow_get_address(
|
||||||
/// *,
|
/// *,
|
||||||
/// address: str | bytes,
|
/// address: str | bytes,
|
||||||
|
@ -3,7 +3,7 @@ use core::cmp::Ordering;
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::{value_error, Error},
|
error::{value_error, Error},
|
||||||
io::BinaryData,
|
io::BinaryData,
|
||||||
micropython::gc::Gc,
|
micropython::{gc::Gc, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -213,6 +213,36 @@ impl UIFeaturesFirmware for ModelMercuryFeatures {
|
|||||||
super::component::check_homescreen_format(image)
|
super::component::check_homescreen_format(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn continue_recovery_homepage(
|
||||||
|
text: TString<'static>,
|
||||||
|
subtext: Option<TString<'static>>,
|
||||||
|
_button: Option<TString<'static>>,
|
||||||
|
recovery_type: RecoveryType,
|
||||||
|
show_instructions: bool,
|
||||||
|
remaining_shares: Option<crate::micropython::obj::Obj>,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let pages_vec = if let Some(pages_obj) = remaining_shares {
|
||||||
|
let mut vec = ParagraphVecLong::new();
|
||||||
|
for page in crate::micropython::iter::IterBuf::new().try_iterate(pages_obj)? {
|
||||||
|
let [title, description]: [TString; 2] = util::iter_into_array(page)?;
|
||||||
|
vec.add(Paragraph::new(&theme::TEXT_SUB_GREY, title))
|
||||||
|
.add(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, description).break_after());
|
||||||
|
}
|
||||||
|
Some(vec)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let flow = flow::continue_recovery_homepage::new_continue_recovery_homepage(
|
||||||
|
text,
|
||||||
|
subtext,
|
||||||
|
recovery_type,
|
||||||
|
show_instructions,
|
||||||
|
pages_vec,
|
||||||
|
)?;
|
||||||
|
LayoutObj::new_root(flow)
|
||||||
|
}
|
||||||
|
|
||||||
fn request_bip39(
|
fn request_bip39(
|
||||||
prompt: TString<'static>,
|
prompt: TString<'static>,
|
||||||
prefill_word: TString<'static>,
|
prefill_word: TString<'static>,
|
||||||
@ -499,7 +529,7 @@ impl UIFeaturesFirmware for ModelMercuryFeatures {
|
|||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
// Mercury: remaining shares is a part of `continue_recovery` flow
|
// Mercury: remaining shares is a part of `continue_recovery` flow
|
||||||
Err::<RootComponent<Empty, ModelMercuryFeatures>, Error>(Error::ValueError(
|
Err::<RootComponent<Empty, ModelMercuryFeatures>, Error>(Error::ValueError(
|
||||||
c"show remaining shares not supported",
|
c"show_remaining_shares not implemented",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,44 +922,6 @@ extern "C" fn new_show_share_words(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_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
|
||||||
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
|
||||||
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
|
||||||
let show_instructions: bool = kwargs.get(Qstr::MP_QSTR_show_instructions)?.try_into()?;
|
|
||||||
|
|
||||||
let mut paragraphs = ParagraphVecShort::new();
|
|
||||||
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, description));
|
|
||||||
if show_instructions {
|
|
||||||
paragraphs
|
|
||||||
.add(Paragraph::new(
|
|
||||||
&theme::TEXT_NORMAL,
|
|
||||||
TR::recovery__enter_each_word,
|
|
||||||
))
|
|
||||||
.add(Paragraph::new(
|
|
||||||
&theme::TEXT_NORMAL,
|
|
||||||
TR::recovery__cursor_will_change,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let title = match recovery_type {
|
|
||||||
RecoveryType::DryRun => TR::recovery__title_dry_run,
|
|
||||||
RecoveryType::UnlockRepeatedBackup => TR::recovery__title_dry_run,
|
|
||||||
_ => TR::recovery__title,
|
|
||||||
};
|
|
||||||
|
|
||||||
content_in_button_page(
|
|
||||||
title.into(),
|
|
||||||
paragraphs.into_paragraphs(),
|
|
||||||
button,
|
|
||||||
Some("".into()),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub static mp_module_trezorui2: Module = obj_module! {
|
pub static mp_module_trezorui2: Module = obj_module! {
|
||||||
/// from trezor import utils
|
/// from trezor import utils
|
||||||
@ -1138,16 +1100,4 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Shows a backup seed."""
|
/// """Shows a backup seed."""
|
||||||
Qstr::MP_QSTR_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
Qstr::MP_QSTR_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
||||||
|
|
||||||
/// def confirm_recovery(
|
|
||||||
/// *,
|
|
||||||
/// title: str, # unused on TR
|
|
||||||
/// description: str,
|
|
||||||
/// button: str,
|
|
||||||
/// recovery_type: RecoveryType,
|
|
||||||
/// info_button: bool, # unused on TR
|
|
||||||
/// show_instructions: bool,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Device recovery homescreen."""
|
|
||||||
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),
|
|
||||||
};
|
};
|
||||||
|
@ -232,6 +232,45 @@ impl UIFeaturesFirmware for ModelTRFeatures {
|
|||||||
super::component::check_homescreen_format(image)
|
super::component::check_homescreen_format(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn continue_recovery_homepage(
|
||||||
|
text: TString<'static>,
|
||||||
|
_subtext: Option<TString<'static>>,
|
||||||
|
button: Option<TString<'static>>,
|
||||||
|
recovery_type: RecoveryType,
|
||||||
|
show_instructions: bool,
|
||||||
|
_remaining_shares: Option<crate::micropython::obj::Obj>,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let mut paragraphs = ParagraphVecShort::new();
|
||||||
|
let button = button.unwrap_or(TString::empty());
|
||||||
|
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, text));
|
||||||
|
if show_instructions {
|
||||||
|
paragraphs
|
||||||
|
.add(Paragraph::new(
|
||||||
|
&theme::TEXT_NORMAL,
|
||||||
|
TR::recovery__enter_each_word,
|
||||||
|
))
|
||||||
|
.add(Paragraph::new(
|
||||||
|
&theme::TEXT_NORMAL,
|
||||||
|
TR::recovery__cursor_will_change,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = match recovery_type {
|
||||||
|
RecoveryType::DryRun => TR::recovery__title_dry_run,
|
||||||
|
RecoveryType::UnlockRepeatedBackup => TR::recovery__title_dry_run,
|
||||||
|
_ => TR::recovery__title,
|
||||||
|
};
|
||||||
|
|
||||||
|
let layout = content_in_button_page(
|
||||||
|
title.into(),
|
||||||
|
paragraphs.into_paragraphs(),
|
||||||
|
button,
|
||||||
|
Some("".into()),
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
LayoutObj::new_root(layout)
|
||||||
|
}
|
||||||
|
|
||||||
fn request_bip39(
|
fn request_bip39(
|
||||||
prompt: TString<'static>,
|
prompt: TString<'static>,
|
||||||
prefill_word: TString<'static>,
|
prefill_word: TString<'static>,
|
||||||
|
@ -821,50 +821,6 @@ extern "C" fn new_show_share_words(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_confirm_recovery(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 description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
|
||||||
let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
|
||||||
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
|
||||||
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
|
|
||||||
|
|
||||||
let paragraphs = Paragraphs::new([
|
|
||||||
Paragraph::new(&theme::TEXT_DEMIBOLD, title),
|
|
||||||
Paragraph::new(&theme::TEXT_NORMAL, description),
|
|
||||||
])
|
|
||||||
.with_spacing(theme::RECOVERY_SPACING);
|
|
||||||
|
|
||||||
let notification = match recovery_type {
|
|
||||||
RecoveryType::DryRun => TR::recovery__title_dry_run.into(),
|
|
||||||
RecoveryType::UnlockRepeatedBackup => TR::recovery__title_dry_run.into(),
|
|
||||||
_ => TR::recovery__title.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let obj = if info_button {
|
|
||||||
LayoutObj::new(Frame::left_aligned(
|
|
||||||
theme::label_title(),
|
|
||||||
notification,
|
|
||||||
Dialog::new(
|
|
||||||
paragraphs,
|
|
||||||
Button::cancel_info_confirm(
|
|
||||||
TR::buttons__continue.into(),
|
|
||||||
TR::buttons__more_info.into(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
))?
|
|
||||||
} else {
|
|
||||||
LayoutObj::new(Frame::left_aligned(
|
|
||||||
theme::label_title(),
|
|
||||||
notification,
|
|
||||||
Dialog::new(paragraphs, Button::cancel_confirm_text(None, Some(button))),
|
|
||||||
))?
|
|
||||||
};
|
|
||||||
Ok(obj.into())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub static mp_module_trezorui2: Module = obj_module! {
|
pub static mp_module_trezorui2: Module = obj_module! {
|
||||||
/// from trezor import utils
|
/// from trezor import utils
|
||||||
@ -1015,18 +971,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
/// """Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
||||||
Qstr::MP_QSTR_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
Qstr::MP_QSTR_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(),
|
||||||
|
|
||||||
/// def confirm_recovery(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// description: str,
|
|
||||||
/// button: str,
|
|
||||||
/// recovery_type: RecoveryType,
|
|
||||||
/// info_button: bool = False,
|
|
||||||
/// show_instructions: bool = False, # unused on TT
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Device recovery homescreen."""
|
|
||||||
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -248,6 +248,49 @@ impl UIFeaturesFirmware for ModelTTFeatures {
|
|||||||
super::component::check_homescreen_format(image, false)
|
super::component::check_homescreen_format(image, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn continue_recovery_homepage(
|
||||||
|
text: TString<'static>,
|
||||||
|
subtext: Option<TString<'static>>,
|
||||||
|
button: Option<TString<'static>>,
|
||||||
|
recovery_type: RecoveryType,
|
||||||
|
_show_instructions: bool,
|
||||||
|
remaining_shares: Option<crate::micropython::obj::Obj>,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let paragraphs = Paragraphs::new([
|
||||||
|
Paragraph::new(&theme::TEXT_DEMIBOLD, text),
|
||||||
|
Paragraph::new(&theme::TEXT_NORMAL, subtext.unwrap_or(TString::empty())),
|
||||||
|
])
|
||||||
|
.with_spacing(theme::RECOVERY_SPACING);
|
||||||
|
|
||||||
|
let notification = match recovery_type {
|
||||||
|
RecoveryType::DryRun => TR::recovery__title_dry_run.into(),
|
||||||
|
RecoveryType::UnlockRepeatedBackup => TR::recovery__title_dry_run.into(),
|
||||||
|
_ => TR::recovery__title.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Model T shows remaining shares info in a separate layout
|
||||||
|
let show_info_button = remaining_shares.is_some();
|
||||||
|
if show_info_button {
|
||||||
|
LayoutObj::new(Frame::left_aligned(
|
||||||
|
theme::label_title(),
|
||||||
|
notification,
|
||||||
|
Dialog::new(
|
||||||
|
paragraphs,
|
||||||
|
Button::cancel_info_confirm(
|
||||||
|
TR::buttons__continue.into(),
|
||||||
|
TR::buttons__more_info.into(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
LayoutObj::new(Frame::left_aligned(
|
||||||
|
theme::label_title(),
|
||||||
|
notification,
|
||||||
|
Dialog::new(paragraphs, Button::cancel_confirm_text(None, button)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn request_bip39(
|
fn request_bip39(
|
||||||
prompt: TString<'static>,
|
prompt: TString<'static>,
|
||||||
prefill_word: TString<'static>,
|
prefill_word: TString<'static>,
|
||||||
|
@ -56,6 +56,15 @@ pub trait UIFeaturesFirmware {
|
|||||||
|
|
||||||
fn confirm_reset_device(recovery: bool) -> Result<impl LayoutMaybeTrace, Error>;
|
fn confirm_reset_device(recovery: bool) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
|
|
||||||
|
fn continue_recovery_homepage(
|
||||||
|
text: TString<'static>,
|
||||||
|
subtext: Option<TString<'static>>,
|
||||||
|
button: Option<TString<'static>>,
|
||||||
|
recovery_type: RecoveryType,
|
||||||
|
show_instructions: bool,
|
||||||
|
remaining_shares: Option<Obj>, // TODO: replace Obj
|
||||||
|
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
|
||||||
|
|
||||||
fn check_homescreen_format(image: BinaryData, accept_toif: bool) -> bool;
|
fn check_homescreen_format(image: BinaryData, accept_toif: bool) -> bool;
|
||||||
|
|
||||||
fn request_bip39(
|
fn request_bip39(
|
||||||
|
@ -163,18 +163,6 @@ def flow_show_share_words(
|
|||||||
confirmation."""
|
confirmation."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
|
||||||
def flow_continue_recovery(
|
|
||||||
*,
|
|
||||||
first_screen: bool,
|
|
||||||
recovery_type: RecoveryType,
|
|
||||||
text: str,
|
|
||||||
subtext: str | None = None,
|
|
||||||
pages: Iterable[tuple[str, str]] | None = None,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Device recovery homescreen."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
# rust/src/ui/model_mercury/layout.rs
|
||||||
def flow_get_address(
|
def flow_get_address(
|
||||||
*,
|
*,
|
||||||
@ -432,19 +420,6 @@ def show_share_words(
|
|||||||
share_words: Iterable[str],
|
share_words: Iterable[str],
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
"""Shows a backup seed."""
|
"""Shows a backup seed."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tr/layout.rs
|
|
||||||
def confirm_recovery(
|
|
||||||
*,
|
|
||||||
title: str, # unused on TR
|
|
||||||
description: str,
|
|
||||||
button: str,
|
|
||||||
recovery_type: RecoveryType,
|
|
||||||
info_button: bool, # unused on TR
|
|
||||||
show_instructions: bool,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Device recovery homescreen."""
|
|
||||||
from trezor import utils
|
from trezor import utils
|
||||||
from trezorui_api import *
|
from trezorui_api import *
|
||||||
|
|
||||||
@ -603,16 +578,3 @@ def show_share_words(
|
|||||||
pages: Iterable[str],
|
pages: Iterable[str],
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
"""Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
"""Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tt/layout.rs
|
|
||||||
def confirm_recovery(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
description: str,
|
|
||||||
button: str,
|
|
||||||
recovery_type: RecoveryType,
|
|
||||||
info_button: bool = False,
|
|
||||||
show_instructions: bool = False, # unused on TT
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Device recovery homescreen."""
|
|
||||||
|
@ -150,6 +150,19 @@ def confirm_reset_device(recovery: bool) -> LayoutObj[UiResult]:
|
|||||||
"""Confirm TOS before creating wallet creation or wallet recovery."""
|
"""Confirm TOS before creating wallet creation or wallet recovery."""
|
||||||
|
|
||||||
|
|
||||||
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
|
def continue_recovery_homepage(
|
||||||
|
*,
|
||||||
|
text: str,
|
||||||
|
subtext: str | None,
|
||||||
|
button: str | None,
|
||||||
|
recovery_type: RecoveryType,
|
||||||
|
show_instructions: bool = False, # unused on TT
|
||||||
|
remaining_shares: Iterable[tuple[str, str]] | None = None,
|
||||||
|
) -> LayoutObj[UiResult]:
|
||||||
|
"""Device recovery homescreen."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_upy.rs
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
def request_bip39(
|
def request_bip39(
|
||||||
*,
|
*,
|
||||||
|
@ -100,7 +100,7 @@ async def show_group_share_success(share_index: int, group_index: int) -> None:
|
|||||||
|
|
||||||
|
|
||||||
async def continue_recovery(
|
async def continue_recovery(
|
||||||
button_label: str, # unused on mercury
|
_button_label: str, # unused on mercury
|
||||||
text: str,
|
text: str,
|
||||||
subtext: str | None,
|
subtext: str | None,
|
||||||
recovery_type: RecoveryType,
|
recovery_type: RecoveryType,
|
||||||
@ -108,12 +108,13 @@ async def continue_recovery(
|
|||||||
remaining_shares_info: "RemainingSharesInfo | None" = None,
|
remaining_shares_info: "RemainingSharesInfo | None" = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
result = await interact(
|
result = await interact(
|
||||||
trezorui2.flow_continue_recovery(
|
trezorui_api.continue_recovery_homepage(
|
||||||
first_screen=show_instructions,
|
|
||||||
recovery_type=recovery_type,
|
|
||||||
text=text,
|
text=text,
|
||||||
subtext=subtext,
|
subtext=subtext,
|
||||||
pages=(
|
button=None,
|
||||||
|
recovery_type=recovery_type,
|
||||||
|
show_instructions=show_instructions,
|
||||||
|
remaining_shares=(
|
||||||
format_remaining_shares_info(remaining_shares_info)
|
format_remaining_shares_info(remaining_shares_info)
|
||||||
if remaining_shares_info
|
if remaining_shares_info
|
||||||
else None
|
else None
|
||||||
|
@ -123,13 +123,13 @@ async def continue_recovery(
|
|||||||
if subtext:
|
if subtext:
|
||||||
text += f"\n\n{subtext}"
|
text += f"\n\n{subtext}"
|
||||||
|
|
||||||
homepage = trezorui2.confirm_recovery(
|
homepage = trezorui_api.continue_recovery_homepage(
|
||||||
title="",
|
text=text,
|
||||||
description=text,
|
subtext=None,
|
||||||
button=button_label,
|
button=button_label,
|
||||||
recovery_type=recovery_type,
|
recovery_type=recovery_type,
|
||||||
info_button=False,
|
|
||||||
show_instructions=show_instructions,
|
show_instructions=show_instructions,
|
||||||
|
remaining_shares=None,
|
||||||
)
|
)
|
||||||
while True:
|
while True:
|
||||||
result = await interact(
|
result = await interact(
|
||||||
|
@ -51,14 +51,14 @@ async def request_word(
|
|||||||
return word
|
return word
|
||||||
|
|
||||||
|
|
||||||
def show_remaining_shares(
|
def format_remaining_shares_info(
|
||||||
groups: set[tuple[str, ...]],
|
remaining_shares_info: "RemainingSharesInfo",
|
||||||
shares_remaining: list[int],
|
) -> list[tuple[str, str]]:
|
||||||
group_threshold: int,
|
|
||||||
) -> Awaitable[trezorui_api.UiResult]:
|
|
||||||
from trezor import strings
|
from trezor import strings
|
||||||
from trezor.crypto.slip39 import MAX_SHARE_COUNT
|
from trezor.crypto.slip39 import MAX_SHARE_COUNT
|
||||||
|
|
||||||
|
groups, shares_remaining, group_threshold = remaining_shares_info
|
||||||
|
|
||||||
pages: list[tuple[str, str]] = []
|
pages: list[tuple[str, str]] = []
|
||||||
completed_groups = shares_remaining.count(0)
|
completed_groups = shares_remaining.count(0)
|
||||||
|
|
||||||
@ -81,6 +81,12 @@ def show_remaining_shares(
|
|||||||
words = "\n".join(group)
|
words = "\n".join(group)
|
||||||
pages.append((title, words))
|
pages.append((title, words))
|
||||||
|
|
||||||
|
return pages
|
||||||
|
|
||||||
|
|
||||||
|
def show_remaining_shares(
|
||||||
|
pages: list[tuple[str, str]],
|
||||||
|
) -> Awaitable[trezorui_api.UiResult]:
|
||||||
return interact(
|
return interact(
|
||||||
trezorui_api.show_remaining_shares(pages=pages),
|
trezorui_api.show_remaining_shares(pages=pages),
|
||||||
"show_shares",
|
"show_shares",
|
||||||
@ -146,12 +152,17 @@ async def continue_recovery(
|
|||||||
else:
|
else:
|
||||||
description = subtext or ""
|
description = subtext or ""
|
||||||
|
|
||||||
homepage = trezorui2.confirm_recovery(
|
remaining_shares = (
|
||||||
title=text,
|
format_remaining_shares_info(remaining_shares_info)
|
||||||
description=description,
|
if remaining_shares_info
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
homepage = trezorui_api.continue_recovery_homepage(
|
||||||
|
text=text,
|
||||||
|
subtext=description,
|
||||||
button=button_label,
|
button=button_label,
|
||||||
recovery_type=recovery_type,
|
recovery_type=recovery_type,
|
||||||
info_button=remaining_shares_info is not None,
|
remaining_shares=remaining_shares,
|
||||||
)
|
)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -164,8 +175,8 @@ async def continue_recovery(
|
|||||||
|
|
||||||
if result is trezorui_api.CONFIRMED:
|
if result is trezorui_api.CONFIRMED:
|
||||||
return True
|
return True
|
||||||
elif result is trezorui_api.INFO and remaining_shares_info is not None:
|
elif result is trezorui_api.INFO and remaining_shares is not None:
|
||||||
await show_remaining_shares(*remaining_shares_info)
|
await show_remaining_shares(remaining_shares)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
await _confirm_abort(recovery_type != RecoveryType.NormalRecovery)
|
await _confirm_abort(recovery_type != RecoveryType.NormalRecovery)
|
||||||
|
Loading…
Reference in New Issue
Block a user