diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index 8f3073a319f..3197b9ff120 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -63,6 +63,7 @@ static void _librust_qstrs(void) { MP_QSTR_address_details__derivation_path_colon; MP_QSTR_address_details__title_receive_address; MP_QSTR_address_details__title_receiving_to; + MP_QSTR_address_label; MP_QSTR_address_qr; MP_QSTR_address_title; MP_QSTR_allow_cancel; diff --git a/core/embed/rust/src/ui/api/firmware_micropython.rs b/core/embed/rust/src/ui/api/firmware_micropython.rs index ed4d6244bd3..e47b9145ef3 100644 --- a/core/embed/rust/src/ui/api/firmware_micropython.rs +++ b/core/embed/rust/src/ui/api/firmware_micropython.rs @@ -89,23 +89,21 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M extern "C" fn new_confirm_address(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 description: Option = kwargs - .get(Qstr::MP_QSTR_description) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let extra: Option = kwargs - .get(Qstr::MP_QSTR_extra) + let address: Obj = kwargs.get(Qstr::MP_QSTR_address)?; + let address_label: Option = kwargs + .get(Qstr::MP_QSTR_address_label) .unwrap_or_else(|_| Obj::const_none()) .try_into_option()?; let verb: Option = kwargs .get(Qstr::MP_QSTR_verb) .unwrap_or_else(|_| Obj::const_none()) .try_into_option()?; + let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; - let layout = ModelUI::confirm_address(title, data, description, extra, verb, chunkify)?; - Ok(LayoutObj::new_root(layout)?.into()) + let layout_obj = + ModelUI::confirm_address(title, address, address_label, verb, info_button, chunkify)?; + Ok(layout_obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } @@ -1163,10 +1161,10 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// def confirm_address( /// *, /// title: str, - /// data: str | bytes, - /// description: str | None, - /// extra: str | None, + /// address: str | bytes, + /// address_label: str | None = None, /// verb: str | None = None, + /// info_button: bool = False, /// chunkify: bool = False, /// ) -> LayoutObj[UiResult]: /// """Confirm address.""" diff --git a/core/embed/rust/src/ui/model_mercury/ui_firmware.rs b/core/embed/rust/src/ui/model_mercury/ui_firmware.rs index ba22ac4e2c5..716eabdf20b 100644 --- a/core/embed/rust/src/ui/model_mercury/ui_firmware.rs +++ b/core/embed/rust/src/ui/model_mercury/ui_firmware.rs @@ -75,16 +75,14 @@ impl FirmwareUI for UIMercury { fn confirm_address( _title: TString<'static>, - _data: Obj, - _description: Option>, - _extra: Option>, + _address: Obj, + _address_label: Option>, _verb: Option>, + _info_button: bool, _chunkify: bool, - ) -> Result { + ) -> Result, Error> { // confirm_value is used instead - Err::, Error>(Error::ValueError( - c"confirm_address not implemented", - )) + Err::, Error>(Error::ValueError(c"confirm_address not implemented")) } fn confirm_blob( diff --git a/core/embed/rust/src/ui/model_tr/ui_firmware.rs b/core/embed/rust/src/ui/model_tr/ui_firmware.rs index ef3b4e18f86..8f8fdde3d28 100644 --- a/core/embed/rust/src/ui/model_tr/ui_firmware.rs +++ b/core/embed/rust/src/ui/model_tr/ui_firmware.rs @@ -89,34 +89,50 @@ impl FirmwareUI for UIModelTR { fn confirm_address( title: TString<'static>, - data: Obj, - _description: Option>, - _extra: Option>, + address: Obj, + address_label: Option>, verb: Option>, + info_button: bool, chunkify: bool, - ) -> Result { + ) -> Result, Error> { let verb = verb.unwrap_or(TR::buttons__confirm.into()); - let address: TString = data.try_into()?; + let address: TString = address.try_into()?; let get_page = move |page_index| { assert!(page_index == 0); - - let btn_layout = ButtonLayout::cancel_armed_info(verb); - let btn_actions = ButtonActions::cancel_confirm_info(); - let style = if chunkify { - // Chunkifying the address into smaller pieces when requested - theme::TEXT_MONO_ADDRESS_CHUNKS + let (btn_layout, btn_actions) = if info_button { + ( + ButtonLayout::cancel_armed_info(verb), + ButtonActions::cancel_confirm_info(), + ) } else { - theme::TEXT_MONO_DATA + ( + ButtonLayout::cancel_none_text(verb), + ButtonActions::cancel_none_confirm(), + ) }; - let ops = OpTextLayout::new(style).text_mono(address); + let mut ops = OpTextLayout::new(theme::TEXT_MONO_DATA); + if let Some(label) = address_label { + // NOTE: need to explicitly turn off the chunkification before rendering the + // address label (for some reason it does not help to turn it off after + // rendering the chunks) + if chunkify { + ops = ops.chunkify_text(None); + } + ops = ops.text_normal(label).newline(); + } + if chunkify { + // Chunkifying the address into smaller pieces when requested + ops = ops.chunkify_text(Some((theme::MONO_CHUNKS, 2))); + } + ops = ops.text_mono(address); let formatted = FormattedText::new(ops).vertically_centered(); Page::new(btn_layout, btn_actions, formatted).with_title(title) }; let pages = FlowPages::new(get_page, 1); - let layout = RootComponent::new(Flow::new(pages)); - Ok(layout) + let obj = LayoutObj::new(Flow::new(pages))?; + Ok(obj) } fn confirm_blob( diff --git a/core/embed/rust/src/ui/model_tt/ui_firmware.rs b/core/embed/rust/src/ui/model_tt/ui_firmware.rs index d2790d3c167..4f9b0c5085e 100644 --- a/core/embed/rust/src/ui/model_tt/ui_firmware.rs +++ b/core/embed/rust/src/ui/model_tt/ui_firmware.rs @@ -87,41 +87,18 @@ impl FirmwareUI for UIModelTT { fn confirm_address( title: TString<'static>, - data: Obj, - description: Option>, - extra: Option>, + address: Obj, + address_label: Option>, verb: Option>, + info_button: bool, chunkify: bool, - ) -> Result { + ) -> Result, Error> { let verb = verb.unwrap_or(TR::buttons__confirm.into()); - let data_style = if chunkify { - let address: TString = data.try_into()?; - theme::get_chunkified_text_style(address.len()) - } else { - &theme::TEXT_MONO - }; - - let paragraphs = ConfirmBlob { - description: description.unwrap_or("".into()), - extra: extra.unwrap_or("".into()), - data: data.try_into()?, - description_font: &theme::TEXT_NORMAL, - extra_font: &theme::TEXT_DEMIBOLD, - data_font: data_style, - } - .into_paragraphs(); - - let layout = RootComponent::new( - Frame::left_aligned( - theme::label_title(), - title, - ButtonPage::new(paragraphs, theme::BG) - .with_swipe_left() - .with_cancel_confirm(None, Some(verb)), - ) - .with_info_button(), - ); - Ok(layout) + ConfirmBlobParams::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( diff --git a/core/embed/rust/src/ui/ui_firmware.rs b/core/embed/rust/src/ui/ui_firmware.rs index 3c29d736a15..51796745116 100644 --- a/core/embed/rust/src/ui/ui_firmware.rs +++ b/core/embed/rust/src/ui/ui_firmware.rs @@ -33,12 +33,12 @@ pub trait FirmwareUI { fn confirm_address( title: TString<'static>, - data: Obj, // TODO: replace Obj - description: Option>, - extra: Option>, + address: Obj, // TODO: replace Obj + address_label: Option>, verb: Option>, + info_button: bool, chunkify: bool, - ) -> Result; + ) -> Result, Error>; // TODO: return LayoutMaybeTrace #[allow(clippy::too_many_arguments)] fn confirm_blob( diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index 1de4c9e95c5..2b21ee96cd6 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -102,10 +102,10 @@ def confirm_action( def confirm_address( *, title: str, - data: str | bytes, - description: str | None, - extra: str | None, + address: str | bytes, + address_label: str | None = None, verb: str | None = None, + info_button: bool = False, chunkify: bool = False, ) -> LayoutObj[UiResult]: """Confirm address.""" diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index 96076760afd..807baeac025 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -257,9 +257,9 @@ async def show_address( result = await interact( trezorui_api.confirm_address( title=title, - data=address, - description="", # unused on TR - extra=None, # unused on TR + address=address, + address_label=None, + info_button=True, chunkify=chunkify, ), br_name if send_button_request else None, @@ -485,13 +485,12 @@ async def confirm_output( while True: await interact( - trezorui_api.confirm_blob( + trezorui_api.confirm_address( title=address_title, - data=address, - description=address_label or "", - subtitle=None, + address=address, + address_label=address_label or None, verb=TR.buttons__continue, - verb_cancel="", + info_button=False, chunkify=chunkify, ), "confirm_output", @@ -500,9 +499,9 @@ async def confirm_output( try: await interact( - trezorui_api.confirm_blob( + trezorui_api.confirm_value( title=amount_title, - data=amount, + value=amount, description=None, subtitle=None, verb_cancel="^", diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index bb3558f330e..9248293c950 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -243,9 +243,9 @@ async def show_address( result = await interact( trezorui_api.confirm_address( title=title, - data=address, - description=network or "", - extra=None, + address=address, + address_label=network or None, + info_button=True, chunkify=chunkify, ), br_name if send_button_request else None, @@ -427,13 +427,11 @@ async def confirm_output( while True: # if the user cancels here, raise ActionCancelled (by default) await interact( - trezorui_api.confirm_value( + trezorui_api.confirm_address( title=recipient_title, - subtitle=address_label, - description=None, - value=address, + address=address, + address_label=address_label, verb=TR.buttons__continue, - hold=False, info_button=False, chunkify=chunkify, ), @@ -1105,10 +1103,10 @@ async def confirm_signverify( address_layout = trezorui_api.confirm_address( title=address_title, - data=address, - description="", + address=address, + address_label=None, verb=TR.buttons__continue, - extra=None, + info_button=True, chunkify=chunkify, )