mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-09 10:28:46 +00:00
feat(eckhart): update request number trait function
add request number flow instead of screen only add updatable info screen to show extra information
This commit is contained in:
parent
9c1203522c
commit
a606b1374b
@ -15,10 +15,9 @@ use crate::{
|
|||||||
|
|
||||||
use super::firmware::{
|
use super::firmware::{
|
||||||
AllowedTextContent, ConfirmHomescreen, ConfirmHomescreenMsg, DeviceMenuMsg, DeviceMenuScreen,
|
AllowedTextContent, ConfirmHomescreen, ConfirmHomescreenMsg, DeviceMenuMsg, DeviceMenuScreen,
|
||||||
Homescreen, HomescreenMsg, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg,
|
Homescreen, HomescreenMsg, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg, PinKeyboard,
|
||||||
NumberInputScreen, NumberInputScreenMsg, PinKeyboard, PinKeyboardMsg, SelectWordCountMsg,
|
PinKeyboardMsg, SelectWordCountMsg, SelectWordCountScreen, SelectWordMsg, SelectWordScreen,
|
||||||
SelectWordCountScreen, SelectWordMsg, SelectWordScreen, SetBrightnessScreen, TextScreen,
|
SetBrightnessScreen, TextScreen, TextScreenMsg,
|
||||||
TextScreenMsg,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ComponentMsgObj for PinKeyboard<'_> {
|
impl ComponentMsgObj for PinKeyboard<'_> {
|
||||||
@ -111,16 +110,6 @@ impl ComponentMsgObj for SelectWordCountScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComponentMsgObj for NumberInputScreen {
|
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
|
||||||
match msg {
|
|
||||||
NumberInputScreenMsg::Confirmed(i) => i.try_into(),
|
|
||||||
NumberInputScreenMsg::Cancelled => Ok(CANCELLED.as_obj()),
|
|
||||||
NumberInputScreenMsg::Menu => Ok(INFO.as_obj()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ComponentMsgObj for ConfirmHomescreen {
|
impl ComponentMsgObj for ConfirmHomescreen {
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
|
@ -12,6 +12,7 @@ mod qr_screen;
|
|||||||
mod select_word_screen;
|
mod select_word_screen;
|
||||||
mod share_words;
|
mod share_words;
|
||||||
mod text_screen;
|
mod text_screen;
|
||||||
|
mod updatable_info_screen;
|
||||||
mod vertical_menu;
|
mod vertical_menu;
|
||||||
mod vertical_menu_screen;
|
mod vertical_menu_screen;
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ pub use qr_screen::{QrMsg, QrScreen};
|
|||||||
pub use select_word_screen::{SelectWordMsg, SelectWordScreen};
|
pub use select_word_screen::{SelectWordMsg, SelectWordScreen};
|
||||||
pub use share_words::{ShareWordsScreen, ShareWordsScreenMsg};
|
pub use share_words::{ShareWordsScreen, ShareWordsScreenMsg};
|
||||||
pub use text_screen::{AllowedTextContent, TextScreen, TextScreenMsg};
|
pub use text_screen::{AllowedTextContent, TextScreen, TextScreenMsg};
|
||||||
|
pub use updatable_info_screen::UpdatableInfoScreen;
|
||||||
pub use vertical_menu::{VerticalMenu, VerticalMenuMsg, MENU_MAX_ITEMS};
|
pub use vertical_menu::{VerticalMenu, VerticalMenuMsg, MENU_MAX_ITEMS};
|
||||||
pub use vertical_menu_screen::{VerticalMenuScreen, VerticalMenuScreenMsg};
|
pub use vertical_menu_screen::{VerticalMenuScreen, VerticalMenuScreenMsg};
|
||||||
|
|
||||||
|
@ -2,9 +2,11 @@ use crate::{
|
|||||||
strutil::{self, TString},
|
strutil::{self, TString},
|
||||||
translations::TR,
|
translations::TR,
|
||||||
ui::{
|
ui::{
|
||||||
component::{Component, Event, EventCtx, Label, Maybe, Never},
|
component::{swipe_detect::SwipeConfig, Component, Event, EventCtx, Label, Maybe},
|
||||||
|
flow::Swipable,
|
||||||
geometry::{Alignment, Insets, Offset, Rect},
|
geometry::{Alignment, Insets, Offset, Rect},
|
||||||
shape::{self, Renderer},
|
shape::{self, Renderer},
|
||||||
|
util::Pager,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,6 +22,7 @@ use super::{
|
|||||||
pub enum NumberInputScreenMsg {
|
pub enum NumberInputScreenMsg {
|
||||||
Cancelled,
|
Cancelled,
|
||||||
Confirmed(u32),
|
Confirmed(u32),
|
||||||
|
Changed(u32),
|
||||||
Menu,
|
Menu,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +90,7 @@ impl Component for NumberInputScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
self.number_input.event(ctx, event);
|
let changed = self.number_input.event(ctx, event);
|
||||||
|
|
||||||
if let Some(HeaderMsg::Menu) = self.header.event(ctx, event) {
|
if let Some(HeaderMsg::Menu) = self.header.event(ctx, event) {
|
||||||
return Some(NumberInputScreenMsg::Menu);
|
return Some(NumberInputScreenMsg::Menu);
|
||||||
@ -103,6 +106,10 @@ impl Component for NumberInputScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(NumberInputMsg::Changed(value)) = changed {
|
||||||
|
return Some(NumberInputScreenMsg::Changed(value));
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +121,15 @@ impl Component for NumberInputScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Swipable for NumberInputScreen {
|
||||||
|
fn get_pager(&self) -> Pager {
|
||||||
|
Pager::single_page()
|
||||||
|
}
|
||||||
|
fn get_swipe_config(&self) -> SwipeConfig {
|
||||||
|
SwipeConfig::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl crate::trace::Trace for NumberInputScreen {
|
impl crate::trace::Trace for NumberInputScreen {
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
@ -132,6 +148,10 @@ struct NumberInput {
|
|||||||
value: u32,
|
value: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum NumberInputMsg {
|
||||||
|
Changed(u32),
|
||||||
|
}
|
||||||
|
|
||||||
impl NumberInput {
|
impl NumberInput {
|
||||||
const BUTTON_PADDING: i16 = 10;
|
const BUTTON_PADDING: i16 = 10;
|
||||||
const BUTTON_SIZE: Offset = Offset::new(138, 130);
|
const BUTTON_SIZE: Offset = Offset::new(138, 130);
|
||||||
@ -204,7 +224,7 @@ impl NumberInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Component for NumberInput {
|
impl Component for NumberInput {
|
||||||
type Msg = Never;
|
type Msg = NumberInputMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
self.area = bounds;
|
self.area = bounds;
|
||||||
@ -231,12 +251,19 @@ impl Component for NumberInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
let mut changed = false;
|
||||||
if let Some(ButtonMsg::Clicked) = self.dec.event(ctx, event) {
|
if let Some(ButtonMsg::Clicked) = self.dec.event(ctx, event) {
|
||||||
self.decrease(ctx);
|
self.decrease(ctx);
|
||||||
|
changed = true;
|
||||||
};
|
};
|
||||||
if let Some(ButtonMsg::Clicked) = self.inc.event(ctx, event) {
|
if let Some(ButtonMsg::Clicked) = self.inc.event(ctx, event) {
|
||||||
self.increase(ctx);
|
self.increase(ctx);
|
||||||
|
changed = true;
|
||||||
};
|
};
|
||||||
|
if changed {
|
||||||
|
ctx.request_paint();
|
||||||
|
return Some(NumberInputMsg::Changed(self.value));
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
use crate::{
|
||||||
|
strutil::TString,
|
||||||
|
translations::TR,
|
||||||
|
ui::{
|
||||||
|
component::{
|
||||||
|
swipe_detect::SwipeConfig,
|
||||||
|
text::paragraphs::{Paragraph, ParagraphSource, Paragraphs},
|
||||||
|
Component, Event, EventCtx,
|
||||||
|
},
|
||||||
|
flow::Swipable,
|
||||||
|
geometry::{LinearPlacement, Rect},
|
||||||
|
shape::Renderer,
|
||||||
|
util::Pager,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{theme, Header, TextScreen, TextScreenMsg};
|
||||||
|
|
||||||
|
pub struct UpdatableInfoScreen<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> TString<'static>,
|
||||||
|
{
|
||||||
|
info_func: F,
|
||||||
|
paragraphs: Paragraphs<Paragraph<'static>>,
|
||||||
|
area: Rect,
|
||||||
|
text_screen: TextScreen<Paragraphs<Paragraph<'static>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> UpdatableInfoScreen<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> TString<'static>,
|
||||||
|
{
|
||||||
|
pub fn new(info_func: F) -> Self {
|
||||||
|
let paragraphs = Paragraph::new(&theme::TEXT_REGULAR, TString::empty())
|
||||||
|
.into_paragraphs()
|
||||||
|
.with_placement(LinearPlacement::vertical());
|
||||||
|
let text_screen = create_text_screen(paragraphs.clone());
|
||||||
|
Self {
|
||||||
|
info_func,
|
||||||
|
paragraphs,
|
||||||
|
area: Rect::zero(),
|
||||||
|
text_screen,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_text(&mut self, ctx: &mut EventCtx) {
|
||||||
|
let text = (self.info_func)();
|
||||||
|
self.paragraphs.update(text);
|
||||||
|
self.text_screen = create_text_screen(self.paragraphs.clone());
|
||||||
|
self.text_screen.place(self.area);
|
||||||
|
ctx.request_paint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> Component for UpdatableInfoScreen<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> TString<'static>,
|
||||||
|
{
|
||||||
|
type Msg = TextScreenMsg;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
self.text_screen.place(bounds);
|
||||||
|
self.area = bounds;
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
if let Event::Attach(_) = event {
|
||||||
|
self.update_text(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.text_screen.event(ctx, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||||
|
self.text_screen.render(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_text_screen(
|
||||||
|
paragraphs: Paragraphs<Paragraph<'static>>,
|
||||||
|
) -> TextScreen<Paragraphs<Paragraph<'static>>> {
|
||||||
|
TextScreen::new(paragraphs)
|
||||||
|
.with_header(Header::new(TR::buttons__more_info.into()).with_close_button())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Fn() -> TString<'static>> Swipable for UpdatableInfoScreen<F> {
|
||||||
|
fn get_pager(&self) -> Pager {
|
||||||
|
Pager::single_page()
|
||||||
|
}
|
||||||
|
fn get_swipe_config(&self) -> SwipeConfig {
|
||||||
|
SwipeConfig::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
impl<F> crate::trace::Trace for UpdatableInfoScreen<F>
|
||||||
|
where
|
||||||
|
F: Fn() -> TString<'static>,
|
||||||
|
{
|
||||||
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
|
t.component("UpdatableInfoScreen");
|
||||||
|
t.child("screen", &self.text_screen);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ pub mod confirm_summary;
|
|||||||
pub mod continue_recovery_homepage;
|
pub mod continue_recovery_homepage;
|
||||||
pub mod get_address;
|
pub mod get_address;
|
||||||
pub mod prompt_backup;
|
pub mod prompt_backup;
|
||||||
|
pub mod request_number;
|
||||||
pub mod request_passphrase;
|
pub mod request_passphrase;
|
||||||
pub mod show_danger;
|
pub mod show_danger;
|
||||||
pub mod show_share_words;
|
pub mod show_share_words;
|
||||||
@ -16,6 +17,7 @@ pub use confirm_summary::new_confirm_summary;
|
|||||||
pub use continue_recovery_homepage::new_continue_recovery_homepage;
|
pub use continue_recovery_homepage::new_continue_recovery_homepage;
|
||||||
pub use get_address::GetAddress;
|
pub use get_address::GetAddress;
|
||||||
pub use prompt_backup::PromptBackup;
|
pub use prompt_backup::PromptBackup;
|
||||||
|
pub use request_number::new_request_number;
|
||||||
pub use request_passphrase::RequestPassphrase;
|
pub use request_passphrase::RequestPassphrase;
|
||||||
pub use show_danger::ShowDanger;
|
pub use show_danger::ShowDanger;
|
||||||
pub use show_share_words::new_show_share_words_flow;
|
pub use show_share_words::new_show_share_words_flow;
|
||||||
|
122
core/embed/rust/src/ui/layout_eckhart/flow/request_number.rs
Normal file
122
core/embed/rust/src/ui/layout_eckhart/flow/request_number.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
use crate::{
|
||||||
|
error,
|
||||||
|
strutil::TString,
|
||||||
|
translations::TR,
|
||||||
|
ui::{
|
||||||
|
component::ComponentExt,
|
||||||
|
flow::{
|
||||||
|
base::{Decision, DecisionBuilder as _},
|
||||||
|
FlowController, FlowMsg, SwipeFlow,
|
||||||
|
},
|
||||||
|
geometry::{Alignment, Direction, Offset},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use core::sync::atomic::{AtomicU16, Ordering};
|
||||||
|
|
||||||
|
use super::super::{
|
||||||
|
component::Button,
|
||||||
|
firmware::{
|
||||||
|
Header, NumberInputScreen, NumberInputScreenMsg, TextScreenMsg, UpdatableInfoScreen,
|
||||||
|
VerticalMenu, VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||||
|
},
|
||||||
|
theme,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum RequestNumber {
|
||||||
|
Number,
|
||||||
|
Menu,
|
||||||
|
Info,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlowController for RequestNumber {
|
||||||
|
#[inline]
|
||||||
|
fn index(&'static self) -> usize {
|
||||||
|
*self as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_swipe(&'static self, _direction: Direction) -> Decision {
|
||||||
|
self.do_nothing()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&'static self, msg: FlowMsg) -> Decision {
|
||||||
|
match (self, msg) {
|
||||||
|
(Self::Number, FlowMsg::Info) => Self::Menu.goto(),
|
||||||
|
(Self::Menu, FlowMsg::Choice(0)) => Self::Info.goto(),
|
||||||
|
(Self::Menu, FlowMsg::Choice(1)) => self.return_msg(FlowMsg::Cancelled),
|
||||||
|
(Self::Menu, FlowMsg::Cancelled) => Self::Number.goto(),
|
||||||
|
(Self::Info, FlowMsg::Cancelled) => Self::Menu.goto(),
|
||||||
|
(Self::Number, FlowMsg::Choice(n)) => self.return_msg(FlowMsg::Choice(n)),
|
||||||
|
_ => self.do_nothing(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NUM_DISPLAYED: AtomicU16 = AtomicU16::new(0);
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn new_request_number(
|
||||||
|
title: TString<'static>,
|
||||||
|
count: u32,
|
||||||
|
min_count: u32,
|
||||||
|
max_count: u32,
|
||||||
|
description: TString<'static>,
|
||||||
|
info_closure: impl Fn(u32) -> TString<'static> + 'static,
|
||||||
|
) -> Result<SwipeFlow, error::Error> {
|
||||||
|
NUM_DISPLAYED.store(count as u16, Ordering::Relaxed);
|
||||||
|
|
||||||
|
// wrap the closure for obtaining MoreInfo text and call it with NUM_DISPLAYED
|
||||||
|
let info_closure = move || {
|
||||||
|
let curr_number = NUM_DISPLAYED.load(Ordering::Relaxed);
|
||||||
|
info_closure(curr_number as u32)
|
||||||
|
};
|
||||||
|
|
||||||
|
let content_input = NumberInputScreen::new(min_count, max_count, count, description)
|
||||||
|
.with_header(Header::new(title).with_menu_button())
|
||||||
|
.map(|msg| match msg {
|
||||||
|
NumberInputScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||||
|
NumberInputScreenMsg::Confirmed(n) => {
|
||||||
|
NUM_DISPLAYED.store(n as u16, Ordering::Relaxed);
|
||||||
|
Some(FlowMsg::Choice(n as usize))
|
||||||
|
}
|
||||||
|
NumberInputScreenMsg::Changed(n) => {
|
||||||
|
NUM_DISPLAYED.store(n as u16, Ordering::Relaxed);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
NumberInputScreenMsg::Menu => Some(FlowMsg::Info),
|
||||||
|
});
|
||||||
|
|
||||||
|
let menu_items = VerticalMenu::empty()
|
||||||
|
.item(
|
||||||
|
Button::with_text(TR::buttons__more_info.into())
|
||||||
|
.styled(theme::menu_item_title())
|
||||||
|
.with_text_align(Alignment::Start)
|
||||||
|
.with_content_offset(Offset::x(12)),
|
||||||
|
)
|
||||||
|
.item(
|
||||||
|
Button::with_text(TR::buttons__cancel.into())
|
||||||
|
.styled(theme::menu_item_title_orange())
|
||||||
|
.with_text_align(Alignment::Start)
|
||||||
|
.with_content_offset(Offset::x(12)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let content_menu = VerticalMenuScreen::new(menu_items)
|
||||||
|
.with_header(Header::new(TString::empty()).with_close_button())
|
||||||
|
.map(move |msg| match msg {
|
||||||
|
VerticalMenuScreenMsg::Selected(i) => Some(FlowMsg::Choice(i)),
|
||||||
|
VerticalMenuScreenMsg::Close => Some(FlowMsg::Cancelled),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let content_info = UpdatableInfoScreen::new(info_closure).map(|msg| match msg {
|
||||||
|
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut res = SwipeFlow::new(&RequestNumber::Number)?;
|
||||||
|
res.add_page(&RequestNumber::Number, content_input)?
|
||||||
|
.add_page(&RequestNumber::Menu, content_menu)?
|
||||||
|
.add_page(&RequestNumber::Info, content_info)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
@ -33,8 +33,8 @@ use super::{
|
|||||||
component::Button,
|
component::Button,
|
||||||
firmware::{
|
firmware::{
|
||||||
ActionBar, Bip39Input, ConfirmHomescreen, DeviceMenuScreen, Header, HeaderMsg, Hint,
|
ActionBar, Bip39Input, ConfirmHomescreen, DeviceMenuScreen, Header, HeaderMsg, Hint,
|
||||||
Homescreen, MnemonicKeyboard, NumberInputScreen, PinKeyboard, SelectWordCountScreen,
|
Homescreen, MnemonicKeyboard, PinKeyboard, SelectWordCountScreen, SelectWordScreen,
|
||||||
SelectWordScreen, SetBrightnessScreen, Slip39Input, TextScreen,
|
SetBrightnessScreen, Slip39Input, TextScreen,
|
||||||
},
|
},
|
||||||
flow, fonts, theme, UIEckhart,
|
flow, fonts, theme, UIEckhart,
|
||||||
};
|
};
|
||||||
@ -619,15 +619,19 @@ impl FirmwareUI for UIEckhart {
|
|||||||
min_count: u32,
|
min_count: u32,
|
||||||
max_count: u32,
|
max_count: u32,
|
||||||
description: Option<TString<'static>>,
|
description: Option<TString<'static>>,
|
||||||
_more_info_callback: Option<impl Fn(u32) -> TString<'static> + 'static>,
|
more_info_callback: Option<impl Fn(u32) -> TString<'static> + 'static>,
|
||||||
) -> Result<impl LayoutMaybeTrace, Error> {
|
) -> Result<impl LayoutMaybeTrace, Error> {
|
||||||
let description = description.unwrap_or(TString::empty());
|
let description = description.unwrap_or(TString::empty());
|
||||||
let component = NumberInputScreen::new(min_count, max_count, count, description)
|
|
||||||
.with_header(Header::new(title));
|
|
||||||
|
|
||||||
let layout = RootComponent::new(component);
|
let flow = flow::request_number::new_request_number(
|
||||||
|
title,
|
||||||
Ok(layout)
|
count,
|
||||||
|
min_count,
|
||||||
|
max_count,
|
||||||
|
description,
|
||||||
|
unwrap!(more_info_callback),
|
||||||
|
)?;
|
||||||
|
Ok(flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_pin(
|
fn request_pin(
|
||||||
|
Loading…
Reference in New Issue
Block a user