diff --git a/core/embed/rust/src/ui/api/firmware_upy.rs b/core/embed/rust/src/ui/api/firmware_upy.rs index 6318327674..10b07e4933 100644 --- a/core/embed/rust/src/ui/api/firmware_upy.rs +++ b/core/embed/rust/src/ui/api/firmware_upy.rs @@ -299,6 +299,16 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_show_mismatch(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 layout = ModelUI::show_mismatch(title)?; + Ok(LayoutObj::new_root(layout)?.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; @@ -600,6 +610,10 @@ pub static mp_module_trezorui_api: Module = obj_module! { /// """Homescreen for locked device.""" Qstr::MP_QSTR_show_lockscreen => obj_fn_kw!(0, new_show_lockscreen).as_obj(), + /// def show_mismatch(*, title: str) -> LayoutObj[UiResult]: + /// """Warning of receiving address mismatch.""" + Qstr::MP_QSTR_show_mismatch => obj_fn_kw!(0, new_show_mismatch).as_obj(), + /// def show_progress( /// *, /// description: str, diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index 00ba1a6dba..887e9a2bf3 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -853,31 +853,6 @@ extern "C" fn new_show_success(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_show_mismatch(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 description: TString = TR::addr_mismatch__contact_support_at.into(); - let url: TString = TR::addr_mismatch__support_url.into(); - let button: TString = TR::buttons__quit.into(); - - let paragraphs = ParagraphVecShort::from_iter([ - Paragraph::new(&theme::TEXT_NORMAL, description).centered(), - Paragraph::new(&theme::TEXT_DEMIBOLD, url).centered(), - ]) - .into_paragraphs(); - - let obj = LayoutObj::new(SwipeUpScreen::new( - Frame::left_aligned(title, SwipeContent::new(paragraphs)) - .with_cancel_button() - .with_footer(TR::instructions__swipe_up.into(), Some(button)) - .with_swipe(Direction::Up, SwipeSettings::default()), - ))?; - - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?; @@ -1289,10 +1264,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Success screen. Description is used in the footer.""" Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(), - /// def show_mismatch(*, title: str) -> LayoutObj[UiResult]: - /// """Warning modal, receiving address mismatch.""" - Qstr::MP_QSTR_show_mismatch => obj_fn_kw!(0, new_show_mismatch).as_obj(), - /// def show_simple( /// *, /// title: str | None, diff --git a/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs b/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs index 13e7cd9866..df1de7083d 100644 --- a/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs +++ b/core/embed/rust/src/ui/model_mercury/ui_features_fw.rs @@ -292,6 +292,27 @@ impl UIFeaturesFirmware for ModelMercuryFeatures { Ok(layout) } + fn show_mismatch(title: TString<'static>) -> Result { + let description: TString = TR::addr_mismatch__contact_support_at.into(); + let url: TString = TR::addr_mismatch__support_url.into(); + let button: TString = TR::buttons__quit.into(); + + let paragraphs = ParagraphVecShort::from_iter([ + Paragraph::new(&theme::TEXT_NORMAL, description).centered(), + Paragraph::new(&theme::TEXT_DEMIBOLD, url).centered(), + ]) + .into_paragraphs(); + + let layout = RootComponent::new(SwipeUpScreen::new( + Frame::left_aligned(title, SwipeContent::new(paragraphs)) + .with_cancel_button() + .with_footer(TR::instructions__swipe_up.into(), Some(button)) + .with_swipe(Direction::Up, SwipeSettings::default()), + )); + + Ok(layout) + } + fn show_progress( description: TString<'static>, indeterminate: bool, diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs index 6b9e3df134..d5f9c629ed 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -1072,33 +1072,6 @@ extern "C" fn new_show_waiting_text(message: Obj) -> Obj { unsafe { util::try_or_raise(block) } } -extern "C" fn new_show_mismatch(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 get_page = move |page_index| { - assert!(page_index == 0); - - let btn_layout = ButtonLayout::arrow_none_text(TR::buttons__quit.into()); - let btn_actions = ButtonActions::cancel_none_confirm(); - let ops = OpTextLayout::new(theme::TEXT_NORMAL) - .text_bold_upper(title) - .newline() - .newline_half() - .text_normal(TR::addr_mismatch__contact_support_at) - .newline() - .text_bold(TR::addr_mismatch__support_url); - let formatted = FormattedText::new(ops); - Page::new(btn_layout, btn_actions, formatted) - }; - let pages = FlowPages::new(get_page, 1); - - let obj = LayoutObj::new(Flow::new(pages))?; - Ok(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()?; @@ -1467,10 +1440,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Show passphrase on host dialog.""" Qstr::MP_QSTR_show_passphrase => obj_fn_0!(new_show_passphrase).as_obj(), - /// def show_mismatch(*, title: str) -> LayoutObj[UiResult]: - /// """Warning modal, receiving address mismatch.""" - Qstr::MP_QSTR_show_mismatch => obj_fn_kw!(0, new_show_mismatch).as_obj(), - /// def confirm_with_info( /// *, /// title: str, diff --git a/core/embed/rust/src/ui/model_tr/ui_features_fw.rs b/core/embed/rust/src/ui/model_tr/ui_features_fw.rs index df57b5c5b4..8f6a528364 100644 --- a/core/embed/rust/src/ui/model_tr/ui_features_fw.rs +++ b/core/embed/rust/src/ui/model_tr/ui_features_fw.rs @@ -10,25 +10,27 @@ use crate::{ ui::{ component::{ connect::Connect, - text::paragraphs::{ - Checklist, Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort, - Paragraphs, VecExt, + text::{ + op::OpTextLayout, + paragraphs::{ + Checklist, Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort, + Paragraphs, VecExt, + }, }, - Component, ComponentExt, Empty, Label, LineBreaking, Paginate, Timeout, + Component, ComponentExt, Empty, FormattedText, Label, LineBreaking, Paginate, Timeout, }, layout::{ obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, util::RecoveryType, }, + model_tr::component::{ButtonActions, ButtonLayout, Page}, ui_features_fw::UIFeaturesFirmware, }, }; use super::{ component::{ - ButtonDetails, ButtonPage, CoinJoinProgress, ConfirmHomescreen, Frame, Homescreen, - Lockscreen, NumberInput, PassphraseEntry, PinEntry, Progress, ScrollableFrame, - SimpleChoice, WordlistEntry, WordlistType, + ButtonDetails, ButtonPage, CoinJoinProgress, ConfirmHomescreen, Flow, FlowPages, Frame, Homescreen, Lockscreen, NumberInput, PassphraseEntry, PinEntry, Progress, ScrollableFrame, SimpleChoice, WordlistEntry, WordlistType }, theme, ModelTRFeatures, }; @@ -303,6 +305,28 @@ impl UIFeaturesFirmware for ModelTRFeatures { Ok(layout) } + fn show_mismatch(title: TString<'static>) -> Result { + let get_page = move |page_index| { + assert!(page_index == 0); + + let btn_layout = ButtonLayout::arrow_none_text(TR::buttons__quit.into()); + let btn_actions = ButtonActions::cancel_none_confirm(); + let ops = OpTextLayout::new(theme::TEXT_NORMAL) + .text_bold_upper(title) + .newline() + .newline_half() + .text_normal(TR::addr_mismatch__contact_support_at) + .newline() + .text_bold(TR::addr_mismatch__support_url); + let formatted = FormattedText::new(ops); + Page::new(btn_layout, btn_actions, formatted) + }; + let pages = FlowPages::new(get_page, 1); + + let obj = RootComponent::new(Flow::new(pages)); + Ok(obj) + } + fn show_progress( description: TString<'static>, indeterminate: bool, diff --git a/core/embed/rust/src/ui/model_tt/layout.rs b/core/embed/rust/src/ui/model_tt/layout.rs index 572bc5ca45..7b2483d8a8 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -947,46 +947,6 @@ extern "C" fn new_show_success(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_show_mismatch(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 description: TString = TR::addr_mismatch__contact_support_at.into(); - let url: TString = TR::addr_mismatch__support_url.into(); - let button: TString = TR::buttons__quit.into(); - - let icon = BlendedImage::new( - theme::IMAGE_BG_OCTAGON, - theme::IMAGE_FG_WARN, - theme::WARN_COLOR, - theme::FG, - theme::BG, - ); - let obj = LayoutObj::new( - IconDialog::new( - icon, - title, - Button::cancel_confirm( - Button::with_icon(theme::ICON_BACK), - Button::with_text(button).styled(theme::button_reset()), - true, - ), - ) - .with_paragraph( - Paragraph::new(&theme::TEXT_NORMAL, description) - .centered() - .with_bottom_padding( - theme::TEXT_NORMAL.text_font.text_height() - - theme::TEXT_DEMIBOLD.text_font.text_height(), - ), - ) - .with_text(&theme::TEXT_DEMIBOLD, url), - )?; - - Ok(obj.into()) - }; - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } -} - extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let title: Option = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?; @@ -1417,10 +1377,6 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Success modal. No buttons shown when `button` is empty string.""" Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(), - /// def show_mismatch(*, title: str) -> LayoutObj[UiResult]: - /// """Warning modal, receiving address mismatch.""" - Qstr::MP_QSTR_show_mismatch => obj_fn_kw!(0, new_show_mismatch).as_obj(), - /// def show_simple( /// *, /// title: str | None, diff --git a/core/embed/rust/src/ui/model_tt/ui_features_fw.rs b/core/embed/rust/src/ui/model_tt/ui_features_fw.rs index 64eef877fb..bd1cf6885a 100644 --- a/core/embed/rust/src/ui/model_tt/ui_features_fw.rs +++ b/core/embed/rust/src/ui/model_tt/ui_features_fw.rs @@ -335,6 +335,42 @@ impl UIFeaturesFirmware for ModelTTFeatures { Ok(layout) } + fn show_mismatch(title: TString<'static>) -> Result { + let description: TString = TR::addr_mismatch__contact_support_at.into(); + let url: TString = TR::addr_mismatch__support_url.into(); + let button: TString = TR::buttons__quit.into(); + + let icon = BlendedImage::new( + theme::IMAGE_BG_OCTAGON, + theme::IMAGE_FG_WARN, + theme::WARN_COLOR, + theme::FG, + theme::BG, + ); + let layout = RootComponent::new( + IconDialog::new( + icon, + title, + Button::cancel_confirm( + Button::with_icon(theme::ICON_BACK), + Button::with_text(button).styled(theme::button_reset()), + true, + ), + ) + .with_paragraph( + Paragraph::new(&theme::TEXT_NORMAL, description) + .centered() + .with_bottom_padding( + theme::TEXT_NORMAL.text_font.text_height() + - theme::TEXT_DEMIBOLD.text_font.text_height(), + ), + ) + .with_text(&theme::TEXT_DEMIBOLD, url), + ); + + Ok(layout) + } + fn show_progress( description: TString<'static>, indeterminate: bool, diff --git a/core/embed/rust/src/ui/ui_features_fw.rs b/core/embed/rust/src/ui/ui_features_fw.rs index 1f6d8b307d..60d52f30c4 100644 --- a/core/embed/rust/src/ui/ui_features_fw.rs +++ b/core/embed/rust/src/ui/ui_features_fw.rs @@ -102,6 +102,8 @@ pub trait UIFeaturesFirmware { coinjoin_authorized: bool, ) -> Result; + fn show_mismatch(title: TString<'static>) -> Result; + fn show_progress( description: TString<'static>, indeterminate: bool, diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index 8e79661305..d626a6e76d 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -186,11 +186,6 @@ def show_success( """Success screen. Description is used in the footer.""" -# rust/src/ui/model_mercury/layout.rs -def show_mismatch(*, title: str) -> LayoutObj[UiResult]: - """Warning modal, receiving address mismatch.""" - - # rust/src/ui/model_mercury/layout.rs def show_simple( *, @@ -555,11 +550,6 @@ def show_passphrase() -> LayoutObj[UiResult]: """Show passphrase on host dialog.""" -# rust/src/ui/model_tr/layout.rs -def show_mismatch(*, title: str) -> LayoutObj[UiResult]: - """Warning modal, receiving address mismatch.""" - - # rust/src/ui/model_tr/layout.rs def confirm_with_info( *, @@ -845,11 +835,6 @@ def show_success( """Success modal. No buttons shown when `button` is empty string.""" -# rust/src/ui/model_tt/layout.rs -def show_mismatch(*, title: str) -> LayoutObj[UiResult]: - """Warning modal, receiving address mismatch.""" - - # rust/src/ui/model_tt/layout.rs def show_simple( *, diff --git a/core/mocks/generated/trezorui_api.pyi b/core/mocks/generated/trezorui_api.pyi index 8f22ecfbee..4b36e08e8c 100644 --- a/core/mocks/generated/trezorui_api.pyi +++ b/core/mocks/generated/trezorui_api.pyi @@ -242,6 +242,11 @@ def show_lockscreen( """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( *, diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py index d87633da72..55b6fed606 100644 --- a/core/src/trezor/ui/layouts/mercury/__init__.py +++ b/core/src/trezor/ui/layouts/mercury/__init__.py @@ -1042,7 +1042,7 @@ async def confirm_signverify( await with_info(address_layout, info_layout, br_name, br_code=BR_CODE_OTHER) except ActionCancelled: result = await interact( - trezorui2.show_mismatch(title=TR.addr_mismatch__mismatch), + trezorui_api.show_mismatch(title=TR.addr_mismatch__mismatch), None, raise_on_cancel=None, ) diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index e305ec0444..618e0169d6 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -306,7 +306,7 @@ async def show_address( # User pressed left cancel button, show mismatch dialogue. else: result = await interact( - trezorui2.show_mismatch(title=mismatch_title), + trezorui_api.show_mismatch(title=mismatch_title), None, raise_on_cancel=None, ) diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index 4c83561ded..b6b757889b 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -289,7 +289,7 @@ async def show_address( else: result = await interact( - trezorui2.show_mismatch(title=mismatch_title), + trezorui_api.show_mismatch(title=mismatch_title), None, raise_on_cancel=None, ) @@ -1097,7 +1097,7 @@ async def confirm_signverify( await with_info(address_layout, info_layout, br_name, br_code=BR_CODE_OTHER) except ActionCancelled: result = await interact( - trezorui2.show_mismatch(title=TR.addr_mismatch__mismatch), + trezorui_api.show_mismatch(title=TR.addr_mismatch__mismatch), None, raise_on_cancel=None, )