1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-05 04:10:58 +00:00

refactor(core): merge confirm_blob and confirm_value

[no changelog]
This commit is contained in:
Ioan Bizău 2025-01-08 12:57:41 +01:00 committed by Ioan Bizău
parent 96bc9db9e0
commit e99beaf486
16 changed files with 208 additions and 387 deletions

View File

@ -187,8 +187,6 @@ static void _librust_qstrs(void) {
MP_QSTR_coinjoin_authorized;
MP_QSTR_confirm_action;
MP_QSTR_confirm_address;
MP_QSTR_confirm_blob;
MP_QSTR_confirm_blob_intro;
MP_QSTR_confirm_coinjoin;
MP_QSTR_confirm_emphasized;
MP_QSTR_confirm_fido;
@ -206,12 +204,12 @@ static void _librust_qstrs(void) {
MP_QSTR_confirm_total__title_fee;
MP_QSTR_confirm_total__title_sending_from;
MP_QSTR_confirm_value;
MP_QSTR_confirm_value_intro;
MP_QSTR_confirm_with_info;
MP_QSTR_continue_recovery_homepage;
MP_QSTR_count;
MP_QSTR_current;
MP_QSTR_danger;
MP_QSTR_data;
MP_QSTR_data_hash;
MP_QSTR_data_len;
MP_QSTR_debug__loading_seed;
@ -299,6 +297,7 @@ static void _librust_qstrs(void) {
MP_QSTR_instructions__tap_to_confirm;
MP_QSTR_instructions__tap_to_start;
MP_QSTR_instructions__view_all_data;
MP_QSTR_is_data;
MP_QSTR_is_type_of;
MP_QSTR_items;
MP_QSTR_joint__title;
@ -725,7 +724,6 @@ static void _librust_qstrs(void) {
MP_QSTR_value;
MP_QSTR_verb;
MP_QSTR_verb_cancel;
MP_QSTR_verb_info;
MP_QSTR_verify;
MP_QSTR_version;
MP_QSTR_wipe__info;

View File

@ -108,15 +108,15 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?;
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
let description: Option<TString> = kwargs
.get(Qstr::MP_QSTR_description)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?;
let is_data: bool = kwargs.get_or(Qstr::MP_QSTR_is_data, true)?;
let extra: Option<TString> = kwargs
.get(Qstr::MP_QSTR_extra)
.unwrap_or_else(|_| Obj::const_none())
@ -133,10 +133,6 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
.get(Qstr::MP_QSTR_verb_cancel)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let verb_info: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb_info)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let info: bool = kwargs.get_or(Qstr::MP_QSTR_info, false)?;
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
@ -144,16 +140,15 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
let prompt_screen: bool = kwargs.get_or(Qstr::MP_QSTR_prompt_screen, false)?;
let cancel: bool = kwargs.get_or(Qstr::MP_QSTR_cancel, false)?;
let layout_obj = ModelUI::confirm_blob(
let layout_obj = ModelUI::confirm_value(
title,
data,
value,
description,
text_mono,
is_data,
extra,
subtitle,
verb,
verb_cancel,
verb_info,
info,
hold,
chunkify,
@ -166,10 +161,10 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_blob_intro(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
extern "C" fn new_confirm_value_intro(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_data)?;
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
let subtitle: Option<TString> = kwargs
.get(Qstr::MP_QSTR_subtitle)
.unwrap_or_else(|_| Obj::const_none())
@ -185,7 +180,7 @@ extern "C" fn new_confirm_blob_intro(n_args: usize, args: *const Obj, kwargs: *m
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
let layout_obj =
ModelUI::confirm_blob_intro(title, data, subtitle, verb, verb_cancel, chunkify)?;
ModelUI::confirm_value_intro(title, value, subtitle, verb, verb_cancel, chunkify)?;
Ok(layout_obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -373,53 +368,6 @@ extern "C" fn new_confirm_summary(n_args: usize, args: *const Obj, kwargs: *mut
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let subtitle: Option<TString> = kwargs
.get(Qstr::MP_QSTR_subtitle)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let description: Option<TString> = kwargs
.get(Qstr::MP_QSTR_description)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
let verb: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let verb_info: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb_info)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let verb_cancel: Option<TString> = kwargs
.get(Qstr::MP_QSTR_verb_cancel)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?;
let layout_obj = ModelUI::confirm_value(
title,
value,
description,
subtitle,
verb,
verb_info,
verb_cancel,
info_button,
hold,
chunkify,
text_mono,
)?;
Ok(layout_obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
@ -1170,17 +1118,16 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// """Confirm address."""
Qstr::MP_QSTR_confirm_address => obj_fn_kw!(0, new_confirm_address).as_obj(),
/// def confirm_blob(
/// def confirm_value(
/// *,
/// title: str,
/// data: str | bytes,
/// value: str | bytes,
/// description: str | None,
/// text_mono: bool = True,
/// is_data: 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,
@ -1188,22 +1135,27 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// prompt_screen: bool = False,
/// cancel: bool = False,
/// ) -> LayoutObj[UiResult]:
/// """Confirm byte sequence data."""
Qstr::MP_QSTR_confirm_blob => obj_fn_kw!(0, new_confirm_blob).as_obj(),
/// """Confirm a generic piece of information on the screen.
/// The value can either be human readable text (`is_data=False`)
/// or something else - like an address or a blob of data.
/// The difference between the two kinds of values
/// is both in the font and in the linebreak strategy."""
Qstr::MP_QSTR_confirm_value => obj_fn_kw!(0, new_confirm_value).as_obj(),
/// def confirm_blob_intro(
/// def confirm_value_intro(
/// *,
/// title: str,
/// data: str | bytes,
/// value: 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."""
Qstr::MP_QSTR_confirm_blob_intro => obj_fn_kw!(0, new_confirm_blob_intro).as_obj(),
/// """Similar to `confirm_value`, but only the first page is shown.
/// This function is intended as a building block for a higher level `confirm_blob`
/// abstraction which can paginate the blob, show just the first page
/// and instruct the user to view the complete blob if they wish."""
Qstr::MP_QSTR_confirm_value_intro => obj_fn_kw!(0, new_confirm_value_intro).as_obj(),
/// def confirm_coinjoin(
/// *,
@ -1312,23 +1264,6 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// """Confirm summary of a transaction."""
Qstr::MP_QSTR_confirm_summary => obj_fn_kw!(0, new_confirm_summary).as_obj(),
/// 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."""
Qstr::MP_QSTR_confirm_value => obj_fn_kw!(0, new_confirm_value).as_obj(),
/// def confirm_with_info(
/// *,
/// title: str,

View File

@ -57,21 +57,21 @@ impl TryFrom<Obj> for StrOrBytes {
}
#[derive(Clone)]
pub struct ConfirmBlob {
pub struct ConfirmValueParams {
pub description: TString<'static>,
pub extra: TString<'static>,
pub data: StrOrBytes,
pub value: StrOrBytes,
pub font: &'static TextStyle,
pub description_font: &'static TextStyle,
pub extra_font: &'static TextStyle,
pub data_font: &'static TextStyle,
}
impl ParagraphSource<'static> for ConfirmBlob {
impl ParagraphSource<'static> for ConfirmValueParams {
fn at(&self, index: usize, offset: usize) -> Paragraph<'static> {
match index {
0 => Paragraph::new(self.description_font, self.description.skip_prefix(offset)),
1 => Paragraph::new(self.extra_font, self.extra.skip_prefix(offset)),
2 => Paragraph::new(self.data_font, self.data.as_str_offset(offset)),
2 => Paragraph::new(self.font, self.value.as_str_offset(offset)),
_ => unreachable!(),
}
}

View File

@ -23,7 +23,7 @@ use crate::{
geometry,
layout::{
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
util::{ConfirmBlob, PropsList, RecoveryType},
util::{ConfirmValueParams, PropsList, RecoveryType},
},
ui_firmware::{
FirmwareUI, MAX_CHECKLIST_ITEMS, MAX_GROUP_SHARE_LINES, MAX_WORD_QUIZ_ITEMS,
@ -94,23 +94,22 @@ impl FirmwareUI for UIBolt {
chunkify: bool,
) -> Result<Gc<LayoutObj>, Error> {
let verb = verb.unwrap_or(TR::buttons__confirm.into());
ConfirmBlobParams::new(title, address, None, Some(verb), None, false)
ConfirmValue::new(title, address, None, Some(verb), None, false)
.with_subtitle(address_label)
.with_info_button(info_button)
.with_chunkify(chunkify)
.into_layout()
}
fn confirm_blob(
fn confirm_value(
title: TString<'static>,
data: Obj,
value: Obj,
description: Option<TString<'static>>,
text_mono: bool,
is_data: bool,
extra: Option<TString<'static>>,
_subtitle: 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,
@ -118,23 +117,24 @@ impl FirmwareUI for UIBolt {
_prompt_screen: bool,
_cancel: bool,
) -> Result<Gc<LayoutObj>, Error> {
ConfirmBlobParams::new(title, data, description, verb, verb_cancel, hold)
.with_text_mono(text_mono)
ConfirmValue::new(title, value, description, verb, verb_cancel, hold)
.with_text_mono(is_data)
.with_subtitle(subtitle)
.with_extra(extra)
.with_chunkify(chunkify)
.with_info_button(info)
.into_layout()
}
fn confirm_blob_intro(
fn confirm_value_intro(
_title: TString<'static>,
_data: Obj,
_value: Obj,
_subtitle: Option<TString<'static>>,
_verb: Option<TString<'static>>,
_verb_cancel: Option<TString<'static>>,
_chunkify: bool,
) -> Result<Gc<LayoutObj>, Error> {
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"confirm_blob_intro not implemented"))
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"confirm_value_intro not implemented"))
}
fn confirm_homescreen(
@ -450,27 +450,6 @@ impl FirmwareUI for UIBolt {
Ok(layout)
}
fn confirm_value(
title: TString<'static>,
value: 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> {
ConfirmBlobParams::new(title, value, description, verb, verb_cancel, hold)
.with_subtitle(subtitle)
.with_info_button(info_button)
.with_chunkify(chunkify)
.with_text_mono(text_mono)
.into_layout()
}
fn confirm_with_info(
title: TString<'static>,
button: TString<'static>,
@ -1221,10 +1200,10 @@ fn new_show_modal(
}
// TODO: move to some util.rs?
struct ConfirmBlobParams {
struct ConfirmValue {
title: TString<'static>,
subtitle: Option<TString<'static>>,
data: Obj,
value: Obj,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
verb: Option<TString<'static>>,
@ -1235,10 +1214,10 @@ struct ConfirmBlobParams {
text_mono: bool,
}
impl ConfirmBlobParams {
impl ConfirmValue {
fn new(
title: TString<'static>,
data: Obj,
value: Obj,
description: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
@ -1247,7 +1226,7 @@ impl ConfirmBlobParams {
Self {
title,
subtitle: None,
data,
value,
description,
extra: None,
verb,
@ -1285,20 +1264,20 @@ impl ConfirmBlobParams {
}
fn into_layout(self) -> Result<Gc<LayoutObj>, Error> {
let paragraphs = ConfirmBlob {
let paragraphs = ConfirmValueParams {
description: self.description.unwrap_or("".into()),
extra: self.extra.unwrap_or("".into()),
data: self.data.try_into()?,
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD,
data_font: if self.chunkify {
let data: TString = self.data.try_into()?;
theme::get_chunkified_text_style(data.len())
value: self.value.try_into()?,
font: if self.chunkify {
let value: TString = self.value.try_into()?;
theme::get_chunkified_text_style(value.len())
} else if self.text_mono {
&theme::TEXT_MONO
} else {
&theme::TEXT_NORMAL
},
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD,
}
.into_paragraphs();

View File

@ -24,7 +24,7 @@ use crate::{
geometry,
layout::{
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
util::{ConfirmBlob, RecoveryType},
util::{ConfirmValueParams, RecoveryType},
},
ui_firmware::{
FirmwareUI, MAX_CHECKLIST_ITEMS, MAX_GROUP_SHARE_LINES, MAX_WORD_QUIZ_ITEMS,
@ -132,16 +132,15 @@ impl FirmwareUI for UICaesar {
Ok(obj)
}
fn confirm_blob(
fn confirm_value(
title: TString<'static>,
data: Obj,
value: Obj,
description: Option<TString<'static>>,
_text_mono: bool,
is_data: 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,
@ -149,20 +148,20 @@ impl FirmwareUI for UICaesar {
_prompt_screen: bool,
_cancel: bool,
) -> Result<Gc<LayoutObj>, Error> {
let style = if chunkify {
// Chunkifying the address into smaller pieces when requested
&theme::TEXT_MONO_ADDRESS_CHUNKS
} else {
&theme::TEXT_MONO_DATA
};
let paragraphs = ConfirmBlob {
let paragraphs = ConfirmValueParams {
description: description.unwrap_or("".into()),
extra: extra.unwrap_or("".into()),
data: data.try_into()?,
value: value.try_into()?,
font: if chunkify {
// Chunkifying the address into smaller pieces when requested
&theme::TEXT_MONO_ADDRESS_CHUNKS
} else if is_data {
&theme::TEXT_MONO_DATA
} else {
&theme::TEXT_NORMAL
},
description_font: &theme::TEXT_BOLD,
extra_font: &theme::TEXT_NORMAL,
data_font: style,
}
.into_paragraphs();
@ -176,15 +175,15 @@ impl FirmwareUI for UICaesar {
LayoutObj::new_root(layout)
}
fn confirm_blob_intro(
fn confirm_value_intro(
_title: TString<'static>,
_data: Obj,
_value: Obj,
_subtitle: Option<TString<'static>>,
_verb: Option<TString<'static>>,
_verb_cancel: Option<TString<'static>>,
_chunkify: bool,
) -> Result<Gc<LayoutObj>, Error> {
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"confirm_blob_intro not implemented"))
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"confirm_value_intro not implemented"))
}
fn confirm_homescreen(
@ -590,36 +589,6 @@ impl FirmwareUI for UICaesar {
Ok(layout)
}
fn confirm_value(
title: TString<'static>,
value: 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> {
let value: TString = value.try_into()?;
let description = description.unwrap_or("".into());
let paragraphs = Paragraphs::new([
Paragraph::new(&theme::TEXT_BOLD, description),
Paragraph::new(&theme::TEXT_MONO, value),
]);
let layout = content_in_button_page(
title,
paragraphs,
verb.unwrap_or(TR::buttons__confirm.into()),
verb_cancel,
hold,
)?;
LayoutObj::new_root(layout)
}
fn confirm_with_info(
title: TString<'static>,
button: TString<'static>,

View File

@ -23,7 +23,7 @@ use super::{
},
theme,
},
util::{ConfirmBlobParams, ShowInfoParams},
util::{ConfirmValue, ShowInfoParams},
};
const MENU_ITEM_CANCEL: usize = 0;
@ -214,13 +214,13 @@ fn get_cancel_page(
#[allow(clippy::too_many_arguments)]
pub fn new_confirm_output(
main_params: ConfirmBlobParams,
confirm_main: ConfirmValue,
account: Option<TString<'static>>,
account_path: Option<TString<'static>>,
br_name: TString<'static>,
br_code: u16,
content_amount_params: Option<ConfirmBlobParams>,
address_params: Option<ConfirmBlobParams>,
confirm_amount: Option<ConfirmValue>,
confirm_address: Option<ConfirmValue>,
address_title: TString<'static>,
summary_items_params: Option<ShowInfoParams>,
fee_items_params: ShowInfoParams,
@ -229,14 +229,14 @@ pub fn new_confirm_output(
cancel_text: Option<TString<'static>>,
) -> Result<SwipeFlow, error::Error> {
// Main
let main_content = main_params
let main_content = confirm_main
.into_layout()?
.one_button_request(ButtonRequest::from_num(br_code, br_name));
// MainMenu
let mut main_menu = VerticalMenu::empty();
let mut main_menu_items = Vec::<usize, 3>::new();
if address_params.is_some() {
if confirm_address.is_some() {
main_menu = main_menu.item(theme::ICON_CHEVRON_RIGHT, address_title);
unwrap!(main_menu_items.push(MENU_ITEM_ADDRESS_INFO));
}
@ -267,14 +267,14 @@ pub fn new_confirm_output(
let ac = AddressDetails::new(TR::send__send_from.into(), account, account_path)?;
let account_content = ac.map(|_| Some(FlowMsg::Cancelled));
let res = if let Some(content_amount_params) = content_amount_params {
let content_amount = content_amount_params
let res = if let Some(confirm_amount) = confirm_amount {
let confirm_amount = confirm_amount
.into_layout()?
.one_button_request(ButtonRequest::from_num(br_code, br_name));
SwipeFlow::new(&ConfirmOutputWithAmount::Address)?
.with_page(&ConfirmOutputWithAmount::Address, main_content)?
.with_page(&ConfirmOutputWithAmount::Amount, content_amount)?
.with_page(&ConfirmOutputWithAmount::Amount, confirm_amount)?
.with_page(&ConfirmOutputWithAmount::Menu, content_main_menu)?
.with_page(&ConfirmOutputWithAmount::AccountInfo, account_content)?
.with_page(&ConfirmOutputWithAmount::CancelTap, get_cancel_page())?
@ -352,8 +352,8 @@ pub fn new_confirm_output(
.with_page(&ConfirmOutputWithSummary::Main, main_content)?
.with_page(&ConfirmOutputWithSummary::MainMenu, content_main_menu)?
.with_page(&ConfirmOutputWithSummary::MainMenuCancel, get_cancel_page())?;
if let Some(address_params) = address_params {
let address_content = address_params.into_layout()?;
if let Some(confirm_address) = confirm_address {
let address_content = confirm_address.into_layout()?;
flow = flow.with_page(&ConfirmOutputWithSummary::AddressInfo, address_content)?;
} else {
// dummy page - this will never be shown since there is no menu item pointing to

View File

@ -15,7 +15,7 @@ use crate::{
FlowController, FlowMsg, SwipeFlow, SwipePage,
},
geometry::Direction,
layout::util::ConfirmBlob,
layout::util::ConfirmValueParams,
},
};
@ -101,19 +101,18 @@ pub fn new_get_address(
br_name: TString<'static>,
) -> Result<SwipeFlow, error::Error> {
// Address
let data_style = if chunkify {
let address: TString = address.try_into()?;
theme::get_chunkified_text_style(address.len())
} else {
&theme::TEXT_MONO
};
let paragraphs = ConfirmBlob {
let paragraphs = ConfirmValueParams {
description: description.unwrap_or_else(|| "".into()),
extra: extra.unwrap_or_else(|| "".into()),
data: address.try_into()?,
value: address.try_into()?,
font: if chunkify {
let address: TString = address.try_into()?;
theme::get_chunkified_text_style(address.len())
} else {
&theme::TEXT_MONO
},
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD,
data_font: data_style,
}
.into_paragraphs();
let content_address =

View File

@ -39,4 +39,4 @@ pub use set_brightness::SetBrightness;
pub use show_danger::ShowDanger;
pub use show_share_words::ShowShareWords;
pub use show_tutorial::ShowTutorial;
pub use util::{ConfirmBlobParams, ShowInfoParams};
pub use util::{ConfirmValue, ShowInfoParams};

View File

@ -16,7 +16,7 @@ use crate::{
},
flow::{FlowMsg, Swipable, SwipeFlow, SwipePage},
geometry::Direction,
layout::util::{ConfirmBlob, StrOrBytes},
layout::util::{ConfirmValueParams, StrOrBytes},
},
};
use heapless::Vec;
@ -29,12 +29,12 @@ use super::{
ConfirmActionExtra, ConfirmActionMenuStrings, ConfirmActionStrings,
};
pub struct ConfirmBlobParams {
pub struct ConfirmValue {
title: TString<'static>,
subtitle: Option<TString<'static>>,
footer_instruction: Option<TString<'static>>,
footer_description: Option<TString<'static>>,
data: Obj,
value: Obj,
description: Option<TString<'static>>,
description_font: &'static TextStyle,
extra: Option<TString<'static>>,
@ -56,14 +56,14 @@ pub struct ConfirmBlobParams {
cancel: bool,
}
impl ConfirmBlobParams {
pub fn new(title: TString<'static>, data: Obj, description: Option<TString<'static>>) -> Self {
impl ConfirmValue {
pub fn new(title: TString<'static>, value: Obj, description: Option<TString<'static>>) -> Self {
Self {
title,
subtitle: None,
footer_instruction: None,
footer_description: None,
data,
value,
description,
description_font: &theme::TEXT_NORMAL,
extra: None,
@ -202,24 +202,24 @@ impl ConfirmBlobParams {
pub fn into_layout(
self,
) -> Result<impl Component<Msg = FlowMsg> + Swipable + MaybeTrace, Error> {
let paragraphs = ConfirmBlob {
let paragraphs = ConfirmValueParams {
description: self.description.unwrap_or("".into()),
extra: self.extra.unwrap_or("".into()),
data: if self.data != Obj::const_none() {
self.data.try_into()?
value: if self.value != Obj::const_none() {
self.value.try_into()?
} else {
StrOrBytes::Str("".into())
},
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD,
data_font: if self.chunkify {
let data: TString = self.data.try_into()?;
theme::get_chunkified_text_style(data.len())
font: if self.chunkify {
let value: TString = self.value.try_into()?;
theme::get_chunkified_text_style(value.len())
} else if self.text_mono {
&theme::TEXT_MONO
} else {
&theme::TEXT_NORMAL
},
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_DEMIBOLD,
}
.into_paragraphs();
@ -257,20 +257,20 @@ impl ConfirmBlobParams {
}
pub fn into_flow(self) -> Result<SwipeFlow, Error> {
let paragraphs = ConfirmBlob {
let paragraphs = ConfirmValueParams {
description: self.description.unwrap_or("".into()),
extra: self.extra.unwrap_or("".into()),
data: self.data.try_into()?,
description_font: self.description_font,
extra_font: &theme::TEXT_DEMIBOLD,
data_font: if self.chunkify {
let data: TString = self.data.try_into()?;
theme::get_chunkified_text_style(data.len())
value: self.value.try_into()?,
font: if self.chunkify {
let value: TString = self.value.try_into()?;
theme::get_chunkified_text_style(value.len())
} else if self.text_mono {
&theme::TEXT_MONO
} else {
&theme::TEXT_NORMAL
},
description_font: self.description_font,
extra_font: &theme::TEXT_DEMIBOLD,
}
.into_paragraphs();

View File

@ -40,7 +40,7 @@ use super::{
},
flow::{
self, new_confirm_action_simple, ConfirmActionExtra, ConfirmActionMenuStrings,
ConfirmActionStrings, ConfirmBlobParams, ShowInfoParams,
ConfirmActionStrings, ConfirmValue, ShowInfoParams,
},
theme, UIDelizia,
};
@ -85,16 +85,15 @@ impl FirmwareUI for UIDelizia {
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"confirm_address not implemented"))
}
fn confirm_blob(
fn confirm_value(
title: TString<'static>,
data: Obj,
value: Obj,
description: Option<TString<'static>>,
text_mono: bool,
is_data: 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,
@ -102,14 +101,14 @@ impl FirmwareUI for UIDelizia {
prompt_screen: bool,
cancel: bool,
) -> Result<Gc<LayoutObj>, Error> {
ConfirmBlobParams::new(title, data, description)
ConfirmValue::new(title, value, description)
.with_description_font(&theme::TEXT_SUB_GREY)
.with_text_mono(text_mono)
.with_text_mono(is_data)
.with_subtitle(subtitle)
.with_verb(verb)
.with_verb_cancel(verb_cancel)
.with_verb_info(if info {
Some(verb_info.unwrap_or(TR::words__title_information.into()))
Some(TR::buttons__more_info.into())
} else {
None
})
@ -124,16 +123,16 @@ impl FirmwareUI for UIDelizia {
.map(Into::into)
}
fn confirm_blob_intro(
fn confirm_value_intro(
title: TString<'static>,
data: Obj,
value: Obj,
subtitle: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
chunkify: bool,
) -> Result<Gc<LayoutObj>, Error> {
const CONFIRM_BLOB_INTRO_MARGIN: usize = 24;
ConfirmBlobParams::new(title, data, Some(TR::instructions__view_all_data.into()))
const CONFIRM_VALUE_INTRO_MARGIN: usize = 24;
ConfirmValue::new(title, value, Some(TR::instructions__view_all_data.into()))
.with_verb(verb)
.with_verb_info(Some(TR::buttons__view_all_data.into()))
.with_description_font(&theme::TEXT_SUB_GREEN_LIME)
@ -144,7 +143,7 @@ impl FirmwareUI for UIDelizia {
))
.with_chunkify(chunkify)
.with_page_limit(Some(1))
.with_frame_margin(CONFIRM_BLOB_INTRO_MARGIN)
.with_frame_margin(CONFIRM_VALUE_INTRO_MARGIN)
.into_flow()
.and_then(LayoutObj::new_root)
.map(Into::into)
@ -438,37 +437,6 @@ impl FirmwareUI for UIDelizia {
Ok(flow)
}
fn confirm_value(
title: TString<'static>,
value: 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> {
ConfirmBlobParams::new(title, value, description)
.with_subtitle(subtitle)
.with_verb(verb)
.with_verb_cancel(verb_cancel)
.with_verb_info(if info_button {
Some(verb_info.unwrap_or(TR::words__title_information.into()))
} else {
None
})
.with_chunkify(chunkify)
.with_text_mono(text_mono)
.with_prompt(hold)
.with_hold(hold)
.into_flow()
.and_then(LayoutObj::new_root)
.map(Into::into)
}
fn confirm_with_info(
title: TString<'static>,
button: TString<'static>,
@ -559,7 +527,7 @@ impl FirmwareUI for UIDelizia {
) -> Result<impl LayoutMaybeTrace, Error> {
let address_title = address_title.unwrap_or(TR::words__address.into());
let main_params = ConfirmBlobParams::new(title.unwrap_or(TString::empty()), message, None)
let confirm_main = ConfirmValue::new(title.unwrap_or(TString::empty()), message, None)
.with_subtitle(subtitle)
.with_menu_button()
.with_footer(TR::instructions__swipe_up.into(), None)
@ -567,8 +535,8 @@ impl FirmwareUI for UIDelizia {
.with_text_mono(text_mono)
.with_swipe_up();
let content_amount_params = amount.map(|amount| {
ConfirmBlobParams::new(TR::words__amount.into(), amount, None)
let confirm_amount = amount.map(|amount| {
ConfirmValue::new(TR::words__amount.into(), amount, None)
.with_subtitle(subtitle)
.with_menu_button()
.with_footer(TR::instructions__swipe_up.into(), None)
@ -577,8 +545,8 @@ impl FirmwareUI for UIDelizia {
.with_swipe_down()
});
let address_params = address.map(|address| {
ConfirmBlobParams::new(address_title, address, None)
let confirm_value = address.map(|address| {
ConfirmValue::new(address_title, address, None)
.with_cancel_button()
.with_chunkify(true)
.with_text_mono(true)
@ -611,13 +579,13 @@ impl FirmwareUI for UIDelizia {
};
let flow = flow::confirm_output::new_confirm_output(
main_params,
confirm_main,
account,
account_path,
br_name,
br_code,
content_amount_params,
address_params,
confirm_amount,
confirm_value,
address_title,
summary_items_params,
fee_items_params,

View File

@ -41,16 +41,15 @@ pub trait FirmwareUI {
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
#[allow(clippy::too_many_arguments)]
fn confirm_blob(
fn confirm_value(
title: TString<'static>,
data: Obj, // TODO: replace Obj
value: Obj, // TODO: replace Obj
description: Option<TString<'static>>,
text_mono: bool,
is_data: 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,
@ -59,9 +58,9 @@ pub trait FirmwareUI {
cancel: bool,
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
fn confirm_blob_intro(
fn confirm_value_intro(
title: TString<'static>,
data: Obj, // TODO: replace Obj
value: Obj, // TODO: replace Obj
subtitle: Option<TString<'static>>,
verb: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
@ -138,21 +137,6 @@ pub trait FirmwareUI {
verb_cancel: Option<TString<'static>>,
) -> Result<impl LayoutMaybeTrace, Error>;
#[allow(clippy::too_many_arguments)]
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>,

View File

@ -112,17 +112,16 @@ def confirm_address(
# rust/src/ui/api/firmware_micropython.rs
def confirm_blob(
def confirm_value(
*,
title: str,
data: str | bytes,
value: str | bytes,
description: str | None,
text_mono: bool = True,
is_data: 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,
@ -130,22 +129,27 @@ def confirm_blob(
prompt_screen: bool = False,
cancel: bool = False,
) -> LayoutObj[UiResult]:
"""Confirm byte sequence data."""
"""Confirm a generic piece of information on the screen.
The value can either be human readable text (`is_data=False`)
or something else - like an address or a blob of data.
The difference between the two kinds of values
is both in the font and in the linebreak strategy."""
# rust/src/ui/api/firmware_micropython.rs
def confirm_blob_intro(
def confirm_value_intro(
*,
title: str,
data: str | bytes,
value: 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."""
"""Similar to `confirm_value`, but only the first page is shown.
This function is intended as a building block for a higher level `confirm_blob`
abstraction which can paginate the blob, show just the first page
and instruct the user to view the complete blob if they wish."""
# rust/src/ui/api/firmware_micropython.rs
@ -265,24 +269,6 @@ def confirm_summary(
"""Confirm summary of a transaction."""
# rust/src/ui/api/firmware_micropython.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_micropython.rs
def confirm_with_info(
*,

View File

@ -310,14 +310,17 @@ async def confirm_nondefault_locktime(lock_time: int, lock_time_disabled: bool)
if lock_time < _LOCKTIME_TIMESTAMP_MIN_VALUE:
text = TR.bitcoin__locktime_set_to_blockheight
value = str(lock_time)
is_data = True
else:
text = TR.bitcoin__locktime_set_to
value = format_timestamp(lock_time)
is_data = False
await layouts.confirm_value(
TR.bitcoin__confirm_locktime,
value,
text,
"nondefault_locktime",
is_data=is_data,
br_code=ButtonRequestType.SignTx,
verb=TR.buttons__confirm,
)

View File

@ -443,13 +443,13 @@ async def confirm_output(
await interact(
trezorui_api.confirm_value(
title=amount_title,
subtitle=None,
description=None,
value=amount,
description=None,
subtitle=None,
verb=None if hold else TR.buttons__confirm,
verb_cancel="^",
info=False,
hold=hold,
info_button=False,
),
"confirm_output",
br_code,
@ -569,7 +569,6 @@ def confirm_blob(
title: str,
data: bytes | str,
description: str | None = None,
text_mono: bool = True,
subtitle: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
@ -581,11 +580,10 @@ def confirm_blob(
prompt_screen: bool = True,
) -> Awaitable[None]:
verb = verb or TR.buttons__confirm # def_arg
layout = trezorui_api.confirm_blob(
layout = trezorui_api.confirm_value(
title=title,
description=description,
text_mono=text_mono,
data=data,
value=data,
hold=hold,
verb=verb,
verb_cancel=None,
@ -669,7 +667,7 @@ def confirm_value(
verb: str | None = None,
subtitle: str | None = None,
hold: bool = False,
value_text_mono: bool = True,
is_data: bool = True,
info_items: Iterable[tuple[str, str]] | None = None,
info_title: str | None = None,
chunkify_info: bool = False,
@ -689,13 +687,13 @@ def confirm_value(
return with_info(
trezorui_api.confirm_value(
title=title,
subtitle=subtitle,
description=description,
value=value,
description=description,
is_data=is_data,
subtitle=subtitle,
verb=verb,
info=bool(info_items),
hold=hold,
info_button=bool(info_items),
text_mono=value_text_mono,
),
info_layout,
br_name,
@ -874,6 +872,7 @@ if not utils.BITCOIN_ONLY:
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
# intro
await confirm_value(
title,
intro_question,
@ -881,7 +880,7 @@ if not utils.BITCOIN_ONLY:
br_name,
br_code,
verb=verb,
value_text_mono=False,
is_data=False,
info_items=(("", address),),
info_title=address_title,
chunkify_info=chunkify,
@ -1009,9 +1008,9 @@ async def confirm_modify_output(
while True:
# if the user cancels here, raise ActionCancelled (by default)
await interact(
trezorui_api.confirm_blob(
trezorui_api.confirm_value(
title="MODIFY AMOUNT",
data=address,
value=address,
verb="CONTINUE",
verb_cancel=None,
description="Address:",
@ -1128,10 +1127,10 @@ async def confirm_signverify(
horizontal=True,
)
message_layout = trezorui_api.confirm_blob(
message_layout = trezorui_api.confirm_value(
title=TR.sign_message__confirm_message,
description=None,
data=message,
value=message,
hold=not verify,
verb=TR.buttons__confirm if verify else None,
)

View File

@ -503,7 +503,6 @@ async def confirm_output(
title=amount_title,
value=amount,
description=None,
subtitle=None,
verb_cancel="^",
verb=TR.buttons__confirm,
),
@ -590,12 +589,14 @@ def confirm_blob(
chunkify: bool = False,
prompt_screen: bool = True,
) -> Awaitable[None]:
verb = verb or TR.buttons__confirm # def_arg
layout = trezorui_api.confirm_blob(
if description and ":" not in description:
description += ":"
layout = trezorui_api.confirm_value(
title=title,
description=description,
data=data,
verb=verb,
value=data,
verb=verb or TR.buttons__confirm,
verb_cancel="",
hold=hold,
chunkify=chunkify,
@ -736,6 +737,7 @@ async def confirm_value(
*,
verb: str | None = None,
hold: bool = False,
is_data: bool = True,
info_items: Iterable[tuple[str, str]] | None = None,
chunkify_info: bool = False,
) -> None:
@ -746,13 +748,15 @@ async def confirm_value(
if info_items is None:
return await raise_if_not_confirmed(
trezorui_api.confirm_value( # type: ignore [Argument missing for parameter "subtitle"]
trezorui_api.confirm_value(
title=title,
description=description,
value=value,
description=description,
verb=verb or TR.buttons__hold_to_confirm,
verb_cancel="",
info=False,
hold=hold,
is_data=is_data,
),
br_name,
br_code,
@ -782,13 +786,14 @@ async def confirm_value(
elif result is INFO:
info_title, info_value = info_items_list[0]
await interact(
trezorui_api.confirm_blob(
trezorui_api.confirm_value(
title=info_title,
data=info_value,
value=info_value,
description=description,
verb="",
verb_cancel="<",
hold=False,
is_data=is_data,
chunkify=chunkify_info,
),
None,
@ -1031,9 +1036,9 @@ async def confirm_modify_output(
amount_change: str,
amount_new: str,
) -> None:
address_layout = trezorui_api.confirm_blob(
address_layout = trezorui_api.confirm_value(
title=TR.modify_amount__title,
data=address,
value=address,
verb=TR.buttons__continue,
description=f"{TR.words__address}:",
)
@ -1133,10 +1138,10 @@ async def confirm_signverify(
)
try:
await raise_if_not_confirmed(
trezorui_api.confirm_blob(
trezorui_api.confirm_value(
title=TR.sign_message__confirm_message,
description=None,
data=message,
value=message,
verb=None,
verb_cancel="^",
hold=False,

View File

@ -484,7 +484,6 @@ def confirm_blob(
title: str,
data: bytes | str,
description: str | None = None,
text_mono: bool = True,
subtitle: str | None = None,
verb: str | None = None,
verb_cancel: str | None = None,
@ -496,17 +495,17 @@ def confirm_blob(
prompt_screen: bool = True,
) -> Awaitable[None]:
if ask_pagination:
main_layout = trezorui_api.confirm_blob_intro(
main_layout = trezorui_api.confirm_value_intro(
title=title,
data=data,
value=data,
subtitle=description,
verb=verb,
verb_cancel=verb_cancel,
chunkify=chunkify,
)
info_layout = trezorui_api.confirm_blob(
info_layout = trezorui_api.confirm_value(
title=title,
data=data,
value=data,
subtitle=description,
description=None,
verb=None,
@ -528,11 +527,10 @@ def confirm_blob(
info_layout_can_confirm=True,
)
else:
layout = trezorui_api.confirm_blob(
layout = trezorui_api.confirm_value(
title=title,
data=data,
value=data,
description=description,
text_mono=text_mono,
subtitle=subtitle,
verb=verb,
verb_cancel=verb_cancel,
@ -615,7 +613,7 @@ def confirm_value(
verb: str | None = None,
subtitle: str | None = None,
hold: bool = False,
value_text_mono: bool = True,
is_data: bool = True,
chunkify: bool = False,
info_items: Iterable[tuple[str, str]] | None = None,
info_title: str | None = None,
@ -636,14 +634,14 @@ def confirm_value(
return with_info(
trezorui_api.confirm_value(
title=title,
subtitle=subtitle,
description=description,
value=value,
is_data=is_data,
description=description,
subtitle=subtitle,
verb=verb,
info=bool(info_items),
hold=hold,
info_button=bool(info_items),
chunkify=chunkify,
text_mono=value_text_mono,
),
info_layout,
br_name,
@ -936,9 +934,9 @@ async def confirm_modify_output(
amount_change: str,
amount_new: str,
) -> None:
address_layout = trezorui_api.confirm_blob(
address_layout = trezorui_api.confirm_value(
title=TR.modify_amount__title,
data=address,
value=address,
verb=TR.buttons__continue,
verb_cancel=None,
description=f"{TR.words__address}:",
@ -1033,12 +1031,10 @@ async def confirm_signverify(
address_layout = trezorui_api.confirm_value(
title=address_title,
subtitle=None,
description="",
value=address,
description="",
verb=TR.buttons__continue,
verb_info=TR.buttons__more_info,
info_button=True,
info=True,
chunkify=chunkify,
)
@ -1060,10 +1056,10 @@ async def confirm_signverify(
horizontal=True,
)
message_layout = trezorui_api.confirm_blob(
message_layout = trezorui_api.confirm_value(
title=TR.sign_message__confirm_message,
description=None,
data=message,
value=message,
extra=None,
prompt_screen=True,
hold=not verify,