mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-20 05:28:14 +00:00
feat(eckhart): bld welcome screen
[no changelog]
This commit is contained in:
parent
cb9eb28dc9
commit
cf1e892d13
@ -1,23 +1,23 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
trezorhal::ble,
|
||||
ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
geometry::{Offset, Point, Rect},
|
||||
geometry::{Alignment2D, Offset, Point, Rect},
|
||||
shape::{self, Renderer},
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
super::{constant::SCREEN, fonts, theme},
|
||||
BldActionBar, BldHeader,
|
||||
super::{component::Button, constant::SCREEN, fonts, theme},
|
||||
BldActionBar, BldActionBarMsg, BldHeader,
|
||||
};
|
||||
|
||||
#[cfg(feature = "power_manager")]
|
||||
use super::BldHeaderMsg;
|
||||
|
||||
// TODO: adjust the origin
|
||||
const TEXT_ORIGIN: Point = Point::new(24, 205);
|
||||
const STRIDE: i16 = 38;
|
||||
const TEXT_ORIGIN: Point = Point::new(24, 76);
|
||||
const STRIDE: i16 = 46;
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, ToPrimitive)]
|
||||
@ -27,48 +27,60 @@ pub enum WelcomeMsg {
|
||||
Menu = 3,
|
||||
}
|
||||
|
||||
/// Bootloader welcome screen
|
||||
/// Full-screen component for Bootloader welcome screen. This is the first
|
||||
/// screen shown after the bootloader is started on empty device. The user can
|
||||
/// initiate pairing. If the device is already paired, the screen shows a
|
||||
/// message that Trezor is paired and Bootloader Menu is accessible.
|
||||
pub struct BldWelcomeScreen {
|
||||
header: Option<BldHeader<'static>>,
|
||||
action_bar: Option<BldActionBar>,
|
||||
action_bar: BldActionBar,
|
||||
ble_paired: bool,
|
||||
}
|
||||
|
||||
impl BldWelcomeScreen {
|
||||
pub fn new() -> Self {
|
||||
let ble_paired = ble::peer_count() > 0;
|
||||
let (header, button) = if ble_paired {
|
||||
(
|
||||
Some(BldHeader::new(TString::empty()).with_menu_button()),
|
||||
Button::with_text("More at trezor.io/start".into())
|
||||
.styled(theme::bootloader::button_welcome_screen())
|
||||
.initially_enabled(false),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
None,
|
||||
Button::with_text("Tap to begin setup".into())
|
||||
.styled(theme::bootloader::button_welcome_screen())
|
||||
.initially_enabled(true),
|
||||
)
|
||||
};
|
||||
Self {
|
||||
header: Some(BldHeader::new(TString::empty()).with_menu_button()),
|
||||
action_bar: None,
|
||||
header,
|
||||
action_bar: BldActionBar::new_single(button),
|
||||
ble_paired,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_header(mut self, header: BldHeader<'static>) -> Self {
|
||||
self.header = Some(header);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_action_bar(mut self, action_bar: BldActionBar) -> Self {
|
||||
self.action_bar = Some(action_bar);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for BldWelcomeScreen {
|
||||
type Msg = WelcomeMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
fn place(&mut self, _bounds: Rect) -> Rect {
|
||||
let (header_area, rest) = SCREEN.split_top(theme::HEADER_HEIGHT);
|
||||
let (_rest, action_bar_area) = rest.split_bottom(theme::ACTION_BAR_HEIGHT);
|
||||
|
||||
self.header.place(header_area);
|
||||
self.action_bar.place(action_bar_area);
|
||||
bounds
|
||||
SCREEN
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
#[cfg(all(feature = "ble", feature = "button"))]
|
||||
if let Event::Button(_) = _event {
|
||||
#[cfg(feature = "ble")]
|
||||
if let Some(BldActionBarMsg::Confirmed) = self.action_bar.event(_ctx, _event) {
|
||||
return Some(WelcomeMsg::PairingMode);
|
||||
}
|
||||
|
||||
#[cfg(feature = "power_manager")]
|
||||
if let Some(BldHeaderMsg::Menu) = self.header.event(_ctx, _event) {
|
||||
return Some(WelcomeMsg::Menu);
|
||||
@ -77,31 +89,40 @@ impl Component for BldWelcomeScreen {
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.action_bar.render(target);
|
||||
#[cfg(feature = "power_manager")]
|
||||
self.header.render(target);
|
||||
|
||||
let font = fonts::FONT_SATOSHI_REGULAR_38;
|
||||
shape::Text::new(TEXT_ORIGIN, "Get started", font)
|
||||
.with_fg(theme::GREY)
|
||||
shape::Text::new(TEXT_ORIGIN, "Trezor", font)
|
||||
.with_fg(theme::GREY_LIGHT)
|
||||
.render(target);
|
||||
|
||||
shape::Text::new(TEXT_ORIGIN + Offset::y(STRIDE), "with your Trezor", font)
|
||||
.with_fg(theme::GREY)
|
||||
shape::Text::new(TEXT_ORIGIN + Offset::y(STRIDE), "Safe", font)
|
||||
.with_fg(theme::GREY_LIGHT)
|
||||
.render(target);
|
||||
|
||||
shape::Text::new(TEXT_ORIGIN + Offset::y(2 * STRIDE), "at", font)
|
||||
.with_fg(theme::GREY)
|
||||
.render(target);
|
||||
|
||||
let at_width = font.text_width("at ");
|
||||
|
||||
shape::Text::new(
|
||||
TEXT_ORIGIN + Offset::new(at_width, 2 * STRIDE),
|
||||
"trezor.io/start",
|
||||
font,
|
||||
shape::ToifImage::new(
|
||||
TEXT_ORIGIN + Offset::y(2 * STRIDE),
|
||||
theme::bootloader::ICON_SEVEN.toif,
|
||||
)
|
||||
.with_fg(theme::GREY_EXTRA_LIGHT)
|
||||
.with_fg(theme::GREY)
|
||||
.with_align(Alignment2D::CENTER_LEFT)
|
||||
.render(target);
|
||||
|
||||
// hint
|
||||
let icon_pos = Point::new(24, 398);
|
||||
let link_pos = icon_pos + Offset::x(theme::ICON_INFO.toif.width() + 12);
|
||||
let (hint_color, hint_text) = if self.ble_paired {
|
||||
(theme::GREEN_LIME, "Trezor is paired")
|
||||
} else {
|
||||
(theme::GREY, "trezor.io/start")
|
||||
};
|
||||
shape::ToifImage::new(icon_pos, theme::ICON_INFO.toif)
|
||||
.with_fg(hint_color)
|
||||
.with_align(Alignment2D::BOTTOM_LEFT)
|
||||
.render(target);
|
||||
shape::Text::new(link_pos, hint_text, fonts::FONT_SATOSHI_MEDIUM_26)
|
||||
.with_fg(hint_color)
|
||||
.render(target);
|
||||
|
||||
self.action_bar.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ use super::{
|
||||
component::{ButtonStyle, ButtonStyleSheet},
|
||||
fonts,
|
||||
},
|
||||
BLACK, BLUE, GREY, GREY_DARK, GREY_EXTRA_LIGHT, GREY_LIGHT, GREY_SUPER_DARK, ORANGE, RED,
|
||||
WHITE,
|
||||
BLACK, BLUE, GREEN_LIGHT, GREY, GREY_DARK, GREY_EXTRA_LIGHT, GREY_LIGHT, GREY_SUPER_DARK,
|
||||
ORANGE, RED, WHITE,
|
||||
};
|
||||
|
||||
pub const BLD_BG: Color = BLACK;
|
||||
@ -181,6 +181,34 @@ pub fn button_bld_menu_danger() -> ButtonStyleSheet {
|
||||
}
|
||||
}
|
||||
|
||||
/// Button style for the welcome screen
|
||||
pub fn button_welcome_screen() -> ButtonStyleSheet {
|
||||
ButtonStyleSheet {
|
||||
normal: &ButtonStyle {
|
||||
font: fonts::FONT_SATOSHI_MEDIUM_26,
|
||||
text_color: GREY_LIGHT,
|
||||
button_color: BLD_BG,
|
||||
icon_color: GREY_LIGHT,
|
||||
background_color: BLD_BG,
|
||||
},
|
||||
active: &ButtonStyle {
|
||||
font: fonts::FONT_SATOSHI_MEDIUM_26,
|
||||
text_color: GREY_EXTRA_LIGHT,
|
||||
button_color: GREY_SUPER_DARK,
|
||||
icon_color: GREY_EXTRA_LIGHT,
|
||||
background_color: BLD_BG,
|
||||
},
|
||||
// used for the "Trezor is paired" button/footer
|
||||
disabled: &ButtonStyle {
|
||||
font: fonts::FONT_SATOSHI_MEDIUM_26,
|
||||
text_color: GREEN_LIGHT,
|
||||
button_color: BLD_BG,
|
||||
icon_color: GREEN_LIGHT,
|
||||
background_color: BLD_FG,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn text_title(bg: Color) -> TextStyle {
|
||||
TextStyle::new(fonts::FONT_SATOSHI_MEDIUM_26, GREY, bg, GREY, GREY)
|
||||
}
|
||||
|
@ -133,8 +133,6 @@ impl BootloaderLayoutType for BootloaderLayout {
|
||||
}
|
||||
|
||||
fn init_welcome() -> Self {
|
||||
// TODO: different UI. needs to decide based on some host already paired:
|
||||
// peer_count() > 0
|
||||
let screen = BldWelcomeScreen::new();
|
||||
Self::Welcome(screen)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user