Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eckhart share words and select word components #4618

Open
wants to merge 11 commits into
base: ui-eckhart
Choose a base branch
from
4 changes: 3 additions & 1 deletion core/embed/rust/librust_qstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,8 @@ static void _librust_qstrs(void) {
MP_QSTR_set_brightness;
MP_QSTR_setting__adjust;
MP_QSTR_setting__apply;
MP_QSTR_share_words__first_word;
MP_QSTR_share_words__word_multiple_times;
MP_QSTR_share_words__words_in_order;
MP_QSTR_share_words__wrote_down_all;
MP_QSTR_show_address_details;
Expand All @@ -650,7 +652,7 @@ static void _librust_qstrs(void) {
MP_QSTR_show_progress_coinjoin;
MP_QSTR_show_remaining_shares;
MP_QSTR_show_share_words;
MP_QSTR_show_share_words_delizia;
MP_QSTR_show_share_words_extended;
MP_QSTR_show_simple;
MP_QSTR_show_success;
MP_QSTR_show_wait_text;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions core/embed/rust/src/ui/api/firmware_micropython.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
}

extern "C" fn new_show_share_words_delizia(
extern "C" fn new_show_share_words_extended(
n_args: usize,
args: *const Obj,
kwargs: *mut Map,
Expand All @@ -898,7 +898,7 @@ extern "C" fn new_show_share_words_delizia(

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,
subtitle,
instructions,
Expand Down Expand Up @@ -1589,7 +1589,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// """Show mnemonic for backup."""
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],
/// subtitle: str | None,
Expand All @@ -1599,7 +1599,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// ) -> LayoutObj[UiResult]:
/// """Show mnemonic for wallet backup preceded by an instruction screen and followed by a
/// 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(
/// *,
Expand Down
2 changes: 1 addition & 1 deletion core/embed/rust/src/ui/layout_bolt/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,7 @@ impl FirmwareUI for UIBolt {
Ok(layout)
}

fn show_share_words_delizia(
fn show_share_words_extended(
_words: heapless::Vec<TString<'static>, 33>,
_subtitle: Option<TString<'static>>,
_instructions: Obj,
Expand Down
2 changes: 1 addition & 1 deletion core/embed/rust/src/ui/layout_caesar/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,7 @@ impl FirmwareUI for UICaesar {
Ok(layout)
}

fn show_share_words_delizia(
fn show_share_words_extended(
_words: heapless::Vec<TString<'static>, 33>,
_subtitle: Option<TString<'static>>,
_instructions: Obj,
Expand Down
4 changes: 2 additions & 2 deletions core/embed/rust/src/ui/layout_delizia/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,11 +996,11 @@ impl FirmwareUI for UIDelizia {
_title: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error> {
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>,
subtitle: Option<TString<'static>>,
instructions: Obj,
Expand Down
2 changes: 2 additions & 0 deletions core/embed/rust/src/ui/layout_eckhart/flow/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod eckhart_swipe_flow_test;
pub mod show_share_words;

pub use eckhart_swipe_flow_test::new_eckhart_swipe_flow;
pub use show_share_words::new_show_share_words_flow;
93 changes: 93 additions & 0 deletions core/embed/rust/src/ui/layout_eckhart/flow/show_share_words.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use crate::{
error,
strutil::TString,
translations::TR,
ui::{
component::{text::op::OpTextLayout, ComponentExt, FormattedText},
flow::{
base::{Decision, DecisionBuilder as _},
FlowController, FlowMsg, SwipeFlow,
},
geometry::Direction,
layout_eckhart::{
component::{
ActionBar, Button, Header, HeaderMsg, Hint, ShareWordsScreen, ShareWordsScreenMsg,
TextScreen, TextScreenMsg,
},
fonts, theme,
},
},
};

use heapless::Vec;

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ShowShareWords {
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::ShareWords, FlowMsg::Cancelled) => self.return_msg(FlowMsg::Cancelled),
(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>,
text_confirm: TString<'static>,
) -> Result<SwipeFlow, error::Error> {
let share_words = ShareWordsScreen::new(words)
.with_action_bar(ActionBar::new_double(
Button::with_icon(theme::ICON_CHEVRON_UP),
Button::with_text(TR::buttons__continue.into()),
))
.with_hint(Hint::new_page_counter())
.with_header(
Header::new(TR::reset__recovery_wallet_backup_title.into())
.with_right_button(Button::with_icon(theme::ICON_MENU), HeaderMsg::Cancelled),
)
.map(|msg| match msg {
ShareWordsScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
ShareWordsScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
ShareWordsScreenMsg::Menu => todo!(),
});

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_menu_button())
.with_action_bar(ActionBar::new_double(
Button::with_icon(theme::ICON_CHEVRON_LEFT),
Button::with_text(TR::buttons__hold_to_confirm.into())
.with_long_press(theme::CONFIRM_HOLD_DURATION),
))
.map(|msg| match msg {
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
TextScreenMsg::Menu => todo!(),
});

let res = SwipeFlow::new(&ShowShareWords::ShareWords)?
.with_page(&ShowShareWords::ShareWords, share_words)?
.with_page(&ShowShareWords::Confirm, confirm)?;
Ok(res)
}
15 changes: 9 additions & 6 deletions core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{

use super::{
component::{ActionBar, Button, Header, HeaderMsg, Hint, TextScreen},
fonts, theme, UIEckhart,
flow, fonts, theme, UIEckhart,
};

impl FirmwareUI for UIEckhart {
Expand Down Expand Up @@ -553,17 +553,20 @@ impl FirmwareUI for UIEckhart {
_words: heapless::Vec<TString<'static>, 33>,
_title: Option<TString<'static>>,
) -> 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(
_words: heapless::Vec<TString<'static>, 33>,
fn show_share_words_extended(
words: heapless::Vec<TString<'static>, 33>,
_subtitle: Option<TString<'static>>,
_instructions: Obj,
_text_footer: Option<TString<'static>>,
_text_confirm: TString<'static>,
text_confirm: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error> {
Err::<RootComponent<Empty, ModelUI>, Error>(Error::ValueError(c"not implemented"))
let flow = flow::show_share_words::new_show_share_words_flow(words, text_confirm)?;
Ok(flow)
}

fn show_remaining_shares(_pages_iterable: Obj) -> Result<impl LayoutMaybeTrace, Error> {
Expand Down
4 changes: 2 additions & 2 deletions core/embed/rust/src/ui/ui_firmware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,8 @@ pub trait FirmwareUI {
) -> Result<impl LayoutMaybeTrace, Error>;

// TODO: merge with `show_share_words` instead of having specific version for
// Delizia UI
fn show_share_words_delizia(
// Delizia/Eckhart UI
fn show_share_words_extended(
words: Vec<TString<'static>, 33>,
subtitle: Option<TString<'static>>,
instructions: Obj, // TODO: replace Obj
Expand Down
2 changes: 1 addition & 1 deletion core/mocks/generated/trezorui_api.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ def show_share_words(


# rust/src/ui/api/firmware_micropython.rs
def show_share_words_delizia(
def show_share_words_extended(
*,
words: Iterable[str],
subtitle: str | None,
Expand Down
2 changes: 2 additions & 0 deletions core/mocks/trezortranslate_keys.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,8 @@ class TR:
send__you_are_contributing: str = "You are contributing:"
setting__adjust: str = "Adjust"
setting__apply: str = "Apply"
share_words__first_word: str = "Write down the first word from the backup."
share_words__word_multiple_times: str = "The word appears multiple times in the backup."
obrusvit marked this conversation as resolved.
Show resolved Hide resolved
share_words__words_in_order: str = " words in order."
share_words__wrote_down_all: str = "I wrote down all "
sign_message__bytes_template: str = "{0} Bytes"
Expand Down
2 changes: 1 addition & 1 deletion core/src/trezor/ui/layouts/delizia/reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def show_share_words(
text_confirm = TR.reset__words_written_down_template.format(words_count)

return raise_if_not_confirmed(
trezorui_api.show_share_words_delizia(
trezorui_api.show_share_words_extended(
words=share_words,
subtitle=subtitle,
instructions=instructions,
Expand Down
33 changes: 31 additions & 2 deletions core/src/trezor/ui/layouts/eckhart/reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,37 @@ def show_share_words(
share_index: int | None = None,
group_index: int | None = None,
) -> Awaitable[None]:
# FIXME: not implemented
raise NotImplemented
if share_index is None:
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
instructions = [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
instructions.append(TR.reset__words_may_repeat)
if share_index == 0:
# regular SLIP39, 1st share
description = TR.instructions__shares_start_with_1
instructions.append(TR.reset__repeat_for_all_shares)
assert len(instructions) < 3
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(
Expand Down
2 changes: 2 additions & 0 deletions core/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,8 @@
"setting__apply": "Apply",
"share_words__words_in_order": " words in order.",
"share_words__wrote_down_all": "I wrote down all ",
"share_words__word_multiple_times": "The word appears multiple times in the backup.",
"share_words__first_word": "Write down the first word from the backup.",
"sign_message__bytes_template": "{0} Bytes",
"sign_message__confirm_address": "Signing address",
"sign_message__confirm_message": "Confirm message",
Expand Down
4 changes: 3 additions & 1 deletion core/translations/order.json
Original file line number Diff line number Diff line change
Expand Up @@ -973,5 +973,7 @@
"971": "instructions__view_all_data",
"972": "ethereum__interaction_contract",
"973": "misc__enable_labeling",
"974": "ethereum__unknown_contract_address_short"
"974": "ethereum__unknown_contract_address_short",
"975": "share_words__first_word",
"976": "share_words__word_multiple_times"
}
6 changes: 3 additions & 3 deletions core/translations/signatures.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"current": {
"merkle_root": "6b7c949ee3a2332eca6a3224cab4f161b7b0ae8e4b8c54591ec50731091b99c9",
"datetime": "2025-02-07T14:30:18.145419",
"commit": "061e71213ea8340874e47eab7d0aec07ec444c1e"
"merkle_root": "31454a46346717afd55e29f2a23f6cf64e4e23679af127d774895aa3a700c764",
"datetime": "2025-02-11T20:37:31.846640",
"commit": "76038b3f457b2c4d601ea2313c2e35aa1d5ebeca"
},
"history": [
{
Expand Down