mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-26 09:52:34 +00:00
chore(eckhart): simplify updatable info screen
[no changelog]
This commit is contained in:
parent
13a020202e
commit
468ddaab9d
@ -42,7 +42,7 @@ pub use qr_screen::{QrMsg, QrScreen};
|
||||
pub use select_word_screen::{SelectWordMsg, SelectWordScreen};
|
||||
pub use share_words::{ShareWordsScreen, ShareWordsScreenMsg};
|
||||
pub use text_screen::{AllowedTextContent, TextScreen, TextScreenMsg};
|
||||
pub use updatable_info_screen::UpdatableInfoScreen;
|
||||
pub use updatable_info_screen::{UpdatableInfoScreen, UpdatableInfoScreenMsg};
|
||||
pub use value_input_screen::{
|
||||
DurationInput, NumberInput, ValueInput, ValueInputScreen, ValueInputScreenMsg,
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
component::{
|
||||
swipe_detect::SwipeConfig,
|
||||
text::paragraphs::{Paragraph, ParagraphSource, Paragraphs},
|
||||
Component, Event, EventCtx,
|
||||
Component, Event, EventCtx, PaginateFull,
|
||||
},
|
||||
flow::Swipable,
|
||||
geometry::{LinearPlacement, Rect},
|
||||
@ -14,16 +14,20 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use super::{theme, Header, TextScreen, TextScreenMsg};
|
||||
use super::{constant::SCREEN, theme, ActionBar, ActionBarMsg, Header};
|
||||
|
||||
pub enum UpdatableInfoScreenMsg {
|
||||
Close,
|
||||
}
|
||||
|
||||
pub struct UpdatableInfoScreen<F>
|
||||
where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
header: Header,
|
||||
info_func: F,
|
||||
paragraphs: Paragraphs<Paragraph<'static>>,
|
||||
area: Rect,
|
||||
text_screen: TextScreen<Paragraphs<Paragraph<'static>>>,
|
||||
paragraph: Paragraphs<Paragraph<'static>>,
|
||||
action_bar: ActionBar,
|
||||
}
|
||||
|
||||
impl<F> UpdatableInfoScreen<F>
|
||||
@ -31,59 +35,97 @@ where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
pub fn new(info_func: F) -> Self {
|
||||
let paragraphs = Paragraph::new(&theme::TEXT_REGULAR, TString::empty())
|
||||
let paragraph = Paragraph::new(&theme::TEXT_REGULAR, TString::empty())
|
||||
.into_paragraphs()
|
||||
.with_placement(LinearPlacement::vertical());
|
||||
let text_screen = create_text_screen(paragraphs.clone());
|
||||
Self {
|
||||
header: Header::new(TR::buttons__more_info.into()).with_close_button(),
|
||||
info_func,
|
||||
paragraphs,
|
||||
area: Rect::zero(),
|
||||
text_screen,
|
||||
paragraph,
|
||||
action_bar: ActionBar::new_paginate_only(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_header(mut self, header: Header) -> Self {
|
||||
self.header = header;
|
||||
self
|
||||
}
|
||||
|
||||
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);
|
||||
self.paragraph.update(text);
|
||||
|
||||
self.update_page(0);
|
||||
ctx.request_paint();
|
||||
}
|
||||
|
||||
fn update_page(&mut self, page_idx: u16) {
|
||||
self.paragraph.change_page(page_idx);
|
||||
self.action_bar.update(self.paragraph.pager());
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Component for UpdatableInfoScreen<F>
|
||||
where
|
||||
F: Fn() -> TString<'static>,
|
||||
{
|
||||
type Msg = TextScreenMsg;
|
||||
type Msg = UpdatableInfoScreenMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.text_screen.place(bounds);
|
||||
self.area = bounds;
|
||||
// assert full screen
|
||||
debug_assert_eq!(bounds.height(), SCREEN.height());
|
||||
debug_assert_eq!(bounds.width(), SCREEN.width());
|
||||
|
||||
let (header_area, rest) = bounds.split_top(Header::HEADER_HEIGHT);
|
||||
let (info_area, action_bar_area) = rest.split_bottom(ActionBar::ACTION_BAR_HEIGHT);
|
||||
|
||||
self.header.place(header_area);
|
||||
self.paragraph.place(info_area.inset(theme::SIDE_INSETS));
|
||||
self.action_bar.place(action_bar_area);
|
||||
|
||||
self.update_page(0);
|
||||
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
// Update page count of the screen
|
||||
ctx.set_page_count(self.paragraph.pager().total() as usize);
|
||||
|
||||
if let Event::Attach(_) = event {
|
||||
self.update_text(ctx);
|
||||
}
|
||||
|
||||
self.text_screen.event(ctx, event)
|
||||
self.paragraph.event(ctx, event);
|
||||
|
||||
if self.header.event(ctx, event).is_some() {
|
||||
return Some(UpdatableInfoScreenMsg::Close);
|
||||
}
|
||||
|
||||
if let Some(msg) = self.action_bar.event(ctx, event) {
|
||||
match msg {
|
||||
ActionBarMsg::Prev => {
|
||||
self.update_page(self.paragraph.pager().prev());
|
||||
return None;
|
||||
}
|
||||
ActionBarMsg::Next => {
|
||||
self.update_page(self.paragraph.pager().next());
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.text_screen.render(target);
|
||||
self.header.render(target);
|
||||
self.paragraph.render(target);
|
||||
self.action_bar.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()
|
||||
@ -93,6 +135,9 @@ impl<F: Fn() -> TString<'static>> Swipable for UpdatableInfoScreen<F> {
|
||||
}
|
||||
}
|
||||
|
||||
trait UpdatableTextContent: Component + PaginateFull {}
|
||||
impl<'a, T> UpdatableTextContent for Paragraphs<T> where T: ParagraphSource<'a> {}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<F> crate::trace::Trace for UpdatableInfoScreen<F>
|
||||
where
|
||||
@ -100,6 +145,8 @@ where
|
||||
{
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("UpdatableInfoScreen");
|
||||
t.child("screen", &self.text_screen);
|
||||
t.child("Header", &self.header);
|
||||
t.child("Content", &self.paragraph);
|
||||
t.child("ActionBar", &self.action_bar);
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,8 @@ use core::sync::atomic::{AtomicU16, Ordering};
|
||||
use super::super::{
|
||||
component::Button,
|
||||
firmware::{
|
||||
ActionBar, Header, NumberInput, ShortMenuVec, TextScreenMsg, UpdatableInfoScreen,
|
||||
ValueInputScreen, ValueInputScreenMsg, VerticalMenu, VerticalMenuScreen,
|
||||
VerticalMenuScreenMsg,
|
||||
ActionBar, Header, NumberInput, ShortMenuVec, UpdatableInfoScreen, ValueInputScreen,
|
||||
ValueInputScreenMsg, VerticalMenu, VerticalMenuScreen, VerticalMenuScreenMsg,
|
||||
},
|
||||
theme,
|
||||
};
|
||||
@ -104,17 +103,16 @@ pub fn new_request_number(
|
||||
));
|
||||
|
||||
let content_menu = VerticalMenuScreen::new(menu_items)
|
||||
.with_header(Header::new(TString::empty()).with_close_button())
|
||||
.with_header(Header::new(title).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 content_info = UpdatableInfoScreen::new(info_closure)
|
||||
.with_header(Header::new(title).with_close_button())
|
||||
.map(|_| Some(FlowMsg::Cancelled));
|
||||
|
||||
let mut res = SwipeFlow::new(&RequestNumber::Number)?;
|
||||
res.add_page(&RequestNumber::Number, content_input)?
|
||||
|
Loading…
Reference in New Issue
Block a user