mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-24 21:32:03 +00:00
feat(eckhart): share words flow
This commit is contained in:
parent
4c6a0d038e
commit
1b34921162
@ -532,6 +532,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_reset__set_it_to_count_template;
|
MP_QSTR_reset__set_it_to_count_template;
|
||||||
MP_QSTR_reset__share_checked_successfully_template;
|
MP_QSTR_reset__share_checked_successfully_template;
|
||||||
MP_QSTR_reset__share_completed_template;
|
MP_QSTR_reset__share_completed_template;
|
||||||
|
MP_QSTR_reset__share_words_first;
|
||||||
MP_QSTR_reset__share_words_title;
|
MP_QSTR_reset__share_words_title;
|
||||||
MP_QSTR_reset__slip39_checklist_more_info_threshold;
|
MP_QSTR_reset__slip39_checklist_more_info_threshold;
|
||||||
MP_QSTR_reset__slip39_checklist_more_info_threshold_example_template;
|
MP_QSTR_reset__slip39_checklist_more_info_threshold_example_template;
|
||||||
@ -651,7 +652,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_show_progress_coinjoin;
|
MP_QSTR_show_progress_coinjoin;
|
||||||
MP_QSTR_show_remaining_shares;
|
MP_QSTR_show_remaining_shares;
|
||||||
MP_QSTR_show_share_words;
|
MP_QSTR_show_share_words;
|
||||||
MP_QSTR_show_share_words_delizia;
|
MP_QSTR_show_share_words_extended;
|
||||||
MP_QSTR_show_simple;
|
MP_QSTR_show_simple;
|
||||||
MP_QSTR_show_success;
|
MP_QSTR_show_success;
|
||||||
MP_QSTR_show_wait_text;
|
MP_QSTR_show_wait_text;
|
||||||
|
@ -855,7 +855,7 @@ pub enum TranslatedString {
|
|||||||
reset__recovery_share_title_template = 567, // "Recovery share #{0}"
|
reset__recovery_share_title_template = 567, // "Recovery share #{0}"
|
||||||
reset__required_number_of_groups = 568, // "The required number of groups for recovery."
|
reset__required_number_of_groups = 568, // "The required number of groups for recovery."
|
||||||
reset__select_correct_word = 569, // "Select the correct word for each position."
|
reset__select_correct_word = 569, // "Select the correct word for each position."
|
||||||
reset__select_word_template = 570, // "Select {0} word"
|
reset__select_word_template = 570, // {"Bolt": "Select {0} word", "Caesar": "Select {0} word", "Delizia": "Select {0} word", "Eckhart": "Select word #{0} from your wallet backup"}
|
||||||
reset__select_word_x_of_y_template = 571, // "Select word {0} of {1}:"
|
reset__select_word_x_of_y_template = 571, // "Select word {0} of {1}:"
|
||||||
reset__set_it_to_count_template = 572, // "Set it to {0} and you will need "
|
reset__set_it_to_count_template = 572, // "Set it to {0} and you will need "
|
||||||
reset__share_checked_successfully_template = 573, // "Share #{0} checked successfully."
|
reset__share_checked_successfully_template = 573, // "Share #{0} checked successfully."
|
||||||
@ -1339,7 +1339,7 @@ pub enum TranslatedString {
|
|||||||
reset__repeat_for_all_shares = 938, // "Repeat for all shares."
|
reset__repeat_for_all_shares = 938, // "Repeat for all shares."
|
||||||
homescreen__settings_subtitle = 939, // "Settings"
|
homescreen__settings_subtitle = 939, // "Settings"
|
||||||
homescreen__settings_title = 940, // "Homescreen"
|
homescreen__settings_title = 940, // "Homescreen"
|
||||||
reset__the_word_is_repeated = 941, // "The word is repeated"
|
reset__the_word_is_repeated = 941, // {"Bolt": "The word is repeated", "Caesar": "The word is repeated", "Delizia": "The word is repeated", "Eckhart": "The word appears multiple times in the backup."}
|
||||||
tutorial__title_lets_begin = 942, // "Let's begin"
|
tutorial__title_lets_begin = 942, // "Let's begin"
|
||||||
tutorial__did_you_know = 943, // "Did you know?"
|
tutorial__did_you_know = 943, // "Did you know?"
|
||||||
tutorial__first_wallet = 944, // "The Trezor Model One, created in 2013,\nwas the world's first hardware wallet."
|
tutorial__first_wallet = 944, // "The Trezor Model One, created in 2013,\nwas the world's first hardware wallet."
|
||||||
@ -1383,6 +1383,7 @@ pub enum TranslatedString {
|
|||||||
#[cfg(feature = "universal_fw")]
|
#[cfg(feature = "universal_fw")]
|
||||||
ethereum__unknown_contract_address_short = 974, // "Unknown contract address."
|
ethereum__unknown_contract_address_short = 974, // "Unknown contract address."
|
||||||
instructions__keep_holding = 975, // "Keep holding"
|
instructions__keep_holding = 975, // "Keep holding"
|
||||||
|
reset__share_words_first = 976, // "Write down the first word from the backup."
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TranslatedString {
|
impl TranslatedString {
|
||||||
@ -2234,7 +2235,14 @@ impl TranslatedString {
|
|||||||
Self::reset__recovery_share_title_template => "Recovery share #{0}",
|
Self::reset__recovery_share_title_template => "Recovery share #{0}",
|
||||||
Self::reset__required_number_of_groups => "The required number of groups for recovery.",
|
Self::reset__required_number_of_groups => "The required number of groups for recovery.",
|
||||||
Self::reset__select_correct_word => "Select the correct word for each position.",
|
Self::reset__select_correct_word => "Select the correct word for each position.",
|
||||||
|
#[cfg(feature = "layout_bolt")]
|
||||||
Self::reset__select_word_template => "Select {0} word",
|
Self::reset__select_word_template => "Select {0} word",
|
||||||
|
#[cfg(feature = "layout_caesar")]
|
||||||
|
Self::reset__select_word_template => "Select {0} word",
|
||||||
|
#[cfg(feature = "layout_delizia")]
|
||||||
|
Self::reset__select_word_template => "Select {0} word",
|
||||||
|
#[cfg(feature = "layout_eckhart")]
|
||||||
|
Self::reset__select_word_template => "Select word #{0} from your wallet backup",
|
||||||
Self::reset__select_word_x_of_y_template => "Select word {0} of {1}:",
|
Self::reset__select_word_x_of_y_template => "Select word {0} of {1}:",
|
||||||
Self::reset__set_it_to_count_template => "Set it to {0} and you will need ",
|
Self::reset__set_it_to_count_template => "Set it to {0} and you will need ",
|
||||||
Self::reset__share_checked_successfully_template => "Share #{0} checked successfully.",
|
Self::reset__share_checked_successfully_template => "Share #{0} checked successfully.",
|
||||||
@ -2718,7 +2726,14 @@ impl TranslatedString {
|
|||||||
Self::reset__repeat_for_all_shares => "Repeat for all shares.",
|
Self::reset__repeat_for_all_shares => "Repeat for all shares.",
|
||||||
Self::homescreen__settings_subtitle => "Settings",
|
Self::homescreen__settings_subtitle => "Settings",
|
||||||
Self::homescreen__settings_title => "Homescreen",
|
Self::homescreen__settings_title => "Homescreen",
|
||||||
|
#[cfg(feature = "layout_bolt")]
|
||||||
Self::reset__the_word_is_repeated => "The word is repeated",
|
Self::reset__the_word_is_repeated => "The word is repeated",
|
||||||
|
#[cfg(feature = "layout_caesar")]
|
||||||
|
Self::reset__the_word_is_repeated => "The word is repeated",
|
||||||
|
#[cfg(feature = "layout_delizia")]
|
||||||
|
Self::reset__the_word_is_repeated => "The word is repeated",
|
||||||
|
#[cfg(feature = "layout_eckhart")]
|
||||||
|
Self::reset__the_word_is_repeated => "The word appears multiple times in the backup.",
|
||||||
Self::tutorial__title_lets_begin => "Let's begin",
|
Self::tutorial__title_lets_begin => "Let's begin",
|
||||||
Self::tutorial__did_you_know => "Did you know?",
|
Self::tutorial__did_you_know => "Did you know?",
|
||||||
Self::tutorial__first_wallet => "The Trezor Model One, created in 2013,\nwas the world's first hardware wallet.",
|
Self::tutorial__first_wallet => "The Trezor Model One, created in 2013,\nwas the world's first hardware wallet.",
|
||||||
@ -2762,6 +2777,7 @@ impl TranslatedString {
|
|||||||
#[cfg(feature = "universal_fw")]
|
#[cfg(feature = "universal_fw")]
|
||||||
Self::ethereum__unknown_contract_address_short => "Unknown contract address.",
|
Self::ethereum__unknown_contract_address_short => "Unknown contract address.",
|
||||||
Self::instructions__keep_holding => "Keep holding",
|
Self::instructions__keep_holding => "Keep holding",
|
||||||
|
Self::reset__share_words_first => "Write down the first word from the backup.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4140,6 +4156,7 @@ impl TranslatedString {
|
|||||||
#[cfg(feature = "universal_fw")]
|
#[cfg(feature = "universal_fw")]
|
||||||
Qstr::MP_QSTR_ethereum__unknown_contract_address_short => Some(Self::ethereum__unknown_contract_address_short),
|
Qstr::MP_QSTR_ethereum__unknown_contract_address_short => Some(Self::ethereum__unknown_contract_address_short),
|
||||||
Qstr::MP_QSTR_instructions__keep_holding => Some(Self::instructions__keep_holding),
|
Qstr::MP_QSTR_instructions__keep_holding => Some(Self::instructions__keep_holding),
|
||||||
|
Qstr::MP_QSTR_reset__share_words_first => Some(Self::reset__share_words_first),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -878,7 +878,7 @@ extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut
|
|||||||
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_share_words_delizia(
|
extern "C" fn new_show_share_words_extended(
|
||||||
n_args: usize,
|
n_args: usize,
|
||||||
args: *const Obj,
|
args: *const Obj,
|
||||||
kwargs: *mut Map,
|
kwargs: *mut Map,
|
||||||
@ -898,7 +898,7 @@ extern "C" fn new_show_share_words_delizia(
|
|||||||
|
|
||||||
let words: Vec<TString, 33> = util::iter_into_vec(words)?;
|
let words: Vec<TString, 33> = util::iter_into_vec(words)?;
|
||||||
|
|
||||||
let layout = ModelUI::show_share_words_delizia(
|
let layout = ModelUI::show_share_words_extended(
|
||||||
words,
|
words,
|
||||||
subtitle,
|
subtitle,
|
||||||
instructions,
|
instructions,
|
||||||
@ -1589,7 +1589,7 @@ pub static mp_module_trezorui_api: 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(),
|
||||||
|
|
||||||
/// def show_share_words_delizia(
|
/// def show_share_words_extended(
|
||||||
/// *,
|
/// *,
|
||||||
/// words: Iterable[str],
|
/// words: Iterable[str],
|
||||||
/// subtitle: str | None,
|
/// subtitle: str | None,
|
||||||
@ -1599,7 +1599,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
|||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Show mnemonic for wallet backup preceded by an instruction screen and followed by a
|
/// """Show mnemonic for wallet backup preceded by an instruction screen and followed by a
|
||||||
/// confirmation screen."""
|
/// confirmation screen."""
|
||||||
Qstr::MP_QSTR_show_share_words_delizia => obj_fn_kw!(0, new_show_share_words_delizia).as_obj(),
|
Qstr::MP_QSTR_show_share_words_extended => obj_fn_kw!(0, new_show_share_words_extended).as_obj(),
|
||||||
|
|
||||||
/// def show_simple(
|
/// def show_simple(
|
||||||
/// *,
|
/// *,
|
||||||
|
@ -1013,7 +1013,7 @@ impl FirmwareUI for UIBolt {
|
|||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_share_words_delizia(
|
fn show_share_words_extended(
|
||||||
_words: heapless::Vec<TString<'static>, 33>,
|
_words: heapless::Vec<TString<'static>, 33>,
|
||||||
_subtitle: Option<TString<'static>>,
|
_subtitle: Option<TString<'static>>,
|
||||||
_instructions: Obj,
|
_instructions: Obj,
|
||||||
|
@ -1133,7 +1133,7 @@ impl FirmwareUI for UICaesar {
|
|||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_share_words_delizia(
|
fn show_share_words_extended(
|
||||||
_words: heapless::Vec<TString<'static>, 33>,
|
_words: heapless::Vec<TString<'static>, 33>,
|
||||||
_subtitle: Option<TString<'static>>,
|
_subtitle: Option<TString<'static>>,
|
||||||
_instructions: Obj,
|
_instructions: Obj,
|
||||||
|
@ -996,11 +996,11 @@ impl FirmwareUI for UIDelizia {
|
|||||||
_title: Option<TString<'static>>,
|
_title: Option<TString<'static>>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(
|
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(
|
||||||
c"use show_share_words_delizia instead",
|
c"use show_share_words_extended instead",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_share_words_delizia(
|
fn show_share_words_extended(
|
||||||
words: heapless::Vec<TString<'static>, 33>,
|
words: heapless::Vec<TString<'static>, 33>,
|
||||||
subtitle: Option<TString<'static>>,
|
subtitle: Option<TString<'static>>,
|
||||||
instructions: Obj,
|
instructions: Obj,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
pub mod eckhart_swipe_flow_test;
|
pub mod eckhart_swipe_flow_test;
|
||||||
|
pub mod show_share_words;
|
||||||
|
|
||||||
pub use eckhart_swipe_flow_test::new_eckhart_swipe_flow;
|
pub use eckhart_swipe_flow_test::new_eckhart_swipe_flow;
|
||||||
|
pub use show_share_words::new_show_share_words_flow;
|
||||||
|
111
core/embed/rust/src/ui/layout_eckhart/flow/show_share_words.rs
Normal file
111
core/embed/rust/src/ui/layout_eckhart/flow/show_share_words.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use crate::{
|
||||||
|
error,
|
||||||
|
strutil::TString,
|
||||||
|
translations::TR,
|
||||||
|
ui::{
|
||||||
|
component::{
|
||||||
|
text::{
|
||||||
|
op::OpTextLayout,
|
||||||
|
paragraphs::{Paragraph, ParagraphSource},
|
||||||
|
},
|
||||||
|
ComponentExt, FormattedText,
|
||||||
|
},
|
||||||
|
flow::{
|
||||||
|
base::{Decision, DecisionBuilder as _},
|
||||||
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
|
},
|
||||||
|
geometry::{Direction, LinearPlacement},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use heapless::Vec;
|
||||||
|
|
||||||
|
use super::super::{
|
||||||
|
component::{
|
||||||
|
ActionBar, Button, Header, ShareWordsScreen, ShareWordsScreenMsg, TextScreen, TextScreenMsg,
|
||||||
|
},
|
||||||
|
fonts, theme,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum ShowShareWords {
|
||||||
|
Instruction,
|
||||||
|
ShareWords,
|
||||||
|
Confirm,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlowController for ShowShareWords {
|
||||||
|
#[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::Instruction, FlowMsg::Cancelled) => self.return_msg(FlowMsg::Cancelled),
|
||||||
|
(Self::Instruction, FlowMsg::Confirmed) => Self::ShareWords.goto(),
|
||||||
|
(Self::ShareWords, FlowMsg::Cancelled) => Self::Instruction.goto(),
|
||||||
|
(Self::ShareWords, FlowMsg::Confirmed) => Self::Confirm.goto(),
|
||||||
|
(Self::Confirm, FlowMsg::Cancelled) => Self::ShareWords.goto(),
|
||||||
|
(Self::Confirm, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
|
||||||
|
_ => self.do_nothing(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_show_share_words_flow(
|
||||||
|
words: Vec<TString<'static>, 33>,
|
||||||
|
_subtitle: TString<'static>,
|
||||||
|
instruction: Paragraph<'static>,
|
||||||
|
text_confirm: TString<'static>,
|
||||||
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
|
let instruction = TextScreen::new(
|
||||||
|
instruction
|
||||||
|
.into_paragraphs()
|
||||||
|
.with_placement(LinearPlacement::vertical()),
|
||||||
|
)
|
||||||
|
.with_header(Header::new(TR::reset__recovery_wallet_backup_title.into()))
|
||||||
|
.with_action_bar(ActionBar::new_double(
|
||||||
|
Button::with_icon(theme::ICON_CHEVRON_UP),
|
||||||
|
Button::with_text(TR::buttons__continue.into()),
|
||||||
|
))
|
||||||
|
.map(|msg| match msg {
|
||||||
|
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||||
|
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
|
||||||
|
_ => Some(FlowMsg::Cancelled),
|
||||||
|
});
|
||||||
|
|
||||||
|
let share_words = ShareWordsScreen::new(words).map(|msg| match msg {
|
||||||
|
ShareWordsScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||||
|
ShareWordsScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
|
||||||
|
});
|
||||||
|
|
||||||
|
let op_confirm =
|
||||||
|
OpTextLayout::new(theme::TEXT_NORMAL).text(text_confirm, fonts::FONT_SATOSHI_REGULAR_38);
|
||||||
|
|
||||||
|
let confirm = TextScreen::new(FormattedText::new(op_confirm))
|
||||||
|
.with_header(Header::new(TR::reset__recovery_wallet_backup_title.into()))
|
||||||
|
.with_action_bar(ActionBar::new_double(
|
||||||
|
Button::with_icon(theme::ICON_CHEVRON_LEFT),
|
||||||
|
Button::with_text(TR::buttons__hold_to_confirm.into())
|
||||||
|
.styled(theme::button_confirm())
|
||||||
|
.with_long_press(theme::CONFIRM_HOLD_DURATION),
|
||||||
|
))
|
||||||
|
.map(|msg| match msg {
|
||||||
|
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||||
|
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
|
||||||
|
TextScreenMsg::Menu => Some(FlowMsg::Cancelled),
|
||||||
|
});
|
||||||
|
|
||||||
|
let res = SwipeFlow::new(&ShowShareWords::Instruction)?
|
||||||
|
.with_page(&ShowShareWords::Instruction, instruction)?
|
||||||
|
.with_page(&ShowShareWords::ShareWords, share_words)?
|
||||||
|
.with_page(&ShowShareWords::Confirm, confirm)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
@ -25,7 +25,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
component::{ActionBar, Button, Header, HeaderMsg, Hint, TextScreen},
|
component::{ActionBar, Button, Header, HeaderMsg, Hint, TextScreen},
|
||||||
fonts, theme, UIEckhart,
|
flow, fonts, theme, UIEckhart,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl FirmwareUI for UIEckhart {
|
impl FirmwareUI for UIEckhart {
|
||||||
@ -553,17 +553,33 @@ impl FirmwareUI for UIEckhart {
|
|||||||
_words: heapless::Vec<TString<'static>, 33>,
|
_words: heapless::Vec<TString<'static>, 33>,
|
||||||
_title: Option<TString<'static>>,
|
_title: Option<TString<'static>>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(c"not implemented"))
|
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(
|
||||||
|
c"use show_share_words_extended instead",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_share_words_delizia(
|
fn show_share_words_extended(
|
||||||
_words: heapless::Vec<TString<'static>, 33>,
|
words: heapless::Vec<TString<'static>, 33>,
|
||||||
_subtitle: Option<TString<'static>>,
|
subtitle: Option<TString<'static>>,
|
||||||
_instructions: Obj,
|
instructions: Obj,
|
||||||
|
// Irrelevant for Eckhart because the footer is dynamic
|
||||||
_text_footer: Option<TString<'static>>,
|
_text_footer: Option<TString<'static>>,
|
||||||
_text_confirm: TString<'static>,
|
text_confirm: TString<'static>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(c"not implemented"))
|
// TODO: add support for multiple instructions
|
||||||
|
let instruction: TString = IterBuf::new()
|
||||||
|
.try_iterate(instructions)?
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.try_into()?;
|
||||||
|
|
||||||
|
let flow = flow::show_share_words::new_show_share_words_flow(
|
||||||
|
words,
|
||||||
|
subtitle.unwrap_or(TString::empty()),
|
||||||
|
Paragraph::new(&theme::TEXT_REGULAR, instruction),
|
||||||
|
text_confirm,
|
||||||
|
)?;
|
||||||
|
Ok(flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_remaining_shares(_pages_iterable: Obj) -> Result<impl LayoutMaybeTrace, Error> {
|
fn show_remaining_shares(_pages_iterable: Obj) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
|
@ -340,8 +340,8 @@ pub trait FirmwareUI {
|
|||||||
) -> Result<impl LayoutMaybeTrace, Error>;
|
) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
|
|
||||||
// TODO: merge with `show_share_words` instead of having specific version for
|
// TODO: merge with `show_share_words` instead of having specific version for
|
||||||
// Delizia UI
|
// Delizia/Eckhart UI
|
||||||
fn show_share_words_delizia(
|
fn show_share_words_extended(
|
||||||
words: Vec<TString<'static>, 33>,
|
words: Vec<TString<'static>, 33>,
|
||||||
subtitle: Option<TString<'static>>,
|
subtitle: Option<TString<'static>>,
|
||||||
instructions: Obj, // TODO: replace Obj
|
instructions: Obj, // TODO: replace Obj
|
||||||
|
@ -603,7 +603,7 @@ def show_share_words(
|
|||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_micropython.rs
|
# rust/src/ui/api/firmware_micropython.rs
|
||||||
def show_share_words_delizia(
|
def show_share_words_extended(
|
||||||
*,
|
*,
|
||||||
words: Iterable[str],
|
words: Iterable[str],
|
||||||
subtitle: str | None,
|
subtitle: str | None,
|
||||||
|
@ -665,6 +665,7 @@ class TR:
|
|||||||
reset__set_it_to_count_template: str = "Set it to {0} and you will need "
|
reset__set_it_to_count_template: str = "Set it to {0} and you will need "
|
||||||
reset__share_checked_successfully_template: str = "Share #{0} checked successfully."
|
reset__share_checked_successfully_template: str = "Share #{0} checked successfully."
|
||||||
reset__share_completed_template: str = "Share #{0} completed"
|
reset__share_completed_template: str = "Share #{0} completed"
|
||||||
|
reset__share_words_first: str = "Write down the first word from the backup."
|
||||||
reset__share_words_title: str = "Standard backup"
|
reset__share_words_title: str = "Standard backup"
|
||||||
reset__slip39_checklist_more_info_threshold: str = "The threshold sets the minumum number of shares needed to recover your wallet."
|
reset__slip39_checklist_more_info_threshold: str = "The threshold sets the minumum number of shares needed to recover your wallet."
|
||||||
reset__slip39_checklist_more_info_threshold_example_template: str = "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet."
|
reset__slip39_checklist_more_info_threshold_example_template: str = "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet."
|
||||||
|
@ -38,7 +38,7 @@ def show_share_words(
|
|||||||
text_confirm = TR.reset__words_written_down_template.format(words_count)
|
text_confirm = TR.reset__words_written_down_template.format(words_count)
|
||||||
|
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui_api.show_share_words_delizia(
|
trezorui_api.show_share_words_extended(
|
||||||
words=share_words,
|
words=share_words,
|
||||||
subtitle=subtitle,
|
subtitle=subtitle,
|
||||||
instructions=instructions,
|
instructions=instructions,
|
||||||
|
@ -16,8 +16,31 @@ def show_share_words(
|
|||||||
share_index: int | None = None,
|
share_index: int | None = None,
|
||||||
group_index: int | None = None,
|
group_index: int | None = None,
|
||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
# FIXME: not implemented
|
if share_index is None:
|
||||||
raise NotImplemented
|
subtitle = None
|
||||||
|
elif group_index is None:
|
||||||
|
subtitle = TR.reset__recovery_share_title_template.format(share_index + 1)
|
||||||
|
else:
|
||||||
|
subtitle = TR.reset__group_share_title_template.format(
|
||||||
|
group_index + 1, share_index + 1
|
||||||
|
)
|
||||||
|
words_count = len(share_words)
|
||||||
|
description = None
|
||||||
|
# Eckhart currently has only one instruction, other are shown in the hint area
|
||||||
|
instructions = [TR.reset__write_down_words_template.format(words_count)]
|
||||||
|
assert len(instructions) == 1
|
||||||
|
text_confirm = TR.reset__words_written_down_template.format(words_count)
|
||||||
|
|
||||||
|
return raise_if_not_confirmed(
|
||||||
|
trezorui_api.show_share_words_extended(
|
||||||
|
words=share_words,
|
||||||
|
subtitle=subtitle,
|
||||||
|
instructions=instructions,
|
||||||
|
text_footer=description,
|
||||||
|
text_confirm=text_confirm,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def select_word(
|
async def select_word(
|
||||||
@ -46,9 +69,7 @@ async def select_word(
|
|||||||
result = await interact(
|
result = await interact(
|
||||||
trezorui_api.select_word(
|
trezorui_api.select_word(
|
||||||
title=title,
|
title=title,
|
||||||
description=TR.reset__select_word_x_of_y_template.format(
|
description=TR.reset__select_word_template.format(checked_index + 1),
|
||||||
checked_index + 1, count
|
|
||||||
),
|
|
||||||
words=(words[0], words[1], words[2]),
|
words=(words[0], words[1], words[2]),
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
|
@ -662,12 +662,18 @@
|
|||||||
"reset__required_number_of_groups": "The required number of groups for recovery.",
|
"reset__required_number_of_groups": "The required number of groups for recovery.",
|
||||||
"reset__select_correct_word": "Select the correct word for each position.",
|
"reset__select_correct_word": "Select the correct word for each position.",
|
||||||
"reset__select_threshold": "Select the minimum shares required to recover your wallet.",
|
"reset__select_threshold": "Select the minimum shares required to recover your wallet.",
|
||||||
"reset__select_word_template": "Select {0} word",
|
"reset__select_word_template": {
|
||||||
|
"Bolt": "Select {0} word",
|
||||||
|
"Caesar": "Select {0} word",
|
||||||
|
"Delizia": "Select {0} word",
|
||||||
|
"Eckhart": "Select word #{0} from your wallet backup"
|
||||||
|
},
|
||||||
"reset__select_word_x_of_y_template": "Select word {0} of {1}:",
|
"reset__select_word_x_of_y_template": "Select word {0} of {1}:",
|
||||||
"reset__set_it_to_count_template": "Set it to {0} and you will need ",
|
"reset__set_it_to_count_template": "Set it to {0} and you will need ",
|
||||||
"reset__share_checked_successfully_template": "Share #{0} checked successfully.",
|
"reset__share_checked_successfully_template": "Share #{0} checked successfully.",
|
||||||
"reset__share_completed_template": "Share #{0} completed",
|
"reset__share_completed_template": "Share #{0} completed",
|
||||||
"reset__share_words_title": "Standard backup",
|
"reset__share_words_title": "Standard backup",
|
||||||
|
"reset__share_words_first": "Write down the first word from the backup.",
|
||||||
"reset__slip39_checklist_more_info_threshold": "The threshold sets the minumum number of shares needed to recover your wallet.",
|
"reset__slip39_checklist_more_info_threshold": "The threshold sets the minumum number of shares needed to recover your wallet.",
|
||||||
"reset__slip39_checklist_more_info_threshold_example_template": "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet.",
|
"reset__slip39_checklist_more_info_threshold_example_template": "If you set {0} out of {1} shares, you'll need {2} backup shares to recover your wallet.",
|
||||||
"reset__slip39_checklist_num_groups": "Number of groups",
|
"reset__slip39_checklist_num_groups": "Number of groups",
|
||||||
@ -684,7 +690,12 @@
|
|||||||
"reset__slip39_checklist_write_down": "Write down and check all shares",
|
"reset__slip39_checklist_write_down": "Write down and check all shares",
|
||||||
"reset__slip39_checklist_write_down_recovery": "Write down & check all wallet backup shares",
|
"reset__slip39_checklist_write_down_recovery": "Write down & check all wallet backup shares",
|
||||||
"reset__the_threshold_sets_the_number_of_shares": "The threshold sets the number of shares ",
|
"reset__the_threshold_sets_the_number_of_shares": "The threshold sets the number of shares ",
|
||||||
"reset__the_word_is_repeated": "The word is repeated",
|
"reset__the_word_is_repeated": {
|
||||||
|
"Bolt": "The word is repeated",
|
||||||
|
"Caesar": "The word is repeated",
|
||||||
|
"Delizia": "The word is repeated",
|
||||||
|
"Eckhart": "The word appears multiple times in the backup."
|
||||||
|
},
|
||||||
"reset__threshold_info": "= minimum number of unique word lists used for recovery.",
|
"reset__threshold_info": "= minimum number of unique word lists used for recovery.",
|
||||||
"reset__title_backup_is_done": "Backup is done",
|
"reset__title_backup_is_done": "Backup is done",
|
||||||
"reset__title_create_wallet": "Create wallet",
|
"reset__title_create_wallet": "Create wallet",
|
||||||
|
@ -974,5 +974,6 @@
|
|||||||
"972": "ethereum__interaction_contract",
|
"972": "ethereum__interaction_contract",
|
||||||
"973": "misc__enable_labeling",
|
"973": "misc__enable_labeling",
|
||||||
"974": "ethereum__unknown_contract_address_short",
|
"974": "ethereum__unknown_contract_address_short",
|
||||||
"975": "instructions__keep_holding"
|
"975": "instructions__keep_holding",
|
||||||
|
"976": "reset__share_words_first"
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"current": {
|
"current": {
|
||||||
"merkle_root": "43c08e81d71c1c28d77b1650fc96b0dfcd473fde0c922717e5588baeeb581bd3",
|
"merkle_root": "31454a46346717afd55e29f2a23f6cf64e4e23679af127d774895aa3a700c764",
|
||||||
"datetime": "2025-02-14T16:12:57.065880",
|
"datetime": "2025-02-18T22:33:29.769368",
|
||||||
"commit": "3dabb94653e04856efc89d07c67b7e6f0c587f8c"
|
"commit": "778d5265dc258c1b0b74e8433acbd08d090b8746"
|
||||||
},
|
},
|
||||||
"history": [
|
"history": [
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user