1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-24 07:18:09 +00:00

feat(core/ui): improve T3T1 recovery

This commit is contained in:
obrusvit 2024-04-25 23:41:16 +02:00 committed by Martin Milata
parent 6486b03248
commit 4471281adc
7 changed files with 76 additions and 71 deletions

View File

@ -153,6 +153,7 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_backup_written_down; MP_QSTR_confirm_backup_written_down;
MP_QSTR_confirm_blob; MP_QSTR_confirm_blob;
MP_QSTR_confirm_coinjoin; MP_QSTR_confirm_coinjoin;
MP_QSTR_confirm_create_wallet;
MP_QSTR_confirm_emphasized; MP_QSTR_confirm_emphasized;
MP_QSTR_confirm_fido; MP_QSTR_confirm_fido;
MP_QSTR_confirm_firmware_update; MP_QSTR_confirm_firmware_update;

View File

@ -21,7 +21,6 @@ use super::super::{
pub enum ConfirmResetDevice { pub enum ConfirmResetDevice {
Intro, Intro,
Menu, Menu,
Confirm,
} }
impl FlowState for ConfirmResetDevice { impl FlowState for ConfirmResetDevice {
@ -33,12 +32,7 @@ impl FlowState for ConfirmResetDevice {
(ConfirmResetDevice::Menu, SwipeDirection::Right) => { (ConfirmResetDevice::Menu, SwipeDirection::Right) => {
Decision::Goto(ConfirmResetDevice::Intro, direction) Decision::Goto(ConfirmResetDevice::Intro, direction)
} }
(ConfirmResetDevice::Intro, SwipeDirection::Up) => { (ConfirmResetDevice::Intro, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed),
Decision::Goto(ConfirmResetDevice::Confirm, direction)
}
(ConfirmResetDevice::Confirm, SwipeDirection::Down) => {
Decision::Goto(ConfirmResetDevice::Intro, direction)
}
_ => Decision::Nothing, _ => Decision::Nothing,
} }
} }
@ -52,9 +46,6 @@ impl FlowState for ConfirmResetDevice {
Decision::Goto(ConfirmResetDevice::Intro, SwipeDirection::Right) Decision::Goto(ConfirmResetDevice::Intro, SwipeDirection::Right)
} }
(ConfirmResetDevice::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled), (ConfirmResetDevice::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled),
(ConfirmResetDevice::Confirm, FlowMsg::Confirmed) => {
Decision::Return(FlowMsg::Confirmed)
}
_ => Decision::Nothing, _ => Decision::Nothing,
} }
} }

View File

@ -192,6 +192,15 @@ impl ComponentMsgObj for ShareWords<'_> {
} }
} }
impl ComponentMsgObj for SelectWordCount {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
SelectWordCountMsg::Selected(n) => n.try_into(),
_ => Err(Error::TypeError),
}
}
}
impl ComponentMsgObj for VerticalMenu { impl ComponentMsgObj for VerticalMenu {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg { 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) } 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 { extern "C" fn new_confirm_value(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()?;
@ -1314,8 +1335,9 @@ extern "C" fn new_confirm_backup_written_down(
args: *const Obj, args: *const Obj,
kwargs: *mut Map, kwargs: *mut Map,
) -> Obj { ) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| { let block = move |_args: &[Obj], _kwargs: &Map| {
let content = PromptScreen::new_hold_to_confirm(); let content = PromptScreen::new_hold_to_confirm();
// TODO: use TR
let frame_with_hold_to_confirm = let frame_with_hold_to_confirm =
Frame::left_aligned("I wrote down all words in order.".into(), content) Frame::left_aligned("I wrote down all words in order.".into(), content)
.with_footer(TR::instructions__hold_to_confirm.into(), None); .with_footer(TR::instructions__hold_to_confirm.into(), None);
@ -1396,17 +1418,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 { extern "C" fn new_confirm_recovery(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: TString = kwargs.get(Qstr::MP_QSTR_description)?.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 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([ let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]);
Paragraph::new(&theme::TEXT_DEMIBOLD, title),
Paragraph::new(&theme::TEXT_NORMAL, description),
])
.with_spacing(theme::RECOVERY_SPACING);
let notification: TString = if dry_run { let notification: TString = if dry_run {
TR::recovery__title_dry_run.try_into()? TR::recovery__title_dry_run.try_into()?
@ -1414,23 +1432,12 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
TR::recovery__title.try_into()? TR::recovery__title.try_into()?
}; };
let obj = if info_button { let content = SwipeUpScreen::new(paragraphs);
LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(
notification, Frame::left_aligned(notification, content)
Dialog::new( .with_footer(TR::instructions__swipe_up.into(), None)
paragraphs, .with_subtitle("Instructions".into()), // FIXME: use TR
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))),
))?
};
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1438,21 +1445,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 { 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 block = move |_args: &[Obj], kwargs: &Map| {
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; 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 obj = LayoutObj::new(Frame::left_aligned( let obj = LayoutObj::new(Frame::left_aligned(
title, TR::recovery__select_num_of_words.into(),
Dialog::new(paragraphs, SelectWordCount::new()), SelectWordCount::new(),
))?; ))?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -1808,6 +1805,10 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Confirm TOS before device setup.""" /// """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(), 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( /// def show_address_details(
/// *, /// *,
/// qr_title: str, /// qr_title: str,

View File

@ -154,6 +154,11 @@ def confirm_reset_device(
"""Confirm TOS before device setup.""" """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 # rust/src/ui/model_mercury/layout.rs
def show_address_details( def show_address_details(
*, *,

View File

@ -228,11 +228,12 @@ def draw_simple(layout: Any) -> None:
ui.backlight_fade(ui.style.BACKLIGHT_NORMAL) 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 result = await a
if result is not CONFIRMED: if result is not CONFIRMED:
raise exc raise exc
return result
async def confirm_action( async def confirm_action(
@ -322,22 +323,36 @@ async def confirm_single(
async def confirm_reset_device(title: str, recovery: bool = False) -> None: async def confirm_reset_device(title: str, recovery: bool = False) -> None:
await raise_if_not_confirmed( if recovery:
interact( 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( RustLayout(
trezorui2.confirm_reset_device( trezorui2.confirm_reset_device(
title=title, title=title,
button="", # not used 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: async def prompt_backup() -> bool:
@ -565,15 +580,12 @@ async def show_success(
subheader: str | None = None, subheader: str | None = None,
button: str | None = None, button: str | None = None,
) -> None: ) -> None:
button = button or TR.buttons__continue # def_arg
await raise_if_not_confirmed( await raise_if_not_confirmed(
interact( interact(
RustLayout( RustLayout(
trezorui2.show_success( trezorui2.show_success(
title=subheader or "", title=content,
description="", description="",
button=button.upper(),
allow_cancel=False,
) )
), ),
br_type, br_type,

View File

@ -160,9 +160,7 @@ async def show_recovery_warning(
RustLayout( RustLayout(
trezorui2.show_warning( trezorui2.show_warning(
title=content, title=content,
description=subheader or "", value="Try again", # TODO: use TR
button=button.upper(),
allow_cancel=False,
) )
), ),
br_type, br_type,

View File

@ -41,10 +41,7 @@ async def show_share_words(
result = await interact( result = await interact(
RustLayout( RustLayout(
trezorui2.confirm_backup_written_down( trezorui2.confirm_backup_written_down(),
title=title,
pages=share_words,
),
), ),
"backup_words", "backup_words",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,