1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 15:38:11 +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:
obrusvit 2024-11-07 12:23:13 +01:00
parent 46a98b937e
commit 0bc5dfac6a
16 changed files with 220 additions and 219 deletions

View File

@ -205,7 +205,6 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_output_address;
MP_QSTR_confirm_output_amount;
MP_QSTR_confirm_properties;
MP_QSTR_confirm_recovery;
MP_QSTR_confirm_reset_device;
MP_QSTR_confirm_total;
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_value;
MP_QSTR_confirm_with_info;
MP_QSTR_continue_recovery_homepage;
MP_QSTR_count;
MP_QSTR_current;
MP_QSTR_danger;
@ -249,11 +249,9 @@ static void _librust_qstrs(void) {
MP_QSTR_fingerprint;
MP_QSTR_firmware_update__title;
MP_QSTR_firmware_update__title_fingerprint;
MP_QSTR_first_screen;
MP_QSTR_flow_confirm_output;
MP_QSTR_flow_confirm_set_new_pin;
MP_QSTR_flow_confirm_summary;
MP_QSTR_flow_continue_recovery;
MP_QSTR_flow_get_address;
MP_QSTR_flow_prompt_backup;
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__you_have_entered;
MP_QSTR_recovery_type;
MP_QSTR_remaining_shares;
MP_QSTR_request_bip39;
MP_QSTR_request_complete_repaint;
MP_QSTR_request_number;

View File

@ -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) }
}
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 {
let block = move |_args: &[Obj], kwargs: &Map| {
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."""
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(
/// *,
/// prompt: str,

View File

@ -154,11 +154,11 @@ fn footer_update_fn(
footer.update_page_counter(ctx, current_page, Some(total_pages));
}
pub fn new_continue_recovery(
first_screen: bool,
recovery_type: RecoveryType,
pub fn new_continue_recovery_homepage(
text: TString<'static>,
subtext: Option<TString<'static>>,
recovery_type: RecoveryType,
show_instructions: bool, // 1st screen of the recovery process
pages: Option<ParagraphVecLong<'static>>,
) -> Result<SwipeFlow, error::Error> {
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 footer_instruction;
let footer_description;
if first_screen {
if show_instructions {
pars_main.add(Paragraph::new(
&theme::TEXT_MAIN_GREY_EXTRA_LIGHT,
TR::recovery__enter_each_word,
@ -246,7 +246,7 @@ pub fn new_continue_recovery(
_ => None,
});
let res = if first_screen {
let res = if show_instructions {
let content_menu = Frame::left_aligned(
TString::empty(),
VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()),

View File

@ -8,7 +8,7 @@ pub mod confirm_reset;
pub mod confirm_set_new_pin;
pub mod confirm_summary;
pub mod confirm_with_info;
pub mod continue_recovery;
pub mod continue_recovery_homepage;
pub mod get_address;
pub mod prompt_backup;
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_summary::new_confirm_summary;
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 prompt_backup::PromptBackup;
pub use request_number::RequestNumber;

View File

@ -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) }
}
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 {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
@ -997,17 +965,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// confirmation."""
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(
/// *,
/// address: str | bytes,

View File

@ -3,7 +3,7 @@ use core::cmp::Ordering;
use crate::{
error::{value_error, Error},
io::BinaryData,
micropython::gc::Gc,
micropython::{gc::Gc, util},
strutil::TString,
translations::TR,
ui::{
@ -213,6 +213,36 @@ impl UIFeaturesFirmware for ModelMercuryFeatures {
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(
prompt: TString<'static>,
prefill_word: TString<'static>,
@ -499,7 +529,7 @@ impl UIFeaturesFirmware for ModelMercuryFeatures {
) -> Result<impl LayoutMaybeTrace, Error> {
// Mercury: remaining shares is a part of `continue_recovery` flow
Err::<RootComponent<Empty, ModelMercuryFeatures>, Error>(Error::ValueError(
c"show remaining shares not supported",
c"show_remaining_shares not implemented",
))
}

View File

@ -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) }
}
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]
pub static mp_module_trezorui2: Module = obj_module! {
/// from trezor import utils
@ -1138,16 +1100,4 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// ) -> LayoutObj[UiResult]:
/// """Shows a backup seed."""
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(),
};

View File

@ -232,6 +232,45 @@ impl UIFeaturesFirmware for ModelTRFeatures {
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(
prompt: TString<'static>,
prefill_word: TString<'static>,

View File

@ -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) }
}
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]
pub static mp_module_trezorui2: Module = obj_module! {
/// from trezor import utils
@ -1015,18 +971,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// ) -> LayoutObj[UiResult]:
/// """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(),
/// 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)]

View File

@ -248,6 +248,49 @@ impl UIFeaturesFirmware for ModelTTFeatures {
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(
prompt: TString<'static>,
prefill_word: TString<'static>,

View File

@ -56,6 +56,15 @@ pub trait UIFeaturesFirmware {
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 request_bip39(

View File

@ -163,18 +163,6 @@ def flow_show_share_words(
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
def flow_get_address(
*,
@ -432,19 +420,6 @@ def show_share_words(
share_words: Iterable[str],
) -> LayoutObj[UiResult]:
"""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 trezorui_api import *
@ -603,16 +578,3 @@ def show_share_words(
pages: Iterable[str],
) -> LayoutObj[UiResult]:
"""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."""

View File

@ -150,6 +150,19 @@ def confirm_reset_device(recovery: bool) -> LayoutObj[UiResult]:
"""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
def request_bip39(
*,

View File

@ -100,7 +100,7 @@ async def show_group_share_success(share_index: int, group_index: int) -> None:
async def continue_recovery(
button_label: str, # unused on mercury
_button_label: str, # unused on mercury
text: str,
subtext: str | None,
recovery_type: RecoveryType,
@ -108,12 +108,13 @@ async def continue_recovery(
remaining_shares_info: "RemainingSharesInfo | None" = None,
) -> bool:
result = await interact(
trezorui2.flow_continue_recovery(
first_screen=show_instructions,
recovery_type=recovery_type,
trezorui_api.continue_recovery_homepage(
text=text,
subtext=subtext,
pages=(
button=None,
recovery_type=recovery_type,
show_instructions=show_instructions,
remaining_shares=(
format_remaining_shares_info(remaining_shares_info)
if remaining_shares_info
else None

View File

@ -123,13 +123,13 @@ async def continue_recovery(
if subtext:
text += f"\n\n{subtext}"
homepage = trezorui2.confirm_recovery(
title="",
description=text,
homepage = trezorui_api.continue_recovery_homepage(
text=text,
subtext=None,
button=button_label,
recovery_type=recovery_type,
info_button=False,
show_instructions=show_instructions,
remaining_shares=None,
)
while True:
result = await interact(

View File

@ -51,14 +51,14 @@ async def request_word(
return word
def show_remaining_shares(
groups: set[tuple[str, ...]],
shares_remaining: list[int],
group_threshold: int,
) -> Awaitable[trezorui_api.UiResult]:
def format_remaining_shares_info(
remaining_shares_info: "RemainingSharesInfo",
) -> list[tuple[str, str]]:
from trezor import strings
from trezor.crypto.slip39 import MAX_SHARE_COUNT
groups, shares_remaining, group_threshold = remaining_shares_info
pages: list[tuple[str, str]] = []
completed_groups = shares_remaining.count(0)
@ -81,6 +81,12 @@ def show_remaining_shares(
words = "\n".join(group)
pages.append((title, words))
return pages
def show_remaining_shares(
pages: list[tuple[str, str]],
) -> Awaitable[trezorui_api.UiResult]:
return interact(
trezorui_api.show_remaining_shares(pages=pages),
"show_shares",
@ -146,12 +152,17 @@ async def continue_recovery(
else:
description = subtext or ""
homepage = trezorui2.confirm_recovery(
title=text,
description=description,
remaining_shares = (
format_remaining_shares_info(remaining_shares_info)
if remaining_shares_info
else None
)
homepage = trezorui_api.continue_recovery_homepage(
text=text,
subtext=description,
button=button_label,
recovery_type=recovery_type,
info_button=remaining_shares_info is not None,
remaining_shares=remaining_shares,
)
while True:
@ -164,8 +175,8 @@ async def continue_recovery(
if result is trezorui_api.CONFIRMED:
return True
elif result is trezorui_api.INFO and remaining_shares_info is not None:
await show_remaining_shares(*remaining_shares_info)
elif result is trezorui_api.INFO and remaining_shares is not None:
await show_remaining_shares(remaining_shares)
else:
try:
await _confirm_abort(recovery_type != RecoveryType.NormalRecovery)