fix(core/ui): Model T style update

[no changelog]
pull/2905/head
Martin Milata 1 year ago
parent 3623f966dc
commit 19a2ea21b6

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 182 B

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

@ -27,7 +27,7 @@
#define BUFFER_PIXELS DISPLAY_RESX
#define TEXT_BUFFER_HEIGHT 32
#define TEXT_BUFFER_HEIGHT 36
#if TEXT_BUFFER_HEIGHT < FONT_MAX_HEIGHT
#error Text buffer height is too small, please adjust to match used fonts

@ -149,7 +149,7 @@ void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b,
void display_bar_radius_buffer(int x, int y, int w, int h, uint8_t r,
buffer_text_t *buffer) {
if (h > 32) {
if (h > TEXT_BUFFER_HEIGHT) {
return;
}
if (r != 2 && r != 4 && r != 8 && r != 16) {

@ -29,6 +29,7 @@
/// FONT_MONO: int # id of monospace font
/// FONT_NORMAL: int # id of normal-width font
/// FONT_BOLD: int # id of bold-width font
/// FONT_DEMIBOLD: int # id of demibold font
/// TOIF_FULL_COLOR_BE: int # full color big endian TOI image
/// TOIF_FULL_COLOR_LE: int # full color little endian TOI image
/// TOIF_GRAYSCALE_EH: int # grayscale even high TOI image
@ -621,6 +622,7 @@ STATIC const mp_rom_map_elem_t mod_trezorui_Display_locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(DISPLAY_RESY)},
{MP_ROM_QSTR(MP_QSTR_FONT_NORMAL), MP_ROM_INT(FONT_NORMAL)},
{MP_ROM_QSTR(MP_QSTR_FONT_BOLD), MP_ROM_INT(FONT_BOLD)},
{MP_ROM_QSTR(MP_QSTR_FONT_DEMIBOLD), MP_ROM_INT(FONT_DEMIBOLD)},
{MP_ROM_QSTR(MP_QSTR_FONT_MONO), MP_ROM_INT(FONT_MONO)},
{MP_ROM_QSTR(MP_QSTR_TOIF_FULL_COLOR_BE), MP_ROM_INT(TOIF_FULL_COLOR_BE)},
{MP_ROM_QSTR(MP_QSTR_TOIF_FULL_COLOR_LE), MP_ROM_INT(TOIF_FULL_COLOR_LE)},

@ -26,7 +26,7 @@ pub use maybe::Maybe;
pub use pad::Pad;
pub use paginated::{AuxPageMsg, PageMsg, Paginate};
pub use painter::Painter;
pub use placed::{FixedHeightBar, Floating, GridPlaced, VSplit};
pub use placed::{FixedHeightBar, Floating, GridPlaced, Split};
pub use qr_code::Qr;
pub use text::{
formatted::FormattedText,

@ -1,6 +1,6 @@
use crate::ui::{
component::{Component, Event, EventCtx},
geometry::{Alignment, Alignment2D, Grid, GridCellSpan, Insets, Offset, Rect, TOP_RIGHT},
geometry::{Alignment, Alignment2D, Axis, Grid, GridCellSpan, Insets, Offset, Rect, TOP_RIGHT},
};
pub struct GridPlaced<T> {
@ -195,25 +195,35 @@ where
}
}
pub struct VSplit<T, U> {
pub struct Split<T, U> {
first: T,
second: U,
width: i16,
axis: Axis,
size: i16,
spacing: i16,
}
impl<T, U> VSplit<T, U> {
pub const fn new(width: i16, spacing: i16, first: T, second: U) -> Self {
impl<T, U> Split<T, U> {
pub const fn new(axis: Axis, size: i16, spacing: i16, first: T, second: U) -> Self {
Self {
first,
second,
width,
axis,
size,
spacing,
}
}
pub const fn vertical(size: i16, spacing: i16, first: T, second: U) -> Self {
Self::new(Axis::Vertical, size, spacing, first, second)
}
pub const fn horizontal(size: i16, spacing: i16, first: T, second: U) -> Self {
Self::new(Axis::Horizontal, size, spacing, first, second)
}
}
impl<M, T, U> Component for VSplit<T, U>
impl<M, T, U> Component for Split<T, U>
where
T: Component<Msg = M>,
U: Component<Msg = M>,
@ -221,10 +231,26 @@ where
type Msg = M;
fn place(&mut self, bounds: Rect) -> Rect {
let (left, right) = bounds.split_left(self.width);
let right = right.inset(Insets::left(self.spacing));
self.first.place(left);
self.second.place(right);
let size = if self.size == 0 {
(bounds.size().axis(self.axis.cross()) - self.spacing) / 2
} else {
self.size
};
let (first, second) = match self.axis {
Axis::Vertical if size > 0 => bounds.split_left(size),
Axis::Vertical => bounds.split_right(-size),
Axis::Horizontal if size > 0 => bounds.split_top(size),
Axis::Horizontal => bounds.split_bottom(-size),
};
let (first, second) = match self.axis {
Axis::Vertical if size > 0 => (first, second.inset(Insets::left(self.spacing))),
Axis::Vertical => (first.inset(Insets::right(self.spacing)), second),
Axis::Horizontal if size > 0 => (first, second.inset(Insets::top(self.spacing))),
Axis::Horizontal => (first.inset(Insets::bottom(self.spacing)), second),
};
self.first.place(first);
self.second.place(second);
bounds
}
@ -241,13 +267,13 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T, U> crate::trace::Trace for VSplit<T, U>
impl<T, U> crate::trace::Trace for Split<T, U>
where
T: Component + crate::trace::Trace,
U: Component + crate::trace::Trace,
{
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
d.open("VSplit");
d.open("Split");
d.field("first", &self.first);
d.field("second", &self.second);
d.close();

@ -56,8 +56,8 @@ pub const TITLE_AREA_START_Y: i16 = 8;
pub const BUTTON_AREA_START: i16 = 188;
// UI icons.
pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/cancel.toif");
pub const ICON_CONFIRM: &[u8] = include_res!("model_tt/res/confirm.toif");
pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/x24.toif");
pub const ICON_CONFIRM: &[u8] = include_res!("model_tt/res/check24.toif");
// BLD icons
pub const CLOSE: &[u8] = include_res!("model_tt/res/close.toif");

@ -15,24 +15,30 @@ use crate::{
use super::{theme, Frame};
const MAX_XPUBS: usize = 16;
pub struct AddressDetails<T> {
qr_code: Frame<Qr, T>,
details: Frame<Paragraphs<ParagraphVecShort<T>>, T>,
xpub_view: Frame<Paragraphs<Paragraph<T>>, T>,
xpubs: Vec<(T, T), 16>,
xpubs: Vec<(T, T), MAX_XPUBS>,
xpub_page_count: Vec<u8, MAX_XPUBS>,
current_page: usize,
}
impl<T> AddressDetails<T>
where
T: ParagraphStrType + From<&'static str>,
T: ParagraphStrType,
{
pub fn new(
qr_address: T,
case_sensitive: bool,
account: Option<T>,
path: Option<T>,
) -> Result<Self, Error> {
) -> Result<Self, Error>
where
T: From<&'static str>,
{
let mut para = ParagraphVecShort::new();
if let Some(a) = account {
para.add(Paragraph::new(&theme::TEXT_NORMAL, "Account:".into()));
@ -61,10 +67,11 @@ where
xpub_view: Frame::left_aligned(
theme::label_title(),
" \n ".into(),
Paragraph::new(&theme::TEXT_XPUB, "".into()).into_paragraphs(),
Paragraph::new(&theme::TEXT_MONO, "".into()).into_paragraphs(),
)
.with_border(theme::borders_horizontal_scroll()),
xpubs: Vec::new(),
xpub_page_count: Vec::new(),
current_page: 0,
};
Ok(result)
@ -75,6 +82,41 @@ where
.push((title, xpub))
.map_err(|_| Error::OutOfRange)
}
fn switch_xpub(&mut self, i: usize, page: usize) -> usize
where
T: Clone,
{
// Context is needed for updating child so that it can request repaint. In this
// case the parent component that handles paging always requests complete
// repaint after page change so we can use a dummy context here.
let mut dummy_ctx = EventCtx::new();
self.xpub_view
.update_title(&mut dummy_ctx, self.xpubs[i].0.clone());
self.xpub_view.update_content(&mut dummy_ctx, |p| {
p.inner_mut().update(self.xpubs[i].1.clone());
let npages = p.page_count();
p.change_page(page);
npages
})
}
fn lookup(&self, scrollbar_page: usize) -> (usize, usize) {
let mut xpub_index = 0;
let mut xpub_page = scrollbar_page;
for page_count in self.xpub_page_count.iter().map(|pc| {
let upc: usize = (*pc).into();
upc
}) {
if page_count <= xpub_page {
xpub_page -= page_count;
xpub_index += 1;
} else {
break;
}
}
(xpub_index, xpub_page)
}
}
impl<T> Paginate for AddressDetails<T>
@ -82,30 +124,23 @@ where
T: ParagraphStrType + Clone,
{
fn page_count(&mut self) -> usize {
2 + self.xpubs.len()
let total_xpub_pages: u8 = self.xpub_page_count.iter().copied().sum();
2usize.saturating_add(total_xpub_pages.into())
}
fn change_page(&mut self, to_page: usize) {
self.current_page = to_page;
if to_page > 1 {
let i = to_page - 2;
// Context is needed for updating child so that it can request repaint. In this
// case the parent component that handles paging always requests complete
// repaint after page change so we can use a dummy context here.
let mut dummy_ctx = EventCtx::new();
self.xpub_view
.update_title(&mut dummy_ctx, self.xpubs[i].0.clone());
self.xpub_view.update_content(&mut dummy_ctx, |p| {
p.inner_mut().update(self.xpubs[i].1.clone());
p.change_page(0)
});
let (xpub_index, xpub_page) = self.lookup(i);
self.switch_xpub(xpub_index, xpub_page);
}
}
}
impl<T> Component for AddressDetails<T>
where
T: ParagraphStrType,
T: ParagraphStrType + Clone,
{
type Msg = Never;
@ -113,6 +148,13 @@ where
self.qr_code.place(bounds);
self.details.place(bounds);
self.xpub_view.place(bounds);
self.xpub_page_count.clear();
for i in 0..self.xpubs.len() {
let npages = self.switch_xpub(i, 0) as u8;
unwrap!(self.xpub_page_count.push(npages));
}
bounds
}

@ -2,8 +2,8 @@ use crate::{
time::Duration,
ui::{
component::{
Component, ComponentExt, Event, EventCtx, FixedHeightBar, Floating, GridPlaced, Map,
Paginate, TimerToken, VSplit,
Component, ComponentExt, Event, EventCtx, FixedHeightBar, Floating, Map, Paginate,
Split, TimerToken,
},
display::{self, toif::Icon, Color, Font},
event::TouchEvent,
@ -33,7 +33,7 @@ pub struct Button<T> {
impl<T> Button<T> {
/// Offsets the baseline of the button text either up (negative) or down
/// (positive).
pub const BASELINE_OFFSET: i16 = -3;
pub const BASELINE_OFFSET: i16 = -2;
pub const fn new(content: ButtonContent<T>) -> Self {
Self {
@ -63,16 +63,16 @@ impl<T> Button<T> {
Self::new(ButtonContent::IconBlend(bg, fg, fg_offset))
}
pub fn empty() -> Self {
pub const fn empty() -> Self {
Self::new(ButtonContent::Empty)
}
pub fn styled(mut self, styles: ButtonStyleSheet) -> Self {
pub const fn styled(mut self, styles: ButtonStyleSheet) -> Self {
self.styles = styles;
self
}
pub fn with_expanded_touch_area(mut self, expand: Insets) -> Self {
pub const fn with_expanded_touch_area(mut self, expand: Insets) -> Self {
self.touch_expand = Some(expand);
self
}
@ -377,7 +377,7 @@ impl<T> Button<T> {
pub fn cancel_confirm(
left: Button<T>,
right: Button<T>,
right_size_factor: usize,
left_is_small: bool,
) -> CancelConfirm<
T,
impl Fn(ButtonMsg) -> Option<CancelConfirmMsg>,
@ -386,28 +386,26 @@ impl<T> Button<T> {
where
T: AsRef<str>,
{
let columns = 1 + right_size_factor;
theme::button_bar((
GridPlaced::new(left)
.with_grid(1, columns)
.with_spacing(theme::BUTTON_SPACING)
.with_row_col(0, 0)
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Cancelled)
}),
GridPlaced::new(right)
.with_grid(1, columns)
.with_spacing(theme::BUTTON_SPACING)
.with_from_to((0, 1), (0, right_size_factor))
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
}),
let width = if left_is_small {
theme::BUTTON_WIDTH
} else {
0
};
theme::button_bar(Split::vertical(
width,
theme::BUTTON_SPACING,
left.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Cancelled)
}),
right.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
}),
))
}
pub fn cancel_confirm_text(
left: Option<T>,
right: T,
right: Option<T>,
) -> CancelConfirm<
T,
impl Fn(ButtonMsg) -> Option<CancelConfirmMsg>,
@ -416,37 +414,21 @@ impl<T> Button<T> {
where
T: AsRef<str>,
{
let (left, right_size_factor) = if let Some(verb) = left {
(Button::with_text(verb), 1)
let left_is_small: bool;
let left = if let Some(verb) = left {
left_is_small = verb.as_ref().len() <= 4;
Button::with_text(verb)
} else {
(Button::with_icon(Icon::new(theme::ICON_CANCEL)), 2)
left_is_small = right.is_some();
Button::with_icon(Icon::new(theme::ICON_CANCEL))
};
let right = Button::with_text(right).styled(theme::button_confirm());
Self::cancel_confirm(left, right, right_size_factor)
}
pub fn cancel_confirm_square(
left: Button<T>,
right: Button<T>,
) -> CancelConfirmSquare<
T,
impl Fn(ButtonMsg) -> Option<CancelConfirmMsg>,
impl Fn(ButtonMsg) -> Option<CancelConfirmMsg>,
>
where
T: AsRef<str>,
{
theme::button_bar(VSplit::new(
theme::BUTTON_HEIGHT,
theme::BUTTON_SPACING,
left.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Cancelled)
}),
right.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
}),
))
let right = if let Some(verb) = right {
Button::with_text(verb).styled(theme::button_confirm())
} else {
Button::with_icon(Icon::new(theme::ICON_CONFIRM)).styled(theme::button_confirm())
};
Self::cancel_confirm(left, right, left_is_small)
}
pub fn cancel_info_confirm(
@ -461,69 +443,29 @@ impl<T> Button<T> {
where
T: AsRef<str>,
{
let right = Button::with_text(confirm).styled(theme::button_confirm());
let top = Button::with_text(info);
let left = Button::with_icon(Icon::new(theme::ICON_CANCEL));
theme::button_bar_rows(
2,
(
GridPlaced::new(left)
.with_grid(2, 3)
.with_spacing(theme::BUTTON_SPACING)
.with_row_col(1, 0)
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Cancelled)
}),
GridPlaced::new(top)
.with_grid(2, 3)
.with_spacing(theme::BUTTON_SPACING)
.with_from_to((0, 0), (0, 2))
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Info)
}),
GridPlaced::new(right)
.with_grid(2, 3)
.with_spacing(theme::BUTTON_SPACING)
.with_from_to((1, 1), (1, 2))
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Confirmed)
}),
let right = Button::with_text(confirm)
.styled(theme::button_confirm())
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Confirmed)
});
let top = Button::with_text(info)
.styled(theme::button_moreinfo())
.map(|msg| (matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Info));
let left = Button::with_icon(Icon::new(theme::ICON_CANCEL)).map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Cancelled)
});
let total_height = theme::BUTTON_HEIGHT + theme::BUTTON_SPACING + theme::INFO_BUTTON_HEIGHT;
FixedHeightBar::bottom(
Split::horizontal(
theme::INFO_BUTTON_HEIGHT,
theme::BUTTON_SPACING,
top,
Split::vertical(theme::BUTTON_WIDTH, theme::BUTTON_SPACING, left, right),
),
total_height,
)
}
pub fn abort_info_enter() -> CancelInfoConfirm<
&'static str,
impl Fn(ButtonMsg) -> Option<CancelInfoConfirmMsg>,
impl Fn(ButtonMsg) -> Option<CancelInfoConfirmMsg>,
impl Fn(ButtonMsg) -> Option<CancelInfoConfirmMsg>,
> {
let left = Button::with_text("ABORT").styled(theme::button_cancel());
let middle = Button::with_text("INFO");
let right = Button::with_text("ENTER").styled(theme::button_confirm());
theme::button_bar((
GridPlaced::new(left)
.with_grid(1, 3)
.with_spacing(theme::BUTTON_SPACING)
.with_row_col(0, 0)
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Cancelled)
}),
GridPlaced::new(middle)
.with_grid(1, 3)
.with_spacing(theme::BUTTON_SPACING)
.with_row_col(0, 1)
.map(|msg| (matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Info)),
GridPlaced::new(right)
.with_grid(1, 3)
.with_spacing(theme::BUTTON_SPACING)
.with_row_col(0, 2)
.map(|msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelInfoConfirmMsg::Confirmed)
}),
))
}
pub fn select_word(
words: [T; 3],
) -> CancelInfoConfirm<
@ -536,38 +478,41 @@ impl<T> Button<T> {
T: AsRef<str>,
{
let btn = move |i, word| {
GridPlaced::new(Button::with_text(word))
.with_grid(3, 1)
.with_spacing(theme::BUTTON_SPACING)
.with_row_col(i, 0)
Button::with_text(word)
.styled(theme::button_pin())
.map(move |msg| {
(matches!(msg, ButtonMsg::Clicked)).then(|| SelectWordMsg::Selected(i))
})
};
let [top, middle, bottom] = words;
theme::button_bar_rows(3, (btn(0, top), btn(1, middle), btn(2, bottom)))
let total_height = 3 * theme::BUTTON_HEIGHT + 2 * theme::BUTTON_SPACING;
FixedHeightBar::bottom(
Split::horizontal(
theme::BUTTON_HEIGHT,
theme::BUTTON_SPACING,
btn(0, top),
Split::horizontal(
theme::BUTTON_HEIGHT,
theme::BUTTON_SPACING,
btn(1, middle),
btn(2, bottom),
),
),
total_height,
)
}
}
type CancelConfirm<T, F0, F1> = FixedHeightBar<(
Map<GridPlaced<Button<T>>, F0>,
Map<GridPlaced<Button<T>>, F1>,
)>;
pub enum CancelConfirmMsg {
Cancelled,
Confirmed,
}
type CancelInfoConfirm<T, F0, F1, F2> = FixedHeightBar<(
Map<GridPlaced<Button<T>>, F0>,
Map<GridPlaced<Button<T>>, F1>,
Map<GridPlaced<Button<T>>, F2>,
)>;
type CancelInfoConfirm<T, F0, F1, F2> =
FixedHeightBar<Split<Map<Button<T>, F0>, Split<Map<Button<T>, F1>, Map<Button<T>, F2>>>>;
type CancelConfirmSquare<T, F0, F1> =
FixedHeightBar<VSplit<Map<Button<T>, F0>, Map<Button<T>, F1>>>;
type CancelConfirm<T, F0, F1> = FixedHeightBar<Split<Map<Button<T>, F0>, Map<Button<T>, F1>>>;
pub enum CancelInfoConfirmMsg {
Cancelled,
@ -658,7 +603,9 @@ where
button: Floating::top_right(
theme::CORNER_BUTTON_SIDE,
theme::CORNER_BUTTON_SPACING,
Button::with_icon(icon),
Button::with_icon(icon)
.with_expanded_touch_area(Insets::uniform(theme::CORNER_BUTTON_SPACING))
.styled(theme::button_moreinfo()),
),
}
}

@ -60,8 +60,8 @@ where
page_swipe.allow_left = scrollbar.has_next_page();
Self {
app_name: Label::new(app_name, Alignment::Center, theme::TEXT_BOLD),
account_name: Label::new("".into(), Alignment::Center, theme::TEXT_BOLD),
app_name: Label::new(app_name, Alignment::Center, theme::TEXT_DEMIBOLD),
account_name: Label::new("".into(), Alignment::Center, theme::TEXT_DEMIBOLD),
page_swipe,
icon: Child::new(Image::new(icon_data)),
get_account,

@ -3,9 +3,8 @@ use crate::ui::{
component::{
base::ComponentExt, label::Label, text::TextStyle, Child, Component, Event, EventCtx,
},
display::{self, toif::Icon, Color},
display::{self, Color, Font},
geometry::{Alignment, Insets, Offset, Rect},
util::icon_text_center,
};
pub struct Frame<T, U> {
@ -55,13 +54,14 @@ where
})
}
pub fn update_content<F>(&mut self, ctx: &mut EventCtx, update_fn: F)
pub fn update_content<F, R>(&mut self, ctx: &mut EventCtx, update_fn: F) -> R
where
F: Fn(&mut T),
F: Fn(&mut T) -> R,
{
self.content.mutate(ctx, |ctx, c| {
update_fn(c);
c.request_complete_repaint(ctx)
let res = update_fn(c);
c.request_complete_repaint(ctx);
res
})
}
}
@ -116,7 +116,6 @@ where
pub struct NotificationFrame<T, U> {
area: Rect,
icon: Icon,
title: U,
content: Child<T>,
}
@ -126,15 +125,12 @@ where
T: Component,
U: AsRef<str>,
{
const HEIGHT: i16 = 32;
const HEIGHT: i16 = 36;
const COLOR: Color = theme::YELLOW;
const TEXT_OFFSET: Offset = Offset::new(1, -2);
const ICON_SPACE: i16 = 8;
const BORDER: i16 = 8;
const BORDER: i16 = 6;
pub fn new(icon: Icon, title: U, content: T) -> Self {
pub fn new(title: U, content: T) -> Self {
Self {
icon,
title,
area: Rect::zero(),
content: Child::new(content),
@ -145,22 +141,18 @@ where
self.content.inner()
}
pub fn paint_notification(area: Rect, icon: Icon, title: &str, color: Color) {
pub fn paint_notification(area: Rect, title: &str, color: Color) {
let (area, _) = area
.inset(Insets::uniform(Self::BORDER))
.split_top(Self::HEIGHT);
let style = TextStyle {
background_color: color,
..theme::TEXT_BOLD
};
let font = Font::BOLD;
display::rect_fill_rounded(area, color, theme::BG, 2);
icon_text_center(
area.center(),
icon,
Self::ICON_SPACE,
display::text_center(
area.center() + Offset::y((font.text_max_height() - font.text_baseline()) / 2),
title,
style,
Self::TEXT_OFFSET,
Font::BOLD,
theme::FG,
color,
);
}
}
@ -184,7 +176,7 @@ where
}
fn paint(&mut self) {
Self::paint_notification(self.area, self.icon, self.title.as_ref(), Self::COLOR);
Self::paint_notification(self.area, self.title.as_ref(), Self::COLOR);
self.content.paint();
}

@ -22,7 +22,7 @@ use super::{theme, Loader, LoaderMsg};
const AREA: Rect = constant::screen();
const TOP_CENTER: Point = AREA.top_center();
const LABEL_Y: i16 = 216;
const LABEL_Y: i16 = 222;
const LOCKED_Y: i16 = 107;
const TAP_Y: i16 = 134;
const HOLD_Y: i16 = 35;
@ -181,7 +181,7 @@ where
if self.loader.is_animating() || self.loader.is_completely_grown(Instant::now()) {
self.paint_loader();
} else {
let mut label_style = theme::TEXT_BOLD;
let mut label_style = theme::TEXT_DEMIBOLD;
label_style.text_color = theme::FG;
let text = HomescreenText {
@ -262,10 +262,7 @@ where
("LOCKED", "Tap to unlock")
};
let mut tap_style = theme::TEXT_NORMAL;
tap_style.text_color = theme::OFF_WHITE;
let mut label_style = theme::TEXT_BOLD;
let mut label_style = theme::TEXT_DEMIBOLD;
label_style.text_color = theme::GREY_LIGHT;
let texts: [HomescreenText; 3] = [
@ -277,7 +274,7 @@ where
},
HomescreenText {
text: tap,
style: tap_style,
style: theme::TEXT_NORMAL,
offset: Offset::new(10, TAP_Y),
icon: None,
},

@ -53,19 +53,20 @@ struct HomescreenTextInfo {
pub const HOMESCREEN_IMAGE_SIZE: i16 = 240;
const HOMESCREEN_MAX_ICON_SIZE: i16 = 20;
const NOTIFICATION_HEIGHT: i16 = 32;
const NOTIFICATION_BORDER: i16 = 8;
const NOTIFICATION_HEIGHT: i16 = 36;
const NOTIFICATION_BORDER: i16 = 6;
const NOTIFICATION_ICON_SPACE: i16 = 8;
const NOTIFICATION_TEXT_OFFSET: Offset = Offset::new(1, -2);
const TEXT_ICON_SPACE: i16 = 2;
const HOMESCREEN_DIM_HIEGHT: i16 = 30;
const HOMESCREEN_DIM_START: i16 = 195;
const HOMESCREEN_DIM: f32 = 0.85;
const HOMESCREEN_DIM_BORDER: i16 = 20;
const HOMESCREEN_DIM_HEIGHT: i16 = 35;
const HOMESCREEN_DIM_START: i16 = 198;
const HOMESCREEN_DIM: f32 = 0.65;
const HOMESCREEN_DIM_BORDER: i16 = theme::BUTTON_SPACING;
const LOCKSCREEN_DIM: f32 = 0.85;
const LOCKSCREEN_DIM: f32 = 0.55;
const LOCKSCREEN_DIM_BG: f32 = 0.0;
const LOCKSCREEN_DIM_ALL: bool = true;
const BLUR_SIZE: usize = 9;
const BLUR_DIV: u32 =
@ -174,14 +175,14 @@ fn homescreen_position_text(
fn homescreen_dim_area(x: i16, y: i16) -> bool {
y >= HOMESCREEN_DIM_START
&& (y > HOMESCREEN_DIM_START + 1
&& y < (HOMESCREEN_DIM_START + HOMESCREEN_DIM_HIEGHT - 1)
&& y < (HOMESCREEN_DIM_START + HOMESCREEN_DIM_HEIGHT - 1)
&& x > HOMESCREEN_DIM_BORDER
&& x < WIDTH - HOMESCREEN_DIM_BORDER)
|| (y > HOMESCREEN_DIM_START
&& y < (HOMESCREEN_DIM_START + HOMESCREEN_DIM_HIEGHT)
&& y < (HOMESCREEN_DIM_START + HOMESCREEN_DIM_HEIGHT)
&& x > HOMESCREEN_DIM_BORDER + 1
&& x < WIDTH - (HOMESCREEN_DIM_BORDER + 1))
|| ((HOMESCREEN_DIM_START..=(HOMESCREEN_DIM_START + HOMESCREEN_DIM_HIEGHT)).contains(&y)
|| ((HOMESCREEN_DIM_START..=(HOMESCREEN_DIM_START + HOMESCREEN_DIM_HEIGHT)).contains(&y)
&& x > HOMESCREEN_DIM_BORDER + 2
&& x < WIDTH - (HOMESCREEN_DIM_BORDER + 2))
}
@ -197,7 +198,7 @@ fn homescreen_line_blurred(
let mut img_buffer = unsafe { get_buffer_16bpp((y & 0x1) as u16, false) };
for x in 0..HOMESCREEN_IMAGE_SIZE {
let c = if homescreen_dim_area(x, y) {
let c = if LOCKSCREEN_DIM_ALL {
let x = x as usize;
let coef = (65536_f32 * LOCKSCREEN_DIM) as u32;

@ -3,12 +3,13 @@ use crate::ui::{
base::ComponentExt, AuxPageMsg, Component, Event, EventCtx, Never, Pad, PageMsg, Paginate,
},
display::{self, Color},
geometry::Rect,
geometry::{Insets, Rect},
};
use super::{theme, ScrollBar, Swipe, SwipeDirection};
const SCROLLBAR_HEIGHT: i16 = 32;
const SCROLLBAR_HEIGHT: i16 = 18;
const SCROLLBAR_BORDER: i16 = 4;
pub struct HorizontalPage<T> {
content: T,
@ -75,10 +76,11 @@ where
fn place(&mut self, bounds: Rect) -> Rect {
self.swipe.place(bounds);
let (content, scrollbar) = bounds.split_bottom(SCROLLBAR_HEIGHT);
let (content, scrollbar) = bounds.split_bottom(SCROLLBAR_HEIGHT + SCROLLBAR_BORDER);
self.pad.place(content);
self.content.place(content);
self.scrollbar.place(scrollbar);
self.scrollbar
.place(scrollbar.inset(Insets::bottom(SCROLLBAR_BORDER)));
self.scrollbar
.set_count_and_active_page(self.content.page_count(), 0);

@ -215,20 +215,21 @@ impl Bip39Input {
{
// Confirm button.
self.button.enable(ctx);
self.button.set_stylesheet(ctx, theme::button_confirm());
self.button.set_stylesheet(ctx, theme::button_pin_confirm());
self.button
.set_content(ctx, ButtonContent::Icon(Icon::new(theme::ICON_CONFIRM)));
.set_content(ctx, ButtonContent::Icon(Icon::new(theme::ICON_LIST_CHECK)));
} else {
// Auto-complete button.
self.button.enable(ctx);
self.button.set_stylesheet(ctx, theme::button_default());
self.button
.set_stylesheet(ctx, theme::button_pin_autocomplete());
self.button
.set_content(ctx, ButtonContent::Icon(Icon::new(theme::ICON_CLICK)));
}
} else {
// Disabled button.
self.button.disable(ctx);
self.button.set_stylesheet(ctx, theme::button_default());
self.button.set_stylesheet(ctx, theme::button_pin());
self.button.set_content(ctx, ButtonContent::Text(""));
}
}

@ -43,11 +43,13 @@ where
Icon::new(theme::ICON_BACK),
Offset::new(30, 17),
)
.styled(theme::button_clear())
.styled(theme::button_reset())
.with_long_press(theme::ERASE_HOLD_DURATION),
)),
input: Child::new(Maybe::hidden(theme::BG, input)),
keys: T::keys().map(Button::with_text).map(Child::new),
keys: T::keys()
.map(|t| Button::with_text(t).styled(theme::button_pin()))
.map(Child::new),
}
}
@ -94,8 +96,10 @@ where
type Msg = MnemonicKeyboardMsg;
fn place(&mut self, bounds: Rect) -> Rect {
let grid =
Grid::new(bounds.inset(theme::borders()), 4, 3).with_spacing(theme::KEYBOARD_SPACING);
let (_, bounds) = bounds
.inset(theme::borders())
.split_bottom(4 * theme::MNEMONIC_BUTTON_HEIGHT + 3 * theme::KEYBOARD_SPACING);
let grid = Grid::new(bounds, 4, 3).with_spacing(theme::KEYBOARD_SPACING);
let back_area = grid.row_col(0, 0);
let input_area = grid.row_col(0, 1).union(grid.row_col(0, 3));

@ -2,13 +2,10 @@ use crate::ui::{
component::{base::ComponentExt, Child, Component, Event, EventCtx, Never},
display,
display::toif::Icon,
geometry::{Grid, Insets, Offset, Rect},
geometry::{Grid, Offset, Rect},
model_tt::component::{
button::{Button, ButtonContent, ButtonMsg},
keyboard::common::{
paint_pending_marker, MultiTapKeyboard, TextBox, HEADER_HEIGHT, HEADER_PADDING_BOTTOM,
HEADER_PADDING_SIDE,
},
keyboard::common::{paint_pending_marker, MultiTapKeyboard, TextBox},
swipe::{Swipe, SwipeDirection},
theme, ScrollBar,
},
@ -41,6 +38,7 @@ const KEYBOARD: [[&str; KEY_COUNT]; PAGE_COUNT] = [
];
const MAX_LENGTH: usize = 50;
const INPUT_AREA_HEIGHT: i16 = ScrollBar::DOT_SIZE + 9;
impl PassphraseKeyboard {
pub fn new() -> Self {
@ -59,8 +57,9 @@ impl PassphraseKeyboard {
.initially_enabled(false)
.with_long_press(theme::ERASE_HOLD_DURATION)
.into_child(),
keys: KEYBOARD[STARTING_PAGE]
.map(|text| Child::new(Button::new(Self::key_content(text)))),
keys: KEYBOARD[STARTING_PAGE].map(|text| {
Child::new(Button::new(Self::key_content(text)).styled(theme::button_pin()))
}),
scrollbar: ScrollBar::horizontal(),
fade: false,
}
@ -152,14 +151,13 @@ impl Component for PassphraseKeyboard {
fn place(&mut self, bounds: Rect) -> Rect {
let bounds = bounds.inset(theme::borders());
let (input_area, key_grid_area) = bounds.split_top(HEADER_HEIGHT + HEADER_PADDING_BOTTOM);
let (input_area, key_grid_area) =
bounds.split_bottom(4 * theme::PIN_BUTTON_HEIGHT + 3 * theme::BUTTON_SPACING);
let (input_area, scroll_area) =
input_area.split_bottom(ScrollBar::DOT_SIZE + theme::KEYBOARD_SPACING);
let (input_area, scroll_area) = input_area.split_bottom(INPUT_AREA_HEIGHT);
let (scroll_area, _) = scroll_area.split_top(ScrollBar::DOT_SIZE);
let input_area = input_area.inset(Insets::sides(HEADER_PADDING_SIDE));
let key_grid = Grid::new(key_grid_area, 4, 3).with_spacing(theme::KEYBOARD_SPACING);
let key_grid = Grid::new(key_grid_area, 4, 3).with_spacing(theme::BUTTON_SPACING);
let confirm_btn_area = key_grid.cell(11);
let back_btn_area = key_grid.cell(9);

@ -59,8 +59,8 @@ where
T: AsRef<str>,
{
// Label position fine-tuning.
const MAJOR_OFF: Offset = Offset::y(-2);
const MINOR_OFF: Offset = Offset::y(-1);
const MAJOR_OFF: Offset = Offset::y(11);
const MINOR_OFF: Offset = Offset::y(11);
pub fn new(
major_prompt: T,
@ -165,14 +165,14 @@ where
// Prompts and PIN dots display.
let (header, keypad) = bounds
.inset(borders_no_top)
.split_top(theme::borders().top + HEADER_HEIGHT + HEADER_PADDING_BOTTOM);
.split_bottom(4 * theme::PIN_BUTTON_HEIGHT + 3 * theme::BUTTON_SPACING);
let prompt = header.inset(HEADER_PADDING);
// the inset -3 is a workaround for long text in "re-enter wipe code"
let major_area = prompt.translate(Self::MAJOR_OFF).inset(Insets::right(-3));
let minor_area = prompt.translate(Self::MINOR_OFF);
// Control buttons.
let grid = Grid::new(keypad, 4, 3).with_spacing(theme::KEYBOARD_SPACING);
let grid = Grid::new(keypad, 4, 3).with_spacing(theme::BUTTON_SPACING);
// Prompts and PIN dots display.
self.textbox_pad.place(header);

@ -224,13 +224,13 @@ impl Slip39Input {
if self.final_word.is_some() {
// Confirm button.
self.button.enable(ctx);
self.button.set_stylesheet(ctx, theme::button_confirm());
self.button.set_stylesheet(ctx, theme::button_pin_confirm());
self.button
.set_content(ctx, ButtonContent::Icon(Icon::new(theme::ICON_CONFIRM)));
.set_content(ctx, ButtonContent::Icon(Icon::new(theme::ICON_LIST_CHECK)));
} else {
// Disabled button.
self.button.disable(ctx);
self.button.set_stylesheet(ctx, theme::button_default());
self.button.set_stylesheet(ctx, theme::button_pin());
self.button.set_content(ctx, ButtonContent::Text(""));
}
}

@ -22,7 +22,7 @@ pub enum SelectWordCountMsg {
impl SelectWordCount {
pub fn new() -> Self {
SelectWordCount {
button: LABELS.map(Button::with_text),
button: LABELS.map(|t| Button::with_text(t).styled(theme::button_pin())),
}
}
}
@ -31,7 +31,7 @@ impl Component for SelectWordCount {
type Msg = SelectWordCountMsg;
fn place(&mut self, bounds: Rect) -> Rect {
let (_, bounds) = bounds.split_bottom(theme::button_rows(2));
let (_, bounds) = bounds.split_bottom(2 * theme::BUTTON_HEIGHT + theme::BUTTON_SPACING);
let grid = Grid::new(bounds, 2, 6).with_spacing(theme::BUTTON_SPACING);
for (btn, (x, y)) in self.button.iter_mut().zip(CELLS) {
btn.place(grid.cells(GridCellSpan {

@ -87,13 +87,12 @@ where
theme::CONTENT_BORDER,
));
let grid = Grid::new(button_area, 1, 3).with_spacing(theme::KEYBOARD_SPACING);
let grid = Grid::new(button_area, 1, 2).with_spacing(theme::KEYBOARD_SPACING);
self.input.place(input_area);
self.paragraphs.place(content_area);
self.paragraphs_pad.place(content_area);
self.info_button.place(grid.row_col(0, 0));
self.confirm_button
.place(grid.row_col(0, 1).union(grid.row_col(0, 2)));
self.confirm_button.place(grid.row_col(0, 1));
bounds
}

@ -368,7 +368,7 @@ where
impl<T> ComponentMsgObj for AddressDetails<T>
where
T: ParagraphStrType,
T: ParagraphStrType + Clone,
{
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
unreachable!();
@ -381,7 +381,10 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
let action: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
let description: Option<StrBuffer> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let verb: StrBuffer = kwargs.get_or(Qstr::MP_QSTR_verb, "CONFIRM".into())?;
let verb: Option<StrBuffer> = kwargs
.get(Qstr::MP_QSTR_verb)
.unwrap_or_else(|_| Obj::const_none())
.try_into_option()?;
let verb_cancel: Option<StrBuffer> = kwargs
.get(Qstr::MP_QSTR_verb_cancel)
.unwrap_or_else(|_| Obj::const_none())
@ -396,12 +399,12 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
let mut paragraphs = ParagraphVecShort::new();
if !reverse {
paragraphs
.add(Paragraph::new(&theme::TEXT_BOLD, action))
.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_BOLD, action));
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, action));
}
paragraphs.into_paragraphs()
};
@ -440,7 +443,7 @@ fn confirm_blob(
extra: extra.unwrap_or_else(StrBuffer::empty),
data: data.try_into()?,
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_BOLD,
extra_font: &theme::TEXT_DEMIBOLD,
data_font: &theme::TEXT_MONO,
}
.into_paragraphs();
@ -452,7 +455,7 @@ fn confirm_blob(
SwipeHoldPage::new(paragraphs, theme::BG),
))?
} else if let Some(verb) = verb {
let buttons = Button::cancel_confirm_text(verb_cancel, verb);
let buttons = Button::cancel_confirm_text(verb_cancel, Some(verb));
LayoutObj::new(Frame::left_aligned(
theme::label_title(),
title,
@ -499,19 +502,14 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
extra: extra.unwrap_or_else(StrBuffer::empty),
data: data.try_into()?,
description_font: &theme::TEXT_NORMAL,
extra_font: &theme::TEXT_BOLD,
extra_font: &theme::TEXT_DEMIBOLD,
data_font: &theme::TEXT_MONO,
}
.into_paragraphs();
let buttons = Button::cancel_confirm(
Button::<&'static str>::with_icon(Icon::new(theme::ICON_CANCEL)),
Button::<&'static str>::with_icon(Icon::new(theme::ICON_CONFIRM))
.styled(theme::button_confirm()),
1,
);
let buttons = Button::cancel_confirm_text(None, Some("CONFIRM"));
let obj = LayoutObj::new(FloatingButton::top_right_corner(
Icon::new(theme::ICON_INFO_CIRCLE),
Icon::new(theme::ICON_CORNER_INFO),
Frame::left_aligned(
theme::label_title(),
title,
@ -542,7 +540,7 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
SwipeHoldPage::new(paragraphs.into_paragraphs(), theme::BG),
))?
} else {
let buttons = Button::cancel_confirm_text(None, "CONFIRM");
let buttons = Button::cancel_confirm_text(None, Some("CONFIRM"));
LayoutObj::new(Frame::left_aligned(
theme::label_title(),
title,
@ -570,7 +568,7 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
_ => return Err(Error::ValueError(cstr!("Invalid image."))),
};
let buttons = Button::cancel_confirm_text(None, "CONFIRM");
let buttons = Button::cancel_confirm_text(None, Some("CONFIRM"));
let obj = LayoutObj::new(
Frame::centered(
theme::label_title(),
@ -590,33 +588,26 @@ extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs:
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
let paragraphs = Paragraphs::new(Paragraph::new(
&theme::TEXT_NORMAL,
StrBuffer::from("By continuing you agree\nto Trezor Company's\nterms and conditions."),
));
let url = FormattedText::new(
theme::TEXT_NORMAL,
theme::FORMATTED,
"More info at {demibold}trezor.io/tos",
);
let paragraphs = Paragraphs::new([
Paragraph::new(
&theme::TEXT_NORMAL,
StrBuffer::from(
"By continuing you agree\nto Trezor Company's\nterms and conditions.\r",
),
),
Paragraph::new(&theme::TEXT_NORMAL, StrBuffer::from("More info at")),
Paragraph::new(&theme::TEXT_DEMIBOLD, StrBuffer::from("trezor.io/tos")),
]);
let buttons = Button::cancel_confirm(
Button::with_icon(Icon::new(theme::ICON_CANCEL)),
Button::with_text(button).styled(theme::button_confirm()),
3,
true,
);
let obj = LayoutObj::new(
Frame::left_aligned(
theme::label_title(),
title,
Dialog::new(
(
GridPlaced::new(paragraphs)
.with_grid(3, 1)
.with_from_to((0, 0), (1, 0)),
GridPlaced::new(url).with_grid(3, 1).with_row_col(2, 0),
),
buttons,
),
Dialog::new(paragraphs, buttons),
)
.with_border(theme::borders()),
)?;
@ -635,7 +626,7 @@ extern "C" fn new_show_qr(n_args: usize, args: *const Obj, kwargs: *mut Map) ->
let buttons = Button::cancel_confirm(
Button::with_text(verb_cancel),
Button::with_text("CONFIRM".into()).styled(theme::button_confirm()),
1,
false,
);
let obj = LayoutObj::new(
@ -671,7 +662,7 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
let obj = LayoutObj::new(
HorizontalPage::new(
FloatingButton::top_right_corner(Icon::new(theme::ICON_CANCEL_LARGER), ad),
FloatingButton::top_right_corner(Icon::new(theme::ICON_CORNER_CANCEL), ad),
theme::BG,
)
.with_swipe_right_to_go_back(),
@ -746,7 +737,7 @@ extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs:
let buttons = Button::cancel_confirm(
Button::with_icon(Icon::new(theme::ICON_CANCEL)),
Button::with_text("NEXT").styled(theme::button_confirm()),
2,
true,
);
let obj = LayoutObj::new(Frame::left_aligned(
@ -781,7 +772,7 @@ extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *m
let buttons = Button::cancel_confirm(
Button::with_icon(Icon::new(theme::ICON_CANCEL)),
Button::with_text("NEXT").styled(theme::button_confirm()),
2,
true,
);
let obj = LayoutObj::new(Frame::left_aligned(
@ -832,7 +823,7 @@ fn new_show_modal(
Button::cancel_confirm(
Button::with_icon(Icon::new(theme::ICON_CANCEL)).styled(theme::button_cancel()),
Button::with_text(button).styled(button_style),
2,
true,
),
)
.with_description(description),
@ -890,7 +881,7 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
let controls = Button::cancel_confirm(
Button::with_icon(Icon::new(theme::ICON_CANCEL)),
Button::with_text("CONFIRM").styled(theme::button_confirm()),
2,
true,
);
let fido_page = FidoConfirm::new(app_name, get_page, page_count, icon, controls);
@ -906,7 +897,7 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
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(
Icon::new(theme::IMAGE_BG_TRIANGLE),
Icon::new(theme::IMAGE_BG_OCTAGON),
Icon::new(theme::IMAGE_FG_WARN),
theme::WARN_COLOR,
theme::FG,
@ -952,15 +943,21 @@ extern "C" fn new_show_mismatch() -> Obj {
let url: StrBuffer = "trezor.io/support".into();
let button = "QUIT";
let icon = BlendedImage::single(Icon::new(theme::ICON_OCTA), theme::WARN_COLOR, theme::BG);
let icon = BlendedImage::new(
Icon::new(theme::IMAGE_BG_OCTAGON),
Icon::new(theme::IMAGE_FG_WARN),
theme::WARN_COLOR,
theme::FG,
theme::BG,
);
let obj = LayoutObj::new(
IconDialog::new(
icon,
title,
Button::cancel_confirm_square(
Button::cancel_confirm(
Button::with_icon(Icon::new(theme::ICON_BACK)),
Button::with_text(button).styled(theme::button_reset()),
true,
),
)
.with_description(description)
@ -1095,9 +1092,9 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut
let paragraphs = Paragraphs::new([
Paragraph::new(&theme::TEXT_NORMAL, "Maximum rounds:".into()),
Paragraph::new(&theme::TEXT_BOLD, max_rounds),
Paragraph::new(&theme::TEXT_MONO, max_rounds),
Paragraph::new(&theme::TEXT_NORMAL, "Maximum mining fee:".into()),
Paragraph::new(&theme::TEXT_BOLD, max_feerate),
Paragraph::new(&theme::TEXT_MONO, max_feerate),
]);
let obj = LayoutObj::new(Frame::left_aligned(
@ -1162,7 +1159,7 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
let words_iterable: Obj = kwargs.get(Qstr::MP_QSTR_words)?;
let words: [StrBuffer; 3] = iter_into_array(words_iterable)?;
let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]);
let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_DEMIBOLD, description)]);
let buttons = Button::select_word(words);
let obj = LayoutObj::new(Frame::left_aligned(
@ -1295,7 +1292,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false).unwrap();
let paragraphs = Paragraphs::new([
Paragraph::new(&theme::TEXT_BOLD, title).centered(),
Paragraph::new(&theme::TEXT_DEMIBOLD, title).centered(),
Paragraph::new(&theme::TEXT_NORMAL_OFF_WHITE, description).centered(),
])
.with_spacing(theme::RECOVERY_SPACING);
@ -1308,15 +1305,16 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
let obj = if info_button {
LayoutObj::new(NotificationFrame::new(
Icon::new(theme::ICON_WARN),
notification,
Dialog::new(paragraphs, Button::<&'static str>::abort_info_enter()),
Dialog::new(
paragraphs,
Button::cancel_info_confirm("CONTINUE", "MORE INFO"),
),
))?
} else {
LayoutObj::new(NotificationFrame::new(
Icon::new(theme::ICON_WARN),
notification,
Dialog::new(paragraphs, Button::cancel_confirm_text(None, button)),
Dialog::new(paragraphs, Button::cancel_confirm_text(None, Some(button))),
))?
};
Ok(obj.into())
@ -1334,11 +1332,15 @@ extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mu
let title = if dry_run {
"SEED CHECK"
} else {
"RECOVERY MODE"
"WALLET RECOVERY"
};
let paragraphs = Paragraphs::new(
Paragraph::new(&theme::TEXT_BOLD, StrBuffer::from("Number of words?")).centered(),
Paragraph::new(
&theme::TEXT_DEMIBOLD,
StrBuffer::from("Select number of words in your recovery seed."),
)
.centered(),
);
let obj = LayoutObj::new(
@ -1384,7 +1386,7 @@ extern "C" fn new_show_remaining_shares(n_args: usize, args: *const Obj, kwargs:
for page in iter {
let [title, description]: [StrBuffer; 2] = iter_into_array(page)?;
paragraphs
.add(Paragraph::new(&theme::TEXT_BOLD, title))
.add(Paragraph::new(&theme::TEXT_DEMIBOLD, title))
.add(Paragraph::new(&theme::TEXT_NORMAL, description).break_after());
}
@ -1915,7 +1917,7 @@ mod tests {
#[test]
fn trace_example_layout() {
let buttons =
Button::cancel_confirm(Button::with_text("Left"), Button::with_text("Right"), 1);
Button::cancel_confirm(Button::with_text("Left"), Button::with_text("Right"), false);
let mut layout = Dialog::new(
FormattedText::new(
theme::TEXT_NORMAL,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save