mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-24 15:38:22 +00:00
WIP - add DELETE option in recovery words
This commit is contained in:
parent
cd0c4d1cbd
commit
96d0a7b2e7
@ -497,11 +497,11 @@ impl ButtonLayout {
|
||||
|
||||
/// Default button layout for all three buttons - icons.
|
||||
pub fn default_three_icons() -> Self {
|
||||
Self::arrow_armed_icon("SELECT".into())
|
||||
Self::arrow_armed_arrow("SELECT".into())
|
||||
}
|
||||
|
||||
/// Special middle text for default icon layout.
|
||||
pub fn arrow_armed_icon(text: StrBuffer) -> Self {
|
||||
pub fn arrow_armed_arrow(text: StrBuffer) -> Self {
|
||||
Self::new(
|
||||
Some(ButtonDetails::left_arrow_icon()),
|
||||
Some(ButtonDetails::armed_text(text)),
|
||||
@ -518,6 +518,15 @@ impl ButtonLayout {
|
||||
)
|
||||
}
|
||||
|
||||
/// Middle armed text and next right arrow.
|
||||
pub fn none_armed_arrow(text: StrBuffer) -> Self {
|
||||
Self::new(
|
||||
None,
|
||||
Some(ButtonDetails::armed_text(text)),
|
||||
Some(ButtonDetails::right_arrow_icon()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Left cancel, armed text and right text.
|
||||
pub fn cancel_armed_text(middle: StrBuffer, right: StrBuffer) -> Self {
|
||||
Self::new(
|
||||
|
@ -156,12 +156,12 @@ where
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
new_choices: F,
|
||||
reset_page_counter: bool,
|
||||
new_page_counter: Option<u8>,
|
||||
is_carousel: bool,
|
||||
) {
|
||||
self.choices = new_choices;
|
||||
if reset_page_counter {
|
||||
self.page_counter = 0;
|
||||
if let Some(new_counter) = new_page_counter {
|
||||
self.page_counter = new_counter;
|
||||
}
|
||||
self.is_carousel = is_carousel;
|
||||
self.update(ctx);
|
||||
|
@ -135,7 +135,7 @@ impl ChoiceFactoryPassphrase {
|
||||
/// return back
|
||||
fn get_character_item(&self, choice_index: u8) -> ChoiceItem {
|
||||
if is_menu_choice(&self.current_category, choice_index) {
|
||||
ChoiceItem::new("MENU", ButtonLayout::arrow_armed_icon("RETURN".into()))
|
||||
ChoiceItem::new("MENU", ButtonLayout::arrow_armed_arrow("RETURN".into()))
|
||||
} else {
|
||||
let ch = get_char(&self.current_category, choice_index);
|
||||
ChoiceItem::new(char_to_string::<1>(ch), ButtonLayout::default_three_icons())
|
||||
@ -211,7 +211,7 @@ impl PassphraseEntry {
|
||||
/// Displaying the MENU
|
||||
fn show_menu_page(&mut self, ctx: &mut EventCtx) {
|
||||
let menu_choices = ChoiceFactoryPassphrase::new(ChoiceCategory::Menu);
|
||||
self.choice_page.reset(ctx, menu_choices, true, false);
|
||||
self.choice_page.reset(ctx, menu_choices, Some(0), false);
|
||||
// Going back to the last MENU position before showing the MENU
|
||||
self.choice_page.set_page_counter(ctx, self.menu_position);
|
||||
}
|
||||
@ -219,7 +219,7 @@ impl PassphraseEntry {
|
||||
/// Displaying the character category
|
||||
fn show_category_page(&mut self, ctx: &mut EventCtx) {
|
||||
let category_choices = ChoiceFactoryPassphrase::new(self.current_category.clone());
|
||||
self.choice_page.reset(ctx, category_choices, true, true);
|
||||
self.choice_page.reset(ctx, category_choices, Some(0), true);
|
||||
}
|
||||
|
||||
pub fn passphrase(&self) -> &str {
|
||||
|
@ -24,6 +24,12 @@ const MAX_LETTERS_LENGTH: usize = 26;
|
||||
/// Offer words when there will be fewer of them than this
|
||||
const OFFER_WORDS_THRESHOLD: usize = 10;
|
||||
|
||||
/// Where will be the DELETE option - at the first position
|
||||
const DELETE_INDEX: u8 = 0;
|
||||
/// Which index will be used at the beginning.
|
||||
/// (Accounts for DELETE to be at index 0)
|
||||
const INITIAL_PAGE_COUNTER: u8 = DELETE_INDEX + 1;
|
||||
|
||||
const PROMPT: &str = "_";
|
||||
|
||||
/// Type of the wordlist, deciding the list of words to be used
|
||||
@ -61,13 +67,15 @@ impl ChoiceFactory for ChoiceFactoryWordlist {
|
||||
|
||||
fn get(&self, choice_index: u8) -> ChoiceItem {
|
||||
// Letters have a carousel, words do not
|
||||
// Putting DELETE as the first option in both cases
|
||||
// (is a requirement for WORDS, doing it for LETTERS as well to unite it)
|
||||
match self {
|
||||
Self::Letters(letter_choices) => {
|
||||
if choice_index >= letter_choices.len() as u8 {
|
||||
ChoiceItem::new("DELETE", ButtonLayout::arrow_armed_icon("CONFIRM".into()))
|
||||
if choice_index == DELETE_INDEX {
|
||||
ChoiceItem::new("DELETE", ButtonLayout::arrow_armed_arrow("CONFIRM".into()))
|
||||
.with_icon(Icon::new(theme::ICON_DELETE))
|
||||
} else {
|
||||
let letter = letter_choices[choice_index as usize];
|
||||
let letter = letter_choices[choice_index as usize - 1];
|
||||
ChoiceItem::new(
|
||||
char_to_string::<1>(letter),
|
||||
ButtonLayout::default_three_icons(),
|
||||
@ -75,17 +83,14 @@ impl ChoiceFactory for ChoiceFactoryWordlist {
|
||||
}
|
||||
}
|
||||
Self::Words(word_choices) => {
|
||||
if choice_index >= word_choices.len() as u8 {
|
||||
let mut item =
|
||||
ChoiceItem::new("DELETE", ButtonLayout::arrow_armed_icon("CONFIRM".into()))
|
||||
.with_icon(Icon::new(theme::ICON_DELETE));
|
||||
item.set_right_btn(None);
|
||||
item
|
||||
if choice_index == DELETE_INDEX {
|
||||
ChoiceItem::new("DELETE", ButtonLayout::none_armed_arrow("CONFIRM".into()))
|
||||
.with_icon(Icon::new(theme::ICON_DELETE))
|
||||
} else {
|
||||
let word = word_choices[choice_index as usize];
|
||||
let word = word_choices[choice_index as usize - 1];
|
||||
let mut item = ChoiceItem::new(word, ButtonLayout::default_three_icons());
|
||||
if choice_index == 0 {
|
||||
item.set_left_btn(None);
|
||||
if choice_index == self.count() - 1 {
|
||||
item.set_right_btn(None);
|
||||
}
|
||||
item
|
||||
}
|
||||
@ -113,9 +118,11 @@ impl WordlistEntry {
|
||||
let choices = ChoiceFactoryWordlist::letters(letter_choices.clone());
|
||||
|
||||
Self {
|
||||
// Starting at second page because of DELETE option
|
||||
choice_page: ChoicePage::new(choices)
|
||||
.with_incomplete(true)
|
||||
.with_carousel(true),
|
||||
.with_carousel(true)
|
||||
.with_initial_page_counter(INITIAL_PAGE_COUNTER),
|
||||
chosen_letters: Child::new(ChangingTextLine::center_mono(String::from(PROMPT))),
|
||||
letter_choices,
|
||||
textbox: TextBox::empty(),
|
||||
@ -160,8 +167,12 @@ impl WordlistEntry {
|
||||
let new_choices = self.get_current_choices();
|
||||
// Not using carousel in case of words, as that looks weird in case
|
||||
// there is only one word to choose from.
|
||||
self.choice_page
|
||||
.reset(ctx, new_choices, true, !self.offer_words);
|
||||
self.choice_page.reset(
|
||||
ctx,
|
||||
new_choices,
|
||||
Some(INITIAL_PAGE_COUNTER),
|
||||
!self.offer_words,
|
||||
);
|
||||
ctx.request_paint();
|
||||
}
|
||||
|
||||
@ -211,21 +222,21 @@ impl Component for WordlistEntry {
|
||||
// Clicked SELECT.
|
||||
// When we already offer words, return the word at the given index.
|
||||
// Otherwise, resetting the choice page with up-to-date choices.
|
||||
if page_counter as usize == self.delete_index() {
|
||||
if page_counter == DELETE_INDEX {
|
||||
// Clicked DELETE. Deleting last letter, updating wordlist and updating choices
|
||||
self.delete_last_letter(ctx);
|
||||
self.reset_wordlist();
|
||||
self.update(ctx);
|
||||
} else if self.offer_words {
|
||||
let word = self
|
||||
.words_list
|
||||
.get(page_counter as usize)
|
||||
.unwrap_or_default();
|
||||
return Some(WordlistEntryMsg::ResultWord(String::from(word)));
|
||||
} else {
|
||||
let new_letter = self.letter_choices[page_counter as usize];
|
||||
self.append_letter(ctx, new_letter);
|
||||
self.update(ctx);
|
||||
let index = page_counter as usize - 1;
|
||||
if self.offer_words {
|
||||
let word = self.words_list.get(index).unwrap_or_default();
|
||||
return Some(WordlistEntryMsg::ResultWord(String::from(word)));
|
||||
} else {
|
||||
let new_letter = self.letter_choices[index];
|
||||
self.append_letter(ctx, new_letter);
|
||||
self.update(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,16 +263,16 @@ impl crate::trace::Trace for WordlistEntry {
|
||||
ButtonPos::Left => ButtonAction::PrevPage.string(),
|
||||
ButtonPos::Right => ButtonAction::NextPage.string(),
|
||||
ButtonPos::Middle => {
|
||||
let current_index = self.choice_page.page_index() as usize;
|
||||
let choice: String<10> = if current_index == self.delete_index() {
|
||||
let current_index = self.choice_page.page_index();
|
||||
let choice: String<10> = if current_index == DELETE_INDEX {
|
||||
String::from("DELETE")
|
||||
} else if self.offer_words {
|
||||
self.words_list
|
||||
.get(current_index)
|
||||
.unwrap_or_default()
|
||||
.into()
|
||||
} else {
|
||||
util::char_to_string(self.letter_choices[current_index])
|
||||
let index = current_index as usize - 1;
|
||||
if self.offer_words {
|
||||
self.words_list.get(index).unwrap_or_default().into()
|
||||
} else {
|
||||
util::char_to_string(self.letter_choices[index])
|
||||
}
|
||||
};
|
||||
ButtonAction::select_item(choice)
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
} else {
|
||||
// Page in the middle
|
||||
(
|
||||
ButtonLayout::arrow_armed_icon("SELECT".into()),
|
||||
ButtonLayout::arrow_armed_arrow("SELECT".into()),
|
||||
ButtonActions::prev_confirm_next(),
|
||||
)
|
||||
};
|
||||
|
@ -1309,7 +1309,7 @@ async def pin_mismatch(
|
||||
ctx,
|
||||
br_type,
|
||||
"PIN MISMATCH",
|
||||
"The PINs you entered do not match.\nPlease try again.",
|
||||
description="The PINs you entered do not match.\nPlease try again.",
|
||||
verb="TRY AGAIN",
|
||||
verb_cancel=None,
|
||||
br_code=br_code,
|
||||
|
Loading…
Reference in New Issue
Block a user