1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-22 11:05:43 +00:00

feat(eckhart): make homescreen hold to lock

- lock the device by long-pressing the homescreen anywhere but the
action bar
This commit is contained in:
obrusvit 2025-03-19 23:23:57 +01:00
parent 99b48fd578
commit 4e9cbc10fd
5 changed files with 88 additions and 15 deletions

View File

@ -221,6 +221,11 @@ impl Button {
self.area
}
pub fn touch_area(&self) -> Rect {
self.touch_expand
.map_or(self.area, |expand| self.area.outset(expand))
}
fn set(&mut self, ctx: &mut EventCtx, state: State) {
if self.state != state {
self.state = state;
@ -364,12 +369,7 @@ impl Component for Button {
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
let touch_area = if let Some(expand) = self.touch_expand {
self.area.outset(expand)
} else {
self.area
};
let touch_area = self.touch_area();
match event {
Event::Touch(TouchEvent::TouchStart(pos)) => {
match self.state {

View File

@ -74,6 +74,7 @@ impl ComponentMsgObj for Homescreen {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
HomescreenMsg::Dismissed => Ok(CANCELLED.as_obj()),
HomescreenMsg::Menu => Ok(INFO.as_obj()),
}
}
}

View File

@ -124,6 +124,13 @@ impl ActionBar {
self.right_button.set_expanded_touch_area(expand);
}
pub fn touch_area(&self) -> Rect {
let right_area = self.right_button.touch_area();
self.left_button
.as_ref()
.map_or(right_area, |left| right_area.union(left.touch_area()))
}
pub fn update(&mut self, new_pager: Pager) {
// TODO: review `clone()` of `left_content`/`right_content`
if let Mode::Double { pager } = &mut self.mode {
@ -347,9 +354,7 @@ impl Component for ActionBar {
btn.render(target);
}
self.right_button.render(target);
if let Some(htc_anim) = &self.htc_anim {
htc_anim.render(target);
}
self.htc_anim.render(target);
}
}

View File

@ -9,6 +9,7 @@ use crate::{
geometry::{Insets, Offset, Rect},
layout::util::get_user_custom_image,
shape::{self, Renderer},
util::{animation_disabled, Pager},
},
};
@ -16,7 +17,7 @@ use super::{
super::{component::Button, fonts},
constant::{HEIGHT, SCREEN, WIDTH},
theme::{self, firmware::button_homebar_style, BLACK, GREEN_DARK, GREEN_EXTRA_DARK},
ActionBar, ActionBarMsg, Hint,
ActionBar, ActionBarMsg, Hint, HoldToConfirmAnim,
};
/// Full-screen component for the homescreen and lockscreen.
@ -33,10 +34,15 @@ pub struct Homescreen {
lockable: bool,
/// Whether the homescreen is locked
locked: bool,
/// Hold to lock button placed everywhere except the `action_bar`
virtual_locking_button: Button,
/// Hold to lock animation
htc_anim: Option<HoldToConfirmAnim>,
}
pub enum HomescreenMsg {
Dismissed,
Menu,
}
impl Homescreen {
@ -81,6 +87,20 @@ impl Homescreen {
Button::with_homebar_content(None).styled(button_style)
};
let lock_duration = theme::LOCK_HOLD_DURATION;
// Locking animation
let htc_anim = if lockable && !animation_disabled() {
Some(
HoldToConfirmAnim::new()
.with_color(theme::GREY_LIGHT)
.with_duration(lock_duration)
.with_header_overlay(TR::progress__locking_device.into()),
)
} else {
None
};
Ok(Self {
label: HomeLabel::new(label),
hint,
@ -88,8 +108,49 @@ impl Homescreen {
image,
lockable,
locked,
virtual_locking_button: Button::empty().with_long_press(lock_duration),
htc_anim,
})
}
fn event_hold(&mut self, ctx: &mut EventCtx, event: Event) -> bool {
self.htc_anim.event(ctx, event);
if let Some(msg) = self.virtual_locking_button.event(ctx, event) {
match msg {
ButtonMsg::Pressed => {
if let Some(htc_anim) = &mut self.htc_anim {
htc_anim.start();
ctx.request_anim_frame();
ctx.request_paint();
ctx.disable_swipe();
}
}
ButtonMsg::Clicked => {
if let Some(htc_anim) = &mut self.htc_anim {
htc_anim.stop();
ctx.request_anim_frame();
ctx.request_paint();
ctx.enable_swipe();
} else {
// Animations disabled
return true;
}
}
ButtonMsg::Released => {
if let Some(htc_anim) = &mut self.htc_anim {
htc_anim.stop();
ctx.request_anim_frame();
ctx.request_paint();
ctx.enable_swipe();
}
}
ButtonMsg::LongPressed => {
return true;
}
}
}
false
}
}
impl Component for Homescreen {
@ -114,6 +175,9 @@ impl Component for Homescreen {
self.label.place(label_area);
self.action_bar.place(bar_area);
// Locking button is placed everywhere except the action bar
let locking_area = bounds.inset(Insets::bottom(self.action_bar.touch_area().height()));
self.virtual_locking_button.place(locking_area);
bounds
}
@ -122,13 +186,14 @@ impl Component for Homescreen {
if self.locked {
return Some(HomescreenMsg::Dismissed);
} else {
// TODO: Show menu and handle "lock" action differently
if self.lockable {
return Some(HomescreenMsg::Dismissed);
}
return Some(HomescreenMsg::Menu);
}
}
None
if self.lockable {
Self::event_hold(self, ctx, event).then_some(HomescreenMsg::Dismissed)
} else {
None
}
}
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
@ -142,6 +207,7 @@ impl Component for Homescreen {
self.label.render(target);
self.hint.render(target);
self.action_bar.render(target);
self.htc_anim.render(target);
}
}

View File

@ -14,6 +14,7 @@ use super::{
*,
};
pub const LOCK_HOLD_DURATION: Duration = Duration::from_millis(1500);
pub const CONFIRM_HOLD_DURATION: Duration = Duration::from_millis(1500);
pub const ERASE_HOLD_DURATION: Duration = Duration::from_millis(1500);