mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-18 05:28:40 +00:00
feat(core): mercury ui homescreen
[no changelog]
This commit is contained in:
parent
429a558d78
commit
88078db700
@ -8,7 +8,7 @@ use crate::{
|
|||||||
component::{Component, Event, EventCtx, TimerToken},
|
component::{Component, Event, EventCtx, TimerToken},
|
||||||
display::{image::ImageInfo, toif::Icon, Color, Font},
|
display::{image::ImageInfo, toif::Icon, Color, Font},
|
||||||
event::{TouchEvent, USBEvent},
|
event::{TouchEvent, USBEvent},
|
||||||
geometry::{Alignment, Alignment2D, Insets, Offset, Point, Rect},
|
geometry::{Alignment, Alignment2D, Offset, Point, Rect},
|
||||||
layout::util::get_user_custom_image,
|
layout::util::get_user_custom_image,
|
||||||
model_mercury::{constant, theme::IMAGE_HOMESCREEN},
|
model_mercury::{constant, theme::IMAGE_HOMESCREEN},
|
||||||
shape::{self, Renderer},
|
shape::{self, Renderer},
|
||||||
@ -17,10 +17,11 @@ use crate::{
|
|||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
|
component::Label,
|
||||||
constant::{screen, HEIGHT, WIDTH},
|
constant::{screen, HEIGHT, WIDTH},
|
||||||
model_mercury::{
|
model_mercury::{
|
||||||
cshape,
|
cshape,
|
||||||
theme::{GREY_LIGHT, ICON_KEY},
|
theme::{GREY_LIGHT, ICON_KEY, TITLE_HEIGHT},
|
||||||
},
|
},
|
||||||
shape::{render_on_canvas, ImageBuffer, Rgb565Canvas},
|
shape::{render_on_canvas, ImageBuffer, Rgb565Canvas},
|
||||||
util::animation_disabled,
|
util::animation_disabled,
|
||||||
@ -51,7 +52,7 @@ pub struct HomescreenNotification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Homescreen {
|
pub struct Homescreen {
|
||||||
label: TString<'static>,
|
label: Label<'static>,
|
||||||
notification: Option<(TString<'static>, u8)>,
|
notification: Option<(TString<'static>, u8)>,
|
||||||
image: BinaryData<'static>,
|
image: BinaryData<'static>,
|
||||||
hold_to_lock: bool,
|
hold_to_lock: bool,
|
||||||
@ -70,7 +71,7 @@ impl Homescreen {
|
|||||||
hold_to_lock: bool,
|
hold_to_lock: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
label,
|
label: Label::new(label, Alignment::Start, theme::TEXT_DEMIBOLD).vertically_centered(),
|
||||||
notification,
|
notification,
|
||||||
image: get_homescreen_image(),
|
image: get_homescreen_image(),
|
||||||
hold_to_lock,
|
hold_to_lock,
|
||||||
@ -81,10 +82,10 @@ impl Homescreen {
|
|||||||
|
|
||||||
fn level_to_style(level: u8) -> (Color, Icon) {
|
fn level_to_style(level: u8) -> (Color, Icon) {
|
||||||
match level {
|
match level {
|
||||||
3 => (theme::YELLOW, theme::ICON_COINJOIN),
|
3 => (theme::ORANGE_DARK, theme::ICON_COINJOIN),
|
||||||
2 => (theme::VIOLET, theme::ICON_MAGIC),
|
2 => (theme::ORANGE_DARK, theme::ICON_MAGIC),
|
||||||
1 => (theme::YELLOW, theme::ICON_WARN),
|
1 => (theme::ORANGE_DARK, theme::ICON_WARN),
|
||||||
_ => (theme::RED, theme::ICON_WARN),
|
_ => (theme::ORANGE_DARK, theme::ICON_WARN),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +171,8 @@ impl Component for Homescreen {
|
|||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
self.loader.place(AREA.translate(LOADER_OFFSET));
|
self.loader.place(AREA.translate(LOADER_OFFSET));
|
||||||
|
self.label
|
||||||
|
.place(bounds.split_top(TITLE_HEIGHT).0.translate(Offset::x(4)));
|
||||||
bounds
|
bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,65 +193,61 @@ impl Component for Homescreen {
|
|||||||
if self.loader.is_animating() || self.loader.is_completely_grown(Instant::now()) {
|
if self.loader.is_animating() || self.loader.is_completely_grown(Instant::now()) {
|
||||||
self.render_loader(target);
|
self.render_loader(target);
|
||||||
} else {
|
} else {
|
||||||
match ImageInfo::parse(self.image) {
|
if let ImageInfo::Jpeg(_) = ImageInfo::parse(self.image) {
|
||||||
ImageInfo::Jpeg(_) => shape::JpegImage::new_image(AREA.center(), self.image)
|
shape::JpegImage::new_image(AREA.center(), self.image)
|
||||||
.with_align(Alignment2D::CENTER)
|
.with_align(Alignment2D::CENTER)
|
||||||
.render(target),
|
.render(target);
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.label.map(|t| {
|
let label_width = self
|
||||||
let r = Rect::new(Point::new(6, 198), Point::new(234, 233));
|
.label
|
||||||
shape::Bar::new(r)
|
.text()
|
||||||
.with_bg(Color::black())
|
.map(|t| theme::TEXT_DEMIBOLD.text_font.text_width(t));
|
||||||
.with_alpha(89)
|
|
||||||
.with_radius(3)
|
|
||||||
.render(target);
|
|
||||||
|
|
||||||
let style = theme::TEXT_DEMIBOLD;
|
let r = Rect::new(Point::new(-30, -30), Point::new(label_width + 12, 42));
|
||||||
let pos = Point::new(AREA.center().x, LABEL_Y);
|
shape::Bar::new(r)
|
||||||
shape::Text::new(pos, t)
|
.with_bg(Color::black())
|
||||||
.with_align(Alignment::Center)
|
.with_alpha(160)
|
||||||
.with_font(style.text_font)
|
.with_radius(16)
|
||||||
.with_fg(theme::FG)
|
.render(target);
|
||||||
.render(target);
|
|
||||||
});
|
self.label.render(target);
|
||||||
|
|
||||||
if let Some(notif) = self.get_notification() {
|
if let Some(notif) = self.get_notification() {
|
||||||
const NOTIFICATION_HEIGHT: i16 = 36;
|
const NOTIFICATION_HEIGHT: i16 = 34;
|
||||||
const NOTIFICATION_BORDER: i16 = 6;
|
const NOTIFICATION_TOP: i16 = 202;
|
||||||
const TEXT_ICON_SPACE: i16 = 8;
|
const NOTIFICATION_BORDER: i16 = 16;
|
||||||
|
|
||||||
let banner = AREA
|
|
||||||
.inset(Insets::sides(NOTIFICATION_BORDER))
|
|
||||||
.with_height(NOTIFICATION_HEIGHT)
|
|
||||||
.translate(Offset::y(NOTIFICATION_BORDER));
|
|
||||||
|
|
||||||
shape::Bar::new(banner)
|
|
||||||
.with_radius(2)
|
|
||||||
.with_bg(notif.color)
|
|
||||||
.render(target);
|
|
||||||
|
|
||||||
notif.text.map(|t| {
|
notif.text.map(|t| {
|
||||||
let style = theme::TEXT_BOLD;
|
let style = theme::TEXT_BOLD;
|
||||||
let icon_width = notif.icon.toif.width() + TEXT_ICON_SPACE;
|
|
||||||
|
let text_width = style.text_font.text_width(t);
|
||||||
|
|
||||||
|
let banner = Rect::new(
|
||||||
|
Point::new(
|
||||||
|
AREA.center().x - NOTIFICATION_BORDER - text_width / 2,
|
||||||
|
NOTIFICATION_TOP,
|
||||||
|
),
|
||||||
|
Point::new(
|
||||||
|
AREA.center().x + NOTIFICATION_BORDER + text_width / 2,
|
||||||
|
NOTIFICATION_TOP + NOTIFICATION_HEIGHT,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
let text_pos = Point::new(
|
let text_pos = Point::new(
|
||||||
style
|
style.text_font.horz_center(banner.x0, banner.x1, t),
|
||||||
.text_font
|
|
||||||
.horz_center(banner.x0 + icon_width, banner.x1, t),
|
|
||||||
style.text_font.vert_center(banner.y0, banner.y1, "A"),
|
style.text_font.vert_center(banner.y0, banner.y1, "A"),
|
||||||
);
|
);
|
||||||
|
|
||||||
shape::Text::new(text_pos, t)
|
shape::Bar::new(banner)
|
||||||
.with_font(style.text_font)
|
.with_radius(16)
|
||||||
.with_fg(style.text_color)
|
.with_bg(theme::ORANGE_DARK)
|
||||||
|
.with_alpha(160)
|
||||||
.render(target);
|
.render(target);
|
||||||
|
|
||||||
let icon_pos = Point::new(text_pos.x - icon_width, banner.center().y);
|
shape::Text::new(text_pos, t)
|
||||||
|
.with_font(style.text_font)
|
||||||
shape::ToifImage::new(icon_pos, notif.icon.toif)
|
.with_fg(theme::ORANGE_LIGHT)
|
||||||
.with_fg(style.text_color)
|
|
||||||
.with_align(Alignment2D::CENTER_LEFT)
|
|
||||||
.render(target);
|
.render(target);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -266,7 +265,7 @@ impl Component for Homescreen {
|
|||||||
impl crate::trace::Trace for Homescreen {
|
impl crate::trace::Trace for Homescreen {
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.component("Homescreen");
|
t.component("Homescreen");
|
||||||
t.string("label", self.label);
|
t.child("label", &self.label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ mod frame;
|
|||||||
|
|
||||||
#[cfg(feature = "translations")]
|
#[cfg(feature = "translations")]
|
||||||
mod hold_to_confirm;
|
mod hold_to_confirm;
|
||||||
#[cfg(feature = "micropython")]
|
#[cfg(feature = "translations")]
|
||||||
mod homescreen;
|
mod homescreen;
|
||||||
#[cfg(feature = "translations")]
|
#[cfg(feature = "translations")]
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
Loading…
Reference in New Issue
Block a user