diff --git a/core/embed/extmod/modtrezorui/fonts/font_unifont_bold_16.h b/core/embed/extmod/modtrezorui/fonts/font_unifont_bold_16.h index c28e0048d6..9d425d4ab5 100644 --- a/core/embed/extmod/modtrezorui/fonts/font_unifont_bold_16.h +++ b/core/embed/extmod/modtrezorui/fonts/font_unifont_bold_16.h @@ -3,8 +3,8 @@ #if TREZOR_FONT_BPP != 1 #error Wrong TREZOR_FONT_BPP (expected 1) #endif -#define Font_Unifont_Bold_16_HEIGHT 16 -#define Font_Unifont_Bold_16_MAX_HEIGHT 15 +#define Font_Unifont_Bold_16_HEIGHT 12 // <--- 12 from 16 +#define Font_Unifont_Bold_16_MAX_HEIGHT 12 // <--- 12 from 15 #define Font_Unifont_Bold_16_BASELINE 2 extern const uint8_t* const Font_Unifont_Bold_16[126 + 1 - 32]; extern const uint8_t Font_Unifont_Bold_16_glyph_nonprintable[]; diff --git a/core/embed/extmod/modtrezorui/fonts/font_unifont_regular_16.h b/core/embed/extmod/modtrezorui/fonts/font_unifont_regular_16.h index f9a1ec2c1c..b01b1cff67 100644 --- a/core/embed/extmod/modtrezorui/fonts/font_unifont_regular_16.h +++ b/core/embed/extmod/modtrezorui/fonts/font_unifont_regular_16.h @@ -3,8 +3,8 @@ #if TREZOR_FONT_BPP != 1 #error Wrong TREZOR_FONT_BPP (expected 1) #endif -#define Font_Unifont_Regular_16_HEIGHT 16 -#define Font_Unifont_Regular_16_MAX_HEIGHT 15 +#define Font_Unifont_Regular_16_HEIGHT 12 // <--- 12 from 16 +#define Font_Unifont_Regular_16_MAX_HEIGHT 12 // <--- 12 from 15 #define Font_Unifont_Regular_16_BASELINE 2 extern const uint8_t* const Font_Unifont_Regular_16[126 + 1 - 32]; extern const uint8_t Font_Unifont_Regular_16_glyph_nonprintable[]; diff --git a/core/embed/rust/src/ui/model_tr/component/bip39.rs b/core/embed/rust/src/ui/model_tr/component/bip39.rs index 2193b6f9fa..9339dd8abb 100644 --- a/core/embed/rust/src/ui/model_tr/component/bip39.rs +++ b/core/embed/rust/src/ui/model_tr/component/bip39.rs @@ -136,7 +136,7 @@ impl Bip39Entry { let choices = ChoiceFactoryBIP39::letters(letter_choices.clone()); Self { - choice_page: ChoicePage::new(choices).with_incomplete(), + choice_page: ChoicePage::new(choices).with_incomplete(true), chosen_letters: Child::new(ChangingTextLine::center_mono(String::from(PROMPT))), letter_choices, textbox: TextBox::empty(), diff --git a/core/embed/rust/src/ui/model_tr/component/button.rs b/core/embed/rust/src/ui/model_tr/component/button.rs index fa96c6c547..7a9635067c 100644 --- a/core/embed/rust/src/ui/model_tr/component/button.rs +++ b/core/embed/rust/src/ui/model_tr/component/button.rs @@ -661,6 +661,11 @@ impl ButtonLayout<&'static str> { Some(ButtonDetails::text(text).with_duration(duration)), ) } + + /// Only right arrow facing down. + pub fn only_arrow_down() -> Self { + Self::new(None, None, Some(ButtonDetails::down_arrow_icon_wide())) + } } /// What happens when a button is triggered. @@ -789,6 +794,11 @@ impl ButtonActions { ) } + /// Only going to the next page with right + pub fn only_next() -> Self { + Self::new(None, None, Some(ButtonAction::NextPage)) + } + /// Cancelling with left, confirming with right pub fn cancel_confirm() -> Self { Self::new( diff --git a/core/embed/rust/src/ui/model_tr/component/choice.rs b/core/embed/rust/src/ui/model_tr/component/choice.rs index 312b1502af..55406967c8 100644 --- a/core/embed/rust/src/ui/model_tr/component/choice.rs +++ b/core/embed/rust/src/ui/model_tr/component/choice.rs @@ -58,6 +58,8 @@ where /// Whether we should show items on left/right even when they cannot /// be painted entirely (they would be cut off). show_incomplete: bool, + /// Whether to show only the currently selected item, nothing left/right. + show_only_one_item: bool, /// Whether the middle selected item should be painted with /// inverse colors - black on white. inverse_selected_item: bool, @@ -79,6 +81,7 @@ where items_distance: DEFAULT_ITEMS_DISTANCE, is_carousel: false, show_incomplete: false, + show_only_one_item: false, inverse_selected_item: false, } } @@ -90,14 +93,20 @@ where } /// Enabling the carousel mode. - pub fn with_carousel(mut self) -> Self { - self.is_carousel = true; + pub fn with_carousel(mut self, carousel: bool) -> Self { + self.is_carousel = carousel; self } /// Show incomplete items, even when they cannot render in their entirety. - pub fn with_incomplete(mut self) -> Self { - self.show_incomplete = true; + pub fn with_incomplete(mut self, show_incomplete: bool) -> Self { + self.show_incomplete = show_incomplete; + self + } + + /// Show only the currently selected item, nothing left/right. + pub fn with_only_one_item(mut self, only_one_item: bool) -> Self { + self.show_only_one_item = only_one_item; self } @@ -152,6 +161,11 @@ where // Drawing the current item in the middle. self.show_current_choice(available_area); + // Not drawing the rest when not wanted + if self.show_only_one_item { + return; + } + // Getting the remaining left and right areas. let (left_area, _center_area, right_area) = available_area.split_center(self.current_choice().width_center()); diff --git a/core/embed/rust/src/ui/model_tr/component/choice_item.rs b/core/embed/rust/src/ui/model_tr/component/choice_item.rs index 511945dc49..ec3cbe15ed 100644 --- a/core/embed/rust/src/ui/model_tr/component/choice_item.rs +++ b/core/embed/rust/src/ui/model_tr/component/choice_item.rs @@ -84,7 +84,7 @@ impl ChoiceItem { area.bottom_center() + Offset::new(-self.width_center() / 2 - bound, bound + 1); let outline_size = Offset::new( self.width_center() + 2 * bound, - self.font.text_height() + 2 * bound - 3, // -3 because font is actually smaller + self.font.text_height() + 2 * bound, ); let outline = Rect::from_bottom_left_and_size(left_bottom, outline_size); if inverse { diff --git a/core/embed/rust/src/ui/model_tr/component/pin.rs b/core/embed/rust/src/ui/model_tr/component/pin.rs index a7e0647173..97cef259f1 100644 --- a/core/embed/rust/src/ui/model_tr/component/pin.rs +++ b/core/embed/rust/src/ui/model_tr/component/pin.rs @@ -99,7 +99,7 @@ impl PinEntry { // Starting at the digit 0 choice_page: ChoicePage::new(choices) .with_initial_page_counter(PROMPT_INDEX as u8 + 1) - .with_carousel(), + .with_carousel(true), pin_dots: Child::new(ChangingTextLine::center_mono(String::new())), show_real_pin: false, textbox: TextBox::empty(), diff --git a/core/embed/rust/src/ui/model_tr/component/simple_choice.rs b/core/embed/rust/src/ui/model_tr/component/simple_choice.rs index c5485c8822..f452585821 100644 --- a/core/embed/rust/src/ui/model_tr/component/simple_choice.rs +++ b/core/embed/rust/src/ui/model_tr/component/simple_choice.rs @@ -15,14 +15,15 @@ pub enum SimpleChoiceMsg { struct ChoiceFactorySimple { choices: Vec, + carousel: bool, } impl ChoiceFactorySimple where T: AsRef, { - fn new(choices: Vec) -> Self { - Self { choices } + fn new(choices: Vec, carousel: bool) -> Self { + Self { choices, carousel } } } @@ -34,11 +35,13 @@ where let text = &self.choices[choice_index as usize]; let mut choice_item = ChoiceItem::new(text, ButtonLayout::default_three_icons()); - // Disabling prev/next buttons for the first/last choice. - if choice_index == 0 { - choice_item.set_left_btn(None); - } else if choice_index as usize == N - 1 { - choice_item.set_right_btn(None); + // Disabling prev/next buttons for the first/last choice when not in carousel. + if !self.carousel { + if choice_index == 0 { + choice_item.set_left_btn(None); + } else if choice_index as usize == N - 1 { + choice_item.set_right_btn(None); + } } choice_item @@ -65,11 +68,13 @@ where T: AsRef, T: Clone, { - pub fn new(str_choices: Vec) -> Self { - let choices = ChoiceFactorySimple::new(str_choices.clone()); + pub fn new(str_choices: Vec, carousel: bool, show_incomplete: bool) -> Self { + let choices = ChoiceFactorySimple::new(str_choices.clone(), carousel); Self { choices: str_choices, - choice_page: ChoicePage::new(choices), + choice_page: ChoicePage::new(choices) + .with_carousel(carousel) + .with_incomplete(show_incomplete), } } } diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs index 972da373ca..556ea57ace 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -473,11 +473,11 @@ extern "C" fn show_share_words(n_args: usize, args: *const Obj, kwargs: *mut Map ) .text_bold("Write all words in order on recovery seed card.".into()) .newline() - .newline() + .newline_half() .text_mono("Do NOT make digital copies.".into()), 1 => Page::<10>::new( - ButtonLayout::cancel_and_arrow_down(), - ButtonActions::cancel_next(), + ButtonLayout::only_arrow_down(), + ButtonActions::only_next(), Font::NORMAL, ) .text_normal(share_words.clone()), @@ -506,7 +506,10 @@ extern "C" fn select_word(n_args: usize, args: *const Obj, kwargs: *mut Map) -> let words: Vec = iter_into_vec(words_iterable)?; // TODO: should return int, to be consistent with TT's select_word - let obj = LayoutObj::new(Frame::new(title, SimpleChoice::new(words).into_child()))?; + let obj = LayoutObj::new(Frame::new( + title, + SimpleChoice::new(words, true, true).into_child(), + ))?; Ok(obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } @@ -518,7 +521,10 @@ extern "C" fn request_word_count(n_args: usize, args: *const Obj, kwargs: *mut M let choices: Vec<&str, 5> = ["12", "18", "20", "24", "33"].into_iter().collect(); - let obj = LayoutObj::new(Frame::new(title, SimpleChoice::new(choices).into_child()))?; + let obj = LayoutObj::new(Frame::new( + title, + SimpleChoice::new(choices, true, false).into_child(), + ))?; Ok(obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } diff --git a/core/src/apps/management/reset_device/layout.py b/core/src/apps/management/reset_device/layout.py index f7454a965d..f3cc5ba757 100644 --- a/core/src/apps/management/reset_device/layout.py +++ b/core/src/apps/management/reset_device/layout.py @@ -3,7 +3,7 @@ from typing import Sequence from trezor import ui, utils, wire from trezor.crypto import random from trezor.enums import ButtonRequestType -from trezor.ui.layouts import confirm_action, confirm_blob, show_success, show_warning +from trezor.ui.layouts import confirm_blob, show_success, show_warning from trezor.ui.layouts.reset import ( # noqa: F401 select_word, show_share_words, diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index d540442a54..7796b3a1ca 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -590,7 +590,7 @@ async def confirm_backup(ctx: wire.GenericContext) -> bool: confirmed = await get_bool( ctx=ctx, title="WARNING", - data="Are you sure you want to skip the backup?\n\n", + data="Are you sure you want to skip the backup?\n", description="You can back up your Trezor once, at any time.", verb="BACK UP", verb_cancel="SKIP",