diff --git a/core/assets/arrow-right16.png b/core/assets/arrow-right16.png new file mode 100644 index 0000000000..63ad6e313c Binary files /dev/null and b/core/assets/arrow-right16.png differ diff --git a/core/assets/back_btn.png b/core/assets/back_btn.png deleted file mode 100644 index f7e591f698..0000000000 Binary files a/core/assets/back_btn.png and /dev/null differ diff --git a/core/assets/back_btn_tall.png b/core/assets/back_btn_tall.png deleted file mode 100644 index 8e054340f0..0000000000 Binary files a/core/assets/back_btn_tall.png and /dev/null differ diff --git a/core/assets/bg-back52.png b/core/assets/bg-back52.png new file mode 100644 index 0000000000..7dc3cd16db Binary files /dev/null and b/core/assets/bg-back52.png differ diff --git a/core/assets/cancel.png b/core/assets/cancel.png deleted file mode 100644 index 5cff6ab6bf..0000000000 Binary files a/core/assets/cancel.png and /dev/null differ diff --git a/core/assets/caret-down24.png b/core/assets/caret-down24.png new file mode 100644 index 0000000000..50526e9fe7 Binary files /dev/null and b/core/assets/caret-down24.png differ diff --git a/core/assets/caret-left24.png b/core/assets/caret-left24.png new file mode 100644 index 0000000000..74a9a33df1 Binary files /dev/null and b/core/assets/caret-left24.png differ diff --git a/core/assets/caret-right24.png b/core/assets/caret-right24.png new file mode 100644 index 0000000000..f78b161823 Binary files /dev/null and b/core/assets/caret-right24.png differ diff --git a/core/assets/caret-up24.png b/core/assets/caret-up24.png new file mode 100644 index 0000000000..fda86d4abb Binary files /dev/null and b/core/assets/caret-up24.png differ diff --git a/core/assets/check.png b/core/assets/check.png deleted file mode 100644 index 8f290f3318..0000000000 Binary files a/core/assets/check.png and /dev/null differ diff --git a/core/assets/check16.png b/core/assets/check16.png new file mode 100644 index 0000000000..be64cca490 Binary files /dev/null and b/core/assets/check16.png differ diff --git a/core/assets/check24.png b/core/assets/check24.png new file mode 100644 index 0000000000..889f925bf5 Binary files /dev/null and b/core/assets/check24.png differ diff --git a/core/assets/check_list.png b/core/assets/check_list.png deleted file mode 100644 index a53b2a024a..0000000000 Binary files a/core/assets/check_list.png and /dev/null differ diff --git a/core/assets/circle.png b/core/assets/circle.png deleted file mode 100644 index 56a3287b6e..0000000000 Binary files a/core/assets/circle.png and /dev/null differ diff --git a/core/assets/circle48.png b/core/assets/circle48.png new file mode 100644 index 0000000000..e171b97f88 Binary files /dev/null and b/core/assets/circle48.png differ diff --git a/core/assets/coinjoin16.png b/core/assets/coinjoin16.png new file mode 100644 index 0000000000..ac4470474f Binary files /dev/null and b/core/assets/coinjoin16.png differ diff --git a/core/assets/confirm.png b/core/assets/confirm.png deleted file mode 100644 index 69a3df952a..0000000000 Binary files a/core/assets/confirm.png and /dev/null differ diff --git a/core/assets/current.png b/core/assets/current.png deleted file mode 100644 index 41213a46e7..0000000000 Binary files a/core/assets/current.png and /dev/null differ diff --git a/core/assets/error.png b/core/assets/error.png deleted file mode 100644 index 132547c4fa..0000000000 Binary files a/core/assets/error.png and /dev/null differ diff --git a/core/assets/error_fg.png b/core/assets/error_fg.png deleted file mode 100644 index 657d6dc345..0000000000 Binary files a/core/assets/error_fg.png and /dev/null differ diff --git a/core/assets/fg-check48.png b/core/assets/fg-check48.png new file mode 100644 index 0000000000..1a79d71285 Binary files /dev/null and b/core/assets/fg-check48.png differ diff --git a/core/assets/fg-error48.png b/core/assets/fg-error48.png new file mode 100644 index 0000000000..b0af74db88 Binary files /dev/null and b/core/assets/fg-error48.png differ diff --git a/core/assets/fg-info48.png b/core/assets/fg-info48.png new file mode 100644 index 0000000000..048267faf9 Binary files /dev/null and b/core/assets/fg-info48.png differ diff --git a/core/assets/fg-user48.png b/core/assets/fg-user48.png new file mode 100644 index 0000000000..ce69288fdc Binary files /dev/null and b/core/assets/fg-user48.png differ diff --git a/core/assets/fg-warning48.png b/core/assets/fg-warning48.png new file mode 100644 index 0000000000..385594de2f Binary files /dev/null and b/core/assets/fg-warning48.png differ diff --git a/core/assets/info-circle.png b/core/assets/info-circle.png deleted file mode 100644 index 3db384f5b9..0000000000 Binary files a/core/assets/info-circle.png and /dev/null differ diff --git a/core/assets/info.png b/core/assets/info.png deleted file mode 100644 index af15fbf3d9..0000000000 Binary files a/core/assets/info.png and /dev/null differ diff --git a/core/assets/info32.png b/core/assets/info32.png new file mode 100644 index 0000000000..ff68382d60 Binary files /dev/null and b/core/assets/info32.png differ diff --git a/core/assets/info_fg.png b/core/assets/info_fg.png deleted file mode 100644 index 55ec533d1a..0000000000 Binary files a/core/assets/info_fg.png and /dev/null differ diff --git a/core/assets/lock-new.png b/core/assets/lock16.png similarity index 100% rename from core/assets/lock-new.png rename to core/assets/lock16.png diff --git a/core/assets/octa-bang.png b/core/assets/octa-bang.png deleted file mode 100644 index f3e7f5179f..0000000000 Binary files a/core/assets/octa-bang.png and /dev/null differ diff --git a/core/assets/octagon48.png b/core/assets/octagon48.png new file mode 100644 index 0000000000..a35f8cf1f4 Binary files /dev/null and b/core/assets/octagon48.png differ diff --git a/core/assets/success.png b/core/assets/success.png deleted file mode 100644 index a30c455366..0000000000 Binary files a/core/assets/success.png and /dev/null differ diff --git a/core/assets/success_fg.png b/core/assets/success_fg.png deleted file mode 100644 index f133c7aaf9..0000000000 Binary files a/core/assets/success_fg.png and /dev/null differ diff --git a/core/assets/triangle.png b/core/assets/triangle.png deleted file mode 100644 index 3ff4722452..0000000000 Binary files a/core/assets/triangle.png and /dev/null differ diff --git a/core/assets/warn-icon.png b/core/assets/warn-icon.png deleted file mode 100644 index 2ae3841dd2..0000000000 Binary files a/core/assets/warn-icon.png and /dev/null differ diff --git a/core/assets/warn.png b/core/assets/warn.png deleted file mode 100644 index 39d160084e..0000000000 Binary files a/core/assets/warn.png and /dev/null differ diff --git a/core/assets/warn_fg.png b/core/assets/warn_fg.png deleted file mode 100644 index d3ccbc3757..0000000000 Binary files a/core/assets/warn_fg.png and /dev/null differ diff --git a/core/assets/warning16.png b/core/assets/warning16.png new file mode 100644 index 0000000000..d9854f00b3 Binary files /dev/null and b/core/assets/warning16.png differ diff --git a/core/assets/x24.png b/core/assets/x24.png new file mode 100644 index 0000000000..4da9a6f9ea Binary files /dev/null and b/core/assets/x24.png differ diff --git a/core/assets/x32.png b/core/assets/x32.png new file mode 100644 index 0000000000..6cef1cab93 Binary files /dev/null and b/core/assets/x32.png differ diff --git a/core/embed/extmod/modtrezorui/buffers.h b/core/embed/extmod/modtrezorui/buffers.h index 339876fe73..ca3f1431ec 100644 --- a/core/embed/extmod/modtrezorui/buffers.h +++ b/core/embed/extmod/modtrezorui/buffers.h @@ -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 diff --git a/core/embed/extmod/modtrezorui/display.c b/core/embed/extmod/modtrezorui/display.c index f1203f6b0d..a4cf2969dc 100644 --- a/core/embed/extmod/modtrezorui/display.c +++ b/core/embed/extmod/modtrezorui/display.c @@ -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) { diff --git a/core/embed/extmod/modtrezorui/modtrezorui-display.h b/core/embed/extmod/modtrezorui/modtrezorui-display.h index 2c633f5ef2..9eead63e0f 100644 --- a/core/embed/extmod/modtrezorui/modtrezorui-display.h +++ b/core/embed/extmod/modtrezorui/modtrezorui-display.h @@ -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)}, diff --git a/core/embed/rust/src/ui/component/mod.rs b/core/embed/rust/src/ui/component/mod.rs index 502dd39465..a89f77cf20 100644 --- a/core/embed/rust/src/ui/component/mod.rs +++ b/core/embed/rust/src/ui/component/mod.rs @@ -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, diff --git a/core/embed/rust/src/ui/component/placed.rs b/core/embed/rust/src/ui/component/placed.rs index 0d67ab4359..8f709ac332 100644 --- a/core/embed/rust/src/ui/component/placed.rs +++ b/core/embed/rust/src/ui/component/placed.rs @@ -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 { @@ -195,25 +195,35 @@ where } } -pub struct VSplit { +pub struct Split { first: T, second: U, - width: i16, + axis: Axis, + size: i16, spacing: i16, } -impl VSplit { - pub const fn new(width: i16, spacing: i16, first: T, second: U) -> Self { +impl Split { + 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 Component for VSplit +impl Component for Split where T: Component, U: Component, @@ -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 crate::trace::Trace for VSplit +impl crate::trace::Trace for Split 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(); diff --git a/core/embed/rust/src/ui/model_tt/bootloader/theme.rs b/core/embed/rust/src/ui/model_tt/bootloader/theme.rs index e5fc4cf3da..bba7416a17 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/theme.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/theme.rs @@ -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"); diff --git a/core/embed/rust/src/ui/model_tt/component/address_details.rs b/core/embed/rust/src/ui/model_tt/component/address_details.rs index aa7c7c8436..1140063603 100644 --- a/core/embed/rust/src/ui/model_tt/component/address_details.rs +++ b/core/embed/rust/src/ui/model_tt/component/address_details.rs @@ -15,24 +15,30 @@ use crate::{ use super::{theme, Frame}; +const MAX_XPUBS: usize = 16; + pub struct AddressDetails { qr_code: Frame, details: Frame>, T>, xpub_view: Frame>, T>, - xpubs: Vec<(T, T), 16>, + xpubs: Vec<(T, T), MAX_XPUBS>, + xpub_page_count: Vec, current_page: usize, } impl AddressDetails where - T: ParagraphStrType + From<&'static str>, + T: ParagraphStrType, { pub fn new( qr_address: T, case_sensitive: bool, account: Option, path: Option, - ) -> Result { + ) -> Result + 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 Paginate for AddressDetails @@ -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 Component for AddressDetails 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 } diff --git a/core/embed/rust/src/ui/model_tt/component/button.rs b/core/embed/rust/src/ui/model_tt/component/button.rs index 87ce99d8bf..1917688b10 100644 --- a/core/embed/rust/src/ui/model_tt/component/button.rs +++ b/core/embed/rust/src/ui/model_tt/component/button.rs @@ -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 { impl Button { /// 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) -> Self { Self { @@ -63,16 +63,16 @@ impl Button { 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 Button { pub fn cancel_confirm( left: Button, right: Button, - right_size_factor: usize, + left_is_small: bool, ) -> CancelConfirm< T, impl Fn(ButtonMsg) -> Option, @@ -386,59 +386,13 @@ impl Button { where T: AsRef, { - 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) - }), - )) - } - - pub fn cancel_confirm_text( - left: Option, - right: T, - ) -> CancelConfirm< - T, - impl Fn(ButtonMsg) -> Option, - impl Fn(ButtonMsg) -> Option, - > - where - T: AsRef, - { - let (left, right_size_factor) = if let Some(verb) = left { - (Button::with_text(verb), 1) + let width = if left_is_small { + theme::BUTTON_WIDTH } else { - (Button::with_icon(Icon::new(theme::ICON_CANCEL)), 2) + 0 }; - 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, - right: Button, - ) -> CancelConfirmSquare< - T, - impl Fn(ButtonMsg) -> Option, - impl Fn(ButtonMsg) -> Option, - > - where - T: AsRef, - { - theme::button_bar(VSplit::new( - theme::BUTTON_HEIGHT, + theme::button_bar(Split::vertical( + width, theme::BUTTON_SPACING, left.map(|msg| { (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Cancelled) @@ -449,6 +403,34 @@ impl Button { )) } + pub fn cancel_confirm_text( + left: Option, + right: Option, + ) -> CancelConfirm< + T, + impl Fn(ButtonMsg) -> Option, + impl Fn(ButtonMsg) -> Option, + > + where + T: AsRef, + { + 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 { + left_is_small = right.is_some(); + Button::with_icon(Icon::new(theme::ICON_CANCEL)) + }; + 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( confirm: T, info: T, @@ -461,69 +443,29 @@ impl Button { where T: AsRef, { - 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, - impl Fn(ButtonMsg) -> Option, - impl Fn(ButtonMsg) -> Option, - > { - 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 Button { T: AsRef, { 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 = FixedHeightBar<( - Map>, F0>, - Map>, F1>, -)>; - pub enum CancelConfirmMsg { Cancelled, Confirmed, } -type CancelInfoConfirm = FixedHeightBar<( - Map>, F0>, - Map>, F1>, - Map>, F2>, -)>; +type CancelInfoConfirm = + FixedHeightBar, F0>, Split, F1>, Map, F2>>>>; -type CancelConfirmSquare = - FixedHeightBar, F0>, Map, F1>>>; +type CancelConfirm = FixedHeightBar, F0>, Map, 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()), ), } } diff --git a/core/embed/rust/src/ui/model_tt/component/fido.rs b/core/embed/rust/src/ui/model_tt/component/fido.rs index ed2e7dffbf..923d932bc8 100644 --- a/core/embed/rust/src/ui/model_tt/component/fido.rs +++ b/core/embed/rust/src/ui/model_tt/component/fido.rs @@ -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, diff --git a/core/embed/rust/src/ui/model_tt/component/frame.rs b/core/embed/rust/src/ui/model_tt/component/frame.rs index aafb2e64c2..7fc67cb17d 100644 --- a/core/embed/rust/src/ui/model_tt/component/frame.rs +++ b/core/embed/rust/src/ui/model_tt/component/frame.rs @@ -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 { @@ -55,13 +54,14 @@ where }) } - pub fn update_content(&mut self, ctx: &mut EventCtx, update_fn: F) + pub fn update_content(&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 { area: Rect, - icon: Icon, title: U, content: Child, } @@ -126,15 +125,12 @@ where T: Component, U: AsRef, { - 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(); } diff --git a/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs b/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs index 1b47ad51c1..9921efa4a3 100644 --- a/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs +++ b/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs @@ -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, }, diff --git a/core/embed/rust/src/ui/model_tt/component/homescreen/render.rs b/core/embed/rust/src/ui/model_tt/component/homescreen/render.rs index 70f91713ba..1a35e8cf7c 100644 --- a/core/embed/rust/src/ui/model_tt/component/homescreen/render.rs +++ b/core/embed/rust/src/ui/model_tt/component/homescreen/render.rs @@ -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; diff --git a/core/embed/rust/src/ui/model_tt/component/horizontal_page.rs b/core/embed/rust/src/ui/model_tt/component/horizontal_page.rs index 1652335baa..e6ee842f54 100644 --- a/core/embed/rust/src/ui/model_tt/component/horizontal_page.rs +++ b/core/embed/rust/src/ui/model_tt/component/horizontal_page.rs @@ -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 { 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); diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs index 6ea210ee13..31601df79e 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs @@ -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("")); } } diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs index fa34523522..cf5aeb9120 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs @@ -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)); diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs index 22516324ca..7e0995e106 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs @@ -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); diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs index 8b3d70a0fc..2301e2d7ec 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs @@ -59,8 +59,8 @@ where T: AsRef, { // 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); diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs index 034f7af600..3cd3aa6ba5 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs @@ -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("")); } } diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs index 5d580c7acf..3562419937 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs @@ -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 { diff --git a/core/embed/rust/src/ui/model_tt/component/number_input.rs b/core/embed/rust/src/ui/model_tt/component/number_input.rs index f4a15cc68b..7637e2e8b0 100644 --- a/core/embed/rust/src/ui/model_tt/component/number_input.rs +++ b/core/embed/rust/src/ui/model_tt/component/number_input.rs @@ -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 } diff --git a/core/embed/rust/src/ui/model_tt/layout.rs b/core/embed/rust/src/ui/model_tt/layout.rs index 2c5cf7f71a..9761a9d624 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -368,7 +368,7 @@ where impl ComponentMsgObj for AddressDetails where - T: ParagraphStrType, + T: ParagraphStrType + Clone, { fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result { unreachable!(); @@ -381,7 +381,10 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M let action: Option = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?; let description: Option = kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; - let verb: StrBuffer = kwargs.get_or(Qstr::MP_QSTR_verb, "CONFIRM".into())?; + let verb: Option = kwargs + .get(Qstr::MP_QSTR_verb) + .unwrap_or_else(|_| Obj::const_none()) + .try_into_option()?; let verb_cancel: Option = 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, diff --git a/core/embed/rust/src/ui/model_tt/res/arrow-right16.toif b/core/embed/rust/src/ui/model_tt/res/arrow-right16.toif new file mode 100644 index 0000000000..027edec0a2 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/arrow-right16.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/back.toif b/core/embed/rust/src/ui/model_tt/res/back.toif deleted file mode 100644 index 08ce9e4255..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/back.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/back_btn.toif b/core/embed/rust/src/ui/model_tt/res/back_btn.toif deleted file mode 100644 index 2a79539573..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/back_btn.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/bg-back40.toif b/core/embed/rust/src/ui/model_tt/res/bg-back40.toif new file mode 100644 index 0000000000..0245cf5a81 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/bg-back40.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/bg-back52.toif b/core/embed/rust/src/ui/model_tt/res/bg-back52.toif new file mode 100644 index 0000000000..6f16f72fef Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/bg-back52.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/cancel-larger.toif b/core/embed/rust/src/ui/model_tt/res/cancel-larger.toif deleted file mode 100644 index a53d508b3d..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/cancel-larger.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/cancel.toif b/core/embed/rust/src/ui/model_tt/res/cancel.toif deleted file mode 100644 index 11d01447db..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/cancel.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/caret-down24.toif b/core/embed/rust/src/ui/model_tt/res/caret-down24.toif new file mode 100644 index 0000000000..1f5f891bc8 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/caret-down24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/caret-left24.toif b/core/embed/rust/src/ui/model_tt/res/caret-left24.toif new file mode 100644 index 0000000000..86aa04e039 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/caret-left24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/caret-right24.toif b/core/embed/rust/src/ui/model_tt/res/caret-right24.toif new file mode 100644 index 0000000000..2be54044b9 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/caret-right24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/caret-up24.toif b/core/embed/rust/src/ui/model_tt/res/caret-up24.toif new file mode 100644 index 0000000000..047c14a6d9 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/caret-up24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/check.toif b/core/embed/rust/src/ui/model_tt/res/check.toif deleted file mode 100644 index 8581b7f371..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/check.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/check16.toif b/core/embed/rust/src/ui/model_tt/res/check16.toif new file mode 100644 index 0000000000..a22d339fe9 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/check16.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/check24.toif b/core/embed/rust/src/ui/model_tt/res/check24.toif new file mode 100644 index 0000000000..6f80468e70 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/check24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/circle.toif b/core/embed/rust/src/ui/model_tt/res/circle.toif deleted file mode 100644 index d5ad41dea1..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/circle.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/circle48.toif b/core/embed/rust/src/ui/model_tt/res/circle48.toif new file mode 100644 index 0000000000..bd2c156490 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/circle48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/click.toif b/core/embed/rust/src/ui/model_tt/res/click.toif deleted file mode 100644 index adcef93ff3..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/click.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/coinjoin16.toif b/core/embed/rust/src/ui/model_tt/res/coinjoin16.toif new file mode 100644 index 0000000000..1a6a41aadb Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/coinjoin16.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/confirm.toif b/core/embed/rust/src/ui/model_tt/res/confirm.toif deleted file mode 100644 index be616962bb..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/confirm.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/current.toif b/core/embed/rust/src/ui/model_tt/res/current.toif deleted file mode 100644 index b1d6ec7068..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/current.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/fg-check48.toif b/core/embed/rust/src/ui/model_tt/res/fg-check48.toif new file mode 100644 index 0000000000..408f4bd6d5 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/fg-check48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/fg-error48.toif b/core/embed/rust/src/ui/model_tt/res/fg-error48.toif new file mode 100644 index 0000000000..2ebd10a0c0 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/fg-error48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/fg-info48.toif b/core/embed/rust/src/ui/model_tt/res/fg-info48.toif new file mode 100644 index 0000000000..cb8ccb3376 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/fg-info48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/fg-user48.toif b/core/embed/rust/src/ui/model_tt/res/fg-user48.toif new file mode 100644 index 0000000000..045b2b7e7c Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/fg-user48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/fg-warning48.toif b/core/embed/rust/src/ui/model_tt/res/fg-warning48.toif new file mode 100644 index 0000000000..e1349e9c35 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/fg-warning48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/finger24.toif b/core/embed/rust/src/ui/model_tt/res/finger24.toif new file mode 100644 index 0000000000..9793363e5d Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/finger24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/info-circle.toif b/core/embed/rust/src/ui/model_tt/res/info-circle.toif deleted file mode 100644 index 56f41b7f4f..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/info-circle.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/info32.toif b/core/embed/rust/src/ui/model_tt/res/info32.toif new file mode 100644 index 0000000000..ed95e5de14 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/info32.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/info_fg.toif b/core/embed/rust/src/ui/model_tt/res/info_fg.toif deleted file mode 100644 index c80d6ec295..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/info_fg.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/lock.toif b/core/embed/rust/src/ui/model_tt/res/lock16.toif similarity index 100% rename from core/embed/rust/src/ui/model_tt/res/lock.toif rename to core/embed/rust/src/ui/model_tt/res/lock16.toif diff --git a/core/embed/rust/src/ui/model_tt/res/octa-bang.toif b/core/embed/rust/src/ui/model_tt/res/octa-bang.toif deleted file mode 100644 index a0d4efb46e..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/octa-bang.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/octagon48.toif b/core/embed/rust/src/ui/model_tt/res/octagon48.toif new file mode 100644 index 0000000000..0b3a4137fb Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/octagon48.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/success_fg.toif b/core/embed/rust/src/ui/model_tt/res/success_fg.toif deleted file mode 100644 index 55a45afce5..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/success_fg.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/triangle.toif b/core/embed/rust/src/ui/model_tt/res/triangle.toif deleted file mode 100644 index 017308bae3..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/triangle.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/warn.toif b/core/embed/rust/src/ui/model_tt/res/warn.toif deleted file mode 100644 index 108a6b91e3..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/warn.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/warn_fg.toif b/core/embed/rust/src/ui/model_tt/res/warn_fg.toif deleted file mode 100644 index 8e493ef6dd..0000000000 Binary files a/core/embed/rust/src/ui/model_tt/res/warn_fg.toif and /dev/null differ diff --git a/core/embed/rust/src/ui/model_tt/res/warning16.toif b/core/embed/rust/src/ui/model_tt/res/warning16.toif new file mode 100644 index 0000000000..53760d4314 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/warning16.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/x24.toif b/core/embed/rust/src/ui/model_tt/res/x24.toif new file mode 100644 index 0000000000..217ae07d86 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/x24.toif differ diff --git a/core/embed/rust/src/ui/model_tt/res/x32.toif b/core/embed/rust/src/ui/model_tt/res/x32.toif new file mode 100644 index 0000000000..0b8ca34f05 Binary files /dev/null and b/core/embed/rust/src/ui/model_tt/res/x32.toif differ diff --git a/core/embed/rust/src/ui/model_tt/theme.rs b/core/embed/rust/src/ui/model_tt/theme.rs index 1b986ab5f4..fd3b17f82d 100644 --- a/core/embed/rust/src/ui/model_tt/theme.rs +++ b/core/embed/rust/src/ui/model_tt/theme.rs @@ -50,43 +50,53 @@ pub const RADIUS: u8 = 2; // Full-size QR code. pub const QR_SIDE_MAX: u32 = 140; -// Size of icons in the UI (i.e. inside buttons). -pub const ICON_SIZE: i16 = 16; - // UI icons (greyscale). -pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/cancel.toif"); -pub const ICON_CANCEL_LARGER: &[u8] = include_res!("model_tt/res/cancel-larger.toif"); -pub const ICON_CONFIRM: &[u8] = include_res!("model_tt/res/confirm.toif"); +// Button icons. +pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/x24.toif"); +pub const ICON_CONFIRM: &[u8] = include_res!("model_tt/res/check24.toif"); pub const ICON_SPACE: &[u8] = include_res!("model_tt/res/space.toif"); -pub const ICON_BACK: &[u8] = include_res!("model_tt/res/back.toif"); -pub const ICON_CLICK: &[u8] = include_res!("model_tt/res/click.toif"); -pub const ICON_NEXT: &[u8] = include_res!("model_tt/res/next.toif"); -pub const ICON_WARN: &[u8] = include_res!("model_tt/res/warn-icon.toif"); +pub const ICON_BACK: &[u8] = include_res!("model_tt/res/caret-left24.toif"); +pub const ICON_FORWARD: &[u8] = include_res!("model_tt/res/caret-right24.toif"); +pub const ICON_UP: &[u8] = include_res!("model_tt/res/caret-up24.toif"); +pub const ICON_DOWN: &[u8] = include_res!("model_tt/res/caret-down24.toif"); +pub const ICON_CLICK: &[u8] = include_res!("model_tt/res/finger24.toif"); + +pub const ICON_CORNER_CANCEL: &[u8] = include_res!("model_tt/res/x32.toif"); +pub const ICON_CORNER_INFO: &[u8] = include_res!("model_tt/res/info32.toif"); + +// Checklist symbols. +pub const ICON_LIST_CURRENT: &[u8] = include_res!("model_tt/res/arrow-right16.toif"); +pub const ICON_LIST_CHECK: &[u8] = include_res!("model_tt/res/check16.toif"); + +// Homescreen notifications. +pub const ICON_WARN: &[u8] = include_res!("model_tt/res/warning16.toif"); +pub const ICON_LOCK: &[u8] = include_res!("model_tt/res/lock16.toif"); +pub const ICON_COINJOIN: &[u8] = include_res!("model_tt/res/coinjoin16.toif"); pub const ICON_MAGIC: &[u8] = include_res!("model_tt/res/magic.toif"); -pub const ICON_LIST_CURRENT: &[u8] = include_res!("model_tt/res/current.toif"); -pub const ICON_LIST_CHECK: &[u8] = include_res!("model_tt/res/check.toif"); -pub const ICON_LOCK: &[u8] = include_res!("model_tt/res/lock.toif"); -pub const ICON_LOGO: &[u8] = include_res!("model_tt/res/logo.toif"); -pub const ICON_SUCCESS_SMALL: &[u8] = include_res!("model_tt/res/success_bld.toif"); -pub const ICON_WARN_SMALL: &[u8] = include_res!("model_tt/res/warn_bld.toif"); + +// Text arrows. pub const ICON_PAGE_NEXT: &[u8] = include_res!("model_tt/res/page-next.toif"); pub const ICON_PAGE_PREV: &[u8] = include_res!("model_tt/res/page-prev.toif"); -pub const ICON_OCTA: &[u8] = include_res!("model_tt/res/octa-bang.toif"); -pub const ICON_INFO_CIRCLE: &[u8] = include_res!("model_tt/res/info-circle.toif"); // Large, three-color icons. pub const WARN_COLOR: Color = YELLOW; pub const INFO_COLOR: Color = BLUE; pub const SUCCESS_COLOR: Color = GREEN; pub const ERROR_COLOR: Color = RED; -pub const IMAGE_FG_WARN: &[u8] = include_res!("model_tt/res/warn_fg.toif"); -pub const IMAGE_FG_SUCCESS: &[u8] = include_res!("model_tt/res/success_fg.toif"); -pub const IMAGE_FG_ERROR: &[u8] = include_res!("model_tt/res/error_fg.toif"); -pub const IMAGE_FG_INFO: &[u8] = include_res!("model_tt/res/info_fg.toif"); -pub const IMAGE_BG_CIRCLE: &[u8] = include_res!("model_tt/res/circle.toif"); -pub const IMAGE_BG_TRIANGLE: &[u8] = include_res!("model_tt/res/triangle.toif"); -pub const IMAGE_BG_BACK_BTN: &[u8] = include_res!("model_tt/res/back_btn.toif"); -pub const IMAGE_BG_BACK_BTN_TALL: &[u8] = include_res!("model_tt/res/back_btn_tall.toif"); +pub const IMAGE_FG_WARN: &[u8] = include_res!("model_tt/res/fg-warning48.toif"); +pub const IMAGE_FG_SUCCESS: &[u8] = include_res!("model_tt/res/fg-check48.toif"); +pub const IMAGE_FG_ERROR: &[u8] = include_res!("model_tt/res/fg-error48.toif"); +pub const IMAGE_FG_INFO: &[u8] = include_res!("model_tt/res/fg-info48.toif"); +pub const IMAGE_FG_USER: &[u8] = include_res!("model_tt/res/fg-user48.toif"); +pub const IMAGE_BG_CIRCLE: &[u8] = include_res!("model_tt/res/circle48.toif"); +pub const IMAGE_BG_OCTAGON: &[u8] = include_res!("model_tt/res/octagon48.toif"); + +// Non-square button backgrounds. +pub const IMAGE_BG_BACK_BTN: &[u8] = include_res!("model_tt/res/bg-back40.toif"); +pub const IMAGE_BG_BACK_BTN_TALL: &[u8] = include_res!("model_tt/res/bg-back52.toif"); + +// Welcome screen. +pub const ICON_LOGO: &[u8] = include_res!("model_tt/res/logo.toif"); // Default homescreen pub const IMAGE_HOMESCREEN: &[u8] = include_res!("model_tt/res/bg.jpg"); @@ -98,6 +108,10 @@ pub const DOT_INACTIVE_HALF: &[u8] = include_res!("model_tt/res/scroll-inactive- pub const DOT_INACTIVE_QUARTER: &[u8] = include_res!("model_tt/res/scroll-inactive-quarter.toif"); pub const DOT_SMALL: &[u8] = include_res!("model_tt/res/scroll-small.toif"); +// Bootloader. TODO +pub const ICON_SUCCESS_SMALL: &[u8] = include_res!("model_tt/res/success_bld.toif"); +pub const ICON_WARN_SMALL: &[u8] = include_res!("model_tt/res/warn_bld.toif"); + pub const fn label_default() -> TextStyle { TEXT_NORMAL } @@ -274,6 +288,38 @@ pub const fn button_reset() -> ButtonStyleSheet { } } +pub const fn button_moreinfo() -> ButtonStyleSheet { + ButtonStyleSheet { + normal: &ButtonStyle { + font: Font::BOLD, + text_color: FG, + button_color: BG, + background_color: BG, + border_color: GREY_DARK, + border_radius: RADIUS, + border_width: 2, + }, + active: &ButtonStyle { + font: Font::BOLD, + text_color: FG, + button_color: BG, + background_color: BG, + border_color: GREY_MEDIUM, + border_radius: RADIUS, + border_width: 2, + }, + disabled: &ButtonStyle { + font: Font::BOLD, + text_color: GREY_LIGHT, + button_color: BG, + background_color: BG, + border_color: GREY_DARK, + border_radius: RADIUS, + border_width: 2, + }, + } +} + pub const fn button_info() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { @@ -338,6 +384,70 @@ pub const fn button_pin() -> ButtonStyleSheet { } } +pub const fn button_pin_confirm() -> ButtonStyleSheet { + ButtonStyleSheet { + normal: &ButtonStyle { + font: Font::MONO, + text_color: FG, + button_color: GREEN, + background_color: BG, + border_color: BG, + border_radius: RADIUS, + border_width: 0, + }, + active: &ButtonStyle { + font: Font::MONO, + text_color: FG, + button_color: GREY_DARK, + background_color: BG, + border_color: FG, + border_radius: RADIUS, + border_width: 0, + }, + disabled: &ButtonStyle { + font: Font::MONO, + text_color: GREY_LIGHT, + button_color: GREEN, + background_color: BG, + border_color: BG, + border_radius: RADIUS, + border_width: 0, + }, + } +} + +pub const fn button_pin_autocomplete() -> ButtonStyleSheet { + ButtonStyleSheet { + normal: &ButtonStyle { + font: Font::MONO, + text_color: FG, + button_color: BG, + background_color: BG, + border_color: BG, + border_radius: RADIUS, + border_width: 0, + }, + active: &ButtonStyle { + font: Font::MONO, + text_color: FG, + button_color: GREY_DARK, + background_color: BG, + border_color: FG, + border_radius: RADIUS, + border_width: 0, + }, + disabled: &ButtonStyle { + font: Font::MONO, + text_color: GREY_LIGHT, + button_color: BG, + background_color: BG, + border_color: BG, + border_radius: RADIUS, + border_width: 0, + }, + } +} + pub const fn button_counter() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { @@ -421,7 +531,6 @@ pub const TEXT_CHECKLIST_SELECTED: TextStyle = TextStyle::new(Font::NORMAL, FG, BG, GREY_LIGHT, GREY_LIGHT); pub const TEXT_CHECKLIST_DONE: TextStyle = TextStyle::new(Font::NORMAL, GREEN_DARK, BG, GREY_LIGHT, GREY_LIGHT); -pub const TEXT_XPUB: TextStyle = TEXT_NORMAL.with_line_breaking(LineBreaking::BreakWordsNoHyphen); pub const FORMATTED: FormattedFonts = FormattedFonts { normal: Font::NORMAL, @@ -430,27 +539,21 @@ pub const FORMATTED: FormattedFonts = FormattedFonts { mono: Font::MONO, }; -pub const CONTENT_BORDER: i16 = 5; -pub const KEYBOARD_SPACING: i16 = 8; -pub const BUTTON_HEIGHT: i16 = 38; +pub const CONTENT_BORDER: i16 = 0; +pub const BUTTON_HEIGHT: i16 = 50; +pub const BUTTON_WIDTH: i16 = 56; pub const BUTTON_SPACING: i16 = 6; +pub const KEYBOARD_SPACING: i16 = BUTTON_SPACING; pub const CHECKLIST_SPACING: i16 = 10; pub const RECOVERY_SPACING: i16 = 18; -pub const CORNER_BUTTON_SIDE: i16 = 32; -pub const CORNER_BUTTON_SPACING: i16 = 8; - -/// Standard button height in pixels. -pub const fn button_rows(count: usize) -> i16 { - let count = count as i16; - BUTTON_HEIGHT * count + BUTTON_SPACING * count.saturating_sub(1) -} - -pub const fn button_bar_rows(rows: usize, inner: T) -> FixedHeightBar { - FixedHeightBar::bottom(inner, button_rows(rows)) -} +pub const CORNER_BUTTON_SIDE: i16 = 44; +pub const CORNER_BUTTON_SPACING: i16 = BUTTON_SPACING; +pub const INFO_BUTTON_HEIGHT: i16 = 44; +pub const PIN_BUTTON_HEIGHT: i16 = 40; +pub const MNEMONIC_BUTTON_HEIGHT: i16 = 52; pub const fn button_bar(inner: T) -> FixedHeightBar { - button_bar_rows(1, inner) + FixedHeightBar::bottom(inner, BUTTON_HEIGHT) } /// +----------+ diff --git a/core/mocks/generated/trezorui.pyi b/core/mocks/generated/trezorui.pyi index 3cd672112c..57cfb32554 100644 --- a/core/mocks/generated/trezorui.pyi +++ b/core/mocks/generated/trezorui.pyi @@ -11,6 +11,7 @@ class Display: 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 diff --git a/core/src/apps/cardano/layout.py b/core/src/apps/cardano/layout.py index 9aa74d4ac4..39da0f3710 100644 --- a/core/src/apps/cardano/layout.py +++ b/core/src/apps/cardano/layout.py @@ -190,7 +190,7 @@ async def show_tx_init(ctx: Context, title: str) -> bool: "Confirm transaction", ( ( - ui.BOLD, + ui.DEMIBOLD, title, ), (ui.NORMAL, "Choose level of details:"), diff --git a/core/src/apps/common/passphrase.py b/core/src/apps/common/passphrase.py index 3149371df8..8ebeed5b04 100644 --- a/core/src/apps/common/passphrase.py +++ b/core/src/apps/common/passphrase.py @@ -66,7 +66,7 @@ async def _request_on_host(ctx: Context) -> str: ctx, "passphrase_host1_hidden", "Hidden wallet", - description=f"Access hidden wallet?\n\n{explanation}", + description=f"Access hidden wallet?\n{explanation}", ) else: await confirm_action( diff --git a/core/src/apps/ethereum/layout.py b/core/src/apps/ethereum/layout.py index 615d2dd906..aea383d855 100644 --- a/core/src/apps/ethereum/layout.py +++ b/core/src/apps/ethereum/layout.py @@ -168,8 +168,8 @@ async def should_show_domain(ctx: Context, name: bytes, version: bytes) -> bool: para = ( (ui.NORMAL, "Name and version"), - (ui.BOLD, domain_name), - (ui.BOLD, domain_version), + (ui.DEMIBOLD, domain_name), + (ui.DEMIBOLD, domain_version), ) return await should_show_more( ctx, @@ -188,7 +188,7 @@ async def should_show_struct( button_text: str = "Show full struct", ) -> bool: para = ( - (ui.BOLD, description), + (ui.DEMIBOLD, description), ( ui.NORMAL, format_plural("Contains {count} {plural}", len(data_members), "key"), diff --git a/core/src/apps/management/change_pin.py b/core/src/apps/management/change_pin.py index 9c970aacdc..29eceaf0ea 100644 --- a/core/src/apps/management/change_pin.py +++ b/core/src/apps/management/change_pin.py @@ -28,7 +28,7 @@ async def change_pin(ctx: Context, msg: ChangePin) -> Success: await _require_confirm_change_pin(ctx, msg) # get old pin - curpin, salt = await request_pin_and_sd_salt(ctx, "Enter old PIN") + curpin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN") # if changing pin, pre-check the entered pin before getting new pin if curpin and not msg.remove: diff --git a/core/src/trezor/ui/__init__.py b/core/src/trezor/ui/__init__.py index 9b93df79a4..733663b4db 100644 --- a/core/src/trezor/ui/__init__.py +++ b/core/src/trezor/ui/__init__.py @@ -12,6 +12,7 @@ display = Display() # re-export constants from modtrezorui NORMAL: int = Display.FONT_NORMAL BOLD: int = Display.FONT_BOLD +DEMIBOLD: int = Display.FONT_DEMIBOLD MONO: int = Display.FONT_MONO WIDTH: int = Display.WIDTH HEIGHT: int = Display.HEIGHT diff --git a/core/src/trezor/ui/layouts/tr/__init__.py b/core/src/trezor/ui/layouts/tr/__init__.py index 718ec16457..f13955df7f 100644 --- a/core/src/trezor/ui/layouts/tr/__init__.py +++ b/core/src/trezor/ui/layouts/tr/__init__.py @@ -70,7 +70,6 @@ async def confirm_action( action: str | None = None, description: str | None = None, description_param: str | None = None, - description_param_font: int = ui.BOLD, verb: str = "CONFIRM", verb_cancel: str | None = None, hold: bool = False, @@ -82,8 +81,6 @@ async def confirm_action( verb_cancel = verb_cancel.upper() if description is not None and description_param is not None: - if description_param_font != ui.BOLD: - log.error(__name__, "confirm_action description_param_font not implemented") description = description.format(description_param) if hold: diff --git a/core/src/trezor/ui/layouts/tt_v2/__init__.py b/core/src/trezor/ui/layouts/tt_v2/__init__.py index 582daab11e..9cf93027ee 100644 --- a/core/src/trezor/ui/layouts/tt_v2/__init__.py +++ b/core/src/trezor/ui/layouts/tt_v2/__init__.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING -from trezor import io, log, loop, ui +from trezor import io, loop, ui from trezor.enums import ButtonRequestType from trezor.wire import ActionCancelled @@ -212,8 +212,7 @@ async def confirm_action( action: str | None = None, description: str | None = None, description_param: str | None = None, - description_param_font: int = ui.BOLD, - verb: str = "CONFIRM", + verb: str | None = None, verb_cancel: str | None = None, hold: bool = False, hold_danger: bool = False, @@ -221,12 +220,12 @@ async def confirm_action( exc: ExceptionType = ActionCancelled, br_code: ButtonRequestType = BR_TYPE_OTHER, ) -> None: + if verb is not None: + verb = verb.upper() if verb_cancel is not None: verb_cancel = verb_cancel.upper() if description is not None and description_param is not None: - if description_param_font != ui.BOLD: - log.error(__name__, "confirm_action description_param_font not implemented") description = description.format(description_param) await raise_if_not_confirmed( @@ -237,7 +236,7 @@ async def confirm_action( title=title.upper(), action=action, description=description, - verb=verb.upper(), + verb=verb, verb_cancel=verb_cancel, hold=hold, hold_danger=hold_danger, @@ -414,7 +413,7 @@ async def show_address( def xpub_title(i: int): result = f"MULTISIG XPUB #{i + 1}\n" - result += " (YOURS)" if i == multisig_index else " (COSIGNER)" + result += "(YOURS)" if i == multisig_index else "(COSIGNER)" return result result = await interact( @@ -431,8 +430,7 @@ async def show_address( "show_address_details", ButtonRequestType.Address, ) - # Can only go back from the address details but corner button returns INFO. - assert result in (INFO, CANCELLED) + assert result is CANCELLED else: result = await interact( diff --git a/core/src/trezor/ui/layouts/tt_v2/recovery.py b/core/src/trezor/ui/layouts/tt_v2/recovery.py index 9766c5dc8c..bcd59c55e4 100644 --- a/core/src/trezor/ui/layouts/tt_v2/recovery.py +++ b/core/src/trezor/ui/layouts/tt_v2/recovery.py @@ -42,7 +42,7 @@ async def request_word_count(ctx: GenericContext, dry_run: bool) -> int: async def request_word( ctx: GenericContext, word_index: int, word_count: int, is_slip39: bool ) -> str: - prompt = f"Type word {word_index + 1} of {word_count}:" + prompt = f"Type word {word_index + 1} of {word_count}" if is_slip39: keyboard = RustLayout(trezorui2.request_slip39(prompt=prompt)) else: diff --git a/core/src/trezor/ui/layouts/tt_v2/reset.py b/core/src/trezor/ui/layouts/tt_v2/reset.py index 155f34534c..34fa712c83 100644 --- a/core/src/trezor/ui/layouts/tt_v2/reset.py +++ b/core/src/trezor/ui/layouts/tt_v2/reset.py @@ -109,7 +109,7 @@ async def select_word( trezorui2.select_word( title=title, description=f"Select word {checked_index + 1} of {count}:", - words=(words[0].upper(), words[1].upper(), words[2].upper()), + words=(words[0], words[1], words[2]), ) ) ) diff --git a/tests/click_tests/recovery.py b/tests/click_tests/recovery.py index 79d1979094..5acfd59a2b 100644 --- a/tests/click_tests/recovery.py +++ b/tests/click_tests/recovery.py @@ -41,7 +41,7 @@ def select_number_of_words( assert layout.text == "WordSelector" else: # Two title options - assert layout.get_title() in ("SEED CHECK", "RECOVERY MODE") + assert layout.get_title() in ("SEED CHECK", "WALLET RECOVERY") # click the number word_option_offset = 6 diff --git a/tests/device_tests/bitcoin/test_getaddress_show.py b/tests/device_tests/bitcoin/test_getaddress_show.py index c63b880be3..856bd47596 100644 --- a/tests/device_tests/bitcoin/test_getaddress_show.py +++ b/tests/device_tests/bitcoin/test_getaddress_show.py @@ -281,7 +281,7 @@ def test_show_multisig_xpubs( def input_flow(): yield # show address layout = client.debug.wait_layout() - assert layout.get_title() == "RECEIVE ADDRESS (MULTISIG)" + assert "RECEIVE ADDRESS (MULTISIG)" in layout.get_title() assert layout.get_content().replace(" ", "") == address client.debug.click(CORNER_BUTTON) @@ -294,12 +294,11 @@ def test_show_multisig_xpubs( # Three xpub pages with the same testing logic for xpub_num in range(3): - expected_title = f"MULTISIG XPUB #{xpub_num + 1} " + ( + expected_title = f"MULTISIG XPUB #{xpub_num + 1} " + ( "(YOURS)" if i == xpub_num else "(COSIGNER)" ) - layout = client.debug.swipe_left(wait=True) - assert layout.get_title() == expected_title + assert expected_title in layout.get_title() content = layout.get_content().replace(" ", "") assert xpubs[xpub_num] in content diff --git a/tests/persistence_tests/test_shamir_persistence.py b/tests/persistence_tests/test_shamir_persistence.py index 4cfb6aee5c..0944bc3a09 100644 --- a/tests/persistence_tests/test_shamir_persistence.py +++ b/tests/persistence_tests/test_shamir_persistence.py @@ -53,7 +53,7 @@ def test_abort(emulator: Emulator): assert layout.get_title() == "WALLET RECOVERY" layout = debug.click(buttons.OK, wait=True) - assert "Select number of words" in layout.text + assert "Select number of words" in layout.get_content() device_handler.restart(emulator) debug = device_handler.debuglink() @@ -63,7 +63,7 @@ def test_abort(emulator: Emulator): # no waiting for layout because layout doesn't change layout = debug.read_layout() - assert "Select number of words" in layout.text + assert "Select number of words" in layout.get_content() layout = debug.click(buttons.CANCEL, wait=True) assert layout.get_title() == "ABORT RECOVERY"