diff --git a/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs b/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs index 9c2231fa33..348255b4cc 100644 --- a/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs +++ b/core/embed/rust/src/ui/layout_eckhart/theme/mod.rs @@ -12,6 +12,7 @@ use super::{ fonts, }; +pub const CONFIRM_HOLD_DURATION: Duration = Duration::from_millis(1500); pub const ERASE_HOLD_DURATION: Duration = Duration::from_millis(1500); // Color palette. @@ -147,7 +148,7 @@ pub const fn button_default() -> ButtonStyleSheet { font: fonts::FONT_SATOSHI_MEDIUM_26, text_color: GREY_LIGHT, button_color: BG, - icon_color: FG, + icon_color: GREY_LIGHT, background_color: BG, }, active: &ButtonStyle { @@ -167,6 +168,32 @@ pub const fn button_default() -> ButtonStyleSheet { } } +pub const fn button_confirm() -> ButtonStyleSheet { + ButtonStyleSheet { + normal: &ButtonStyle { + font: fonts::FONT_SATOSHI_MEDIUM_26, + text_color: GREEN_LIGHT, + button_color: BG, + icon_color: GREEN_LIGHT, + background_color: BG, + }, + active: &ButtonStyle { + font: fonts::FONT_SATOSHI_MEDIUM_26, + text_color: GREEN, + button_color: GREY_SUPER_DARK, + icon_color: GREEN, + background_color: BG, + }, + disabled: &ButtonStyle { + font: fonts::FONT_SATOSHI_MEDIUM_26, + text_color: GREY_LIGHT, + button_color: GREY_DARK, + icon_color: GREY_LIGHT, + background_color: GREY_DARK, + }, + } +} + pub const fn button_header() -> ButtonStyleSheet { ButtonStyleSheet { diff --git a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs index c1c0c381bf..80f40b59e5 100644 --- a/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs +++ b/core/embed/rust/src/ui/layout_eckhart/ui_firmware.rs @@ -3,14 +3,18 @@ use crate::{ io::BinaryData, micropython::{gc::Gc, list::List, obj::Obj}, strutil::TString, + translations::TR, ui::{ component::{ - text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort}, - Empty, + text::{ + op::OpTextLayout, + paragraphs::{Paragraph, ParagraphSource, ParagraphVecShort}, + }, + Empty, FormattedText, }, layout::{ obj::{LayoutMaybeTrace, LayoutObj, RootComponent}, - util::RecoveryType, + util::{ConfirmValueParams, RecoveryType, StrOrBytes}, }, ui_firmware::{ FirmwareUI, MAX_CHECKLIST_ITEMS, MAX_GROUP_SHARE_LINES, MAX_WORD_QUIZ_ITEMS, @@ -20,25 +24,60 @@ use crate::{ }; use super::{ - component::{ActionBar, Button, GenericScreen, Header, Hint}, - theme, UIEckhart, + component::{ActionBar, Button, Header, Hint, TextScreen}, + fonts, theme, UIEckhart, }; impl FirmwareUI for UIEckhart { fn confirm_action( - _title: TString<'static>, - _action: Option>, - _description: Option>, + title: TString<'static>, + action: Option>, + description: Option>, _subtitle: Option>, - _verb: Option>, + verb: Option>, _verb_cancel: Option>, - _hold: bool, + hold: bool, _hold_danger: bool, - _reverse: bool, + reverse: bool, _prompt_screen: bool, _prompt_title: Option>, ) -> Result { - Err::, Error>(Error::ValueError(c"not implemented")) + let action = action.unwrap_or("".into()); + let description = description.unwrap_or("".into()); + let formatted_text = { + let ops = if !reverse { + OpTextLayout::new(theme::TEXT_NORMAL) + .color(theme::GREY_LIGHT) + .text(action, fonts::FONT_SATOSHI_REGULAR_38) + .newline() + .color(theme::GREY) + .text(description, fonts::FONT_SATOSHI_REGULAR_22) + } else { + OpTextLayout::new(theme::TEXT_NORMAL) + .color(theme::GREY) + .text(description, fonts::FONT_SATOSHI_REGULAR_22) + .newline() + .color(theme::GREY_LIGHT) + .text(action, fonts::FONT_SATOSHI_REGULAR_38) + }; + FormattedText::new(ops).vertically_centered() + }; + + let verb = verb.unwrap_or(TR::buttons__confirm.into()); + let right_button = if hold { + Button::with_text(verb).with_long_press(theme::CONFIRM_HOLD_DURATION) + } else { + Button::with_text(verb) + }; + let screen = TextScreen::new(formatted_text) + .with_header(Header::new(title).with_menu_button()) + .with_hint(Hint::new_instruction(description, None)) + .with_action_bar(ActionBar::new_double( + Button::with_icon(theme::ICON_CHEVRON_LEFT), + right_button, + )); + let layout = RootComponent::new(screen); + Ok(layout) } fn confirm_address(