1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-18 13:38:12 +00:00

feat(core/ui): T3T1 confirm backup flow

This commit is contained in:
obrusvit 2024-04-21 22:43:12 +02:00 committed by Martin Milata
parent 7905770e7e
commit 0615b1bbc2
12 changed files with 142 additions and 59 deletions

View File

@ -150,6 +150,7 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_action; MP_QSTR_confirm_action;
MP_QSTR_confirm_address; MP_QSTR_confirm_address;
MP_QSTR_confirm_backup; MP_QSTR_confirm_backup;
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_emphasized; MP_QSTR_confirm_emphasized;
@ -173,6 +174,7 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_value; MP_QSTR_confirm_value;
MP_QSTR_confirm_with_info; MP_QSTR_confirm_with_info;
MP_QSTR_count; MP_QSTR_count;
MP_QSTR_create_backup_flow;
MP_QSTR_data; MP_QSTR_data;
MP_QSTR_data_hash; MP_QSTR_data_hash;
MP_QSTR_data_len; MP_QSTR_data_len;
@ -232,6 +234,9 @@ static void _librust_qstrs(void) {
MP_QSTR_inputs__return; MP_QSTR_inputs__return;
MP_QSTR_inputs__show; MP_QSTR_inputs__show;
MP_QSTR_inputs__space; MP_QSTR_inputs__space;
MP_QSTR_instructions__hold_to_confirm;
MP_QSTR_instructions__swipe_up;
MP_QSTR_instructions__tap_to_confirm;
MP_QSTR_is_type_of; MP_QSTR_is_type_of;
MP_QSTR_items; MP_QSTR_items;
MP_QSTR_joint__title; MP_QSTR_joint__title;
@ -620,6 +625,7 @@ static void _librust_qstrs(void) {
MP_QSTR_words__error; MP_QSTR_words__error;
MP_QSTR_words__fee; MP_QSTR_words__fee;
MP_QSTR_words__from; MP_QSTR_words__from;
MP_QSTR_words__important;
MP_QSTR_words__keep_it_safe; MP_QSTR_words__keep_it_safe;
MP_QSTR_words__know_what_your_doing; MP_QSTR_words__know_what_your_doing;
MP_QSTR_words__my_trezor; MP_QSTR_words__my_trezor;

View File

@ -1254,6 +1254,7 @@ pub enum TranslatedString {
instructions__swipe_up = 853, // "Swipe up" instructions__swipe_up = 853, // "Swipe up"
instructions__tap_to_confirm = 854, // "Tap to confirm" instructions__tap_to_confirm = 854, // "Tap to confirm"
instructions__hold_to_confirm = 855, // "Hold to confirm" instructions__hold_to_confirm = 855, // "Hold to confirm"
words__important = 856, // "Important"
} }
impl TranslatedString { impl TranslatedString {
@ -2503,6 +2504,7 @@ impl TranslatedString {
Self::instructions__swipe_up => "Swipe up", Self::instructions__swipe_up => "Swipe up",
Self::instructions__tap_to_confirm => "Tap to confirm", Self::instructions__tap_to_confirm => "Tap to confirm",
Self::instructions__hold_to_confirm => "Hold to confirm", Self::instructions__hold_to_confirm => "Hold to confirm",
Self::words__important => "Important",
} }
} }
@ -3753,6 +3755,7 @@ impl TranslatedString {
Qstr::MP_QSTR_instructions__swipe_up => Some(Self::instructions__swipe_up), Qstr::MP_QSTR_instructions__swipe_up => Some(Self::instructions__swipe_up),
Qstr::MP_QSTR_instructions__tap_to_confirm => Some(Self::instructions__tap_to_confirm), Qstr::MP_QSTR_instructions__tap_to_confirm => Some(Self::instructions__tap_to_confirm),
Qstr::MP_QSTR_instructions__hold_to_confirm => Some(Self::instructions__hold_to_confirm), Qstr::MP_QSTR_instructions__hold_to_confirm => Some(Self::instructions__hold_to_confirm),
Qstr::MP_QSTR_words__important => Some(Self::words__important),
_ => None, _ => None,
} }
} }

View File

@ -1,5 +1,7 @@
pub mod get_address; pub mod get_address;
pub mod confirm_reset_device; pub mod confirm_reset_device;
pub mod create_backup;
pub use get_address::GetAddress; pub use get_address::GetAddress;
pub use confirm_reset_device::ConfirmResetDevice; pub use confirm_reset_device::ConfirmResetDevice;
pub use create_backup::CreateBackup;

View File

@ -1018,42 +1018,50 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_warning(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 icon = BlendedImage::new( let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
theme::IMAGE_BG_OCTAGON, let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
theme::IMAGE_FG_WARN,
theme::WARN_COLOR, let content = SwipeUpScreen::new(Paragraphs::new([Paragraph::new(
theme::FG, &theme::TEXT_MAIN_GREY_LIGHT,
theme::BG, value,
); )]));
new_show_modal(kwargs, icon, theme::button_reset()) let obj = LayoutObj::new(
Frame::left_aligned(title, content)
.with_warning_button()
.button_styled(theme::button_warning_low())
.with_footer(TR::instructions__swipe_up.into(), None),
)?;
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) }
} }
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 icon = BlendedImage::new( let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
theme::IMAGE_BG_CIRCLE, let content = StatusScreen::new_success();
theme::IMAGE_FG_SUCCESS, let obj = LayoutObj::new(
theme::SUCCESS_COLOR, Frame::left_aligned(title, content)
theme::FG, .with_footer(TR::instructions__swipe_up.into(), None),
theme::BG, )?;
); Ok(obj.into())
new_show_modal(kwargs, icon, theme::button_confirm())
}; };
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_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { extern "C" fn new_show_info(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 icon = BlendedImage::new( let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
theme::IMAGE_BG_CIRCLE, let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
theme::IMAGE_FG_INFO, let content = SwipeUpScreen::new(Paragraphs::new([Paragraph::new(
theme::INFO_COLOR, &theme::TEXT_MAIN_GREY_LIGHT,
theme::FG, description,
theme::BG, )]));
); let obj = LayoutObj::new(
new_show_modal(kwargs, icon, theme::button_info()) Frame::left_aligned(title, content)
.with_footer(TR::instructions__swipe_up.into(), None),
)?;
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) }
} }
@ -1330,7 +1338,7 @@ 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();
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)
@ -2044,6 +2052,11 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// information, 3) Cancel transaction""" /// information, 3) Cancel transaction"""
Qstr::MP_QSTR_show_tx_context_menu => obj_fn_kw!(0, new_show_tx_context_menu).as_obj(), Qstr::MP_QSTR_show_tx_context_menu => obj_fn_kw!(0, new_show_tx_context_menu).as_obj(),
// TODO: This is just POC
/// def create_backup_flow() -> LayoutObj[UiResult]
/// """Start create backup or skip flow."""
Qstr::MP_QSTR_create_backup_flow => obj_fn_kw!(0, flow::create_backup::new_create_backup).as_obj(),
/// def show_share_words( /// def show_share_words(
/// *, /// *,
/// title: str, /// title: str,
@ -2052,6 +2065,11 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Show mnemonic for backup.""" /// """Show mnemonic for backup."""
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(),
// TODO: This is just POC
/// def confirm_backup_written_down() -> LayoutObj[UiResult]
/// """Confirm with the user that backup words are written down."""
Qstr::MP_QSTR_confirm_backup_written_down => obj_fn_kw!(0, new_confirm_backup_written_down).as_obj(),
/// def request_number( /// def request_number(
/// *, /// *,
/// title: str, /// title: str,

View File

@ -292,6 +292,41 @@ pub const fn button_warning_high() -> ButtonStyleSheet {
} }
} }
pub const fn button_warning_low() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
font: Font::DEMIBOLD,
text_color: GREY_LIGHT,
button_color: BG,
icon_color: GREEN_LIME,
background_color: BG,
border_color: BG,
border_radius: RADIUS,
border_width: 0,
},
active: &ButtonStyle {
font: Font::DEMIBOLD,
text_color: GREY_LIGHT,
button_color: BG,
icon_color: GREEN_LIME,
background_color: BG,
border_color: FG,
border_radius: RADIUS,
border_width: 0,
},
disabled: &ButtonStyle {
font: Font::DEMIBOLD,
text_color: GREY_LIGHT,
button_color: BG,
icon_color: GREEN_LIME,
background_color: BG,
border_color: BG,
border_radius: RADIUS,
border_width: 0,
},
}
}
// TODO: delete // TODO: delete
pub const fn button_confirm() -> ButtonStyleSheet { pub const fn button_confirm() -> ButtonStyleSheet {
ButtonStyleSheet { ButtonStyleSheet {

View File

@ -395,6 +395,11 @@ def show_tx_context_menu() -> LayoutObj[int]:
information, 3) Cancel transaction""" information, 3) Cancel transaction"""
# rust/src/ui/model_mercury/layout.rs
def create_backup_flow() -> LayoutObj[UiResult]
"""Start create backup or skip flow."""
# rust/src/ui/model_mercury/layout.rs # rust/src/ui/model_mercury/layout.rs
def show_share_words( def show_share_words(
*, *,
@ -404,6 +409,11 @@ def show_share_words(
"""Show mnemonic for backup.""" """Show mnemonic for backup."""
# rust/src/ui/model_mercury/layout.rs
def confirm_backup_written_down() -> LayoutObj[UiResult]
"""Confirm with the user that backup words are written down."""
# rust/src/ui/model_mercury/layout.rs # rust/src/ui/model_mercury/layout.rs
def request_number( def request_number(
*, *,

View File

@ -833,6 +833,7 @@ class TR:
words__error: str = "Error" words__error: str = "Error"
words__fee: str = "Fee" words__fee: str = "Fee"
words__from: str = "from" words__from: str = "from"
words__important: str = "Important"
words__keep_it_safe: str = "Keep it safe!" words__keep_it_safe: str = "Keep it safe!"
words__know_what_your_doing: str = "Continue only if you know what you are doing!" words__know_what_your_doing: str = "Continue only if you know what you are doing!"
words__my_trezor: str = "My Trezor" words__my_trezor: str = "My Trezor"

View File

@ -340,37 +340,21 @@ async def confirm_reset_device(title: str, recovery: bool = False) -> None:
) )
# TODO cleanup @ redesign
async def prompt_backup() -> bool: async def prompt_backup() -> bool:
result = await interact( # result = await interact(RustLayout(trezorui2.))
RustLayout( await interact(
trezorui2.confirm_action( RustLayout(trezorui2.show_success(title=TR.backup__new_wallet_created)),
title=TR.words__title_success,
action=TR.backup__new_wallet_successfully_created,
description=TR.backup__it_should_be_backed_up,
verb=TR.buttons__back_up,
verb_cancel=TR.buttons__skip,
)
),
"backup_device", "backup_device",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
if result is CONFIRMED:
return True
result = await interact( result = await interact(
RustLayout( # TODO: this is just POC
trezorui2.confirm_action( RustLayout(trezorui2.create_backup_flow()),
title=TR.words__warning.upper(),
action=TR.backup__want_to_skip,
description=TR.backup__can_back_up_anytime,
verb=TR.buttons__back_up,
verb_cancel=TR.buttons__skip,
)
),
"backup_device", "backup_device",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
return result is CONFIRMED return result is CONFIRMED
@ -586,8 +570,8 @@ async def show_success(
interact( interact(
RustLayout( RustLayout(
trezorui2.show_success( trezorui2.show_success(
title=content, title=subheader or "",
description=subheader or "", description="",
button=button.upper(), button=button.upper(),
allow_cancel=False, allow_cancel=False,
) )

View File

@ -32,9 +32,16 @@ async def show_share_words(
group_index + 1, share_index + 1 group_index + 1, share_index + 1
) )
await RustLayout(
trezorui2.show_share_words(
title=title,
pages=share_words,
),
)
result = await interact( result = await interact(
RustLayout( RustLayout(
trezorui2.show_share_words( trezorui2.confirm_backup_written_down(
title=title, title=title,
pages=share_words, pages=share_words,
), ),
@ -42,6 +49,13 @@ async def show_share_words(
"backup_words", "backup_words",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
result = await RustLayout(
trezorui2.show_info(
title="Check wallet backup",
description="Let's do a quick check of your backup.",
)
)
if result != CONFIRMED: if result != CONFIRMED:
raise ActionCancelled raise ActionCancelled
@ -296,15 +310,22 @@ async def slip39_advanced_prompt_group_threshold(num_of_groups: int) -> int:
async def show_warning_backup(slip39: bool) -> None: async def show_warning_backup(slip39: bool) -> None:
result = await interact( result = await interact(
RustLayout( RustLayout(
trezorui2.show_info( trezorui2.show_warning(
title=TR.reset__never_make_digital_copy, title=TR.words__important,
button=TR.buttons__ok_i_understand, value=TR.reset__never_make_digital_copy,
button="",
allow_cancel=False, allow_cancel=False,
) )
), ),
"backup_warning", "backup_warning",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
result = await RustLayout(
trezorui2.show_info(
title="Wallet backup",
description="Write the following words in order on your wallet backup card.",
)
)
if result != CONFIRMED: if result != CONFIRMED:
raise ActionCancelled raise ActionCancelled
@ -332,8 +353,9 @@ async def show_reset_warning(
RustLayout( RustLayout(
trezorui2.show_warning( trezorui2.show_warning(
title=subheader or "", title=subheader or "",
description=content, description="",
button=button.upper(), value=content,
button="",
allow_cancel=False, allow_cancel=False,
) )
), ),

View File

@ -835,6 +835,7 @@
"words__error": "Error", "words__error": "Error",
"words__fee": "Fee", "words__fee": "Fee",
"words__from": "from", "words__from": "from",
"words__important": "Important",
"words__keep_it_safe": "Keep it safe!", "words__keep_it_safe": "Keep it safe!",
"words__know_what_your_doing": "Continue only if you know what you are doing!", "words__know_what_your_doing": "Continue only if you know what you are doing!",
"words__my_trezor": "My Trezor", "words__my_trezor": "My Trezor",

View File

@ -854,5 +854,6 @@
"852": "cardano__vote_delegation", "852": "cardano__vote_delegation",
"853": "instructions__swipe_up", "853": "instructions__swipe_up",
"854": "instructions__tap_to_confirm", "854": "instructions__tap_to_confirm",
"855": "instructions__hold_to_confirm" "855": "instructions__hold_to_confirm",
"856": "words__important"
} }

View File

@ -1,8 +1,8 @@
{ {
"current": { "current": {
"merkle_root": "ba39f116679b466d0b1192964d3037d54f5e2486c1ba6e2fc6de522f984f6f0c", "merkle_root": "04a116dbd20d79235dd81e26fa428eb7c5f4971e76f08a47cde1ec98c959e586",
"datetime": "2024-05-17T10:09:38.714090", "datetime": "2024-05-17T10:12:24.161735",
"commit": "e797e871c50530f1c1058e588e3ec0ead9f5b13f" "commit": "aea8bdbe8f9cc2fe629e624a06f4f1b1af6e0a8f"
}, },
"history": [ "history": [
{ {