mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 06:48:16 +00:00
fix(core/mercury): adjust swipe effect direction when animating transition through python
This commit is contained in:
parent
2de8acc141
commit
a4ff76e840
1
core/.changelog.d/3965.fixed
Normal file
1
core/.changelog.d/3965.fixed
Normal file
@ -0,0 +1 @@
|
||||
[T3T1] Improve swipe behavior and animations
|
@ -242,6 +242,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_flow_show_share_words;
|
||||
MP_QSTR_flow_warning_hi_prio;
|
||||
MP_QSTR_get_language;
|
||||
MP_QSTR_get_transition_out;
|
||||
MP_QSTR_haptic_feedback__disable;
|
||||
MP_QSTR_haptic_feedback__enable;
|
||||
MP_QSTR_haptic_feedback__subtitle;
|
||||
|
@ -212,6 +212,7 @@ where
|
||||
pub struct Root<T> {
|
||||
inner: Option<Child<T>>,
|
||||
marked_for_clear: bool,
|
||||
transition_out: Option<AttachType>,
|
||||
}
|
||||
|
||||
impl<T> Root<T> {
|
||||
@ -219,6 +220,7 @@ impl<T> Root<T> {
|
||||
Self {
|
||||
inner: Some(Child::new(component)),
|
||||
marked_for_clear: true,
|
||||
transition_out: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,6 +248,10 @@ impl<T> Root<T> {
|
||||
self.marked_for_clear = true;
|
||||
}
|
||||
|
||||
pub fn get_transition_out(&self) -> Option<AttachType> {
|
||||
self.transition_out
|
||||
}
|
||||
|
||||
pub fn delete(&mut self) {
|
||||
self.inner = None;
|
||||
}
|
||||
@ -270,6 +276,11 @@ where
|
||||
assert!(paint_msg.is_none());
|
||||
assert!(dummy_ctx.timers.is_empty());
|
||||
}
|
||||
|
||||
if let Some(t) = ctx.get_transition_out() {
|
||||
self.transition_out = Some(t);
|
||||
}
|
||||
|
||||
msg
|
||||
}
|
||||
|
||||
@ -528,6 +539,7 @@ pub struct EventCtx {
|
||||
root_repaint_requested: bool,
|
||||
swipe_disable_req: bool,
|
||||
swipe_enable_req: bool,
|
||||
transition_out: Option<AttachType>,
|
||||
}
|
||||
|
||||
impl EventCtx {
|
||||
@ -557,6 +569,7 @@ impl EventCtx {
|
||||
root_repaint_requested: false,
|
||||
swipe_disable_req: false,
|
||||
swipe_enable_req: false,
|
||||
transition_out: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,6 +671,7 @@ impl EventCtx {
|
||||
self.root_repaint_requested = false;
|
||||
self.swipe_disable_req = false;
|
||||
self.swipe_enable_req = false;
|
||||
self.transition_out = None;
|
||||
}
|
||||
|
||||
fn register_timer(&mut self, token: TimerToken, deadline: Duration) {
|
||||
@ -680,4 +694,12 @@ impl EventCtx {
|
||||
.unwrap_or(Self::STARTING_TIMER_TOKEN);
|
||||
token
|
||||
}
|
||||
|
||||
pub fn set_transition_out(&mut self, attach_type: AttachType) {
|
||||
self.transition_out = Some(attach_type);
|
||||
}
|
||||
|
||||
pub fn get_transition_out(&self) -> Option<AttachType> {
|
||||
self.transition_out
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::ui::{
|
||||
shape::Renderer,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, ToPrimitive, FromPrimitive)]
|
||||
#[cfg_attr(feature = "debug", derive(ufmt::derive::uDebug))]
|
||||
pub enum SwipeDirection {
|
||||
Up,
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
base::AttachType, swipe_detect::SwipeSettings, Component, Event, EventCtx, SwipeDetect,
|
||||
SwipeDetectMsg, SwipeDirection,
|
||||
},
|
||||
event::SwipeEvent,
|
||||
event::{SwipeEvent, TouchEvent},
|
||||
flow::{base::Decision, FlowMsg, FlowState, FlowStore},
|
||||
geometry::Rect,
|
||||
shape::Renderer,
|
||||
@ -107,6 +107,7 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
let mut decision: Decision<Q> = Decision::Nothing;
|
||||
let mut return_transition: AttachType = AttachType::Initial;
|
||||
|
||||
let mut attach = false;
|
||||
|
||||
@ -139,6 +140,8 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
||||
decision = self.handle_swipe_child(ctx, dir);
|
||||
}
|
||||
|
||||
return_transition = AttachType::Swipe(dir);
|
||||
|
||||
let states_num = self.internal_pages;
|
||||
if states_num > 0 {
|
||||
if config.has_horizontal_pages() {
|
||||
@ -230,6 +233,7 @@ impl<Q: FlowState, S: FlowStore> Component for SwipeFlow<Q, S> {
|
||||
None
|
||||
}
|
||||
Decision::Return(msg) => {
|
||||
ctx.set_transition_out(return_transition);
|
||||
self.swipe.reset();
|
||||
self.allow_swipe = true;
|
||||
Some(msg)
|
||||
|
@ -2,6 +2,7 @@ use core::{
|
||||
cell::RefCell,
|
||||
convert::{TryFrom, TryInto},
|
||||
};
|
||||
use num_traits::{FromPrimitive, ToPrimitive};
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
@ -9,7 +10,7 @@ use crate::{
|
||||
micropython::{
|
||||
buffer::StrBuffer,
|
||||
gc::Gc,
|
||||
macros::{obj_dict, obj_fn_1, obj_fn_2, obj_fn_var, obj_map, obj_type},
|
||||
macros::{obj_dict, obj_fn_1, obj_fn_2, obj_fn_3, obj_fn_var, obj_map, obj_type},
|
||||
map::Map,
|
||||
obj::{Obj, ObjBase},
|
||||
qstr::Qstr,
|
||||
@ -32,9 +33,33 @@ use crate::ui::{display::Color, shape::render_on_display};
|
||||
|
||||
#[cfg(feature = "button")]
|
||||
use crate::ui::event::ButtonEvent;
|
||||
#[cfg(feature = "touch")]
|
||||
use crate::ui::event::TouchEvent;
|
||||
use crate::ui::event::USBEvent;
|
||||
#[cfg(feature = "touch")]
|
||||
use crate::ui::{component::SwipeDirection, event::TouchEvent};
|
||||
|
||||
impl AttachType {
|
||||
fn to_obj(self) -> Obj {
|
||||
match self {
|
||||
Self::Initial => Obj::const_none(),
|
||||
#[cfg(feature = "touch")]
|
||||
Self::Swipe(dir) => dir.to_u8().into(),
|
||||
}
|
||||
}
|
||||
fn try_from_obj(obj: Obj) -> Result<Self, Error> {
|
||||
if obj == Obj::const_none() {
|
||||
return Ok(Self::Initial);
|
||||
}
|
||||
#[cfg(feature = "touch")]
|
||||
{
|
||||
let dir: u8 = obj.try_into()?;
|
||||
return Ok(AttachType::Swipe(
|
||||
SwipeDirection::from_u8(dir).ok_or(Error::TypeError)?,
|
||||
));
|
||||
}
|
||||
#[allow(unreachable_code)]
|
||||
Err(Error::TypeError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Conversion trait implemented by components that know how to convert their
|
||||
/// message values into MicroPython `Obj`s.
|
||||
@ -57,6 +82,7 @@ pub trait ObjComponent: MaybeTrace {
|
||||
fn obj_skip_paint(&mut self) {}
|
||||
fn obj_request_clear(&mut self) {}
|
||||
fn obj_delete(&mut self) {}
|
||||
fn obj_get_transition_out(&self) -> Result<Obj, Error>;
|
||||
}
|
||||
|
||||
impl<T> ObjComponent for Root<T>
|
||||
@ -112,6 +138,14 @@ where
|
||||
fn obj_delete(&mut self) {
|
||||
self.delete()
|
||||
}
|
||||
|
||||
fn obj_get_transition_out(&self) -> Result<Obj, Error> {
|
||||
if let Some(msg) = self.get_transition_out() {
|
||||
Ok(msg.to_obj())
|
||||
} else {
|
||||
Ok(Obj::const_none())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `LayoutObj` is a GC-allocated object exported to MicroPython, with type
|
||||
@ -278,6 +312,14 @@ impl LayoutObj {
|
||||
}
|
||||
}
|
||||
|
||||
fn obj_get_transition_out(&self) -> Result<Obj, Error> {
|
||||
let inner = &mut *self.inner.borrow_mut();
|
||||
|
||||
// Get transition out result
|
||||
// SAFETY: `inner.root` is unique because of the `inner.borrow_mut()`.
|
||||
unsafe { Gc::as_mut(&mut inner.root) }.obj_get_transition_out()
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
fn obj_bounds(&self) {
|
||||
use crate::ui::display;
|
||||
@ -299,7 +341,7 @@ impl LayoutObj {
|
||||
static TYPE: Type = obj_type! {
|
||||
name: Qstr::MP_QSTR_LayoutObj,
|
||||
locals: &obj_dict!(obj_map! {
|
||||
Qstr::MP_QSTR_attach_timer_fn => obj_fn_2!(ui_layout_attach_timer_fn).as_obj(),
|
||||
Qstr::MP_QSTR_attach_timer_fn => obj_fn_3!(ui_layout_attach_timer_fn).as_obj(),
|
||||
Qstr::MP_QSTR_touch_event => obj_fn_var!(4, 4, ui_layout_touch_event).as_obj(),
|
||||
Qstr::MP_QSTR_button_event => obj_fn_var!(3, 3, ui_layout_button_event).as_obj(),
|
||||
Qstr::MP_QSTR_progress_event => obj_fn_var!(3, 3, ui_layout_progress_event).as_obj(),
|
||||
@ -312,6 +354,7 @@ impl LayoutObj {
|
||||
Qstr::MP_QSTR___del__ => obj_fn_1!(ui_layout_delete).as_obj(),
|
||||
Qstr::MP_QSTR_page_count => obj_fn_1!(ui_layout_page_count).as_obj(),
|
||||
Qstr::MP_QSTR_button_request => obj_fn_1!(ui_layout_button_request).as_obj(),
|
||||
Qstr::MP_QSTR_get_transition_out => obj_fn_1!(ui_layout_get_transition_out).as_obj(),
|
||||
}),
|
||||
};
|
||||
&TYPE
|
||||
@ -378,11 +421,12 @@ impl TryFrom<Never> for Obj {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn ui_layout_attach_timer_fn(this: Obj, timer_fn: Obj) -> Obj {
|
||||
extern "C" fn ui_layout_attach_timer_fn(this: Obj, timer_fn: Obj, attach_type: Obj) -> Obj {
|
||||
let block = || {
|
||||
let this: Gc<LayoutObj> = this.try_into()?;
|
||||
this.obj_set_timer_fn(timer_fn);
|
||||
let msg = this.obj_event(Event::Attach(AttachType::Initial))?;
|
||||
|
||||
let msg = this.obj_event(Event::Attach(AttachType::try_from_obj(attach_type)?))?;
|
||||
assert!(msg == Obj::const_none());
|
||||
Ok(Obj::const_none())
|
||||
};
|
||||
@ -510,6 +554,14 @@ extern "C" fn ui_layout_button_request(this: Obj) -> Obj {
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
extern "C" fn ui_layout_get_transition_out(this: Obj) -> Obj {
|
||||
let block = || {
|
||||
let this: Gc<LayoutObj> = this.try_into()?;
|
||||
this.obj_get_transition_out()
|
||||
};
|
||||
unsafe { util::try_or_raise(block) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ui_debug_layout_type() -> &'static Type {
|
||||
|
@ -45,6 +45,9 @@ impl AttachAnimation {
|
||||
);
|
||||
|
||||
match attach_type {
|
||||
Some(AttachType::Initial) => {
|
||||
Offset::lerp(Offset::new(0, -20), Offset::zero(), value.eval(t))
|
||||
}
|
||||
Some(AttachType::Swipe(dir)) => match dir {
|
||||
SwipeDirection::Up => {
|
||||
Offset::lerp(Offset::new(0, 20), Offset::zero(), value.eval(t))
|
||||
@ -66,7 +69,8 @@ impl AttachAnimation {
|
||||
pareen::constant(1.0),
|
||||
);
|
||||
match attach_type {
|
||||
Some(AttachType::Swipe(SwipeDirection::Up))
|
||||
Some(AttachType::Initial)
|
||||
| Some(AttachType::Swipe(SwipeDirection::Up))
|
||||
| Some(AttachType::Swipe(SwipeDirection::Down)) => {}
|
||||
_ => {
|
||||
return 255;
|
||||
@ -89,9 +93,9 @@ pub struct SwipeContent<T> {
|
||||
bounds: Rect,
|
||||
progress: i16,
|
||||
dir: SwipeDirection,
|
||||
normal: Option<AttachType>,
|
||||
attach_animation: AttachAnimation,
|
||||
attach_type: Option<AttachType>,
|
||||
show_attach_anim: bool,
|
||||
}
|
||||
|
||||
impl<T: Component> SwipeContent<T> {
|
||||
@ -101,17 +105,15 @@ impl<T: Component> SwipeContent<T> {
|
||||
bounds: Rect::zero(),
|
||||
progress: 0,
|
||||
dir: SwipeDirection::Up,
|
||||
normal: Some(AttachType::Swipe(SwipeDirection::Down)),
|
||||
attach_animation: AttachAnimation::default(),
|
||||
attach_type: None,
|
||||
show_attach_anim: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_normal_attach(self, attach_type: Option<AttachType>) -> Self {
|
||||
Self {
|
||||
normal: attach_type,
|
||||
..self
|
||||
}
|
||||
pub fn with_no_attach_anim(mut self) -> Self {
|
||||
self.show_attach_anim = false;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &T {
|
||||
@ -130,9 +132,7 @@ impl<T: Component> Component for SwipeContent<T> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Event::Attach(attach_type) = event {
|
||||
self.progress = 0;
|
||||
if let AttachType::Initial = attach_type {
|
||||
self.attach_type = self.normal;
|
||||
} else {
|
||||
if self.show_attach_anim {
|
||||
self.attach_type = Some(attach_type);
|
||||
}
|
||||
self.attach_animation.reset();
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, SwipeDetect, SwipeDetectMsg},
|
||||
event::SwipeEvent,
|
||||
component::{base::AttachType, Component, Event, EventCtx, SwipeDetect, SwipeDetectMsg},
|
||||
event::{SwipeEvent},
|
||||
flow::Swipable,
|
||||
geometry::Rect,
|
||||
shape::Renderer,
|
||||
@ -49,7 +49,8 @@ impl<T: Swipable + Component> Component for SwipeUpScreen<T> {
|
||||
.swipe
|
||||
.event(ctx, event, self.content.get_swipe_config())
|
||||
{
|
||||
Some(SwipeDetectMsg::Trigger(_)) => {
|
||||
Some(SwipeDetectMsg::Trigger(dir)) => {
|
||||
ctx.set_transition_out(AttachType::Swipe(dir));
|
||||
return Some(SwipeUpScreenMsg::Swiped);
|
||||
}
|
||||
Some(SwipeDetectMsg::Move(dir, progress)) => {
|
||||
|
@ -20,7 +20,7 @@ use crate::{
|
||||
ui::{
|
||||
backlight::BACKLIGHT_LEVELS_OBJ,
|
||||
component::{
|
||||
base::{AttachType, ComponentExt},
|
||||
base::ComponentExt,
|
||||
connect::Connect,
|
||||
swipe_detect::SwipeSettings,
|
||||
text::{
|
||||
@ -811,7 +811,7 @@ extern "C" fn new_show_success(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
|
||||
let content = StatusScreen::new_success();
|
||||
let obj = LayoutObj::new(SwipeUpScreen::new(
|
||||
Frame::left_aligned(title, SwipeContent::new(content).with_normal_attach(None))
|
||||
Frame::left_aligned(title, SwipeContent::new(content).with_no_attach_anim())
|
||||
.with_footer(TR::instructions__swipe_up.into(), description)
|
||||
.with_swipe(SwipeDirection::Up, SwipeSettings::default()),
|
||||
))?;
|
||||
@ -1070,11 +1070,7 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
.with_done_offset(theme::CHECKLIST_DONE_OFFSET);
|
||||
|
||||
let obj = LayoutObj::new(SwipeUpScreen::new(
|
||||
Frame::left_aligned(
|
||||
title,
|
||||
SwipeContent::new(checklist_content)
|
||||
.with_normal_attach(Some(AttachType::Swipe(SwipeDirection::Up))),
|
||||
)
|
||||
Frame::left_aligned(title, SwipeContent::new(checklist_content))
|
||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||
.with_swipe(SwipeDirection::Up, SwipeSettings::default()),
|
||||
))?;
|
||||
@ -1317,12 +1313,15 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
///
|
||||
/// T = TypeVar("T")
|
||||
///
|
||||
/// class AttachType:
|
||||
/// ...
|
||||
///
|
||||
/// class LayoutObj(Generic[T]):
|
||||
/// """Representation of a Rust-based layout object.
|
||||
/// see `trezor::ui::layout::obj::LayoutObj`.
|
||||
/// """
|
||||
///
|
||||
/// def attach_timer_fn(self, fn: Callable[[int, int], None]) -> None:
|
||||
/// def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> None:
|
||||
/// """Attach a timer setter function.
|
||||
///
|
||||
/// The layout object can call the timer setter with two arguments,
|
||||
@ -1379,6 +1378,9 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// def page_count(self) -> int:
|
||||
/// """Return the number of pages in the layout object."""
|
||||
///
|
||||
/// def get_transition_out(self) -> AttachType:
|
||||
/// """Return the transition type."""
|
||||
///
|
||||
/// def __del__(self) -> None:
|
||||
/// """Calls drop on contents of the root component."""
|
||||
///
|
||||
|
@ -1625,12 +1625,15 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
///
|
||||
/// T = TypeVar("T")
|
||||
///
|
||||
/// class AttachType:
|
||||
/// ...
|
||||
///
|
||||
/// class LayoutObj(Generic[T]):
|
||||
/// """Representation of a Rust-based layout object.
|
||||
/// see `trezor::ui::layout::obj::LayoutObj`.
|
||||
/// """
|
||||
///
|
||||
/// def attach_timer_fn(self, fn: Callable[[int, int], None]) -> None:
|
||||
/// def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> None:
|
||||
/// """Attach a timer setter function.
|
||||
///
|
||||
/// The layout object can call the timer setter with two arguments,
|
||||
@ -1690,6 +1693,9 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// def button_request(self) -> tuple[int, str] | None:
|
||||
/// """Return (code, type) of button request made during the last event or timer pass."""
|
||||
///
|
||||
/// def get_transition_out(self) -> AttachType:
|
||||
/// """Return the transition type."""
|
||||
///
|
||||
/// def __del__(self) -> None:
|
||||
/// """Calls drop on contents of the root component."""
|
||||
///
|
||||
|
@ -3,12 +3,17 @@ from trezor import utils
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
# rust/src/ui/model_mercury/layout.rs
|
||||
class AttachType:
|
||||
...
|
||||
|
||||
|
||||
# rust/src/ui/model_mercury/layout.rs
|
||||
class LayoutObj(Generic[T]):
|
||||
"""Representation of a Rust-based layout object.
|
||||
see `trezor::ui::layout::obj::LayoutObj`.
|
||||
"""
|
||||
def attach_timer_fn(self, fn: Callable[[int, int], None]) -> None:
|
||||
def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> None:
|
||||
"""Attach a timer setter function.
|
||||
The layout object can call the timer setter with two arguments,
|
||||
`token` and `deadline`. When `deadline` is reached, the layout object
|
||||
@ -49,6 +54,8 @@ class LayoutObj(Generic[T]):
|
||||
"""Paint bounds of individual components on screen."""
|
||||
def page_count(self) -> int:
|
||||
"""Return the number of pages in the layout object."""
|
||||
def get_transition_out(self) -> AttachType:
|
||||
"""Return the transition type."""
|
||||
def __del__(self) -> None:
|
||||
"""Calls drop on contents of the root component."""
|
||||
|
||||
@ -1083,12 +1090,17 @@ from trezor import utils
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
class AttachType:
|
||||
...
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
class LayoutObj(Generic[T]):
|
||||
"""Representation of a Rust-based layout object.
|
||||
see `trezor::ui::layout::obj::LayoutObj`.
|
||||
"""
|
||||
def attach_timer_fn(self, fn: Callable[[int, int], None]) -> None:
|
||||
def attach_timer_fn(self, fn: Callable[[int, int], None], attach_type: AttachType | None) -> None:
|
||||
"""Attach a timer setter function.
|
||||
The layout object can call the timer setter with two arguments,
|
||||
`token` and `deadline`. When `deadline` is reached, the layout object
|
||||
@ -1131,6 +1143,8 @@ class LayoutObj(Generic[T]):
|
||||
"""Return the number of pages in the layout object."""
|
||||
def button_request(self) -> tuple[int, str] | None:
|
||||
"""Return (code, type) of button request made during the last event or timer pass."""
|
||||
def get_transition_out(self) -> AttachType:
|
||||
"""Return the transition type."""
|
||||
def __del__(self) -> None:
|
||||
"""Calls drop on contents of the root component."""
|
||||
|
||||
|
@ -9,7 +9,7 @@ from trezorui2 import BacklightLevels
|
||||
if TYPE_CHECKING:
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
from trezorui2 import UiResult # noqa: F401
|
||||
from trezorui2 import AttachType, UiResult # noqa: F401
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
@ -34,6 +34,9 @@ layout_chan = loop.chan()
|
||||
# allow only one alert at a time to avoid alerts overlapping
|
||||
_alert_in_progress = False
|
||||
|
||||
# storing last transition type, so that next layout can continue nicely
|
||||
LAST_TRANSITION_OUT: AttachType | None = None
|
||||
|
||||
# in debug mode, display an indicator in top right corner
|
||||
if __debug__:
|
||||
|
||||
@ -131,6 +134,12 @@ class Layout(Generic[T]):
|
||||
raised, usually from some of the child components.
|
||||
"""
|
||||
|
||||
def finalize(self) -> None:
|
||||
"""
|
||||
Called when the layout is done. Usually overridden to allow cleanup or storing context.
|
||||
"""
|
||||
pass
|
||||
|
||||
async def __iter__(self) -> T:
|
||||
"""
|
||||
Run the layout and wait until it completes. Returns the result value.
|
||||
@ -159,6 +168,8 @@ class Layout(Generic[T]):
|
||||
except Result as result:
|
||||
# Result exception was raised, this means this layout is complete.
|
||||
value = result.value
|
||||
finally:
|
||||
self.finalize()
|
||||
return value
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -36,7 +36,7 @@ class RustLayout(ui.Layout):
|
||||
self.br_chan = loop.chan()
|
||||
self.layout = layout
|
||||
self.timer = loop.Timer()
|
||||
self.layout.attach_timer_fn(self.set_timer)
|
||||
self.layout.attach_timer_fn(self.set_timer, ui.LAST_TRANSITION_OUT)
|
||||
self._send_button_request()
|
||||
self.backlight_level = ui.BacklightLevels.NORMAL
|
||||
|
||||
@ -191,6 +191,7 @@ class RustLayout(ui.Layout):
|
||||
)
|
||||
|
||||
def _first_paint(self) -> None:
|
||||
|
||||
ui.backlight_fade(ui.BacklightLevels.NONE)
|
||||
self._paint()
|
||||
|
||||
@ -213,7 +214,7 @@ class RustLayout(ui.Layout):
|
||||
|
||||
notify_layout_change(self, event_id)
|
||||
|
||||
# Turn the brightness on again.
|
||||
# Fade brightness to desired level
|
||||
ui.backlight_fade(self.backlight_level)
|
||||
|
||||
def handle_input_and_rendering(self) -> loop.Task:
|
||||
@ -260,13 +261,16 @@ class RustLayout(ui.Layout):
|
||||
br_code, br_type = res
|
||||
self.br_chan.publish((br_code, br_type, self.layout.page_count()))
|
||||
|
||||
def finalize(self):
|
||||
ui.LAST_TRANSITION_OUT = self.layout.get_transition_out()
|
||||
|
||||
|
||||
def draw_simple(layout: Any) -> None:
|
||||
# Simple drawing not supported for layouts that set timers.
|
||||
def dummy_set_timer(token: int, deadline: int) -> None:
|
||||
raise RuntimeError
|
||||
|
||||
layout.attach_timer_fn(dummy_set_timer)
|
||||
layout.attach_timer_fn(dummy_set_timer, None)
|
||||
ui.backlight_fade(ui.BacklightLevels.DIM)
|
||||
layout.paint()
|
||||
ui.refresh()
|
||||
|
@ -35,7 +35,7 @@ class RustProgress:
|
||||
):
|
||||
self.layout = layout
|
||||
ui.backlight_fade(ui.BacklightLevels.DIM)
|
||||
self.layout.attach_timer_fn(self.set_timer)
|
||||
self.layout.attach_timer_fn(self.set_timer, None)
|
||||
if self.layout.paint():
|
||||
ui.refresh()
|
||||
ui.backlight_fade(ui.BacklightLevels.NORMAL)
|
||||
|
@ -41,7 +41,7 @@ class RustLayout(LayoutParentType[T]):
|
||||
self.br_chan = loop.chan()
|
||||
self.layout = layout
|
||||
self.timer = loop.Timer()
|
||||
self.layout.attach_timer_fn(self.set_timer)
|
||||
self.layout.attach_timer_fn(self.set_timer, None)
|
||||
self._send_button_request()
|
||||
|
||||
def __del__(self):
|
||||
@ -309,7 +309,7 @@ def draw_simple(layout: trezorui2.LayoutObj[Any]) -> None:
|
||||
def dummy_set_timer(token: int, deadline: int) -> None:
|
||||
raise RuntimeError
|
||||
|
||||
layout.attach_timer_fn(dummy_set_timer)
|
||||
layout.attach_timer_fn(dummy_set_timer, None)
|
||||
layout.paint()
|
||||
ui.refresh()
|
||||
|
||||
|
@ -42,7 +42,7 @@ class RustLayout(LayoutParentType[T]):
|
||||
self.br_chan = loop.chan()
|
||||
self.layout = layout
|
||||
self.timer = loop.Timer()
|
||||
self.layout.attach_timer_fn(self.set_timer)
|
||||
self.layout.attach_timer_fn(self.set_timer, None)
|
||||
self._send_button_request()
|
||||
self.backlight_level = ui.BacklightLevels.NORMAL
|
||||
|
||||
@ -272,7 +272,7 @@ def draw_simple(layout: trezorui2.LayoutObj[Any]) -> None:
|
||||
def dummy_set_timer(token: int, deadline: int) -> None:
|
||||
raise RuntimeError
|
||||
|
||||
layout.attach_timer_fn(dummy_set_timer)
|
||||
layout.attach_timer_fn(dummy_set_timer, None)
|
||||
ui.backlight_fade(ui.BacklightLevels.DIM)
|
||||
layout.paint()
|
||||
ui.refresh()
|
||||
|
Loading…
Reference in New Issue
Block a user