mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 04:18:10 +00:00
feat(core/ui): info screens before ShareWords
Inform the user about possible repeated words in 1-of-1 SLIP39. Instruct the user to "repeat for all shares". [no changelog]
This commit is contained in:
parent
d4b854a95e
commit
25a9ef3cf5
@ -502,6 +502,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_reset__only_one_share_will_be_created;
|
MP_QSTR_reset__only_one_share_will_be_created;
|
||||||
MP_QSTR_reset__recovery_share_title_template;
|
MP_QSTR_reset__recovery_share_title_template;
|
||||||
MP_QSTR_reset__recovery_wallet_backup_title;
|
MP_QSTR_reset__recovery_wallet_backup_title;
|
||||||
|
MP_QSTR_reset__repeat_for_all_shares;
|
||||||
MP_QSTR_reset__required_number_of_groups;
|
MP_QSTR_reset__required_number_of_groups;
|
||||||
MP_QSTR_reset__select_correct_word;
|
MP_QSTR_reset__select_correct_word;
|
||||||
MP_QSTR_reset__select_threshold;
|
MP_QSTR_reset__select_threshold;
|
||||||
@ -541,6 +542,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_reset__tos_link;
|
MP_QSTR_reset__tos_link;
|
||||||
MP_QSTR_reset__total_number_of_shares_in_group_template;
|
MP_QSTR_reset__total_number_of_shares_in_group_template;
|
||||||
MP_QSTR_reset__use_your_backup;
|
MP_QSTR_reset__use_your_backup;
|
||||||
|
MP_QSTR_reset__words_may_repeat;
|
||||||
MP_QSTR_reset__words_written_down_template;
|
MP_QSTR_reset__words_written_down_template;
|
||||||
MP_QSTR_reset__write_down_words_template;
|
MP_QSTR_reset__write_down_words_template;
|
||||||
MP_QSTR_reset__wrong_word_selected;
|
MP_QSTR_reset__wrong_word_selected;
|
||||||
|
@ -1334,6 +1334,8 @@ pub enum TranslatedString {
|
|||||||
recovery__unlock_repeated_backup = 934, // "Create additional backup?"
|
recovery__unlock_repeated_backup = 934, // "Create additional backup?"
|
||||||
recovery__unlock_repeated_backup_verb = 935, // "Unlock backup"
|
recovery__unlock_repeated_backup_verb = 935, // "Unlock backup"
|
||||||
homescreen__set_default = 936, // "Do you really want to set default homescreen image?"
|
homescreen__set_default = 936, // "Do you really want to set default homescreen image?"
|
||||||
|
reset__words_may_repeat = 937, // "Words may repeat."
|
||||||
|
reset__repeat_for_all_shares = 938, // "Repeat for all shares."
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TranslatedString {
|
impl TranslatedString {
|
||||||
@ -2663,6 +2665,8 @@ impl TranslatedString {
|
|||||||
Self::recovery__unlock_repeated_backup => "Create additional backup?",
|
Self::recovery__unlock_repeated_backup => "Create additional backup?",
|
||||||
Self::recovery__unlock_repeated_backup_verb => "Unlock backup",
|
Self::recovery__unlock_repeated_backup_verb => "Unlock backup",
|
||||||
Self::homescreen__set_default => "Do you really want to set default homescreen image?",
|
Self::homescreen__set_default => "Do you really want to set default homescreen image?",
|
||||||
|
Self::reset__words_may_repeat => "Words may repeat.",
|
||||||
|
Self::reset__repeat_for_all_shares => "Repeat for all shares.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3993,6 +3997,8 @@ impl TranslatedString {
|
|||||||
Qstr::MP_QSTR_recovery__unlock_repeated_backup => Some(Self::recovery__unlock_repeated_backup),
|
Qstr::MP_QSTR_recovery__unlock_repeated_backup => Some(Self::recovery__unlock_repeated_backup),
|
||||||
Qstr::MP_QSTR_recovery__unlock_repeated_backup_verb => Some(Self::recovery__unlock_repeated_backup_verb),
|
Qstr::MP_QSTR_recovery__unlock_repeated_backup_verb => Some(Self::recovery__unlock_repeated_backup_verb),
|
||||||
Qstr::MP_QSTR_homescreen__set_default => Some(Self::homescreen__set_default),
|
Qstr::MP_QSTR_homescreen__set_default => Some(Self::homescreen__set_default),
|
||||||
|
Qstr::MP_QSTR_reset__words_may_repeat => Some(Self::reset__words_may_repeat),
|
||||||
|
Qstr::MP_QSTR_reset__repeat_for_all_shares => Some(Self::reset__repeat_for_all_shares),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequestCode,
|
button_request::ButtonRequestCode,
|
||||||
component::{
|
component::{
|
||||||
swipe_detect::SwipeSettings,
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, Paragraphs},
|
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt},
|
||||||
ButtonRequestExt, ComponentExt, SwipeDirection,
|
ButtonRequestExt, ComponentExt, SwipeDirection,
|
||||||
},
|
},
|
||||||
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
flow::{base::Decision, flow_store, FlowMsg, FlowState, FlowStore, SwipeFlow},
|
||||||
@ -24,7 +24,6 @@ use super::super::{
|
|||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
||||||
pub enum ShowShareWords {
|
pub enum ShowShareWords {
|
||||||
// TODO: potentially also add there the 'never put anywhere digital' warning?
|
|
||||||
Instruction,
|
Instruction,
|
||||||
Words,
|
Words,
|
||||||
Confirm,
|
Confirm,
|
||||||
@ -80,16 +79,23 @@ impl ShowShareWords {
|
|||||||
let subtitle: TString = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into()?;
|
let subtitle: TString = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into()?;
|
||||||
let share_words_obj: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
|
let share_words_obj: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
|
||||||
let share_words_vec: Vec<TString, 33> = util::iter_into_vec(share_words_obj)?;
|
let share_words_vec: Vec<TString, 33> = util::iter_into_vec(share_words_obj)?;
|
||||||
let text_info: TString = kwargs.get(Qstr::MP_QSTR_text_info)?.try_into()?;
|
let text_info: Obj = kwargs.get(Qstr::MP_QSTR_text_info)?;
|
||||||
let text_confirm: TString = kwargs.get(Qstr::MP_QSTR_text_confirm)?.try_into()?;
|
let text_confirm: TString = kwargs.get(Qstr::MP_QSTR_text_confirm)?.try_into()?;
|
||||||
let nwords = share_words_vec.len();
|
let nwords = share_words_vec.len();
|
||||||
|
|
||||||
|
let mut instructions_paragraphs = ParagraphVecShort::new();
|
||||||
|
for item in IterBuf::new().try_iterate(text_info)? {
|
||||||
|
let text: TString = item.try_into()?;
|
||||||
|
instructions_paragraphs.add(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text));
|
||||||
|
}
|
||||||
|
let paragraphs_spacing = 8;
|
||||||
let content_instruction = Frame::left_aligned(
|
let content_instruction = Frame::left_aligned(
|
||||||
title,
|
title,
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
SwipeContent::new(
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
instructions_paragraphs
|
||||||
text_info,
|
.into_paragraphs()
|
||||||
))),
|
.with_spacing(paragraphs_spacing),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.with_subtitle(TR::words__instructions.into())
|
.with_subtitle(TR::words__instructions.into())
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
|
@ -1688,7 +1688,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// title: str,
|
/// title: str,
|
||||||
/// subtitle: str,
|
/// subtitle: str,
|
||||||
/// words: Iterable[str],
|
/// words: Iterable[str],
|
||||||
/// text_info: str,
|
/// text_info: Iterable[str],
|
||||||
/// text_confirm: str,
|
/// text_confirm: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Show wallet backup words preceded by an instruction screen and followed by
|
/// """Show wallet backup words preceded by an instruction screen and followed by
|
||||||
|
@ -402,7 +402,7 @@ def flow_show_share_words(
|
|||||||
title: str,
|
title: str,
|
||||||
subtitle: str,
|
subtitle: str,
|
||||||
words: Iterable[str],
|
words: Iterable[str],
|
||||||
text_info: str,
|
text_info: Iterable[str],
|
||||||
text_confirm: str,
|
text_confirm: str,
|
||||||
) -> LayoutObj[UiResult]:
|
) -> LayoutObj[UiResult]:
|
||||||
"""Show wallet backup words preceded by an instruction screen and followed by
|
"""Show wallet backup words preceded by an instruction screen and followed by
|
||||||
|
@ -638,6 +638,7 @@ class TR:
|
|||||||
reset__only_one_share_will_be_created: str = "Only one share will be created."
|
reset__only_one_share_will_be_created: str = "Only one share will be created."
|
||||||
reset__recovery_share_title_template: str = "Recovery share #{0}"
|
reset__recovery_share_title_template: str = "Recovery share #{0}"
|
||||||
reset__recovery_wallet_backup_title: str = "Wallet backup"
|
reset__recovery_wallet_backup_title: str = "Wallet backup"
|
||||||
|
reset__repeat_for_all_shares: str = "Repeat for all shares."
|
||||||
reset__required_number_of_groups: str = "The required number of groups for recovery."
|
reset__required_number_of_groups: str = "The required number of groups for recovery."
|
||||||
reset__select_correct_word: str = "Select the correct word for each position."
|
reset__select_correct_word: str = "Select the correct word for each position."
|
||||||
reset__select_threshold: str = "Select the minimum shares required to recover your wallet."
|
reset__select_threshold: str = "Select the minimum shares required to recover your wallet."
|
||||||
@ -676,6 +677,7 @@ class TR:
|
|||||||
reset__tos_link: str = "trezor.io/tos"
|
reset__tos_link: str = "trezor.io/tos"
|
||||||
reset__total_number_of_shares_in_group_template: str = "Set the total number of shares in Group {0}."
|
reset__total_number_of_shares_in_group_template: str = "Set the total number of shares in Group {0}."
|
||||||
reset__use_your_backup: str = "Use your backup when you need to recover your wallet."
|
reset__use_your_backup: str = "Use your backup when you need to recover your wallet."
|
||||||
|
reset__words_may_repeat: str = "Words may repeat."
|
||||||
reset__words_written_down_template: str = "I wrote down all {0} words in order."
|
reset__words_written_down_template: str = "I wrote down all {0} words in order."
|
||||||
reset__write_down_words_template: str = "Write the following {0} words in order on your wallet backup card."
|
reset__write_down_words_template: str = "Write the following {0} words in order on your wallet backup card."
|
||||||
reset__wrong_word_selected: str = "Wrong word selected!"
|
reset__wrong_word_selected: str = "Wrong word selected!"
|
||||||
|
@ -32,7 +32,13 @@ async def show_share_words(
|
|||||||
group_index + 1, share_index + 1
|
group_index + 1, share_index + 1
|
||||||
)
|
)
|
||||||
words_count = len(share_words)
|
words_count = len(share_words)
|
||||||
text_info = TR.reset__write_down_words_template.format(words_count)
|
text_info = [TR.reset__write_down_words_template.format(words_count)]
|
||||||
|
if words_count == 20 and share_index is None:
|
||||||
|
# 1-of-1 SLIP39: inform the user about repeated words
|
||||||
|
text_info.append(TR.reset__words_may_repeat)
|
||||||
|
if share_index == 0:
|
||||||
|
# regular SLIP39, 1st share
|
||||||
|
text_info.append(TR.reset__repeat_for_all_shares)
|
||||||
text_confirm = TR.reset__words_written_down_template.format(words_count)
|
text_confirm = TR.reset__words_written_down_template.format(words_count)
|
||||||
|
|
||||||
result = await RustLayout(
|
result = await RustLayout(
|
||||||
|
@ -642,6 +642,7 @@
|
|||||||
"reset__only_one_share_will_be_created": "Only one share will be created.",
|
"reset__only_one_share_will_be_created": "Only one share will be created.",
|
||||||
"reset__recovery_share_title_template": "Recovery share #{0}",
|
"reset__recovery_share_title_template": "Recovery share #{0}",
|
||||||
"reset__recovery_wallet_backup_title": "Wallet backup",
|
"reset__recovery_wallet_backup_title": "Wallet backup",
|
||||||
|
"reset__repeat_for_all_shares": "Repeat for all shares.",
|
||||||
"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.",
|
||||||
@ -680,6 +681,7 @@
|
|||||||
"reset__tos_link": "trezor.io/tos",
|
"reset__tos_link": "trezor.io/tos",
|
||||||
"reset__total_number_of_shares_in_group_template": "Set the total number of shares in Group {0}.",
|
"reset__total_number_of_shares_in_group_template": "Set the total number of shares in Group {0}.",
|
||||||
"reset__use_your_backup": "Use your backup when you need to recover your wallet.",
|
"reset__use_your_backup": "Use your backup when you need to recover your wallet.",
|
||||||
|
"reset__words_may_repeat": "Words may repeat.",
|
||||||
"reset__words_written_down_template": "I wrote down all {0} words in order.",
|
"reset__words_written_down_template": "I wrote down all {0} words in order.",
|
||||||
"reset__write_down_words_template": "Write the following {0} words in order on your wallet backup card.",
|
"reset__write_down_words_template": "Write the following {0} words in order on your wallet backup card.",
|
||||||
"reset__wrong_word_selected": "Wrong word selected!",
|
"reset__wrong_word_selected": "Wrong word selected!",
|
||||||
|
@ -935,5 +935,7 @@
|
|||||||
"933": "recovery__title_unlock_repeated_backup",
|
"933": "recovery__title_unlock_repeated_backup",
|
||||||
"934": "recovery__unlock_repeated_backup",
|
"934": "recovery__unlock_repeated_backup",
|
||||||
"935": "recovery__unlock_repeated_backup_verb",
|
"935": "recovery__unlock_repeated_backup_verb",
|
||||||
"936": "homescreen__set_default"
|
"936": "homescreen__set_default",
|
||||||
|
"937": "reset__words_may_repeat",
|
||||||
|
"938": "reset__repeat_for_all_shares"
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"current": {
|
"current": {
|
||||||
"merkle_root": "7a115e582a5f5f09b1850946030762360f55e516a60cf960dffc9ba174c2e4d2",
|
"merkle_root": "405ce2be8dcb492a1d4b25ec8aaeaa9914ff88594151beaceea52315172b11d0",
|
||||||
"datetime": "2024-06-02T11:07:12.183601",
|
"datetime": "2024-06-03T12:40:07.498873",
|
||||||
"commit": "66496206ccbe9583203fbfebf8c9222e8c6379b8"
|
"commit": "2ac4967ef190dac1fe238cc00878ff2d08e17bb5"
|
||||||
},
|
},
|
||||||
"history": [
|
"history": [
|
||||||
{
|
{
|
||||||
|
@ -1554,7 +1554,9 @@ class InputFlowSlip39BasicResetRecovery(InputFlowBase):
|
|||||||
# 6. threshold info
|
# 6. threshold info
|
||||||
# 7. Set & confirm threshold value
|
# 7. Set & confirm threshold value
|
||||||
# 8. Confirm show seeds
|
# 8. Confirm show seeds
|
||||||
yield from click_through(self.debug, screens=9, code=B.ResetDevice)
|
# 9. Warning
|
||||||
|
# 10. Instructions
|
||||||
|
yield from click_through(self.debug, screens=10, code=B.ResetDevice)
|
||||||
|
|
||||||
# Mnemonic phrases
|
# Mnemonic phrases
|
||||||
self.mnemonics = yield from load_N_shares(self.debug, 5)
|
self.mnemonics = yield from load_N_shares(self.debug, 5)
|
||||||
|
Loading…
Reference in New Issue
Block a user