From a353c35b781a4a88f0ea47c33e0ec32e98088476 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Thu, 5 Oct 2023 23:19:12 +0200 Subject: [PATCH] fix(core/ui): draw hold-to-confirm loader over dialog title [no changelog] --- .../rust/src/ui/model_tt/component/loader.rs | 26 ++++++++++--------- .../rust/src/ui/model_tt/component/page.rs | 18 +++++++++---- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/core/embed/rust/src/ui/model_tt/component/loader.rs b/core/embed/rust/src/ui/model_tt/component/loader.rs index a135154f98..2f6b9d62d4 100644 --- a/core/embed/rust/src/ui/model_tt/component/loader.rs +++ b/core/embed/rust/src/ui/model_tt/component/loader.rs @@ -2,7 +2,7 @@ use crate::{ time::{Duration, Instant}, ui::{ animation::Animation, - component::{Component, Event, EventCtx}, + component::{Component, Event, EventCtx, Pad}, display::{self, toif::Icon, Color}, geometry::{Offset, Rect}, model_tt::constant, @@ -27,7 +27,7 @@ enum State { } pub struct Loader { - offset_y: i16, + pub pad: Pad, state: State, growing_duration: Duration, shrinking_duration: Duration, @@ -38,12 +38,13 @@ impl Loader { pub const SIZE: Offset = Offset::new(120, 120); pub fn new() -> Self { + let styles = theme::loader_default(); Self { - offset_y: 0, + pad: Pad::with_background(styles.normal.background_color), state: State::Initial, growing_duration: Duration::from_millis(GROWING_DURATION_MS), shrinking_duration: Duration::from_millis(SHRINKING_DURATION_MS), - styles: theme::loader_default(), + styles, } } @@ -130,13 +131,8 @@ impl Component for Loader { type Msg = LoaderMsg; fn place(&mut self, bounds: Rect) -> Rect { - // Current loader API only takes Y-offset relative to screen center, which we - // compute from the bounds center point. - // NOTE: SwipeHoldPage relies on Loader being X-centered regardless of bounds. - // If this changes then SwipeHoldPage needs to be changed too. - let screen_center = constant::screen().center(); - self.offset_y = bounds.center().y - screen_center.y; - Rect::from_center_and_size(screen_center + Offset::y(self.offset_y), Self::SIZE) + self.pad.place(bounds); + Rect::from_center_and_size(bounds.center(), Self::SIZE) } fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option { @@ -177,9 +173,15 @@ impl Component for Loader { self.styles.active }; + // Current loader API only takes Y-offset relative to screen center, which we + // compute from the bounds center point. + let screen_center = constant::screen().center(); + let offset_y = self.pad.area.center().y - screen_center.y; + + self.pad.paint(); display::loader( progress, - self.offset_y, + offset_y, style.loader_color, style.background_color, style.icon, diff --git a/core/embed/rust/src/ui/model_tt/component/page.rs b/core/embed/rust/src/ui/model_tt/component/page.rs index 757cad16f3..f2b3be19e4 100644 --- a/core/embed/rust/src/ui/model_tt/component/page.rs +++ b/core/embed/rust/src/ui/model_tt/component/page.rs @@ -2,6 +2,7 @@ use crate::{ time::Instant, ui::{ component::{paginated::PageMsg, Component, ComponentExt, Event, EventCtx, Pad, Paginate}, + constant, display::{self, Color}, geometry::{Insets, Rect}, util::animation_disabled, @@ -153,6 +154,14 @@ where self.cancel_from_any_page || !self.scrollbar.has_previous_page() } + /// Area for drawing loader (and black rectangle behind it). Can be outside + /// bounds as we repaint entire UI tree after hiding the loader. + const fn loader_area() -> Rect { + constant::screen() + .inset(theme::borders()) + .inset(Insets::bottom(theme::BUTTON_HEIGHT + theme::BUTTON_SPACING)) + } + fn handle_swipe( &mut self, ctx: &mut EventCtx, @@ -225,12 +234,12 @@ where let now = Instant::now(); if let Some(LoaderMsg::ShrunkCompletely) = loader.event(ctx, event) { - // Clear the remnants of the loader. - self.pad.clear(); // Switch it to the initial state, so we stop painting it. loader.reset(); // Re-draw the whole content tree. self.content.request_complete_repaint(ctx); + // Loader overpainted our bounds, repaint entire screen from scratch. + ctx.request_repaint_root() // This can be a result of an animation frame event, we should take // care to not short-circuit here and deliver the event to the // content as well. @@ -238,7 +247,7 @@ where match button_msg { Some(ButtonMsg::Pressed) => { loader.start_growing(ctx, now); - self.pad.clear(); // Clear the remnants of the content. + loader.pad.clear(); // Clear the remnants of the content. } Some(ButtonMsg::Released) => { loader.start_shrinking(ctx, now); @@ -313,8 +322,7 @@ where self.scrollbar.set_count_and_active_page(page_count, 0); self.setup_swipe(); - let content_area = layout.content_single_page.union(layout.scrollbar); - self.loader.place(content_area); + self.loader.place(Self::loader_area()); bounds }