From 3628630584099233d807fc8762584d40d62dafa7 Mon Sep 17 00:00:00 2001 From: obrusvit Date: Thu, 25 Apr 2024 23:41:16 +0200 Subject: [PATCH] feat(core/ui): improve T3T1 recovery --- core/embed/rust/librust_qstr.h | 1 + .../flow/confirm_reset_device.rs | 11 +-- .../embed/rust/src/ui/model_mercury/layout.rs | 79 ++++++++++--------- core/mocks/generated/trezorui2.pyi | 5 ++ .../src/trezor/ui/layouts/mercury/__init__.py | 42 ++++++---- .../src/trezor/ui/layouts/mercury/recovery.py | 4 +- core/src/trezor/ui/layouts/mercury/reset.py | 5 +- 7 files changed, 76 insertions(+), 71 deletions(-) diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index f8d306fb9..5eb4d0d5b 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -152,6 +152,7 @@ static void _librust_qstrs(void) { MP_QSTR_confirm_backup_written_down; MP_QSTR_confirm_blob; MP_QSTR_confirm_coinjoin; + MP_QSTR_confirm_create_wallet; MP_QSTR_confirm_emphasized; MP_QSTR_confirm_fido; MP_QSTR_confirm_firmware_update; diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs index 66381204e..c03a868fc 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs @@ -22,7 +22,6 @@ use super::super::{ pub enum ConfirmResetDevice { Intro, Menu, - Confirm, } impl FlowState for ConfirmResetDevice { @@ -34,12 +33,7 @@ impl FlowState for ConfirmResetDevice { (ConfirmResetDevice::Menu, SwipeDirection::Right) => { Decision::Goto(ConfirmResetDevice::Intro, direction) } - (ConfirmResetDevice::Intro, SwipeDirection::Up) => { - Decision::Goto(ConfirmResetDevice::Confirm, direction) - } - (ConfirmResetDevice::Confirm, SwipeDirection::Down) => { - Decision::Goto(ConfirmResetDevice::Intro, direction) - } + (ConfirmResetDevice::Intro, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed), _ => Decision::Nothing, } } @@ -53,9 +47,6 @@ impl FlowState for ConfirmResetDevice { Decision::Goto(ConfirmResetDevice::Intro, SwipeDirection::Right) } (ConfirmResetDevice::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled), - (ConfirmResetDevice::Confirm, FlowMsg::Confirmed) => { - Decision::Return(FlowMsg::Confirmed) - } _ => Decision::Nothing, } } diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index 145798bbc..2e3e8b785 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -192,6 +192,15 @@ impl ComponentMsgObj for ShareWords<'_> { } } +impl ComponentMsgObj for SelectWordCount { + fn msg_try_into_obj(&self, msg: Self::Msg) -> Result { + match msg { + SelectWordCountMsg::Selected(n) => n.try_into(), + _ => Err(Error::TypeError), + } + } +} + impl ComponentMsgObj for VerticalMenu { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result { match msg { @@ -758,6 +767,18 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs: unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_confirm_create_wallet(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], _kwargs: &Map| { + let content = PromptScreen::new_hold_to_confirm(); + let obj = LayoutObj::new( + Frame::left_aligned(TR::reset__title_create_wallet.into(), content) + .with_footer(TR::instructions__hold_to_confirm.into(), None), + )?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_confirm_value(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()?; @@ -1331,8 +1352,9 @@ extern "C" fn new_confirm_backup_written_down( args: *const Obj, kwargs: *mut Map, ) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { + let block = move |_args: &[Obj], _kwargs: &Map| { let content = PromptScreen::new_hold_to_confirm(); + // TODO: use TR let frame_with_hold_to_confirm = Frame::left_aligned("I wrote down all words in order.".into(), content) .with_footer(TR::instructions__hold_to_confirm.into(), None); @@ -1413,17 +1435,13 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M 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 _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 _button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; - let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; + 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 paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]); let notification: TString = if dry_run { TR::recovery__title_dry_run.try_into()? @@ -1431,23 +1449,12 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut TR::recovery__title.try_into()? }; - let obj = if info_button { - LayoutObj::new(Frame::left_aligned( - notification, - Dialog::new( - paragraphs, - Button::cancel_info_confirm( - TR::buttons__continue.into(), - TR::buttons__more_info.into(), - ), - ), - ))? - } else { - LayoutObj::new(Frame::left_aligned( - notification, - Dialog::new(paragraphs, Button::cancel_confirm_text(None, Some(button))), - ))? - }; + let content = SwipeUpScreen::new(paragraphs); + let obj = LayoutObj::new( + Frame::left_aligned(notification, content) + .with_footer(TR::instructions__swipe_up.into(), None) + .with_subtitle("Instructions".into()), // FIXME: use TR + )?; Ok(obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } @@ -1455,21 +1462,11 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { - let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; - let title: TString = if dry_run { - TR::recovery__title_dry_run.try_into()? - } else { - TR::recovery__title.try_into()? - }; - - let paragraphs = Paragraphs::new(Paragraph::new( - &theme::TEXT_DEMIBOLD, - TR::recovery__select_num_of_words, - )); + let _dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; let obj = LayoutObj::new(Frame::left_aligned( - title, - Dialog::new(paragraphs, SelectWordCount::new()), + TR::recovery__select_num_of_words.into(), + SelectWordCount::new(), ))?; Ok(obj.into()) }; @@ -1825,6 +1822,10 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Confirm TOS before device setup.""" Qstr::MP_QSTR_confirm_reset_device => obj_fn_kw!(0, flow::confirm_reset_device::new_confirm_reset_device).as_obj(), + /// def confirm_create_wallet() -> LayoutObj[UiResult]: + /// """Confirm creating wallet""" + Qstr::MP_QSTR_confirm_create_wallet => obj_fn_kw!(0, new_confirm_create_wallet).as_obj(), + /// def show_address_details( /// *, /// qr_title: str, diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index d03a58cdc..6e16c11c9 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -154,6 +154,11 @@ def confirm_reset_device( """Confirm TOS before device setup.""" +# rust/src/ui/model_mercury/layout.rs +def confirm_create_wallet() -> LayoutObj[UiResult]: + """Confirm creating wallet""" + + # rust/src/ui/model_mercury/layout.rs def show_address_details( *, diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py index af012cfef..d33eda0cf 100644 --- a/core/src/trezor/ui/layouts/mercury/__init__.py +++ b/core/src/trezor/ui/layouts/mercury/__init__.py @@ -228,11 +228,12 @@ def draw_simple(layout: Any) -> None: ui.backlight_fade(ui.style.BACKLIGHT_NORMAL) -async def raise_if_not_confirmed(a: Awaitable[T], exc: Any = ActionCancelled) -> T: +async def raise_if_not_confirmed( + a: Awaitable[ui.UiResult], exc: Any = ActionCancelled +) -> None: result = await a if result is not CONFIRMED: raise exc - return result async def confirm_action( @@ -322,22 +323,36 @@ async def confirm_single( async def confirm_reset_device(title: str, recovery: bool = False) -> None: - await raise_if_not_confirmed( - interact( + if recovery: + await raise_if_not_confirmed( + interact( + RustLayout( + trezorui2.confirm_reset_device( + title=title, + button="", # not used + ) + ), + "recover_device", + ButtonRequestType.ProtectCall, + ) + ) + else: + # creating wallet shows TOS first and then an extra screen confirms + await raise_if_not_confirmed( RustLayout( trezorui2.confirm_reset_device( title=title, button="", # not used ) ), - "recover_device" if recovery else "setup_device", - ( - ButtonRequestType.ProtectCall - if recovery - else ButtonRequestType.ResetDevice - ), ) - ) + await raise_if_not_confirmed( + interact( + RustLayout(trezorui2.confirm_create_wallet()), + "setup_device", + ButtonRequestType.ResetDevice, + ) + ) async def prompt_backup() -> bool: @@ -565,15 +580,12 @@ async def show_success( subheader: str | None = None, button: str | None = None, ) -> None: - button = button or TR.buttons__continue # def_arg await raise_if_not_confirmed( interact( RustLayout( trezorui2.show_success( - title=subheader or "", + title=content, description="", - button=button.upper(), - allow_cancel=False, ) ), br_type, diff --git a/core/src/trezor/ui/layouts/mercury/recovery.py b/core/src/trezor/ui/layouts/mercury/recovery.py index 10c8f3aa5..410434d10 100644 --- a/core/src/trezor/ui/layouts/mercury/recovery.py +++ b/core/src/trezor/ui/layouts/mercury/recovery.py @@ -160,9 +160,7 @@ async def show_recovery_warning( RustLayout( trezorui2.show_warning( title=content, - description=subheader or "", - button=button.upper(), - allow_cancel=False, + value="Try again", # TODO: use TR ) ), br_type, diff --git a/core/src/trezor/ui/layouts/mercury/reset.py b/core/src/trezor/ui/layouts/mercury/reset.py index 337ab74d4..a6025edc2 100644 --- a/core/src/trezor/ui/layouts/mercury/reset.py +++ b/core/src/trezor/ui/layouts/mercury/reset.py @@ -41,10 +41,7 @@ async def show_share_words( result = await interact( RustLayout( - trezorui2.confirm_backup_written_down( - title=title, - pages=share_words, - ), + trezorui2.confirm_backup_written_down(), ), "backup_words", ButtonRequestType.ResetDevice,