mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-01 20:08:26 +00:00
refactor(core): move confirm_action to UiFeatures
This commit is contained in:
parent
cd32737141
commit
3188f8a1aa
@ -13,7 +13,8 @@ use crate::{
|
||||
layout::{
|
||||
base::LAYOUT_STATE,
|
||||
obj::{LayoutObj, ATTACH_TYPE_OBJ},
|
||||
result::{CANCELLED, CONFIRMED, INFO}, util::upy_disable_animation,
|
||||
result::{CANCELLED, CONFIRMED, INFO},
|
||||
util::upy_disable_animation,
|
||||
},
|
||||
ui_features::ModelUI,
|
||||
ui_features_fw::UIFeaturesFirmware,
|
||||
@ -24,6 +25,51 @@ use crate::{
|
||||
// UIFeaturesFirmware`
|
||||
// NOTE: `disable_animation` not a part of trait UiFeaturesFirmware
|
||||
|
||||
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_else(|_| Obj::const_none())
|
||||
.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 hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
|
||||
let hold_danger: bool = kwargs.get_or(Qstr::MP_QSTR_hold_danger, false)?;
|
||||
let reverse: bool = kwargs.get_or(Qstr::MP_QSTR_reverse, false)?;
|
||||
let prompt_screen: bool = kwargs.get_or(Qstr::MP_QSTR_prompt_screen, false)?;
|
||||
let prompt_title: Option<TString> = kwargs
|
||||
.get(Qstr::MP_QSTR_prompt_title)
|
||||
.unwrap_or_else(|_| Obj::const_none())
|
||||
.try_into_option()?;
|
||||
|
||||
let layout = ModelUI::confirm_action(
|
||||
title,
|
||||
action,
|
||||
description,
|
||||
subtitle,
|
||||
verb,
|
||||
verb_cancel,
|
||||
hold,
|
||||
hold_danger,
|
||||
reverse,
|
||||
prompt_screen,
|
||||
prompt_title,
|
||||
)?;
|
||||
Ok(LayoutObj::new_root(layout)?.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_request_bip39(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()?;
|
||||
@ -200,6 +246,23 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
||||
/// """Disable animations, debug builds only."""
|
||||
Qstr::MP_QSTR_disable_animation => obj_fn_1!(upy_disable_animation).as_obj(),
|
||||
|
||||
/// def confirm_action(
|
||||
/// *,
|
||||
/// title: str,
|
||||
/// action: str | None,
|
||||
/// description: str | None,
|
||||
/// subtitle: str | None = None,
|
||||
/// verb: str | None = None,
|
||||
/// verb_cancel: str | None = None,
|
||||
/// hold: bool = False,
|
||||
/// hold_danger: bool = False,
|
||||
/// reverse: bool = False,
|
||||
/// prompt_screen: bool = False,
|
||||
/// prompt_title: str | None = None,
|
||||
/// ) -> LayoutObj[UiResult]:
|
||||
/// """Confirm action."""
|
||||
Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(),
|
||||
|
||||
/// def request_bip39(
|
||||
/// *,
|
||||
/// prompt: str,
|
||||
|
@ -358,40 +358,6 @@ extern "C" fn new_confirm_blob_intro(n_args: usize, args: *const Obj, kwargs: *m
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_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)?;
|
||||
|
||||
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 {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
@ -1881,5 +1847,5 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// cancel_text: str | None = None,
|
||||
/// ) -> LayoutObj[UiResult]:
|
||||
/// """Total summary and hold to confirm."""
|
||||
Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, flow::new_confirm_summary).as_obj(),
|
||||
Qstr::MP_QSTR_flow_confirm_summary => obj_fn_kw!(0, new_confirm_summary).as_obj(),
|
||||
};
|
||||
|
@ -18,7 +18,8 @@ use crate::{
|
||||
use super::{
|
||||
component::{
|
||||
Bip39Input, Frame, MnemonicKeyboard, PinKeyboard, Slip39Input, SwipeContent, SwipeUpScreen,
|
||||
}, flow, theme, ModelMercuryFeatures
|
||||
},
|
||||
flow, theme, ModelMercuryFeatures,
|
||||
};
|
||||
|
||||
impl UIFeaturesFirmware for ModelMercuryFeatures {
|
||||
|
@ -270,42 +270,6 @@ fn content_in_button_page<T: Component + Paginate + MaybeTrace + 'static>(
|
||||
Ok(obj.into())
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = |_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 verb: TString<'static> =
|
||||
kwargs.get_or(Qstr::MP_QSTR_verb, TR::buttons__confirm.into())?;
|
||||
let verb_cancel: Option<TString<'static>> = 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 paragraphs = {
|
||||
let action = action.unwrap_or("".into());
|
||||
let description = description.unwrap_or("".into());
|
||||
let mut paragraphs = ParagraphVecShort::new();
|
||||
if !reverse {
|
||||
paragraphs
|
||||
.add(Paragraph::new(&theme::TEXT_BOLD, action))
|
||||
.add(Paragraph::new(&theme::TEXT_NORMAL, description));
|
||||
} else {
|
||||
paragraphs
|
||||
.add(Paragraph::new(&theme::TEXT_NORMAL, description))
|
||||
.add(Paragraph::new(&theme::TEXT_BOLD, action));
|
||||
}
|
||||
paragraphs.into_paragraphs()
|
||||
};
|
||||
|
||||
content_in_button_page(title, paragraphs, verb, verb_cancel, hold)
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
|
@ -6,8 +6,8 @@ use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
ComponentExt, Timeout,
|
||||
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, Paragraphs, VecExt},
|
||||
Component, ComponentExt, Paginate, Timeout,
|
||||
},
|
||||
layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
|
||||
ui_features_fw::UIFeaturesFirmware,
|
||||
@ -15,7 +15,10 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
component::{Frame, PassphraseEntry, PinEntry, WordlistEntry, WordlistType},
|
||||
component::{
|
||||
ButtonDetails, ButtonPage, Frame, PassphraseEntry, PinEntry, ScrollableFrame,
|
||||
WordlistEntry, WordlistType,
|
||||
},
|
||||
theme, ModelTRFeatures,
|
||||
};
|
||||
|
||||
@ -135,3 +138,40 @@ impl UIFeaturesFirmware for ModelTRFeatures {
|
||||
Ok(obj)
|
||||
}
|
||||
}
|
||||
|
||||
/// Function to create and call a `ButtonPage` dialog based on paginable content
|
||||
/// (e.g. `Paragraphs` or `FormattedText`).
|
||||
/// Has optional title (supply empty `TString` for that) and hold-to-confirm
|
||||
/// functionality.
|
||||
fn content_in_button_page<T: Component + Paginate + MaybeTrace + 'static>(
|
||||
title: TString<'static>,
|
||||
content: T,
|
||||
verb: TString<'static>,
|
||||
verb_cancel: Option<TString<'static>>,
|
||||
hold: bool,
|
||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||
// Left button - icon, text or nothing.
|
||||
let cancel_btn = verb_cancel.map(ButtonDetails::from_text_possible_icon);
|
||||
|
||||
// Right button - text or nothing.
|
||||
// Optional HoldToConfirm
|
||||
let mut confirm_btn = if !verb.is_empty() {
|
||||
Some(ButtonDetails::text(verb))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if hold {
|
||||
confirm_btn = confirm_btn.map(|btn| btn.with_default_duration());
|
||||
}
|
||||
|
||||
let content = ButtonPage::new(content, theme::BG)
|
||||
.with_cancel_btn(cancel_btn)
|
||||
.with_confirm_btn(confirm_btn);
|
||||
|
||||
let mut frame = ScrollableFrame::new(content);
|
||||
if !title.is_empty() {
|
||||
frame = frame.with_title(title);
|
||||
}
|
||||
|
||||
Ok(RootComponent::new(frame))
|
||||
}
|
||||
|
@ -317,54 +317,6 @@ impl ComponentMsgObj for super::component::bl_confirm::Confirm<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
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 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 paragraphs = {
|
||||
let action = action.unwrap_or("".into());
|
||||
let description = description.unwrap_or("".into());
|
||||
let mut paragraphs = ParagraphVecShort::new();
|
||||
if !reverse {
|
||||
paragraphs
|
||||
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, action))
|
||||
.add(Paragraph::new(&theme::TEXT_NORMAL, description));
|
||||
} else {
|
||||
paragraphs
|
||||
.add(Paragraph::new(&theme::TEXT_NORMAL, description))
|
||||
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, action));
|
||||
}
|
||||
paragraphs.into_paragraphs()
|
||||
};
|
||||
|
||||
let mut page = if hold {
|
||||
ButtonPage::new(paragraphs, theme::BG).with_hold()?
|
||||
} else {
|
||||
ButtonPage::new(paragraphs, theme::BG).with_cancel_confirm(verb_cancel, verb)
|
||||
};
|
||||
if hold && hold_danger {
|
||||
page = page.with_confirm_style(theme::button_danger())
|
||||
}
|
||||
let obj = LayoutObj::new(Frame::left_aligned(theme::label_title(), title, page))?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_emphasized(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()?;
|
||||
@ -1561,23 +1513,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// from trezorui_api import *
|
||||
///
|
||||
|
||||
/// def confirm_action(
|
||||
/// *,
|
||||
/// title: str,
|
||||
/// action: str | None,
|
||||
/// description: str | None,
|
||||
/// subtitle: str | None = None,
|
||||
/// verb: str | None = None,
|
||||
/// verb_cancel: str | None = None,
|
||||
/// hold: bool = False,
|
||||
/// hold_danger: bool = False,
|
||||
/// reverse: bool = False,
|
||||
/// prompt_screen: bool = False,
|
||||
/// prompt_title: str | None = None,
|
||||
/// ) -> LayoutObj[UiResult]:
|
||||
/// """Confirm action."""
|
||||
Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(),
|
||||
|
||||
/// def confirm_emphasized(
|
||||
/// *,
|
||||
/// title: str,
|
||||
|
@ -5,7 +5,11 @@ use crate::{
|
||||
strutil::TString,
|
||||
translations::TR,
|
||||
ui::{
|
||||
component::{image::BlendedImage, ComponentExt, Empty, Timeout},
|
||||
component::{
|
||||
image::BlendedImage,
|
||||
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort, VecExt},
|
||||
ComponentExt, Empty, Timeout,
|
||||
},
|
||||
layout::obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
|
||||
ui_features_fw::UIFeaturesFirmware,
|
||||
},
|
||||
@ -13,8 +17,8 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
component::{
|
||||
Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, IconDialog,
|
||||
MnemonicKeyboard, PassphraseKeyboard, PinKeyboard, Slip39Input,
|
||||
Bip39Input, Button, ButtonMsg, ButtonPage, ButtonStyleSheet, CancelConfirmMsg, Frame,
|
||||
IconDialog, MnemonicKeyboard, PassphraseKeyboard, PinKeyboard, Slip39Input,
|
||||
},
|
||||
theme, ModelTTFeatures,
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ use crate::{error::Error, io::BinaryData, micropython::gc::Gc, strutil::TString}
|
||||
|
||||
use super::layout::obj::{LayoutMaybeTrace, LayoutObj};
|
||||
|
||||
|
||||
pub trait UIFeaturesFirmware {
|
||||
fn confirm_action(
|
||||
title: TString<'static>,
|
||||
|
@ -78,6 +78,24 @@ def disable_animation(disable: bool) -> None:
|
||||
"""Disable animations, debug builds only."""
|
||||
|
||||
|
||||
# rust/src/ui/api/firmware_upy.rs
|
||||
def confirm_action(
|
||||
*,
|
||||
title: str,
|
||||
action: str | None,
|
||||
description: str | None,
|
||||
subtitle: str | None = None,
|
||||
verb: str | None = None,
|
||||
verb_cancel: str | None = None,
|
||||
hold: bool = False,
|
||||
hold_danger: bool = False,
|
||||
reverse: bool = False,
|
||||
prompt_screen: bool = False,
|
||||
prompt_title: str | None = None,
|
||||
) -> LayoutObj[UiResult]:
|
||||
"""Confirm action."""
|
||||
|
||||
|
||||
# rust/src/ui/api/firmware_upy.rs
|
||||
def request_bip39(
|
||||
*,
|
||||
|
@ -44,7 +44,7 @@ def confirm_action(
|
||||
description = description.format(description_param)
|
||||
|
||||
return raise_if_not_confirmed(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=title,
|
||||
action=action,
|
||||
description=description,
|
||||
|
@ -44,7 +44,7 @@ async def confirm_fido_reset() -> bool:
|
||||
from trezor import TR
|
||||
|
||||
confirm = ui.Layout(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=TR.fido__title_reset,
|
||||
action=TR.fido__erase_credentials,
|
||||
description=TR.words__really_wanna,
|
||||
|
@ -70,7 +70,7 @@ def confirm_action(
|
||||
description = description.format(description_param)
|
||||
|
||||
return raise_if_not_confirmed(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=title,
|
||||
action=action,
|
||||
description=description,
|
||||
@ -146,7 +146,7 @@ async def prompt_backup() -> bool:
|
||||
return True
|
||||
|
||||
result = await interact(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=TR.backup__title_skip,
|
||||
action=None,
|
||||
description=TR.backup__want_to_skip,
|
||||
|
@ -34,7 +34,7 @@ async def confirm_fido(
|
||||
async def confirm_fido_reset() -> bool:
|
||||
from trezor import TR
|
||||
|
||||
confirm = trezorui2.confirm_action(
|
||||
confirm = trezorui_api.confirm_action(
|
||||
title=TR.fido__title_reset,
|
||||
description=TR.fido__wanna_erase_credentials,
|
||||
action=None,
|
||||
|
@ -42,7 +42,7 @@ def confirm_action(
|
||||
description = description.format(description_param)
|
||||
|
||||
return raise_if_not_confirmed(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=title,
|
||||
action=action,
|
||||
description=description,
|
||||
@ -108,7 +108,7 @@ async def show_wallet_created_success() -> None:
|
||||
# TODO cleanup @ redesign
|
||||
async def prompt_backup() -> bool:
|
||||
result = await interact(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=TR.words__title_success,
|
||||
action=TR.backup__new_wallet_successfully_created,
|
||||
description=TR.backup__it_should_be_backed_up,
|
||||
@ -123,7 +123,7 @@ async def prompt_backup() -> bool:
|
||||
return True
|
||||
|
||||
result = await interact(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=TR.words__warning,
|
||||
action=TR.backup__want_to_skip,
|
||||
description=TR.backup__can_back_up_anytime,
|
||||
|
@ -53,7 +53,7 @@ async def confirm_fido_reset() -> bool:
|
||||
from trezor import TR
|
||||
|
||||
confirm = ui.Layout(
|
||||
trezorui2.confirm_action(
|
||||
trezorui_api.confirm_action(
|
||||
title=TR.fido__title_reset,
|
||||
action=TR.fido__erase_credentials,
|
||||
description=TR.words__really_wanna,
|
||||
|
Loading…
Reference in New Issue
Block a user