diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index 4048cc9623..e22b7ee2ec 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -90,6 +90,7 @@ static void _librust_qstrs(void) { MP_QSTR_backup__it_should_be_backed_up_now; MP_QSTR_backup__new_wallet_created; MP_QSTR_backup__new_wallet_successfully_created; + MP_QSTR_backup__not_recommend; MP_QSTR_backup__recover_anytime; MP_QSTR_backup__title_backup_completed; MP_QSTR_backup__title_backup_wallet; @@ -775,6 +776,7 @@ static void _librust_qstrs(void) { MP_QSTR_words__not_recommended; MP_QSTR_words__operation_cancelled; MP_QSTR_words__outputs; + MP_QSTR_words__pay_attention; MP_QSTR_words__please_check_again; MP_QSTR_words__please_try_again; MP_QSTR_words__really_wanna; diff --git a/core/embed/rust/src/translations/generated/translated_string.rs b/core/embed/rust/src/translations/generated/translated_string.rs index 7a65e7f5b0..94d88cf919 100644 --- a/core/embed/rust/src/translations/generated/translated_string.rs +++ b/core/embed/rust/src/translations/generated/translated_string.rs @@ -29,7 +29,7 @@ pub enum TranslatedString { auto_lock__change_template = 15, // "Auto-lock Trezor after {0} of inactivity?" auto_lock__title = 16, // "Auto-lock delay" backup__can_back_up_anytime = 17, // "You can back up your Trezor once, at any time." - backup__it_should_be_backed_up = 18, // "You should back up your new wallet right now." + backup__it_should_be_backed_up = 18, // {"Bolt": "You should back up your new wallet right now.", "Caesar": "You should back up your new wallet right now.", "Delizia": "You should back up your new wallet right now.", "Eckhart": "Back up your new wallet now."} backup__it_should_be_backed_up_now = 19, // "It should be backed up now!" backup__new_wallet_created = 20, // "Wallet created.\n" backup__new_wallet_successfully_created = 21, // "Wallet created successfully." @@ -1249,7 +1249,7 @@ pub enum TranslatedString { instructions__hold_to_confirm = 855, // "Hold to confirm" words__important = 856, // "Important" reset__words_written_down_template = 857, // "I wrote down all {0} words in order." - backup__create_backup_to_prevent_loss = 858, // "Create a backup to avoid losing access to your funds" + backup__create_backup_to_prevent_loss = 858, // {"Bolt": "Create a backup to avoid losing access to your funds", "Caesar": "Create a backup to avoid losing access to your funds", "Delizia": "Create a backup to avoid losing access to your funds", "Eckhart": "Create a wallet backup to avoid losing access to your funds."} reset__check_backup_instructions = 859, // "Let's do a quick check of your backup." words__instructions = 860, // "Instructions" words__not_recommended = 861, // "Not recommended!" @@ -1405,6 +1405,8 @@ pub enum TranslatedString { #[cfg(feature = "universal_fw")] nostr__event_kind_template = 992, // "Event kind: {0}" reset__share_words_first = 993, // "Write down the first word from the backup." + backup__not_recommend = 994, // "We don't recommend to skip wallet backup creation." + words__pay_attention = 995, // "Pay attention" } impl TranslatedString { @@ -1430,7 +1432,14 @@ impl TranslatedString { Self::auto_lock__change_template => "Auto-lock Trezor after {0} of inactivity?", Self::auto_lock__title => "Auto-lock delay", Self::backup__can_back_up_anytime => "You can back up your Trezor once, at any time.", + #[cfg(feature = "layout_bolt")] Self::backup__it_should_be_backed_up => "You should back up your new wallet right now.", + #[cfg(feature = "layout_caesar")] + Self::backup__it_should_be_backed_up => "You should back up your new wallet right now.", + #[cfg(feature = "layout_delizia")] + Self::backup__it_should_be_backed_up => "You should back up your new wallet right now.", + #[cfg(feature = "layout_eckhart")] + Self::backup__it_should_be_backed_up => "Back up your new wallet now.", Self::backup__it_should_be_backed_up_now => "It should be backed up now!", Self::backup__new_wallet_created => "Wallet created.\n", Self::backup__new_wallet_successfully_created => "Wallet created successfully.", @@ -2671,7 +2680,14 @@ impl TranslatedString { Self::instructions__hold_to_confirm => "Hold to confirm", Self::words__important => "Important", Self::reset__words_written_down_template => "I wrote down all {0} words in order.", + #[cfg(feature = "layout_bolt")] Self::backup__create_backup_to_prevent_loss => "Create a backup to avoid losing access to your funds", + #[cfg(feature = "layout_caesar")] + Self::backup__create_backup_to_prevent_loss => "Create a backup to avoid losing access to your funds", + #[cfg(feature = "layout_delizia")] + Self::backup__create_backup_to_prevent_loss => "Create a backup to avoid losing access to your funds", + #[cfg(feature = "layout_eckhart")] + Self::backup__create_backup_to_prevent_loss => "Create a wallet backup to avoid losing access to your funds.", Self::reset__check_backup_instructions => "Let's do a quick check of your backup.", Self::words__instructions => "Instructions", Self::words__not_recommended => "Not recommended!", @@ -2841,6 +2857,8 @@ impl TranslatedString { #[cfg(feature = "universal_fw")] Self::nostr__event_kind_template => "Event kind: {0}", Self::reset__share_words_first => "Write down the first word from the backup.", + Self::backup__not_recommend => "We don't recommend to skip wallet backup creation.", + Self::words__pay_attention => "Pay attention", } } @@ -4241,6 +4259,8 @@ impl TranslatedString { #[cfg(feature = "universal_fw")] Qstr::MP_QSTR_nostr__event_kind_template => Some(Self::nostr__event_kind_template), Qstr::MP_QSTR_reset__share_words_first => Some(Self::reset__share_words_first), + Qstr::MP_QSTR_backup__not_recommend => Some(Self::backup__not_recommend), + Qstr::MP_QSTR_words__pay_attention => Some(Self::words__pay_attention), _ => None, } } diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs b/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs index a83f738009..5835ae7e81 100644 --- a/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs +++ b/core/embed/rust/src/ui/layout_eckhart/flow/mod.rs @@ -1,7 +1,9 @@ pub mod confirm_reset; +pub mod prompt_backup; pub mod request_passphrase; pub mod show_share_words; pub use confirm_reset::new_confirm_reset; +pub use prompt_backup::PromptBackup; pub use request_passphrase::RequestPassphrase; pub use show_share_words::new_show_share_words_flow; diff --git a/core/embed/rust/src/ui/layout_eckhart/flow/prompt_backup.rs b/core/embed/rust/src/ui/layout_eckhart/flow/prompt_backup.rs new file mode 100644 index 0000000000..302b6210ad --- /dev/null +++ b/core/embed/rust/src/ui/layout_eckhart/flow/prompt_backup.rs @@ -0,0 +1,123 @@ +use crate::{ + error, + strutil::TString, + translations::TR, + ui::{ + component::{ + text::paragraphs::{Paragraph, ParagraphSource, Paragraphs}, + ComponentExt, + }, + flow::{ + base::{Decision, DecisionBuilder as _}, + FlowController, FlowMsg, SwipeFlow, + }, + geometry::{Alignment, Direction, LinearPlacement, Offset}, + }, +}; + +use super::super::{ + component::{ + ActionBar, Button, Header, HeaderMsg, Hint, TextScreen, TextScreenMsg, VerticalMenu, + VerticalMenuScreen, VerticalMenuScreenMsg, + }, + theme, +}; + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum PromptBackup { + Intro, + Menu, + SkipBackup, +} + +impl FlowController for PromptBackup { + #[inline] + fn index(&'static self) -> usize { + *self as usize + } + + fn handle_swipe(&'static self, direction: Direction) -> Decision { + match (self, direction) { + _ => self.do_nothing(), + } + } + + fn handle_event(&'static self, msg: FlowMsg) -> Decision { + match (self, msg) { + (Self::Intro, FlowMsg::Info) => Self::Menu.goto(), + (Self::Intro, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed), + (Self::Menu, FlowMsg::Choice(0)) => Self::SkipBackup.swipe_left(), + (Self::Menu, FlowMsg::Cancelled) => Self::Intro.goto(), + (Self::SkipBackup, FlowMsg::Cancelled) => Self::Intro.goto(), + (Self::SkipBackup, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Cancelled), + _ => self.do_nothing(), + } + } +} + +pub fn new_prompt_backup() -> Result { + let title: TString = TR::backup__title_create_wallet_backup.into(); + let content: TString = TR::backup__it_should_be_backed_up.into(); + + let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_REGULAR, content)) + .with_placement(LinearPlacement::vertical()); + + let content_intro = TextScreen::new(paragraphs) + .with_header(Header::new(title).with_menu_button()) + .with_action_bar(ActionBar::new_single(Button::with_text( + TR::buttons__continue.into(), + ))) + .map(|msg| match msg { + TextScreenMsg::Menu => Some(FlowMsg::Info), + TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed), + _ => None, + }); + + let content_menu = VerticalMenuScreen::new( + VerticalMenu::empty().item( + Button::with_text(TR::backup__title_skip.into()) + .styled(theme::menu_item_title_red()) + .with_text_align(Alignment::Start) + .with_content_offset(Offset::x(12)), + ), + ) + .with_header( + Header::new(title) + .with_right_button(Button::with_icon(theme::ICON_CROSS), HeaderMsg::Cancelled), + ) + .map(|msg| match msg { + VerticalMenuScreenMsg::Selected(i) => Some(FlowMsg::Choice(i)), + VerticalMenuScreenMsg::Close => Some(FlowMsg::Cancelled), + _ => None, + }); + + let paragraphs_skip_intro = Paragraph::new( + &theme::TEXT_REGULAR, + TR::backup__create_backup_to_prevent_loss, + ) + .into_paragraphs() + .with_placement(LinearPlacement::vertical()); + + let content_skip_intro = TextScreen::new(paragraphs_skip_intro) + .with_header( + Header::new(TR::words__pay_attention.into()) + .with_icon(theme::ICON_WARNING, theme::ORANGE) + .with_text_style(theme::label_title_danger()), + ) + .with_action_bar(ActionBar::new_double( + Button::with_icon(theme::ICON_CHEVRON_LEFT), + Button::with_text(TR::buttons__skip.into()).styled(theme::button_cancel()), + )) + .with_hint(Hint::new_instruction(TR::backup__not_recommend, None)) + .map(|msg| match msg { + TextScreenMsg::Menu => Some(FlowMsg::Cancelled), + TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed), + TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled), + }); + + let mut res = SwipeFlow::new(&PromptBackup::Intro)?; + res.add_page(&PromptBackup::Intro, content_intro)? + .add_page(&PromptBackup::Menu, content_menu)? + .add_page(&PromptBackup::SkipBackup, content_skip_intro)?; + Ok(res) +} diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs index a95e0678a4..06b34e6610 100644 --- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs @@ -351,7 +351,8 @@ impl FirmwareUI for UIEckhart { } fn prompt_backup() -> Result { - Err::, Error>(Error::ValueError(c"not implemented")) + let flow = flow::prompt_backup::new_prompt_backup()?; + Ok(flow) } fn request_bip39( @@ -575,8 +576,6 @@ impl FirmwareUI for UIEckhart { Ok(layout) } - // TODO: This is a temporary implementation so the UI can be functional. - // TODO: This is a temporary implementation so the UI can be functional. fn show_progress( description: TString<'static>, _indeterminate: bool, diff --git a/core/mocks/trezortranslate_keys.pyi b/core/mocks/trezortranslate_keys.pyi index db00d8acf9..63032020fc 100644 --- a/core/mocks/trezortranslate_keys.pyi +++ b/core/mocks/trezortranslate_keys.pyi @@ -35,6 +35,7 @@ class TR: backup__it_should_be_backed_up_now: str = "It should be backed up now!" backup__new_wallet_created: str = "Wallet created.\n" backup__new_wallet_successfully_created: str = "Wallet created successfully." + backup__not_recommend: str = "We don't recommend to skip wallet backup creation." backup__recover_anytime: str = "You can use your backup to recover your wallet at any time." backup__title_backup_completed: str = "Wallet backup completed" backup__title_backup_wallet: str = "Back up wallet" @@ -963,6 +964,7 @@ class TR: words__not_recommended: str = "Not recommended!" words__operation_cancelled: str = "Operation cancelled" words__outputs: str = "outputs" + words__pay_attention: str = "Pay attention" words__please_check_again: str = "Please check again" words__please_try_again: str = "Please try again" words__really_wanna: str = "Do you really want to" diff --git a/core/translations/en.json b/core/translations/en.json index 4f13ea706f..91f9fa2e29 100644 --- a/core/translations/en.json +++ b/core/translations/en.json @@ -30,10 +30,21 @@ "auto_lock__title": "Auto-lock delay", "auto_lock__turned_on": "Auto-lock turned on", "backup__can_back_up_anytime": "You can back up your Trezor once, at any time.", - "backup__create_backup_to_prevent_loss": "Create a backup to avoid losing access to your funds", + "backup__create_backup_to_prevent_loss": { + "Bolt": "Create a backup to avoid losing access to your funds", + "Caesar": "Create a backup to avoid losing access to your funds", + "Delizia": "Create a backup to avoid losing access to your funds", + "Eckhart": "Create a wallet backup to avoid losing access to your funds." + }, + "backup__not_recommend": "We don't recommend to skip wallet backup creation.", "backup__info_multi_share_backup": "Your wallet backup contains multiple lists of words in a specific order (shares).", "backup__info_single_share_backup": "Your wallet backup contains {0} words in a specific order.", - "backup__it_should_be_backed_up": "You should back up your new wallet right now.", + "backup__it_should_be_backed_up": { + "Bolt": "You should back up your new wallet right now.", + "Caesar": "You should back up your new wallet right now.", + "Delizia": "You should back up your new wallet right now.", + "Eckhart": "Back up your new wallet now." + }, "backup__it_should_be_backed_up_now": "It should be backed up now!", "backup__new_wallet_created": "Wallet created.\n", "backup__new_wallet_successfully_created": "Wallet created successfully.", @@ -978,6 +989,7 @@ "words__good_to_know": "Good to know", "words__important": "Important", "words__instructions": "Instructions", + "words__pay_attention": "Pay attention", "words__keep_it_safe": "Keep it safe!", "words__know_what_your_doing": "Continue only if you know what you are doing!", "words__my_trezor": "My Trezor", diff --git a/core/translations/order.json b/core/translations/order.json index da5ee4e428..461a7dbb18 100644 --- a/core/translations/order.json +++ b/core/translations/order.json @@ -992,5 +992,7 @@ "990": "sign_message__confirm_without_review", "991": "instructions__tap_to_continue", "992": "nostr__event_kind_template", - "993": "reset__share_words_first" + "993": "reset__share_words_first", + "994": "backup__not_recommend", + "995": "words__pay_attention" }