diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index f8d306fb9..5eb4d0d5b 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -152,6 +152,7 @@ static void _librust_qstrs(void) { MP_QSTR_confirm_backup_written_down; MP_QSTR_confirm_blob; MP_QSTR_confirm_coinjoin; + MP_QSTR_confirm_create_wallet; MP_QSTR_confirm_emphasized; MP_QSTR_confirm_fido; MP_QSTR_confirm_firmware_update; diff --git a/core/embed/rust/src/ui/model_mercury/component/button.rs b/core/embed/rust/src/ui/model_mercury/component/button.rs index f57414c89..eed4ce5cb 100644 --- a/core/embed/rust/src/ui/model_mercury/component/button.rs +++ b/core/embed/rust/src/ui/model_mercury/component/button.rs @@ -9,7 +9,7 @@ use crate::{ }, display::{self, toif::Icon, Color, Font}, event::TouchEvent, - geometry::{Alignment2D, Insets, Offset, Point, Rect}, + geometry::{Alignment, Alignment2D, Insets, Offset, Point, Rect}, shape, shape::Renderer, }, @@ -30,6 +30,7 @@ pub struct Button { touch_expand: Option, content: ButtonContent, styles: ButtonStyleSheet, + text_align: Alignment, state: State, long_press: Option, long_timer: Option, @@ -47,6 +48,7 @@ impl Button { area: Rect::zero(), touch_expand: None, styles: theme::button_default(), + text_align: Alignment::Start, state: State::Initial, long_press: None, long_timer: None, @@ -78,6 +80,11 @@ impl Button { self } + pub const fn with_text_align(mut self, align: Alignment) -> Self { + self.text_align = align; + self + } + pub const fn with_expanded_touch_area(mut self, expand: Insets) -> Self { self.touch_expand = Some(expand); self @@ -217,11 +224,19 @@ impl Button { match &self.content { ButtonContent::Empty => {} ButtonContent::Text(text) => { - let start_of_baseline = self.area.left_center() + Self::BASELINE_OFFSET; + let y_offset = Offset::y(self.style().font.allcase_text_height() / 2); + let start_of_baseline = match self.text_align { + Alignment::Start => { + self.area.left_center() + Offset::x(Self::BASELINE_OFFSET.x) + } + Alignment::Center => self.area.center(), + Alignment::End => self.area.right_center() - Offset::x(Self::BASELINE_OFFSET.x), + } + y_offset; text.map(|text| { shape::Text::new(start_of_baseline, text) .with_font(style.font) .with_fg(style.text_color) + .with_align(self.text_align) .render(target); }); } diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs index 8aba67d34..81e01c2fc 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/bip39.rs @@ -196,7 +196,7 @@ impl Component for Bip39Input { let icon_center = area.top_right().center(area.bottom_right()) - Offset::new(16 + 8, 0); shape::ToifImage::new(icon_center, icon.toif) .with_align(Alignment2D::CENTER) - .with_fg(style.text_color) + .with_fg(style.icon_color) .render(target); } } @@ -227,7 +227,8 @@ impl Bip39Input { // Styling the input to reflect already filled word Self { - button: Button::with_icon(theme::ICON_LIST_CHECK).styled(theme::button_pin_confirm()), + button: Button::with_icon(theme::ICON_CONFIRM_INPUT) + .styled(theme::button_pin_confirm()), textbox: TextBox::new(unwrap!(String::try_from(word))), multi_tap: MultiTapKeyboard::new(), options_num: bip39::options_num(word), @@ -293,7 +294,7 @@ impl Bip39Input { self.button.enable(ctx); self.button.set_stylesheet(ctx, theme::button_pin_confirm()); self.button - .set_content(ctx, ButtonContent::Icon(theme::ICON_LIST_CHECK)); + .set_content(ctx, ButtonContent::Icon(theme::ICON_CONFIRM_INPUT)); self.button_suggestion .set_stylesheet(ctx, theme::button_suggestion_confirm()); } else { @@ -302,7 +303,7 @@ impl Bip39Input { self.button .set_stylesheet(ctx, theme::button_pin_autocomplete()); self.button - .set_content(ctx, ButtonContent::Icon(theme::ICON_CLICK)); + .set_content(ctx, ButtonContent::Icon(theme::ICON_AUTOFILL)); self.button_suggestion .set_stylesheet(ctx, theme::button_suggestion_autocomplete()); } diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs index def0f6897..839dbbcd9 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/mnemonic.rs @@ -2,7 +2,7 @@ use crate::{ strutil::TString, ui::{ component::{maybe::paint_overlapping, Child, Component, Event, EventCtx, Label, Maybe}, - geometry::{Alignment2D, Grid, Offset, Rect}, + geometry::{Alignment, Grid, Rect}, model_mercury::{ component::{Button, ButtonMsg, Swipe, SwipeDirection}, theme, @@ -44,23 +44,23 @@ where Self { prompt: Child::new(Maybe::new( theme::BG, - Label::centered(prompt, theme::label_keyboard_prompt()), + Label::centered(prompt, theme::TEXT_MAIN_GREY_LIGHT), prompt_visible, )), back: Child::new(Maybe::new( theme::BG, - Button::with_icon_blend( - theme::IMAGE_BG_BACK_BTN_TALL, - theme::ICON_BACK, - Offset::new(30, 17), - ) - .styled(theme::button_reset()) - .with_long_press(theme::ERASE_HOLD_DURATION), + Button::with_icon(theme::ICON_DELETE) + .styled(theme::button_default()) + .with_long_press(theme::ERASE_HOLD_DURATION), !prompt_visible, )), input: Child::new(Maybe::new(theme::BG, input, !prompt_visible)), keys: T::keys() - .map(|t| Button::with_text(t.into()).styled(theme::button_pin())) + .map(|t| { + Button::with_text(t.into()) + .styled(theme::button_pin()) + .with_text_align(Alignment::Center) + }) .map(Child::new), swipe: Swipe::new().right(), can_go_back, @@ -109,23 +109,27 @@ where type Msg = MnemonicKeyboardMsg; fn place(&mut self, bounds: Rect) -> Rect { - 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)); - - let prompt_center = grid.row_col(0, 0).union(grid.row_col(0, 3)).center(); - let prompt_size = self.prompt.inner().inner().max_size(); - let prompt_area = Rect::snap(prompt_center, prompt_size, Alignment2D::CENTER); + let height_input_area: i16 = 30; + let space_top: i16 = 8; + let (remaining, keyboard_area) = + bounds.split_bottom(3 * theme::BUTTON_HEIGHT + 2 * theme::KEYBOARD_SPACING); + let prompt_area = remaining + .split_top(space_top) + .1 + .split_top(height_input_area) + .0; + assert!(prompt_area.height() == height_input_area); + + let (back_btn_area, input_area) = prompt_area.split_left(30); + let keyboard_grid = Grid::new(keyboard_area, 3, 3).with_spacing(theme::KEYBOARD_SPACING); self.swipe.place(bounds); self.prompt.place(prompt_area); - self.back.place(back_area); + self.back.place(back_btn_area); self.input.place(input_area); + for (key, btn) in self.keys.iter_mut().enumerate() { - btn.place(grid.cell(key + grid.cols)); // Start in the second row. + btn.place(keyboard_grid.cell(key)); } bounds } @@ -185,9 +189,12 @@ where } fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { - self.prompt.render(target); - self.input.render(target); - self.back.render(target); + if self.input.inner().inner().is_empty() { + self.prompt.render(target); + } else { + self.input.render(target); + self.back.render(target); + } for btn in &self.keys { btn.render(target); diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs index 2aba48275..5160e7ddc 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/slip39.rs @@ -181,7 +181,7 @@ impl Component for Slip39Input { icon.draw( icon_center, Alignment2D::CENTER, - style.text_color, + style.icon_color, style.button_color, ); } @@ -247,7 +247,7 @@ impl Component for Slip39Input { let icon_center = area.top_right().center(area.bottom_right()) - Offset::new(16 + 8, 0); shape::ToifImage::new(icon_center, icon.toif) .with_align(Alignment2D::CENTER) - .with_fg(style.text_color) + .with_fg(style.icon_color) .render(target); } } @@ -356,7 +356,7 @@ impl Slip39Input { // Confirm button. self.button.enable(ctx); self.button - .set_content(ctx, ButtonContent::Icon(theme::ICON_LIST_CHECK)); + .set_content(ctx, ButtonContent::Icon(theme::ICON_CONFIRM_INPUT)); } else { // Disabled button. self.button.disable(ctx); diff --git a/core/embed/rust/src/ui/model_mercury/component/keyboard/word_count.rs b/core/embed/rust/src/ui/model_mercury/component/keyboard/word_count.rs index bdccf58bf..fbda9ca84 100644 --- a/core/embed/rust/src/ui/model_mercury/component/keyboard/word_count.rs +++ b/core/embed/rust/src/ui/model_mercury/component/keyboard/word_count.rs @@ -1,6 +1,6 @@ use crate::ui::{ component::{Component, Event, EventCtx}, - geometry::{Grid, GridCellSpan, Rect}, + geometry::{Alignment, Grid, GridCellSpan, Rect}, model_mercury::{ component::button::{Button, ButtonMsg}, theme, @@ -10,7 +10,7 @@ use crate::ui::{ const NUMBERS: [u32; 5] = [12, 18, 20, 24, 33]; const LABELS: [&str; 5] = ["12", "18", "20", "24", "33"]; -const CELLS: [(usize, usize); 5] = [(0, 0), (0, 2), (0, 4), (1, 0), (1, 2)]; +const CELLS: [(usize, usize); 5] = [(0, 0), (0, 2), (1, 0), (1, 2), (2, 1)]; pub struct SelectWordCount { button: [Button; NUMBERS.len()], @@ -23,7 +23,11 @@ pub enum SelectWordCountMsg { impl SelectWordCount { pub fn new() -> Self { SelectWordCount { - button: LABELS.map(|t| Button::with_text(t.into()).styled(theme::button_pin())), + button: LABELS.map(|t| { + Button::with_text(t.into()) + .styled(theme::button_pin()) + .with_text_align(Alignment::Center) + }), } } } @@ -32,8 +36,13 @@ impl Component for SelectWordCount { type Msg = SelectWordCountMsg; fn place(&mut self, bounds: Rect) -> Rect { - let (_, bounds) = bounds.split_bottom(2 * theme::BUTTON_HEIGHT + theme::BUTTON_SPACING); - let grid = Grid::new(bounds, 2, 6).with_spacing(theme::BUTTON_SPACING); + let n_rows: usize = 3; + let n_cols: usize = 4; + + let (_, bounds) = bounds.split_bottom( + n_rows as i16 * theme::BUTTON_HEIGHT + (n_rows as i16 - 1) * theme::BUTTON_SPACING, + ); + let grid = Grid::new(bounds, n_rows, n_cols).with_spacing(theme::BUTTON_SPACING); for (btn, (x, y)) in self.button.iter_mut().zip(CELLS) { btn.place(grid.cells(GridCellSpan { from: (x, y), diff --git a/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs b/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs index 66381204e..c03a868fc 100644 --- a/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs +++ b/core/embed/rust/src/ui/model_mercury/flow/confirm_reset_device.rs @@ -22,7 +22,6 @@ use super::super::{ pub enum ConfirmResetDevice { Intro, Menu, - Confirm, } impl FlowState for ConfirmResetDevice { @@ -34,12 +33,7 @@ impl FlowState for ConfirmResetDevice { (ConfirmResetDevice::Menu, SwipeDirection::Right) => { Decision::Goto(ConfirmResetDevice::Intro, direction) } - (ConfirmResetDevice::Intro, SwipeDirection::Up) => { - Decision::Goto(ConfirmResetDevice::Confirm, direction) - } - (ConfirmResetDevice::Confirm, SwipeDirection::Down) => { - Decision::Goto(ConfirmResetDevice::Intro, direction) - } + (ConfirmResetDevice::Intro, SwipeDirection::Up) => Decision::Return(FlowMsg::Confirmed), _ => Decision::Nothing, } } @@ -53,9 +47,6 @@ impl FlowState for ConfirmResetDevice { Decision::Goto(ConfirmResetDevice::Intro, SwipeDirection::Right) } (ConfirmResetDevice::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled), - (ConfirmResetDevice::Confirm, FlowMsg::Confirmed) => { - Decision::Return(FlowMsg::Confirmed) - } _ => Decision::Nothing, } } diff --git a/core/embed/rust/src/ui/model_mercury/layout.rs b/core/embed/rust/src/ui/model_mercury/layout.rs index 145798bbc..2e3e8b785 100644 --- a/core/embed/rust/src/ui/model_mercury/layout.rs +++ b/core/embed/rust/src/ui/model_mercury/layout.rs @@ -192,6 +192,15 @@ impl ComponentMsgObj for ShareWords<'_> { } } +impl ComponentMsgObj for SelectWordCount { + fn msg_try_into_obj(&self, msg: Self::Msg) -> Result { + match msg { + SelectWordCountMsg::Selected(n) => n.try_into(), + _ => Err(Error::TypeError), + } + } +} + impl ComponentMsgObj for VerticalMenu { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result { match msg { @@ -758,6 +767,18 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs: unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } } +extern "C" fn new_confirm_create_wallet(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { + let block = move |_args: &[Obj], _kwargs: &Map| { + let content = PromptScreen::new_hold_to_confirm(); + let obj = LayoutObj::new( + Frame::left_aligned(TR::reset__title_create_wallet.into(), content) + .with_footer(TR::instructions__hold_to_confirm.into(), None), + )?; + Ok(obj.into()) + }; + unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } +} + extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; @@ -1331,8 +1352,9 @@ extern "C" fn new_confirm_backup_written_down( args: *const Obj, kwargs: *mut Map, ) -> Obj { - let block = move |_args: &[Obj], kwargs: &Map| { + let block = move |_args: &[Obj], _kwargs: &Map| { let content = PromptScreen::new_hold_to_confirm(); + // TODO: use TR let frame_with_hold_to_confirm = Frame::left_aligned("I wrote down all words in order.".into(), content) .with_footer(TR::instructions__hold_to_confirm.into(), None); @@ -1413,17 +1435,13 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { - let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; + let _title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; let description: TString = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?; - let button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; + let _button: TString = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?; let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; - let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; + let _info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false)?; - let paragraphs = Paragraphs::new([ - Paragraph::new(&theme::TEXT_DEMIBOLD, title), - Paragraph::new(&theme::TEXT_NORMAL, description), - ]) - .with_spacing(theme::RECOVERY_SPACING); + let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]); let notification: TString = if dry_run { TR::recovery__title_dry_run.try_into()? @@ -1431,23 +1449,12 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut TR::recovery__title.try_into()? }; - let obj = if info_button { - LayoutObj::new(Frame::left_aligned( - notification, - Dialog::new( - paragraphs, - Button::cancel_info_confirm( - TR::buttons__continue.into(), - TR::buttons__more_info.into(), - ), - ), - ))? - } else { - LayoutObj::new(Frame::left_aligned( - notification, - Dialog::new(paragraphs, Button::cancel_confirm_text(None, Some(button))), - ))? - }; + let content = SwipeUpScreen::new(paragraphs); + let obj = LayoutObj::new( + Frame::left_aligned(notification, content) + .with_footer(TR::instructions__swipe_up.into(), None) + .with_subtitle("Instructions".into()), // FIXME: use TR + )?; Ok(obj.into()) }; unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } @@ -1455,21 +1462,11 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { - let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; - let title: TString = if dry_run { - TR::recovery__title_dry_run.try_into()? - } else { - TR::recovery__title.try_into()? - }; - - let paragraphs = Paragraphs::new(Paragraph::new( - &theme::TEXT_DEMIBOLD, - TR::recovery__select_num_of_words, - )); + let _dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?; let obj = LayoutObj::new(Frame::left_aligned( - title, - Dialog::new(paragraphs, SelectWordCount::new()), + TR::recovery__select_num_of_words.into(), + SelectWordCount::new(), ))?; Ok(obj.into()) }; @@ -1825,6 +1822,10 @@ pub static mp_module_trezorui2: Module = obj_module! { /// """Confirm TOS before device setup.""" Qstr::MP_QSTR_confirm_reset_device => obj_fn_kw!(0, flow::confirm_reset_device::new_confirm_reset_device).as_obj(), + /// def confirm_create_wallet() -> LayoutObj[UiResult]: + /// """Confirm creating wallet""" + Qstr::MP_QSTR_confirm_create_wallet => obj_fn_kw!(0, new_confirm_create_wallet).as_obj(), + /// def show_address_details( /// *, /// qr_title: str, diff --git a/core/embed/rust/src/ui/model_mercury/res/autofill30.png b/core/embed/rust/src/ui/model_mercury/res/autofill30.png index 16cd93f3a..67c67a7b7 100644 Binary files a/core/embed/rust/src/ui/model_mercury/res/autofill30.png and b/core/embed/rust/src/ui/model_mercury/res/autofill30.png differ diff --git a/core/embed/rust/src/ui/model_mercury/res/autofill30.toif b/core/embed/rust/src/ui/model_mercury/res/autofill30.toif index 5551d07fe..712fb68e2 100644 Binary files a/core/embed/rust/src/ui/model_mercury/res/autofill30.toif and b/core/embed/rust/src/ui/model_mercury/res/autofill30.toif differ diff --git a/core/embed/rust/src/ui/model_mercury/res/confirm_input30.png b/core/embed/rust/src/ui/model_mercury/res/confirm_input30.png new file mode 100644 index 000000000..dc7148c8c Binary files /dev/null and b/core/embed/rust/src/ui/model_mercury/res/confirm_input30.png differ diff --git a/core/embed/rust/src/ui/model_mercury/res/confirm_input30.toif b/core/embed/rust/src/ui/model_mercury/res/confirm_input30.toif new file mode 100644 index 000000000..a34c5e952 Binary files /dev/null and b/core/embed/rust/src/ui/model_mercury/res/confirm_input30.toif differ diff --git a/core/embed/rust/src/ui/model_mercury/res/delete30.png b/core/embed/rust/src/ui/model_mercury/res/delete30.png index 3366c0704..9e30374a8 100644 Binary files a/core/embed/rust/src/ui/model_mercury/res/delete30.png and b/core/embed/rust/src/ui/model_mercury/res/delete30.png differ diff --git a/core/embed/rust/src/ui/model_mercury/res/delete30.toif b/core/embed/rust/src/ui/model_mercury/res/delete30.toif index 925396407..eea1cf0df 100644 Binary files a/core/embed/rust/src/ui/model_mercury/res/delete30.toif and b/core/embed/rust/src/ui/model_mercury/res/delete30.toif differ diff --git a/core/embed/rust/src/ui/model_mercury/theme/mod.rs b/core/embed/rust/src/ui/model_mercury/theme/mod.rs index 93afbb921..1aeb18bc6 100644 --- a/core/embed/rust/src/ui/model_mercury/theme/mod.rs +++ b/core/embed/rust/src/ui/model_mercury/theme/mod.rs @@ -88,6 +88,7 @@ include_icon!(ICON_WARNING, "model_mercury/res/warning24.toif"); // 30x30 include_icon!(ICON_AUTOFILL, "model_mercury/res/autofill30.toif"); include_icon!(ICON_CLOSE, "model_mercury/res/close30.toif"); +include_icon!(ICON_CONFIRM_INPUT, "model_mercury/res/confirm_input30.toif"); include_icon!(ICON_DELETE, "model_mercury/res/delete30.toif"); include_icon!(ICON_MENU, "model_mercury/res/menu30.toif"); include_icon!( @@ -388,22 +389,22 @@ pub const fn button_reset() -> ButtonStyleSheet { pub const fn button_pin() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { - font: Font::MONO, - text_color: FG, - button_color: GREY_DARK, + font: Font::NORMAL, + text_color: GREY_LIGHT, + button_color: GREY_EXTRA_DARK, icon_color: GREY_LIGHT, background_color: BG, }, active: &ButtonStyle { - font: Font::MONO, - text_color: FG, - button_color: GREY_MEDIUM, + font: Font::NORMAL, + text_color: GREY_LIGHT, + button_color: GREY_EXTRA_DARK, icon_color: GREY_LIGHT, background_color: BG, }, disabled: &ButtonStyle { - font: Font::MONO, - text_color: GREY_LIGHT, + font: Font::NORMAL, + text_color: GREY_DARK, button_color: BG, // so there is no "button" itself, just the text icon_color: GREY_LIGHT, background_color: BG, @@ -411,27 +412,29 @@ pub const fn button_pin() -> ButtonStyleSheet { } } +// TODO: will button_pin_xyz styles be the same for PIN and Mnemonic keyboard? +// Wait for Figma pub const fn button_pin_confirm() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREEN, - icon_color: GREY_LIGHT, + button_color: BG, + icon_color: GREEN_LIGHT, background_color: BG, }, active: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREEN_DARK, - icon_color: GREY_LIGHT, + button_color: GREY_DARK, + icon_color: GREEN_LIGHT, background_color: BG, }, disabled: &ButtonStyle { font: Font::MONO, - text_color: GREY_LIGHT, - button_color: GREY_DARK, - icon_color: GREY_LIGHT, + text_color: FG, + button_color: BG, + icon_color: GREEN_LIGHT, background_color: BG, }, } @@ -442,20 +445,20 @@ pub const fn button_pin_autocomplete() -> ButtonStyleSheet { normal: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREY_DARK, // same as PIN buttons + button_color: BG, icon_color: GREY_LIGHT, background_color: BG, }, active: &ButtonStyle { font: Font::MONO, text_color: FG, - button_color: GREEN_DARK, + button_color: BG, icon_color: GREY_LIGHT, background_color: BG, }, disabled: &ButtonStyle { font: Font::MONO, - text_color: GREY_LIGHT, + text_color: FG, button_color: BG, icon_color: GREY_LIGHT, background_color: BG, @@ -467,7 +470,7 @@ pub const fn button_suggestion_confirm() -> ButtonStyleSheet { ButtonStyleSheet { normal: &ButtonStyle { font: Font::MONO, - text_color: GREEN_DARK, + text_color: GREY_LIGHT, button_color: GREEN, icon_color: GREY_LIGHT, background_color: BG, @@ -639,9 +642,9 @@ pub const TEXT_CHECKLIST_DONE: TextStyle = TextStyle::new(Font::NORMAL, GREEN_DARK, BG, GREY_LIGHT, GREY_LIGHT); 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 BUTTON_HEIGHT: i16 = 62; +pub const BUTTON_WIDTH: i16 = 78; +pub const BUTTON_SPACING: i16 = 2; pub const KEYBOARD_SPACING: i16 = BUTTON_SPACING; pub const CHECKLIST_SPACING: i16 = 10; pub const RECOVERY_SPACING: i16 = 18; diff --git a/core/mocks/generated/trezorui2.pyi b/core/mocks/generated/trezorui2.pyi index d03a58cdc..6e16c11c9 100644 --- a/core/mocks/generated/trezorui2.pyi +++ b/core/mocks/generated/trezorui2.pyi @@ -154,6 +154,11 @@ def confirm_reset_device( """Confirm TOS before device setup.""" +# rust/src/ui/model_mercury/layout.rs +def confirm_create_wallet() -> LayoutObj[UiResult]: + """Confirm creating wallet""" + + # rust/src/ui/model_mercury/layout.rs def show_address_details( *, diff --git a/core/src/trezor/ui/layouts/mercury/__init__.py b/core/src/trezor/ui/layouts/mercury/__init__.py index af012cfef..d33eda0cf 100644 --- a/core/src/trezor/ui/layouts/mercury/__init__.py +++ b/core/src/trezor/ui/layouts/mercury/__init__.py @@ -228,11 +228,12 @@ def draw_simple(layout: Any) -> None: ui.backlight_fade(ui.style.BACKLIGHT_NORMAL) -async def raise_if_not_confirmed(a: Awaitable[T], exc: Any = ActionCancelled) -> T: +async def raise_if_not_confirmed( + a: Awaitable[ui.UiResult], exc: Any = ActionCancelled +) -> None: result = await a if result is not CONFIRMED: raise exc - return result async def confirm_action( @@ -322,22 +323,36 @@ async def confirm_single( async def confirm_reset_device(title: str, recovery: bool = False) -> None: - await raise_if_not_confirmed( - interact( + if recovery: + await raise_if_not_confirmed( + interact( + RustLayout( + trezorui2.confirm_reset_device( + title=title, + button="", # not used + ) + ), + "recover_device", + ButtonRequestType.ProtectCall, + ) + ) + else: + # creating wallet shows TOS first and then an extra screen confirms + await raise_if_not_confirmed( RustLayout( trezorui2.confirm_reset_device( title=title, button="", # not used ) ), - "recover_device" if recovery else "setup_device", - ( - ButtonRequestType.ProtectCall - if recovery - else ButtonRequestType.ResetDevice - ), ) - ) + await raise_if_not_confirmed( + interact( + RustLayout(trezorui2.confirm_create_wallet()), + "setup_device", + ButtonRequestType.ResetDevice, + ) + ) async def prompt_backup() -> bool: @@ -565,15 +580,12 @@ async def show_success( subheader: str | None = None, button: str | None = None, ) -> None: - button = button or TR.buttons__continue # def_arg await raise_if_not_confirmed( interact( RustLayout( trezorui2.show_success( - title=subheader or "", + title=content, description="", - button=button.upper(), - allow_cancel=False, ) ), br_type, diff --git a/core/src/trezor/ui/layouts/mercury/recovery.py b/core/src/trezor/ui/layouts/mercury/recovery.py index 10c8f3aa5..410434d10 100644 --- a/core/src/trezor/ui/layouts/mercury/recovery.py +++ b/core/src/trezor/ui/layouts/mercury/recovery.py @@ -160,9 +160,7 @@ async def show_recovery_warning( RustLayout( trezorui2.show_warning( title=content, - description=subheader or "", - button=button.upper(), - allow_cancel=False, + value="Try again", # TODO: use TR ) ), br_type, diff --git a/core/src/trezor/ui/layouts/mercury/reset.py b/core/src/trezor/ui/layouts/mercury/reset.py index 337ab74d4..a6025edc2 100644 --- a/core/src/trezor/ui/layouts/mercury/reset.py +++ b/core/src/trezor/ui/layouts/mercury/reset.py @@ -41,10 +41,7 @@ async def show_share_words( result = await interact( RustLayout( - trezorui2.confirm_backup_written_down( - title=title, - pages=share_words, - ), + trezorui2.confirm_backup_written_down(), ), "backup_words", ButtonRequestType.ResetDevice,