mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-03 16:56:07 +00:00
feat(core/ui): show success screens between shares
This commit also adds minor improvements to reset flow. [no changelog]
This commit is contained in:
parent
72bdea6754
commit
5bd6996ae4
@ -97,9 +97,11 @@ impl ConfirmResetCreate {
|
|||||||
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info))
|
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info))
|
||||||
.one_button_request(ButtonRequestCode::ResetDevice.with_type("setup_device"));
|
.one_button_request(ButtonRequestCode::ResetDevice.with_type("setup_device"));
|
||||||
|
|
||||||
|
// FIXME: TR::reset__cancel_create_wallet should be used but Button text on
|
||||||
|
// multiple lines not supported yet
|
||||||
let content_menu = Frame::left_aligned(
|
let content_menu = Frame::left_aligned(
|
||||||
"".into(),
|
"".into(),
|
||||||
VerticalMenu::empty().danger(theme::ICON_CANCEL, "Cancel".into()), // TODO: use TR
|
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
|
||||||
)
|
)
|
||||||
.with_cancel_button()
|
.with_cancel_button()
|
||||||
.with_swipe(SwipeDirection::Right, SwipeSettings::immediate())
|
.with_swipe(SwipeDirection::Right, SwipeSettings::immediate())
|
||||||
|
@ -112,13 +112,12 @@ impl ShowShareWords {
|
|||||||
.map(|_| Some(FlowMsg::Confirmed));
|
.map(|_| Some(FlowMsg::Confirmed));
|
||||||
|
|
||||||
let content_check_backup_intro = Frame::left_aligned(
|
let content_check_backup_intro = Frame::left_aligned(
|
||||||
TR::reset__check_backup_title.into(),
|
TR::reset__check_wallet_backup_title.into(),
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
TR::reset__check_backup_instructions,
|
TR::reset__check_backup_instructions,
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
.with_subtitle(TR::words__instructions.into())
|
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
.with_swipe(SwipeDirection::Up, SwipeSettings::default())
|
.with_swipe(SwipeDirection::Up, SwipeSettings::default())
|
||||||
.map(|_| Some(FlowMsg::Confirmed));
|
.map(|_| Some(FlowMsg::Confirmed));
|
||||||
|
@ -788,10 +788,15 @@ extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
extern "C" fn new_show_success(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
extern "C" fn new_show_success(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()?;
|
||||||
|
let description: Option<TString> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_description)?
|
||||||
|
.try_into_option()?
|
||||||
|
.and_then(|desc: TString| if desc.is_empty() { None } else { Some(desc) });
|
||||||
|
|
||||||
let content = StatusScreen::new_success();
|
let content = StatusScreen::new_success();
|
||||||
let obj = LayoutObj::new(SwipeUpScreen::new(
|
let obj = LayoutObj::new(SwipeUpScreen::new(
|
||||||
Frame::left_aligned(title, SwipeContent::new(content).with_normal_attach(None))
|
Frame::left_aligned(title, SwipeContent::new(content).with_normal_attach(None))
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
.with_footer(TR::instructions__swipe_up.into(), description)
|
||||||
.with_swipe(SwipeDirection::Up, SwipeSettings::default()),
|
.with_swipe(SwipeDirection::Up, SwipeSettings::default()),
|
||||||
))?;
|
))?;
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
@ -1572,7 +1577,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// allow_cancel: bool = False,
|
/// allow_cancel: bool = False,
|
||||||
/// time_ms: int = 0,
|
/// time_ms: int = 0,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Success modal. No buttons shown when `button` is empty string."""
|
/// """Success screen. Description is used in the footer."""
|
||||||
Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(),
|
Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(),
|
||||||
|
|
||||||
/// def show_info(
|
/// def show_info(
|
||||||
|
@ -278,7 +278,7 @@ def show_success(
|
|||||||
allow_cancel: bool = False,
|
allow_cancel: bool = False,
|
||||||
time_ms: int = 0,
|
time_ms: int = 0,
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
"""Success modal. No buttons shown when `button` is empty string."""
|
"""Success screen. Description is used in the footer."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
# rust/src/ui/model_mercury/layout.rs
|
||||||
|
@ -69,17 +69,20 @@ async def _share_words_confirmed(
|
|||||||
|
|
||||||
Return true if the words are confirmed successfully.
|
Return true if the words are confirmed successfully.
|
||||||
"""
|
"""
|
||||||
# TODO: confirm_action("Select the words bla bla")
|
from trezor.ui.layouts.reset import (
|
||||||
|
show_share_confirmation_success,
|
||||||
|
show_share_confirmation_failure,
|
||||||
|
)
|
||||||
|
|
||||||
if await _do_confirm_share_words(share_index, share_words, group_index):
|
if await _do_confirm_share_words(share_index, share_words, group_index):
|
||||||
await _show_confirmation_success(
|
await show_share_confirmation_success(
|
||||||
share_index,
|
share_index,
|
||||||
num_of_shares,
|
num_of_shares,
|
||||||
group_index,
|
group_index,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
await _show_confirmation_failure()
|
await show_share_confirmation_failure()
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -105,52 +108,6 @@ async def _do_confirm_share_words(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _show_confirmation_success(
|
|
||||||
share_index: int | None = None,
|
|
||||||
num_of_shares: int | None = None,
|
|
||||||
group_index: int | None = None,
|
|
||||||
) -> None:
|
|
||||||
if share_index is None or num_of_shares is None:
|
|
||||||
# it is a BIP39 or a 1-of-1 SLIP39 backup
|
|
||||||
subheader = TR.reset__finished_verifying_wallet_backup
|
|
||||||
text = ""
|
|
||||||
|
|
||||||
elif share_index == num_of_shares - 1:
|
|
||||||
if group_index is None:
|
|
||||||
subheader = TR.reset__finished_verifying_shares
|
|
||||||
else:
|
|
||||||
subheader = TR.reset__finished_verifying_group_template.format(
|
|
||||||
group_index + 1
|
|
||||||
)
|
|
||||||
text = ""
|
|
||||||
|
|
||||||
else:
|
|
||||||
if group_index is None:
|
|
||||||
subheader = TR.reset__share_checked_successfully_template.format(
|
|
||||||
share_index + 1
|
|
||||||
)
|
|
||||||
text = TR.reset__continue_with_share_template.format(share_index + 2)
|
|
||||||
else:
|
|
||||||
subheader = TR.reset__group_share_checked_successfully_template.format(
|
|
||||||
group_index + 1, share_index + 1
|
|
||||||
)
|
|
||||||
text = TR.reset__continue_with_next_share
|
|
||||||
|
|
||||||
return await show_success("success_recovery", text, subheader)
|
|
||||||
|
|
||||||
|
|
||||||
async def _show_confirmation_failure() -> None:
|
|
||||||
from trezor.ui.layouts.reset import show_reset_warning
|
|
||||||
|
|
||||||
await show_reset_warning(
|
|
||||||
"warning_backup_check",
|
|
||||||
TR.words__please_check_again,
|
|
||||||
TR.reset__wrong_word_selected,
|
|
||||||
TR.buttons__check_again,
|
|
||||||
ButtonRequestType.ResetDevice,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def show_backup_warning() -> None:
|
async def show_backup_warning() -> None:
|
||||||
from trezor.ui.layouts.reset import show_warning_backup
|
from trezor.ui.layouts.reset import show_warning_backup
|
||||||
|
|
||||||
|
@ -369,7 +369,11 @@ async def confirm_reset_device(_title: str, recovery: bool = False) -> None:
|
|||||||
async def prompt_backup() -> bool:
|
async def prompt_backup() -> bool:
|
||||||
# TODO: should we move this to `flow_prompt_backup`?
|
# TODO: should we move this to `flow_prompt_backup`?
|
||||||
await interact(
|
await interact(
|
||||||
RustLayout(trezorui2.show_success(title=TR.backup__new_wallet_created)),
|
RustLayout(
|
||||||
|
trezorui2.show_success(
|
||||||
|
title=TR.backup__new_wallet_created, description=None
|
||||||
|
)
|
||||||
|
),
|
||||||
"backup_device",
|
"backup_device",
|
||||||
ButtonRequestType.ResetDevice,
|
ButtonRequestType.ResetDevice,
|
||||||
)
|
)
|
||||||
@ -562,7 +566,7 @@ async def show_success(
|
|||||||
RustLayout(
|
RustLayout(
|
||||||
trezorui2.show_success(
|
trezorui2.show_success(
|
||||||
title=content,
|
title=content,
|
||||||
description="",
|
description=subheader,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
br_type,
|
br_type,
|
||||||
|
@ -123,7 +123,7 @@ async def continue_recovery(
|
|||||||
|
|
||||||
if show_info:
|
if show_info:
|
||||||
# Show this just one-time
|
# Show this just one-time
|
||||||
description = TR.recovery__only_first_n_letters
|
description = TR.recovery__enter_each_word
|
||||||
else:
|
else:
|
||||||
description = subtext or ""
|
description = subtext or ""
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from trezor.enums import ButtonRequestType
|
|||||||
from trezor.wire import ActionCancelled
|
from trezor.wire import ActionCancelled
|
||||||
|
|
||||||
from ..common import interact
|
from ..common import interact
|
||||||
from . import RustLayout, raise_if_not_confirmed
|
from . import RustLayout, raise_if_not_confirmed, show_success
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
pass
|
pass
|
||||||
@ -57,11 +57,11 @@ async def select_word(
|
|||||||
group_index: int | None = None,
|
group_index: int | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
if share_index is None:
|
if share_index is None:
|
||||||
description: str = TR.reset__check_wallet_backup_title
|
title: str = TR.reset__check_wallet_backup_title
|
||||||
elif group_index is None:
|
elif group_index is None:
|
||||||
description: str = TR.reset__check_share_title_template.format(share_index + 1)
|
title: str = TR.reset__check_share_title_template.format(share_index + 1)
|
||||||
else:
|
else:
|
||||||
description: str = TR.reset__check_group_share_title_template.format(
|
title: str = TR.reset__check_group_share_title_template.format(
|
||||||
group_index + 1, share_index + 1
|
group_index + 1, share_index + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,10 +74,10 @@ async def select_word(
|
|||||||
|
|
||||||
result = await RustLayout(
|
result = await RustLayout(
|
||||||
trezorui2.select_word(
|
trezorui2.select_word(
|
||||||
title=TR.reset__select_word_x_of_y_template.format(
|
title=title,
|
||||||
|
description=TR.reset__select_word_x_of_y_template.format(
|
||||||
checked_index + 1, count
|
checked_index + 1, count
|
||||||
),
|
),
|
||||||
description=description,
|
|
||||||
words=(words[0], words[1], words[2]),
|
words=(words[0], words[1], words[2]),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -316,12 +316,9 @@ async def show_warning_backup() -> None:
|
|||||||
|
|
||||||
|
|
||||||
async def show_success_backup() -> None:
|
async def show_success_backup() -> None:
|
||||||
from . import show_success
|
|
||||||
|
|
||||||
await show_success(
|
await show_success(
|
||||||
"success_backup",
|
"success_backup",
|
||||||
TR.reset__use_your_backup,
|
TR.backup__title_backup_completed,
|
||||||
TR.reset__your_backup_is_done,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -332,15 +329,14 @@ async def show_reset_warning(
|
|||||||
button: str | None = None,
|
button: str | None = None,
|
||||||
br_code: ButtonRequestType = ButtonRequestType.Warning,
|
br_code: ButtonRequestType = ButtonRequestType.Warning,
|
||||||
) -> None:
|
) -> None:
|
||||||
button = button or TR.buttons__try_again # def_arg
|
|
||||||
await raise_if_not_confirmed(
|
await raise_if_not_confirmed(
|
||||||
interact(
|
interact(
|
||||||
RustLayout(
|
RustLayout(
|
||||||
trezorui2.show_warning(
|
trezorui2.show_warning(
|
||||||
title=content or TR.words__warning,
|
title=subheader or "",
|
||||||
description="",
|
description=content,
|
||||||
value=subheader or "",
|
value="",
|
||||||
button=button,
|
button="",
|
||||||
allow_cancel=False,
|
allow_cancel=False,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -348,3 +344,49 @@ async def show_reset_warning(
|
|||||||
br_code,
|
br_code,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_share_confirmation_success(
|
||||||
|
share_index: int | None = None,
|
||||||
|
num_of_shares: int | None = None,
|
||||||
|
group_index: int | None = None,
|
||||||
|
) -> None:
|
||||||
|
if share_index is None or num_of_shares is None:
|
||||||
|
# it is a BIP39 or a 1-of-1 SLIP39 backup
|
||||||
|
# mercury UI shows only final wallet backup confirmation screen later
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO: super-shamir copy not done
|
||||||
|
if share_index == num_of_shares - 1:
|
||||||
|
title = TR.reset__share_completed_template.format(share_index + 1)
|
||||||
|
if group_index is None:
|
||||||
|
footer_description = ""
|
||||||
|
else:
|
||||||
|
footer_description = TR.reset__finished_verifying_group_template.format(
|
||||||
|
group_index + 1
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if group_index is None:
|
||||||
|
title = TR.reset__share_completed_template.format(share_index + 1)
|
||||||
|
footer_description = (
|
||||||
|
TR.instructions__shares_continue_with_x_template.format(share_index + 2)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
title = TR.reset__continue_with_next_share
|
||||||
|
footer_description = (
|
||||||
|
TR.reset__group_share_checked_successfully_template.format(
|
||||||
|
group_index + 1, share_index + 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return await show_success("success_recovery", title, subheader=footer_description)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_share_confirmation_failure() -> None:
|
||||||
|
await show_reset_warning(
|
||||||
|
"warning_backup_check",
|
||||||
|
TR.words__try_again,
|
||||||
|
TR.reset__incorrect_word_selected,
|
||||||
|
"",
|
||||||
|
ButtonRequestType.ResetDevice,
|
||||||
|
)
|
||||||
|
@ -6,7 +6,7 @@ from trezor.enums import ButtonRequestType
|
|||||||
from trezor.wire import ActionCancelled
|
from trezor.wire import ActionCancelled
|
||||||
|
|
||||||
from ..common import interact
|
from ..common import interact
|
||||||
from . import RustLayout, confirm_action, show_warning
|
from . import RustLayout, confirm_action, show_warning, show_success
|
||||||
|
|
||||||
CONFIRMED = trezorui2.CONFIRMED # global_import_cache
|
CONFIRMED = trezorui2.CONFIRMED # global_import_cache
|
||||||
|
|
||||||
@ -291,3 +291,47 @@ async def show_reset_warning(
|
|||||||
button,
|
button,
|
||||||
br_code=br_code,
|
br_code=br_code,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_share_confirmation_success(
|
||||||
|
share_index: int | None = None,
|
||||||
|
num_of_shares: int | None = None,
|
||||||
|
group_index: int | None = None,
|
||||||
|
) -> None:
|
||||||
|
if share_index is None or num_of_shares is None:
|
||||||
|
# it is a BIP39 or a 1-of-1 SLIP39 backup
|
||||||
|
subheader = TR.reset__finished_verifying_wallet_backup
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
elif share_index == num_of_shares - 1:
|
||||||
|
if group_index is None:
|
||||||
|
subheader = TR.reset__finished_verifying_shares
|
||||||
|
else:
|
||||||
|
subheader = TR.reset__finished_verifying_group_template.format(
|
||||||
|
group_index + 1
|
||||||
|
)
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
else:
|
||||||
|
if group_index is None:
|
||||||
|
subheader = TR.reset__share_checked_successfully_template.format(
|
||||||
|
share_index + 1
|
||||||
|
)
|
||||||
|
text = TR.reset__continue_with_share_template.format(share_index + 2)
|
||||||
|
else:
|
||||||
|
subheader = TR.reset__group_share_checked_successfully_template.format(
|
||||||
|
group_index + 1, share_index + 1
|
||||||
|
)
|
||||||
|
text = TR.reset__continue_with_next_share
|
||||||
|
|
||||||
|
return await show_success("success_recovery", text, subheader)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_share_confirmation_failure() -> None:
|
||||||
|
await show_reset_warning(
|
||||||
|
"warning_backup_check",
|
||||||
|
TR.words__please_check_again,
|
||||||
|
TR.reset__wrong_word_selected,
|
||||||
|
TR.buttons__check_again,
|
||||||
|
ButtonRequestType.ResetDevice,
|
||||||
|
)
|
||||||
|
@ -6,7 +6,7 @@ from trezor.enums import ButtonRequestType
|
|||||||
from trezor.wire import ActionCancelled
|
from trezor.wire import ActionCancelled
|
||||||
|
|
||||||
from ..common import interact
|
from ..common import interact
|
||||||
from . import RustLayout, raise_if_not_confirmed
|
from . import RustLayout, raise_if_not_confirmed, show_success
|
||||||
|
|
||||||
CONFIRMED = trezorui2.CONFIRMED # global_import_cache
|
CONFIRMED = trezorui2.CONFIRMED # global_import_cache
|
||||||
|
|
||||||
@ -326,8 +326,6 @@ async def show_warning_backup() -> None:
|
|||||||
|
|
||||||
|
|
||||||
async def show_success_backup() -> None:
|
async def show_success_backup() -> None:
|
||||||
from . import show_success
|
|
||||||
|
|
||||||
await show_success(
|
await show_success(
|
||||||
"success_backup",
|
"success_backup",
|
||||||
TR.reset__use_your_backup,
|
TR.reset__use_your_backup,
|
||||||
@ -357,3 +355,47 @@ async def show_reset_warning(
|
|||||||
br_code,
|
br_code,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_share_confirmation_success(
|
||||||
|
share_index: int | None = None,
|
||||||
|
num_of_shares: int | None = None,
|
||||||
|
group_index: int | None = None,
|
||||||
|
) -> None:
|
||||||
|
if share_index is None or num_of_shares is None:
|
||||||
|
# it is a BIP39 or a 1-of-1 SLIP39 backup
|
||||||
|
subheader = TR.reset__finished_verifying_wallet_backup
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
elif share_index == num_of_shares - 1:
|
||||||
|
if group_index is None:
|
||||||
|
subheader = TR.reset__finished_verifying_shares
|
||||||
|
else:
|
||||||
|
subheader = TR.reset__finished_verifying_group_template.format(
|
||||||
|
group_index + 1
|
||||||
|
)
|
||||||
|
text = ""
|
||||||
|
|
||||||
|
else:
|
||||||
|
if group_index is None:
|
||||||
|
subheader = TR.reset__share_checked_successfully_template.format(
|
||||||
|
share_index + 1
|
||||||
|
)
|
||||||
|
text = TR.reset__continue_with_share_template.format(share_index + 2)
|
||||||
|
else:
|
||||||
|
subheader = TR.reset__group_share_checked_successfully_template.format(
|
||||||
|
group_index + 1, share_index + 1
|
||||||
|
)
|
||||||
|
text = TR.reset__continue_with_next_share
|
||||||
|
|
||||||
|
return await show_success("success_recovery", text, subheader)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_share_confirmation_failure() -> None:
|
||||||
|
await show_reset_warning(
|
||||||
|
"warning_backup_check",
|
||||||
|
TR.words__please_check_again,
|
||||||
|
TR.reset__wrong_word_selected,
|
||||||
|
TR.buttons__check_again,
|
||||||
|
ButtonRequestType.ResetDevice,
|
||||||
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"current": {
|
"current": {
|
||||||
"merkle_root": "57561824d2bed19054d5570b0181b5907c7ae5546e4d6c2e589a727898a69237",
|
"merkle_root": "7a115e582a5f5f09b1850946030762360f55e516a60cf960dffc9ba174c2e4d2",
|
||||||
"datetime": "2024-05-31T09:09:13.124759",
|
"datetime": "2024-06-02T11:07:12.183601",
|
||||||
"commit": "6000eaf8280116d0cc947aa8d2aceb568dca56f8"
|
"commit": "66496206ccbe9583203fbfebf8c9222e8c6379b8"
|
||||||
},
|
},
|
||||||
"history": [
|
"history": [
|
||||||
{
|
{
|
||||||
|
@ -171,27 +171,32 @@ class LayoutContent(UnstructuredJSONReader):
|
|||||||
|
|
||||||
return visible
|
return visible
|
||||||
|
|
||||||
|
def _get_str_or_dict_text(self, key: str) -> str:
|
||||||
|
value = self.find_unique_value_by_key(key, "")
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return value["text"]
|
||||||
|
return value
|
||||||
|
|
||||||
def title(self) -> str:
|
def title(self) -> str:
|
||||||
"""Getting text that is displayed as a title."""
|
"""Getting text that is displayed as a title and potentially subtitle."""
|
||||||
# There could be possibly subtitle as well
|
# There could be possibly subtitle as well
|
||||||
title_parts: List[str] = []
|
title_parts: List[str] = []
|
||||||
|
|
||||||
def _get_str_or_dict_text(key: str) -> str:
|
title = self._get_str_or_dict_text("title")
|
||||||
value = self.find_unique_value_by_key(key, "")
|
|
||||||
if isinstance(value, dict):
|
|
||||||
return value["text"]
|
|
||||||
return value
|
|
||||||
|
|
||||||
title = _get_str_or_dict_text("title")
|
|
||||||
if title:
|
if title:
|
||||||
title_parts.append(title)
|
title_parts.append(title)
|
||||||
|
|
||||||
subtitle = _get_str_or_dict_text("subtitle")
|
subtitle = self.subtitle()
|
||||||
if subtitle:
|
if subtitle:
|
||||||
title_parts.append(subtitle)
|
title_parts.append(subtitle)
|
||||||
|
|
||||||
return "\n".join(title_parts)
|
return "\n".join(title_parts)
|
||||||
|
|
||||||
|
def subtitle(self) -> str:
|
||||||
|
"""Getting text that is displayed as a subtitle."""
|
||||||
|
subtitle = self._get_str_or_dict_text("subtitle")
|
||||||
|
return subtitle
|
||||||
|
|
||||||
def text_content(self) -> str:
|
def text_content(self) -> str:
|
||||||
"""What is on the screen, in one long string, so content can be
|
"""What is on the screen, in one long string, so content can be
|
||||||
asserted regardless of newlines. Also getting rid of possible ellipsis.
|
asserted regardless of newlines. Also getting rid of possible ellipsis.
|
||||||
|
@ -277,13 +277,21 @@ def check_share(
|
|||||||
Given the mnemonic word list, proceed with the backup check:
|
Given the mnemonic word list, proceed with the backup check:
|
||||||
three rounds of `Select word X of Y` choices.
|
three rounds of `Select word X of Y` choices.
|
||||||
"""
|
"""
|
||||||
|
re_num_of_word = r"\d+"
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
if debug.model is models.T2B1:
|
if debug.model is models.T2T1:
|
||||||
# T2B1 has the instruction in the title
|
# T2T1 has position as the first number in the text
|
||||||
word_pos_match = re.search(r"\d+", debug.wait_layout().title())
|
word_pos_match = re.search(
|
||||||
|
re_num_of_word, debug.wait_layout().text_content()
|
||||||
|
)
|
||||||
|
elif debug.model is models.T2B1:
|
||||||
|
# other models have the instruction in the title/subtitle
|
||||||
|
word_pos_match = re.search(re_num_of_word, debug.wait_layout().title())
|
||||||
|
elif debug.model is models.T3T1:
|
||||||
|
word_pos_match = re.search(re_num_of_word, debug.wait_layout().subtitle())
|
||||||
else:
|
else:
|
||||||
# Other models has position as the first number in the text
|
word_pos_match = None
|
||||||
word_pos_match = re.search(r"\d+", debug.wait_layout().text_content())
|
|
||||||
assert word_pos_match is not None
|
assert word_pos_match is not None
|
||||||
word_pos = int(word_pos_match.group(0))
|
word_pos = int(word_pos_match.group(0))
|
||||||
|
|
||||||
|
@ -1255,9 +1255,11 @@ def get_mnemonic_and_confirm_success(
|
|||||||
# mnemonic phrases
|
# mnemonic phrases
|
||||||
mnemonic = yield from read_and_confirm_mnemonic(debug)
|
mnemonic = yield from read_and_confirm_mnemonic(debug)
|
||||||
|
|
||||||
br = yield # confirm recovery seed check
|
is_slip39 = len(mnemonic.split()) in (20, 33)
|
||||||
assert br.code == B.Success
|
if debug.model in (models.T2T1, models.T2B1) or is_slip39:
|
||||||
debug.press_yes()
|
br = yield # confirm recovery share check
|
||||||
|
assert br.code == B.Success
|
||||||
|
debug.press_yes()
|
||||||
|
|
||||||
br = yield # confirm success
|
br = yield # confirm success
|
||||||
assert br.code == B.Success
|
assert br.code == B.Success
|
||||||
|
@ -93,7 +93,7 @@ class RecoveryFlow:
|
|||||||
def enter_your_backup(self) -> BRGeneratorType:
|
def enter_your_backup(self) -> BRGeneratorType:
|
||||||
yield
|
yield
|
||||||
if self.debug.model is models.T3T1:
|
if self.debug.model is models.T3T1:
|
||||||
TR.assert_in(self._text_content(), "recovery__only_first_n_letters")
|
TR.assert_in(self._text_content(), "recovery__enter_each_word")
|
||||||
else:
|
else:
|
||||||
TR.assert_in(self._text_content(), "recovery__enter_backup")
|
TR.assert_in(self._text_content(), "recovery__enter_backup")
|
||||||
is_dry_run = any(
|
is_dry_run = any(
|
||||||
@ -110,7 +110,7 @@ class RecoveryFlow:
|
|||||||
yield
|
yield
|
||||||
TR.assert_in_multiple(
|
TR.assert_in_multiple(
|
||||||
self._text_content(),
|
self._text_content(),
|
||||||
["recovery__enter_any_share", "recovery__only_first_n_letters"],
|
["recovery__enter_any_share", "recovery__enter_each_word"],
|
||||||
)
|
)
|
||||||
is_dry_run = any(
|
is_dry_run = any(
|
||||||
title in self.debug.wait_layout().title().lower()
|
title in self.debug.wait_layout().title().lower()
|
||||||
@ -127,7 +127,7 @@ class RecoveryFlow:
|
|||||||
if self.client.model is models.T2B1:
|
if self.client.model is models.T2B1:
|
||||||
TR.assert_in(self._text_content(), "recovery__num_of_words")
|
TR.assert_in(self._text_content(), "recovery__num_of_words")
|
||||||
elif self.client.model is models.T3T1:
|
elif self.client.model is models.T3T1:
|
||||||
TR.assert_in(self._text_content(), "recovery__only_first_n_letters")
|
TR.assert_in(self._text_content(), "recovery__enter_each_word")
|
||||||
else:
|
else:
|
||||||
TR.assert_in(self._text_content(), "recovery__enter_any_share")
|
TR.assert_in(self._text_content(), "recovery__enter_any_share")
|
||||||
self.debug.press_no()
|
self.debug.press_no()
|
||||||
|
Loading…
Reference in New Issue
Block a user