From e8b0b9294742a07c128066b7baa41f2000e5f149 Mon Sep 17 00:00:00 2001 From: obrusvit Date: Sat, 14 Sep 2024 00:26:23 +0200 Subject: [PATCH] refactor(core/mercury): separate upy args parsing WIP - lifetime issues to FIX [no changelog] --- .../ui/model_mercury/flow/confirm_action.rs | 48 +-- .../flow/confirm_firmware_update.rs | 129 +++--- .../ui/model_mercury/flow/confirm_output.rs | 65 +-- .../ui/model_mercury/flow/confirm_reset.rs | 13 +- .../model_mercury/flow/confirm_set_new_pin.rs | 133 +++--- .../ui/model_mercury/flow/confirm_summary.rs | 228 +++++----- .../model_mercury/flow/continue_recovery.rs | 40 +- .../src/ui/model_mercury/flow/get_address.rs | 289 ++++++------- .../ui/model_mercury/flow/prompt_backup.rs | 137 +++--- .../ui/model_mercury/flow/request_number.rs | 119 +++--- .../model_mercury/flow/request_passphrase.rs | 50 +-- .../ui/model_mercury/flow/set_brightness.rs | 134 +++--- .../ui/model_mercury/flow/show_share_words.rs | 145 +++---- .../ui/model_mercury/flow/show_tutorial.rs | 253 ++++++----- .../ui/model_mercury/flow/warning_hi_prio.rs | 110 +++-- .../embed/rust/src/ui/model_mercury/layout.rs | 397 +++++++++++++++++- 16 files changed, 1233 insertions(+), 1057 deletions(-) diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_action.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_action.rs index 0e2913f3200..43518f5f11f 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_action.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_action.rs @@ -1,7 +1,6 @@ use crate::{ error::{self, Error}, maybe_trace::MaybeTrace, - micropython::{map::Map, obj::Obj, qstr::Qstr, util}, strutil::TString, translations::TR, ui::{ @@ -15,7 +14,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, SwipePage, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -96,33 +94,17 @@ impl FlowController for ConfirmActionSimple { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_action_obj) } -} - -fn new_confirm_action_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let action: Option = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?; - let description: Option = kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; - let subtitle: Option = kwargs - .get(Qstr::MP_QSTR_subtitle) - .unwrap_or(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 verb_cancel: Option = kwargs - .get(Qstr::MP_QSTR_verb_cancel) - .unwrap_or_else(|_| Obj::const_none()) - .try_into_option()?; - let reverse: bool = kwargs.get_or(Qstr::MP_QSTR_reverse, false)?; - let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; - // let hold_danger: bool = kwargs.get_or(Qstr::MP_QSTR_hold_danger, false)?; - let prompt_screen: bool = kwargs.get_or(Qstr::MP_QSTR_prompt_screen, false)?; - let prompt_title: TString = kwargs.get_or(Qstr::MP_QSTR_prompt_title, title)?; - +pub fn new_confirm_action( + title: TString<'static>, + action: Option>, + description: Option>, + subtitle: Option>, + verb_cancel: Option>, + reverse: bool, + hold: bool, + prompt_screen: bool, + prompt_title: TString<'static>, +) -> Result { let paragraphs = { let action = action.unwrap_or("".into()); let description = description.unwrap_or("".into()); @@ -159,7 +141,7 @@ pub fn new_confirm_action_uni( prompt_screen: Option>, hold: bool, info: bool, -) -> Result { +) -> Result { let (prompt_screen, prompt_pages, flow, page) = create_flow(title, prompt_screen, hold); let mut content_intro = Frame::left_aligned(title, content) @@ -220,12 +202,12 @@ fn create_menu_and_confirm( info: bool, prompt_screen: Option>, flow: SwipeFlow, -) -> Result { +) -> Result { let flow = create_menu(flow, verb_cancel, info, prompt_screen)?; let flow = create_confirm(flow, subtitle, hold, prompt_screen)?; - Ok(LayoutObj::new(flow)?.into()) + Ok(flow) } fn create_menu( @@ -310,7 +292,7 @@ pub fn new_confirm_action_simple prompt_screen: Option>, hold: bool, info: bool, -) -> Result { +) -> Result { new_confirm_action_uni( SwipeContent::new(SwipePage::vertical(content)), title, diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_firmware_update.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_firmware_update.rs index 0beb2484a91..df7e1e47361 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_firmware_update.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_firmware_update.rs @@ -1,6 +1,5 @@ use crate::{ error, - micropython::{map::Map, obj::Obj, qstr::Qstr, util}, strutil::TString, translations::TR, ui::{ @@ -14,7 +13,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -65,78 +63,65 @@ impl FlowController for ConfirmFirmwareUpdate { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_confirm_firmware_update( - n_args: usize, - args: *const Obj, - kwargs: *mut Map, -) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmFirmwareUpdate::new_obj) } -} - -impl ConfirmFirmwareUpdate { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; - let fingerprint: TString = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?; +pub fn new_confirm_firmware_update( + description: TString<'static>, + fingerprint: TString<'static>, // FIXME: static lifetime is clearly wrong here +) -> Result { + let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description)); + let content_intro = Frame::left_aligned( + TR::firmware_update__title.into(), + SwipeContent::new(paragraphs), + ) + .with_menu_button() + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Left, SwipeSettings::default()) + .map(|msg| matches!(msg, FrameMsg::Button(FlowMsg::Info)).then_some(FlowMsg::Info)); - let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description)); - let content_intro = Frame::left_aligned( - TR::firmware_update__title.into(), - SwipeContent::new(paragraphs), - ) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .map(|msg| matches!(msg, FrameMsg::Button(FlowMsg::Info)).then_some(FlowMsg::Info)); + let content_menu = Frame::left_aligned( + TString::empty(), + VerticalMenu::empty() + .item( + theme::ICON_CHEVRON_RIGHT, + TR::firmware_update__title_fingerprint.into(), + ) + .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_menu = Frame::left_aligned( - TString::empty(), - VerticalMenu::empty() - .item( - theme::ICON_CHEVRON_RIGHT, - TR::firmware_update__title_fingerprint.into(), - ) - .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 paragraphs_fingerprint = + Paragraphs::new(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, fingerprint)); + let content_fingerprint = Frame::left_aligned( + TR::firmware_update__title_fingerprint.into(), + SwipeContent::new(paragraphs_fingerprint), + ) + .with_cancel_button() + .with_swipe(Direction::Right, SwipeSettings::default()) + .map(|msg| matches!(msg, FrameMsg::Button(FlowMsg::Cancelled)).then_some(FlowMsg::Cancelled)); - let paragraphs_fingerprint = - Paragraphs::new(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, fingerprint)); - let content_fingerprint = Frame::left_aligned( - TR::firmware_update__title_fingerprint.into(), - SwipeContent::new(paragraphs_fingerprint), - ) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::default()) - .map(|msg| { - matches!(msg, FrameMsg::Button(FlowMsg::Cancelled)).then_some(FlowMsg::Cancelled) - }); + let content_confirm = Frame::left_aligned( + TR::firmware_update__title.into(), + SwipeContent::new(PromptScreen::new_hold_to_confirm()), + ) + .with_menu_button() + .with_footer(TR::instructions__hold_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 content_confirm = Frame::left_aligned( - TR::firmware_update__title.into(), - SwipeContent::new(PromptScreen::new_hold_to_confirm()), - ) - .with_menu_button() - .with_footer(TR::instructions__hold_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(&ConfirmFirmwareUpdate::Intro)? - .with_page(&ConfirmFirmwareUpdate::Intro, content_intro)? - .with_page(&ConfirmFirmwareUpdate::Menu, content_menu)? - .with_page(&ConfirmFirmwareUpdate::Fingerprint, content_fingerprint)? - .with_page(&ConfirmFirmwareUpdate::Confirm, content_confirm)?; - Ok(LayoutObj::new(res)?.into()) - } + let res = SwipeFlow::new(&ConfirmFirmwareUpdate::Intro)? + .with_page(&ConfirmFirmwareUpdate::Intro, content_intro)? + .with_page(&ConfirmFirmwareUpdate::Menu, content_menu)? + .with_page(&ConfirmFirmwareUpdate::Fingerprint, content_fingerprint)? + .with_page(&ConfirmFirmwareUpdate::Confirm, content_confirm)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs index 5aa3b2a8f86..3ea64885d15 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_output.rs @@ -2,7 +2,7 @@ use heapless::Vec; use crate::{ error, - micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util}, + micropython::{iter::IterBuf, obj::Obj, util}, strutil::TString, translations::TR, ui::{ @@ -13,7 +13,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -212,46 +211,26 @@ fn get_cancel_page( }) } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_output_obj) } -} - -fn new_confirm_output_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: Option = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?; - let subtitle: Option = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?; - - let account: Option = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?; - let account_path: Option = - kwargs.get(Qstr::MP_QSTR_account_path)?.try_into_option()?; - - let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; - let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; - - let message: Obj = kwargs.get(Qstr::MP_QSTR_message)?; - let amount: Option = kwargs.get(Qstr::MP_QSTR_amount)?.try_into_option()?; - - 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 address: Option = kwargs.get(Qstr::MP_QSTR_address)?.try_into_option()?; - let address_title: Option = - kwargs.get(Qstr::MP_QSTR_address_title)?.try_into_option()?; - - let summary_items: Obj = kwargs.get(Qstr::MP_QSTR_summary_items)?; - let fee_items: Obj = kwargs.get(Qstr::MP_QSTR_fee_items)?; - - let summary_title: Option = - kwargs.get(Qstr::MP_QSTR_summary_title)?.try_into_option()?; - let summary_br_name: Option = kwargs - .get(Qstr::MP_QSTR_summary_br_name)? - .try_into_option()?; - let summary_br_code: Option = kwargs - .get(Qstr::MP_QSTR_summary_br_code)? - .try_into_option()?; - - let cancel_text: Option = kwargs.get(Qstr::MP_QSTR_cancel_text)?.try_into_option()?; - +pub fn new_confirm_output( + title: Option>, + subtitle: Option>, + account: Option>, + account_path: Option>, + br_name: TString<'static>, + br_code: u16, + message: Obj, + amount: Option, + chunkify: bool, + text_mono: bool, + address: Option, + address_title: Option>, + summary_items: Obj, + fee_items: Obj, + summary_title: Option>, + summary_br_name: Option>, + summary_br_code: Option, + cancel_text: Option>, +) -> Result { // Main let main_content = ConfirmBlobParams::new(title.unwrap_or(TString::empty()), message, None) .with_subtitle(subtitle) @@ -450,5 +429,5 @@ fn new_confirm_output_obj(_args: &[Obj], kwargs: &Map) -> Result Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_reset_obj) } -} - -fn new_confirm_reset_obj(_args: &[Obj], kwargs: &Map) -> Result { - let recovery: bool = kwargs.get_or(Qstr::MP_QSTR_recovery, false)?; - +pub fn new_confirm_reset(recovery: bool) -> Result { let (title, br, cancel_btn_text) = if recovery { ( TR::recovery__title_recover.into(), @@ -168,5 +159,5 @@ fn new_confirm_reset_obj(_args: &[Obj], kwargs: &Map) -> Result Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetNewPin::new_obj) } -} - -impl SetNewPin { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - // TODO: supply more arguments for Wipe code setting when figma done - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; - - let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description)); - let content_intro = Frame::left_aligned(title, SwipeContent::new(paragraphs)) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .map(|msg| match msg { - FrameMsg::Button(bm) => Some(bm), - _ => None, - }); - - let content_menu = Frame::left_aligned( - "".into(), - VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::pin__cancel_setup.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(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - FrameMsg::Button(_) => None, - }); - - let paragraphs_cancel_intro = ParagraphVecShort::from_iter([ - Paragraph::new(&theme::TEXT_WARNING, TR::words__not_recommended), - Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, TR::pin__cancel_info), - ]) - .into_paragraphs(); - let content_cancel_intro = Frame::left_aligned( - TR::pin__cancel_setup.into(), - SwipeContent::new(paragraphs_cancel_intro), - ) - .with_cancel_button() - .with_footer( - TR::instructions__swipe_up.into(), - Some(TR::pin__cancel_description.into()), - ) +pub fn new_set_new_pin( + title: TString<'static>, + description: TString<'static>, +) -> Result { + // TODO: supply more arguments for Wipe code setting when figma done + let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description)); + let content_intro = Frame::left_aligned(title, SwipeContent::new(paragraphs)) + .with_menu_button() + .with_footer(TR::instructions__swipe_up.into(), None) .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Right, SwipeSettings::immediate()) + .with_swipe(Direction::Left, SwipeSettings::default()) .map(|msg| match msg { FrameMsg::Button(bm) => Some(bm), _ => None, }); - let content_cancel_confirm = Frame::left_aligned( - TR::pin__cancel_setup.into(), - SwipeContent::new(PromptScreen::new_tap_to_cancel()), - ) - .with_cancel_button() - .with_footer(TR::instructions__tap_to_confirm.into(), None) - .with_swipe(Direction::Down, SwipeSettings::default()) - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| match msg { - FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), - FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - _ => None, - }); + let content_menu = Frame::left_aligned( + "".into(), + VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::pin__cancel_setup.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(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + FrameMsg::Button(_) => None, + }); - let res = SwipeFlow::new(&SetNewPin::Intro)? - .with_page(&SetNewPin::Intro, content_intro)? - .with_page(&SetNewPin::Menu, content_menu)? - .with_page(&SetNewPin::CancelPinIntro, content_cancel_intro)? - .with_page(&SetNewPin::CancelPinConfirm, content_cancel_confirm)?; - Ok(LayoutObj::new(res)?.into()) - } + let paragraphs_cancel_intro = ParagraphVecShort::from_iter([ + Paragraph::new(&theme::TEXT_WARNING, TR::words__not_recommended), + Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, TR::pin__cancel_info), + ]) + .into_paragraphs(); + let content_cancel_intro = Frame::left_aligned( + TR::pin__cancel_setup.into(), + SwipeContent::new(paragraphs_cancel_intro), + ) + .with_cancel_button() + .with_footer( + TR::instructions__swipe_up.into(), + Some(TR::pin__cancel_description.into()), + ) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Button(bm) => Some(bm), + _ => None, + }); + + let content_cancel_confirm = Frame::left_aligned( + TR::pin__cancel_setup.into(), + SwipeContent::new(PromptScreen::new_tap_to_cancel()), + ) + .with_cancel_button() + .with_footer(TR::instructions__tap_to_confirm.into(), None) + .with_swipe(Direction::Down, SwipeSettings::default()) + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), + FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + _ => None, + }); + + let res = SwipeFlow::new(&SetNewPin::Intro)? + .with_page(&SetNewPin::Intro, content_intro)? + .with_page(&SetNewPin::Menu, content_menu)? + .with_page(&SetNewPin::CancelPinIntro, content_cancel_intro)? + .with_page(&SetNewPin::CancelPinConfirm, content_cancel_confirm)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs index 8df9baa749f..2b2c4b9533e 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_summary.rs @@ -2,7 +2,7 @@ use heapless::Vec; use crate::{ error, - micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util}, + micropython::{iter::IterBuf, obj::Obj, util}, strutil::TString, translations::TR, ui::{ @@ -13,8 +13,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, - model_mercury::component::SwipeContent, }, }; @@ -76,127 +74,119 @@ impl FlowController for ConfirmSummary { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_confirm_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmSummary::new_obj) } -} - -impl ConfirmSummary { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; - let account_items: Obj = kwargs.get(Qstr::MP_QSTR_account_items)?; - let fee_items: Obj = kwargs.get(Qstr::MP_QSTR_fee_items)?; - let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; - let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; - let cancel_text: Option = - kwargs.get(Qstr::MP_QSTR_cancel_text)?.try_into_option()?; - - // Summary - let mut summary = ShowInfoParams::new(title) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe_up(); - for pair in IterBuf::new().try_iterate(items)? { - let [label, value]: [TString; 2] = util::iter_into_array(pair)?; - summary = unwrap!(summary.add(label, value)); - } - let content_summary = summary - .into_layout()? - .one_button_request(ButtonRequest::from_num(br_code, br_name)) - // Summary(1) + Hold(1) - .with_pages(|summary_pages| summary_pages + 1); - - // Hold to confirm - let content_hold = Frame::left_aligned( - TR::send__sign_transaction.into(), - SwipeContent::new(PromptScreen::new_hold_to_confirm()), - ) +pub fn new_confirm_summary( + title: TString<'static>, + items: Obj, + account_items: Obj, + fee_items: Obj, + br_name: TString<'static>, + br_code: u16, + cancel_text: Option>, +) -> Result { + // Summary + let mut summary = ShowInfoParams::new(title) .with_menu_button() - .with_footer(TR::instructions__hold_to_sign.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, - }); - - // FeeInfo - let mut has_fee_info = false; - let mut fee = ShowInfoParams::new(TR::confirm_total__title_fee.into()).with_cancel_button(); - for pair in IterBuf::new().try_iterate(fee_items)? { - let [label, value]: [TString; 2] = util::iter_into_array(pair)?; - fee = unwrap!(fee.add(label, value)); - has_fee_info = true; - } - let content_fee = fee.into_layout()?; - - // AccountInfo - let mut has_account_info = false; - let mut account = ShowInfoParams::new(TR::send__send_from.into()).with_cancel_button(); - for pair in IterBuf::new().try_iterate(account_items)? { - let [label, value]: [TString; 2] = util::iter_into_array(pair)?; - account = unwrap!(account.add(label, value)); - has_account_info = true; - } - let content_account = account.into_layout()?; - - // Menu - let mut menu = VerticalMenu::empty(); - let mut menu_items = Vec::::new(); - if has_fee_info { - menu = menu.item( - theme::ICON_CHEVRON_RIGHT, - TR::confirm_total__title_fee.into(), - ); - unwrap!(menu_items.push(MENU_ITEM_FEE_INFO)); - } - if has_account_info { - menu = menu.item( - theme::ICON_CHEVRON_RIGHT, - TR::address_details__account_info.into(), - ); - unwrap!(menu_items.push(MENU_ITEM_ACCOUNT_INFO)); - } - menu = menu.danger( - theme::ICON_CANCEL, - cancel_text.unwrap_or(TR::send__cancel_sign.into()), + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe_up(); + for pair in IterBuf::new().try_iterate(items)? { + let [label, value]: [TString; 2] = util::iter_into_array(pair)?; + summary = unwrap!(summary.add(label, value)); + } + let content_summary = summary + .into_layout()? + .one_button_request(ButtonRequest::from_num(br_code, br_name)) + // Summary(1) + Hold(1) + .with_pages(|summary_pages| summary_pages + 1); + + // Hold to confirm + let content_hold = Frame::left_aligned( + TR::send__sign_transaction.into(), + SwipeContent::new(PromptScreen::new_hold_to_confirm()), + ) + .with_menu_button() + .with_footer(TR::instructions__hold_to_sign.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, + }); + + // FeeInfo + let mut has_fee_info = false; + let mut fee = ShowInfoParams::new(TR::confirm_total__title_fee.into()).with_cancel_button(); + for pair in IterBuf::new().try_iterate(fee_items)? { + let [label, value]: [TString; 2] = util::iter_into_array(pair)?; + fee = unwrap!(fee.add(label, value)); + has_fee_info = true; + } + let content_fee = fee.into_layout()?; + + // AccountInfo + let mut has_account_info = false; + let mut account = ShowInfoParams::new(TR::send__send_from.into()).with_cancel_button(); + for pair in IterBuf::new().try_iterate(account_items)? { + let [label, value]: [TString; 2] = util::iter_into_array(pair)?; + account = unwrap!(account.add(label, value)); + has_account_info = true; + } + let content_account = account.into_layout()?; + + // Menu + let mut menu = VerticalMenu::empty(); + let mut menu_items = Vec::::new(); + if has_fee_info { + menu = menu.item( + theme::ICON_CHEVRON_RIGHT, + TR::confirm_total__title_fee.into(), ); - unwrap!(menu_items.push(MENU_ITEM_CANCEL)); - let content_menu = Frame::left_aligned(TString::empty(), menu) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(move |msg| match msg { - FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => { - let selected_item = menu_items[i]; - Some(FlowMsg::Choice(selected_item)) - } - FrameMsg::Button(_) => Some(FlowMsg::Cancelled), - }); - - // CancelTap - let content_cancel_tap = Frame::left_aligned( - TR::send__cancel_sign.into(), - PromptScreen::new_tap_to_cancel(), - ) + unwrap!(menu_items.push(MENU_ITEM_FEE_INFO)); + } + if has_account_info { + menu = menu.item( + theme::ICON_CHEVRON_RIGHT, + TR::address_details__account_info.into(), + ); + unwrap!(menu_items.push(MENU_ITEM_ACCOUNT_INFO)); + } + menu = menu.danger( + theme::ICON_CANCEL, + cancel_text.unwrap_or(TR::send__cancel_sign.into()), + ); + unwrap!(menu_items.push(MENU_ITEM_CANCEL)); + let content_menu = Frame::left_aligned(TString::empty(), menu) .with_cancel_button() - .with_footer(TR::instructions__tap_to_confirm.into(), None) .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| match msg { - FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), + .map(move |msg| match msg { + FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => { + let selected_item = menu_items[i]; + Some(FlowMsg::Choice(selected_item)) + } FrameMsg::Button(_) => Some(FlowMsg::Cancelled), - _ => None, }); - let res = SwipeFlow::new(&ConfirmSummary::Summary)? - .with_page(&ConfirmSummary::Summary, content_summary)? - .with_page(&ConfirmSummary::Hold, content_hold)? - .with_page(&ConfirmSummary::Menu, content_menu)? - .with_page(&ConfirmSummary::FeeInfo, content_fee)? - .with_page(&ConfirmSummary::AccountInfo, content_account)? - .with_page(&ConfirmSummary::CancelTap, content_cancel_tap)?; - - Ok(LayoutObj::new(res)?.into()) - } + // CancelTap + let content_cancel_tap = Frame::left_aligned( + TR::send__cancel_sign.into(), + PromptScreen::new_tap_to_cancel(), + ) + .with_cancel_button() + .with_footer(TR::instructions__tap_to_confirm.into(), None) + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), + FrameMsg::Button(_) => Some(FlowMsg::Cancelled), + _ => None, + }); + + let res = SwipeFlow::new(&ConfirmSummary::Summary)? + .with_page(&ConfirmSummary::Summary, content_summary)? + .with_page(&ConfirmSummary::Hold, content_hold)? + .with_page(&ConfirmSummary::Menu, content_menu)? + .with_page(&ConfirmSummary::FeeInfo, content_fee)? + .with_page(&ConfirmSummary::AccountInfo, content_account)? + .with_page(&ConfirmSummary::CancelTap, content_cancel_tap)?; + + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/continue_recovery.rs b/core/embed/rust/src/ui/model_mercury/flow/continue_recovery.rs index d8b2218018d..1196c4f4161 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/continue_recovery.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/continue_recovery.rs @@ -1,6 +1,5 @@ use crate::{ error, - micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util}, strutil::TString, translations::TR, ui::{ @@ -18,7 +17,7 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, SwipePage, }, geometry::Direction, - layout::{obj::LayoutObj, util::RecoveryType}, + layout::util::RecoveryType, }, }; @@ -143,10 +142,6 @@ impl FlowController for ContinueRecoveryBetweenSharesAdvanced { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_continue_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_obj) } -} fn footer_update_fn( content: &SwipeContent>>, ctx: &mut EventCtx, @@ -159,24 +154,13 @@ fn footer_update_fn( footer.update_page_counter(ctx, current_page, Some(total_pages)); } -fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let first_screen: bool = kwargs.get(Qstr::MP_QSTR_first_screen)?.try_into()?; - let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?; - let text: TString = kwargs.get(Qstr::MP_QSTR_text)?.try_into()?; // #shares entered - let subtext: Option = kwargs.get(Qstr::MP_QSTR_subtext)?.try_into_option()?; // #shares remaining - let pages: Option = kwargs.get(Qstr::MP_QSTR_pages)?.try_into_option()?; // info about remaining shares - - let mut pars_show_shares = ParagraphVecLong::new(); - if let Some(pages) = pages { - let pages_iterable: Obj = pages; - for page in IterBuf::new().try_iterate(pages_iterable)? { - let [title, description]: [TString; 2] = util::iter_into_array(page)?; - pars_show_shares - .add(Paragraph::new(&theme::TEXT_SUB_GREY, title)) - .add(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, description).break_after()); - } - } - +pub fn new_continue_recovery( + first_screen: bool, + recovery_type: RecoveryType, + text: TString<'static>, + subtext: Option>, + pages: Option>, // FIXME: Lifetime +) -> Result { let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type { RecoveryType::Normal => ( TR::recovery__title, @@ -277,7 +261,7 @@ fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { SwipeFlow::new(&ContinueRecoveryBeforeShares::Main)? .with_page(&ContinueRecoveryBeforeShares::Main, content_main)? .with_page(&ContinueRecoveryBeforeShares::Menu, content_menu)? - } else if pars_show_shares.is_empty() { + } else if pages.is_none() { let content_menu = Frame::left_aligned( TString::empty(), VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()), @@ -321,10 +305,10 @@ fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { TR::instructions__swipe_up.into(), TR::recovery__more_shares_needed.into(), ); - let n_remaining_shares = pars_show_shares.len() / 2; + let n_remaining_shares = pages.as_ref().unwrap().len() / 2; let content_remaining_shares = Frame::left_aligned( TR::recovery__title_remaining_shares.into(), - SwipeContent::new(SwipePage::vertical(pars_show_shares.into_paragraphs())), + SwipeContent::new(SwipePage::vertical(pages.unwrap().into_paragraphs())), ) .with_cancel_button() .with_footer_page_hint( @@ -360,5 +344,5 @@ fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { content_remaining_shares, )? }; - Ok(LayoutObj::new(res)?.into()) + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/get_address.rs b/core/embed/rust/src/ui/model_mercury/flow/get_address.rs index eda7695ae49..df84622fd54 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/get_address.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/get_address.rs @@ -1,6 +1,6 @@ use crate::{ error, - micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util}, + micropython::{iter::IterBuf, obj::Obj, util}, strutil::TString, translations::TR, ui::{ @@ -15,7 +15,7 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, SwipePage, }, geometry::Direction, - layout::{obj::LayoutObj, util::ConfirmBlob}, + layout::util::ConfirmBlob, }, }; @@ -84,153 +84,142 @@ impl FlowController for GetAddress { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_get_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, GetAddress::new_obj) } -} - -impl GetAddress { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let description: Option = - kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; - let extra: Option = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?; - let address: Obj = kwargs.get(Qstr::MP_QSTR_address)?; - let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; - - let address_qr: TString = kwargs.get(Qstr::MP_QSTR_address_qr)?.try_into()?; - let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?; - - let account: Option = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?; - let path: Option = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?; - let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?; - - let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; - let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; - - // 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 { - description: description.unwrap_or("".into()), - extra: extra.unwrap_or("".into()), - data: address.try_into()?, - description_font: &theme::TEXT_NORMAL, - extra_font: &theme::TEXT_DEMIBOLD, - data_font: data_style, - } - .into_paragraphs(); - let content_address = - Frame::left_aligned(title, SwipeContent::new(SwipePage::vertical(paragraphs))) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .with_vertical_pages() - .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)) - .one_button_request(ButtonRequest::from_num(br_code, br_name)) - // Count tap-to-confirm screen towards page count - .with_pages(|address_pages| address_pages + 1); - - // Tap - let content_tap = - Frame::left_aligned(title, SwipeContent::new(PromptScreen::new_tap_to_confirm())) - .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 content_confirmed = Frame::left_aligned( - TR::words__title_success.into(), - StatusScreen::new_success_timeout(TR::address__confirmed.into()), - ) - .with_footer(TR::instructions__continue_in_app.into(), None) - .with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT) - .map(|_| Some(FlowMsg::Confirmed)); - - // Menu - let content_menu = Frame::left_aligned( - "".into(), - VerticalMenu::empty() - .item(theme::ICON_QR_CODE, TR::address__qr_code.into()) - .item( - theme::ICON_CHEVRON_RIGHT, - TR::address_details__account_info.into(), - ) - .danger(theme::ICON_CANCEL, TR::address__cancel_receive.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), - }); - - // QrCode - let content_qr = Frame::left_aligned( - title, - address_qr - .map(|s| Qr::new(s, case_sensitive))? - .with_border(QR_BORDER), - ) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Cancelled)); - - // AccountInfo - let mut ad = AddressDetails::new(TR::address_details__account_info.into(), account, path)?; - for i in IterBuf::new().try_iterate(xpubs)? { - let [xtitle, text]: [TString; 2] = util::iter_into_array(i)?; - ad.add_xpub(xtitle, text)?; - } - let content_account = ad.map(|_| Some(FlowMsg::Cancelled)); - - // Cancel - let content_cancel_info = Frame::left_aligned( - TR::address__cancel_receive.into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::address__cancel_contact_support, - ))), - ) - .with_cancel_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::Cancelled)); - - // CancelTap - let content_cancel_tap = Frame::left_aligned( - TR::address__cancel_receive.into(), - PromptScreen::new_tap_to_cancel(), - ) - .with_cancel_button() - .with_footer(TR::instructions__tap_to_confirm.into(), None) - .with_swipe(Direction::Down, SwipeSettings::default()) - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| match msg { - FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), - FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - _ => None, - }); - - let res = SwipeFlow::new(&GetAddress::Address)? - .with_page(&GetAddress::Address, content_address)? - .with_page(&GetAddress::Tap, content_tap)? - .with_page(&GetAddress::Confirmed, content_confirmed)? - .with_page(&GetAddress::Menu, content_menu)? - .with_page(&GetAddress::QrCode, content_qr)? - .with_page(&GetAddress::AccountInfo, content_account)? - .with_page(&GetAddress::Cancel, content_cancel_info)? - .with_page(&GetAddress::CancelTap, content_cancel_tap)?; - Ok(LayoutObj::new(res)?.into()) +pub fn new_get_address( + title: TString<'static>, + description: Option>, + extra: Option>, + address: Obj, // TODO: get rid of Obj + chunkify: bool, + address_qr: TString<'static>, + case_sensitive: bool, + account: Option>, + path: Option>, + xpubs: Obj, // TODO: get rid of Obj + br_code: u16, + br_name: TString<'static>, +) -> Result { + // 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 { + description: description.unwrap_or_else(|| "".into()), + extra: extra.unwrap_or_else(|| "".into()), + data: address.try_into()?, + description_font: &theme::TEXT_NORMAL, + extra_font: &theme::TEXT_DEMIBOLD, + data_font: data_style, + } + .into_paragraphs(); + let content_address = + Frame::left_aligned(title, SwipeContent::new(SwipePage::vertical(paragraphs))) + .with_menu_button() + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Left, SwipeSettings::default()) + .with_vertical_pages() + .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)) + .one_button_request(ButtonRequest::from_num(br_code, br_name)) + // Count tap-to-confirm screen towards page count + .with_pages(|address_pages| address_pages + 1); + + // Tap + let content_tap = + Frame::left_aligned(title, SwipeContent::new(PromptScreen::new_tap_to_confirm())) + .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 content_confirmed = Frame::left_aligned( + TR::words__title_success.into(), + StatusScreen::new_success_timeout(TR::address__confirmed.into()), + ) + .with_footer(TR::instructions__continue_in_app.into(), None) + .with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT) + .map(|_| Some(FlowMsg::Confirmed)); + + // Menu + let content_menu = Frame::left_aligned( + "".into(), + VerticalMenu::empty() + .item(theme::ICON_QR_CODE, TR::address__qr_code.into()) + .item( + theme::ICON_CHEVRON_RIGHT, + TR::address_details__account_info.into(), + ) + .danger(theme::ICON_CANCEL, TR::address__cancel_receive.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), + }); + + // QrCode + let content_qr = Frame::left_aligned( + title, + address_qr + .map(|s| Qr::new(s, case_sensitive))? + .with_border(QR_BORDER), + ) + .with_cancel_button() + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Cancelled)); + + // AccountInfo + let mut ad = AddressDetails::new(TR::address_details__account_info.into(), account, path)?; + for i in IterBuf::new().try_iterate(xpubs)? { + let [xtitle, text]: [TString; 2] = util::iter_into_array(i)?; + ad.add_xpub(xtitle, text)?; } + let content_account = ad.map(|_| Some(FlowMsg::Cancelled)); + + // Cancel + let content_cancel_info = Frame::left_aligned( + TR::address__cancel_receive.into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::address__cancel_contact_support, + ))), + ) + .with_cancel_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::Cancelled)); + + // CancelTap + let content_cancel_tap = Frame::left_aligned( + TR::address__cancel_receive.into(), + PromptScreen::new_tap_to_cancel(), + ) + .with_cancel_button() + .with_footer(TR::instructions__tap_to_confirm.into(), None) + .with_swipe(Direction::Down, SwipeSettings::default()) + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), + FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + _ => None, + }); + + let res = SwipeFlow::new(&GetAddress::Address)? + .with_page(&GetAddress::Address, content_address)? + .with_page(&GetAddress::Tap, content_tap)? + .with_page(&GetAddress::Confirmed, content_confirmed)? + .with_page(&GetAddress::Menu, content_menu)? + .with_page(&GetAddress::QrCode, content_qr)? + .with_page(&GetAddress::AccountInfo, content_account)? + .with_page(&GetAddress::Cancel, content_cancel_info)? + .with_page(&GetAddress::CancelTap, content_cancel_tap)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/prompt_backup.rs b/core/embed/rust/src/ui/model_mercury/flow/prompt_backup.rs index 4ffc88ac45a..8af19acefb0 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/prompt_backup.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/prompt_backup.rs @@ -1,6 +1,5 @@ use crate::{ error, - micropython::{map::Map, obj::Obj, util}, strutil::TString, translations::TR, ui::{ @@ -14,7 +13,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -65,82 +63,75 @@ impl FlowController for PromptBackup { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_prompt_backup(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, PromptBackup::new_obj) } -} - -impl PromptBackup { - fn new_obj(_args: &[Obj], _kwargs: &Map) -> Result { - let title: TString = TR::backup__title_create_wallet_backup.into(); - let text_intro: TString = TR::backup__it_should_be_backed_up.into(); - - let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text_intro)); - let content_intro = Frame::left_aligned(title, SwipeContent::new(paragraphs)) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .map(|msg| match msg { - FrameMsg::Button(bm) => Some(bm), - _ => None, - }); - - let content_menu = Frame::left_aligned( - "".into(), - VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::backup__title_skip.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(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - FrameMsg::Button(_) => None, - }); +pub fn new_prompt_backup() -> Result { + let title: TString = TR::backup__title_create_wallet_backup.into(); + let text_intro: TString = TR::backup__it_should_be_backed_up.into(); - let paragraphs_skip_intro = ParagraphVecShort::from_iter([ - Paragraph::new(&theme::TEXT_WARNING, TR::words__not_recommended), - Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::backup__create_backup_to_prevent_loss, - ), - ]) - .into_paragraphs(); - let content_skip_intro = Frame::left_aligned( - TR::backup__title_skip.into(), - SwipeContent::new(paragraphs_skip_intro), - ) - .with_cancel_button() - .with_footer( - TR::instructions__swipe_up.into(), - Some(TR::words__continue_anyway.into()), - ) + let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text_intro)); + let content_intro = Frame::left_aligned(title, SwipeContent::new(paragraphs)) + .with_menu_button() + .with_footer(TR::instructions__swipe_up.into(), None) .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Right, SwipeSettings::immediate()) + .with_swipe(Direction::Left, SwipeSettings::default()) .map(|msg| match msg { - FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + FrameMsg::Button(bm) => Some(bm), _ => None, }); - let content_skip_confirm = Frame::left_aligned( - TR::backup__title_skip.into(), - SwipeContent::new(PromptScreen::new_tap_to_cancel()), - ) - .with_cancel_button() - .with_footer(TR::instructions__tap_to_confirm.into(), None) - .with_swipe(Direction::Down, SwipeSettings::default()) - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| match msg { - FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), - FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - _ => None, - }); + let content_menu = Frame::left_aligned( + "".into(), + VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::backup__title_skip.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(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + FrameMsg::Button(_) => None, + }); - let res = SwipeFlow::new(&PromptBackup::Intro)? - .with_page(&PromptBackup::Intro, content_intro)? - .with_page(&PromptBackup::Menu, content_menu)? - .with_page(&PromptBackup::SkipBackupIntro, content_skip_intro)? - .with_page(&PromptBackup::SkipBackupConfirm, content_skip_confirm)?; - Ok(LayoutObj::new(res)?.into()) - } + let paragraphs_skip_intro = ParagraphVecShort::from_iter([ + Paragraph::new(&theme::TEXT_WARNING, TR::words__not_recommended), + Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::backup__create_backup_to_prevent_loss, + ), + ]) + .into_paragraphs(); + let content_skip_intro = Frame::left_aligned( + TR::backup__title_skip.into(), + SwipeContent::new(paragraphs_skip_intro), + ) + .with_cancel_button() + .with_footer( + TR::instructions__swipe_up.into(), + Some(TR::words__continue_anyway.into()), + ) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + _ => None, + }); + + let content_skip_confirm = Frame::left_aligned( + TR::backup__title_skip.into(), + SwipeContent::new(PromptScreen::new_tap_to_cancel()), + ) + .with_cancel_button() + .with_footer(TR::instructions__tap_to_confirm.into(), None) + .with_swipe(Direction::Down, SwipeSettings::default()) + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), + FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + _ => None, + }); + + let res = SwipeFlow::new(&PromptBackup::Intro)? + .with_page(&PromptBackup::Intro, content_intro)? + .with_page(&PromptBackup::Menu, content_menu)? + .with_page(&PromptBackup::SkipBackupIntro, content_skip_intro)? + .with_page(&PromptBackup::SkipBackupConfirm, content_skip_confirm)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/request_number.rs b/core/embed/rust/src/ui/model_mercury/flow/request_number.rs index b12b3dd93af..6a01b1fcdc6 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/request_number.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/request_number.rs @@ -1,6 +1,5 @@ use crate::{ error, - micropython::{map::Map, obj::Obj, qstr::Qstr, util}, strutil::TString, translations::TR, ui::{ @@ -11,7 +10,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -61,77 +59,68 @@ impl FlowController for RequestNumber { static NUM_DISPLAYED: AtomicU16 = AtomicU16::new(0); -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestNumber::new_obj) } -} +pub fn new_request_number( + title: TString<'static>, + count: u32, + min_count: u32, + max_count: u32, + description: TString<'static>, + info_closure: impl Fn(u32) -> TString<'static> + 'static, // FIXME: lifetime + br_code: u16, + br_name: TString<'static>, +) -> Result +{ + NUM_DISPLAYED.store(count as u16, Ordering::Relaxed); -impl RequestNumber { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?; - let min_count: u32 = kwargs.get(Qstr::MP_QSTR_min_count)?.try_into()?; - let max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?; - let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; - let info: Obj = kwargs.get(Qstr::MP_QSTR_info)?; - assert!(info != Obj::const_none()); - let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; - let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; + // wrap the closure for obtaining MoreInfo text and call it with NUM_DISPLAYED + let info_closure = move || { + let curr_number = NUM_DISPLAYED.load(Ordering::Relaxed); + info_closure(curr_number as u32) + }; - NUM_DISPLAYED.store(count as u16, Ordering::Relaxed); - let info_cb = move || { - let curr_number = NUM_DISPLAYED.load(Ordering::Relaxed) as u32; - let text = info - .call_with_n_args(&[curr_number.try_into().unwrap()]) - .unwrap(); - TString::try_from(text).unwrap() - }; + let number_input_dialog = NumberInputDialog::new(min_count, max_count, count, description)?; + let content_number_input = Frame::left_aligned(title, SwipeContent::new(number_input_dialog)) + .with_menu_button() + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Left, SwipeSettings::default()) + .map(|msg| match msg { + FrameMsg::Button(_) => Some(FlowMsg::Info), + FrameMsg::Content(NumberInputDialogMsg::Changed(n)) => { + NUM_DISPLAYED.store(n as u16, Ordering::Relaxed); + None + } + FrameMsg::Content(NumberInputDialogMsg::Confirmed(n)) => { + NUM_DISPLAYED.store(n as u16, Ordering::Relaxed); + Some(FlowMsg::Choice(n as usize)) + } + }) + .one_button_request(ButtonRequest::from_num(br_code, br_name)); - let number_input_dialog = NumberInputDialog::new(min_count, max_count, count, description)?; - let content_number_input = - Frame::left_aligned(title, SwipeContent::new(number_input_dialog)) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .map(|msg| match msg { - FrameMsg::Button(_) => Some(FlowMsg::Info), - FrameMsg::Content(NumberInputDialogMsg::Changed(n)) => { - NUM_DISPLAYED.store(n as u16, Ordering::Relaxed); - None - } - FrameMsg::Content(NumberInputDialogMsg::Confirmed(n)) => { - NUM_DISPLAYED.store(n as u16, Ordering::Relaxed); - Some(FlowMsg::Choice(n as usize)) - } - }) - .one_button_request(ButtonRequest::from_num(br_code, br_name)); + let content_menu = Frame::left_aligned( + TString::empty(), + VerticalMenu::empty().item(theme::ICON_CHEVRON_RIGHT, TR::buttons__more_info.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(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), + FrameMsg::Button(_) => None, + }); - let content_menu = Frame::left_aligned( - TString::empty(), - VerticalMenu::empty().item(theme::ICON_CHEVRON_RIGHT, TR::buttons__more_info.into()), - ) + let updatable_info = UpdatableMoreInfo::new(info_closure); + let content_info = Frame::left_aligned(TString::empty(), SwipeContent::new(updatable_info)) .with_cancel_button() .with_swipe(Direction::Right, SwipeSettings::immediate()) .map(|msg| match msg { - FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)), FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - FrameMsg::Button(_) => None, + _ => None, }); - let updatable_info = UpdatableMoreInfo::new(info_cb); - let content_info = Frame::left_aligned(TString::empty(), SwipeContent::new(updatable_info)) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| match msg { - FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled), - _ => None, - }); - - let res = SwipeFlow::new(&RequestNumber::Number)? - .with_page(&RequestNumber::Number, content_number_input)? - .with_page(&RequestNumber::Menu, content_menu)? - .with_page(&RequestNumber::Info, content_info)?; - Ok(LayoutObj::new(res)?.into()) - } + let res = SwipeFlow::new(&RequestNumber::Number)? + .with_page(&RequestNumber::Number, content_number_input)? + .with_page(&RequestNumber::Menu, content_menu)? + .with_page(&RequestNumber::Info, content_info)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/request_passphrase.rs b/core/embed/rust/src/ui/model_mercury/flow/request_passphrase.rs index 7a01f0a0e3e..99eb358bd55 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/request_passphrase.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/request_passphrase.rs @@ -1,7 +1,6 @@ use crate::{ error, - micropython::{map::Map, obj::Obj, qstr::Qstr, util}, - strutil::{ShortString, TString}, + strutil::ShortString, translations::TR, ui::{ component::ComponentExt, @@ -10,7 +9,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -53,34 +51,24 @@ impl FlowController for RequestPassphrase { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestPassphrase::new_obj) } -} - -impl RequestPassphrase { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; - let _max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?; +pub fn new_request_passphrase() -> Result { + let content_confirm_empty = Frame::left_aligned( + TR::passphrase__continue_with_empty_passphrase.into(), + PromptScreen::new_yes_or_no(), + ) + .map(|msg| match msg { + FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), + FrameMsg::Content(PromptMsg::Cancelled) => Some(FlowMsg::Cancelled), + _ => None, + }); - let content_confirm_empty = Frame::left_aligned( - TR::passphrase__continue_with_empty_passphrase.into(), - PromptScreen::new_yes_or_no(), - ) - .map(|msg| match msg { - FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed), - FrameMsg::Content(PromptMsg::Cancelled) => Some(FlowMsg::Cancelled), - _ => None, - }); + let content_keypad = PassphraseKeyboard::new().map(|msg| match msg { + PassphraseKeyboardMsg::Confirmed(s) => Some(FlowMsg::Text(s)), + PassphraseKeyboardMsg::Cancelled => Some(FlowMsg::Cancelled), + }); - let content_keypad = PassphraseKeyboard::new().map(|msg| match msg { - PassphraseKeyboardMsg::Confirmed(s) => Some(FlowMsg::Text(s)), - PassphraseKeyboardMsg::Cancelled => Some(FlowMsg::Cancelled), - }); - - let res = SwipeFlow::new(&RequestPassphrase::Keypad)? - .with_page(&RequestPassphrase::Keypad, content_keypad)? - .with_page(&RequestPassphrase::ConfirmEmpty, content_confirm_empty)?; - Ok(LayoutObj::new(res)?.into()) - } + let res = SwipeFlow::new(&RequestPassphrase::Keypad)? + .with_page(&RequestPassphrase::Keypad, content_keypad)? + .with_page(&RequestPassphrase::ConfirmEmpty, content_confirm_empty)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/set_brightness.rs b/core/embed/rust/src/ui/model_mercury/flow/set_brightness.rs index c194dcd95e4..8461eaa078a 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/set_brightness.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/set_brightness.rs @@ -2,7 +2,6 @@ use core::sync::atomic::{AtomicU8, Ordering}; use crate::{ error::Error, - micropython::{map::Map, obj::Obj, qstr::Qstr, util}, storage, translations::TR, trezorhal::display, @@ -13,7 +12,6 @@ use crate::{ FlowController, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -66,79 +64,71 @@ impl FlowController for SetBrightness { static BRIGHTNESS: AtomicU8 = AtomicU8::new(0); -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_set_brightness(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetBrightness::new_obj) } -} - -impl SetBrightness { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let current: Option = kwargs.get(Qstr::MP_QSTR_current)?.try_into_option()?; - let content_slider = Frame::left_aligned( - TR::brightness__title.into(), - NumberInputSliderDialog::new( - theme::backlight::get_backlight_min() as u16, - theme::backlight::get_backlight_max() as u16, - current.unwrap_or(theme::backlight::get_backlight_normal()) as u16, - ), - ) - .with_subtitle(TR::homescreen__settings_subtitle.into()) - .with_menu_button() - .with_swipe(Direction::Up, SwipeSettings::default()) - .map(|msg| match msg { - FrameMsg::Content(NumberInputSliderDialogMsg::Changed(n)) => { - display::backlight(n as _); - BRIGHTNESS.store(n as u8, Ordering::Relaxed); - None - } - FrameMsg::Button(_) => Some(FlowMsg::Info), - }); +pub fn new_set_brightness(brightness: u8) -> Result { + let content_slider = Frame::left_aligned( + TR::brightness__title.into(), + NumberInputSliderDialog::new( + theme::backlight::get_backlight_min() as u16, + theme::backlight::get_backlight_max() as u16, + brightness as u16, + ), + ) + .with_subtitle(TR::homescreen__settings_subtitle.into()) + .with_menu_button() + .with_swipe(Direction::Up, SwipeSettings::default()) + .map(|msg| match msg { + FrameMsg::Content(NumberInputSliderDialogMsg::Changed(n)) => { + display::backlight(n as _); + BRIGHTNESS.store(n as u8, Ordering::Relaxed); + None + } + FrameMsg::Button(_) => Some(FlowMsg::Info), + }); - let content_menu = Frame::left_aligned( - "".into(), - VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()), - ) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(move |msg| match msg { - FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)), - FrameMsg::Button(_) => Some(FlowMsg::Cancelled), - }); + let content_menu = Frame::left_aligned( + "".into(), + VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()), + ) + .with_cancel_button() + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(move |msg| match msg { + FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)), + FrameMsg::Button(_) => Some(FlowMsg::Cancelled), + }); - let content_confirm = Frame::left_aligned( - TR::brightness__change_title.into(), - SwipeContent::new(PromptScreen::new_tap_to_confirm()), - ) - .with_footer(TR::instructions__tap_to_confirm.into(), None) - .with_menu_button() - .with_swipe(Direction::Down, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .map(move |msg| match msg { - FrameMsg::Content(PromptMsg::Confirmed) => { - let _ = storage::set_brightness(BRIGHTNESS.load(Ordering::Relaxed)); - Some(FlowMsg::Confirmed) - } - FrameMsg::Button(_) => Some(FlowMsg::Info), - _ => None, - }); + let content_confirm = Frame::left_aligned( + TR::brightness__change_title.into(), + SwipeContent::new(PromptScreen::new_tap_to_confirm()), + ) + .with_footer(TR::instructions__tap_to_confirm.into(), None) + .with_menu_button() + .with_swipe(Direction::Down, SwipeSettings::default()) + .with_swipe(Direction::Left, SwipeSettings::default()) + .map(move |msg| match msg { + FrameMsg::Content(PromptMsg::Confirmed) => { + let _ = storage::set_brightness(BRIGHTNESS.load(Ordering::Relaxed)); + Some(FlowMsg::Confirmed) + } + FrameMsg::Button(_) => Some(FlowMsg::Info), + _ => None, + }); - let content_confirmed = Frame::left_aligned( - TR::words__title_success.into(), - SwipeContent::new(StatusScreen::new_success( - TR::brightness__changed_title.into(), - )) - .with_no_attach_anim(), - ) - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .map(move |_msg| Some(FlowMsg::Confirmed)); + let content_confirmed = Frame::left_aligned( + TR::words__title_success.into(), + SwipeContent::new(StatusScreen::new_success( + TR::brightness__changed_title.into(), + )) + .with_no_attach_anim(), + ) + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe(Direction::Up, SwipeSettings::default()) + .map(move |_msg| Some(FlowMsg::Confirmed)); - let res = SwipeFlow::new(&SetBrightness::Slider)? - .with_page(&SetBrightness::Slider, content_slider)? - .with_page(&SetBrightness::Menu, content_menu)? - .with_page(&SetBrightness::Confirm, content_confirm)? - .with_page(&SetBrightness::Confirmed, content_confirmed)?; + let res = SwipeFlow::new(&SetBrightness::Slider)? + .with_page(&SetBrightness::Slider, content_slider)? + .with_page(&SetBrightness::Menu, content_menu)? + .with_page(&SetBrightness::Confirm, content_confirm)? + .with_page(&SetBrightness::Confirmed, content_confirmed)?; - Ok(LayoutObj::new(res)?.into()) - } + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/show_share_words.rs b/core/embed/rust/src/ui/model_mercury/flow/show_share_words.rs index e23010c38df..76203de9c60 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/show_share_words.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/show_share_words.rs @@ -1,13 +1,12 @@ use crate::{ error, - micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util}, strutil::TString, translations::TR, ui::{ button_request::ButtonRequestCode, component::{ swipe_detect::SwipeSettings, - text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt}, + text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs}, ButtonRequestExt, ComponentExt, EventCtx, }, flow::{ @@ -15,7 +14,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, model_mercury::component::{InternallySwipable, InternallySwipableContent, SwipeContent}, }, }; @@ -61,11 +59,6 @@ impl FlowController for ShowShareWords { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ShowShareWords::new_obj) } -} - fn header_updating_func( content: &InternallySwipableContent, ctx: &mut EventCtx, @@ -84,82 +77,72 @@ fn footer_updating_func( footer.update_page_counter(ctx, current_page, Some(total_pages)); } -impl ShowShareWords { - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let subtitle: TString = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into()?; - let share_words_obj: Obj = kwargs.get(Qstr::MP_QSTR_words)?; - let share_words_vec: Vec = util::iter_into_vec(share_words_obj)?; - let description: Option = kwargs - .get(Qstr::MP_QSTR_description)? - .try_into_option()? - .and_then(|desc: TString| if desc.is_empty() { None } else { Some(desc) }); - let text_info: Obj = kwargs.get(Qstr::MP_QSTR_text_info)?; - let text_confirm: TString = kwargs.get(Qstr::MP_QSTR_text_confirm)?.try_into()?; - let nwords = share_words_vec.len(); +pub fn new_show_share_words( + title: TString<'static>, + subtitle: TString<'static>, + share_words_vec: Vec, 33>, + description: Option>, + instructions_paragraphs: ParagraphVecShort<'static>, + text_confirm: TString<'static>, +) -> Result { + let nwords = share_words_vec.len(); + let paragraphs_spacing = 8; - let mut instructions_paragraphs = ParagraphVecShort::new(); - for item in IterBuf::new().try_iterate(text_info)? { - let text: TString = item.try_into()?; - instructions_paragraphs.add(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text)); - } - let paragraphs_spacing = 8; - let content_instruction = Frame::left_aligned( - title, - SwipeContent::new( - instructions_paragraphs - .into_paragraphs() - .with_spacing(paragraphs_spacing), - ), - ) - .with_subtitle(TR::words__instructions.into()) - .with_footer(TR::instructions__swipe_up.into(), description) - .with_swipe(Direction::Up, SwipeSettings::default()) - .map(|msg| matches!(msg, FrameMsg::Content(_)).then_some(FlowMsg::Confirmed)) - .one_button_request(ButtonRequestCode::ResetDevice.with_name("share_words")) - .with_pages(move |_| nwords + 2); + let content_instruction = Frame::left_aligned( + title, + SwipeContent::new( + instructions_paragraphs + .into_paragraphs() + .with_spacing(paragraphs_spacing), + ), + ) + .with_subtitle(TR::words__instructions.into()) + .with_footer(TR::instructions__swipe_up.into(), description) + .with_swipe(Direction::Up, SwipeSettings::default()) + .map(|msg| matches!(msg, FrameMsg::Content(_)).then_some(FlowMsg::Confirmed)) + .one_button_request(ButtonRequestCode::ResetDevice.with_name("share_words")) + .with_pages(move |_| nwords + 2); - let n_words = share_words_vec.len(); - let content_words = Frame::left_aligned( - title, - InternallySwipableContent::new(ShareWords::new(share_words_vec, subtitle)), - ) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Down, SwipeSettings::default()) - .with_vertical_pages() - .with_subtitle(subtitle) - .register_header_update_fn(header_updating_func) - .with_footer_counter(TR::instructions__swipe_up.into(), n_words as u8) - .register_footer_update_fn(footer_updating_func) - .map(|_| None); + let n_words = share_words_vec.len(); + let content_words = Frame::left_aligned( + title, + InternallySwipableContent::new(ShareWords::new(share_words_vec, subtitle)), + ) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Down, SwipeSettings::default()) + .with_vertical_pages() + .with_subtitle(subtitle) + .register_header_update_fn(header_updating_func) + .with_footer_counter(TR::instructions__swipe_up.into(), n_words as u8) + .register_footer_update_fn(footer_updating_func) + .map(|_| None); - let content_confirm = Frame::left_aligned( - text_confirm, - SwipeContent::new(PromptScreen::new_hold_to_confirm()), - ) - .with_footer(TR::instructions__hold_to_confirm.into(), None) - .with_swipe(Direction::Down, SwipeSettings::default()) - .map(|_| Some(FlowMsg::Confirmed)); + let content_confirm = Frame::left_aligned( + text_confirm, + SwipeContent::new(PromptScreen::new_hold_to_confirm()), + ) + .with_footer(TR::instructions__hold_to_confirm.into(), None) + .with_swipe(Direction::Down, SwipeSettings::default()) + .map(|_| Some(FlowMsg::Confirmed)); - let content_check_backup_intro = Frame::left_aligned( - TR::reset__check_wallet_backup_title.into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::reset__check_backup_instructions, - ))), - ) - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .map(|_| Some(FlowMsg::Confirmed)); + let content_check_backup_intro = Frame::left_aligned( + TR::reset__check_wallet_backup_title.into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::reset__check_backup_instructions, + ))), + ) + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe(Direction::Up, SwipeSettings::default()) + .map(|_| Some(FlowMsg::Confirmed)); - let res = SwipeFlow::new(&ShowShareWords::Instruction)? - .with_page(&ShowShareWords::Instruction, content_instruction)? - .with_page(&ShowShareWords::Words, content_words)? - .with_page(&ShowShareWords::Confirm, content_confirm)? - .with_page( - &ShowShareWords::CheckBackupIntro, - content_check_backup_intro, - )?; - Ok(LayoutObj::new(res)?.into()) - } + let res = SwipeFlow::new(&ShowShareWords::Instruction)? + .with_page(&ShowShareWords::Instruction, content_instruction)? + .with_page(&ShowShareWords::Words, content_words)? + .with_page(&ShowShareWords::Confirm, content_confirm)? + .with_page( + &ShowShareWords::CheckBackupIntro, + content_check_backup_intro, + )?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/show_tutorial.rs b/core/embed/rust/src/ui/model_mercury/flow/show_tutorial.rs index 8e9c9f722af..1d4f61f60f7 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/show_tutorial.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/show_tutorial.rs @@ -1,6 +1,5 @@ use crate::{ error, - micropython::{map::Map, obj::Obj, util}, translations::TR, ui::{ component::{ @@ -13,7 +12,6 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, }, }; @@ -75,133 +73,126 @@ impl FlowController for ShowTutorial { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_show_tutorial(_n_args: usize, _args: *const Obj, _kwargs: *mut Map) -> Obj { - unsafe { util::try_or_raise(ShowTutorial::new_obj) } -} - -impl ShowTutorial { - fn new_obj() -> Result { - let content_step_welcome = Frame::left_aligned( - TR::tutorial__welcome_safe5.into(), - SwipeContent::new(PromptScreen::new_tap_to_start()), - ) - .with_footer(TR::instructions__tap_to_start.into(), None) - .map(|msg| { - matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed) - }); - - let content_step_begin = Frame::left_aligned( - TR::tutorial__title_lets_begin.into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::tutorial__lets_begin, - ))), - ) - .with_footer( - TR::instructions__swipe_up.into(), - Some(TR::tutorial__get_started.into()), - ) - .with_swipe(Direction::Up, SwipeSettings::default()) - .map(|_| None); - - let content_step_navigation = Frame::left_aligned( - TR::tutorial__title_easy_navigation.into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::tutorial__swipe_up_and_down, - ))), - ) - .with_footer( - TR::instructions__swipe_up.into(), - Some(TR::tutorial__continue.into()), - ) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Down, SwipeSettings::default()) - .map(|_| None); - - let content_step_menu = Frame::left_aligned( - TR::tutorial__title_handy_menu.into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::tutorial__menu, - ))), - ) - .with_menu_button() - .button_styled(theme::button_warning_low()) - .with_footer( - TR::instructions__swipe_up.into(), - Some(TR::buttons__continue.into()), - ) - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Down, SwipeSettings::default()) - .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)); - - let content_step_hold = Frame::left_aligned( - TR::tutorial__title_hold.into(), - SwipeContent::new(PromptScreen::new_hold_to_confirm()), - ) - .with_footer(TR::instructions__hold_to_exit_tutorial.into(), None) - .map(|msg| { - matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed) - }); - - let content_step_done = Frame::left_aligned( - TR::tutorial__title_well_done.into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::tutorial__ready_to_use_safe5, - ))), - ) - .with_footer(TR::instructions__swipe_up.into(), None) - .with_swipe(Direction::Up, SwipeSettings::default()) - .map(|_| None); - - let content_menu = Frame::left_aligned( - "".into(), - VerticalMenu::empty() - .item(theme::ICON_CHEVRON_RIGHT, TR::tutorial__did_you_know.into()) - .item(theme::ICON_REBOOT, TR::tutorial__restart_tutorial.into()) - .danger(theme::ICON_CANCEL, TR::tutorial__exit.into()), - ) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .with_swipe(Direction::Left, SwipeSettings::immediate()) - .map(|msg| match msg { - FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)), - FrameMsg::Button(_) => Some(FlowMsg::Cancelled), - }); - - let content_did_you_know = Frame::left_aligned( - "".into(), - SwipeContent::new(Paragraphs::new(Paragraph::new( - &theme::TEXT_MAIN_GREY_LIGHT, - TR::tutorial__first_wallet, - ))), - ) - .with_cancel_button() - .with_swipe(Direction::Right, SwipeSettings::immediate()) - .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Cancelled)); - - let content_hold_to_exit = Frame::left_aligned( - TR::tutorial__title_hold.into(), - SwipeContent::new(PromptScreen::new_hold_to_confirm_danger()), - ) - .with_footer(TR::instructions__hold_to_exit_tutorial.into(), None) - .map(|msg| { - matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed) - }); - - let res = SwipeFlow::new(&ShowTutorial::StepWelcome)? - .with_page(&ShowTutorial::StepWelcome, content_step_welcome)? - .with_page(&ShowTutorial::StepBegin, content_step_begin)? - .with_page(&ShowTutorial::StepNavigation, content_step_navigation)? - .with_page(&ShowTutorial::StepMenu, content_step_menu)? - .with_page(&ShowTutorial::StepHold, content_step_hold)? - .with_page(&ShowTutorial::StepDone, content_step_done)? - .with_page(&ShowTutorial::Menu, content_menu)? - .with_page(&ShowTutorial::DidYouKnow, content_did_you_know)? - .with_page(&ShowTutorial::HoldToExit, content_hold_to_exit)?; - Ok(LayoutObj::new(res)?.into()) - } +pub fn new_show_tutorial() -> Result { + let content_step_welcome = Frame::left_aligned( + TR::tutorial__welcome_safe5.into(), + SwipeContent::new(PromptScreen::new_tap_to_start()), + ) + .with_footer(TR::instructions__tap_to_start.into(), None) + .map(|msg| { + matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed) + }); + + let content_step_begin = Frame::left_aligned( + TR::tutorial__title_lets_begin.into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::tutorial__lets_begin, + ))), + ) + .with_footer( + TR::instructions__swipe_up.into(), + Some(TR::tutorial__get_started.into()), + ) + .with_swipe(Direction::Up, SwipeSettings::default()) + .map(|_| None); + + let content_step_navigation = Frame::left_aligned( + TR::tutorial__title_easy_navigation.into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::tutorial__swipe_up_and_down, + ))), + ) + .with_footer( + TR::instructions__swipe_up.into(), + Some(TR::tutorial__continue.into()), + ) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Down, SwipeSettings::default()) + .map(|_| None); + + let content_step_menu = Frame::left_aligned( + TR::tutorial__title_handy_menu.into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::tutorial__menu, + ))), + ) + .with_menu_button() + .button_styled(theme::button_warning_low()) + .with_footer( + TR::instructions__swipe_up.into(), + Some(TR::buttons__continue.into()), + ) + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Down, SwipeSettings::default()) + .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)); + + let content_step_hold = Frame::left_aligned( + TR::tutorial__title_hold.into(), + SwipeContent::new(PromptScreen::new_hold_to_confirm()), + ) + .with_footer(TR::instructions__hold_to_exit_tutorial.into(), None) + .map(|msg| { + matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed) + }); + + let content_step_done = Frame::left_aligned( + TR::tutorial__title_well_done.into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::tutorial__ready_to_use_safe5, + ))), + ) + .with_footer(TR::instructions__swipe_up.into(), None) + .with_swipe(Direction::Up, SwipeSettings::default()) + .map(|_| None); + + let content_menu = Frame::left_aligned( + "".into(), + VerticalMenu::empty() + .item(theme::ICON_CHEVRON_RIGHT, TR::tutorial__did_you_know.into()) + .item(theme::ICON_REBOOT, TR::tutorial__restart_tutorial.into()) + .danger(theme::ICON_CANCEL, TR::tutorial__exit.into()), + ) + .with_cancel_button() + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .with_swipe(Direction::Left, SwipeSettings::immediate()) + .map(|msg| match msg { + FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)), + FrameMsg::Button(_) => Some(FlowMsg::Cancelled), + }); + + let content_did_you_know = Frame::left_aligned( + "".into(), + SwipeContent::new(Paragraphs::new(Paragraph::new( + &theme::TEXT_MAIN_GREY_LIGHT, + TR::tutorial__first_wallet, + ))), + ) + .with_cancel_button() + .with_swipe(Direction::Right, SwipeSettings::immediate()) + .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Cancelled)); + + let content_hold_to_exit = Frame::left_aligned( + TR::tutorial__title_hold.into(), + SwipeContent::new(PromptScreen::new_hold_to_confirm_danger()), + ) + .with_footer(TR::instructions__hold_to_exit_tutorial.into(), None) + .map(|msg| { + matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed) + }); + + let res = SwipeFlow::new(&ShowTutorial::StepWelcome)? + .with_page(&ShowTutorial::StepWelcome, content_step_welcome)? + .with_page(&ShowTutorial::StepBegin, content_step_begin)? + .with_page(&ShowTutorial::StepNavigation, content_step_navigation)? + .with_page(&ShowTutorial::StepMenu, content_step_menu)? + .with_page(&ShowTutorial::StepHold, content_step_hold)? + .with_page(&ShowTutorial::StepDone, content_step_done)? + .with_page(&ShowTutorial::Menu, content_menu)? + .with_page(&ShowTutorial::DidYouKnow, content_did_you_know)? + .with_page(&ShowTutorial::HoldToExit, content_hold_to_exit)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/flow/warning_hi_prio.rs b/core/embed/rust/src/ui/model_mercury/flow/warning_hi_prio.rs index fd357c0748a..99dce03f506 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/warning_hi_prio.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/warning_hi_prio.rs @@ -1,6 +1,5 @@ use crate::{ error, - micropython::{map::Map, obj::Obj, qstr::Qstr, util}, strutil::TString, translations::TR, ui::{ @@ -14,13 +13,11 @@ use crate::{ FlowController, FlowMsg, SwipeFlow, }, geometry::Direction, - layout::obj::LayoutObj, - model_mercury::component::SwipeContent, }, }; use super::super::{ - component::{Frame, FrameMsg, StatusScreen, VerticalMenu, VerticalMenuChoiceMsg}, + component::{Frame, FrameMsg, StatusScreen, SwipeContent, VerticalMenu, VerticalMenuChoiceMsg}, theme, }; @@ -58,65 +55,58 @@ impl FlowController for WarningHiPrio { } } -#[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn new_warning_hi_prio(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { - unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, WarningHiPrio::new_obj) } -} - -impl WarningHiPrio { - const EXTRA_PADDING: i16 = 6; +const EXTRA_PADDING: i16 = 6; - fn new_obj(_args: &[Obj], kwargs: &Map) -> Result { - let title: TString = kwargs.get_or(Qstr::MP_QSTR_title, TR::words__warning.into())?; - let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; - let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?; - let cancel: TString = TR::words__cancel_and_exit.into(); - let confirm: TString = "Continue anyway".into(); // FIXME: en.json has punctuation - let done_title: TString = "Operation cancelled".into(); +pub fn new_warning_hi_prio( + title: TString<'static>, + description: TString<'static>, + value: TString<'static>, +) -> Result { + let cancel: TString = TR::words__cancel_and_exit.into(); + let confirm: TString = "Continue anyway".into(); // FIXME: en.json has punctuation + let done_title: TString = "Operation cancelled".into(); - // Message - let paragraphs = [ - Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description), - Paragraph::new(&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, value) - .with_top_padding(Self::EXTRA_PADDING), - ] - .into_paragraphs(); - let content_message = Frame::left_aligned(title, SwipeContent::new(paragraphs)) - .with_menu_button() - .with_footer(TR::instructions__swipe_up.into(), Some(cancel)) - .with_danger() - .with_swipe(Direction::Up, SwipeSettings::default()) - .with_swipe(Direction::Left, SwipeSettings::default()) - .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)); - // .one_button_request(ButtonRequestCode::Warning, br_name); + // Message + let paragraphs = [ + Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description), + Paragraph::new(&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, value).with_top_padding(EXTRA_PADDING), + ] + .into_paragraphs(); + let content_message = Frame::left_aligned(title, SwipeContent::new(paragraphs)) + .with_menu_button() + .with_footer(TR::instructions__swipe_up.into(), Some(cancel)) + .with_danger() + .with_swipe(Direction::Up, SwipeSettings::default()) + .with_swipe(Direction::Left, SwipeSettings::default()) + .map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info)); + // .one_button_request(ButtonRequestCode::Warning, br_name); - // Menu - let content_menu = Frame::left_aligned( - "".into(), - VerticalMenu::empty() - .item(theme::ICON_CANCEL, "Cancel".into()) // TODO: button__cancel after it's lowercase - .danger(theme::ICON_CHEVRON_RIGHT, confirm), - ) - .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), - }); + // Menu + let content_menu = Frame::left_aligned( + "".into(), + VerticalMenu::empty() + .item(theme::ICON_CANCEL, "Cancel".into()) // TODO: button__cancel after it's lowercase + .danger(theme::ICON_CHEVRON_RIGHT, confirm), + ) + .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), + }); - // Cancelled - let content_cancelled = Frame::left_aligned( - TR::words__title_done.into(), - StatusScreen::new_neutral_timeout(done_title), - ) - .with_footer(TR::instructions__continue_in_app.into(), None) - .with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREY_DARK) - .map(|_| Some(FlowMsg::Cancelled)); + // Cancelled + let content_cancelled = Frame::left_aligned( + TR::words__title_done.into(), + StatusScreen::new_neutral_timeout(done_title), + ) + .with_footer(TR::instructions__continue_in_app.into(), None) + .with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREY_DARK) + .map(|_| Some(FlowMsg::Cancelled)); - let res = SwipeFlow::new(&WarningHiPrio::Message)? - .with_page(&WarningHiPrio::Message, content_message)? - .with_page(&WarningHiPrio::Menu, content_menu)? - .with_page(&WarningHiPrio::Cancelled, content_cancelled)?; - Ok(LayoutObj::new(res)?.into()) - } + let res = SwipeFlow::new(&WarningHiPrio::Message)? + .with_page(&WarningHiPrio::Message, content_message)? + .with_page(&WarningHiPrio::Menu, content_menu)? + .with_page(&WarningHiPrio::Cancelled, content_cancelled)?; + Ok(res) } diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index a881619bbe1..8394de5019f 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -1,4 +1,5 @@ use core::{cmp::Ordering, convert::TryInto}; +use heapless::Vec; use super::{ component::{ @@ -14,7 +15,7 @@ use crate::{ io::BinaryData, micropython::{ iter::IterBuf, - macros::{obj_fn_1, obj_fn_kw, obj_module}, + macros::{obj_fn_0, obj_fn_1, obj_fn_kw, obj_module}, map::Map, module::Module, obj::Obj, @@ -247,6 +248,8 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m false, false, ) + .and_then(LayoutObj::new) + .map(Into::into) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } @@ -287,6 +290,36 @@ 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_action(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 action: Option = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?; + let description: Option = + kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; + let subtitle: Option = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?; + let verb_cancel: Option = + kwargs.get(Qstr::MP_QSTR_verb_cancel)?.try_into_option()?; + let reverse: bool = kwargs.get_or(Qstr::MP_QSTR_reverse, false)?; + let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?; + let prompt_screen: bool = kwargs.get_or(Qstr::MP_QSTR_prompt_screen, false)?; + let prompt_title: TString = kwargs.get_or(Qstr::MP_QSTR_prompt_title, title.clone())?; + + let flow = flow::confirm_action::new_confirm_action( + title, + action, + description, + subtitle, + verb_cancel, + reverse, + hold, + prompt_screen, + prompt_title, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} 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()?; @@ -314,6 +347,25 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut .into_paragraphs(); flow::new_confirm_action_simple(paragraphs, title, None, None, None, false, false) + .and_then(LayoutObj::new) + .map(Into::into) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_confirm_firmware_update( + 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()?; + let fingerprint: TString = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?; + + let flow = + flow::confirm_firmware_update::new_confirm_firmware_update(description, fingerprint)?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } @@ -340,6 +392,8 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m hold, false, ) + .and_then(LayoutObj::new) + .map(Into::into) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } @@ -369,6 +423,8 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m false, false, ) + .and_then(LayoutObj::new) + .map(Into::into) } else { if !check_homescreen_format(jpeg) { return Err(value_error!(c"Invalid image.")); @@ -391,6 +447,128 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_confirm_reset(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let recovery: bool = kwargs.get(Qstr::MP_QSTR_recovery)?.try_into()?; + + let flow = flow::confirm_reset::new_confirm_reset(recovery)?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_confirm_set_new_pin(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 = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; + + let flow = flow::confirm_set_new_pin::new_set_new_pin(title, description)?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_confirm_output(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()?; + let subtitle: Option = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?; + + let account: Option = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?; + let account_path: Option = + kwargs.get(Qstr::MP_QSTR_account_path)?.try_into_option()?; + + let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; + let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; + + let message: Obj = kwargs.get(Qstr::MP_QSTR_message)?; + let amount: Option = kwargs.get(Qstr::MP_QSTR_amount)?.try_into_option()?; + + 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 address: Option = kwargs.get(Qstr::MP_QSTR_address)?.try_into_option()?; + let address_title: Option = + kwargs.get(Qstr::MP_QSTR_address_title)?.try_into_option()?; + + let summary_items: Obj = kwargs.get(Qstr::MP_QSTR_summary_items)?; + let fee_items: Obj = kwargs.get(Qstr::MP_QSTR_fee_items)?; + + let summary_title: Option = + kwargs.get(Qstr::MP_QSTR_summary_title)?.try_into_option()?; + let summary_br_name: Option = kwargs + .get(Qstr::MP_QSTR_summary_br_name)? + .try_into_option()?; + let summary_br_code: Option = kwargs + .get(Qstr::MP_QSTR_summary_br_code)? + .try_into_option()?; + + let cancel_text: Option = + kwargs.get(Qstr::MP_QSTR_cancel_text)?.try_into_option()?; + + let flow = flow::confirm_output::new_confirm_output( + title, + subtitle, + account, + account_path, + br_name, + br_code, + message, + amount, + chunkify, + text_mono, + address, + address_title, + summary_items, + fee_items, + summary_title, + summary_br_name, + summary_br_code, + cancel_text, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_confirm_summary(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 items: Obj = kwargs.get(Qstr::MP_QSTR_items)?; + let account_items: Obj = kwargs.get(Qstr::MP_QSTR_account_items)?; + let fee_items: Obj = kwargs.get(Qstr::MP_QSTR_fee_items)?; + let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; + let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; + let cancel_text: Option = + kwargs.get(Qstr::MP_QSTR_cancel_text)?.try_into_option()?; + + let flow = flow::confirm_summary::new_confirm_summary( + title, + items, + account_items, + fee_items, + br_name, + br_code, + cancel_text, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_set_brightness(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let current: u8 = kwargs.get(Qstr::MP_QSTR_current)?.try_into()?; + let flow = flow::set_brightness::new_set_brightness(current)?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_show_info_with_cancel(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()?; @@ -482,6 +660,8 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma true, true, ) + .and_then(LayoutObj::new) + .map(Into::into) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } @@ -588,6 +768,39 @@ extern "C" fn new_show_error(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_share_words(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: TString = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into()?; + let share_words_obj: Obj = kwargs.get(Qstr::MP_QSTR_words)?; + let share_words_vec: Vec = util::iter_into_vec(share_words_obj)?; + let description: Option = kwargs + .get(Qstr::MP_QSTR_description)? + .try_into_option()? + .and_then(|desc: TString| if desc.is_empty() { None } else { Some(desc) }); + let text_info: Obj = kwargs.get(Qstr::MP_QSTR_text_info)?; + let text_confirm: TString = kwargs.get(Qstr::MP_QSTR_text_confirm)?.try_into()?; + + let mut instructions_paragraphs = ParagraphVecShort::new(); + for item in IterBuf::new().try_iterate(text_info)? { + let text: TString = item.try_into()?; + instructions_paragraphs.add(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text)); + } + + let flow = flow::show_share_words::new_show_share_words( + title, + subtitle, + share_words_vec, + description, + instructions_paragraphs, + text_confirm, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_show_warning(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()?; @@ -771,6 +984,134 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut true, false, ) + .and_then(LayoutObj::new) + .map(Into::into) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_continue_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let first_screen: bool = kwargs.get(Qstr::MP_QSTR_first_screen)?.try_into()?; + let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?; + let text: TString = kwargs.get(Qstr::MP_QSTR_text)?.try_into()?; // #shares entered + let subtext: Option = kwargs.get(Qstr::MP_QSTR_subtext)?.try_into_option()?; // #shares remaining + let pages: Option = kwargs.get(Qstr::MP_QSTR_pages)?.try_into_option()?; // info about remaining shares + + let pages_vec = if let Some(pages_obj) = pages { + let mut vec = ParagraphVecLong::new(); + for page in IterBuf::new().try_iterate(pages_obj)? { + let [title, description]: [TString; 2] = util::iter_into_array(page)?; + vec.add(Paragraph::new(&theme::TEXT_SUB_GREY, title)) + .add(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, description).break_after()); + } + Some(vec) + } else { + None + }; + + let flow = flow::continue_recovery::new_continue_recovery( + first_screen, + recovery_type, + text, + subtext, + pages_vec, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_get_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 description: Option = + kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; + let extra: Option = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?; + let address: Obj = kwargs.get(Qstr::MP_QSTR_address)?; + let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?; + let address_qr: TString = kwargs.get(Qstr::MP_QSTR_address_qr)?.try_into()?; + let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?; + let account: Option = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?; + let path: Option = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?; + let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?; + let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; + let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; + + let flow = flow::get_address::new_get_address( + title, + description, + extra, + address, + chunkify, + address_qr, + case_sensitive, + account, + path, + xpubs, + br_code, + br_name, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_prompt_backup() -> Obj { + let block = || { + let flow = flow::prompt_backup::new_prompt_backup()?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_or_raise(block) } +} + +extern "C" fn new_request_number(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 count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?; + let min_count: u32 = kwargs.get(Qstr::MP_QSTR_min_count)?.try_into()?; + let max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?; + let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; + let info_cb: Obj = kwargs.get(Qstr::MP_QSTR_info)?; + assert!(info_cb != Obj::const_none()); + let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?; + let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?; + + let mp_info_closure = move |num: u32| { + // TODO: Handle error + let text = info_cb + .call_with_n_args(&[num.try_into().unwrap()]) + .unwrap(); + TString::try_from(text).unwrap() + }; + + let flow = flow::request_number::new_request_number( + title, + count, + min_count, + max_count, + description, + mp_info_closure, + br_code, + br_name, + )?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + +extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], kwargs: &Map| { + let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?; + let _max_len: usize = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?; + + let flow = flow::request_passphrase::new_request_passphrase()?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } @@ -878,6 +1219,15 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_show_tutorial() -> Obj { + let block = || { + let flow = flow::show_tutorial::new_show_tutorial()?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_or_raise(block) } +} + extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?; @@ -1036,6 +1386,19 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map panic!(); } +extern "C" fn new_warning_hi_prio(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 = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; + let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?; + + let flow = flow::warning_hi_prio::new_warning_hi_prio(title, description, value)?; + let obj = LayoutObj::new(flow)?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + #[no_mangle] pub static mp_module_trezorui2: Module = obj_module! { /// from trezor import utils @@ -1149,7 +1512,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// prompt_title: str | None = None, /// ) -> LayoutObj[UiResult]: /// """Confirm action.""" - Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, flow::confirm_action::new_confirm_action).as_obj(), + Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(), /// def confirm_emphasized( /// *, @@ -1209,7 +1572,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// def flow_confirm_reset(recovery: bool) -> LayoutObj[UiResult]: /// """Confirm TOS before creating wallet creation or wallet recovery.""" - Qstr::MP_QSTR_flow_confirm_reset => obj_fn_kw!(0, flow::confirm_reset::new_confirm_reset).as_obj(), + Qstr::MP_QSTR_flow_confirm_reset => obj_fn_kw!(0, new_confirm_reset).as_obj(), // TODO: supply more arguments for Wipe code setting when figma done /// def flow_confirm_set_new_pin( @@ -1218,7 +1581,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// description: str, /// ) -> LayoutObj[UiResult]: /// """Confirm new PIN setup with an option to cancel action.""" - Qstr::MP_QSTR_flow_confirm_set_new_pin => obj_fn_kw!(0, flow::confirm_set_new_pin::new_set_new_pin).as_obj(), + Qstr::MP_QSTR_flow_confirm_set_new_pin => obj_fn_kw!(0, new_confirm_set_new_pin).as_obj(), /// def show_info_with_cancel( /// *, @@ -1393,7 +1756,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// max_len: int, /// ) -> LayoutObj[str | UiResult]: /// """Passphrase input keyboard.""" - Qstr::MP_QSTR_flow_request_passphrase => obj_fn_kw!(0, flow::request_passphrase::new_request_passphrase).as_obj(), + Qstr::MP_QSTR_flow_request_passphrase => obj_fn_kw!(0, new_request_passphrase).as_obj(), /// def request_bip39( /// *, @@ -1425,7 +1788,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// def flow_prompt_backup() -> LayoutObj[UiResult] /// """Prompt a user to create backup with an option to skip.""" - Qstr::MP_QSTR_flow_prompt_backup => obj_fn_kw!(0, flow::prompt_backup::new_prompt_backup).as_obj(), + Qstr::MP_QSTR_flow_prompt_backup => obj_fn_0!(new_prompt_backup).as_obj(), /// def flow_show_share_words( /// *, @@ -1438,7 +1801,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// ) -> LayoutObj[UiResult]: /// """Show wallet backup words preceded by an instruction screen and followed by /// confirmation.""" - Qstr::MP_QSTR_flow_show_share_words => obj_fn_kw!(0, flow::show_share_words::new_show_share_words).as_obj(), + Qstr::MP_QSTR_flow_show_share_words => obj_fn_kw!(0, new_show_share_words).as_obj(), /// def flow_request_number( /// *, @@ -1451,16 +1814,16 @@ pub static mp_module_trezorui2: Module = obj_module! { /// br_code: ButtonRequestType, /// br_name: str, /// ) -> LayoutObj[tuple[UiResult, int]]: - /// """Numer input with + and - buttons, description, and context menu with cancel and + /// """Numebr input with + and - buttons, description, and context menu with cancel and /// info.""" - Qstr::MP_QSTR_flow_request_number => obj_fn_kw!(0, flow::request_number::new_request_number).as_obj(), + Qstr::MP_QSTR_flow_request_number => obj_fn_kw!(0, new_request_number).as_obj(), /// def set_brightness( /// *, /// current: int | None = None /// ) -> LayoutObj[UiResult]: /// """Show the brightness configuration dialog.""" - Qstr::MP_QSTR_set_brightness => obj_fn_kw!(0, flow::set_brightness::new_set_brightness).as_obj(), + Qstr::MP_QSTR_set_brightness => obj_fn_kw!(0, new_set_brightness).as_obj(), /// def show_checklist( /// *, @@ -1482,7 +1845,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// pages: Iterable[tuple[str, str]] | None = None, /// ) -> LayoutObj[UiResult]: /// """Device recovery homescreen.""" - Qstr::MP_QSTR_flow_continue_recovery => obj_fn_kw!(0, flow::continue_recovery::new_continue_recovery).as_obj(), + Qstr::MP_QSTR_flow_continue_recovery => obj_fn_kw!(0, new_continue_recovery).as_obj(), /// def select_word_count( /// *, @@ -1548,11 +1911,11 @@ pub static mp_module_trezorui2: Module = obj_module! { /// fingerprint: str, /// ) -> LayoutObj[UiResult]: /// """Ask whether to update firmware, optionally show fingerprint.""" - Qstr::MP_QSTR_confirm_firmware_update => obj_fn_kw!(0, flow::confirm_firmware_update::new_confirm_firmware_update).as_obj(), + Qstr::MP_QSTR_confirm_firmware_update => obj_fn_kw!(0, new_confirm_firmware_update).as_obj(), /// def tutorial() -> LayoutObj[UiResult]: /// """Show user how to interact with the device.""" - Qstr::MP_QSTR_tutorial => obj_fn_kw!(0, flow::show_tutorial::new_show_tutorial).as_obj(), // FIXME turn this into obj_fn_0, T2B1 as well + Qstr::MP_QSTR_tutorial => obj_fn_0!(new_show_tutorial).as_obj(), /// def show_wait_text(message: str, /) -> LayoutObj[None]: /// """Show single-line text in the middle of the screen.""" @@ -1574,7 +1937,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// br_name: str, /// ) -> LayoutObj[UiResult]: /// """Get address / receive funds.""" - Qstr::MP_QSTR_flow_get_address => obj_fn_kw!(0, flow::get_address::new_get_address).as_obj(), + Qstr::MP_QSTR_flow_get_address => obj_fn_kw!(0, new_get_address).as_obj(), /// def flow_warning_hi_prio( /// *, @@ -1583,7 +1946,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// value: str = "", /// ) -> LayoutObj[UiResult]: /// """Warning modal with multiple steps to confirm.""" - Qstr::MP_QSTR_flow_warning_hi_prio => obj_fn_kw!(0, flow::warning_hi_prio::new_warning_hi_prio).as_obj(), + Qstr::MP_QSTR_flow_warning_hi_prio => obj_fn_kw!(0, new_warning_hi_prio).as_obj(), /// def flow_confirm_output( /// *, @@ -1607,7 +1970,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// 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.""" - Qstr::MP_QSTR_flow_confirm_output => obj_fn_kw!(0, flow::new_confirm_output).as_obj(), + Qstr::MP_QSTR_flow_confirm_output => obj_fn_kw!(0, new_confirm_output).as_obj(), /// def flow_confirm_summary( /// *, @@ -1620,7 +1983,7 @@ pub static mp_module_trezorui2: Module = obj_module! { /// cancel_text: str | None = None, /// ) -> LayoutObj[UiResult]: /// """Total summary and hold to confirm.""" - Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, flow::new_confirm_summary).as_obj(), + Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, new_confirm_summary).as_obj(), /// class BacklightLevels: /// """Backlight levels. Values dynamically update based on user settings."""