mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-02 14:18:59 +00:00
refactor(core/mercury): separate upy args parsing
[no changelog]
This commit is contained in:
parent
12388ed24a
commit
7cf38ec4c5
@ -38,7 +38,6 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR___name__;
|
MP_QSTR___name__;
|
||||||
MP_QSTR_account;
|
MP_QSTR_account;
|
||||||
MP_QSTR_account_items;
|
MP_QSTR_account_items;
|
||||||
MP_QSTR_account_items_title;
|
|
||||||
MP_QSTR_account_label;
|
MP_QSTR_account_label;
|
||||||
MP_QSTR_account_path;
|
MP_QSTR_account_path;
|
||||||
MP_QSTR_accounts;
|
MP_QSTR_accounts;
|
||||||
@ -693,7 +692,6 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_time_ms;
|
MP_QSTR_time_ms;
|
||||||
MP_QSTR_timer;
|
MP_QSTR_timer;
|
||||||
MP_QSTR_title;
|
MP_QSTR_title;
|
||||||
MP_QSTR_title_success;
|
|
||||||
MP_QSTR_total_amount;
|
MP_QSTR_total_amount;
|
||||||
MP_QSTR_total_fee_new;
|
MP_QSTR_total_fee_new;
|
||||||
MP_QSTR_total_label;
|
MP_QSTR_total_label;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::{self, Error},
|
error::{self, Error},
|
||||||
maybe_trace::MaybeTrace,
|
maybe_trace::MaybeTrace,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -15,7 +14,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow, SwipePage,
|
FlowController, FlowMsg, SwipeFlow, SwipePage,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,33 +137,18 @@ impl ConfirmActionStrings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub fn new_confirm_action(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_action_obj) }
|
title: TString<'static>,
|
||||||
}
|
action: Option<TString<'static>>,
|
||||||
|
description: Option<TString<'static>>,
|
||||||
fn new_confirm_action_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
subtitle: Option<TString<'static>>,
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
verb_cancel: Option<TString<'static>>,
|
||||||
let action: Option<TString> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
|
reverse: bool,
|
||||||
let description: Option<TString> = kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
|
hold: bool,
|
||||||
let subtitle: Option<TString> = kwargs
|
prompt_screen: bool,
|
||||||
.get(Qstr::MP_QSTR_subtitle)
|
prompt_title: TString<'static>,
|
||||||
.unwrap_or(Obj::const_none())
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
.try_into_option()?;
|
|
||||||
// let verb: Option<TString> = kwargs
|
|
||||||
// .get(Qstr::MP_QSTR_verb)
|
|
||||||
// .unwrap_or_else(|_| Obj::const_none())
|
|
||||||
// .try_into_option()?;
|
|
||||||
let verb_cancel: Option<TString> = kwargs
|
|
||||||
.get(Qstr::MP_QSTR_verb_cancel)
|
|
||||||
.unwrap_or_else(|_| Obj::const_none())
|
|
||||||
.try_into_option()?;
|
|
||||||
let 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)?;
|
|
||||||
|
|
||||||
let paragraphs = {
|
let paragraphs = {
|
||||||
let action = action.unwrap_or("".into());
|
let action = action.unwrap_or("".into());
|
||||||
let description = description.unwrap_or("".into());
|
let description = description.unwrap_or("".into());
|
||||||
@ -197,7 +180,7 @@ fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(
|
|||||||
menu: ConfirmActionMenu,
|
menu: ConfirmActionMenu,
|
||||||
strings: ConfirmActionStrings,
|
strings: ConfirmActionStrings,
|
||||||
hold: bool,
|
hold: bool,
|
||||||
) -> Result<Obj, error::Error> {
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
let (prompt_screen, prompt_pages, flow, page) =
|
let (prompt_screen, prompt_pages, flow, page) =
|
||||||
create_flow(strings.title, strings.prompt_screen, hold);
|
create_flow(strings.title, strings.prompt_screen, hold);
|
||||||
|
|
||||||
@ -225,7 +208,7 @@ fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(
|
|||||||
|
|
||||||
let flow = create_confirm(flow, strings.subtitle, hold, prompt_screen)?;
|
let flow = create_confirm(flow, strings.subtitle, hold, prompt_screen)?;
|
||||||
|
|
||||||
Ok(LayoutObj::new_root(flow)?.into())
|
Ok(flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_flow(
|
fn create_flow(
|
||||||
@ -335,7 +318,7 @@ pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>
|
|||||||
strings: ConfirmActionStrings,
|
strings: ConfirmActionStrings,
|
||||||
hold: bool,
|
hold: bool,
|
||||||
page_limit: Option<usize>,
|
page_limit: Option<usize>,
|
||||||
) -> Result<Obj, error::Error> {
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
new_confirm_action_uni(
|
new_confirm_action_uni(
|
||||||
SwipeContent::new(SwipePage::vertical(content).with_limit(page_limit)),
|
SwipeContent::new(SwipePage::vertical(content).with_limit(page_limit)),
|
||||||
menu,
|
menu,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -14,7 +13,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,78 +63,65 @@ impl FlowController for ConfirmFirmwareUpdate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_confirm_firmware_update(
|
||||||
pub extern "C" fn new_confirm_firmware_update(
|
description: TString<'static>,
|
||||||
n_args: usize,
|
fingerprint: TString<'static>,
|
||||||
args: *const Obj,
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
kwargs: *mut Map,
|
let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description));
|
||||||
) -> Obj {
|
let content_intro = Frame::left_aligned(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmFirmwareUpdate::new_obj) }
|
TR::firmware_update__title.into(),
|
||||||
}
|
SwipeContent::new(paragraphs),
|
||||||
|
)
|
||||||
impl ConfirmFirmwareUpdate {
|
.with_menu_button()
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
let fingerprint: TString = kwargs.get(Qstr::MP_QSTR_fingerprint)?.try_into()?;
|
.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(
|
let content_menu = Frame::left_aligned(
|
||||||
TR::firmware_update__title.into(),
|
TString::empty(),
|
||||||
SwipeContent::new(paragraphs),
|
VerticalMenu::empty()
|
||||||
)
|
.item(
|
||||||
.with_menu_button()
|
theme::ICON_CHEVRON_RIGHT,
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
TR::firmware_update__title_fingerprint.into(),
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
)
|
||||||
.with_swipe(Direction::Left, SwipeSettings::default())
|
.danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
|
||||||
.map(|msg| matches!(msg, FrameMsg::Button(FlowMsg::Info)).then_some(FlowMsg::Info));
|
)
|
||||||
|
.with_cancel_button()
|
||||||
let content_menu = Frame::left_aligned(
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
TString::empty(),
|
.map(|msg| match msg {
|
||||||
VerticalMenu::empty()
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
.item(
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
theme::ICON_CHEVRON_RIGHT,
|
});
|
||||||
TR::firmware_update__title_fingerprint.into(),
|
|
||||||
)
|
let paragraphs_fingerprint =
|
||||||
.danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
|
Paragraphs::new(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, fingerprint));
|
||||||
)
|
let content_fingerprint = Frame::left_aligned(
|
||||||
.with_cancel_button()
|
TR::firmware_update__title_fingerprint.into(),
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
SwipeContent::new(paragraphs_fingerprint),
|
||||||
.map(|msg| match msg {
|
)
|
||||||
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
.with_cancel_button()
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
.with_swipe(Direction::Right, SwipeSettings::default())
|
||||||
});
|
.map(|msg| matches!(msg, FrameMsg::Button(FlowMsg::Cancelled)).then_some(FlowMsg::Cancelled));
|
||||||
|
|
||||||
let paragraphs_fingerprint =
|
let content_confirm = Frame::left_aligned(
|
||||||
Paragraphs::new(Paragraph::new(&theme::TEXT_MONO_GREY_LIGHT, fingerprint));
|
TR::firmware_update__title.into(),
|
||||||
let content_fingerprint = Frame::left_aligned(
|
SwipeContent::new(PromptScreen::new_hold_to_confirm()),
|
||||||
TR::firmware_update__title_fingerprint.into(),
|
)
|
||||||
SwipeContent::new(paragraphs_fingerprint),
|
.with_menu_button()
|
||||||
)
|
.with_footer(TR::instructions__hold_to_confirm.into(), None)
|
||||||
.with_cancel_button()
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
.with_swipe(Direction::Right, SwipeSettings::default())
|
.with_swipe(Direction::Left, SwipeSettings::default())
|
||||||
.map(|msg| {
|
.map(|msg| match msg {
|
||||||
matches!(msg, FrameMsg::Button(FlowMsg::Cancelled)).then_some(FlowMsg::Cancelled)
|
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()),
|
let res = SwipeFlow::new(&ConfirmFirmwareUpdate::Intro)?
|
||||||
)
|
.with_page(&ConfirmFirmwareUpdate::Intro, content_intro)?
|
||||||
.with_menu_button()
|
.with_page(&ConfirmFirmwareUpdate::Menu, content_menu)?
|
||||||
.with_footer(TR::instructions__hold_to_confirm.into(), None)
|
.with_page(&ConfirmFirmwareUpdate::Fingerprint, content_fingerprint)?
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.with_page(&ConfirmFirmwareUpdate::Confirm, content_confirm)?;
|
||||||
.with_swipe(Direction::Left, SwipeSettings::default())
|
Ok(res)
|
||||||
.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_root(res)?.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use heapless::Vec;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
micropython::{iter::IterBuf, obj::Obj, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -13,7 +13,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -212,46 +211,27 @@ fn get_cancel_page(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub fn new_confirm_output(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_output_obj) }
|
title: Option<TString<'static>>,
|
||||||
}
|
subtitle: Option<TString<'static>>,
|
||||||
|
account: Option<TString<'static>>,
|
||||||
fn new_confirm_output_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
account_path: Option<TString<'static>>,
|
||||||
let title: Option<TString> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?;
|
br_name: TString<'static>,
|
||||||
let subtitle: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?;
|
br_code: u16,
|
||||||
|
message: Obj,
|
||||||
let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
|
amount: Option<Obj>,
|
||||||
let account_path: Option<TString> =
|
chunkify: bool,
|
||||||
kwargs.get(Qstr::MP_QSTR_account_path)?.try_into_option()?;
|
text_mono: bool,
|
||||||
|
address: Option<Obj>,
|
||||||
let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?;
|
address_title: Option<TString<'static>>,
|
||||||
let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?;
|
summary_items: Obj,
|
||||||
|
fee_items: Obj,
|
||||||
let message: Obj = kwargs.get(Qstr::MP_QSTR_message)?;
|
summary_title: Option<TString<'static>>,
|
||||||
let amount: Option<Obj> = kwargs.get(Qstr::MP_QSTR_amount)?.try_into_option()?;
|
summary_br_name: Option<TString<'static>>,
|
||||||
|
summary_br_code: Option<u16>,
|
||||||
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
|
cancel_text: Option<TString<'static>>,
|
||||||
let text_mono: bool = kwargs.get_or(Qstr::MP_QSTR_text_mono, true)?;
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
|
|
||||||
let address: Option<Obj> = kwargs.get(Qstr::MP_QSTR_address)?.try_into_option()?;
|
|
||||||
let address_title: Option<TString> =
|
|
||||||
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<TString> =
|
|
||||||
kwargs.get(Qstr::MP_QSTR_summary_title)?.try_into_option()?;
|
|
||||||
let summary_br_name: Option<TString> = kwargs
|
|
||||||
.get(Qstr::MP_QSTR_summary_br_name)?
|
|
||||||
.try_into_option()?;
|
|
||||||
let summary_br_code: Option<u16> = kwargs
|
|
||||||
.get(Qstr::MP_QSTR_summary_br_code)?
|
|
||||||
.try_into_option()?;
|
|
||||||
|
|
||||||
let cancel_text: Option<TString> = kwargs.get(Qstr::MP_QSTR_cancel_text)?.try_into_option()?;
|
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
let main_content = ConfirmBlobParams::new(title.unwrap_or(TString::empty()), message, None)
|
let main_content = ConfirmBlobParams::new(title.unwrap_or(TString::empty()), message, None)
|
||||||
.with_subtitle(subtitle)
|
.with_subtitle(subtitle)
|
||||||
@ -450,5 +430,5 @@ fn new_confirm_output_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Err
|
|||||||
.with_page(&ConfirmOutput::CancelTap, get_cancel_page())?
|
.with_page(&ConfirmOutput::CancelTap, get_cancel_page())?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(LayoutObj::new_root(res)?.into())
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -15,7 +14,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,14 +91,7 @@ impl FlowController for ConfirmResetRecover {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_confirm_reset(recovery: bool) -> Result<SwipeFlow, error::Error> {
|
||||||
pub extern "C" fn new_confirm_reset(n_args: usize, args: *const Obj, kwargs: *mut Map) -> 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<Obj, error::Error> {
|
|
||||||
let recovery: bool = kwargs.get_or(Qstr::MP_QSTR_recovery, false)?;
|
|
||||||
|
|
||||||
let (title, br, cancel_btn_text) = if recovery {
|
let (title, br, cancel_btn_text) = if recovery {
|
||||||
(
|
(
|
||||||
TR::recovery__title_recover.into(),
|
TR::recovery__title_recover.into(),
|
||||||
@ -166,5 +157,5 @@ fn new_confirm_reset_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Erro
|
|||||||
.with_page(&ConfirmResetCreate::Menu, content_menu)?
|
.with_page(&ConfirmResetCreate::Menu, content_menu)?
|
||||||
.with_page(&ConfirmResetCreate::Confirm, content_confirm)?
|
.with_page(&ConfirmResetCreate::Confirm, content_confirm)?
|
||||||
};
|
};
|
||||||
Ok(LayoutObj::new_root(res)?.into())
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -14,7 +13,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
model_mercury::component::SwipeContent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -64,80 +62,73 @@ impl FlowController for SetNewPin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_set_new_pin(
|
||||||
pub extern "C" fn new_set_new_pin(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
title: TString<'static>,
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetNewPin::new_obj) }
|
description: TString<'static>,
|
||||||
}
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
|
// TODO: supply more arguments for Wipe code setting when figma done
|
||||||
impl SetNewPin {
|
let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description));
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
let content_intro = Frame::left_aligned(title, SwipeContent::new(paragraphs))
|
||||||
// TODO: supply more arguments for Wipe code setting when figma done
|
.with_menu_button()
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
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()),
|
|
||||||
)
|
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
.with_swipe(Direction::Left, SwipeSettings::default())
|
||||||
.map(|msg| match msg {
|
.map(|msg| match msg {
|
||||||
FrameMsg::Button(bm) => Some(bm),
|
FrameMsg::Button(bm) => Some(bm),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let content_cancel_confirm = Frame::left_aligned(
|
let content_menu = Frame::left_aligned(
|
||||||
TR::pin__cancel_setup.into(),
|
"".into(),
|
||||||
SwipeContent::new(PromptScreen::new_tap_to_cancel()),
|
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::pin__cancel_setup.into()),
|
||||||
)
|
)
|
||||||
.with_cancel_button()
|
.with_cancel_button()
|
||||||
.with_footer(TR::instructions__tap_to_confirm.into(), None)
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.map(|msg| match msg {
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
.map(|msg| match msg {
|
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||||
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
|
FrameMsg::Button(_) => None,
|
||||||
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
});
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
|
|
||||||
let res = SwipeFlow::new(&SetNewPin::Intro)?
|
let paragraphs_cancel_intro = ParagraphVecShort::from_iter([
|
||||||
.with_page(&SetNewPin::Intro, content_intro)?
|
Paragraph::new(&theme::TEXT_WARNING, TR::words__not_recommended),
|
||||||
.with_page(&SetNewPin::Menu, content_menu)?
|
Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, TR::pin__cancel_info),
|
||||||
.with_page(&SetNewPin::CancelPinIntro, content_cancel_intro)?
|
])
|
||||||
.with_page(&SetNewPin::CancelPinConfirm, content_cancel_confirm)?;
|
.into_paragraphs();
|
||||||
Ok(LayoutObj::new_root(res)?.into())
|
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)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use heapless::Vec;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
micropython::{iter::IterBuf, obj::Obj, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -13,15 +13,14 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
super::{
|
super::{
|
||||||
component::{
|
component::{
|
||||||
Frame, FrameMsg, PromptMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg,
|
Frame, FrameMsg, PromptMsg, PromptScreen, SwipeContent, VerticalMenu,
|
||||||
|
VerticalMenuChoiceMsg,
|
||||||
},
|
},
|
||||||
theme,
|
theme,
|
||||||
},
|
},
|
||||||
@ -76,133 +75,119 @@ impl FlowController for ConfirmSummary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_confirm_summary(
|
||||||
pub extern "C" fn new_confirm_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
title: TString<'static>,
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, ConfirmSummary::new_obj) }
|
items: Obj,
|
||||||
}
|
account_items: Obj,
|
||||||
|
fee_items: Obj,
|
||||||
impl ConfirmSummary {
|
br_name: TString<'static>,
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
br_code: u16,
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
cancel_text: Option<TString<'static>>,
|
||||||
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
let account_items: Obj = kwargs.get(Qstr::MP_QSTR_account_items)?;
|
// Summary
|
||||||
let account_items_title: Option<TString> = kwargs
|
let mut summary = ShowInfoParams::new(title)
|
||||||
.get(Qstr::MP_QSTR_account_items_title)
|
|
||||||
.unwrap_or(Obj::const_none())
|
|
||||||
.try_into_option()?;
|
|
||||||
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<TString> =
|
|
||||||
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()),
|
|
||||||
)
|
|
||||||
.with_menu_button()
|
.with_menu_button()
|
||||||
.with_footer(TR::instructions__hold_to_sign.into(), None)
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.with_swipe_up();
|
||||||
.with_swipe(Direction::Left, SwipeSettings::default())
|
for pair in IterBuf::new().try_iterate(items)? {
|
||||||
.map(|msg| match msg {
|
let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
|
||||||
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
|
summary = unwrap!(summary.add(label, value));
|
||||||
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(account_items_title.unwrap_or(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::<usize, 3>::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,
|
|
||||||
account_items_title.unwrap_or(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_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(),
|
|
||||||
)
|
|
||||||
.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(LayoutObj::new_root(res)?.into())
|
|
||||||
}
|
}
|
||||||
|
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::<usize, 3>::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()),
|
||||||
|
);
|
||||||
|
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(),
|
||||||
|
)
|
||||||
|
.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)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -18,7 +17,7 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow, SwipePage,
|
FlowController, FlowMsg, SwipeFlow, SwipePage,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
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(
|
fn footer_update_fn(
|
||||||
content: &SwipeContent<SwipePage<Paragraphs<ParagraphVecLong>>>,
|
content: &SwipeContent<SwipePage<Paragraphs<ParagraphVecLong>>>,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
@ -159,24 +154,13 @@ fn footer_update_fn(
|
|||||||
footer.update_page_counter(ctx, current_page, Some(total_pages));
|
footer.update_page_counter(ctx, current_page, Some(total_pages));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
pub fn new_continue_recovery(
|
||||||
let first_screen: bool = kwargs.get(Qstr::MP_QSTR_first_screen)?.try_into()?;
|
first_screen: bool,
|
||||||
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
recovery_type: RecoveryType,
|
||||||
let text: TString = kwargs.get(Qstr::MP_QSTR_text)?.try_into()?; // #shares entered
|
text: TString<'static>,
|
||||||
let subtext: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtext)?.try_into_option()?; // #shares remaining
|
subtext: Option<TString<'static>>,
|
||||||
let pages: Option<Obj> = kwargs.get(Qstr::MP_QSTR_pages)?.try_into_option()?; // info about remaining shares
|
pages: Option<ParagraphVecLong<'static>>,
|
||||||
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type {
|
let (title, cancel_btn, cancel_title, cancel_intro) = match recovery_type {
|
||||||
RecoveryType::Normal => (
|
RecoveryType::Normal => (
|
||||||
TR::recovery__title,
|
TR::recovery__title,
|
||||||
@ -277,7 +261,7 @@ fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
|||||||
SwipeFlow::new(&ContinueRecoveryBeforeShares::Main)?
|
SwipeFlow::new(&ContinueRecoveryBeforeShares::Main)?
|
||||||
.with_page(&ContinueRecoveryBeforeShares::Main, content_main)?
|
.with_page(&ContinueRecoveryBeforeShares::Main, content_main)?
|
||||||
.with_page(&ContinueRecoveryBeforeShares::Menu, content_menu)?
|
.with_page(&ContinueRecoveryBeforeShares::Menu, content_menu)?
|
||||||
} else if pars_show_shares.is_empty() {
|
} else if pages.is_none() {
|
||||||
let content_menu = Frame::left_aligned(
|
let content_menu = Frame::left_aligned(
|
||||||
TString::empty(),
|
TString::empty(),
|
||||||
VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()),
|
VerticalMenu::empty().danger(theme::ICON_CANCEL, cancel_btn.into()),
|
||||||
@ -321,10 +305,10 @@ fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
|||||||
TR::instructions__swipe_up.into(),
|
TR::instructions__swipe_up.into(),
|
||||||
TR::recovery__more_shares_needed.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(
|
let content_remaining_shares = Frame::left_aligned(
|
||||||
TR::recovery__title_remaining_shares.into(),
|
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_cancel_button()
|
||||||
.with_footer_page_hint(
|
.with_footer_page_hint(
|
||||||
@ -360,5 +344,5 @@ fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
|||||||
content_remaining_shares,
|
content_remaining_shares,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
Ok(LayoutObj::new_root(res)?.into())
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
micropython::{iter::IterBuf, obj::Obj, util},
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -15,7 +15,7 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow, SwipePage,
|
FlowController, FlowMsg, SwipeFlow, SwipePage,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::{obj::LayoutObj, util::ConfirmBlob},
|
layout::util::ConfirmBlob,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,155 +84,143 @@ impl FlowController for GetAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub extern "C" fn new_get_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub fn new_get_address(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, GetAddress::new_obj) }
|
title: TString<'static>,
|
||||||
}
|
description: Option<TString<'static>>,
|
||||||
|
extra: Option<TString<'static>>,
|
||||||
impl GetAddress {
|
address: Obj, // TODO: get rid of Obj
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
chunkify: bool,
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
address_qr: TString<'static>,
|
||||||
let description: Option<TString> =
|
case_sensitive: bool,
|
||||||
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
|
account: Option<TString<'static>>,
|
||||||
let extra: Option<TString> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
|
path: Option<TString<'static>>,
|
||||||
let address: Obj = kwargs.get(Qstr::MP_QSTR_address)?;
|
xpubs: Obj, // TODO: get rid of Obj
|
||||||
let chunkify: bool = kwargs.get_or(Qstr::MP_QSTR_chunkify, false)?;
|
br_code: u16,
|
||||||
|
br_name: TString<'static>,
|
||||||
let address_qr: TString = kwargs.get(Qstr::MP_QSTR_address_qr)?.try_into()?;
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
let case_sensitive: bool = kwargs.get(Qstr::MP_QSTR_case_sensitive)?.try_into()?;
|
// Address
|
||||||
|
let data_style = if chunkify {
|
||||||
let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
|
let address: TString = address.try_into()?;
|
||||||
let path: Option<TString> = kwargs.get(Qstr::MP_QSTR_path)?.try_into_option()?;
|
theme::get_chunkified_text_style(address.len())
|
||||||
let xpubs: Obj = kwargs.get(Qstr::MP_QSTR_xpubs)?;
|
} else {
|
||||||
|
&theme::TEXT_MONO
|
||||||
let title_success: TString = kwargs.get(Qstr::MP_QSTR_title_success)?.try_into()?;
|
};
|
||||||
|
let paragraphs = ConfirmBlob {
|
||||||
let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?;
|
description: description.unwrap_or_else(|| "".into()),
|
||||||
let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?;
|
extra: extra.unwrap_or_else(|| "".into()),
|
||||||
|
data: address.try_into()?,
|
||||||
// Address
|
description_font: &theme::TEXT_NORMAL,
|
||||||
let data_style = if chunkify {
|
extra_font: &theme::TEXT_DEMIBOLD,
|
||||||
let address: TString = address.try_into()?;
|
data_font: data_style,
|
||||||
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(title_success),
|
|
||||||
)
|
|
||||||
.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_root(res)?.into())
|
|
||||||
}
|
}
|
||||||
|
.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)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -14,7 +13,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,82 +63,75 @@ impl FlowController for PromptBackup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_prompt_backup() -> Result<SwipeFlow, error::Error> {
|
||||||
pub extern "C" fn new_prompt_backup(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
let title: TString = TR::backup__title_create_wallet_backup.into();
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, PromptBackup::new_obj) }
|
let text_intro: TString = TR::backup__it_should_be_backed_up.into();
|
||||||
}
|
|
||||||
|
|
||||||
impl PromptBackup {
|
let paragraphs = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text_intro));
|
||||||
fn new_obj(_args: &[Obj], _kwargs: &Map) -> Result<Obj, error::Error> {
|
let content_intro = Frame::left_aligned(title, SwipeContent::new(paragraphs))
|
||||||
let title: TString = TR::backup__title_create_wallet_backup.into();
|
.with_menu_button()
|
||||||
let text_intro: TString = TR::backup__it_should_be_backed_up.into();
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
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_question.into()),
|
|
||||||
)
|
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
.with_swipe(Direction::Left, SwipeSettings::default())
|
||||||
.map(|msg| match msg {
|
.map(|msg| match msg {
|
||||||
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
FrameMsg::Button(bm) => Some(bm),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let content_skip_confirm = Frame::left_aligned(
|
let content_menu = Frame::left_aligned(
|
||||||
TR::backup__title_skip.into(),
|
"".into(),
|
||||||
SwipeContent::new(PromptScreen::new_tap_to_cancel()),
|
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::backup__title_skip.into()),
|
||||||
)
|
)
|
||||||
.with_cancel_button()
|
.with_cancel_button()
|
||||||
.with_footer(TR::instructions__tap_to_confirm.into(), None)
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.map(|msg| match msg {
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
.map(|msg| match msg {
|
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||||
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
|
FrameMsg::Button(_) => None,
|
||||||
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
});
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
|
|
||||||
let res = SwipeFlow::new(&PromptBackup::Intro)?
|
let paragraphs_skip_intro = ParagraphVecShort::from_iter([
|
||||||
.with_page(&PromptBackup::Intro, content_intro)?
|
Paragraph::new(&theme::TEXT_WARNING, TR::words__not_recommended),
|
||||||
.with_page(&PromptBackup::Menu, content_menu)?
|
Paragraph::new(
|
||||||
.with_page(&PromptBackup::SkipBackupIntro, content_skip_intro)?
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
.with_page(&PromptBackup::SkipBackupConfirm, content_skip_confirm)?;
|
TR::backup__create_backup_to_prevent_loss,
|
||||||
Ok(LayoutObj::new_root(res)?.into())
|
),
|
||||||
}
|
])
|
||||||
|
.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_question.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)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -11,7 +10,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,77 +59,68 @@ impl FlowController for RequestNumber {
|
|||||||
|
|
||||||
static NUM_DISPLAYED: AtomicU16 = AtomicU16::new(0);
|
static NUM_DISPLAYED: AtomicU16 = AtomicU16::new(0);
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
pub fn new_request_number(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestNumber::new_obj) }
|
title: TString<'static>,
|
||||||
}
|
count: u32,
|
||||||
|
min_count: u32,
|
||||||
|
max_count: u32,
|
||||||
|
description: TString<'static>,
|
||||||
|
info_closure: impl Fn(u32) -> TString<'static> + 'static,
|
||||||
|
br_code: u16,
|
||||||
|
br_name: TString<'static>,
|
||||||
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
|
NUM_DISPLAYED.store(count as u16, Ordering::Relaxed);
|
||||||
|
|
||||||
impl RequestNumber {
|
// wrap the closure for obtaining MoreInfo text and call it with NUM_DISPLAYED
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
let info_closure = move || {
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
let curr_number = NUM_DISPLAYED.load(Ordering::Relaxed);
|
||||||
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
|
info_closure(curr_number as u32)
|
||||||
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()?;
|
|
||||||
|
|
||||||
NUM_DISPLAYED.store(count as u16, Ordering::Relaxed);
|
let number_input_dialog = NumberInputDialog::new(min_count, max_count, count, description)?;
|
||||||
let info_cb = move || {
|
let content_number_input = Frame::left_aligned(title, SwipeContent::new(number_input_dialog))
|
||||||
let curr_number = NUM_DISPLAYED.load(Ordering::Relaxed) as u32;
|
.with_menu_button()
|
||||||
let text = info
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
.call_with_n_args(&[curr_number.try_into().unwrap()])
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.unwrap();
|
.with_swipe(Direction::Left, SwipeSettings::default())
|
||||||
TString::try_from(text).unwrap()
|
.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_menu = Frame::left_aligned(
|
||||||
let content_number_input =
|
TString::empty(),
|
||||||
Frame::left_aligned(title, SwipeContent::new(number_input_dialog))
|
VerticalMenu::empty().item(theme::ICON_CHEVRON_RIGHT, TR::buttons__more_info.into()),
|
||||||
.with_menu_button()
|
)
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
.with_cancel_button()
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
.with_swipe(Direction::Left, SwipeSettings::default())
|
.map(|msg| match msg {
|
||||||
.map(|msg| match msg {
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||||
FrameMsg::Content(NumberInputDialogMsg::Changed(n)) => {
|
FrameMsg::Button(_) => None,
|
||||||
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(
|
let updatable_info = UpdatableMoreInfo::new(info_closure);
|
||||||
TString::empty(),
|
let content_info = Frame::left_aligned(TString::empty(), SwipeContent::new(updatable_info))
|
||||||
VerticalMenu::empty().item(theme::ICON_CHEVRON_RIGHT, TR::buttons__more_info.into()),
|
|
||||||
)
|
|
||||||
.with_cancel_button()
|
.with_cancel_button()
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
.map(|msg| match msg {
|
.map(|msg| match msg {
|
||||||
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
|
||||||
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
FrameMsg::Button(FlowMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||||
FrameMsg::Button(_) => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let updatable_info = UpdatableMoreInfo::new(info_cb);
|
let res = SwipeFlow::new(&RequestNumber::Number)?
|
||||||
let content_info = Frame::left_aligned(TString::empty(), SwipeContent::new(updatable_info))
|
.with_page(&RequestNumber::Number, content_number_input)?
|
||||||
.with_cancel_button()
|
.with_page(&RequestNumber::Menu, content_menu)?
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
.with_page(&RequestNumber::Info, content_info)?;
|
||||||
.map(|msg| match msg {
|
Ok(res)
|
||||||
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_root(res)?.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
strutil::ShortString,
|
||||||
strutil::{ShortString, TString},
|
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::ComponentExt,
|
component::ComponentExt,
|
||||||
@ -10,7 +9,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,34 +51,24 @@ impl FlowController for RequestPassphrase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_request_passphrase() -> Result<SwipeFlow, error::Error> {
|
||||||
pub extern "C" fn new_request_passphrase(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
let content_confirm_empty = Frame::left_aligned(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, RequestPassphrase::new_obj) }
|
TR::passphrase__continue_with_empty_passphrase.into(),
|
||||||
}
|
PromptScreen::new_yes_or_no(),
|
||||||
|
)
|
||||||
impl RequestPassphrase {
|
.map(|msg| match msg {
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
|
||||||
let _prompt: TString = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
FrameMsg::Content(PromptMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
||||||
let _max_len: u32 = kwargs.get(Qstr::MP_QSTR_max_len)?.try_into()?;
|
_ => None,
|
||||||
|
});
|
||||||
let content_confirm_empty = Frame::left_aligned(
|
|
||||||
TR::passphrase__continue_with_empty_passphrase.into(),
|
let content_keypad = PassphraseKeyboard::new().map(|msg| match msg {
|
||||||
PromptScreen::new_yes_or_no(),
|
PassphraseKeyboardMsg::Confirmed(s) => Some(FlowMsg::Text(s)),
|
||||||
)
|
PassphraseKeyboardMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||||
.map(|msg| match msg {
|
});
|
||||||
FrameMsg::Content(PromptMsg::Confirmed) => Some(FlowMsg::Confirmed),
|
|
||||||
FrameMsg::Content(PromptMsg::Cancelled) => Some(FlowMsg::Cancelled),
|
let res = SwipeFlow::new(&RequestPassphrase::Keypad)?
|
||||||
_ => None,
|
.with_page(&RequestPassphrase::Keypad, content_keypad)?
|
||||||
});
|
.with_page(&RequestPassphrase::ConfirmEmpty, content_confirm_empty)?;
|
||||||
|
Ok(res)
|
||||||
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_root(res)?.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ use core::sync::atomic::{AtomicU8, Ordering};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
storage,
|
storage,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
trezorhal::display,
|
trezorhal::display,
|
||||||
@ -13,7 +12,6 @@ use crate::{
|
|||||||
FlowController, SwipeFlow,
|
FlowController, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,80 +64,71 @@ impl FlowController for SetBrightness {
|
|||||||
|
|
||||||
static BRIGHTNESS: AtomicU8 = AtomicU8::new(0);
|
static BRIGHTNESS: AtomicU8 = AtomicU8::new(0);
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_set_brightness(brightness: u8) -> Result<SwipeFlow, Error> {
|
||||||
pub extern "C" fn new_set_brightness(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
let content_slider = Frame::left_aligned(
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetBrightness::new_obj) }
|
TR::brightness__title.into(),
|
||||||
}
|
NumberInputSliderDialog::new(
|
||||||
|
theme::backlight::get_backlight_min() as u16,
|
||||||
impl SetBrightness {
|
theme::backlight::get_backlight_max() as u16,
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, Error> {
|
brightness as u16,
|
||||||
let current: Option<u8> = kwargs.get(Qstr::MP_QSTR_current)?.try_into_option()?;
|
),
|
||||||
let content_slider = Frame::left_aligned(
|
)
|
||||||
TR::brightness__title.into(),
|
.with_subtitle(TR::homescreen__settings_subtitle.into())
|
||||||
NumberInputSliderDialog::new(
|
.with_menu_button()
|
||||||
theme::backlight::get_backlight_min() as u16,
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
theme::backlight::get_backlight_max() as u16,
|
.map(|msg| match msg {
|
||||||
current.unwrap_or(theme::backlight::get_backlight_normal()) as u16,
|
FrameMsg::Content(NumberInputSliderDialogMsg::Changed(n)) => {
|
||||||
),
|
display::backlight(n as _);
|
||||||
)
|
BRIGHTNESS.store(n as u8, Ordering::Relaxed);
|
||||||
.with_subtitle(TR::homescreen__settings_subtitle.into())
|
None
|
||||||
.with_menu_button()
|
}
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
||||||
.map(|msg| match msg {
|
});
|
||||||
FrameMsg::Content(NumberInputSliderDialogMsg::Changed(n)) => {
|
|
||||||
display::backlight(n as _);
|
let content_menu = Frame::left_aligned(
|
||||||
BRIGHTNESS.store(n as u8, Ordering::Relaxed);
|
"".into(),
|
||||||
None
|
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
|
||||||
}
|
)
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
.with_cancel_button()
|
||||||
});
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
|
.map(move |msg| match msg {
|
||||||
let content_menu = Frame::left_aligned(
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
"".into(),
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
|
});
|
||||||
)
|
|
||||||
.with_cancel_button()
|
let content_confirm = Frame::left_aligned(
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
TR::brightness__change_title.into(),
|
||||||
.map(move |msg| match msg {
|
SwipeContent::new(PromptScreen::new_tap_to_confirm()),
|
||||||
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
)
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
.with_footer(TR::instructions__tap_to_confirm.into(), None)
|
||||||
});
|
.with_menu_button()
|
||||||
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
let content_confirm = Frame::left_aligned(
|
.with_swipe(Direction::Left, SwipeSettings::default())
|
||||||
TR::brightness__change_title.into(),
|
.map(move |msg| match msg {
|
||||||
SwipeContent::new(PromptScreen::new_tap_to_confirm()),
|
FrameMsg::Content(PromptMsg::Confirmed) => {
|
||||||
)
|
let _ = storage::set_brightness(BRIGHTNESS.load(Ordering::Relaxed));
|
||||||
.with_footer(TR::instructions__tap_to_confirm.into(), None)
|
Some(FlowMsg::Confirmed)
|
||||||
.with_menu_button()
|
}
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
||||||
.with_swipe(Direction::Left, SwipeSettings::default())
|
_ => None,
|
||||||
.map(move |msg| match msg {
|
});
|
||||||
FrameMsg::Content(PromptMsg::Confirmed) => {
|
|
||||||
let _ = storage::set_brightness(BRIGHTNESS.load(Ordering::Relaxed));
|
let content_confirmed = Frame::left_aligned(
|
||||||
Some(FlowMsg::Confirmed)
|
TR::words__title_success.into(),
|
||||||
}
|
SwipeContent::new(StatusScreen::new_success(
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
TR::brightness__changed_title.into(),
|
||||||
_ => None,
|
))
|
||||||
});
|
.with_no_attach_anim(),
|
||||||
|
)
|
||||||
let content_confirmed = Frame::left_aligned(
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
TR::words__title_success.into(),
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
SwipeContent::new(StatusScreen::new_success(
|
.map(move |_msg| Some(FlowMsg::Confirmed));
|
||||||
TR::brightness__changed_title.into(),
|
|
||||||
))
|
let res = SwipeFlow::new(&SetBrightness::Slider)?
|
||||||
.with_no_attach_anim(),
|
.with_page(&SetBrightness::Slider, content_slider)?
|
||||||
)
|
.with_page(&SetBrightness::Menu, content_menu)?
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
.with_page(&SetBrightness::Confirm, content_confirm)?
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.with_page(&SetBrightness::Confirmed, content_confirmed)?;
|
||||||
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT)
|
|
||||||
.map(move |_msg| Some(FlowMsg::Confirmed));
|
Ok(res)
|
||||||
|
|
||||||
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_root(res)?.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{iter::IterBuf, map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
button_request::ButtonRequestCode,
|
button_request::ButtonRequestCode,
|
||||||
component::{
|
component::{
|
||||||
swipe_detect::SwipeSettings,
|
swipe_detect::SwipeSettings,
|
||||||
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt},
|
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs},
|
||||||
ButtonRequestExt, ComponentExt, EventCtx,
|
ButtonRequestExt, ComponentExt, EventCtx,
|
||||||
},
|
},
|
||||||
flow::{
|
flow::{
|
||||||
@ -15,7 +14,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::{InternallySwipable, InternallySwipableContent, SwipeContent},
|
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(
|
fn header_updating_func(
|
||||||
content: &InternallySwipableContent<ShareWords>,
|
content: &InternallySwipableContent<ShareWords>,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
@ -84,82 +77,72 @@ fn footer_updating_func(
|
|||||||
footer.update_page_counter(ctx, current_page, Some(total_pages));
|
footer.update_page_counter(ctx, current_page, Some(total_pages));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShowShareWords {
|
pub fn new_show_share_words(
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
title: TString<'static>,
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
subtitle: TString<'static>,
|
||||||
let subtitle: TString = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into()?;
|
share_words_vec: Vec<TString<'static>, 33>,
|
||||||
let share_words_obj: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
|
description: Option<TString<'static>>,
|
||||||
let share_words_vec: Vec<TString, 33> = util::iter_into_vec(share_words_obj)?;
|
instructions_paragraphs: ParagraphVecShort<'static>,
|
||||||
let description: Option<TString> = kwargs
|
text_confirm: TString<'static>,
|
||||||
.get(Qstr::MP_QSTR_description)?
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
.try_into_option()?
|
let nwords = share_words_vec.len();
|
||||||
.and_then(|desc: TString| if desc.is_empty() { None } else { Some(desc) });
|
let paragraphs_spacing = 8;
|
||||||
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();
|
|
||||||
|
|
||||||
let mut instructions_paragraphs = ParagraphVecShort::new();
|
let content_instruction = Frame::left_aligned(
|
||||||
for item in IterBuf::new().try_iterate(text_info)? {
|
title,
|
||||||
let text: TString = item.try_into()?;
|
SwipeContent::new(
|
||||||
instructions_paragraphs.add(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text));
|
instructions_paragraphs
|
||||||
}
|
.into_paragraphs()
|
||||||
let paragraphs_spacing = 8;
|
.with_spacing(paragraphs_spacing),
|
||||||
let content_instruction = Frame::left_aligned(
|
),
|
||||||
title,
|
)
|
||||||
SwipeContent::new(
|
.with_subtitle(TR::words__instructions.into())
|
||||||
instructions_paragraphs
|
.with_footer(TR::instructions__swipe_up.into(), description)
|
||||||
.into_paragraphs()
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.with_spacing(paragraphs_spacing),
|
.map(|msg| matches!(msg, FrameMsg::Content(_)).then_some(FlowMsg::Confirmed))
|
||||||
),
|
.one_button_request(ButtonRequestCode::ResetDevice.with_name("share_words"))
|
||||||
)
|
.with_pages(move |_| nwords + 2);
|
||||||
.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 n_words = share_words_vec.len();
|
||||||
let content_words = Frame::left_aligned(
|
let content_words = Frame::left_aligned(
|
||||||
title,
|
title,
|
||||||
InternallySwipableContent::new(ShareWords::new(share_words_vec, subtitle)),
|
InternallySwipableContent::new(ShareWords::new(share_words_vec, subtitle)),
|
||||||
)
|
)
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
.with_vertical_pages()
|
.with_vertical_pages()
|
||||||
.with_subtitle(subtitle)
|
.with_subtitle(subtitle)
|
||||||
.register_header_update_fn(header_updating_func)
|
.register_header_update_fn(header_updating_func)
|
||||||
.with_footer_counter(TR::instructions__swipe_up.into(), n_words as u8)
|
.with_footer_counter(TR::instructions__swipe_up.into(), n_words as u8)
|
||||||
.register_footer_update_fn(footer_updating_func)
|
.register_footer_update_fn(footer_updating_func)
|
||||||
.map(|_| None);
|
.map(|_| None);
|
||||||
|
|
||||||
let content_confirm = Frame::left_aligned(
|
let content_confirm = Frame::left_aligned(
|
||||||
text_confirm,
|
text_confirm,
|
||||||
SwipeContent::new(PromptScreen::new_hold_to_confirm()),
|
SwipeContent::new(PromptScreen::new_hold_to_confirm()),
|
||||||
)
|
)
|
||||||
.with_footer(TR::instructions__hold_to_confirm.into(), None)
|
.with_footer(TR::instructions__hold_to_confirm.into(), None)
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
.map(|_| Some(FlowMsg::Confirmed));
|
.map(|_| Some(FlowMsg::Confirmed));
|
||||||
|
|
||||||
let content_check_backup_intro = Frame::left_aligned(
|
let content_check_backup_intro = Frame::left_aligned(
|
||||||
TR::reset__check_wallet_backup_title.into(),
|
TR::reset__check_wallet_backup_title.into(),
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
TR::reset__check_backup_instructions,
|
TR::reset__check_backup_instructions,
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.map(|_| Some(FlowMsg::Confirmed));
|
.map(|_| Some(FlowMsg::Confirmed));
|
||||||
|
|
||||||
let res = SwipeFlow::new(&ShowShareWords::Instruction)?
|
let res = SwipeFlow::new(&ShowShareWords::Instruction)?
|
||||||
.with_page(&ShowShareWords::Instruction, content_instruction)?
|
.with_page(&ShowShareWords::Instruction, content_instruction)?
|
||||||
.with_page(&ShowShareWords::Words, content_words)?
|
.with_page(&ShowShareWords::Words, content_words)?
|
||||||
.with_page(&ShowShareWords::Confirm, content_confirm)?
|
.with_page(&ShowShareWords::Confirm, content_confirm)?
|
||||||
.with_page(
|
.with_page(
|
||||||
&ShowShareWords::CheckBackupIntro,
|
&ShowShareWords::CheckBackupIntro,
|
||||||
content_check_backup_intro,
|
content_check_backup_intro,
|
||||||
)?;
|
)?;
|
||||||
Ok(LayoutObj::new_root(res)?.into())
|
Ok(res)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, util},
|
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
@ -13,7 +12,6 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,133 +73,126 @@ impl FlowController for ShowTutorial {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
pub fn new_show_tutorial() -> Result<SwipeFlow, error::Error> {
|
||||||
pub extern "C" fn new_show_tutorial(_n_args: usize, _args: *const Obj, _kwargs: *mut Map) -> Obj {
|
let content_step_welcome = Frame::left_aligned(
|
||||||
unsafe { util::try_or_raise(ShowTutorial::new_obj) }
|
TR::tutorial__welcome_safe5.into(),
|
||||||
}
|
SwipeContent::new(PromptScreen::new_tap_to_start()),
|
||||||
|
)
|
||||||
impl ShowTutorial {
|
.with_footer(TR::instructions__tap_to_start.into(), None)
|
||||||
fn new_obj() -> Result<Obj, error::Error> {
|
.map(|msg| {
|
||||||
let content_step_welcome = Frame::left_aligned(
|
matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed)
|
||||||
TR::tutorial__welcome_safe5.into(),
|
});
|
||||||
SwipeContent::new(PromptScreen::new_tap_to_start()),
|
|
||||||
)
|
let content_step_begin = Frame::left_aligned(
|
||||||
.with_footer(TR::instructions__tap_to_start.into(), None)
|
TR::tutorial__title_lets_begin.into(),
|
||||||
.map(|msg| {
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed)
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
});
|
TR::tutorial__lets_begin,
|
||||||
|
))),
|
||||||
let content_step_begin = Frame::left_aligned(
|
)
|
||||||
TR::tutorial__title_lets_begin.into(),
|
.with_footer(
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
TR::instructions__swipe_up.into(),
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
Some(TR::tutorial__get_started.into()),
|
||||||
TR::tutorial__lets_begin,
|
)
|
||||||
))),
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
)
|
.map(|_| None);
|
||||||
.with_footer(
|
|
||||||
TR::instructions__swipe_up.into(),
|
let content_step_navigation = Frame::left_aligned(
|
||||||
Some(TR::tutorial__get_started.into()),
|
TR::tutorial__title_easy_navigation.into(),
|
||||||
)
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
.map(|_| None);
|
TR::tutorial__swipe_up_and_down,
|
||||||
|
))),
|
||||||
let content_step_navigation = Frame::left_aligned(
|
)
|
||||||
TR::tutorial__title_easy_navigation.into(),
|
.with_footer(
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
TR::instructions__swipe_up.into(),
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
Some(TR::tutorial__continue.into()),
|
||||||
TR::tutorial__swipe_up_and_down,
|
)
|
||||||
))),
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
)
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
.with_footer(
|
.map(|_| None);
|
||||||
TR::instructions__swipe_up.into(),
|
|
||||||
Some(TR::tutorial__continue.into()),
|
let content_step_menu = Frame::left_aligned(
|
||||||
)
|
TR::tutorial__title_handy_menu.into(),
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
.map(|_| None);
|
TR::tutorial__menu,
|
||||||
|
))),
|
||||||
let content_step_menu = Frame::left_aligned(
|
)
|
||||||
TR::tutorial__title_handy_menu.into(),
|
.with_menu_button()
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
.button_styled(theme::button_warning_low())
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
.with_footer(
|
||||||
TR::tutorial__menu,
|
TR::instructions__swipe_up.into(),
|
||||||
))),
|
Some(TR::buttons__continue.into()),
|
||||||
)
|
)
|
||||||
.with_menu_button()
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
.button_styled(theme::button_warning_low())
|
.with_swipe(Direction::Down, SwipeSettings::default())
|
||||||
.with_footer(
|
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info));
|
||||||
TR::instructions__swipe_up.into(),
|
|
||||||
Some(TR::buttons__continue.into()),
|
let content_step_hold = Frame::left_aligned(
|
||||||
)
|
TR::tutorial__title_hold.into(),
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
SwipeContent::new(PromptScreen::new_hold_to_confirm()),
|
||||||
.with_swipe(Direction::Down, SwipeSettings::default())
|
)
|
||||||
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info));
|
.with_footer(TR::instructions__hold_to_exit_tutorial.into(), None)
|
||||||
|
.map(|msg| {
|
||||||
let content_step_hold = Frame::left_aligned(
|
matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed)
|
||||||
TR::tutorial__title_hold.into(),
|
});
|
||||||
SwipeContent::new(PromptScreen::new_hold_to_confirm()),
|
|
||||||
)
|
let content_step_done = Frame::left_aligned(
|
||||||
.with_footer(TR::instructions__hold_to_exit_tutorial.into(), None)
|
TR::tutorial__title_well_done.into(),
|
||||||
.map(|msg| {
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed)
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
});
|
TR::tutorial__ready_to_use_safe5,
|
||||||
|
))),
|
||||||
let content_step_done = Frame::left_aligned(
|
)
|
||||||
TR::tutorial__title_well_done.into(),
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
.map(|_| None);
|
||||||
TR::tutorial__ready_to_use_safe5,
|
|
||||||
))),
|
let content_menu = Frame::left_aligned(
|
||||||
)
|
"".into(),
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
VerticalMenu::empty()
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.item(theme::ICON_CHEVRON_RIGHT, TR::tutorial__did_you_know.into())
|
||||||
.map(|_| None);
|
.item(theme::ICON_REBOOT, TR::tutorial__restart_tutorial.into())
|
||||||
|
.danger(theme::ICON_CANCEL, TR::tutorial__exit.into()),
|
||||||
let content_menu = Frame::left_aligned(
|
)
|
||||||
"".into(),
|
.with_cancel_button()
|
||||||
VerticalMenu::empty()
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
.item(theme::ICON_CHEVRON_RIGHT, TR::tutorial__did_you_know.into())
|
.with_swipe(Direction::Left, SwipeSettings::immediate())
|
||||||
.item(theme::ICON_REBOOT, TR::tutorial__restart_tutorial.into())
|
.map(|msg| match msg {
|
||||||
.danger(theme::ICON_CANCEL, TR::tutorial__exit.into()),
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
)
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
.with_cancel_button()
|
});
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
|
||||||
.with_swipe(Direction::Left, SwipeSettings::immediate())
|
let content_did_you_know = Frame::left_aligned(
|
||||||
.map(|msg| match msg {
|
"".into(),
|
||||||
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
&theme::TEXT_MAIN_GREY_LIGHT,
|
||||||
});
|
TR::tutorial__first_wallet,
|
||||||
|
))),
|
||||||
let content_did_you_know = Frame::left_aligned(
|
)
|
||||||
"".into(),
|
.with_cancel_button()
|
||||||
SwipeContent::new(Paragraphs::new(Paragraph::new(
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
&theme::TEXT_MAIN_GREY_LIGHT,
|
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Cancelled));
|
||||||
TR::tutorial__first_wallet,
|
|
||||||
))),
|
let content_hold_to_exit = Frame::left_aligned(
|
||||||
)
|
TR::tutorial__title_hold.into(),
|
||||||
.with_cancel_button()
|
SwipeContent::new(PromptScreen::new_hold_to_confirm_danger()),
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
)
|
||||||
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Cancelled));
|
.with_footer(TR::instructions__hold_to_exit_tutorial.into(), None)
|
||||||
|
.map(|msg| {
|
||||||
let content_hold_to_exit = Frame::left_aligned(
|
matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed)
|
||||||
TR::tutorial__title_hold.into(),
|
});
|
||||||
SwipeContent::new(PromptScreen::new_hold_to_confirm_danger()),
|
|
||||||
)
|
let res = SwipeFlow::new(&ShowTutorial::StepWelcome)?
|
||||||
.with_footer(TR::instructions__hold_to_exit_tutorial.into(), None)
|
.with_page(&ShowTutorial::StepWelcome, content_step_welcome)?
|
||||||
.map(|msg| {
|
.with_page(&ShowTutorial::StepBegin, content_step_begin)?
|
||||||
matches!(msg, FrameMsg::Content(PromptMsg::Confirmed)).then_some(FlowMsg::Confirmed)
|
.with_page(&ShowTutorial::StepNavigation, content_step_navigation)?
|
||||||
});
|
.with_page(&ShowTutorial::StepMenu, content_step_menu)?
|
||||||
|
.with_page(&ShowTutorial::StepHold, content_step_hold)?
|
||||||
let res = SwipeFlow::new(&ShowTutorial::StepWelcome)?
|
.with_page(&ShowTutorial::StepDone, content_step_done)?
|
||||||
.with_page(&ShowTutorial::StepWelcome, content_step_welcome)?
|
.with_page(&ShowTutorial::Menu, content_menu)?
|
||||||
.with_page(&ShowTutorial::StepBegin, content_step_begin)?
|
.with_page(&ShowTutorial::DidYouKnow, content_did_you_know)?
|
||||||
.with_page(&ShowTutorial::StepNavigation, content_step_navigation)?
|
.with_page(&ShowTutorial::HoldToExit, content_hold_to_exit)?;
|
||||||
.with_page(&ShowTutorial::StepMenu, content_step_menu)?
|
Ok(res)
|
||||||
.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_root(res)?.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error,
|
error,
|
||||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
@ -14,13 +13,11 @@ use crate::{
|
|||||||
FlowController, FlowMsg, SwipeFlow,
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
},
|
},
|
||||||
geometry::Direction,
|
geometry::Direction,
|
||||||
layout::obj::LayoutObj,
|
|
||||||
model_mercury::component::SwipeContent,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::super::{
|
use super::super::{
|
||||||
component::{Frame, FrameMsg, StatusScreen, VerticalMenu, VerticalMenuChoiceMsg},
|
component::{Frame, FrameMsg, StatusScreen, SwipeContent, VerticalMenu, VerticalMenuChoiceMsg},
|
||||||
theme,
|
theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,70 +55,60 @@ impl FlowController for WarningHiPrio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
const EXTRA_PADDING: i16 = 6;
|
||||||
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) }
|
pub fn new_warning_hi_prio(
|
||||||
}
|
title: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
impl WarningHiPrio {
|
value: TString<'static>,
|
||||||
const EXTRA_PADDING: i16 = 6;
|
verb_cancel: Option<TString<'static>>,
|
||||||
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Error> {
|
let confirm: TString = TR::words__continue_anyway_question.into();
|
||||||
let title: TString = kwargs.get_or(Qstr::MP_QSTR_title, TR::words__warning.into())?;
|
let done_title: TString = TR::words__operation_cancelled.into();
|
||||||
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
|
||||||
let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
|
let verb_cancel = verb_cancel.unwrap_or(TR::words__cancel_and_exit.into());
|
||||||
let verb_cancel: Option<TString> = kwargs
|
|
||||||
.get(Qstr::MP_QSTR_verb_cancel)
|
// Message
|
||||||
.unwrap_or_else(|_| Obj::const_none())
|
let paragraphs = [
|
||||||
.try_into_option()?;
|
Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description),
|
||||||
let confirm: TString = TR::words__continue_anyway.into();
|
Paragraph::new(&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, value).with_top_padding(EXTRA_PADDING),
|
||||||
let done_title: TString = TR::words__operation_cancelled.into();
|
]
|
||||||
|
.into_paragraphs();
|
||||||
let verb_cancel = verb_cancel.unwrap_or(TR::words__cancel_and_exit.into());
|
let content_message = Frame::left_aligned(title, SwipeContent::new(paragraphs))
|
||||||
|
.with_menu_button()
|
||||||
// Message
|
.with_footer(TR::instructions__swipe_up.into(), Some(verb_cancel))
|
||||||
let paragraphs = [
|
.with_danger()
|
||||||
Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description),
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
Paragraph::new(&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, value)
|
.with_swipe(Direction::Left, SwipeSettings::default())
|
||||||
.with_top_padding(Self::EXTRA_PADDING),
|
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info));
|
||||||
]
|
// .one_button_request(ButtonRequestCode::Warning, br_name);
|
||||||
.into_paragraphs();
|
|
||||||
let content_message = Frame::left_aligned(title, SwipeContent::new(paragraphs))
|
// Menu
|
||||||
.with_menu_button()
|
let content_menu = Frame::left_aligned(
|
||||||
.with_footer(TR::instructions__swipe_up.into(), Some(verb_cancel))
|
"".into(),
|
||||||
.with_danger()
|
VerticalMenu::empty()
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
.item(theme::ICON_CANCEL, verb_cancel)
|
||||||
.with_swipe(Direction::Left, SwipeSettings::default())
|
.danger(theme::ICON_CHEVRON_RIGHT, confirm),
|
||||||
.map(|msg| matches!(msg, FrameMsg::Button(_)).then_some(FlowMsg::Info));
|
)
|
||||||
// .one_button_request(ButtonRequestCode::Warning, br_name);
|
.with_cancel_button()
|
||||||
|
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
||||||
// Menu
|
.map(|msg| match msg {
|
||||||
let content_menu = Frame::left_aligned(
|
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||||
"".into(),
|
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||||
VerticalMenu::empty()
|
});
|
||||||
.item(theme::ICON_CANCEL, verb_cancel)
|
|
||||||
.danger(theme::ICON_CHEVRON_RIGHT, confirm),
|
// Cancelled
|
||||||
)
|
let content_cancelled = Frame::left_aligned(
|
||||||
.with_cancel_button()
|
TR::words__title_done.into(),
|
||||||
.with_swipe(Direction::Right, SwipeSettings::immediate())
|
StatusScreen::new_neutral_timeout(done_title),
|
||||||
.map(|msg| match msg {
|
)
|
||||||
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
.with_footer(TR::instructions__continue_in_app.into(), None)
|
||||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREY_DARK)
|
||||||
});
|
.map(|_| Some(FlowMsg::Cancelled));
|
||||||
|
|
||||||
// Cancelled
|
let res = SwipeFlow::new(&WarningHiPrio::Message)?
|
||||||
let content_cancelled = Frame::left_aligned(
|
.with_page(&WarningHiPrio::Message, content_message)?
|
||||||
TR::words__title_done.into(),
|
.with_page(&WarningHiPrio::Menu, content_menu)?
|
||||||
StatusScreen::new_neutral_timeout(done_title),
|
.with_page(&WarningHiPrio::Cancelled, content_cancelled)?;
|
||||||
)
|
Ok(res)
|
||||||
.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_root(res)?.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use core::{cmp::Ordering, convert::TryInto};
|
use core::{cmp::Ordering, convert::TryInto};
|
||||||
|
use heapless::Vec;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
component::{
|
component::{
|
||||||
@ -15,7 +16,7 @@ use crate::{
|
|||||||
io::BinaryData,
|
io::BinaryData,
|
||||||
micropython::{
|
micropython::{
|
||||||
iter::IterBuf,
|
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,
|
map::Map,
|
||||||
module::Module,
|
module::Module,
|
||||||
obj::Obj,
|
obj::Obj,
|
||||||
@ -247,6 +248,8 @@ extern "C" fn new_confirm_emphasized(n_args: usize, args: *const Obj, kwargs: *m
|
|||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.and_then(LayoutObj::new_root)
|
||||||
|
.map(Into::into)
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -316,12 +319,46 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
.with_chunkify(chunkify)
|
.with_chunkify(chunkify)
|
||||||
.with_page_limit(page_limit)
|
.with_page_limit(page_limit)
|
||||||
.into_flow()
|
.into_flow()
|
||||||
.and_then(LayoutObj::new)
|
.and_then(LayoutObj::new_root)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
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<TString> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
|
||||||
|
let description: Option<TString> =
|
||||||
|
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
|
||||||
|
let subtitle: Option<TString> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_subtitle)
|
||||||
|
.unwrap_or(Obj::const_none())
|
||||||
|
.try_into_option()?;
|
||||||
|
let verb_cancel: Option<TString> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_verb_cancel)
|
||||||
|
.unwrap_or_else(|_| Obj::const_none())
|
||||||
|
.try_into_option()?;
|
||||||
|
let 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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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 {
|
extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||||
@ -348,13 +385,31 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
|
|||||||
}
|
}
|
||||||
.into_paragraphs();
|
.into_paragraphs();
|
||||||
|
|
||||||
new_confirm_action_simple(
|
flow::new_confirm_action_simple(
|
||||||
paragraphs,
|
paragraphs,
|
||||||
ConfirmActionMenu::new(None, false, None),
|
ConfirmActionMenu::new(None, false, None),
|
||||||
ConfirmActionStrings::new(title, None, None, None),
|
ConfirmActionStrings::new(title, None, None, None),
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.and_then(LayoutObj::new_root)
|
||||||
|
.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)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.into())
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -379,6 +434,8 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
|
|||||||
hold,
|
hold,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.and_then(LayoutObj::new_root)
|
||||||
|
.map(Into::into)
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -411,6 +468,8 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
|
|||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.and_then(LayoutObj::new_root)
|
||||||
|
.map(Into::into)
|
||||||
} else {
|
} else {
|
||||||
if !check_homescreen_format(jpeg) {
|
if !check_homescreen_format(jpeg) {
|
||||||
return Err(value_error!(c"Invalid image."));
|
return Err(value_error!(c"Invalid image."));
|
||||||
@ -433,6 +492,123 @@ 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) }
|
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)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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<TString> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?;
|
||||||
|
let subtitle: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?;
|
||||||
|
|
||||||
|
let account: Option<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
|
||||||
|
let account_path: Option<TString> =
|
||||||
|
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<Obj> = 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<Obj> = kwargs.get(Qstr::MP_QSTR_address)?.try_into_option()?;
|
||||||
|
let address_title: Option<TString> =
|
||||||
|
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<TString> =
|
||||||
|
kwargs.get(Qstr::MP_QSTR_summary_title)?.try_into_option()?;
|
||||||
|
let summary_br_name: Option<TString> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_summary_br_name)?
|
||||||
|
.try_into_option()?;
|
||||||
|
let summary_br_code: Option<u16> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_summary_br_code)?
|
||||||
|
.try_into_option()?;
|
||||||
|
|
||||||
|
let cancel_text: Option<TString> =
|
||||||
|
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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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<TString> =
|
||||||
|
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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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 {
|
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 block = move |_args: &[Obj], kwargs: &Map| {
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||||
@ -475,7 +651,7 @@ extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
|
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
|
||||||
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
|
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?;
|
||||||
|
|
||||||
let _verb: Option<TString> = kwargs
|
let verb: Option<TString> = kwargs
|
||||||
.get(Qstr::MP_QSTR_verb)
|
.get(Qstr::MP_QSTR_verb)
|
||||||
.unwrap_or_else(|_| Obj::const_none())
|
.unwrap_or_else(|_| Obj::const_none())
|
||||||
.try_into_option()?;
|
.try_into_option()?;
|
||||||
@ -497,7 +673,7 @@ extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
.with_prompt(hold)
|
.with_prompt(hold)
|
||||||
.with_hold(hold)
|
.with_hold(hold)
|
||||||
.into_flow()
|
.into_flow()
|
||||||
.and_then(LayoutObj::new)
|
.and_then(LayoutObj::new_root)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
@ -523,6 +699,8 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.and_then(LayoutObj::new_root)
|
||||||
|
.map(Into::into)
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -623,8 +801,39 @@ extern "C" fn new_show_error(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
|||||||
};
|
};
|
||||||
|
|
||||||
let frame = SwipeUpScreen::new(frame);
|
let frame = SwipeUpScreen::new(frame);
|
||||||
let obj = LayoutObj::new(frame)?;
|
Ok(LayoutObj::new(frame)?.into())
|
||||||
Ok(obj.into())
|
};
|
||||||
|
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<TString, 33> = util::iter_into_vec(share_words_obj)?;
|
||||||
|
let description: Option<TString> = 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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.into())
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -653,8 +862,7 @@ extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
frame.with_warning_low_icon()
|
frame.with_warning_low_icon()
|
||||||
};
|
};
|
||||||
|
|
||||||
let obj = LayoutObj::new(SwipeUpScreen::new(frame_with_icon))?;
|
Ok(LayoutObj::new(SwipeUpScreen::new(frame_with_icon))?.into())
|
||||||
Ok(obj.into())
|
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -812,6 +1020,130 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut
|
|||||||
true,
|
true,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
.and_then(LayoutObj::new_root)
|
||||||
|
.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<TString> = kwargs.get(Qstr::MP_QSTR_subtext)?.try_into_option()?; // #shares remaining
|
||||||
|
let pages: Option<Obj> = 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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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<TString> =
|
||||||
|
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
|
||||||
|
let extra: Option<TString> = 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<TString> = kwargs.get(Qstr::MP_QSTR_account)?.try_into_option()?;
|
||||||
|
let path: Option<TString> = 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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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_root(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,
|
||||||
|
)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.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()?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.into())
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -827,8 +1159,7 @@ extern "C" fn new_request_pin(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let obj = LayoutObj::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel))?;
|
Ok(LayoutObj::new(PinKeyboard::new(prompt, subprompt, warning, allow_cancel))?.into())
|
||||||
Ok(obj.into())
|
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -872,8 +1203,7 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
|||||||
|
|
||||||
let content = VerticalMenu::select_word(words);
|
let content = VerticalMenu::select_word(words);
|
||||||
let frame_with_menu = Frame::left_aligned(title, content).with_subtitle(description);
|
let frame_with_menu = Frame::left_aligned(title, content).with_subtitle(description);
|
||||||
let obj = LayoutObj::new(frame_with_menu)?;
|
Ok(LayoutObj::new(frame_with_menu)?.into())
|
||||||
Ok(obj.into())
|
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -919,6 +1249,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) }
|
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_root(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 {
|
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 block = move |_args: &[Obj], kwargs: &Map| {
|
||||||
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
let recovery_type: RecoveryType = kwargs.get(Qstr::MP_QSTR_recovery_type)?.try_into()?;
|
||||||
@ -980,8 +1319,7 @@ extern "C" fn new_show_progress(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
(description, "".into())
|
(description, "".into())
|
||||||
};
|
};
|
||||||
|
|
||||||
let obj = LayoutObj::new(Progress::new(title, indeterminate, description))?;
|
Ok(LayoutObj::new(Progress::new(title, indeterminate, description))?.into())
|
||||||
Ok(obj.into())
|
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
@ -1063,8 +1401,7 @@ pub extern "C" fn upy_check_homescreen_format(data: Obj) -> Obj {
|
|||||||
extern "C" fn new_show_wait_text(message: Obj) -> Obj {
|
extern "C" fn new_show_wait_text(message: Obj) -> Obj {
|
||||||
let block = || {
|
let block = || {
|
||||||
let message: TString<'static> = message.try_into()?;
|
let message: TString<'static> = message.try_into()?;
|
||||||
let obj = LayoutObj::new(Connect::new(message, theme::FG, theme::BG))?;
|
Ok(LayoutObj::new(Connect::new(message, theme::FG, theme::BG))?.into())
|
||||||
Ok(obj.into())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe { util::try_or_raise(block) }
|
unsafe { util::try_or_raise(block) }
|
||||||
@ -1077,6 +1414,22 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
panic!();
|
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 verb_cancel: Option<TString> = kwargs
|
||||||
|
.get(Qstr::MP_QSTR_verb_cancel)
|
||||||
|
.unwrap_or_else(|_| Obj::const_none())
|
||||||
|
.try_into_option()?;
|
||||||
|
|
||||||
|
let flow = flow::warning_hi_prio::new_warning_hi_prio(title, description, value, verb_cancel)?;
|
||||||
|
Ok(LayoutObj::new_root(flow)?.into())
|
||||||
|
};
|
||||||
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub static mp_module_trezorui2: Module = obj_module! {
|
pub static mp_module_trezorui2: Module = obj_module! {
|
||||||
/// from trezor import utils
|
/// from trezor import utils
|
||||||
@ -1114,7 +1467,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// prompt_title: str | None = None,
|
/// prompt_title: str | None = None,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Confirm action."""
|
/// """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(
|
/// def confirm_emphasized(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1179,7 +1532,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
|
|
||||||
/// def flow_confirm_reset(recovery: bool) -> LayoutObj[UiResult]:
|
/// def flow_confirm_reset(recovery: bool) -> LayoutObj[UiResult]:
|
||||||
/// """Confirm TOS before creating wallet creation or wallet recovery."""
|
/// """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
|
// TODO: supply more arguments for Wipe code setting when figma done
|
||||||
/// def flow_confirm_set_new_pin(
|
/// def flow_confirm_set_new_pin(
|
||||||
@ -1188,7 +1541,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// description: str,
|
/// description: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Confirm new PIN setup with an option to cancel action."""
|
/// """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(
|
/// def show_info_with_cancel(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1363,7 +1716,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// max_len: int,
|
/// max_len: int,
|
||||||
/// ) -> LayoutObj[str | UiResult]:
|
/// ) -> LayoutObj[str | UiResult]:
|
||||||
/// """Passphrase input keyboard."""
|
/// """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(
|
/// def request_bip39(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1395,7 +1748,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
|
|
||||||
/// def flow_prompt_backup() -> LayoutObj[UiResult]:
|
/// def flow_prompt_backup() -> LayoutObj[UiResult]:
|
||||||
/// """Prompt a user to create backup with an option to skip."""
|
/// """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(
|
/// def flow_show_share_words(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1408,7 +1761,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Show wallet backup words preceded by an instruction screen and followed by
|
/// """Show wallet backup words preceded by an instruction screen and followed by
|
||||||
/// confirmation."""
|
/// 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(
|
/// def flow_request_number(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1421,16 +1774,16 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// br_code: ButtonRequestType,
|
/// br_code: ButtonRequestType,
|
||||||
/// br_name: str,
|
/// br_name: str,
|
||||||
/// ) -> LayoutObj[tuple[UiResult, int]]:
|
/// ) -> LayoutObj[tuple[UiResult, int]]:
|
||||||
/// """Numer input with + and - buttons, description, and context menu with cancel and
|
/// """Number input with + and - buttons, description, and context menu with cancel and
|
||||||
/// info."""
|
/// 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(
|
/// def set_brightness(
|
||||||
/// *,
|
/// *,
|
||||||
/// current: int | None = None
|
/// current: int | None = None
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Show the brightness configuration dialog."""
|
/// """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(
|
/// def show_checklist(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1452,7 +1805,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// pages: Iterable[tuple[str, str]] | None = None,
|
/// pages: Iterable[tuple[str, str]] | None = None,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Device recovery homescreen."""
|
/// """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(
|
/// def select_word_count(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1518,11 +1871,11 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// fingerprint: str,
|
/// fingerprint: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Ask whether to update firmware, optionally show fingerprint."""
|
/// """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]:
|
/// def tutorial() -> LayoutObj[UiResult]:
|
||||||
/// """Show user how to interact with the device."""
|
/// """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]:
|
/// def show_wait_text(message: str, /) -> LayoutObj[None]:
|
||||||
/// """Show single-line text in the middle of the screen."""
|
/// """Show single-line text in the middle of the screen."""
|
||||||
@ -1545,7 +1898,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// br_name: str,
|
/// br_name: str,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Get address / receive funds."""
|
/// """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(
|
/// def flow_warning_hi_prio(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1555,7 +1908,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// verb_cancel: str | None = None,
|
/// verb_cancel: str | None = None,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Warning modal with multiple steps to confirm."""
|
/// """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(
|
/// def flow_confirm_output(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1579,7 +1932,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// cancel_text: str | None = None,
|
/// cancel_text: str | None = None,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Confirm the recipient, (optionally) confirm the amount and (optionally) confirm the summary and present a Hold to Sign page."""
|
/// """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(
|
/// def flow_confirm_summary(
|
||||||
/// *,
|
/// *,
|
||||||
@ -1593,7 +1946,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// cancel_text: str | None = None,
|
/// cancel_text: str | None = None,
|
||||||
/// ) -> LayoutObj[UiResult]:
|
/// ) -> LayoutObj[UiResult]:
|
||||||
/// """Total summary and hold to confirm."""
|
/// """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:
|
/// class BacklightLevels:
|
||||||
/// """Backlight levels. Values dynamically update based on user settings."""
|
/// """Backlight levels. Values dynamically update based on user settings."""
|
||||||
|
@ -366,7 +366,7 @@ def flow_request_number(
|
|||||||
br_code: ButtonRequestType,
|
br_code: ButtonRequestType,
|
||||||
br_name: str,
|
br_name: str,
|
||||||
) -> LayoutObj[tuple[UiResult, int]]:
|
) -> LayoutObj[tuple[UiResult, int]]:
|
||||||
"""Numer input with + and - buttons, description, and context menu with cancel and
|
"""Number input with + and - buttons, description, and context menu with cancel and
|
||||||
info."""
|
info."""
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user