mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-01 11:58:28 +00:00
refactor(core): move show_success/warning/error
- return type is Gc<LayoutObj> - new_show_modal removed from model_t layout.rs
This commit is contained in:
parent
e551a61e39
commit
84ca196f35
@ -741,7 +741,6 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_verb_info;
|
MP_QSTR_verb_info;
|
||||||
MP_QSTR_verify;
|
MP_QSTR_verify;
|
||||||
MP_QSTR_version;
|
MP_QSTR_version;
|
||||||
MP_QSTR_warning;
|
|
||||||
MP_QSTR_wipe__info;
|
MP_QSTR_wipe__info;
|
||||||
MP_QSTR_wipe__title;
|
MP_QSTR_wipe__title;
|
||||||
MP_QSTR_wipe__want_to_wipe;
|
MP_QSTR_wipe__want_to_wipe;
|
||||||
|
@ -299,6 +299,20 @@ 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_error(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 button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||||
|
let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
|
||||||
|
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?;
|
||||||
|
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
|
||||||
|
|
||||||
|
let layout = ModelUI::show_error(title, button, description, allow_cancel, time_ms)?;
|
||||||
|
Ok(layout.into())
|
||||||
|
};
|
||||||
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn new_show_group_share_success(
|
extern "C" fn new_show_group_share_success(
|
||||||
n_args: usize,
|
n_args: usize,
|
||||||
args: *const Obj,
|
args: *const Obj,
|
||||||
@ -418,6 +432,20 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:
|
|||||||
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_success(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 button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||||
|
let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, TString::empty())?;
|
||||||
|
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, false)?;
|
||||||
|
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
|
||||||
|
|
||||||
|
let layout = ModelUI::show_success(title, button, description, allow_cancel, time_ms)?;
|
||||||
|
Ok(layout.into())
|
||||||
|
};
|
||||||
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
|
}
|
||||||
|
|
||||||
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()?;
|
||||||
@ -429,6 +457,30 @@ extern "C" fn new_show_wait_text(message: Obj) -> Obj {
|
|||||||
unsafe { util::try_or_raise(block) }
|
unsafe { util::try_or_raise(block) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
|
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||||
|
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||||
|
let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||||
|
let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
|
||||||
|
let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
|
||||||
|
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?;
|
||||||
|
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
|
||||||
|
let danger: bool = kwargs.get_or(Qstr::MP_QSTR_danger, false)?;
|
||||||
|
|
||||||
|
let layout = ModelUI::show_warning(
|
||||||
|
title,
|
||||||
|
button,
|
||||||
|
value,
|
||||||
|
description,
|
||||||
|
allow_cancel,
|
||||||
|
time_ms,
|
||||||
|
danger,
|
||||||
|
)?;
|
||||||
|
Ok(layout.into())
|
||||||
|
};
|
||||||
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn new_tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
extern "C" fn new_tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
let block = |_args: &[Obj], _kwargs: &Map| {
|
let block = |_args: &[Obj], _kwargs: &Map| {
|
||||||
let layout = ModelUI::tutorial()?;
|
let layout = ModelUI::tutorial()?;
|
||||||
@ -700,6 +752,17 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
|||||||
/// mark next to them. Limited to 3 items."""
|
/// mark next to them. Limited to 3 items."""
|
||||||
Qstr::MP_QSTR_show_checklist => obj_fn_kw!(0, new_show_checklist).as_obj(),
|
Qstr::MP_QSTR_show_checklist => obj_fn_kw!(0, new_show_checklist).as_obj(),
|
||||||
|
|
||||||
|
/// def show_error(
|
||||||
|
/// *,
|
||||||
|
/// title: str,
|
||||||
|
/// button: str,
|
||||||
|
/// description: str = "",
|
||||||
|
/// allow_cancel: bool = True,
|
||||||
|
/// time_ms: int = 0,
|
||||||
|
/// ) -> LayoutObj[UiResult]:
|
||||||
|
/// """Error modal. No buttons shown when `button` is empty string."""
|
||||||
|
Qstr::MP_QSTR_show_error => obj_fn_kw!(0, new_show_error).as_obj(),
|
||||||
|
|
||||||
/// def show_group_share_success(
|
/// def show_group_share_success(
|
||||||
/// *,
|
/// *,
|
||||||
/// lines: Iterable[str],
|
/// lines: Iterable[str],
|
||||||
@ -771,10 +834,34 @@ pub static mp_module_trezorui_api: Module = obj_module! {
|
|||||||
/// """Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
/// """Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
||||||
Qstr::MP_QSTR_show_remaining_shares => obj_fn_kw!(0, new_show_remaining_shares).as_obj(),
|
Qstr::MP_QSTR_show_remaining_shares => obj_fn_kw!(0, new_show_remaining_shares).as_obj(),
|
||||||
|
|
||||||
|
/// def show_success(
|
||||||
|
/// *,
|
||||||
|
/// title: str,
|
||||||
|
/// button: str,
|
||||||
|
/// description: str = "",
|
||||||
|
/// allow_cancel: bool = True,
|
||||||
|
/// time_ms: int = 0,
|
||||||
|
/// ) -> LayoutObj[UiResult]:
|
||||||
|
/// """Success modal. No buttons shown when `button` is empty string."""
|
||||||
|
Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(),
|
||||||
|
|
||||||
/// def show_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."""
|
||||||
Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(),
|
Qstr::MP_QSTR_show_wait_text => obj_fn_1!(new_show_wait_text).as_obj(),
|
||||||
|
|
||||||
|
/// def show_warning(
|
||||||
|
/// *,
|
||||||
|
/// title: str,
|
||||||
|
/// button: str,
|
||||||
|
/// value: str = "",
|
||||||
|
/// description: str = "",
|
||||||
|
/// allow_cancel: bool = True,
|
||||||
|
/// time_ms: int = 0,
|
||||||
|
/// danger: bool = False, # unused on TT
|
||||||
|
/// ) -> LayoutObj[UiResult]:
|
||||||
|
/// """Warning modal. TT: No buttons shown when `button` is empty string. TR: middle button and centered text."""
|
||||||
|
Qstr::MP_QSTR_show_warning => obj_fn_kw!(0, new_show_warning).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, new_tutorial).as_obj(),
|
Qstr::MP_QSTR_tutorial => obj_fn_kw!(0, new_tutorial).as_obj(),
|
||||||
|
@ -658,32 +658,6 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
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_error(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 allow_cancel: bool = kwargs.get(Qstr::MP_QSTR_allow_cancel)?.try_into()?;
|
|
||||||
|
|
||||||
let content = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description));
|
|
||||||
let frame = if allow_cancel {
|
|
||||||
Frame::left_aligned(title, SwipeContent::new(content))
|
|
||||||
.with_cancel_button()
|
|
||||||
.with_danger()
|
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
|
||||||
} else {
|
|
||||||
Frame::left_aligned(title, SwipeContent::new(content))
|
|
||||||
.with_danger()
|
|
||||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default())
|
|
||||||
};
|
|
||||||
|
|
||||||
let frame = SwipeUpScreen::new(frame);
|
|
||||||
Ok(LayoutObj::new(frame)?.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 {
|
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 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()?;
|
||||||
@ -716,58 +690,6 @@ extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut
|
|||||||
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_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
|
||||||
let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
|
|
||||||
let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
|
|
||||||
let action: Option<TString> = kwargs.get(Qstr::MP_QSTR_button)?.try_into_option()?;
|
|
||||||
let danger: bool = kwargs.get_or(Qstr::MP_QSTR_danger, false)?;
|
|
||||||
|
|
||||||
let content = ParagraphVecShort::from_iter([
|
|
||||||
Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description),
|
|
||||||
Paragraph::new(&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, value),
|
|
||||||
])
|
|
||||||
.into_paragraphs();
|
|
||||||
|
|
||||||
let frame = Frame::left_aligned(title, SwipeContent::new(content))
|
|
||||||
.with_footer(TR::instructions__swipe_up.into(), action)
|
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default());
|
|
||||||
|
|
||||||
let frame_with_icon = if danger {
|
|
||||||
frame.with_danger_icon()
|
|
||||||
} else {
|
|
||||||
frame.with_warning_low_icon()
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(LayoutObj::new(SwipeUpScreen::new(frame_with_icon))?.into())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_show_success(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()?
|
|
||||||
.and_then(|desc: TString| if desc.is_empty() { None } else { Some(desc) });
|
|
||||||
|
|
||||||
let content = StatusScreen::new_success(title);
|
|
||||||
let obj = LayoutObj::new(SwipeUpScreen::new(
|
|
||||||
Frame::left_aligned(
|
|
||||||
TR::words__title_success.into(),
|
|
||||||
SwipeContent::new(content).with_no_attach_anim(),
|
|
||||||
)
|
|
||||||
.with_footer(TR::instructions__swipe_up.into(), description)
|
|
||||||
.with_result_icon(ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT)
|
|
||||||
.with_swipe(Direction::Up, SwipeSettings::default()),
|
|
||||||
))?;
|
|
||||||
Ok(obj.into())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
extern "C" fn new_show_simple(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 description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
|
let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
|
||||||
@ -1051,41 +973,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// """
|
/// """
|
||||||
Qstr::MP_QSTR_confirm_fido => obj_fn_kw!(0, new_confirm_fido).as_obj(),
|
Qstr::MP_QSTR_confirm_fido => obj_fn_kw!(0, new_confirm_fido).as_obj(),
|
||||||
|
|
||||||
/// def show_error(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// button: str = "CONTINUE",
|
|
||||||
/// description: str = "",
|
|
||||||
/// allow_cancel: bool = False,
|
|
||||||
/// time_ms: int = 0,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Error modal. No buttons shown when `button` is empty string."""
|
|
||||||
Qstr::MP_QSTR_show_error => obj_fn_kw!(0, new_show_error).as_obj(),
|
|
||||||
|
|
||||||
/// def show_warning(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// button: str = "CONTINUE",
|
|
||||||
/// value: str = "",
|
|
||||||
/// description: str = "",
|
|
||||||
/// allow_cancel: bool = False,
|
|
||||||
/// time_ms: int = 0,
|
|
||||||
/// danger: bool = False,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Warning modal. No buttons shown when `button` is empty string."""
|
|
||||||
Qstr::MP_QSTR_show_warning => obj_fn_kw!(0, new_show_warning).as_obj(),
|
|
||||||
|
|
||||||
/// def show_success(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// button: str = "CONTINUE",
|
|
||||||
/// description: str = "",
|
|
||||||
/// allow_cancel: bool = False,
|
|
||||||
/// time_ms: int = 0,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Success screen. Description is used in the footer."""
|
|
||||||
Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(),
|
|
||||||
|
|
||||||
/// def show_simple(
|
/// def show_simple(
|
||||||
/// *,
|
/// *,
|
||||||
/// title: str | None,
|
/// title: str | None,
|
||||||
|
@ -8,10 +8,13 @@ use crate::{
|
|||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
connect::Connect, swipe_detect::SwipeSettings, text::paragraphs::{
|
connect::Connect,
|
||||||
|
swipe_detect::SwipeSettings,
|
||||||
|
text::paragraphs::{
|
||||||
Checklist, Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort,
|
Checklist, Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort,
|
||||||
Paragraphs, VecExt,
|
Paragraphs, VecExt,
|
||||||
}, CachedJpeg, ComponentExt, Empty, Never, Timeout
|
},
|
||||||
|
CachedJpeg, ComponentExt, Empty, Never, Timeout,
|
||||||
},
|
},
|
||||||
geometry::{self, Direction},
|
geometry::{self, Direction},
|
||||||
layout::{
|
layout::{
|
||||||
@ -25,8 +28,8 @@ use crate::{
|
|||||||
use super::{
|
use super::{
|
||||||
component::{
|
component::{
|
||||||
check_homescreen_format, Bip39Input, CoinJoinProgress, Frame, Homescreen, Lockscreen,
|
check_homescreen_format, Bip39Input, CoinJoinProgress, Frame, Homescreen, Lockscreen,
|
||||||
MnemonicKeyboard, PinKeyboard, Progress, SelectWordCount, Slip39Input, SwipeContent,
|
MnemonicKeyboard, PinKeyboard, Progress, SelectWordCount, Slip39Input, StatusScreen,
|
||||||
SwipeUpScreen, VerticalMenu,
|
SwipeContent, SwipeUpScreen, VerticalMenu,
|
||||||
},
|
},
|
||||||
flow::{self, new_confirm_action_simple, ConfirmActionMenu, ConfirmActionStrings},
|
flow::{self, new_confirm_action_simple, ConfirmActionMenu, ConfirmActionStrings},
|
||||||
theme, ModelMercuryFeatures,
|
theme, ModelMercuryFeatures,
|
||||||
@ -356,6 +359,31 @@ impl UIFeaturesFirmware for ModelMercuryFeatures {
|
|||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_error(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let content = Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description));
|
||||||
|
let frame = if allow_cancel {
|
||||||
|
Frame::left_aligned(title, SwipeContent::new(content))
|
||||||
|
.with_cancel_button()
|
||||||
|
.with_danger()
|
||||||
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
|
} else {
|
||||||
|
Frame::left_aligned(title, SwipeContent::new(content))
|
||||||
|
.with_danger()
|
||||||
|
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||||
|
.with_swipe(Direction::Up, SwipeSettings::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
let obj = LayoutObj::new(SwipeUpScreen::new(frame))?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
fn show_group_share_success(
|
fn show_group_share_success(
|
||||||
lines: [TString<'static>; 4],
|
lines: [TString<'static>; 4],
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
@ -475,11 +503,70 @@ impl UIFeaturesFirmware for ModelMercuryFeatures {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_success(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
// description used in the Footer
|
||||||
|
let description = if description.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(description)
|
||||||
|
};
|
||||||
|
let content = StatusScreen::new_success(title);
|
||||||
|
let layout = LayoutObj::new(SwipeUpScreen::new(
|
||||||
|
Frame::left_aligned(
|
||||||
|
TR::words__title_success.into(),
|
||||||
|
SwipeContent::new(content).with_no_attach_anim(),
|
||||||
|
)
|
||||||
|
.with_footer(TR::instructions__swipe_up.into(), description)
|
||||||
|
.with_result_icon(theme::ICON_BULLET_CHECKMARK, theme::GREEN_LIGHT)
|
||||||
|
.with_swipe(Direction::Up, SwipeSettings::default()),
|
||||||
|
))?;
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
|
||||||
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
|
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
let layout = RootComponent::new(Connect::new(text, theme::FG, theme::BG));
|
let layout = RootComponent::new(Connect::new(text, theme::FG, theme::BG));
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_warning(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
value: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
danger: bool,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let action = if button.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(button)
|
||||||
|
};
|
||||||
|
let content = ParagraphVecShort::from_iter([
|
||||||
|
Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, description),
|
||||||
|
Paragraph::new(&theme::TEXT_MAIN_GREY_EXTRA_LIGHT, value),
|
||||||
|
])
|
||||||
|
.into_paragraphs();
|
||||||
|
|
||||||
|
let frame = Frame::left_aligned(title, SwipeContent::new(content))
|
||||||
|
.with_footer(TR::instructions__swipe_up.into(), action)
|
||||||
|
.with_swipe(Direction::Up, SwipeSettings::default());
|
||||||
|
|
||||||
|
let frame_with_icon = if danger {
|
||||||
|
frame.with_danger_icon()
|
||||||
|
} else {
|
||||||
|
frame.with_warning_low_icon()
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(LayoutObj::new(SwipeUpScreen::new(frame_with_icon))?)
|
||||||
|
}
|
||||||
|
|
||||||
fn tutorial() -> Result<impl LayoutMaybeTrace, Error> {
|
fn tutorial() -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
let flow = flow::show_tutorial::new_show_tutorial()?;
|
let flow = flow::show_tutorial::new_show_tutorial()?;
|
||||||
Ok(flow)
|
Ok(flow)
|
||||||
|
@ -842,38 +842,6 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
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_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let button: TString<'static> = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
|
||||||
let warning: TString = kwargs.get(Qstr::MP_QSTR_warning)?.try_into()?;
|
|
||||||
let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
|
||||||
|
|
||||||
let get_page = move |page_index| {
|
|
||||||
assert!(page_index == 0);
|
|
||||||
|
|
||||||
let btn_layout = ButtonLayout::none_armed_none(button);
|
|
||||||
let btn_actions = ButtonActions::none_confirm_none();
|
|
||||||
let mut ops = OpTextLayout::new(theme::TEXT_NORMAL);
|
|
||||||
ops = ops.alignment(geometry::Alignment::Center);
|
|
||||||
if !warning.is_empty() {
|
|
||||||
ops = ops.text_bold_upper(warning);
|
|
||||||
if !description.is_empty() {
|
|
||||||
ops = ops.newline();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !description.is_empty() {
|
|
||||||
ops = ops.text_normal(description);
|
|
||||||
}
|
|
||||||
let formatted = FormattedText::new(ops).vertically_centered();
|
|
||||||
Page::new(btn_layout, btn_actions, formatted)
|
|
||||||
};
|
|
||||||
let pages = FlowPages::new(get_page, 1);
|
|
||||||
let obj = LayoutObj::new(Flow::new(pages))?;
|
|
||||||
Ok(obj.into())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_show_passphrase() -> Obj {
|
extern "C" fn new_show_passphrase() -> Obj {
|
||||||
let block = move || {
|
let block = move || {
|
||||||
let text: TString = TR::passphrase__please_enter.into();
|
let text: TString = TR::passphrase__please_enter.into();
|
||||||
@ -1164,15 +1132,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// """Show multiple texts, each on its own page."""
|
/// """Show multiple texts, each on its own page."""
|
||||||
Qstr::MP_QSTR_multiple_pages_texts => obj_fn_kw!(0, new_multiple_pages_texts).as_obj(),
|
Qstr::MP_QSTR_multiple_pages_texts => obj_fn_kw!(0, new_multiple_pages_texts).as_obj(),
|
||||||
|
|
||||||
/// def show_warning(
|
|
||||||
/// *,
|
|
||||||
/// button: str,
|
|
||||||
/// warning: str,
|
|
||||||
/// description: str,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Warning modal with middle button and centered text."""
|
|
||||||
Qstr::MP_QSTR_show_warning => obj_fn_kw!(0, new_show_warning).as_obj(),
|
|
||||||
|
|
||||||
/// def show_passphrase() -> LayoutObj[UiResult]:
|
/// def show_passphrase() -> LayoutObj[UiResult]:
|
||||||
/// """Show passphrase on host dialog."""
|
/// """Show passphrase on host dialog."""
|
||||||
Qstr::MP_QSTR_show_passphrase => obj_fn_0!(new_show_passphrase).as_obj(),
|
Qstr::MP_QSTR_show_passphrase => obj_fn_0!(new_show_passphrase).as_obj(),
|
||||||
|
@ -19,6 +19,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
Component, ComponentExt, Empty, FormattedText, Label, LineBreaking, Paginate, Timeout,
|
Component, ComponentExt, Empty, FormattedText, Label, LineBreaking, Paginate, Timeout,
|
||||||
},
|
},
|
||||||
|
geometry,
|
||||||
layout::{
|
layout::{
|
||||||
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
|
obj::{LayoutMaybeTrace, LayoutObj, RootComponent},
|
||||||
util::RecoveryType,
|
util::RecoveryType,
|
||||||
@ -375,6 +376,16 @@ impl UIFeaturesFirmware for ModelTRFeatures {
|
|||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_error(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"show error not supported"))
|
||||||
|
}
|
||||||
|
|
||||||
fn show_group_share_success(
|
fn show_group_share_success(
|
||||||
lines: [TString<'static>; 4],
|
lines: [TString<'static>; 4],
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
@ -499,11 +510,54 @@ impl UIFeaturesFirmware for ModelTRFeatures {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_success(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
Err::<Gc<LayoutObj>, Error>(Error::ValueError(c"show success not supported"))
|
||||||
|
}
|
||||||
|
|
||||||
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
|
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
let layout = RootComponent::new(Connect::new(text, theme::FG, theme::BG));
|
let layout = RootComponent::new(Connect::new(text, theme::FG, theme::BG));
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_warning(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
value: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
danger: bool,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let get_page = move |page_index| {
|
||||||
|
assert!(page_index == 0);
|
||||||
|
|
||||||
|
let btn_layout = ButtonLayout::none_armed_none(button);
|
||||||
|
let btn_actions = ButtonActions::none_confirm_none();
|
||||||
|
let mut ops = OpTextLayout::new(theme::TEXT_NORMAL);
|
||||||
|
ops = ops.alignment(geometry::Alignment::Center);
|
||||||
|
if !value.is_empty() {
|
||||||
|
ops = ops.text_bold_upper(value);
|
||||||
|
if !description.is_empty() {
|
||||||
|
ops = ops.newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !description.is_empty() {
|
||||||
|
ops = ops.text_normal(description);
|
||||||
|
}
|
||||||
|
let formatted = FormattedText::new(ops).vertically_centered();
|
||||||
|
Page::new(btn_layout, btn_actions, formatted)
|
||||||
|
};
|
||||||
|
let pages = FlowPages::new(get_page, 1);
|
||||||
|
let obj = LayoutObj::new(Flow::new(pages))?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
fn tutorial() -> Result<impl LayoutMaybeTrace, Error> {
|
fn tutorial() -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
const PAGE_COUNT: usize = 7;
|
const PAGE_COUNT: usize = 7;
|
||||||
|
|
||||||
|
@ -702,89 +702,6 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_show_modal(
|
|
||||||
kwargs: &Map,
|
|
||||||
icon: BlendedImage,
|
|
||||||
button_style: ButtonStyleSheet,
|
|
||||||
) -> Result<Obj, Error> {
|
|
||||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
|
||||||
let value: TString = kwargs.get_or(Qstr::MP_QSTR_value, "".into())?;
|
|
||||||
let description: TString = kwargs.get_or(Qstr::MP_QSTR_description, "".into())?;
|
|
||||||
let button: TString = kwargs.get_or(Qstr::MP_QSTR_button, TR::buttons__continue.into())?;
|
|
||||||
let allow_cancel: bool = kwargs.get_or(Qstr::MP_QSTR_allow_cancel, true)?;
|
|
||||||
let time_ms: u32 = kwargs.get_or(Qstr::MP_QSTR_time_ms, 0)?;
|
|
||||||
|
|
||||||
let no_buttons = button.is_empty();
|
|
||||||
let obj = if no_buttons && time_ms == 0 {
|
|
||||||
// No buttons and no timer, used when we only want to draw the dialog once and
|
|
||||||
// then throw away the layout object.
|
|
||||||
LayoutObj::new(
|
|
||||||
IconDialog::new(icon, title, Empty)
|
|
||||||
.with_value(value)
|
|
||||||
.with_description(description),
|
|
||||||
)?
|
|
||||||
.into()
|
|
||||||
} else if no_buttons && time_ms > 0 {
|
|
||||||
// Timeout, no buttons.
|
|
||||||
LayoutObj::new(
|
|
||||||
IconDialog::new(
|
|
||||||
icon,
|
|
||||||
title,
|
|
||||||
Timeout::new(time_ms).map(|_| Some(CancelConfirmMsg::Confirmed)),
|
|
||||||
)
|
|
||||||
.with_value(value)
|
|
||||||
.with_description(description),
|
|
||||||
)?
|
|
||||||
.into()
|
|
||||||
} else if allow_cancel {
|
|
||||||
// Two buttons.
|
|
||||||
LayoutObj::new(
|
|
||||||
IconDialog::new(
|
|
||||||
icon,
|
|
||||||
title,
|
|
||||||
Button::cancel_confirm(
|
|
||||||
Button::with_icon(theme::ICON_CANCEL),
|
|
||||||
Button::with_text(button).styled(button_style),
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.with_value(value)
|
|
||||||
.with_description(description),
|
|
||||||
)?
|
|
||||||
.into()
|
|
||||||
} else {
|
|
||||||
// Single button.
|
|
||||||
LayoutObj::new(
|
|
||||||
IconDialog::new(
|
|
||||||
icon,
|
|
||||||
title,
|
|
||||||
theme::button_bar(Button::with_text(button).styled(button_style).map(|msg| {
|
|
||||||
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
.with_value(value)
|
|
||||||
.with_description(description),
|
|
||||||
)?
|
|
||||||
.into()
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_show_error(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let icon = BlendedImage::new(
|
|
||||||
theme::IMAGE_BG_CIRCLE,
|
|
||||||
theme::IMAGE_FG_ERROR,
|
|
||||||
theme::ERROR_COLOR,
|
|
||||||
theme::FG,
|
|
||||||
theme::BG,
|
|
||||||
);
|
|
||||||
new_show_modal(kwargs, icon, theme::button_default())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
extern "C" fn new_confirm_fido(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()?;
|
||||||
@ -816,34 +733,6 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
|
|||||||
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_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let icon = BlendedImage::new(
|
|
||||||
theme::IMAGE_BG_OCTAGON,
|
|
||||||
theme::IMAGE_FG_WARN,
|
|
||||||
theme::WARN_COLOR,
|
|
||||||
theme::FG,
|
|
||||||
theme::BG,
|
|
||||||
);
|
|
||||||
new_show_modal(kwargs, icon, theme::button_reset())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_show_success(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
|
||||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
|
||||||
let icon = BlendedImage::new(
|
|
||||||
theme::IMAGE_BG_CIRCLE,
|
|
||||||
theme::IMAGE_FG_SUCCESS,
|
|
||||||
theme::SUCCESS_COLOR,
|
|
||||||
theme::FG,
|
|
||||||
theme::BG,
|
|
||||||
);
|
|
||||||
new_show_modal(kwargs, icon, theme::button_confirm())
|
|
||||||
};
|
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn new_show_simple(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
extern "C" fn new_show_simple(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: Option<TString> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?;
|
let title: Option<TString> = kwargs.get(Qstr::MP_QSTR_title)?.try_into_option()?;
|
||||||
@ -1144,41 +1033,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// """
|
/// """
|
||||||
Qstr::MP_QSTR_confirm_fido => obj_fn_kw!(0, new_confirm_fido).as_obj(),
|
Qstr::MP_QSTR_confirm_fido => obj_fn_kw!(0, new_confirm_fido).as_obj(),
|
||||||
|
|
||||||
/// def show_error(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// button: str = "CONTINUE",
|
|
||||||
/// description: str = "",
|
|
||||||
/// allow_cancel: bool = False,
|
|
||||||
/// time_ms: int = 0,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Error modal. No buttons shown when `button` is empty string."""
|
|
||||||
Qstr::MP_QSTR_show_error => obj_fn_kw!(0, new_show_error).as_obj(),
|
|
||||||
|
|
||||||
/// def show_warning(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// button: str = "CONTINUE",
|
|
||||||
/// value: str = "",
|
|
||||||
/// description: str = "",
|
|
||||||
/// allow_cancel: bool = False,
|
|
||||||
/// time_ms: int = 0,
|
|
||||||
/// danger: bool = False, # unused on TT
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Warning modal. No buttons shown when `button` is empty string."""
|
|
||||||
Qstr::MP_QSTR_show_warning => obj_fn_kw!(0, new_show_warning).as_obj(),
|
|
||||||
|
|
||||||
/// def show_success(
|
|
||||||
/// *,
|
|
||||||
/// title: str,
|
|
||||||
/// button: str = "CONTINUE",
|
|
||||||
/// description: str = "",
|
|
||||||
/// allow_cancel: bool = False,
|
|
||||||
/// time_ms: int = 0,
|
|
||||||
/// ) -> LayoutObj[UiResult]:
|
|
||||||
/// """Success modal. No buttons shown when `button` is empty string."""
|
|
||||||
Qstr::MP_QSTR_show_success => obj_fn_kw!(0, new_show_success).as_obj(),
|
|
||||||
|
|
||||||
/// def show_simple(
|
/// def show_simple(
|
||||||
/// *,
|
/// *,
|
||||||
/// title: str | None,
|
/// title: str | None,
|
||||||
|
@ -406,6 +406,32 @@ impl UIFeaturesFirmware for ModelTTFeatures {
|
|||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_error(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let icon = BlendedImage::new(
|
||||||
|
theme::IMAGE_BG_CIRCLE,
|
||||||
|
theme::IMAGE_FG_ERROR,
|
||||||
|
theme::ERROR_COLOR,
|
||||||
|
theme::FG,
|
||||||
|
theme::BG,
|
||||||
|
);
|
||||||
|
new_show_modal(
|
||||||
|
title,
|
||||||
|
TString::empty(),
|
||||||
|
description,
|
||||||
|
button,
|
||||||
|
allow_cancel,
|
||||||
|
time_ms,
|
||||||
|
icon,
|
||||||
|
theme::button_default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn show_group_share_success(
|
fn show_group_share_success(
|
||||||
lines: [TString<'static>; 4],
|
lines: [TString<'static>; 4],
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
@ -447,7 +473,7 @@ impl UIFeaturesFirmware for ModelTTFeatures {
|
|||||||
theme::FG,
|
theme::FG,
|
||||||
theme::BG,
|
theme::BG,
|
||||||
);
|
);
|
||||||
let obj = new_show_modal(
|
new_show_modal(
|
||||||
title,
|
title,
|
||||||
TString::empty(),
|
TString::empty(),
|
||||||
description,
|
description,
|
||||||
@ -456,8 +482,7 @@ impl UIFeaturesFirmware for ModelTTFeatures {
|
|||||||
time_ms,
|
time_ms,
|
||||||
icon,
|
icon,
|
||||||
theme::button_info(),
|
theme::button_info(),
|
||||||
)?;
|
)
|
||||||
Ok(obj)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_lockscreen(
|
fn show_lockscreen(
|
||||||
@ -562,11 +587,65 @@ impl UIFeaturesFirmware for ModelTTFeatures {
|
|||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_success(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let icon = BlendedImage::new(
|
||||||
|
theme::IMAGE_BG_CIRCLE,
|
||||||
|
theme::IMAGE_FG_SUCCESS,
|
||||||
|
theme::SUCCESS_COLOR,
|
||||||
|
theme::FG,
|
||||||
|
theme::BG,
|
||||||
|
);
|
||||||
|
new_show_modal(
|
||||||
|
title,
|
||||||
|
TString::empty(),
|
||||||
|
description,
|
||||||
|
button,
|
||||||
|
allow_cancel,
|
||||||
|
time_ms,
|
||||||
|
icon,
|
||||||
|
theme::button_confirm(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
|
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
let layout = RootComponent::new(Connect::new(text, theme::FG, theme::BG));
|
let layout = RootComponent::new(Connect::new(text, theme::FG, theme::BG));
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_warning(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
value: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
danger: bool,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error> {
|
||||||
|
let icon = BlendedImage::new(
|
||||||
|
theme::IMAGE_BG_OCTAGON,
|
||||||
|
theme::IMAGE_FG_WARN,
|
||||||
|
theme::WARN_COLOR,
|
||||||
|
theme::FG,
|
||||||
|
theme::BG,
|
||||||
|
);
|
||||||
|
new_show_modal(
|
||||||
|
title,
|
||||||
|
value,
|
||||||
|
description,
|
||||||
|
button,
|
||||||
|
allow_cancel,
|
||||||
|
0,
|
||||||
|
icon,
|
||||||
|
theme::button_reset(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn tutorial() -> Result<impl LayoutMaybeTrace, Error> {
|
fn tutorial() -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
Err::<RootComponent<Empty, ModelTTFeatures>, Error>(Error::ValueError(
|
Err::<RootComponent<Empty, ModelTTFeatures>, Error>(Error::ValueError(
|
||||||
c"tutorial not supported",
|
c"tutorial not supported",
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
use crate::{error::Error, io::BinaryData, micropython::{gc::Gc, obj::Obj}, strutil::TString};
|
use crate::{
|
||||||
|
error::Error,
|
||||||
|
io::BinaryData,
|
||||||
|
micropython::{gc::Gc, obj::Obj},
|
||||||
|
strutil::TString,
|
||||||
|
};
|
||||||
|
|
||||||
use super::layout::{
|
use super::layout::{
|
||||||
obj::{LayoutMaybeTrace, LayoutObj},
|
obj::{LayoutMaybeTrace, LayoutObj},
|
||||||
@ -103,6 +108,14 @@ pub trait UIFeaturesFirmware {
|
|||||||
items: [TString<'static>; 3],
|
items: [TString<'static>; 3],
|
||||||
) -> Result<impl LayoutMaybeTrace, Error>;
|
) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
|
|
||||||
|
fn show_error(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
|
||||||
|
|
||||||
fn show_group_share_success(
|
fn show_group_share_success(
|
||||||
lines: [TString<'static>; 4],
|
lines: [TString<'static>; 4],
|
||||||
) -> Result<impl LayoutMaybeTrace, Error>;
|
) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
@ -146,7 +159,25 @@ pub trait UIFeaturesFirmware {
|
|||||||
pages_iterable: Obj, // TODO: replace Obj
|
pages_iterable: Obj, // TODO: replace Obj
|
||||||
) -> Result<impl LayoutMaybeTrace, Error>;
|
) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
|
|
||||||
|
fn show_success(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
|
||||||
|
|
||||||
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error>;
|
fn show_wait_text(text: TString<'static>) -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
|
|
||||||
|
fn show_warning(
|
||||||
|
title: TString<'static>,
|
||||||
|
button: TString<'static>,
|
||||||
|
value: TString<'static>,
|
||||||
|
description: TString<'static>,
|
||||||
|
allow_cancel: bool,
|
||||||
|
time_ms: u32,
|
||||||
|
danger: bool,
|
||||||
|
) -> Result<Gc<LayoutObj>, Error>; // TODO: return LayoutMaybeTrace
|
||||||
|
|
||||||
fn tutorial() -> Result<impl LayoutMaybeTrace, Error>;
|
fn tutorial() -> Result<impl LayoutMaybeTrace, Error>;
|
||||||
}
|
}
|
||||||
|
@ -121,44 +121,6 @@ def confirm_fido(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
|
||||||
def show_error(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
button: str = "CONTINUE",
|
|
||||||
description: str = "",
|
|
||||||
allow_cancel: bool = False,
|
|
||||||
time_ms: int = 0,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Error modal. No buttons shown when `button` is empty string."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
|
||||||
def show_warning(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
button: str = "CONTINUE",
|
|
||||||
value: str = "",
|
|
||||||
description: str = "",
|
|
||||||
allow_cancel: bool = False,
|
|
||||||
time_ms: int = 0,
|
|
||||||
danger: bool = False,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Warning modal. No buttons shown when `button` is empty string."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
|
||||||
def show_success(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
button: str = "CONTINUE",
|
|
||||||
description: str = "",
|
|
||||||
allow_cancel: bool = False,
|
|
||||||
time_ms: int = 0,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Success screen. Description is used in the footer."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_mercury/layout.rs
|
# rust/src/ui/model_mercury/layout.rs
|
||||||
def show_simple(
|
def show_simple(
|
||||||
*,
|
*,
|
||||||
@ -450,16 +412,6 @@ def multiple_pages_texts(
|
|||||||
"""Show multiple texts, each on its own page."""
|
"""Show multiple texts, each on its own page."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tr/layout.rs
|
|
||||||
def show_warning(
|
|
||||||
*,
|
|
||||||
button: str,
|
|
||||||
warning: str,
|
|
||||||
description: str,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Warning modal with middle button and centered text."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tr/layout.rs
|
# rust/src/ui/model_tr/layout.rs
|
||||||
def show_passphrase() -> LayoutObj[UiResult]:
|
def show_passphrase() -> LayoutObj[UiResult]:
|
||||||
"""Show passphrase on host dialog."""
|
"""Show passphrase on host dialog."""
|
||||||
@ -635,44 +587,6 @@ def confirm_fido(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tt/layout.rs
|
|
||||||
def show_error(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
button: str = "CONTINUE",
|
|
||||||
description: str = "",
|
|
||||||
allow_cancel: bool = False,
|
|
||||||
time_ms: int = 0,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Error modal. No buttons shown when `button` is empty string."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tt/layout.rs
|
|
||||||
def show_warning(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
button: str = "CONTINUE",
|
|
||||||
value: str = "",
|
|
||||||
description: str = "",
|
|
||||||
allow_cancel: bool = False,
|
|
||||||
time_ms: int = 0,
|
|
||||||
danger: bool = False, # unused on TT
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Warning modal. No buttons shown when `button` is empty string."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tt/layout.rs
|
|
||||||
def show_success(
|
|
||||||
*,
|
|
||||||
title: str,
|
|
||||||
button: str = "CONTINUE",
|
|
||||||
description: str = "",
|
|
||||||
allow_cancel: bool = False,
|
|
||||||
time_ms: int = 0,
|
|
||||||
) -> LayoutObj[UiResult]:
|
|
||||||
"""Success modal. No buttons shown when `button` is empty string."""
|
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tt/layout.rs
|
# rust/src/ui/model_tt/layout.rs
|
||||||
def show_simple(
|
def show_simple(
|
||||||
*,
|
*,
|
||||||
|
@ -244,6 +244,18 @@ def show_checklist(
|
|||||||
mark next to them. Limited to 3 items."""
|
mark next to them. Limited to 3 items."""
|
||||||
|
|
||||||
|
|
||||||
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
|
def show_error(
|
||||||
|
*,
|
||||||
|
title: str,
|
||||||
|
button: str,
|
||||||
|
description: str = "",
|
||||||
|
allow_cancel: bool = True,
|
||||||
|
time_ms: int = 0,
|
||||||
|
) -> LayoutObj[UiResult]:
|
||||||
|
"""Error modal. No buttons shown when `button` is empty string."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_upy.rs
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
def show_group_share_success(
|
def show_group_share_success(
|
||||||
*,
|
*,
|
||||||
@ -323,11 +335,37 @@ def show_remaining_shares(
|
|||||||
"""Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
"""Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
||||||
|
|
||||||
|
|
||||||
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
|
def show_success(
|
||||||
|
*,
|
||||||
|
title: str,
|
||||||
|
button: str,
|
||||||
|
description: str = "",
|
||||||
|
allow_cancel: bool = True,
|
||||||
|
time_ms: int = 0,
|
||||||
|
) -> LayoutObj[UiResult]:
|
||||||
|
"""Success modal. No buttons shown when `button` is empty string."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_upy.rs
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
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."""
|
||||||
|
|
||||||
|
|
||||||
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
|
def show_warning(
|
||||||
|
*,
|
||||||
|
title: str,
|
||||||
|
button: str,
|
||||||
|
value: str = "",
|
||||||
|
description: str = "",
|
||||||
|
allow_cancel: bool = True,
|
||||||
|
time_ms: int = 0,
|
||||||
|
danger: bool = False, # unused on TT
|
||||||
|
) -> LayoutObj[UiResult]:
|
||||||
|
"""Warning modal. TT: No buttons shown when `button` is empty string. TR: middle button and centered text."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/api/firmware_upy.rs
|
# rust/src/ui/api/firmware_upy.rs
|
||||||
def tutorial() -> LayoutObj[UiResult]:
|
def tutorial() -> LayoutObj[UiResult]:
|
||||||
"""Show user how to interact with the device."""
|
"""Show user how to interact with the device."""
|
||||||
|
@ -97,7 +97,7 @@ def confirm_reset_device(recovery: bool = False) -> Awaitable[None]:
|
|||||||
|
|
||||||
async def show_wallet_created_success() -> None:
|
async def show_wallet_created_success() -> None:
|
||||||
await interact(
|
await interact(
|
||||||
trezorui2.show_success(title=TR.backup__new_wallet_created, description=""),
|
trezorui_api.show_success(title=TR.backup__new_wallet_created, button=""),
|
||||||
"backup_device",
|
"backup_device",
|
||||||
ButtonRequestType.ResetDevice,
|
ButtonRequestType.ResetDevice,
|
||||||
)
|
)
|
||||||
@ -286,7 +286,7 @@ async def show_error_and_raise(
|
|||||||
) -> NoReturn:
|
) -> NoReturn:
|
||||||
button = button or TR.buttons__try_again # def_arg
|
button = button or TR.buttons__try_again # def_arg
|
||||||
await interact(
|
await interact(
|
||||||
trezorui2.show_error(
|
trezorui_api.show_error(
|
||||||
title=subheader or "",
|
title=subheader or "",
|
||||||
description=content,
|
description=content,
|
||||||
button=button,
|
button=button,
|
||||||
@ -308,7 +308,7 @@ def show_warning(
|
|||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
button = button or TR.buttons__continue # def_arg
|
button = button or TR.buttons__continue # def_arg
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=TR.words__important,
|
title=TR.words__important,
|
||||||
value=content,
|
value=content,
|
||||||
button=subheader or TR.words__continue_anyway_question,
|
button=subheader or TR.words__continue_anyway_question,
|
||||||
@ -326,8 +326,9 @@ def show_success(
|
|||||||
button: str | None = None,
|
button: str | None = None,
|
||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui2.show_success(
|
trezorui_api.show_success(
|
||||||
title=content,
|
title=content,
|
||||||
|
button="",
|
||||||
description=subheader if subheader else "",
|
description=subheader if subheader else "",
|
||||||
),
|
),
|
||||||
br_name,
|
br_name,
|
||||||
@ -1073,7 +1074,7 @@ def error_popup(
|
|||||||
|
|
||||||
if subtitle:
|
if subtitle:
|
||||||
title += f"\n{subtitle}"
|
title += f"\n{subtitle}"
|
||||||
return trezorui2.show_error(
|
return trezorui_api.show_error(
|
||||||
title=title,
|
title=title,
|
||||||
description=description.format(description_param),
|
description=description.format(description_param),
|
||||||
button=button,
|
button=button,
|
||||||
|
@ -135,7 +135,7 @@ async def show_recovery_warning(
|
|||||||
) -> None:
|
) -> None:
|
||||||
button = button or TR.buttons__try_again # def_arg
|
button = button or TR.buttons__try_again # def_arg
|
||||||
await raise_if_not_confirmed(
|
await raise_if_not_confirmed(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=content or TR.words__warning,
|
title=content or TR.words__warning,
|
||||||
value=subheader or "",
|
value=subheader or "",
|
||||||
button=button,
|
button=button,
|
||||||
|
@ -301,7 +301,7 @@ async def show_intro_backup(single_share: bool, num_of_words: int | None) -> Non
|
|||||||
|
|
||||||
def show_warning_backup() -> Awaitable[ui.UiResult]:
|
def show_warning_backup() -> Awaitable[ui.UiResult]:
|
||||||
return interact(
|
return interact(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=TR.words__important,
|
title=TR.words__important,
|
||||||
value=TR.reset__never_make_digital_copy,
|
value=TR.reset__never_make_digital_copy,
|
||||||
button="",
|
button="",
|
||||||
@ -328,7 +328,7 @@ def show_reset_warning(
|
|||||||
br_code: ButtonRequestType = ButtonRequestType.Warning,
|
br_code: ButtonRequestType = ButtonRequestType.Warning,
|
||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=subheader or "",
|
title=subheader or "",
|
||||||
description=content,
|
description=content,
|
||||||
value="",
|
value="",
|
||||||
|
@ -393,9 +393,10 @@ def show_warning(
|
|||||||
content = content + "\n"
|
content = content + "\n"
|
||||||
|
|
||||||
return interact(
|
return interact(
|
||||||
trezorui2.show_warning( # type: ignore [Argument missing for parameter "title"]
|
trezorui_api.show_warning( # type: ignore [Argument missing for parameter "title"]
|
||||||
|
title="",
|
||||||
button=button,
|
button=button,
|
||||||
warning=content, # type: ignore [No parameter named "warning"]
|
value=content,
|
||||||
description=subheader or "",
|
description=subheader or "",
|
||||||
),
|
),
|
||||||
br_name,
|
br_name,
|
||||||
|
@ -136,7 +136,7 @@ def confirm_path_warning(path: str, path_type: str | None = None) -> Awaitable[N
|
|||||||
else f"{TR.words__unknown} {path_type.lower()}."
|
else f"{TR.words__unknown} {path_type.lower()}."
|
||||||
)
|
)
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=title,
|
title=title,
|
||||||
value=path,
|
value=path,
|
||||||
description=TR.words__continue_anyway_question,
|
description=TR.words__continue_anyway_question,
|
||||||
@ -323,7 +323,7 @@ async def show_error_and_raise(
|
|||||||
) -> NoReturn:
|
) -> NoReturn:
|
||||||
button = button or TR.buttons__try_again # def_arg
|
button = button or TR.buttons__try_again # def_arg
|
||||||
await interact(
|
await interact(
|
||||||
trezorui2.show_error(
|
trezorui_api.show_error(
|
||||||
title=subheader or "",
|
title=subheader or "",
|
||||||
description=content,
|
description=content,
|
||||||
button=button,
|
button=button,
|
||||||
@ -347,7 +347,7 @@ def show_warning(
|
|||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
button = button or TR.buttons__continue # def_arg
|
button = button or TR.buttons__continue # def_arg
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=content,
|
title=content,
|
||||||
description=subheader or "",
|
description=subheader or "",
|
||||||
button=button,
|
button=button,
|
||||||
@ -365,7 +365,7 @@ def show_success(
|
|||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
button = button or TR.buttons__continue # def_arg
|
button = button or TR.buttons__continue # def_arg
|
||||||
return raise_if_not_confirmed(
|
return raise_if_not_confirmed(
|
||||||
trezorui2.show_success(
|
trezorui_api.show_success(
|
||||||
title=content,
|
title=content,
|
||||||
description=subheader or "",
|
description=subheader or "",
|
||||||
button=button,
|
button=button,
|
||||||
@ -1121,7 +1121,7 @@ def error_popup(
|
|||||||
|
|
||||||
if subtitle:
|
if subtitle:
|
||||||
title += f"\n{subtitle}"
|
title += f"\n{subtitle}"
|
||||||
layout = trezorui2.show_error(
|
layout = trezorui_api.show_error(
|
||||||
title=title,
|
title=title,
|
||||||
description=description.format(description_param),
|
description=description.format(description_param),
|
||||||
button=button,
|
button=button,
|
||||||
|
@ -185,7 +185,7 @@ def show_recovery_warning(
|
|||||||
button = button or TR.buttons__try_again # def_arg
|
button = button or TR.buttons__try_again # def_arg
|
||||||
|
|
||||||
return interact(
|
return interact(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=content,
|
title=content,
|
||||||
description=subheader or "",
|
description=subheader or "",
|
||||||
button=button,
|
button=button,
|
||||||
|
@ -355,7 +355,7 @@ def show_reset_warning(
|
|||||||
) -> Awaitable[trezorui_api.UiResult]:
|
) -> Awaitable[trezorui_api.UiResult]:
|
||||||
button = button or TR.buttons__try_again # def_arg
|
button = button or TR.buttons__try_again # def_arg
|
||||||
return interact(
|
return interact(
|
||||||
trezorui2.show_warning(
|
trezorui_api.show_warning(
|
||||||
title=subheader or "",
|
title=subheader or "",
|
||||||
description=content,
|
description=content,
|
||||||
button=button,
|
button=button,
|
||||||
|
Loading…
Reference in New Issue
Block a user