Skip to content

Commit e3fcde1

Browse files
committed
feat(core/eckhart): add label keyboard layout
- utilize all passphrase input parameters - add label changing device menu action [no changelog]
1 parent e5e2e06 commit e3fcde1

File tree

33 files changed

+1056
-140
lines changed

33 files changed

+1056
-140
lines changed

core/embed/rust/librust_qstr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static void _librust_qstrs(void) {
3030
MP_QSTR_DONE;
3131
MP_QSTR_DeviceDisconnect;
3232
MP_QSTR_DeviceMenuResult;
33+
MP_QSTR_DeviceName;
3334
MP_QSTR_DevicePair;
3435
MP_QSTR_INFO;
3536
MP_QSTR_INITIAL;
@@ -97,6 +98,7 @@ static void _librust_qstrs(void) {
9798
MP_QSTR_address_label;
9899
MP_QSTR_address_qr;
99100
MP_QSTR_allow_cancel;
101+
MP_QSTR_allow_empty;
100102
MP_QSTR_allow_pairing;
101103
MP_QSTR_amount;
102104
MP_QSTR_amount_change;
@@ -266,6 +268,8 @@ static void _librust_qstrs(void) {
266268
MP_QSTR_details_title;
267269
MP_QSTR_device_name;
268270
MP_QSTR_device_name__change_template;
271+
MP_QSTR_device_name__continue_with_empty_label;
272+
MP_QSTR_device_name__enter;
269273
MP_QSTR_device_name__title;
270274
MP_QSTR_disable_animation;
271275
MP_QSTR_disconnect;
@@ -480,6 +484,7 @@ static void _librust_qstrs(void) {
480484
MP_QSTR_plurals__x_groups_needed;
481485
MP_QSTR_plurals__x_shares_needed;
482486
MP_QSTR_pm_event;
487+
MP_QSTR_prefill;
483488
MP_QSTR_prefill_word;
484489
MP_QSTR_progress__authenticity_check;
485490
MP_QSTR_progress__done;
@@ -494,6 +499,7 @@ static void _librust_qstrs(void) {
494499
MP_QSTR_progress_event;
495500
MP_QSTR_prompt;
496501
MP_QSTR_prompt_backup;
502+
MP_QSTR_prompt_empty;
497503
MP_QSTR_prompt_screen;
498504
MP_QSTR_prompt_title;
499505
MP_QSTR_pubkey;
@@ -565,6 +571,7 @@ static void _librust_qstrs(void) {
565571
MP_QSTR_request_passphrase;
566572
MP_QSTR_request_pin;
567573
MP_QSTR_request_slip39;
574+
MP_QSTR_request_string;
568575
MP_QSTR_reset__advanced_group_threshold_info;
569576
MP_QSTR_reset__all_x_of_y_template;
570577
MP_QSTR_reset__any_x_of_y_template;
@@ -892,6 +899,7 @@ static void _librust_qstrs(void) {
892899
MP_QSTR_words__keep_it_safe;
893900
MP_QSTR_words__know_what_your_doing;
894901
MP_QSTR_words__my_trezor;
902+
MP_QSTR_words__name;
895903
MP_QSTR_words__no;
896904
MP_QSTR_words__not_recommended;
897905
MP_QSTR_words__operation_cancelled;

core/embed/rust/src/translations/generated/translated_string.rs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/embed/rust/src/ui/api/firmware_micropython.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -753,9 +753,23 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
753753
extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
754754
let block = move |_args: &[Obj], kwargs: &Map| {
755755
let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
756-
let max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?;
756+
let prompt_empty: TString = kwargs.get(Qstr::MP_QSTR_prompt_empty)?.try_into()?;
757+
let max_len: usize = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?;
757758

758-
let layout = ModelUI::request_passphrase(prompt, max_len)?;
759+
let layout = ModelUI::request_passphrase(prompt, prompt_empty, max_len)?;
760+
Ok(LayoutObj::new_root(layout)?.into())
761+
};
762+
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
763+
}
764+
765+
extern "C" fn new_request_string(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
766+
let block = move |_args: &[Obj], kwargs: &Map| {
767+
let prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
768+
let max_len: usize = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?;
769+
let allow_empty: bool = kwargs.get(Qstr::MP_QSTR_allow_empty)?.try_into()?;
770+
let prefill: Option<TString> = kwargs.get(Qstr::MP_QSTR_prefill)?.try_into_option()?;
771+
772+
let layout = ModelUI::request_string(prompt, max_len, allow_empty, prefill)?;
759773
Ok(LayoutObj::new_root(layout)?.into())
760774
};
761775
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@@ -924,7 +938,8 @@ extern "C" fn new_show_device_menu(n_args: usize, args: *const Obj, kwargs: *mut
924938
let block = move |_args: &[Obj], kwargs: &Map| {
925939
let failed_backup: bool = kwargs.get(Qstr::MP_QSTR_failed_backup)?.try_into()?;
926940
let firmware_version: TString = kwargs.get(Qstr::MP_QSTR_firmware_version)?.try_into()?;
927-
let device_name: TString = kwargs.get(Qstr::MP_QSTR_device_name)?.try_into()?;
941+
let device_name: Option<TString> =
942+
kwargs.get(Qstr::MP_QSTR_device_name)?.try_into_option()?;
928943
let paired_devices: Obj = kwargs.get(Qstr::MP_QSTR_paired_devices)?;
929944
let paired_devices: Vec<TString, 1> = util::iter_into_vec(paired_devices)?;
930945
let auto_lock_delay: TString<'static> =
@@ -1749,11 +1764,22 @@ pub static mp_module_trezorui_api: Module = obj_module! {
17491764
/// def request_passphrase(
17501765
/// *,
17511766
/// prompt: str,
1767+
/// prompt_empty: str,
17521768
/// max_len: int,
17531769
/// ) -> LayoutObj[str | UiResult]:
17541770
/// """Passphrase input keyboard."""
17551771
Qstr::MP_QSTR_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(),
17561772

1773+
/// def request_string(
1774+
/// *,
1775+
/// prompt: str,
1776+
/// max_len: int,
1777+
/// allow_empty: bool,
1778+
/// prefill: str | None,
1779+
/// ) -> LayoutObj[str | UiResult]:
1780+
/// """Label input keyboard."""
1781+
Qstr::MP_QSTR_request_string => obj_fn_kw!(0, new_request_string).as_obj(),
1782+
17571783
/// def select_menu(
17581784
/// *,
17591785
/// items: Iterable[str],
@@ -1853,7 +1879,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
18531879
/// *,
18541880
/// failed_backup: bool,
18551881
/// firmware_version: str,
1856-
/// device_name: str,
1882+
/// device_name: str | None,
18571883
/// paired_devices: Iterable[str],
18581884
/// auto_lock_delay: str,
18591885
/// ) -> LayoutObj[UiResult | DeviceMenuResult | tuple[DeviceMenuResult, int]]:
@@ -2058,5 +2084,6 @@ pub static mp_module_trezorui_api: Module = obj_module! {
20582084
/// WipeDevice: ClassVar[DeviceMenuResult]
20592085
/// ScreenBrightness: ClassVar[DeviceMenuResult]
20602086
/// AutoLockDelay: ClassVar[DeviceMenuResult]
2087+
/// DeviceName: ClassVar[DeviceMenuResult]
20612088
Qstr::MP_QSTR_DeviceMenuResult => DEVICE_MENU_RESULT.as_obj(),
20622089
};

core/embed/rust/src/ui/layout/device_menu_result.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub static CHECK_BACKUP: SimpleTypeObj = SimpleTypeObj::new(&DEVICE_MENU_RESULT_
1414
pub static WIPE_DEVICE: SimpleTypeObj = SimpleTypeObj::new(&DEVICE_MENU_RESULT_BASE_TYPE);
1515
pub static SCREEN_BRIGHTNESS: SimpleTypeObj = SimpleTypeObj::new(&DEVICE_MENU_RESULT_BASE_TYPE);
1616
pub static AUTO_LOCK_DELAY: SimpleTypeObj = SimpleTypeObj::new(&DEVICE_MENU_RESULT_BASE_TYPE);
17+
pub static DEVICE_NAME: SimpleTypeObj = SimpleTypeObj::new(&DEVICE_MENU_RESULT_BASE_TYPE);
1718

1819
// Create a DeviceMenuResult class that contains all result types
1920
static DEVICE_MENU_RESULT_TYPE: Type = obj_type! {
@@ -26,6 +27,7 @@ static DEVICE_MENU_RESULT_TYPE: Type = obj_type! {
2627
Qstr::MP_QSTR_WipeDevice => WIPE_DEVICE.as_obj(),
2728
Qstr::MP_QSTR_ScreenBrightness => SCREEN_BRIGHTNESS.as_obj(),
2829
Qstr::MP_QSTR_AutoLockDelay => AUTO_LOCK_DELAY.as_obj(),
30+
Qstr::MP_QSTR_DeviceName => DEVICE_NAME.as_obj(),
2931
} },
3032
};
3133

core/embed/rust/src/ui/layout_bolt/component/keyboard/passphrase.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct PassphraseKeyboard {
3535
keys: [Child<Button>; KEY_COUNT],
3636
scrollbar: ScrollBar,
3737
fade: Cell<bool>,
38+
max_len: usize,
3839
}
3940

4041
const STARTING_PAGE: usize = 1;
@@ -48,14 +49,13 @@ const KEYBOARD: [[&str; KEY_COUNT]; PAGE_COUNT] = [
4849
["_<>", ".:@", "/|\\", "!()", "+%&", "-[]", "?{}", ",'`", ";\"~", "$^="],
4950
];
5051

51-
const MAX_LENGTH: usize = 50;
5252
const INPUT_AREA_HEIGHT: i16 = ScrollBar::DOT_SIZE + 9;
5353

5454
impl PassphraseKeyboard {
55-
pub fn new() -> Self {
55+
pub fn new(max_len: usize) -> Self {
5656
Self {
5757
page_swipe: Swipe::horizontal(),
58-
input: Input::new().into_child(),
58+
input: Input::new(max_len).into_child(),
5959
confirm: Button::with_icon(theme::ICON_CONFIRM)
6060
.styled(theme::button_confirm())
6161
.into_child(),
@@ -73,6 +73,7 @@ impl PassphraseKeyboard {
7373
}),
7474
scrollbar: ScrollBar::horizontal(),
7575
fade: Cell::new(false),
76+
max_len,
7677
}
7778
}
7879

@@ -166,7 +167,7 @@ impl PassphraseKeyboard {
166167
/// We should disable the input when the passphrase has reached maximum
167168
/// length and we are not cycling through the characters.
168169
fn is_button_active(&self, key: usize) -> bool {
169-
let textbox_not_full = self.input.inner().textbox.len() < MAX_LENGTH;
170+
let textbox_not_full = self.input.inner().textbox.len() < self.max_len;
170171
let key_is_pending = {
171172
if let Some(pending) = self.input.inner().multi_tap.pending_key() {
172173
pending == key
@@ -318,10 +319,10 @@ struct Input {
318319
}
319320

320321
impl Input {
321-
fn new() -> Self {
322+
fn new(max_len: usize) -> Self {
322323
Self {
323324
area: Rect::zero(),
324-
textbox: TextBox::empty(MAX_LENGTH),
325+
textbox: TextBox::empty(max_len),
325326
multi_tap: MultiTapKeyboard::new(),
326327
}
327328
}

core/embed/rust/src/ui/layout_bolt/ui_firmware.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -723,12 +723,22 @@ impl FirmwareUI for UIBolt {
723723

724724
fn request_passphrase(
725725
_prompt: TString<'static>,
726-
_max_len: u32,
726+
_prompt_empty: TString<'static>,
727+
max_len: usize,
727728
) -> Result<impl LayoutMaybeTrace, Error> {
728-
let layout = RootComponent::new(PassphraseKeyboard::new());
729+
let layout = RootComponent::new(PassphraseKeyboard::new(max_len));
729730
Ok(layout)
730731
}
731732

733+
fn request_string(
734+
_prompt: TString<'static>,
735+
_max_len: usize,
736+
_allow_empty: bool,
737+
_prefill: Option<TString<'static>>,
738+
) -> Result<impl LayoutMaybeTrace, Error> {
739+
Err::<RootComponent<Empty, ModelUI>, Error>(ERROR_NOT_IMPLEMENTED)
740+
}
741+
732742
fn select_menu(
733743
_items: heapless::Vec<TString<'static>, MAX_MENU_ITEMS>,
734744
_current: usize,
@@ -925,7 +935,7 @@ impl FirmwareUI for UIBolt {
925935
fn show_device_menu(
926936
_failed_backup: bool,
927937
_firmware_version: TString<'static>,
928-
_device_name: TString<'static>,
938+
_device_name: Option<TString<'static>>,
929939
_paired_devices: heapless::Vec<TString<'static>, 1>,
930940
_auto_lock_delay: TString<'static>,
931941
) -> Result<impl LayoutMaybeTrace, Error> {

core/embed/rust/src/ui/layout_caesar/component/input_methods/passphrase.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ enum ChoiceCategory {
2626
SpecialSymbol,
2727
}
2828

29-
const MAX_PASSPHRASE_LENGTH: usize = 50;
30-
3129
const DIGITS: &str = "0123456789";
3230
const LOWERCASE_LETTERS: &str = "abcdefghijklmnopqrstuvwxyz";
3331
const UPPERCASE_LETTERS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -273,26 +271,28 @@ pub struct PassphraseEntry {
273271
show_last_digit: bool,
274272
textbox: TextBox,
275273
current_category: ChoiceCategory,
274+
max_len: usize,
276275
}
277276

278277
impl PassphraseEntry {
279-
pub fn new() -> Self {
278+
pub fn new(max_len: usize) -> Self {
280279
Self {
281280
choice_page: ChoicePage::new(ChoiceFactoryPassphrase::new(ChoiceCategory::Menu, true))
282281
.with_initial_page_counter(random_menu_position())
283282
.with_controls(ChoiceControls::Carousel),
284-
passphrase_dots: Child::new(ChangingTextLine::center_mono("", MAX_PASSPHRASE_LENGTH)),
283+
passphrase_dots: Child::new(ChangingTextLine::center_mono("", max_len)),
285284
show_plain_passphrase: false,
286285
show_last_digit: false,
287-
textbox: TextBox::empty(MAX_PASSPHRASE_LENGTH),
286+
textbox: TextBox::empty(max_len),
288287
current_category: ChoiceCategory::Menu,
288+
max_len,
289289
}
290290
}
291291

292292
fn update_passphrase_dots(&mut self, ctx: &mut EventCtx) {
293293
debug_assert!({
294294
let s = ShortString::new();
295-
s.capacity() >= MAX_PASSPHRASE_LENGTH
295+
s.capacity() >= self.max_len
296296
});
297297

298298
let text_to_show = if self.show_plain_passphrase {
@@ -362,7 +362,7 @@ impl PassphraseEntry {
362362
}
363363

364364
fn is_full(&self) -> bool {
365-
self.textbox.len() >= MAX_PASSPHRASE_LENGTH
365+
self.textbox.len() >= self.max_len
366366
}
367367

368368
/// Randomly choose an index in the current category

core/embed/rust/src/ui/layout_caesar/ui_firmware.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -917,13 +917,24 @@ impl FirmwareUI for UICaesar {
917917

918918
fn request_passphrase(
919919
prompt: TString<'static>,
920-
_max_len: u32,
920+
_prompt_empty: TString<'static>,
921+
max_len: usize,
921922
) -> Result<impl LayoutMaybeTrace, Error> {
922-
let layout =
923-
RootComponent::new(Frame::new(prompt, PassphraseEntry::new()).with_title_centered());
923+
let layout = RootComponent::new(
924+
Frame::new(prompt, PassphraseEntry::new(max_len)).with_title_centered(),
925+
);
924926
Ok(layout)
925927
}
926928

929+
fn request_string(
930+
_prompt: TString<'static>,
931+
_max_len: usize,
932+
_allow_empty: bool,
933+
_prefill: Option<TString<'static>>,
934+
) -> Result<impl LayoutMaybeTrace, Error> {
935+
Err::<RootComponent<Empty, ModelUI>, Error>(ERROR_NOT_IMPLEMENTED)
936+
}
937+
927938
fn select_menu(
928939
items: heapless::Vec<TString<'static>, MAX_MENU_ITEMS>,
929940
current: usize,
@@ -1118,7 +1129,7 @@ impl FirmwareUI for UICaesar {
11181129
fn show_device_menu(
11191130
_failed_backup: bool,
11201131
_firmware_version: TString<'static>,
1121-
_device_name: TString<'static>,
1132+
_device_name: Option<TString<'static>>,
11221133
_paired_devices: Vec<TString<'static>, 1>,
11231134
_auto_lock_delay: TString<'static>,
11241135
) -> Result<impl LayoutMaybeTrace, Error> {

0 commit comments

Comments
 (0)