1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-10 01:58:45 +00:00

refactor(core): port functions to FirmwareUI

- keyboards
- standalone functions
  - disable_animations
  - check_homescreen_format
- confirm_action
- selectors
- confirm_firmware_update
- show_homescreen/lockscreen
- confirm_homescreen
- confirm_homescreen of mercury changed according to Figma
- set_brightness
- show_wait_text
- show_progress
- request_number
- show_checklist
- show_mismatch
- confirm_reset
- tutorial
- confirm_coinjoin
- confirm_modify_output/fee
- show_group_share_success
- show_remaining_shares
- show_success/warning/error/danger
- show_simple
- continue_recovery
  - confirm_recovery of model_t and model_r merged with
flow_continue_recovery of mercury into a continue_recovery_homepage
trait function, parameters renamed to be more descriptive
- show_share_words moved and refactored
  - model_t version was moved from using plain Paragraph to a dedicated
component `ShareWords` so that it's consistent with other models. This
allowed to move formatting to Rust and allowed the trait function to
have `words` parameter of type `Vec<TString, 33>`
  - model_r ShareWords::render slightly refactored to be consistent with
the new model_t version
  - mercury uses a unique version. The reason is that mercury SwipeFlow
contains also the initial screen with instructions and prompt screen at
the end.
- confirm_with_info
- show_info_with_cancel
- confirm_blob
- confirm_value
- confirm_properties
- confirm_more
- confirm_address
- prompt_backub
- confirm_emphasized
- show_address_details
- confirm_summary
- TR removed:
  - confirm_output_address and confirm_output_amount replaced with
confirm_blob. UI diff is minimal.
  - confirm_joint_total, replaced a TR-specific function with a generic
`confirm_properties` with no UI changes
- confirm_multiple_pages_texts
  - the function is TR specific and is used only in confirm_set_new_pin,
it would be better to use something different
- remaining mercury flows with no counterpart
  - confirm_blob_intro
  - flow_confirm_set_new_pin
  - flow_confirm_output
  - flow_get_address

[no changelog]
This commit is contained in:
obrusvit 2024-10-22 22:24:40 +02:00 committed by Vít Obrusník
parent b2c6b09bfc
commit dd9ac038d0
42 changed files with 6838 additions and 7155 deletions

View File

@ -63,7 +63,6 @@ static void _librust_qstrs(void) {
MP_QSTR_address_details__derivation_path_colon; MP_QSTR_address_details__derivation_path_colon;
MP_QSTR_address_details__title_receive_address; MP_QSTR_address_details__title_receive_address;
MP_QSTR_address_details__title_receiving_to; MP_QSTR_address_details__title_receiving_to;
MP_QSTR_address_label;
MP_QSTR_address_qr; MP_QSTR_address_qr;
MP_QSTR_address_title; MP_QSTR_address_title;
MP_QSTR_allow_cancel; MP_QSTR_allow_cancel;
@ -71,7 +70,6 @@ static void _librust_qstrs(void) {
MP_QSTR_amount_change; MP_QSTR_amount_change;
MP_QSTR_amount_label; MP_QSTR_amount_label;
MP_QSTR_amount_new; MP_QSTR_amount_new;
MP_QSTR_amount_title;
MP_QSTR_app_name; MP_QSTR_app_name;
MP_QSTR_area_bytesize; MP_QSTR_area_bytesize;
MP_QSTR_attach_timer_fn; MP_QSTR_attach_timer_fn;
@ -187,7 +185,6 @@ static void _librust_qstrs(void) {
MP_QSTR_coinjoin_authorized; MP_QSTR_coinjoin_authorized;
MP_QSTR_confirm_action; MP_QSTR_confirm_action;
MP_QSTR_confirm_address; MP_QSTR_confirm_address;
MP_QSTR_confirm_backup;
MP_QSTR_confirm_blob; MP_QSTR_confirm_blob;
MP_QSTR_confirm_blob_intro; MP_QSTR_confirm_blob_intro;
MP_QSTR_confirm_coinjoin; MP_QSTR_confirm_coinjoin;
@ -195,14 +192,10 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_fido; MP_QSTR_confirm_fido;
MP_QSTR_confirm_firmware_update; MP_QSTR_confirm_firmware_update;
MP_QSTR_confirm_homescreen; MP_QSTR_confirm_homescreen;
MP_QSTR_confirm_joint_total;
MP_QSTR_confirm_modify_fee; MP_QSTR_confirm_modify_fee;
MP_QSTR_confirm_modify_output; MP_QSTR_confirm_modify_output;
MP_QSTR_confirm_more; MP_QSTR_confirm_more;
MP_QSTR_confirm_output_address;
MP_QSTR_confirm_output_amount;
MP_QSTR_confirm_properties; MP_QSTR_confirm_properties;
MP_QSTR_confirm_recovery;
MP_QSTR_confirm_reset_device; MP_QSTR_confirm_reset_device;
MP_QSTR_confirm_summary; MP_QSTR_confirm_summary;
MP_QSTR_confirm_total__fee_rate; MP_QSTR_confirm_total__fee_rate;
@ -212,6 +205,7 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_total__title_sending_from; MP_QSTR_confirm_total__title_sending_from;
MP_QSTR_confirm_value; MP_QSTR_confirm_value;
MP_QSTR_confirm_with_info; MP_QSTR_confirm_with_info;
MP_QSTR_continue_recovery_homepage;
MP_QSTR_count; MP_QSTR_count;
MP_QSTR_current; MP_QSTR_current;
MP_QSTR_danger; MP_QSTR_danger;
@ -246,16 +240,9 @@ static void _librust_qstrs(void) {
MP_QSTR_fingerprint; MP_QSTR_fingerprint;
MP_QSTR_firmware_update__title; MP_QSTR_firmware_update__title;
MP_QSTR_firmware_update__title_fingerprint; MP_QSTR_firmware_update__title_fingerprint;
MP_QSTR_first_screen;
MP_QSTR_flow_confirm_output; MP_QSTR_flow_confirm_output;
MP_QSTR_flow_confirm_reset;
MP_QSTR_flow_confirm_set_new_pin; MP_QSTR_flow_confirm_set_new_pin;
MP_QSTR_flow_continue_recovery;
MP_QSTR_flow_get_address; MP_QSTR_flow_get_address;
MP_QSTR_flow_prompt_backup;
MP_QSTR_flow_request_number;
MP_QSTR_flow_request_passphrase;
MP_QSTR_flow_show_share_words;
MP_QSTR_get_language; MP_QSTR_get_language;
MP_QSTR_get_transition_out; MP_QSTR_get_transition_out;
MP_QSTR_haptic_feedback__disable; MP_QSTR_haptic_feedback__disable;
@ -292,6 +279,7 @@ static void _librust_qstrs(void) {
MP_QSTR_inputs__return; MP_QSTR_inputs__return;
MP_QSTR_inputs__show; MP_QSTR_inputs__show;
MP_QSTR_inputs__space; MP_QSTR_inputs__space;
MP_QSTR_instructions;
MP_QSTR_instructions__continue_holding; MP_QSTR_instructions__continue_holding;
MP_QSTR_instructions__continue_in_app; MP_QSTR_instructions__continue_in_app;
MP_QSTR_instructions__enter_next_share; MP_QSTR_instructions__enter_next_share;
@ -347,6 +335,7 @@ static void _librust_qstrs(void) {
MP_QSTR_modify_fee__no_change; MP_QSTR_modify_fee__no_change;
MP_QSTR_modify_fee__title; MP_QSTR_modify_fee__title;
MP_QSTR_modify_fee__transaction_fee; MP_QSTR_modify_fee__transaction_fee;
MP_QSTR_more_info_callback;
MP_QSTR_multiple_pages_texts; MP_QSTR_multiple_pages_texts;
MP_QSTR_notification; MP_QSTR_notification;
MP_QSTR_notification_level; MP_QSTR_notification_level;
@ -422,6 +411,7 @@ static void _librust_qstrs(void) {
MP_QSTR_progress__x_seconds_left_template; MP_QSTR_progress__x_seconds_left_template;
MP_QSTR_progress_event; MP_QSTR_progress_event;
MP_QSTR_prompt; MP_QSTR_prompt;
MP_QSTR_prompt_backup;
MP_QSTR_prompt_screen; MP_QSTR_prompt_screen;
MP_QSTR_prompt_title; MP_QSTR_prompt_title;
MP_QSTR_qr_title; MP_QSTR_qr_title;
@ -481,6 +471,7 @@ static void _librust_qstrs(void) {
MP_QSTR_recovery__x_of_y_entered_template; MP_QSTR_recovery__x_of_y_entered_template;
MP_QSTR_recovery__you_have_entered; MP_QSTR_recovery__you_have_entered;
MP_QSTR_recovery_type; MP_QSTR_recovery_type;
MP_QSTR_remaining_shares;
MP_QSTR_request_bip39; MP_QSTR_request_bip39;
MP_QSTR_request_complete_repaint; MP_QSTR_request_complete_repaint;
MP_QSTR_request_number; MP_QSTR_request_number;
@ -639,7 +630,6 @@ static void _librust_qstrs(void) {
MP_QSTR_set_brightness; MP_QSTR_set_brightness;
MP_QSTR_setting__adjust; MP_QSTR_setting__adjust;
MP_QSTR_setting__apply; MP_QSTR_setting__apply;
MP_QSTR_share_words;
MP_QSTR_share_words__words_in_order; MP_QSTR_share_words__words_in_order;
MP_QSTR_share_words__wrote_down_all; MP_QSTR_share_words__wrote_down_all;
MP_QSTR_show_address_details; MP_QSTR_show_address_details;
@ -653,11 +643,11 @@ static void _librust_qstrs(void) {
MP_QSTR_show_instructions; MP_QSTR_show_instructions;
MP_QSTR_show_lockscreen; MP_QSTR_show_lockscreen;
MP_QSTR_show_mismatch; MP_QSTR_show_mismatch;
MP_QSTR_show_passphrase;
MP_QSTR_show_progress; MP_QSTR_show_progress;
MP_QSTR_show_progress_coinjoin; MP_QSTR_show_progress_coinjoin;
MP_QSTR_show_remaining_shares; MP_QSTR_show_remaining_shares;
MP_QSTR_show_share_words; MP_QSTR_show_share_words;
MP_QSTR_show_share_words_mercury;
MP_QSTR_show_simple; MP_QSTR_show_simple;
MP_QSTR_show_success; MP_QSTR_show_success;
MP_QSTR_show_wait_text; MP_QSTR_show_wait_text;
@ -669,7 +659,6 @@ static void _librust_qstrs(void) {
MP_QSTR_sign_message__message_size; MP_QSTR_sign_message__message_size;
MP_QSTR_sign_message__verify_address; MP_QSTR_sign_message__verify_address;
MP_QSTR_skip_first_paint; MP_QSTR_skip_first_paint;
MP_QSTR_spending_amount;
MP_QSTR_storage_msg__processing; MP_QSTR_storage_msg__processing;
MP_QSTR_storage_msg__starting; MP_QSTR_storage_msg__starting;
MP_QSTR_storage_msg__verifying_pin; MP_QSTR_storage_msg__verifying_pin;
@ -683,12 +672,12 @@ static void _librust_qstrs(void) {
MP_QSTR_summary_title; MP_QSTR_summary_title;
MP_QSTR_text; MP_QSTR_text;
MP_QSTR_text_confirm; MP_QSTR_text_confirm;
MP_QSTR_text_info; MP_QSTR_text_footer;
MP_QSTR_text_mono; MP_QSTR_text_mono;
MP_QSTR_time_ms; MP_QSTR_time_ms;
MP_QSTR_timer; MP_QSTR_timer;
MP_QSTR_title; MP_QSTR_title;
MP_QSTR_total_amount; MP_QSTR_title_success;
MP_QSTR_total_fee_new; MP_QSTR_total_fee_new;
MP_QSTR_total_len; MP_QSTR_total_len;
MP_QSTR_touch_event; MP_QSTR_touch_event;
@ -738,7 +727,6 @@ static void _librust_qstrs(void) {
MP_QSTR_verb_info; MP_QSTR_verb_info;
MP_QSTR_verify; MP_QSTR_verify;
MP_QSTR_version; MP_QSTR_version;
MP_QSTR_warning;
MP_QSTR_wipe__info; MP_QSTR_wipe__info;
MP_QSTR_wipe__title; MP_QSTR_wipe__title;
MP_QSTR_wipe__want_to_wipe; MP_QSTR_wipe__want_to_wipe;

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
error, error,
micropython::{gc::Gc, list::List, map::Map, obj::Obj, qstr::Qstr, util}, micropython::{gc::Gc, list::List},
strutil::TString, strutil::TString,
translations::TR, translations::TR,
ui::{ ui::{
@ -14,7 +14,6 @@ use crate::{
FlowController, FlowMsg, SwipeFlow, SwipePage, FlowController, FlowMsg, SwipeFlow, SwipePage,
}, },
geometry::Direction, geometry::Direction,
layout::obj::LayoutObj,
}, },
}; };
@ -39,6 +38,7 @@ pub enum ConfirmFido {
static CRED_SELECTED: AtomicUsize = AtomicUsize::new(0); static CRED_SELECTED: AtomicUsize = AtomicUsize::new(0);
static SINGLE_CRED: AtomicBool = AtomicBool::new(false); static SINGLE_CRED: AtomicBool = AtomicBool::new(false);
const EXTRA_PADDING: i16 = 6;
impl FlowController for ConfirmFido { impl FlowController for ConfirmFido {
#[inline] #[inline]
@ -50,7 +50,7 @@ impl FlowController for ConfirmFido {
match (self, direction) { match (self, direction) {
(Self::Intro, Direction::Left) => Self::Menu.swipe(direction), (Self::Intro, Direction::Left) => Self::Menu.swipe(direction),
(Self::Menu, Direction::Right) => { (Self::Menu, Direction::Right) => {
if Self::single_cred() { if single_cred() {
Self::Details.swipe_right() Self::Details.swipe_right()
} else { } else {
Self::Intro.swipe_right() Self::Intro.swipe_right()
@ -69,7 +69,7 @@ impl FlowController for ConfirmFido {
(_, FlowMsg::Info) => Self::Menu.goto(), (_, FlowMsg::Info) => Self::Menu.goto(),
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled), (Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
(Self::Menu, FlowMsg::Cancelled) => { (Self::Menu, FlowMsg::Cancelled) => {
if Self::single_cred() { if single_cred() {
Self::Details.swipe_right() Self::Details.swipe_right()
} else { } else {
Self::Intro.swipe_right() Self::Intro.swipe_right()
@ -88,11 +88,6 @@ impl FlowController for ConfirmFido {
} }
} }
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmFido::new_obj) }
}
fn footer_update_fn( fn footer_update_fn(
content: &SwipeContent<SwipePage<PagedVerticalMenu<impl Fn(usize) -> TString<'static>>>>, content: &SwipeContent<SwipePage<PagedVerticalMenu<impl Fn(usize) -> TString<'static>>>>,
ctx: &mut EventCtx, ctx: &mut EventCtx,
@ -103,124 +98,120 @@ fn footer_update_fn(
footer.update_page_counter(ctx, current_page, total_pages); footer.update_page_counter(ctx, current_page, total_pages);
} }
impl ConfirmFido { fn single_cred() -> bool {
const EXTRA_PADDING: i16 = 6; SINGLE_CRED.load(Ordering::Relaxed)
}
fn single_cred() -> bool { pub fn new_confirm_fido(
SINGLE_CRED.load(Ordering::Relaxed) title: TString<'static>,
app_name: TString<'static>,
icon_name: Option<TString<'static>>,
accounts: Gc<List>,
) -> Result<SwipeFlow, error::Error> {
let num_accounts = accounts.len();
SINGLE_CRED.store(num_accounts <= 1, Ordering::Relaxed);
CRED_SELECTED.store(0, Ordering::Relaxed);
let content_intro = Frame::left_aligned(
title,
SwipeContent::new(Paragraphs::new(Paragraph::new::<TString>(
&theme::TEXT_MAIN_GREY_LIGHT,
TR::fido__select_intro.into(),
))),
)
.with_menu_button()
.with_footer(TR::instructions__swipe_up.into(), None)
.with_swipe(Direction::Up, SwipeSettings::default())
.with_swipe(Direction::Right, SwipeSettings::immediate())
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info));
// Closure to lazy-load the information on given page index.
// Done like this to allow arbitrarily many pages without
// the need of any allocation here in Rust.
let label_fn = move |page_index| {
let account = unwrap!(accounts.get(page_index));
account
.try_into()
.unwrap_or_else(|_| TString::from_str("-"))
};
let content_choose_credential = Frame::left_aligned(
TR::fido__title_select_credential.into(),
SwipeContent::new(SwipePage::vertical(PagedVerticalMenu::new(
num_accounts,
label_fn,
))),
)
.with_subtitle(TR::fido__title_for_authentication.into())
.with_menu_button()
.with_footer_page_hint(
TR::fido__more_credentials.into(),
TR::buttons__go_back.into(),
TR::instructions__swipe_up.into(),
TR::instructions__swipe_down.into(),
)
.register_footer_update_fn(footer_update_fn)
.with_swipe(Direction::Down, SwipeSettings::default())
.with_swipe(Direction::Right, SwipeSettings::immediate())
.with_vertical_pages()
.map(|msg| match msg {
FrameMsg::Button(_) => Some(FlowMsg::Info),
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
});
let get_account = move || {
let current = CRED_SELECTED.load(Ordering::Relaxed);
let account = unwrap!(accounts.get(current));
account.try_into().unwrap_or_else(|_| TString::from_str(""))
};
let content_details = Frame::left_aligned(
TR::fido__title_credential_details.into(),
SwipeContent::new(FidoCredential::new(icon_name, app_name, get_account)),
)
.with_footer(TR::instructions__swipe_up.into(), Some(title))
.with_swipe(Direction::Up, SwipeSettings::default())
.with_swipe(Direction::Right, SwipeSettings::immediate());
let content_details = if single_cred() {
content_details.with_menu_button()
} else {
content_details.with_cancel_button()
} }
.map(|msg| match msg {
FrameMsg::Button(bm) => Some(bm),
_ => None,
});
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> { let content_tap = Frame::left_aligned(title, PromptScreen::new_tap_to_confirm())
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let app_name: TString = kwargs.get(Qstr::MP_QSTR_app_name)?.try_into()?;
let icon_name: Option<TString> = kwargs.get(Qstr::MP_QSTR_icon_name)?.try_into_option()?;
let accounts: Gc<List> = kwargs.get(Qstr::MP_QSTR_accounts)?.try_into()?;
let num_accounts = accounts.len();
SINGLE_CRED.store(num_accounts <= 1, Ordering::Relaxed);
CRED_SELECTED.store(0, Ordering::Relaxed);
let content_intro = Frame::left_aligned(
title,
SwipeContent::new(Paragraphs::new(Paragraph::new::<TString>(
&theme::TEXT_MAIN_GREY_LIGHT,
TR::fido__select_intro.into(),
))),
)
.with_menu_button() .with_menu_button()
.with_footer(TR::instructions__swipe_up.into(), None) .with_footer(TR::instructions__tap_to_confirm.into(), None)
.with_swipe(Direction::Up, SwipeSettings::default())
.with_swipe(Direction::Right, SwipeSettings::immediate())
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info));
// Closure to lazy-load the information on given page index.
// Done like this to allow arbitrarily many pages without
// the need of any allocation here in Rust.
let label_fn = move |page_index| {
let account = unwrap!(accounts.get(page_index));
account
.try_into()
.unwrap_or_else(|_| TString::from_str("-"))
};
let content_choose_credential = Frame::left_aligned(
TR::fido__title_select_credential.into(),
SwipeContent::new(SwipePage::vertical(PagedVerticalMenu::new(
num_accounts,
label_fn,
))),
)
.with_subtitle(TR::fido__title_for_authentication.into())
.with_menu_button()
.with_footer_page_hint(
TR::fido__more_credentials.into(),
TR::buttons__go_back.into(),
TR::instructions__swipe_up.into(),
TR::instructions__swipe_down.into(),
)
.register_footer_update_fn(footer_update_fn)
.with_swipe(Direction::Down, SwipeSettings::default()) .with_swipe(Direction::Down, SwipeSettings::default())
.with_swipe(Direction::Right, SwipeSettings::immediate()) .with_swipe(Direction::Right, SwipeSettings::immediate())
.with_vertical_pages()
.map(|msg| match msg { .map(|msg| match msg {
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
FrameMsg::Button(_) => Some(FlowMsg::Info), FrameMsg::Button(_) => Some(FlowMsg::Info),
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
});
let get_account = move || {
let current = CRED_SELECTED.load(Ordering::Relaxed);
let account = unwrap!(accounts.get(current));
account.try_into().unwrap_or_else(|_| TString::from_str(""))
};
let content_details = Frame::left_aligned(
TR::fido__title_credential_details.into(),
SwipeContent::new(FidoCredential::new(icon_name, app_name, get_account)),
)
.with_footer(TR::instructions__swipe_up.into(), Some(title))
.with_swipe(Direction::Up, SwipeSettings::default())
.with_swipe(Direction::Right, SwipeSettings::immediate());
let content_details = if Self::single_cred() {
content_details.with_menu_button()
} else {
content_details.with_cancel_button()
}
.map(|msg| match msg {
FrameMsg::Button(bm) => Some(bm),
_ => None, _ => None,
}); });
let content_tap = Frame::left_aligned(title, PromptScreen::new_tap_to_confirm()) let content_menu = Frame::left_aligned(
.with_menu_button() "".into(),
.with_footer(TR::instructions__tap_to_confirm.into(), None) VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
.with_swipe(Direction::Down, SwipeSettings::default()) )
.with_swipe(Direction::Right, SwipeSettings::immediate()) .with_cancel_button()
.map(|msg| match msg { .with_swipe(Direction::Right, SwipeSettings::immediate())
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), .map(|msg| match msg {
FrameMsg::Button(_) => Some(FlowMsg::Info), FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
_ => None, FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
}); });
let content_menu = Frame::left_aligned( let initial_page = if single_cred() {
"".into(), &ConfirmFido::Details
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()), } else {
) &ConfirmFido::Intro
.with_cancel_button() };
.with_swipe(Direction::Right, SwipeSettings::immediate()) SwipeFlow::new(initial_page)?
.map(|msg| match msg { .with_page(&ConfirmFido::Intro, content_intro)?
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)), .with_page(&ConfirmFido::ChooseCredential, content_choose_credential)?
FrameMsg::Button(_) => Some(FlowMsg::Cancelled), .with_page(&ConfirmFido::Details, content_details)?
}); .with_page(&ConfirmFido::Tap, content_tap)?
.with_page(&ConfirmFido::Menu, content_menu)
let initial_page = if Self::single_cred() {
&ConfirmFido::Details
} else {
&ConfirmFido::Intro
};
let res = SwipeFlow::new(initial_page)?
.with_page(&ConfirmFido::Intro, content_intro)?
.with_page(&ConfirmFido::ChooseCredential, content_choose_credential)?
.with_page(&ConfirmFido::Details, content_details)?
.with_page(&ConfirmFido::Tap, content_tap)?
.with_page(&ConfirmFido::Menu, content_menu)?;
Ok(LayoutObj::new_root(res)?.into())
}
} }

View File

@ -0,0 +1,108 @@
use crate::{
error,
strutil::TString,
translations::TR,
ui::{
component::{swipe_detect::SwipeSettings, CachedJpeg, ComponentExt},
flow::{
base::{Decision, DecisionBuilder},
FlowController, FlowMsg, SwipeFlow,
},
geometry::Direction,
model_mercury::{
component::{
Frame, FrameMsg, PromptMsg, PromptScreen, SwipeContent, VerticalMenu,
VerticalMenuChoiceMsg,
},
theme,
},
},
};
/// Flow for a setting of homescreen wallpaper showing a preview of the image,
/// menu to cancel and tap to confirm prompt.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ConfirmHomescreen {
Homescreen,
Menu,
Confirm,
}
impl FlowController for ConfirmHomescreen {
#[inline]
fn index(&'static self) -> usize {
*self as usize
}
fn handle_swipe(&'static self, direction: Direction) -> Decision {
match (self, direction) {
(Self::Homescreen, Direction::Left) => Self::Menu.swipe(direction),
(Self::Homescreen, Direction::Up) => Self::Confirm.swipe(direction),
(Self::Menu, Direction::Right) => Self::Homescreen.swipe(direction),
(Self::Confirm, Direction::Down) => Self::Homescreen.swipe(direction),
(Self::Confirm, Direction::Left) => Self::Menu.swipe(direction),
_ => self.do_nothing(),
}
}
fn handle_event(&'static self, msg: FlowMsg) -> Decision {
match (self, msg) {
(Self::Homescreen, FlowMsg::Info) => Self::Menu.goto(),
(Self::Menu, FlowMsg::Cancelled) => Self::Homescreen.swipe_right(),
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
(Self::Confirm, FlowMsg::Confirmed) => self.return_msg(FlowMsg::Confirmed),
(Self::Confirm, FlowMsg::Info) => Self::Menu.goto(),
_ => self.do_nothing(),
}
}
}
pub fn new_confirm_homescreen(
title: TString<'static>,
image: CachedJpeg,
) -> Result<SwipeFlow, error::Error> {
let content_homescreen = Frame::left_aligned(title, SwipeContent::new(image))
.with_menu_button()
.with_footer(
TR::instructions__swipe_up.into(),
Some(TR::buttons__change.into()),
)
.with_swipe(Direction::Up, SwipeSettings::default())
// Homescreen + Tap to confirm
.with_pages(|_| 2)
.map(|msg| match msg {
FrameMsg::Button(_) => Some(FlowMsg::Info),
_ => None,
});
let content_menu = Frame::left_aligned(
TString::empty(),
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
)
.with_cancel_button()
.with_swipe(Direction::Right, SwipeSettings::immediate())
.map(|msg| match msg {
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
});
let content_confirm = Frame::left_aligned(
TR::homescreen__title_set.into(),
SwipeContent::new(PromptScreen::new_tap_to_confirm()),
)
.with_menu_button()
.with_footer(TR::instructions__tap_to_confirm.into(), None)
.with_swipe(Direction::Down, SwipeSettings::default())
.with_swipe(Direction::Left, SwipeSettings::default())
.map(|msg| match msg {
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
FrameMsg::Button(_) => Some(FlowMsg::Info),
_ => None,
});
let res = SwipeFlow::new(&ConfirmHomescreen::Homescreen)?
.with_page(&ConfirmHomescreen::Homescreen, content_homescreen)?
.with_page(&ConfirmHomescreen::Menu, content_menu)?
.with_page(&ConfirmHomescreen::Confirm, content_confirm)?;
Ok(res)
}

View File

@ -154,11 +154,11 @@ fn footer_update_fn(
footer.update_page_counter(ctx, current_page, total_pages); footer.update_page_counter(ctx, current_page, total_pages);
} }
pub fn new_continue_recovery( pub fn new_continue_recovery_homepage(
first_screen: bool,
recovery_type: RecoveryType,
text: TString<'static>, text: TString<'static>,
subtext: Option<TString<'static>>, subtext: Option<TString<'static>>,
recovery_type: RecoveryType,
show_instructions: bool, // 1st screen of the recovery process
pages: Option<ParagraphVecLong<'static>>, pages: Option<ParagraphVecLong<'static>>,
) -> Result<SwipeFlow, error::Error> { ) -> Result<SwipeFlow, error::Error> {
let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type { let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type {
@ -179,7 +179,7 @@ pub fn new_continue_recovery(
let mut pars_main = ParagraphVecShort::new(); let mut pars_main = ParagraphVecShort::new();
let footer_instruction; let footer_instruction;
let footer_description; let footer_description;
if first_screen { if show_instructions {
pars_main.add(Paragraph::new( pars_main.add(Paragraph::new(
&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, &theme::TEXT_MAIN_GREY_EXTRA_LIGHT,
TR::recovery__enter_each_word, TR::recovery__enter_each_word,
@ -246,7 +246,7 @@ pub fn new_continue_recovery(
_ => None, _ => None,
}); });
let res = if first_screen { let res = if show_instructions {
let content_menu = Frame::left_aligned( let content_menu = Frame::left_aligned(
TString::empty(), TString::empty(),
VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()), VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()),

View File

@ -96,6 +96,7 @@ pub fn new_get_address(
account: Option<TString<'static>>, account: Option<TString<'static>>,
path: Option<TString<'static>>, path: Option<TString<'static>>,
xpubs: Obj, // TODO: get rid of Obj xpubs: Obj, // TODO: get rid of Obj
title_success: TString<'static>,
br_code: u16, br_code: u16,
br_name: TString<'static>, br_name: TString<'static>,
) -> Result<SwipeFlow, error::Error> { ) -> Result<SwipeFlow, error::Error> {
@ -141,7 +142,7 @@ pub fn new_get_address(
let content_confirmed = Frame::left_aligned( let content_confirmed = Frame::left_aligned(
TR::words__title_success.into(), TR::words__title_success.into(),
StatusScreen::new_success_timeout(TR::address__confirmed.into()), StatusScreen::new_success_timeout(title_success),
) )
.with_footer(TR::instructions__continue_in_app.into(), None) .with_footer(TR::instructions__continue_in_app.into(), None)
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT) .with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT)

View File

@ -2,11 +2,12 @@ pub mod confirm_action;
#[cfg(feature = "universal_fw")] #[cfg(feature = "universal_fw")]
pub mod confirm_fido; pub mod confirm_fido;
pub mod confirm_firmware_update; pub mod confirm_firmware_update;
pub mod confirm_homescreen;
pub mod confirm_output; pub mod confirm_output;
pub mod confirm_reset; pub mod confirm_reset;
pub mod confirm_set_new_pin; pub mod confirm_set_new_pin;
pub mod confirm_summary; pub mod confirm_summary;
pub mod continue_recovery; pub mod continue_recovery_homepage;
pub mod get_address; pub mod get_address;
pub mod prompt_backup; pub mod prompt_backup;
pub mod request_number; pub mod request_number;
@ -24,11 +25,12 @@ pub use confirm_action::{
#[cfg(feature = "universal_fw")] #[cfg(feature = "universal_fw")]
pub use confirm_fido::new_confirm_fido; pub use confirm_fido::new_confirm_fido;
pub use confirm_firmware_update::new_confirm_firmware_update; pub use confirm_firmware_update::new_confirm_firmware_update;
pub use confirm_homescreen::new_confirm_homescreen;
pub use confirm_output::new_confirm_output; pub use confirm_output::new_confirm_output;
pub use confirm_reset::new_confirm_reset; pub use confirm_reset::new_confirm_reset;
pub use confirm_set_new_pin::SetNewPin; pub use confirm_set_new_pin::SetNewPin;
pub use confirm_summary::new_confirm_summary; pub use confirm_summary::new_confirm_summary;
pub use continue_recovery::new_continue_recovery; pub use continue_recovery_homepage::new_continue_recovery_homepage;
pub use get_address::GetAddress; pub use get_address::GetAddress;
pub use prompt_backup::PromptBackup; pub use prompt_backup::PromptBackup;
pub use request_number::RequestNumber; pub use request_number::RequestNumber;

View File

@ -67,8 +67,6 @@ pub fn new_request_number(
max_count: u32, max_count: u32,
description: TString<'static>, description: TString<'static>,
info_closure: impl Fn(u32) -> TString<'static> + 'static, info_closure: impl Fn(u32) -> TString<'static> + 'static,
br_code: u16,
br_name: TString<'static>,
) -> Result<SwipeFlow, error::Error> { ) -> Result<SwipeFlow, error::Error> {
NUM_DISPLAYED.store(count as u16, Ordering::Relaxed); NUM_DISPLAYED.store(count as u16, Ordering::Relaxed);
@ -94,8 +92,7 @@ pub fn new_request_number(
NUM_DISPLAYED.store(n as u16, Ordering::Relaxed); NUM_DISPLAYED.store(n as u16, Ordering::Relaxed);
Some(FlowMsg::Choice(n as usize)) Some(FlowMsg::Choice(n as usize))
} }
}) });
.one_button_request(ButtonRequest::from_num(br_code, br_name));
let content_menu = Frame::left_aligned( let content_menu = Frame::left_aligned(
TString::empty(), TString::empty(),

View File

@ -78,15 +78,15 @@ fn footer_updating_func(
} }
pub fn new_show_share_words( pub fn new_show_share_words(
title: TString<'static>,
subtitle: TString<'static>,
share_words_vec: Vec<TString<'static>, 33>, share_words_vec: Vec<TString<'static>, 33>,
description: Option<TString<'static>>, subtitle: TString<'static>,
instructions_paragraphs: ParagraphVecShort<'static>, instructions_paragraphs: ParagraphVecShort<'static>,
text_footer: Option<TString<'static>>,
text_confirm: TString<'static>, text_confirm: TString<'static>,
) -> Result<SwipeFlow, error::Error> { ) -> Result<SwipeFlow, error::Error> {
let nwords = share_words_vec.len(); let nwords = share_words_vec.len();
let paragraphs_spacing = 8; let paragraphs_spacing = 8;
let title = TR::reset__recovery_wallet_backup_title.into();
let content_instruction = Frame::left_aligned( let content_instruction = Frame::left_aligned(
title, title,
@ -97,7 +97,7 @@ pub fn new_show_share_words(
), ),
) )
.with_subtitle(TR::words__instructions.into()) .with_subtitle(TR::words__instructions.into())
.with_footer(TR::instructions__swipe_up.into(), description) .with_footer(TR::instructions__swipe_up.into(), text_footer)
.with_swipe(Direction::Up, SwipeSettings::default()) .with_swipe(Direction::Up, SwipeSettings::default())
.map(|msg| matches!(msg, FrameMsg::Content(_)).then_some(FlowMsg::Confirmed)) .map(|msg| matches!(msg, FrameMsg::Content(_)).then_some(FlowMsg::Confirmed))
.one_button_request(ButtonRequestCode::ResetDevice.with_name("share_words")) .one_button_request(ButtonRequestCode::ResetDevice.with_name("share_words"))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -92,23 +92,24 @@ impl<'a> ShareWords<'a> {
fn render_words<'s>(&'s self, target: &mut impl Renderer<'s>) { fn render_words<'s>(&'s self, target: &mut impl Renderer<'s>) {
let mut y_offset = 0; let mut y_offset = 0;
// Showing the word index and the words itself // Showing the word index and the words itself
for i in 0..WORDS_PER_PAGE { for (word_idx, word) in self
.share_words
.iter()
.enumerate()
.skip(self.page_index * WORDS_PER_PAGE)
.take(WORDS_PER_PAGE)
{
let ordinal = word_idx + 1;
y_offset += NUMBER_FONT.line_height() + EXTRA_LINE_HEIGHT; y_offset += NUMBER_FONT.line_height() + EXTRA_LINE_HEIGHT;
let index = self.word_index() + i; let base = self.area.top_left() + Offset::y(y_offset);
if index >= self.share_words.len() {
break;
}
let word = &self.share_words[index];
let baseline = self.area.top_left() + Offset::y(y_offset);
let ordinal = uformat!("{}.", index + 1);
shape::Text::new(baseline + Offset::x(NUMBER_X_OFFSET), &ordinal) let ordinal_txt = uformat!("{}.", ordinal);
shape::Text::new(base + Offset::x(NUMBER_X_OFFSET), &ordinal_txt)
.with_font(NUMBER_FONT) .with_font(NUMBER_FONT)
.with_fg(theme::FG) .with_fg(theme::FG)
.render(target); .render(target);
word.map(|w| { word.map(|w| {
shape::Text::new(baseline + Offset::x(WORD_X_OFFSET), w) shape::Text::new(base + Offset::x(WORD_X_OFFSET), w)
.with_font(WORD_FONT) .with_font(WORD_FONT)
.with_fg(theme::FG) .with_fg(theme::FG)
.render(target); .render(target);
@ -170,13 +171,15 @@ impl<'a> crate::trace::Trace for ShareWords<'a> {
self.get_final_text() self.get_final_text()
} else { } else {
let mut content = ShortString::new(); let mut content = ShortString::new();
for i in 0..WORDS_PER_PAGE { for (word_idx, word) in self
let index = self.word_index() + i; .share_words
if index >= self.share_words.len() { .iter()
break; .enumerate()
} .skip(self.page_index * WORDS_PER_PAGE)
self.share_words[index] .take(WORDS_PER_PAGE)
.map(|word| unwrap!(uwrite!(content, "{}. {}\n", index + 1, word))); {
let ordinal = word_idx + 1;
word.map(|w| unwrap!(uwrite!(content, "{}. {}\n", ordinal, w)));
} }
content content
}; };

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,8 @@ mod screens;
pub mod theme; pub mod theme;
pub struct ModelTRFeatures {} pub struct ModelTRFeatures {}
#[cfg(feature = "micropython")]
pub mod ui_features_fw; pub mod ui_features_fw;
impl UIFeaturesCommon for ModelTRFeatures { impl UIFeaturesCommon for ModelTRFeatures {

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@ mod progress;
mod result; mod result;
mod scroll; mod scroll;
mod set_brightness; mod set_brightness;
#[cfg(feature = "translations")]
mod share_words;
mod simple_page; mod simple_page;
mod swipe; mod swipe;
mod welcome_screen; mod welcome_screen;
@ -59,6 +61,8 @@ pub use progress::Progress;
pub use result::{ResultFooter, ResultScreen, ResultStyle}; pub use result::{ResultFooter, ResultScreen, ResultStyle};
pub use scroll::ScrollBar; pub use scroll::ScrollBar;
pub use set_brightness::SetBrightnessDialog; pub use set_brightness::SetBrightnessDialog;
#[cfg(feature = "translations")]
pub use share_words::ShareWords;
pub use simple_page::SimplePage; pub use simple_page::SimplePage;
pub use swipe::{Swipe, SwipeDirection}; pub use swipe::{Swipe, SwipeDirection};
pub use welcome_screen::WelcomeScreen; pub use welcome_screen::WelcomeScreen;

View File

@ -17,8 +17,7 @@ use super::{
pub struct SetBrightnessDialog(NumberInputSliderDialog); pub struct SetBrightnessDialog(NumberInputSliderDialog);
impl SetBrightnessDialog { impl SetBrightnessDialog {
pub fn new(current: Option<u8>) -> Self { pub fn new(current: u8) -> Self {
let current = current.unwrap_or(theme::backlight::get_backlight_normal());
Self(NumberInputSliderDialog::new( Self(NumberInputSliderDialog::new(
theme::backlight::get_backlight_min() as u16, theme::backlight::get_backlight_min() as u16,
theme::backlight::get_backlight_max() as u16, theme::backlight::get_backlight_max() as u16,

View File

@ -0,0 +1,114 @@
use crate::{
strutil::TString,
ui::{
component::{Component, Event, EventCtx, Never, Paginate},
display::Font,
geometry::{Offset, Rect},
model_tt::theme,
shape::{self, Renderer},
},
};
use heapless::Vec;
use ufmt::uwrite;
const WORDS_PER_PAGE: usize = 4;
const TOP_PADDING_OFFSET: i16 = 13;
const WORD_FONT: Font = Font::MONO;
const MAX_WORDS: usize = 33; // super-shamir has 33 words, all other have less
/// Showing the given share words.
pub struct ShareWords<'a> {
area: Rect,
share_words: Vec<TString<'a>, MAX_WORDS>,
page_index: usize,
}
impl<'a> ShareWords<'a> {
pub fn new(share_words: Vec<TString<'a>, MAX_WORDS>) -> Self {
Self {
area: Rect::zero(),
share_words,
page_index: 0,
}
}
fn total_page_count(&self) -> usize {
(self.share_words.len() + WORDS_PER_PAGE - 1) / WORDS_PER_PAGE
}
}
impl<'a> Component for ShareWords<'a> {
type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect {
self.area = bounds;
bounds
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
None
}
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
let line_height = WORD_FONT.line_height();
let ordinal_largest_on_this_page =
(WORDS_PER_PAGE * (self.page_index + 1)).min(self.share_words.len());
let is_largest_double_digit = ordinal_largest_on_this_page >= 10;
let mut y_offset = self.area.top_left().y + TOP_PADDING_OFFSET;
for (word_idx, word) in self
.share_words
.iter()
.enumerate()
.skip(self.page_index * WORDS_PER_PAGE)
.take(WORDS_PER_PAGE)
{
let ordinal = word_idx + 1;
let base = self.area.top_left() + Offset::y(y_offset);
word.map(|w| {
let double_digit = ordinal >= 10;
let text_fmt = if double_digit || !is_largest_double_digit {
uformat!("{}. {}", ordinal, w)
} else {
uformat!(" {}. {}", ordinal, w)
};
shape::Text::new(base, &text_fmt)
.with_font(WORD_FONT)
.with_fg(theme::FG)
.render(target);
});
y_offset += line_height;
}
}
}
impl<'a> Paginate for ShareWords<'a> {
fn page_count(&self) -> usize {
self.total_page_count()
}
fn change_page(&mut self, active_page: usize) {
self.page_index = active_page;
}
}
// DEBUG-ONLY SECTION BELOW
#[cfg(feature = "ui_debug")]
impl<'a> crate::trace::Trace for ShareWords<'a> {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.component("ShareWords");
let mut content = heapless::String::<64>::new();
for (word_idx, word) in self
.share_words
.iter()
.enumerate()
.skip(self.page_index * WORDS_PER_PAGE)
.take(WORDS_PER_PAGE)
{
let ordinal = word_idx + 1;
word.map(|w| unwrap!(uwrite!(content, "{}. {}\n", ordinal, w)));
}
t.string("screen_content", content.as_str().into());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,8 @@ use crate::ui::{
}; };
pub struct ModelTTFeatures; pub struct ModelTTFeatures;
#[cfg(feature = "micropython")]
pub mod ui_features_fw; pub mod ui_features_fw;
impl UIFeaturesCommon for ModelTTFeatures { impl UIFeaturesCommon for ModelTTFeatures {

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,384 @@
use crate::{error::Error, micropython::gc::Gc, strutil::TString}; use crate::{
error::Error,
io::BinaryData,
micropython::{gc::Gc, list::List, obj::Obj},
strutil::TString,
};
use heapless::Vec;
use super::layout::obj::{LayoutMaybeTrace, LayoutObj}; use super::layout::{
obj::{LayoutMaybeTrace, LayoutObj},
util::RecoveryType,
};
pub trait UIFeaturesFirmware { pub trait UIFeaturesFirmware {
fn confirm_action(
title: TString<'static>,
action: Option<TString<'static>>,
description: Option<TString<'static>>,
subtitle: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
hold: bool,
hold_danger: bool,
reverse: bool,
prompt_screen: bool,
prompt_title: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_address(
title: TString<'static>,
data: Obj, // TODO: replace Obj
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
verb: Option<TString<'static>>,
chunkify: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_blob(
title: TString<'static>,
data: Obj, // TODO: replace Obj
description: Option<TString<'static>>,
text_mono: bool,
extra: Option<TString<'static>>,
subtitle: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
info: bool,
hold: bool,
chunkify: bool,
page_counter: bool,
prompt_screen: bool,
cancel: bool,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn confirm_blob_intro(
title: TString<'static>,
data: Obj, // TODO: replace Obj
subtitle: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
chunkify: bool,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn confirm_homescreen(
title: TString<'static>,
image: BinaryData<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_coinjoin(
max_rounds: TString<'static>,
max_feerate: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_emphasized(
title: TString<'static>,
items: Obj, // TODO: replace Obj
verb: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_fido(
title: TString<'static>,
app_name: TString<'static>,
icon: Option<TString<'static>>,
accounts: Gc<List>, // TODO: replace Gc<List>
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_firmware_update(
description: TString<'static>,
fingerprint: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_modify_fee(
title: TString<'static>,
sign: i32,
user_fee_change: TString<'static>,
total_fee_new: TString<'static>,
fee_rate_amount: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_modify_output(
sign: i32,
amount_change: TString<'static>,
amount_new: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_more(
title: TString<'static>,
button: TString<'static>,
button_style_confirm: bool,
items: Obj, // TODO: replace Obj
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_properties(
title: TString<'static>,
items: Obj, // TODO: replace Obj`
hold: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_reset_device(recovery: bool) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_summary(
amount: TString<'static>,
amount_label: TString<'static>,
fee: TString<'static>,
fee_label: TString<'static>,
title: Option<TString<'static>>,
account_items: Option<Obj>, // TODO: replace Obj
extra_items: Option<Obj>, // TODO: replace Obj
extra_title: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn confirm_value(
title: TString<'static>,
value: Obj, // TODO: replace Obj
description: Option<TString<'static>>,
subtitle: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
info_button: bool,
hold: bool,
chunkify: bool,
text_mono: bool,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn confirm_with_info(
title: TString<'static>,
button: TString<'static>,
info_button: TString<'static>,
verb_cancel: Option<TString<'static>>,
items: Obj, // TODO: replace Obj
) -> Result<impl LayoutMaybeTrace, Error>;
fn continue_recovery_homepage(
text: TString<'static>,
subtext: Option<TString<'static>>,
button: Option<TString<'static>>,
recovery_type: RecoveryType,
show_instructions: bool,
remaining_shares: Option<Obj>, // TODO: replace Obj
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn check_homescreen_format(image: BinaryData, accept_toif: bool) -> bool;
fn flow_confirm_output(
title: Option<TString<'static>>,
subtitle: Option<TString<'static>>,
message: Obj, // TODO: replace Obj
amount: Option<Obj>, // TODO: replace Obj
chunkify: bool,
text_mono: bool,
account: Option<TString<'static>>,
account_path: Option<TString<'static>>,
br_code: u16,
br_name: TString<'static>,
address: Option<Obj>, // TODO: replace Obj
address_title: Option<TString<'static>>,
summary_items: Option<Obj>, // TODO: replace Obj
fee_items: Option<Obj>, // TODO: replace Obj
summary_title: Option<TString<'static>>,
summary_br_code: Option<u16>,
summary_br_name: Option<TString<'static>>,
cancel_text: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn flow_confirm_set_new_pin(
title: TString<'static>,
description: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn flow_get_address(
address: Obj, // TODO: replace Obj
title: TString<'static>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
chunkify: bool,
address_qr: TString<'static>,
case_sensitive: bool,
account: Option<TString<'static>>,
path: Option<TString<'static>>,
xpubs: Obj, // TODO: replace Obj
title_success: TString<'static>,
br_code: u16,
br_name: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
// TODO: this is TR specific and used only in confirm_set_new_pin
fn multiple_pages_texts(
title: TString<'static>,
verb: TString<'static>,
items: Gc<List>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn prompt_backup() -> Result<impl LayoutMaybeTrace, Error>;
fn request_bip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_slip39(
prompt: TString<'static>,
prefill_word: TString<'static>,
can_go_back: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_number(
title: TString<'static>,
count: u32,
min_count: u32,
max_count: u32,
description: Option<TString<'static>>,
more_info_callback: Option<impl Fn(u32) -> TString<'static> + 'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_pin(
prompt: TString<'static>,
subprompt: TString<'static>,
allow_cancel: bool,
warning: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn request_passphrase(
prompt: TString<'static>,
max_len: u32,
) -> Result<impl LayoutMaybeTrace, Error>;
fn select_word(
title: TString<'static>,
description: TString<'static>,
words: [TString<'static>; 3],
) -> Result<impl LayoutMaybeTrace, Error>;
fn select_word_count(recovery_type: RecoveryType) -> Result<impl LayoutMaybeTrace, Error>;
fn set_brightness(current_brightness: Option<u8>) -> Result<impl LayoutMaybeTrace, Error>;
fn show_address_details(
qr_title: TString<'static>,
address: TString<'static>,
case_sensitive: bool,
details_title: TString<'static>,
account: Option<TString<'static>>,
path: Option<TString<'static>>,
xpubs: Obj, // TODO: replace Obj
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_checklist(
title: TString<'static>,
button: TString<'static>,
active: usize,
items: [TString<'static>; 3],
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_danger(
title: TString<'static>,
description: TString<'static>,
value: TString<'static>,
verb_cancel: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_error(
title: TString<'static>,
button: TString<'static>,
description: TString<'static>,
allow_cancel: bool,
time_ms: u32,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn show_group_share_success(
lines: [TString<'static>; 4],
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_homescreen(
label: TString<'static>,
hold: bool,
notification: Option<TString<'static>>,
notification_level: u8,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_info( fn show_info(
title: TString<'static>, title: TString<'static>,
description: TString<'static>, description: TString<'static>,
button: TString<'static>, button: TString<'static>,
time_ms: u32, time_ms: u32,
) -> Result<Gc<LayoutObj>, Error>; ) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn show_info_with_cancel(
title: TString<'static>,
items: Obj, // TODO: replace Obj
horizontal: bool,
chunkify: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_lockscreen(
label: TString<'static>,
bootscreen: bool,
coinjoin_authorized: bool,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_mismatch(title: TString<'static>) -> Result<impl LayoutMaybeTrace, Error>;
fn show_progress(
description: TString<'static>,
indeterminate: bool,
title: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_progress_coinjoin(
title: TString<'static>,
indeterminate: bool,
time_ms: u32,
skip_first_paint: bool,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn show_remaining_shares(
pages_iterable: Obj, // TODO: replace Obj
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_share_words(
words: Vec<TString<'static>, 33>,
title: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
// TODO: merge with `show_share_words` instead of having specific version for mercury
fn show_share_words_mercury(
words: Vec<TString<'static>, 33>,
subtitle: Option<TString<'static>>,
instructions: Obj, // TODO: replace Obj
text_footer: Option<TString<'static>>, // footer description at instruction screen
text_confirm: TString<'static>,
) -> Result<impl LayoutMaybeTrace, Error>;
fn show_simple(
text: TString<'static>,
title: Option<TString<'static>>,
button: Option<TString<'static>>,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn show_success(
title: TString<'static>,
button: TString<'static>,
description: TString<'static>,
allow_cancel: bool,
time_ms: u32,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error>;
fn show_warning(
title: TString<'static>,
button: TString<'static>,
value: TString<'static>,
description: TString<'static>,
allow_cancel: bool,
time_ms: u32,
danger: bool,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn tutorial() -> Result<impl LayoutMaybeTrace, Error>;
} }

File diff suppressed because it is too large Load Diff

View File

@ -68,6 +68,466 @@ CANCELLED: UiResult
INFO: UiResult INFO: UiResult
# rust/src/ui/api/firmware_upy.rs
def check_homescreen_format(data: bytes) -> bool:
"""Check homescreen format and dimensions."""
# rust/src/ui/api/firmware_upy.rs
def disable_animation(disable: bool) -> None:
"""Disable animations, debug builds only."""
# rust/src/ui/api/firmware_upy.rs
def confirm_action(
*,
title: str,
action: str | None,
description: str | None,
subtitle: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
hold: bool = False,
hold_danger: bool = False,
reverse: bool = False,
prompt_screen: bool = False,
prompt_title: str | None = None,
) -> LayoutObj[UiResult]:
"""Confirm action."""
# rust/src/ui/api/firmware_upy.rs
def confirm_address(
*,
title: str,
data: str | bytes,
description: str | None,
extra: str | None,
verb: str | None = None,
chunkify: bool = False,
) -> LayoutObj[UiResult]:
"""Confirm address."""
# rust/src/ui/api/firmware_upy.rs
def confirm_blob(
*,
title: str,
data: str | bytes,
description: str | None,
text_mono: bool = True,
extra: str | None = None,
subtitle: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
verb_info: str | None = None,
info: bool = True,
hold: bool = False,
chunkify: bool = False,
page_counter: bool = False,
prompt_screen: bool = False,
cancel: bool = False,
) -> LayoutObj[UiResult]:
"""Confirm byte sequence data."""
# rust/src/ui/api/firmware_upy.rs
def confirm_blob_intro(
*,
title: str,
data: str | bytes,
subtitle: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
chunkify: bool = False,
) -> LayoutObj[UiResult]:
"""Confirm byte sequence data by showing only the first page of the data
and instructing the user to access the menu in order to view all the data,
which can then be confirmed using confirm_blob."""
# rust/src/ui/api/firmware_upy.rs
def confirm_coinjoin(
*,
max_rounds: str,
max_feerate: str,
) -> LayoutObj[UiResult]:
"""Confirm coinjoin authorization."""
# rust/src/ui/api/firmware_upy.rs
def confirm_emphasized(
*,
title: str,
items: Iterable[str | tuple[bool, str]],
verb: str | None = None,
) -> LayoutObj[UiResult]:
"""Confirm formatted text that has been pre-split in python. For tuples
the first component is a bool indicating whether this part is emphasized."""
# rust/src/ui/api/firmware_upy.rs
def confirm_fido(
*,
title: str,
app_name: str,
icon_name: str | None,
accounts: list[str | None],
) -> LayoutObj[int | UiResult]:
"""FIDO confirmation.
Returns page index in case of confirmation and CANCELLED otherwise.
"""
# rust/src/ui/api/firmware_upy.rs
def confirm_firmware_update(
*,
description: str,
fingerprint: str,
) -> LayoutObj[UiResult]:
"""Ask whether to update firmware, optionally show fingerprint."""
# rust/src/ui/api/firmware_upy.rs
def confirm_homescreen(
*,
title: str,
image: bytes,
) -> LayoutObj[UiResult]:
"""Confirm homescreen."""
# rust/src/ui/api/firmware_upy.rs
def confirm_modify_fee(
*,
title: str,
sign: int,
user_fee_change: str,
total_fee_new: str,
fee_rate_amount: str | None,
) -> LayoutObj[UiResult]:
"""Decrease or increase transaction fee."""
# rust/src/ui/api/firmware_upy.rs
def confirm_modify_output(
*,
sign: int,
amount_change: str,
amount_new: str,
) -> LayoutObj[UiResult]:
"""Decrease or increase output amount."""
# rust/src/ui/api/firmware_upy.rs
def confirm_more(
*,
title: str,
button: str,
button_style_confirm: bool = False,
items: Iterable[tuple[int, str | bytes]],
) -> LayoutObj[UiResult]:
"""Confirm long content with the possibility to go back from any page.
Meant to be used with confirm_with_info on model TT and TR."""
# rust/src/ui/api/firmware_upy.rs
def confirm_properties(
*,
title: str,
items: list[tuple[str | None, str | bytes | None, bool]],
hold: bool = False,
) -> LayoutObj[UiResult]:
"""Confirm list of key-value pairs. The third component in the tuple should be True if
the value is to be rendered as binary with monospace font, False otherwise."""
# rust/src/ui/api/firmware_upy.rs
def confirm_reset_device(recovery: bool) -> LayoutObj[UiResult]:
"""Confirm TOS before creating wallet creation or wallet recovery."""
# rust/src/ui/api/firmware_upy.rs
def confirm_summary(
*,
amount: str,
amount_label: str,
fee: str,
fee_label: str,
title: str | None = None,
account_items: Iterable[tuple[str, str]] | None = None,
extra_items: Iterable[tuple[str, str]] | None = None,
extra_title: str | None = None,
verb_cancel: str | None = None,
) -> LayoutObj[UiResult]:
"""Confirm summary of a transaction."""
# rust/src/ui/api/firmware_upy.rs
def confirm_value(
*,
title: str,
value: str,
description: str | None,
subtitle: str | None,
verb: str | None = None,
verb_info: str | None = None,
verb_cancel: str | None = None,
info_button: bool = False,
hold: bool = False,
chunkify: bool = False,
text_mono: bool = True,
) -> LayoutObj[UiResult]:
"""Confirm value. Merge of confirm_total and confirm_output."""
# rust/src/ui/api/firmware_upy.rs
def confirm_with_info(
*,
title: str,
button: str,
info_button: str,
verb_cancel: str | None = None,
items: Iterable[tuple[int, str | bytes]],
) -> LayoutObj[UiResult]:
"""Confirm given items but with third button. Always single page
without scrolling. In mercury, the button is placed in
context menu."""
# rust/src/ui/api/firmware_upy.rs
def continue_recovery_homepage(
*,
text: str,
subtext: str | None,
button: str | None,
recovery_type: RecoveryType,
show_instructions: bool = False, # unused on TT
remaining_shares: Iterable[tuple[str, str]] | None = None,
) -> LayoutObj[UiResult]:
"""Device recovery homescreen."""
# rust/src/ui/api/firmware_upy.rs
def flow_confirm_output(
*,
title: str | None,
subtitle: str | None,
message: str,
amount: str | None,
chunkify: bool,
text_mono: bool,
account: str | None,
account_path: str | None,
br_code: ButtonRequestType,
br_name: str,
address: str | None,
address_title: str | None,
summary_items: Iterable[tuple[str, str]] | None = None,
fee_items: Iterable[tuple[str, str]] | None = None,
summary_title: str | None = None,
summary_br_code: ButtonRequestType | None = None,
summary_br_name: str | None = None,
cancel_text: str | None = None,
) -> LayoutObj[UiResult]:
"""Confirm the recipient, (optionally) confirm the amount and (optionally) confirm the summary and present a Hold to Sign page."""
# rust/src/ui/api/firmware_upy.rs
def flow_confirm_set_new_pin(
*,
title: str,
description: str,
) -> LayoutObj[UiResult]:
"""Confirm new PIN setup with an option to cancel action."""
# rust/src/ui/api/firmware_upy.rs
def flow_get_address(
*,
address: str | bytes,
title: str,
description: str | None,
extra: str | None,
chunkify: bool,
address_qr: str,
case_sensitive: bool,
account: str | None,
path: str | None,
xpubs: list[tuple[str, str]],
title_success: str,
br_code: ButtonRequestType,
br_name: str,
) -> LayoutObj[UiResult]:
"""Get address / receive funds."""
# rust/src/ui/api/firmware_upy.rs
def multiple_pages_texts(
*,
title: str,
verb: str,
items: list[str],
) -> LayoutObj[UiResult]:
"""Show multiple texts, each on its own page. TR specific."""
# rust/src/ui/api/firmware_upy.rs
def prompt_backup() -> LayoutObj[UiResult]:
"""Strongly recommend user to do a backup."""
# rust/src/ui/api/firmware_upy.rs
def request_bip39(
*,
prompt: str,
prefill_word: str,
can_go_back: bool,
) -> LayoutObj[str]:
"""BIP39 word input keyboard."""
# rust/src/ui/api/firmware_upy.rs
def request_slip39(
*,
prompt: str,
prefill_word: str,
can_go_back: bool,
) -> LayoutObj[str]:
"""SLIP39 word input keyboard."""
# rust/src/ui/api/firmware_upy.rs
def request_number(
*,
title: str,
count: int,
min_count: int,
max_count: int,
description: str | None = None,
more_info_callback: Callable[[int], str] | None = None,
) -> LayoutObj[tuple[UiResult, int]]:
"""Number input with + and - buttons, optional static description and optional dynamic
description."""
# rust/src/ui/api/firmware_upy.rs
def request_pin(
*,
prompt: str,
subprompt: str,
allow_cancel: bool = True,
wrong_pin: bool = False,
) -> LayoutObj[str | UiResult]:
"""Request pin on device."""
# rust/src/ui/api/firmware_upy.rs
def request_passphrase(
*,
prompt: str,
max_len: int,
) -> LayoutObj[str | UiResult]:
"""Passphrase input keyboard."""
# rust/src/ui/api/firmware_upy.rs
def select_word(
*,
title: str,
description: str,
words: Iterable[str],
) -> LayoutObj[int]:
"""Select mnemonic word from three possibilities - seed check after backup. The
iterable must be of exact size. Returns index in range `0..3`."""
# rust/src/ui/api/firmware_upy.rs
def select_word_count(
*,
recovery_type: RecoveryType,
) -> LayoutObj[int | str]: # TR returns str
"""Select a mnemonic word count from the options: 12, 18, 20, 24, or 33.
For unlocking a repeated backup, select from 20 or 33."""
# rust/src/ui/api/firmware_upy.rs
def set_brightness(
*,
current: int | None = None
) -> LayoutObj[UiResult]:
"""Show the brightness configuration dialog."""
# rust/src/ui/api/firmware_upy.rs
def show_address_details(
*,
qr_title: str,
address: str,
case_sensitive: bool,
details_title: str,
account: str | None,
path: str | None,
xpubs: list[tuple[str, str]],
) -> LayoutObj[UiResult]:
"""Show address details - QR code, account, path, cosigner xpubs."""
# rust/src/ui/api/firmware_upy.rs
def show_checklist(
*,
title: str,
items: Iterable[str],
active: int,
button: str,
) -> LayoutObj[UiResult]:
"""Checklist of backup steps. Active index is highlighted, previous items have check
mark next to them. Limited to 3 items."""
# rust/src/ui/api/firmware_upy.rs
def show_danger(
*,
title: str,
description: str,
value: str = "",
verb_cancel: str | None = None,
) -> LayoutObj[UiResult]:
"""Warning modal that makes it easier to cancel than to continue."""
# rust/src/ui/api/firmware_upy.rs
def show_error(
*,
title: str,
button: str,
description: str = "",
allow_cancel: bool = True,
time_ms: int = 0,
) -> LayoutObj[UiResult]:
"""Error modal. No buttons shown when `button` is empty string."""
# rust/src/ui/api/firmware_upy.rs
def show_group_share_success(
*,
lines: Iterable[str],
) -> LayoutObj[UiResult]:
"""Shown after successfully finishing a group."""
# rust/src/ui/api/firmware_upy.rs
def show_homescreen(
*,
label: str | None,
hold: bool,
notification: str | None,
notification_level: int = 0,
skip_first_paint: bool,
) -> LayoutObj[UiResult]:
"""Idle homescreen."""
# rust/src/ui/api/firmware_upy.rs # rust/src/ui/api/firmware_upy.rs
def show_info( def show_info(
*, *,
@ -79,6 +539,133 @@ def show_info(
"""Info screen.""" """Info screen."""
# rust/src/ui/api/firmware_upy.rs
def show_info_with_cancel(
*,
title: str,
items: Iterable[Tuple[str, str]],
horizontal: bool = False,
chunkify: bool = False,
) -> LayoutObj[UiResult]:
"""Show metadata for outgoing transaction."""
# rust/src/ui/api/firmware_upy.rs
def show_lockscreen(
*,
label: str | None,
bootscreen: bool,
skip_first_paint: bool,
coinjoin_authorized: bool = False,
) -> LayoutObj[UiResult]:
"""Homescreen for locked device."""
# rust/src/ui/api/firmware_upy.rs
def show_mismatch(*, title: str) -> LayoutObj[UiResult]:
"""Warning of receiving address mismatch."""
# rust/src/ui/api/firmware_upy.rs
def show_progress(
*,
description: str,
indeterminate: bool = False,
title: str | None = None,
) -> LayoutObj[UiResult]:
"""Show progress loader. Please note that the number of lines reserved on screen for
description is determined at construction time. If you want multiline descriptions
make sure the initial description has at least that amount of lines."""
# rust/src/ui/api/firmware_upy.rs
def show_progress_coinjoin(
*,
title: str,
indeterminate: bool = False,
time_ms: int = 0,
skip_first_paint: bool = False,
) -> LayoutObj[UiResult]:
"""Show progress loader for coinjoin. Returns CANCELLED after a specified time when
time_ms timeout is passed."""
# rust/src/ui/api/firmware_upy.rs
def show_remaining_shares(
*,
pages: Iterable[tuple[str, str]],
) -> LayoutObj[UiResult]:
"""Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
# rust/src/ui/api/firmware_upy.rs
def show_share_words(
*,
words: Iterable[str],
title: str | None = None,
) -> LayoutObj[UiResult]:
"""Show mnemonic for backup."""
# rust/src/ui/api/firmware_upy.rs
def show_share_words_mercury(
*,
words: Iterable[str],
subtitle: str | None,
instructions: Iterable[str],
text_footer: str | None,
text_confirm: str,
) -> LayoutObj[UiResult]:
"""Show mnemonic for wallet backup preceded by an instruction screen and followed by a
confirmation screen."""
# rust/src/ui/api/firmware_upy.rs
def show_simple(
*,
text: str,
title: str | None = None,
button: str | None = None,
) -> LayoutObj[UiResult]:
"""Simple dialog with text. TT: optional button."""
# rust/src/ui/api/firmware_upy.rs
def show_success(
*,
title: str,
button: str,
description: str = "",
allow_cancel: bool = True,
time_ms: int = 0,
) -> LayoutObj[UiResult]:
"""Success modal. No buttons shown when `button` is empty string."""
# rust/src/ui/api/firmware_upy.rs
def show_wait_text(message: str, /) -> LayoutObj[None]:
"""Show single-line text in the middle of the screen."""
# rust/src/ui/api/firmware_upy.rs
def show_warning(
*,
title: str,
button: str,
value: str = "",
description: str = "",
allow_cancel: bool = True,
time_ms: int = 0,
danger: bool = False, # unused on TT
) -> LayoutObj[UiResult]:
"""Warning modal. TT: No buttons shown when `button` is empty string. TR: middle button and centered text."""
# rust/src/ui/api/firmware_upy.rs
def tutorial() -> LayoutObj[UiResult]:
"""Show user how to interact with the device."""
# rust/src/ui/api/firmware_upy.rs # rust/src/ui/api/firmware_upy.rs
class BacklightLevels: class BacklightLevels:
"""Backlight levels. Values dynamically update based on user settings.""" """Backlight levels. Values dynamically update based on user settings."""

View File

@ -1,7 +1,7 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import storage.device as storage_device import storage.device as storage_device
import trezorui2 import trezorui_api
from trezor import TR, utils from trezor import TR, utils
from trezor.enums import ButtonRequestType, DisplayRotation from trezor.enums import ButtonRequestType, DisplayRotation
from trezor.ui.layouts import confirm_action from trezor.ui.layouts import confirm_action
@ -25,7 +25,7 @@ def _validate_homescreen(homescreen: bytes) -> None:
raise DataError( raise DataError(
f"Homescreen is too large, maximum size is {storage_device.HOMESCREEN_MAXSIZE} bytes" f"Homescreen is too large, maximum size is {storage_device.HOMESCREEN_MAXSIZE} bytes"
) )
if not trezorui2.check_homescreen_format(homescreen): if not trezorui_api.check_homescreen_format(homescreen):
raise DataError("Wrong homescreen format") raise DataError("Wrong homescreen format")

View File

@ -67,7 +67,7 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
return await recovery_process() return await recovery_process()
if recovery_type == RecoveryType.NormalRecovery: if recovery_type == RecoveryType.NormalRecovery:
await confirm_reset_device(TR.recovery__title_recover, recovery=True) await confirm_reset_device(recovery=True)
# wipe storage to make sure the device is in a clear state # wipe storage to make sure the device is in a clear state
storage.reset() storage.reset()

View File

@ -55,7 +55,7 @@ async def reset_device(msg: ResetDevice) -> Success:
_validate_reset_device(msg) _validate_reset_device(msg)
# make sure user knows they're setting up a new wallet # make sure user knows they're setting up a new wallet
await confirm_reset_device(TR.reset__title_create_wallet) await confirm_reset_device()
# Rendering empty loader so users do not feel a freezing screen # Rendering empty loader so users do not feel a freezing screen
render_empty_loader(config.StorageMessage.PROCESSING_MSG) render_empty_loader(config.StorageMessage.PROCESSING_MSG)

View File

@ -24,7 +24,9 @@ else:
if __debug__: if __debug__:
trezorui2.disable_animation(utils.DISABLE_ANIMATION) from trezorui_api import disable_animation
disable_animation(utils.DISABLE_ANIMATION)
# all rendering is done through a singleton of `Display` # all rendering is done through a singleton of `Display`

View File

@ -1,7 +1,6 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import storage.cache as storage_cache import storage.cache as storage_cache
import trezorui2
import trezorui_api import trezorui_api
from storage.cache_common import APP_COMMON_BUSY_DEADLINE_MS from storage.cache_common import APP_COMMON_BUSY_DEADLINE_MS
from trezor import TR, ui from trezor import TR, ui
@ -57,7 +56,7 @@ class Homescreen(HomescreenBase):
level = 0 level = 0
super().__init__( super().__init__(
layout=trezorui2.show_homescreen( layout=trezorui_api.show_homescreen(
label=label, label=label,
notification=notification, notification=notification,
notification_level=level, notification_level=level,
@ -97,7 +96,7 @@ class Lockscreen(HomescreenBase):
not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR not bootscreen and storage_cache.homescreen_shown is self.RENDER_INDICATOR
) )
super().__init__( super().__init__(
layout=trezorui2.show_lockscreen( layout=trezorui_api.show_lockscreen(
label=label, label=label,
bootscreen=bootscreen, bootscreen=bootscreen,
skip_first_paint=skip, skip_first_paint=skip,
@ -118,7 +117,7 @@ class Busyscreen(HomescreenBase):
def __init__(self, delay_ms: int) -> None: def __init__(self, delay_ms: int) -> None:
super().__init__( super().__init__(
layout=trezorui2.show_progress_coinjoin( layout=trezorui_api.show_progress_coinjoin(
title=TR.coinjoin__waiting_for_others, title=TR.coinjoin__waiting_for_others,
indeterminate=True, indeterminate=True,
time_ms=delay_ms, time_ms=delay_ms,

View File

@ -44,7 +44,7 @@ def confirm_action(
description = description.format(description_param) description = description.format(description_param)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=title, title=title,
action=action, action=action,
description=description, description=description,
@ -74,12 +74,11 @@ def confirm_single(
# Placeholders are coming from translations in form of {0} # Placeholders are coming from translations in form of {0}
template_str = "{0}" template_str = "{0}"
if template_str not in description: assert template_str in description
template_str = "{}"
begin, _separator, end = description.partition(template_str) begin, _separator, end = description.partition(template_str)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_emphasized( trezorui_api.confirm_emphasized(
title=title, title=title,
items=(begin, (True, description_param), end), items=(begin, (True, description_param), end),
verb=verb, verb=verb,
@ -89,13 +88,15 @@ def confirm_single(
) )
def confirm_reset_device(_title: str, recovery: bool = False) -> Awaitable[None]: def confirm_reset_device(recovery: bool = False) -> Awaitable[None]:
return raise_if_not_confirmed(trezorui2.flow_confirm_reset(recovery=recovery), None) return raise_if_not_confirmed(
trezorui_api.confirm_reset_device(recovery=recovery), None
)
async def show_wallet_created_success() -> None: async def show_wallet_created_success() -> None:
await interact( await interact(
trezorui2.show_success(title=TR.backup__new_wallet_created, description=""), trezorui_api.show_success(title=TR.backup__new_wallet_created, button=""),
"backup_device", "backup_device",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
) )
@ -103,7 +104,7 @@ async def show_wallet_created_success() -> None:
async def prompt_backup() -> bool: async def prompt_backup() -> bool:
result = await interact( result = await interact(
trezorui2.flow_prompt_backup(), trezorui_api.prompt_backup(),
"backup_device", "backup_device",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
raise_on_cancel=None, raise_on_cancel=None,
@ -140,7 +141,7 @@ def confirm_multisig_warning() -> Awaitable[None]:
def confirm_multisig_different_paths_warning() -> Awaitable[None]: def confirm_multisig_different_paths_warning() -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_danger( trezorui_api.show_danger(
title=f"{TR.words__important}!", title=f"{TR.words__important}!",
description="Using different paths for different XPUBs.", description="Using different paths for different XPUBs.",
), ),
@ -158,7 +159,7 @@ def confirm_homescreen(
workflow.close_others() workflow.close_others()
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_homescreen( trezorui_api.confirm_homescreen(
title=TR.homescreen__title_set, title=TR.homescreen__title_set,
image=image, image=image,
), ),
@ -242,7 +243,7 @@ async def show_address(
) )
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.flow_get_address( trezorui_api.flow_get_address(
address=address, address=address,
title=title or TR.address__title_receive_address, title=title or TR.address__title_receive_address,
description=network or "", description=network or "",
@ -293,7 +294,7 @@ async def show_error_and_raise(
) -> NoReturn: ) -> NoReturn:
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
await interact( await interact(
trezorui2.show_error( trezorui_api.show_error(
title=subheader or "", title=subheader or "",
description=content, description=content,
button=button, button=button,
@ -315,7 +316,7 @@ def show_warning(
) -> Awaitable[None]: ) -> Awaitable[None]:
button = button or TR.buttons__continue # def_arg button = button or TR.buttons__continue # def_arg
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_warning( trezorui_api.show_warning(
title=TR.words__important, title=TR.words__important,
value=content, value=content,
button=subheader or TR.words__continue_anyway_question, button=subheader or TR.words__continue_anyway_question,
@ -337,7 +338,7 @@ def show_danger(
title = title or TR.words__warning title = title or TR.words__warning
verb_cancel = verb_cancel or TR.buttons__cancel verb_cancel = verb_cancel or TR.buttons__cancel
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_danger( trezorui_api.show_danger(
title=title, title=title,
description=content, description=content,
value=(value or ""), value=(value or ""),
@ -355,8 +356,9 @@ def show_success(
button: str | None = None, button: str | None = None,
) -> Awaitable[None]: ) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_success( trezorui_api.show_success(
title=content, title=content,
button="",
description=subheader if subheader else "", description=subheader if subheader else "",
), ),
br_name, br_name,
@ -387,7 +389,7 @@ async def confirm_output(
title = TR.send__title_sending_to title = TR.send__title_sending_to
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.flow_confirm_output( trezorui_api.flow_confirm_output(
title=TR.words__address, title=TR.words__address,
subtitle=title, subtitle=title,
message=address, message=address,
@ -422,7 +424,7 @@ async def should_show_payment_request_details(
Raises ActionCancelled if the user cancels. Raises ActionCancelled if the user cancels.
""" """
result = await interact( result = await interact(
trezorui2.confirm_with_info( trezorui_api.confirm_with_info(
title=TR.send__title_sending, title=TR.send__title_sending,
items=[(ui.NORMAL, f"{amount} to\n{recipient_name}")] items=[(ui.NORMAL, f"{amount} to\n{recipient_name}")]
+ [(ui.NORMAL, memo) for memo in memos], + [(ui.NORMAL, memo) for memo in memos],
@ -459,7 +461,7 @@ async def should_show_more(
confirm = TR.buttons__confirm confirm = TR.buttons__confirm
result = await interact( result = await interact(
trezorui2.confirm_with_info( trezorui_api.confirm_with_info(
title=title, title=title,
items=para, items=para,
button=confirm, button=confirm,
@ -495,7 +497,7 @@ def confirm_blob(
prompt_screen: bool = True, prompt_screen: bool = True,
) -> Awaitable[None]: ) -> Awaitable[None]:
if ask_pagination: if ask_pagination:
main_layout = trezorui2.confirm_blob_intro( main_layout = trezorui_api.confirm_blob_intro(
title=title, title=title,
data=data, data=data,
subtitle=description, subtitle=description,
@ -503,7 +505,7 @@ def confirm_blob(
verb_cancel=verb_cancel, verb_cancel=verb_cancel,
chunkify=chunkify, chunkify=chunkify,
) )
info_layout = trezorui2.confirm_blob( info_layout = trezorui_api.confirm_blob(
title=title, title=title,
data=data, data=data,
subtitle=description, subtitle=description,
@ -527,7 +529,7 @@ def confirm_blob(
info_layout_can_confirm=True, info_layout_can_confirm=True,
) )
else: else:
layout = trezorui2.confirm_blob( layout = trezorui_api.confirm_blob(
title=title, title=title,
data=data, data=data,
description=description, description=description,
@ -626,14 +628,14 @@ def confirm_value(
raise ValueError("Either verb or hold=True must be set") raise ValueError("Either verb or hold=True must be set")
info_items = info_items or [] info_items = info_items or []
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=info_title if info_title else TR.words__title_information, title=info_title if info_title else TR.words__title_information,
items=info_items, items=info_items,
chunkify=chunkify_info, chunkify=chunkify_info,
) )
return with_info( return with_info(
trezorui2.confirm_value( trezorui_api.confirm_value(
title=title, title=title,
subtitle=subtitle, subtitle=subtitle,
description=description, description=description,
@ -661,7 +663,7 @@ def confirm_properties(
items = [(prop[0], prop[1], isinstance(prop[1], bytes)) for prop in props] items = [(prop[0], prop[1], isinstance(prop[1], bytes)) for prop in props]
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_properties( trezorui_api.confirm_properties(
title=title, title=title,
items=items, items=items,
hold=hold, hold=hold,
@ -697,7 +699,7 @@ def confirm_total(
fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount)) fee_items.append((TR.confirm_total__fee_rate, fee_rate_amount))
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=total_amount, amount=total_amount,
amount_label=total_label, amount_label=total_label,
fee=fee_amount, fee=fee_amount,
@ -727,7 +729,7 @@ def _confirm_summary(
title = title or TR.words__title_summary # def_arg title = title or TR.words__title_summary # def_arg
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=amount, amount=amount,
amount_label=amount_label, amount_label=amount_label,
fee=fee, fee=fee,
@ -764,7 +766,7 @@ if not utils.BITCOIN_ONLY:
chunkify: bool = False, chunkify: bool = False,
) -> None: ) -> None:
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.flow_confirm_output( trezorui_api.flow_confirm_output(
title=TR.words__address, title=TR.words__address,
subtitle=( subtitle=(
TR.words__recipient TR.words__recipient
@ -817,7 +819,7 @@ if not utils.BITCOIN_ONLY:
(TR.send__maximum_fee, maximum_fee), (TR.send__maximum_fee, maximum_fee),
) )
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.flow_confirm_output( trezorui_api.flow_confirm_output(
title=verb, title=verb,
subtitle=None, subtitle=None,
message=intro_question, message=intro_question,
@ -935,14 +937,14 @@ async def confirm_modify_output(
amount_change: str, amount_change: str,
amount_new: str, amount_new: str,
) -> None: ) -> None:
address_layout = trezorui2.confirm_blob( address_layout = trezorui_api.confirm_blob(
title=TR.modify_amount__title, title=TR.modify_amount__title,
data=address, data=address,
verb=TR.buttons__continue, verb=TR.buttons__continue,
verb_cancel=None, verb_cancel=None,
description=f"{TR.words__address}:", description=f"{TR.words__address}:",
) )
modify_layout = trezorui2.confirm_modify_output( modify_layout = trezorui_api.confirm_modify_output(
sign=sign, sign=sign,
amount_change=amount_change, amount_change=amount_change,
amount_new=amount_new, amount_new=amount_new,
@ -974,7 +976,7 @@ def confirm_modify_fee(
total_fee_new: str, total_fee_new: str,
fee_rate_amount: str | None = None, fee_rate_amount: str | None = None,
) -> Awaitable[None]: ) -> Awaitable[None]:
fee_layout = trezorui2.confirm_modify_fee( fee_layout = trezorui_api.confirm_modify_fee(
title=title, title=title,
sign=sign, sign=sign,
user_fee_change=user_fee_change, user_fee_change=user_fee_change,
@ -984,7 +986,7 @@ def confirm_modify_fee(
items: list[tuple[str, str]] = [] items: list[tuple[str, str]] = []
if fee_rate_amount: if fee_rate_amount:
items.append((TR.bitcoin__new_fee_rate, fee_rate_amount)) items.append((TR.bitcoin__new_fee_rate, fee_rate_amount))
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee, title=TR.confirm_total__title_fee,
items=items, items=items,
) )
@ -993,7 +995,7 @@ def confirm_modify_fee(
def confirm_coinjoin(max_rounds: int, max_fee_per_vbyte: str) -> Awaitable[None]: def confirm_coinjoin(max_rounds: int, max_fee_per_vbyte: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_coinjoin( trezorui_api.confirm_coinjoin(
max_rounds=str(max_rounds), max_rounds=str(max_rounds),
max_feerate=max_fee_per_vbyte, max_feerate=max_fee_per_vbyte,
), ),
@ -1030,7 +1032,7 @@ async def confirm_signverify(
address_title = TR.sign_message__confirm_address address_title = TR.sign_message__confirm_address
br_name = "sign_message" br_name = "sign_message"
address_layout = trezorui2.confirm_value( address_layout = trezorui_api.confirm_value(
title=address_title, title=address_title,
subtitle=None, subtitle=None,
description="", description="",
@ -1053,17 +1055,18 @@ async def confirm_signverify(
) )
) )
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=TR.words__title_information, title=TR.words__title_information,
items=items, items=items,
horizontal=True, horizontal=True,
) )
message_layout = trezorui2.confirm_blob( message_layout = trezorui_api.confirm_blob(
title=TR.sign_message__confirm_message, title=TR.sign_message__confirm_message,
description=None, description=None,
data=message, data=message,
extra=None, extra=None,
prompt_screen=True,
hold=not verify, hold=not verify,
info=False, info=False,
verb=TR.buttons__confirm if verify else None, verb=TR.buttons__confirm if verify else None,
@ -1074,7 +1077,7 @@ async def confirm_signverify(
await with_info(address_layout, info_layout, br_name, br_code=BR_CODE_OTHER) await with_info(address_layout, info_layout, br_name, br_code=BR_CODE_OTHER)
except ActionCancelled: except ActionCancelled:
result = await interact( result = await interact(
trezorui2.show_mismatch(title=TR.addr_mismatch__mismatch), trezorui_api.show_mismatch(title=TR.addr_mismatch__mismatch),
None, None,
raise_on_cancel=None, raise_on_cancel=None,
) )
@ -1103,7 +1106,7 @@ def error_popup(
if subtitle: if subtitle:
title += f"\n{subtitle}" title += f"\n{subtitle}"
return trezorui2.show_error( return trezorui_api.show_error(
title=title, title=title,
description=description.format(description_param), description=description.format(description_param),
button=button, button=button,
@ -1114,20 +1117,20 @@ def error_popup(
def request_passphrase_on_host() -> None: def request_passphrase_on_host() -> None:
draw_simple( draw_simple(
trezorui2.show_simple( trezorui_api.show_simple(
title=None, title=None,
description=TR.passphrase__please_enter, text=TR.passphrase__please_enter,
) )
) )
def show_wait_text(message: str) -> None: def show_wait_text(message: str) -> None:
draw_simple(trezorui2.show_wait_text(message)) draw_simple(trezorui_api.show_wait_text(message))
def request_passphrase_on_device(max_len: int) -> Awaitable[str]: def request_passphrase_on_device(max_len: int) -> Awaitable[str]:
result = interact( result = interact(
trezorui2.flow_request_passphrase( trezorui_api.request_passphrase(
prompt=TR.passphrase__title_enter, max_len=max_len prompt=TR.passphrase__title_enter, max_len=max_len
), ),
"passphrase_device", "passphrase_device",
@ -1153,7 +1156,7 @@ def request_pin_on_device(
subprompt = f"{attempts_remaining} {TR.pin__tries_left}" subprompt = f"{attempts_remaining} {TR.pin__tries_left}"
result = interact( result = interact(
trezorui2.request_pin( trezorui_api.request_pin(
prompt=prompt, prompt=prompt,
subprompt=subprompt, subprompt=subprompt,
allow_cancel=allow_cancel, allow_cancel=allow_cancel,
@ -1207,7 +1210,7 @@ def confirm_set_new_pin(
br_code: ButtonRequestType = BR_CODE_OTHER, br_code: ButtonRequestType = BR_CODE_OTHER,
) -> Awaitable[None]: ) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.flow_confirm_set_new_pin(title=title, description=description), trezorui_api.flow_confirm_set_new_pin(title=title, description=description),
br_name, br_name,
br_code, br_code,
) )
@ -1215,7 +1218,7 @@ def confirm_set_new_pin(
def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[None]: def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_firmware_update( trezorui_api.confirm_firmware_update(
description=description, fingerprint=fingerprint description=description, fingerprint=fingerprint
), ),
"firmware_update", "firmware_update",
@ -1225,7 +1228,7 @@ def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[Non
def set_brightness(current: int | None = None) -> Awaitable[None]: def set_brightness(current: int | None = None) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.set_brightness(current=current), trezorui_api.set_brightness(current=current),
"set_brightness", "set_brightness",
BR_CODE_OTHER, BR_CODE_OTHER,
) )
@ -1234,7 +1237,7 @@ def set_brightness(current: int | None = None) -> Awaitable[None]:
def tutorial(br_code: ButtonRequestType = BR_CODE_OTHER) -> Awaitable[None]: def tutorial(br_code: ButtonRequestType = BR_CODE_OTHER) -> Awaitable[None]:
"""Showing users how to interact with the device.""" """Showing users how to interact with the device."""
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.tutorial(), trezorui_api.tutorial(),
"tutorial", "tutorial",
br_code, br_code,
) )

View File

@ -1,4 +1,3 @@
import trezorui2
import trezorui_api import trezorui_api
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -13,7 +12,7 @@ async def confirm_fido(
accounts: list[str | None], accounts: list[str | None],
) -> int: ) -> int:
"""Webauthn confirmation for one or more credentials.""" """Webauthn confirmation for one or more credentials."""
confirm = trezorui2.confirm_fido( confirm = trezorui_api.confirm_fido(
title=header, title=header,
app_name=app_name, app_name=app_name,
icon_name=icon_name, icon_name=icon_name,
@ -44,7 +43,7 @@ async def confirm_fido_reset() -> bool:
from trezor import TR from trezor import TR
confirm = ui.Layout( confirm = ui.Layout(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=TR.fido__title_reset, title=TR.fido__title_reset,
action=TR.fido__erase_credentials, action=TR.fido__erase_credentials,
description=TR.words__really_wanna, description=TR.words__really_wanna,

View File

@ -17,9 +17,10 @@ if TYPE_CHECKING:
async def request_word_count(recovery_type: RecoveryType) -> int: async def request_word_count(recovery_type: RecoveryType) -> int:
selector = trezorui2.select_word_count(recovery_type=recovery_type)
count = await interact( count = await interact(
selector, "recovery_word_count", ButtonRequestType.MnemonicWordCount trezorui_api.select_word_count(recovery_type=recovery_type),
"recovery_word_count",
ButtonRequestType.MnemonicWordCount,
) )
return int(count) return int(count)
@ -34,11 +35,11 @@ async def request_word(
prompt = TR.recovery__word_x_of_y_template.format(word_index + 1, word_count) prompt = TR.recovery__word_x_of_y_template.format(word_index + 1, word_count)
can_go_back = word_index > 0 can_go_back = word_index > 0
if is_slip39: if is_slip39:
keyboard = trezorui2.request_slip39( keyboard = trezorui_api.request_slip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
else: else:
keyboard = trezorui2.request_bip39( keyboard = trezorui_api.request_bip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
@ -85,7 +86,7 @@ def format_remaining_shares_info(
async def show_group_share_success(share_index: int, group_index: int) -> None: async def show_group_share_success(share_index: int, group_index: int) -> None:
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.show_group_share_success( trezorui_api.show_group_share_success(
lines=[ lines=[
TR.recovery__you_have_entered, TR.recovery__you_have_entered,
TR.recovery__share_num_template.format(share_index + 1), TR.recovery__share_num_template.format(share_index + 1),
@ -99,7 +100,7 @@ async def show_group_share_success(share_index: int, group_index: int) -> None:
async def continue_recovery( async def continue_recovery(
button_label: str, # unused on mercury _button_label: str, # unused on mercury
text: str, text: str,
subtext: str | None, subtext: str | None,
recovery_type: RecoveryType, recovery_type: RecoveryType,
@ -107,12 +108,13 @@ async def continue_recovery(
remaining_shares_info: "RemainingSharesInfo | None" = None, remaining_shares_info: "RemainingSharesInfo | None" = None,
) -> bool: ) -> bool:
result = await interact( result = await interact(
trezorui2.flow_continue_recovery( trezorui_api.continue_recovery_homepage(
first_screen=show_instructions,
recovery_type=recovery_type,
text=text, text=text,
subtext=subtext, subtext=subtext,
pages=( button=None,
recovery_type=recovery_type,
show_instructions=show_instructions,
remaining_shares=(
format_remaining_shares_info(remaining_shares_info) format_remaining_shares_info(remaining_shares_info)
if remaining_shares_info if remaining_shares_info
else None else None
@ -134,7 +136,7 @@ async def show_recovery_warning(
) -> None: ) -> None:
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.show_warning( trezorui_api.show_warning(
title=content or TR.words__warning, title=content or TR.words__warning,
value=subheader or "", value=subheader or "",
button=button, button=button,

View File

@ -1,6 +1,5 @@
from typing import Awaitable, Callable, Sequence from typing import Awaitable, Callable, Sequence
import trezorui2
import trezorui_api import trezorui_api
from trezor import TR, ui from trezor import TR, ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -17,9 +16,8 @@ def show_share_words(
share_index: int | None = None, share_index: int | None = None,
group_index: int | None = None, group_index: int | None = None,
) -> Awaitable[None]: ) -> Awaitable[None]:
title = TR.reset__recovery_wallet_backup_title
if share_index is None: if share_index is None:
subtitle = "" subtitle = None
elif group_index is None: elif group_index is None:
subtitle = TR.reset__recovery_share_title_template.format(share_index + 1) subtitle = TR.reset__recovery_share_title_template.format(share_index + 1)
else: else:
@ -27,24 +25,24 @@ 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)
description = "" description = None
text_info = [TR.reset__write_down_words_template.format(words_count)] instructions = [TR.reset__write_down_words_template.format(words_count)]
if words_count == 20 and share_index is None: if words_count == 20 and share_index is None:
# 1-of-1 SLIP39: inform the user about repeated words # 1-of-1 SLIP39: inform the user about repeated words
text_info.append(TR.reset__words_may_repeat) instructions.append(TR.reset__words_may_repeat)
if share_index == 0: if share_index == 0:
# regular SLIP39, 1st share # regular SLIP39, 1st share
description = TR.instructions__shares_start_with_1 description = TR.instructions__shares_start_with_1
text_info.append(TR.reset__repeat_for_all_shares) instructions.append(TR.reset__repeat_for_all_shares)
assert len(instructions) < 3
text_confirm = TR.reset__words_written_down_template.format(words_count) text_confirm = TR.reset__words_written_down_template.format(words_count)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.flow_show_share_words( trezorui_api.show_share_words_mercury(
title=title,
subtitle=subtitle,
words=share_words, words=share_words,
description=description, subtitle=subtitle,
text_info=text_info, instructions=instructions,
text_footer=description,
text_confirm=text_confirm, text_confirm=text_confirm,
), ),
None, None,
@ -75,7 +73,7 @@ async def select_word(
words.append(words[-1]) words.append(words[-1])
result = await interact( result = await interact(
trezorui2.select_word( trezorui_api.select_word(
title=title, title=title,
description=TR.reset__select_word_x_of_y_template.format( description=TR.reset__select_word_x_of_y_template.format(
checked_index + 1, count checked_index + 1, count
@ -98,7 +96,7 @@ async def slip39_show_checklist(
) -> None: ) -> None:
items = _slip_39_checklist_items(step, advanced, count, threshold) items = _slip_39_checklist_items(step, advanced, count, threshold)
result = await interact( result = await interact(
trezorui2.show_checklist( trezorui_api.show_checklist(
title=TR.reset__title_shamir_backup, title=TR.reset__title_shamir_backup,
button=TR.buttons__continue, button=TR.buttons__continue,
active=step, active=step,
@ -155,17 +153,17 @@ async def _prompt_number(
br_name: str, br_name: str,
) -> int: ) -> int:
result = await interact( result = await interact(
trezorui2.flow_request_number( trezorui_api.request_number(
title=title, title=title,
description=description,
count=count, count=count,
min_count=min_count, min_count=min_count,
max_count=max_count, max_count=max_count,
info=info, description=description,
br_code=ButtonRequestType.ResetDevice, more_info_callback=info,
br_name=br_name,
), ),
None, br_name,
ButtonRequestType.ResetDevice,
raise_on_cancel=None,
) )
if __debug__ and result is CONFIRMED: if __debug__ and result is CONFIRMED:
@ -301,7 +299,7 @@ async def show_intro_backup(single_share: bool, num_of_words: int | None) -> Non
def show_warning_backup() -> Awaitable[ui.UiResult]: def show_warning_backup() -> Awaitable[ui.UiResult]:
return interact( return interact(
trezorui2.show_warning( trezorui_api.show_warning(
title=TR.words__important, title=TR.words__important,
value=TR.reset__never_make_digital_copy, value=TR.reset__never_make_digital_copy,
button="", button="",
@ -328,7 +326,7 @@ def show_reset_warning(
br_code: ButtonRequestType = ButtonRequestType.Warning, br_code: ButtonRequestType = ButtonRequestType.Warning,
) -> Awaitable[None]: ) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_warning( trezorui_api.show_warning(
title=subheader or "", title=subheader or "",
description=content, description=content,
value="", value="",

View File

@ -1,4 +1,4 @@
import trezorui2 import trezorui_api
from trezor import TR, config, ui, utils from trezor import TR, config, ui, utils
@ -30,7 +30,7 @@ def progress(
description = TR.progress__please_wait # def_arg description = TR.progress__please_wait # def_arg
return ui.ProgressLayout( return ui.ProgressLayout(
layout=trezorui2.show_progress( layout=trezorui_api.show_progress(
description=description, description=description,
title=title, title=title,
indeterminate=indeterminate, indeterminate=indeterminate,
@ -44,7 +44,7 @@ def bitcoin_progress(message: str) -> ui.ProgressLayout:
def coinjoin_progress(message: str) -> ui.ProgressLayout: def coinjoin_progress(message: str) -> ui.ProgressLayout:
return ui.ProgressLayout( return ui.ProgressLayout(
layout=trezorui2.show_progress_coinjoin(title=message, indeterminate=False) layout=trezorui_api.show_progress_coinjoin(title=message, indeterminate=False)
) )

View File

@ -70,7 +70,7 @@ def confirm_action(
description = description.format(description_param) description = description.format(description_param)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=title, title=title,
action=action, action=action,
description=description, description=description,
@ -109,19 +109,10 @@ def confirm_single(
def confirm_reset_device( def confirm_reset_device(
title: str,
recovery: bool = False, recovery: bool = False,
) -> Awaitable[None]: ) -> Awaitable[None]:
if recovery:
button = TR.reset__button_recover
else:
button = TR.reset__button_create
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_reset_device( trezorui_api.confirm_reset_device(recovery=recovery),
title=title,
button=button,
),
"recover_device" if recovery else "setup_device", "recover_device" if recovery else "setup_device",
ButtonRequestType.ProtectCall if recovery else ButtonRequestType.ResetDevice, ButtonRequestType.ProtectCall if recovery else ButtonRequestType.ResetDevice,
) )
@ -137,7 +128,7 @@ async def prompt_backup() -> bool:
br_code = ButtonRequestType.ResetDevice br_code = ButtonRequestType.ResetDevice
result = await interact( result = await interact(
trezorui2.confirm_backup(), trezorui_api.prompt_backup(),
br_name, br_name,
br_code, br_code,
raise_on_cancel=None, raise_on_cancel=None,
@ -146,7 +137,7 @@ async def prompt_backup() -> bool:
return True return True
result = await interact( result = await interact(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=TR.backup__title_skip, title=TR.backup__title_skip,
action=None, action=None,
description=TR.backup__want_to_skip, description=TR.backup__want_to_skip,
@ -192,7 +183,7 @@ def confirm_multisig_different_paths_warning() -> Awaitable[ui.UiResult]:
def confirm_homescreen(image: bytes) -> Awaitable[None]: def confirm_homescreen(image: bytes) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_homescreen( trezorui_api.confirm_homescreen(
title=TR.homescreen__title_set, title=TR.homescreen__title_set,
image=image, image=image,
), ),
@ -265,7 +256,7 @@ async def show_address(
while True: while True:
result = await interact( result = await interact(
trezorui2.confirm_address( trezorui_api.confirm_address(
title=title, title=title,
data=address, data=address,
description="", # unused on TR description="", # unused on TR
@ -296,7 +287,7 @@ async def show_address(
return result return result
result = await interact( result = await interact(
trezorui2.show_address_details( trezorui_api.show_address_details(
qr_title="", # unused on this model qr_title="", # unused on this model
address=address if address_qr is None else address_qr, address=address if address_qr is None else address_qr,
case_sensitive=case_sensitive, case_sensitive=case_sensitive,
@ -314,7 +305,7 @@ async def show_address(
# User pressed left cancel button, show mismatch dialogue. # User pressed left cancel button, show mismatch dialogue.
else: else:
result = await interact( result = await interact(
trezorui2.show_mismatch(title=mismatch_title), trezorui_api.show_mismatch(title=mismatch_title),
None, None,
raise_on_cancel=None, raise_on_cancel=None,
) )
@ -410,9 +401,10 @@ def show_warning(
content = content + "\n" content = content + "\n"
return interact( return interact(
trezorui2.show_warning( # type: ignore [Argument missing for parameter "title"] trezorui_api.show_warning( # type: ignore [Argument missing for parameter "title"]
title="",
button=button, button=button,
warning=content, # type: ignore [No parameter named "warning"] value=content,
description=subheader or "", description=subheader or "",
), ),
br_name, br_name,
@ -494,10 +486,13 @@ async def confirm_output(
while True: while True:
await interact( await interact(
trezorui2.confirm_output_address( trezorui_api.confirm_blob(
address=address, title=address_title,
address_label=address_label or "", data=address,
address_title=address_title, description=address_label or "",
subtitle=None,
verb=TR.buttons__continue,
verb_cancel="",
chunkify=chunkify, chunkify=chunkify,
), ),
"confirm_output", "confirm_output",
@ -506,9 +501,13 @@ async def confirm_output(
try: try:
await interact( await interact(
trezorui2.confirm_output_amount( trezorui_api.confirm_blob(
amount_title=amount_title, title=amount_title,
amount=amount, data=amount,
description=None,
subtitle=None,
verb_cancel="^",
verb=TR.buttons__confirm,
), ),
"confirm_output", "confirm_output",
br_code, br_code,
@ -522,7 +521,7 @@ async def confirm_output(
def tutorial(br_code: ButtonRequestType = BR_CODE_OTHER) -> Awaitable[ui.UiResult]: def tutorial(br_code: ButtonRequestType = BR_CODE_OTHER) -> Awaitable[ui.UiResult]:
"""Showing users how to interact with the device.""" """Showing users how to interact with the device."""
return interact(trezorui2.tutorial(), "tutorial", br_code) return interact(trezorui_api.tutorial(), "tutorial", br_code)
async def should_show_payment_request_details( async def should_show_payment_request_details(
@ -559,11 +558,11 @@ async def should_show_more(
confirm = TR.buttons__confirm confirm = TR.buttons__confirm
result = await interact( result = await interact(
trezorui2.confirm_with_info( trezorui_api.confirm_with_info(
title=title, title=title,
items=para, items=para,
button=confirm, button=confirm,
verb_cancel=verb_cancel, # type: ignore [No parameter named "verb_cancel"] verb_cancel=verb_cancel,
info_button=button_text, # unused on TR info_button=button_text, # unused on TR
), ),
br_name, br_name,
@ -594,7 +593,7 @@ def confirm_blob(
prompt_screen: bool = True, prompt_screen: bool = True,
) -> Awaitable[None]: ) -> Awaitable[None]:
verb = verb or TR.buttons__confirm # def_arg verb = verb or TR.buttons__confirm # def_arg
layout = trezorui2.confirm_blob( layout = trezorui_api.confirm_blob(
title=title, title=title,
description=description, description=description,
data=data, data=data,
@ -624,7 +623,7 @@ async def _confirm_ask_pagination(
data = hexlify(data).decode() data = hexlify(data).decode()
confirm_more_layout = trezorui2.confirm_more( confirm_more_layout = trezorui_api.confirm_more(
title=title, title=title,
button=TR.buttons__confirm, button=TR.buttons__confirm,
items=[(ui.NORMAL, description), (ui.MONO, data)], items=[(ui.NORMAL, description), (ui.MONO, data)],
@ -720,7 +719,7 @@ def confirm_properties(
return (key, value, bool(is_data)) return (key, value, bool(is_data))
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_properties( trezorui_api.confirm_properties(
title=title, title=title,
items=map(handle_bytes, props), # type: ignore [cannot be assigned to parameter "items"] items=map(handle_bytes, props), # type: ignore [cannot be assigned to parameter "items"]
hold=hold, hold=hold,
@ -749,11 +748,12 @@ async def confirm_value(
if info_items is None: if info_items is None:
return await raise_if_not_confirmed( return await raise_if_not_confirmed(
trezorui2.confirm_value( # type: ignore [Argument missing for parameter "subtitle"] trezorui_api.confirm_value( # type: ignore [Argument missing for parameter "subtitle"]
title=title, title=title,
description=description, description=description,
value=value, value=value,
verb=verb or TR.buttons__hold_to_confirm, verb=verb or TR.buttons__hold_to_confirm,
verb_cancel="",
hold=hold, hold=hold,
), ),
br_name, br_name,
@ -768,7 +768,7 @@ async def confirm_value(
send_button_request = True send_button_request = True
while True: while True:
result = await interact( result = await interact(
trezorui2.confirm_with_info( trezorui_api.confirm_with_info(
title=title, title=title,
items=((ui.NORMAL, value),), items=((ui.NORMAL, value),),
button=verb or TR.buttons__confirm, button=verb or TR.buttons__confirm,
@ -784,7 +784,7 @@ async def confirm_value(
elif result is INFO: elif result is INFO:
info_title, info_value = info_items_list[0] info_title, info_value = info_items_list[0]
await interact( await interact(
trezorui2.confirm_blob( trezorui_api.confirm_blob(
title=info_title, title=info_title,
data=info_value, data=info_value,
description=description, description=description,
@ -824,7 +824,7 @@ def confirm_total(
account_info_items.append((TR.words__account_colon, source_account)) account_info_items.append((TR.words__account_colon, source_account))
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=total_amount, amount=total_amount,
amount_label=total_label, amount_label=total_label,
fee=fee_amount, fee=fee_amount,
@ -880,7 +880,7 @@ if not utils.BITCOIN_ONLY:
amount_title = f"{TR.words__amount}:" amount_title = f"{TR.words__amount}:"
amount_value = total_amount amount_value = total_amount
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=amount_value, amount=amount_value,
amount_label=amount_title, amount_label=amount_title,
fee=maximum_fee, fee=maximum_fee,
@ -906,7 +906,7 @@ if not utils.BITCOIN_ONLY:
) # def_arg ) # def_arg
fee_title = fee_title or TR.words__fee # def_arg fee_title = fee_title or TR.words__fee # def_arg
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=amount, amount=amount,
amount_label=amount_title, amount_label=amount_title,
fee=fee, fee=fee,
@ -928,7 +928,7 @@ if not utils.BITCOIN_ONLY:
fee_title = TR.send__including_fee fee_title = TR.send__including_fee
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=amount, amount=amount,
amount_label=amount_title, amount_label=amount_title,
fee=fee, fee=fee,
@ -951,7 +951,7 @@ if not utils.BITCOIN_ONLY:
br_code: ButtonRequestType = ButtonRequestType.SignTx, br_code: ButtonRequestType = ButtonRequestType.SignTx,
chunkify: bool = False, chunkify: bool = False,
) -> None: ) -> None:
summary_layout = trezorui2.confirm_summary( summary_layout = trezorui_api.confirm_summary(
amount=total_amount, amount=total_amount,
amount_label=f"{TR.words__amount}:", amount_label=f"{TR.words__amount}:",
fee=maximum_fee, fee=maximum_fee,
@ -987,13 +987,15 @@ if not utils.BITCOIN_ONLY:
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]: def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
return raise_if_not_confirmed( return confirm_properties(
trezorui2.confirm_joint_total(
spending_amount=spending_amount,
total_amount=total_amount,
),
"confirm_joint_total", "confirm_joint_total",
ButtonRequestType.SignTx, TR.joint__title,
[
(TR.joint__you_are_contributing, spending_amount),
(TR.joint__to_the_total_amount, total_amount),
],
hold=True,
br_code=ButtonRequestType.SignTx,
) )
@ -1031,14 +1033,14 @@ async def confirm_modify_output(
amount_change: str, amount_change: str,
amount_new: str, amount_new: str,
) -> None: ) -> None:
address_layout = trezorui2.confirm_blob( address_layout = trezorui_api.confirm_blob(
title=TR.modify_amount__title, title=TR.modify_amount__title,
data=address, data=address,
verb=TR.buttons__continue, verb=TR.buttons__continue,
description=f"{TR.words__address}:", description=f"{TR.words__address}:",
) )
modify_layout = trezorui2.confirm_modify_output( modify_layout = trezorui_api.confirm_modify_output(
sign=sign, sign=sign,
amount_change=amount_change, amount_change=amount_change,
amount_new=amount_new, amount_new=amount_new,
@ -1072,7 +1074,7 @@ def confirm_modify_fee(
fee_rate_amount: str | None = None, fee_rate_amount: str | None = None,
) -> Awaitable[None]: ) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_modify_fee( trezorui_api.confirm_modify_fee(
title=title, title=title,
sign=sign, sign=sign,
user_fee_change=user_fee_change, user_fee_change=user_fee_change,
@ -1086,7 +1088,7 @@ def confirm_modify_fee(
def confirm_coinjoin(max_rounds: int, max_fee_per_vbyte: str) -> Awaitable[None]: def confirm_coinjoin(max_rounds: int, max_fee_per_vbyte: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_coinjoin( trezorui_api.confirm_coinjoin(
max_rounds=str(max_rounds), max_rounds=str(max_rounds),
max_feerate=max_fee_per_vbyte, max_feerate=max_fee_per_vbyte,
), ),
@ -1133,7 +1135,7 @@ async def confirm_signverify(
) )
try: try:
await raise_if_not_confirmed( await raise_if_not_confirmed(
trezorui2.confirm_blob( trezorui_api.confirm_blob(
title=TR.sign_message__confirm_message, title=TR.sign_message__confirm_message,
description=None, description=None,
data=message, data=message,
@ -1174,16 +1176,21 @@ def error_popup(
def request_passphrase_on_host() -> None: def request_passphrase_on_host() -> None:
draw_simple(trezorui2.show_passphrase()) draw_simple(
trezorui_api.show_simple(
title=None,
text=TR.passphrase__please_enter,
)
)
def show_wait_text(message: str) -> None: def show_wait_text(message: str) -> None:
draw_simple(trezorui2.show_wait_text(message)) draw_simple(trezorui_api.show_wait_text(message))
async def request_passphrase_on_device(max_len: int) -> str: async def request_passphrase_on_device(max_len: int) -> str:
result = await interact( result = await interact(
trezorui2.request_passphrase( trezorui_api.request_passphrase(
prompt=TR.passphrase__title_enter, prompt=TR.passphrase__title_enter,
max_len=max_len, max_len=max_len,
), ),
@ -1213,7 +1220,7 @@ async def request_pin_on_device(
subprompt = f"{attempts_remaining} {TR.pin__tries_left}" subprompt = f"{attempts_remaining} {TR.pin__tries_left}"
result = await interact( result = await interact(
trezorui2.request_pin( trezorui_api.request_pin(
prompt=prompt, prompt=prompt,
subprompt=subprompt, subprompt=subprompt,
allow_cancel=allow_cancel, allow_cancel=allow_cancel,
@ -1252,7 +1259,7 @@ def _confirm_multiple_pages_texts(
br_code: ButtonRequestType = BR_CODE_OTHER, br_code: ButtonRequestType = BR_CODE_OTHER,
) -> Awaitable[None]: ) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.multiple_pages_texts( trezorui_api.multiple_pages_texts(
title=title, title=title,
verb=verb, verb=verb,
items=items, items=items,
@ -1321,7 +1328,7 @@ async def confirm_set_new_pin(
def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[None]: def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_firmware_update( trezorui_api.confirm_firmware_update(
description=description, fingerprint=fingerprint description=description, fingerprint=fingerprint
), ),
"firmware_update", "firmware_update",

View File

@ -1,4 +1,3 @@
import trezorui2
import trezorui_api import trezorui_api
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -9,13 +8,14 @@ from ..common import interact
async def confirm_fido( async def confirm_fido(
header: str, header: str,
app_name: str, app_name: str,
icon_name: str | None, _icon_name: str | None, # unused on TR
accounts: list[str | None], accounts: list[str | None],
) -> int: ) -> int:
"""Webauthn confirmation for one or more credentials.""" """Webauthn confirmation for one or more credentials."""
confirm = trezorui2.confirm_fido( # type: ignore [Argument missing for parameter "icon_name"] confirm = trezorui_api.confirm_fido( # type: ignore [Argument missing for parameter "icon_name"]
title=header, title=header,
app_name=app_name, app_name=app_name,
icon_name=None,
accounts=accounts, accounts=accounts,
) )
result = await interact(confirm, "confirm_fido", ButtonRequestType.Other) result = await interact(confirm, "confirm_fido", ButtonRequestType.Other)
@ -34,7 +34,7 @@ async def confirm_fido(
async def confirm_fido_reset() -> bool: async def confirm_fido_reset() -> bool:
from trezor import TR from trezor import TR
confirm = trezorui2.confirm_action( confirm = trezorui_api.confirm_action(
title=TR.fido__title_reset, title=TR.fido__title_reset,
description=TR.fido__wanna_erase_credentials, description=TR.fido__wanna_erase_credentials,
action=None, action=None,

View File

@ -16,7 +16,7 @@ if TYPE_CHECKING:
async def request_word_count(recovery_type: RecoveryType) -> int: async def request_word_count(recovery_type: RecoveryType) -> int:
count = await interact( count = await interact(
trezorui2.select_word_count(recovery_type=recovery_type), trezorui_api.select_word_count(recovery_type=recovery_type),
"recovery_word_count", "recovery_word_count",
ButtonRequestType.MnemonicWordCount, ButtonRequestType.MnemonicWordCount,
) )
@ -36,12 +36,12 @@ async def request_word(
can_go_back = word_index > 0 can_go_back = word_index > 0
if is_slip39: if is_slip39:
keyboard = trezorui2.request_slip39( keyboard = trezorui_api.request_slip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
else: else:
keyboard = trezorui2.request_bip39( keyboard = trezorui_api.request_bip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
@ -65,7 +65,7 @@ def show_group_share_success(
share_index: int, group_index: int share_index: int, group_index: int
) -> Awaitable[ui.UiResult]: ) -> Awaitable[ui.UiResult]:
return interact( return interact(
trezorui2.show_group_share_success( trezorui_api.show_group_share_success(
lines=[ lines=[
TR.recovery__you_have_entered, TR.recovery__you_have_entered,
TR.recovery__share_num_template.format(share_index + 1), TR.recovery__share_num_template.format(share_index + 1),
@ -123,13 +123,13 @@ async def continue_recovery(
if subtext: if subtext:
text += f"\n\n{subtext}" text += f"\n\n{subtext}"
homepage = trezorui2.confirm_recovery( homepage = trezorui_api.continue_recovery_homepage(
title="", text=text,
description=text, subtext=None,
button=button_label, button=button_label,
recovery_type=recovery_type, recovery_type=recovery_type,
info_button=False,
show_instructions=show_instructions, show_instructions=show_instructions,
remaining_shares=None,
) )
while True: while True:
result = await interact( result = await interact(

View File

@ -1,6 +1,5 @@
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import trezorui2
from trezor import TR from trezor import TR
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
import trezorui_api import trezorui_api
@ -50,8 +49,9 @@ async def show_share_words(
) )
result = await interact( result = await interact(
trezorui2.show_share_words( # type: ignore [Arguments missing for parameters] trezorui_api.show_share_words(
share_words=share_words, # type: ignore [No parameter named "share_words"] words=share_words,
title=None,
), ),
br_name, br_name,
br_code, br_code,
@ -88,7 +88,7 @@ async def select_word(
word_ordinal = format_ordinal(checked_index + 1) word_ordinal = format_ordinal(checked_index + 1)
result = await interact( result = await interact(
trezorui2.select_word( trezorui_api.select_word(
title="", title="",
description=TR.reset__select_word_template.format(word_ordinal), description=TR.reset__select_word_template.format(word_ordinal),
words=(words[0].lower(), words[1].lower(), words[2].lower()), words=(words[0].lower(), words[1].lower(), words[2].lower()),
@ -122,7 +122,7 @@ def slip39_show_checklist(
) )
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_checklist( trezorui_api.show_checklist(
title=TR.reset__slip39_checklist_title, title=TR.reset__slip39_checklist_title,
button=TR.buttons__continue, button=TR.buttons__continue,
active=step, active=step,
@ -140,7 +140,7 @@ async def _prompt_number(
max_count: int, max_count: int,
br_name: str, br_name: str,
) -> int: ) -> int:
num_input = trezorui2.request_number( num_input = trezorui_api.request_number(
title=title, title=title,
count=count, count=count,
min_count=min_count, min_count=min_count,

View File

@ -42,7 +42,7 @@ def confirm_action(
description = description.format(description_param) description = description.format(description_param)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=title, title=title,
action=action, action=action,
description=description, description=description,
@ -74,7 +74,7 @@ def confirm_single(
begin, _separator, end = description.partition(template_str) begin, _separator, end = description.partition(template_str)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_emphasized( trezorui_api.confirm_emphasized(
title=title, title=title,
items=(begin, (True, description_param), end), items=(begin, (True, description_param), end),
verb=verb, verb=verb,
@ -84,17 +84,9 @@ def confirm_single(
) )
def confirm_reset_device(title: str, recovery: bool = False) -> Awaitable[None]: def confirm_reset_device(recovery: bool = False) -> Awaitable[None]:
if recovery:
button = TR.reset__button_recover
else:
button = TR.reset__button_create
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_reset_device( trezorui_api.confirm_reset_device(recovery=recovery),
title=title,
button=button,
),
"recover_device" if recovery else "setup_device", "recover_device" if recovery else "setup_device",
(ButtonRequestType.ProtectCall if recovery else ButtonRequestType.ResetDevice), (ButtonRequestType.ProtectCall if recovery else ButtonRequestType.ResetDevice),
) )
@ -108,7 +100,7 @@ async def show_wallet_created_success() -> None:
# TODO cleanup @ redesign # TODO cleanup @ redesign
async def prompt_backup() -> bool: async def prompt_backup() -> bool:
result = await interact( result = await interact(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=TR.words__title_success, title=TR.words__title_success,
action=TR.backup__new_wallet_successfully_created, action=TR.backup__new_wallet_successfully_created,
description=TR.backup__it_should_be_backed_up, description=TR.backup__it_should_be_backed_up,
@ -123,7 +115,7 @@ async def prompt_backup() -> bool:
return True return True
result = await interact( result = await interact(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=TR.words__warning, title=TR.words__warning,
action=TR.backup__want_to_skip, action=TR.backup__want_to_skip,
description=TR.backup__can_back_up_anytime, description=TR.backup__can_back_up_anytime,
@ -144,7 +136,7 @@ def confirm_path_warning(path: str, path_type: str | None = None) -> Awaitable[N
else f"{TR.words__unknown} {path_type.lower()}." else f"{TR.words__unknown} {path_type.lower()}."
) )
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_warning( trezorui_api.show_warning(
title=title, title=title,
value=path, value=path,
description=TR.words__continue_anyway_question, description=TR.words__continue_anyway_question,
@ -173,7 +165,7 @@ def confirm_multisig_different_paths_warning() -> Awaitable[None]:
def confirm_homescreen(image: bytes) -> Awaitable[None]: def confirm_homescreen(image: bytes) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_homescreen( trezorui_api.confirm_homescreen(
title=TR.homescreen__title_set, title=TR.homescreen__title_set,
image=image, image=image,
), ),
@ -250,7 +242,7 @@ async def show_address(
while True: while True:
result = await interact( result = await interact(
trezorui2.confirm_address( trezorui_api.confirm_address(
title=title, title=title,
data=address, data=address,
description=network or "", description=network or "",
@ -281,7 +273,7 @@ async def show_address(
return result return result
result = await interact( result = await interact(
trezorui2.show_address_details( trezorui_api.show_address_details(
qr_title=title, qr_title=title,
address=address if address_qr is None else address_qr, address=address if address_qr is None else address_qr,
case_sensitive=case_sensitive, case_sensitive=case_sensitive,
@ -297,7 +289,7 @@ async def show_address(
else: else:
result = await interact( result = await interact(
trezorui2.show_mismatch(title=mismatch_title), trezorui_api.show_mismatch(title=mismatch_title),
None, None,
raise_on_cancel=None, raise_on_cancel=None,
) )
@ -339,7 +331,7 @@ async def show_error_and_raise(
) -> NoReturn: ) -> NoReturn:
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
await interact( await interact(
trezorui2.show_error( trezorui_api.show_error(
title=subheader or "", title=subheader or "",
description=content, description=content,
button=button, button=button,
@ -363,7 +355,7 @@ def show_warning(
) -> Awaitable[None]: ) -> Awaitable[None]:
button = button or TR.buttons__continue # def_arg button = button or TR.buttons__continue # def_arg
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_warning( trezorui_api.show_warning(
title=content, title=content,
description=subheader or "", description=subheader or "",
button=button, button=button,
@ -397,7 +389,7 @@ def show_success(
) -> Awaitable[None]: ) -> Awaitable[None]:
button = button or TR.buttons__continue # def_arg button = button or TR.buttons__continue # def_arg
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_success( trezorui_api.show_success(
title=content, title=content,
description=subheader or "", description=subheader or "",
button=button, button=button,
@ -436,7 +428,7 @@ async def confirm_output(
while True: while True:
# if the user cancels here, raise ActionCancelled (by default) # if the user cancels here, raise ActionCancelled (by default)
await interact( await interact(
trezorui2.confirm_value( trezorui_api.confirm_value(
title=recipient_title, title=recipient_title,
subtitle=address_label, subtitle=address_label,
description=None, description=None,
@ -452,7 +444,7 @@ async def confirm_output(
try: try:
await interact( await interact(
trezorui2.confirm_value( trezorui_api.confirm_value(
title=amount_title, title=amount_title,
subtitle=None, subtitle=None,
description=None, description=None,
@ -483,7 +475,7 @@ async def should_show_payment_request_details(
Raises ActionCancelled if the user cancels. Raises ActionCancelled if the user cancels.
""" """
result = await interact( result = await interact(
trezorui2.confirm_with_info( trezorui_api.confirm_with_info(
title=TR.send__title_sending, title=TR.send__title_sending,
items=[(ui.NORMAL, f"{amount} to\n{recipient_name}")] items=[(ui.NORMAL, f"{amount} to\n{recipient_name}")]
+ [(ui.NORMAL, memo) for memo in memos], + [(ui.NORMAL, memo) for memo in memos],
@ -520,7 +512,7 @@ async def should_show_more(
confirm = TR.buttons__confirm confirm = TR.buttons__confirm
result = await interact( result = await interact(
trezorui2.confirm_with_info( trezorui_api.confirm_with_info(
title=title, title=title,
items=para, items=para,
button=confirm, button=confirm,
@ -551,7 +543,7 @@ async def _confirm_ask_pagination(
data = hexlify(data).decode() data = hexlify(data).decode()
confirm_more_layout = trezorui2.confirm_more( confirm_more_layout = trezorui_api.confirm_more(
title=title, title=title,
button=TR.buttons__confirm, button=TR.buttons__confirm,
button_style_confirm=True, button_style_confirm=True,
@ -592,7 +584,7 @@ def confirm_blob(
prompt_screen: bool = True, prompt_screen: bool = True,
) -> Awaitable[None]: ) -> Awaitable[None]:
verb = verb or TR.buttons__confirm # def_arg verb = verb or TR.buttons__confirm # def_arg
layout = trezorui2.confirm_blob( layout = trezorui_api.confirm_blob(
title=title, title=title,
description=description, description=description,
text_mono=text_mono, text_mono=text_mono,
@ -691,14 +683,14 @@ def confirm_value(
raise ValueError("Either verb or hold=True must be set") raise ValueError("Either verb or hold=True must be set")
info_items = info_items or [] info_items = info_items or []
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=info_title if info_title else TR.words__title_information, title=info_title if info_title else TR.words__title_information,
items=info_items, items=info_items,
chunkify=chunkify_info, chunkify=chunkify_info,
) )
return with_info( return with_info(
trezorui2.confirm_value( trezorui_api.confirm_value(
title=title, title=title,
subtitle=subtitle, subtitle=subtitle,
description=description, description=description,
@ -725,7 +717,7 @@ def confirm_properties(
items = [(prop[0], prop[1], isinstance(prop[1], bytes)) for prop in props] items = [(prop[0], prop[1], isinstance(prop[1], bytes)) for prop in props]
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_properties( trezorui_api.confirm_properties(
title=title, title=title,
items=items, items=items,
hold=hold, hold=hold,
@ -788,7 +780,7 @@ def _confirm_summary(
) -> Awaitable[None]: ) -> Awaitable[None]:
title = title or TR.words__title_summary # def_arg title = title or TR.words__title_summary # def_arg
total_layout = trezorui2.confirm_summary( total_layout = trezorui_api.confirm_summary(
amount=amount, amount=amount,
amount_label=amount_label, amount_label=amount_label,
fee=fee, fee=fee,
@ -804,7 +796,7 @@ def _confirm_summary(
info_items.extend(account_items) info_items.extend(account_items)
if extra_items: if extra_items:
info_items.extend(extra_items) info_items.extend(extra_items)
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=extra_title if extra_title else TR.words__title_information, title=extra_title if extra_title else TR.words__title_information,
items=info_items, items=info_items,
) )
@ -831,7 +823,7 @@ if not utils.BITCOIN_ONLY:
chunkify: bool = False, chunkify: bool = False,
) -> None: ) -> None:
# NOTE: fee_info used so that info button is shown # NOTE: fee_info used so that info button is shown
total_layout = trezorui2.confirm_summary( total_layout = trezorui_api.confirm_summary(
amount=total_amount, amount=total_amount,
amount_label=f"{TR.words__amount}:", amount_label=f"{TR.words__amount}:",
fee=maximum_fee, fee=maximum_fee,
@ -841,7 +833,7 @@ if not utils.BITCOIN_ONLY:
extra_title=TR.confirm_total__title_fee, extra_title=TR.confirm_total__title_fee,
verb_cancel="^", verb_cancel="^",
) )
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee, title=TR.confirm_total__title_fee,
items=[(f"{k}:", v) for (k, v) in fee_info_items], items=[(f"{k}:", v) for (k, v) in fee_info_items],
) )
@ -965,7 +957,7 @@ if not utils.BITCOIN_ONLY:
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]: def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
# FIXME: arguments for amount/fee are misused here # FIXME: arguments for amount/fee are misused here
trezorui2.confirm_summary( trezorui_api.confirm_summary(
amount=spending_amount, amount=spending_amount,
amount_label=TR.send__you_are_contributing, amount_label=TR.send__you_are_contributing,
fee=total_amount, fee=total_amount,
@ -1020,7 +1012,7 @@ async def confirm_modify_output(
while True: while True:
# if the user cancels here, raise ActionCancelled (by default) # if the user cancels here, raise ActionCancelled (by default)
await interact( await interact(
trezorui2.confirm_blob( trezorui_api.confirm_blob(
title="MODIFY AMOUNT", title="MODIFY AMOUNT",
data=address, data=address,
verb="CONTINUE", verb="CONTINUE",
@ -1033,7 +1025,7 @@ async def confirm_modify_output(
try: try:
await interact( await interact(
trezorui2.confirm_modify_output( trezorui_api.confirm_modify_output(
sign=sign, sign=sign,
amount_change=amount_change, amount_change=amount_change,
amount_new=amount_new, amount_new=amount_new,
@ -1056,7 +1048,7 @@ def confirm_modify_fee(
total_fee_new: str, total_fee_new: str,
fee_rate_amount: str | None = None, fee_rate_amount: str | None = None,
) -> Awaitable[None]: ) -> Awaitable[None]:
fee_layout = trezorui2.confirm_modify_fee( fee_layout = trezorui_api.confirm_modify_fee(
title=title, title=title,
sign=sign, sign=sign,
user_fee_change=user_fee_change, user_fee_change=user_fee_change,
@ -1066,7 +1058,7 @@ def confirm_modify_fee(
items: list[tuple[str, str]] = [] items: list[tuple[str, str]] = []
if fee_rate_amount: if fee_rate_amount:
items.append((TR.bitcoin__new_fee_rate, fee_rate_amount)) items.append((TR.bitcoin__new_fee_rate, fee_rate_amount))
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=TR.confirm_total__title_fee, title=TR.confirm_total__title_fee,
items=items, items=items,
) )
@ -1075,7 +1067,7 @@ def confirm_modify_fee(
def confirm_coinjoin(max_rounds: int, max_fee_per_vbyte: str) -> Awaitable[None]: def confirm_coinjoin(max_rounds: int, max_fee_per_vbyte: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_coinjoin( trezorui_api.confirm_coinjoin(
max_rounds=str(max_rounds), max_rounds=str(max_rounds),
max_feerate=max_fee_per_vbyte, max_feerate=max_fee_per_vbyte,
), ),
@ -1112,7 +1104,7 @@ async def confirm_signverify(
address_title = TR.sign_message__confirm_address address_title = TR.sign_message__confirm_address
br_name = "sign_message" br_name = "sign_message"
address_layout = trezorui2.confirm_address( address_layout = trezorui_api.confirm_address(
title=address_title, title=address_title,
data=address, data=address,
description="", description="",
@ -1133,13 +1125,13 @@ async def confirm_signverify(
) )
) )
info_layout = trezorui2.show_info_with_cancel( info_layout = trezorui_api.show_info_with_cancel(
title=TR.words__title_information, title=TR.words__title_information,
items=items, items=items,
horizontal=True, horizontal=True,
) )
message_layout = trezorui2.confirm_blob( message_layout = trezorui_api.confirm_blob(
title=TR.sign_message__confirm_message, title=TR.sign_message__confirm_message,
description=None, description=None,
data=message, data=message,
@ -1152,7 +1144,7 @@ async def confirm_signverify(
await with_info(address_layout, info_layout, br_name, br_code=BR_CODE_OTHER) await with_info(address_layout, info_layout, br_name, br_code=BR_CODE_OTHER)
except ActionCancelled: except ActionCancelled:
result = await interact( result = await interact(
trezorui2.show_mismatch(title=TR.addr_mismatch__mismatch), trezorui_api.show_mismatch(title=TR.addr_mismatch__mismatch),
None, None,
raise_on_cancel=None, raise_on_cancel=None,
) )
@ -1184,7 +1176,7 @@ def error_popup(
if subtitle: if subtitle:
title += f"\n{subtitle}" title += f"\n{subtitle}"
layout = trezorui2.show_error( layout = trezorui_api.show_error(
title=title, title=title,
description=description.format(description_param), description=description.format(description_param),
button=button, button=button,
@ -1196,20 +1188,22 @@ def error_popup(
def request_passphrase_on_host() -> None: def request_passphrase_on_host() -> None:
draw_simple( draw_simple(
trezorui2.show_simple( trezorui_api.show_simple(
title=None, title=None,
description=TR.passphrase__please_enter, text=TR.passphrase__please_enter,
) )
) )
def show_wait_text(message: str) -> None: def show_wait_text(message: str) -> None:
draw_simple(trezorui2.show_wait_text(message)) draw_simple(trezorui_api.show_wait_text(message))
async def request_passphrase_on_device(max_len: int) -> str: async def request_passphrase_on_device(max_len: int) -> str:
result = await interact( result = await interact(
trezorui2.request_passphrase(prompt="Enter passphrase", max_len=max_len), trezorui_api.request_passphrase(
prompt=TR.passphrase__title_enter, max_len=max_len
),
"passphrase_device", "passphrase_device",
ButtonRequestType.PassphraseEntry, ButtonRequestType.PassphraseEntry,
raise_on_cancel=ActionCancelled("Passphrase entry cancelled"), raise_on_cancel=ActionCancelled("Passphrase entry cancelled"),
@ -1234,7 +1228,7 @@ async def request_pin_on_device(
subprompt = f"{attempts_remaining} {TR.pin__tries_left}" subprompt = f"{attempts_remaining} {TR.pin__tries_left}"
result = await interact( result = await interact(
trezorui2.request_pin( trezorui_api.request_pin(
prompt=prompt, prompt=prompt,
subprompt=subprompt, subprompt=subprompt,
allow_cancel=allow_cancel, allow_cancel=allow_cancel,
@ -1290,7 +1284,7 @@ def confirm_set_new_pin(
br_code: ButtonRequestType = BR_CODE_OTHER, br_code: ButtonRequestType = BR_CODE_OTHER,
) -> Awaitable[None]: ) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_emphasized( trezorui_api.confirm_emphasized(
title=title, title=title,
items=( items=(
(True, description + "\n\n"), (True, description + "\n\n"),
@ -1305,7 +1299,7 @@ def confirm_set_new_pin(
def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[None]: def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[None]:
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.confirm_firmware_update( trezorui_api.confirm_firmware_update(
description=description, fingerprint=fingerprint description=description, fingerprint=fingerprint
), ),
"firmware_update", "firmware_update",
@ -1315,7 +1309,7 @@ def confirm_firmware_update(description: str, fingerprint: str) -> Awaitable[Non
async def set_brightness(current: int | None = None) -> None: async def set_brightness(current: int | None = None) -> None:
await interact( await interact(
trezorui2.set_brightness(current=current), trezorui_api.set_brightness(current=current),
"set_brightness", "set_brightness",
BR_CODE_OTHER, BR_CODE_OTHER,
) )

View File

@ -1,4 +1,3 @@
import trezorui2
import trezorui_api import trezorui_api
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -13,7 +12,7 @@ async def confirm_fido(
accounts: list[str | None], accounts: list[str | None],
) -> int: ) -> int:
"""Webauthn confirmation for one or more credentials.""" """Webauthn confirmation for one or more credentials."""
confirm = trezorui2.confirm_fido( confirm = trezorui_api.confirm_fido(
title=header, title=header,
app_name=app_name, app_name=app_name,
icon_name=icon_name, icon_name=icon_name,
@ -53,7 +52,7 @@ async def confirm_fido_reset() -> bool:
from trezor import TR from trezor import TR
confirm = ui.Layout( confirm = ui.Layout(
trezorui2.confirm_action( trezorui_api.confirm_action(
title=TR.fido__title_reset, title=TR.fido__title_reset,
action=TR.fido__erase_credentials, action=TR.fido__erase_credentials,
description=TR.words__really_wanna, description=TR.words__really_wanna,

View File

@ -17,7 +17,7 @@ if TYPE_CHECKING:
async def request_word_count(recovery_type: RecoveryType) -> int: async def request_word_count(recovery_type: RecoveryType) -> int:
count = await interact( count = await interact(
trezorui2.select_word_count(recovery_type=recovery_type), trezorui_api.select_word_count(recovery_type=recovery_type),
"recovery_word_count", "recovery_word_count",
ButtonRequestType.MnemonicWordCount, ButtonRequestType.MnemonicWordCount,
) )
@ -34,12 +34,12 @@ async def request_word(
prompt = TR.recovery__type_word_x_of_y_template.format(word_index + 1, word_count) prompt = TR.recovery__type_word_x_of_y_template.format(word_index + 1, word_count)
can_go_back = word_index > 0 can_go_back = word_index > 0
if is_slip39: if is_slip39:
keyboard = trezorui2.request_slip39( keyboard = trezorui_api.request_slip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
else: else:
keyboard = trezorui2.request_bip39( keyboard = trezorui_api.request_bip39(
prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back prompt=prompt, prefill_word=prefill_word, can_go_back=can_go_back
) )
@ -51,14 +51,14 @@ async def request_word(
return word return word
def show_remaining_shares( def format_remaining_shares_info(
groups: set[tuple[str, ...]], remaining_shares_info: "RemainingSharesInfo",
shares_remaining: list[int], ) -> list[tuple[str, str]]:
group_threshold: int,
) -> Awaitable[trezorui_api.UiResult]:
from trezor import strings from trezor import strings
from trezor.crypto.slip39 import MAX_SHARE_COUNT from trezor.crypto.slip39 import MAX_SHARE_COUNT
groups, shares_remaining, group_threshold = remaining_shares_info
pages: list[tuple[str, str]] = [] pages: list[tuple[str, str]] = []
completed_groups = shares_remaining.count(0) completed_groups = shares_remaining.count(0)
@ -81,8 +81,14 @@ def show_remaining_shares(
words = "\n".join(group) words = "\n".join(group)
pages.append((title, words)) pages.append((title, words))
return pages
def show_remaining_shares(
pages: list[tuple[str, str]],
) -> Awaitable[trezorui_api.UiResult]:
return interact( return interact(
trezorui2.show_remaining_shares(pages=pages), trezorui_api.show_remaining_shares(pages=pages),
"show_shares", "show_shares",
ButtonRequestType.Other, ButtonRequestType.Other,
) )
@ -92,7 +98,7 @@ def show_group_share_success(
share_index: int, group_index: int share_index: int, group_index: int
) -> Awaitable[ui.UiResult]: ) -> Awaitable[ui.UiResult]:
return interact( return interact(
trezorui2.show_group_share_success( trezorui_api.show_group_share_success(
lines=[ lines=[
TR.recovery__you_have_entered, TR.recovery__you_have_entered,
TR.recovery__share_num_template.format(share_index + 1), TR.recovery__share_num_template.format(share_index + 1),
@ -146,12 +152,17 @@ async def continue_recovery(
else: else:
description = subtext or "" description = subtext or ""
homepage = trezorui2.confirm_recovery( remaining_shares = (
title=text, format_remaining_shares_info(remaining_shares_info)
description=description, if remaining_shares_info
else None
)
homepage = trezorui_api.continue_recovery_homepage(
text=text,
subtext=description,
button=button_label, button=button_label,
recovery_type=recovery_type, recovery_type=recovery_type,
info_button=remaining_shares_info is not None, remaining_shares=remaining_shares,
) )
while True: while True:
@ -164,8 +175,8 @@ async def continue_recovery(
if result is trezorui_api.CONFIRMED: if result is trezorui_api.CONFIRMED:
return True return True
elif result is trezorui_api.INFO and remaining_shares_info is not None: elif result is trezorui_api.INFO and remaining_shares is not None:
await show_remaining_shares(*remaining_shares_info) await show_remaining_shares(remaining_shares)
else: else:
try: try:
await _confirm_abort(recovery_type != RecoveryType.NormalRecovery) await _confirm_abort(recovery_type != RecoveryType.NormalRecovery)
@ -185,7 +196,7 @@ def show_recovery_warning(
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
return interact( return interact(
trezorui2.show_warning( trezorui_api.show_warning(
title=content, title=content,
description=subheader or "", description=subheader or "",
button=button, button=button,

View File

@ -1,6 +1,5 @@
from typing import Awaitable, Callable, Sequence from typing import Awaitable, Callable, Sequence
import trezorui2
import trezorui_api import trezorui_api
from trezor import TR from trezor import TR
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
@ -10,30 +9,6 @@ from ..common import interact, raise_if_not_confirmed
CONFIRMED = trezorui_api.CONFIRMED # global_import_cache CONFIRMED = trezorui_api.CONFIRMED # global_import_cache
def _split_share_into_pages(share_words: Sequence[str], per_page: int = 4) -> list[str]:
pages: list[str] = []
current = ""
fill = 2
for i, word in enumerate(share_words):
if i % per_page == 0:
if i != 0:
pages.append(current)
current = ""
# Align numbers to the right.
lastnum = i + per_page + 1
fill = 1 if lastnum < 10 else 2
else:
current += "\n"
current += f"{i + 1:>{fill}}. {word}"
if current:
pages.append(current)
return pages
def show_share_words( def show_share_words(
share_words: Sequence[str], share_words: Sequence[str],
share_index: int | None = None, share_index: int | None = None,
@ -48,12 +23,10 @@ def show_share_words(
group_index + 1, share_index + 1 group_index + 1, share_index + 1
) )
pages = _split_share_into_pages(share_words)
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_share_words( trezorui_api.show_share_words(
words=share_words,
title=title, title=title,
pages=pages,
), ),
"backup_words", "backup_words",
ButtonRequestType.ResetDevice, ButtonRequestType.ResetDevice,
@ -84,7 +57,7 @@ async def select_word(
words.append(words[-1]) words.append(words[-1])
result = await interact( result = await interact(
trezorui2.select_word( trezorui_api.select_word(
title=title, title=title,
description=TR.reset__select_word_x_of_y_template.format( description=TR.reset__select_word_x_of_y_template.format(
checked_index + 1, count checked_index + 1, count
@ -120,7 +93,7 @@ def slip39_show_checklist(
) )
return raise_if_not_confirmed( return raise_if_not_confirmed(
trezorui2.show_checklist( trezorui_api.show_checklist(
title=TR.reset__slip39_checklist_title, title=TR.reset__slip39_checklist_title,
button=TR.buttons__continue, button=TR.buttons__continue,
active=step, active=step,
@ -140,12 +113,13 @@ async def _prompt_number(
max_count: int, max_count: int,
br_name: str, br_name: str,
) -> int: ) -> int:
num_input = trezorui2.request_number( num_input = trezorui_api.request_number(
title=title, title=title,
description=description,
count=count, count=count,
min_count=min_count, min_count=min_count,
max_count=max_count, max_count=max_count,
description=None,
more_info_callback=description,
) )
while True: while True:
@ -167,9 +141,9 @@ async def _prompt_number(
return value return value
await interact( await interact(
trezorui2.show_simple( trezorui_api.show_simple(
title=None, title=None,
description=info(value), text=info(value),
button=TR.buttons__ok_i_understand, button=TR.buttons__ok_i_understand,
), ),
None, None,
@ -354,7 +328,7 @@ def show_reset_warning(
) -> Awaitable[trezorui_api.UiResult]: ) -> Awaitable[trezorui_api.UiResult]:
button = button or TR.buttons__try_again # def_arg button = button or TR.buttons__try_again # def_arg
return interact( return interact(
trezorui2.show_warning( trezorui_api.show_warning(
title=subheader or "", title=subheader or "",
description=content, description=content,
button=button, button=button,