mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 15:28:10 +00:00
refactor(core/ui): optimize brightness settings for Mercury
This commit is contained in:
parent
2994317dcd
commit
7404436305
1
core/.changelog.d/3969.fixed
Normal file
1
core/.changelog.d/3969.fixed
Normal file
@ -0,0 +1 @@
|
||||
[T3T1] Improved screen brightness settings.
|
@ -1330,7 +1330,7 @@ pub enum TranslatedString {
|
||||
words__settings = 929, // "Settings"
|
||||
words__try_again = 930, // "Try again."
|
||||
reset__slip39_checklist_num_groups_x_template = 931, // "Number of groups: {0}"
|
||||
brightness__title = 932, // "Set brightness"
|
||||
brightness__title = 932, // "Change display brightness"
|
||||
recovery__title_unlock_repeated_backup = 933, // "Multi-share backup"
|
||||
recovery__unlock_repeated_backup = 934, // "Create additional backup?"
|
||||
recovery__unlock_repeated_backup_verb = 935, // "Create backup"
|
||||
@ -2673,7 +2673,7 @@ impl TranslatedString {
|
||||
Self::words__settings => "Settings",
|
||||
Self::words__try_again => "Try again.",
|
||||
Self::reset__slip39_checklist_num_groups_x_template => "Number of groups: {0}",
|
||||
Self::brightness__title => "Set brightness",
|
||||
Self::brightness__title => "Change display brightness",
|
||||
Self::recovery__title_unlock_repeated_backup => "Multi-share backup",
|
||||
Self::recovery__unlock_repeated_backup => "Create additional backup?",
|
||||
Self::recovery__unlock_repeated_backup_verb => "Create backup",
|
||||
|
@ -27,8 +27,6 @@ mod prompt_screen;
|
||||
mod result;
|
||||
mod scroll;
|
||||
#[cfg(feature = "translations")]
|
||||
mod set_brightness;
|
||||
#[cfg(feature = "translations")]
|
||||
mod share_words;
|
||||
mod status_screen;
|
||||
mod swipe_content;
|
||||
@ -74,8 +72,6 @@ pub use prompt_screen::PromptScreen;
|
||||
pub use result::{ResultFooter, ResultScreen, ResultStyle};
|
||||
pub use scroll::ScrollBar;
|
||||
#[cfg(feature = "translations")]
|
||||
pub use set_brightness::SetBrightnessDialog;
|
||||
#[cfg(feature = "translations")]
|
||||
pub use share_words::ShareWords;
|
||||
pub use status_screen::StatusScreen;
|
||||
pub use swipe_content::{InternallySwipable, InternallySwipableContent, SwipeContent};
|
||||
|
@ -5,25 +5,21 @@ use crate::{
|
||||
constant::screen,
|
||||
display,
|
||||
event::TouchEvent,
|
||||
geometry::{Alignment, Grid, Insets, Point, Rect},
|
||||
geometry::{Alignment, Insets, Point, Rect},
|
||||
shape::{self, Renderer},
|
||||
},
|
||||
};
|
||||
|
||||
use super::{theme, Button, ButtonMsg};
|
||||
use super::theme;
|
||||
|
||||
pub enum NumberInputSliderDialogMsg {
|
||||
Changed(u16),
|
||||
Confirmed,
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
pub struct NumberInputSliderDialog {
|
||||
area: Rect,
|
||||
text_area: Rect,
|
||||
input: Child<NumberInputSlider>,
|
||||
cancel_button: Child<Button>,
|
||||
confirm_button: Child<Button>,
|
||||
min: u16,
|
||||
max: u16,
|
||||
val: u16,
|
||||
@ -35,12 +31,6 @@ impl NumberInputSliderDialog {
|
||||
area: Rect::zero(),
|
||||
text_area: Rect::zero(),
|
||||
input: NumberInputSlider::new(min, max, init_value).into_child(),
|
||||
cancel_button: Button::with_text("CANCEL".into())
|
||||
.styled(theme::button_cancel())
|
||||
.into_child(),
|
||||
confirm_button: Button::with_text("CONFIRM".into())
|
||||
.styled(theme::button_confirm())
|
||||
.into_child(),
|
||||
min,
|
||||
max,
|
||||
val: init_value,
|
||||
@ -57,18 +47,14 @@ impl Component for NumberInputSliderDialog {
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.area = bounds;
|
||||
let button_height = theme::BUTTON_HEIGHT;
|
||||
let content_area = self.area.inset(Insets::top(2 * theme::BUTTON_SPACING));
|
||||
let (_, content_area) = content_area.split_top(30);
|
||||
let (input_area, _) = content_area.split_top(15);
|
||||
let (text_area, button_area) = content_area.split_bottom(button_height);
|
||||
let (text_area, _) = content_area.split_bottom(theme::BUTTON_HEIGHT);
|
||||
|
||||
self.text_area = text_area;
|
||||
|
||||
let grid = Grid::new(button_area, 1, 2).with_spacing(theme::KEYBOARD_SPACING);
|
||||
self.input.place(input_area.inset(Insets::sides(20)));
|
||||
self.cancel_button.place(grid.row_col(0, 0));
|
||||
self.confirm_button.place(grid.row_col(0, 1));
|
||||
bounds
|
||||
}
|
||||
|
||||
@ -77,19 +63,11 @@ impl Component for NumberInputSliderDialog {
|
||||
self.val = value;
|
||||
return Some(Self::Msg::Changed(value));
|
||||
}
|
||||
if let Some(ButtonMsg::Clicked) = self.cancel_button.event(ctx, event) {
|
||||
return Some(Self::Msg::Cancelled);
|
||||
}
|
||||
if let Some(ButtonMsg::Clicked) = self.confirm_button.event(ctx, event) {
|
||||
return Some(Self::Msg::Confirmed);
|
||||
};
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.input.paint();
|
||||
self.cancel_button.paint();
|
||||
self.confirm_button.paint();
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
@ -105,9 +83,6 @@ impl Component for NumberInputSliderDialog {
|
||||
.with_fg(theme::TEXT_NORMAL.text_color)
|
||||
.with_align(Alignment::Center)
|
||||
.render(target);
|
||||
|
||||
self.cancel_button.render(target);
|
||||
self.confirm_button.render(target);
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,8 +91,6 @@ impl crate::trace::Trace for NumberInputSliderDialog {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("NumberInputSliderDialog");
|
||||
t.child("input", &self.input);
|
||||
t.child("cancel_button", &self.cancel_button);
|
||||
t.child("confirm_button", &self.confirm_button);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
use crate::{
|
||||
storage,
|
||||
trezorhal::display,
|
||||
ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
geometry::Rect,
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
super::theme,
|
||||
number_input_slider::{NumberInputSliderDialog, NumberInputSliderDialogMsg},
|
||||
CancelConfirmMsg,
|
||||
};
|
||||
|
||||
pub struct SetBrightnessDialog(NumberInputSliderDialog);
|
||||
|
||||
impl SetBrightnessDialog {
|
||||
pub fn new(current: Option<u16>) -> Self {
|
||||
let current = current.unwrap_or(theme::backlight::get_backlight_normal());
|
||||
Self(NumberInputSliderDialog::new(
|
||||
theme::backlight::get_backlight_min(),
|
||||
theme::backlight::get_backlight_max(),
|
||||
current,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for SetBrightnessDialog {
|
||||
type Msg = CancelConfirmMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.0.place(bounds)
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
match self.0.event(ctx, event) {
|
||||
Some(NumberInputSliderDialogMsg::Changed(value)) => {
|
||||
display::backlight(value as _);
|
||||
None
|
||||
}
|
||||
Some(NumberInputSliderDialogMsg::Cancelled) => Some(CancelConfirmMsg::Cancelled),
|
||||
Some(NumberInputSliderDialogMsg::Confirmed) => {
|
||||
match storage::set_brightness(self.0.value() as _) {
|
||||
Ok(_) => Some(CancelConfirmMsg::Confirmed),
|
||||
Err(_) => Some(CancelConfirmMsg::Cancelled), // TODO: handle error
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.0.paint()
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.0.render(target);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl crate::trace::Trace for SetBrightnessDialog {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("SetBrightnessDialog");
|
||||
t.child("input", &self.0);
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ pub mod confirm_summary;
|
||||
pub mod get_address;
|
||||
pub mod prompt_backup;
|
||||
pub mod request_number;
|
||||
pub mod set_brightness;
|
||||
pub mod show_share_words;
|
||||
pub mod show_tutorial;
|
||||
pub mod warning_hi_prio;
|
||||
@ -22,6 +23,7 @@ pub use confirm_summary::new_confirm_summary;
|
||||
pub use get_address::GetAddress;
|
||||
pub use prompt_backup::PromptBackup;
|
||||
pub use request_number::RequestNumber;
|
||||
pub use set_brightness::SetBrightness;
|
||||
pub use show_share_words::ShowShareWords;
|
||||
pub use show_tutorial::ShowTutorial;
|
||||
pub use warning_hi_prio::WarningHiPrio;
|
||||
|
138
core/embed/rust/src/ui/model_mercury/flow/set_brightness.rs
Normal file
138
core/embed/rust/src/ui/model_mercury/flow/set_brightness.rs
Normal file
@ -0,0 +1,138 @@
|
||||
use core::sync::atomic::{AtomicU16, Ordering};
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
micropython::{map::Map, obj::Obj, qstr::Qstr, util},
|
||||
storage,
|
||||
translations::TR,
|
||||
trezorhal::display,
|
||||
ui::{
|
||||
component::{base::ComponentExt, swipe_detect::SwipeSettings, SwipeDirection},
|
||||
flow::{
|
||||
base::{Decision, FlowMsg},
|
||||
flow_store, FlowState, FlowStore, SwipeFlow,
|
||||
},
|
||||
layout::obj::LayoutObj,
|
||||
model_mercury::component::{
|
||||
number_input_slider::{NumberInputSliderDialog, NumberInputSliderDialogMsg},
|
||||
SwipeContent,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
component::{Frame, FrameMsg, PromptScreen, VerticalMenu, VerticalMenuChoiceMsg},
|
||||
theme,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, ToPrimitive)]
|
||||
pub enum SetBrightness {
|
||||
Slider,
|
||||
Menu,
|
||||
Confirm,
|
||||
}
|
||||
|
||||
impl FlowState for SetBrightness {
|
||||
fn handle_swipe(&self, direction: SwipeDirection) -> Decision<Self> {
|
||||
match (self, direction) {
|
||||
(SetBrightness::Menu, SwipeDirection::Right) => {
|
||||
Decision::Goto(SetBrightness::Slider, direction)
|
||||
}
|
||||
(SetBrightness::Slider, SwipeDirection::Up) => {
|
||||
Decision::Goto(SetBrightness::Confirm, direction)
|
||||
}
|
||||
(SetBrightness::Confirm, SwipeDirection::Down) => {
|
||||
Decision::Goto(SetBrightness::Slider, direction)
|
||||
}
|
||||
(SetBrightness::Confirm, SwipeDirection::Left) => {
|
||||
Decision::Goto(SetBrightness::Menu, direction)
|
||||
}
|
||||
_ => Decision::Nothing,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_event(&self, msg: FlowMsg) -> Decision<Self> {
|
||||
match (self, msg) {
|
||||
(SetBrightness::Slider, FlowMsg::Info) => {
|
||||
Decision::Goto(SetBrightness::Menu, SwipeDirection::Left)
|
||||
}
|
||||
(SetBrightness::Menu, FlowMsg::Cancelled) => {
|
||||
Decision::Goto(SetBrightness::Slider, SwipeDirection::Right)
|
||||
}
|
||||
(SetBrightness::Menu, FlowMsg::Choice(0)) => Decision::Return(FlowMsg::Cancelled),
|
||||
(SetBrightness::Confirm, FlowMsg::Confirmed) => Decision::Return(FlowMsg::Confirmed),
|
||||
(SetBrightness::Confirm, FlowMsg::Info) => {
|
||||
Decision::Goto(SetBrightness::Menu, SwipeDirection::Left)
|
||||
}
|
||||
_ => Decision::Nothing,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BRIGHTNESS: AtomicU16 = AtomicU16::new(0);
|
||||
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
pub extern "C" fn new_set_brightness(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, SetBrightness::new_obj) }
|
||||
}
|
||||
|
||||
impl SetBrightness {
|
||||
fn new_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, Error> {
|
||||
let current: Option<u16> = kwargs.get(Qstr::MP_QSTR_current)?.try_into_option()?;
|
||||
let content_slider = Frame::left_aligned(
|
||||
TR::brightness__title.into(),
|
||||
NumberInputSliderDialog::new(
|
||||
theme::backlight::get_backlight_min(),
|
||||
theme::backlight::get_backlight_max(),
|
||||
current.unwrap_or(theme::backlight::get_backlight_normal()),
|
||||
),
|
||||
)
|
||||
.with_menu_button()
|
||||
.with_footer(TR::instructions__swipe_up.into(), None)
|
||||
.with_swipe(SwipeDirection::Up, SwipeSettings::default())
|
||||
.map(|msg| match msg {
|
||||
FrameMsg::Content(NumberInputSliderDialogMsg::Changed(n)) => {
|
||||
display::backlight(n as _);
|
||||
BRIGHTNESS.store(n, Ordering::Relaxed);
|
||||
None
|
||||
}
|
||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
||||
});
|
||||
|
||||
let content_menu = Frame::left_aligned(
|
||||
"".into(),
|
||||
VerticalMenu::empty().danger(theme::ICON_CANCEL, TR::buttons__cancel.into()),
|
||||
)
|
||||
.with_cancel_button()
|
||||
.with_swipe(SwipeDirection::Right, SwipeSettings::immediate())
|
||||
.map(move |msg| match msg {
|
||||
FrameMsg::Content(VerticalMenuChoiceMsg::Selected(i)) => Some(FlowMsg::Choice(i)),
|
||||
FrameMsg::Button(_) => Some(FlowMsg::Cancelled),
|
||||
});
|
||||
|
||||
let content_confirm = Frame::left_aligned(
|
||||
TR::brightness__title.into(),
|
||||
SwipeContent::new(PromptScreen::new_tap_to_confirm()),
|
||||
)
|
||||
.with_footer(TR::instructions__tap_to_confirm.into(), None)
|
||||
.with_menu_button()
|
||||
.with_swipe(SwipeDirection::Down, SwipeSettings::default())
|
||||
.with_swipe(SwipeDirection::Left, SwipeSettings::default())
|
||||
.map(move |msg| match msg {
|
||||
FrameMsg::Content(()) => {
|
||||
let _ = storage::set_brightness(BRIGHTNESS.load(Ordering::Relaxed) as u8);
|
||||
Some(FlowMsg::Confirmed)
|
||||
}
|
||||
FrameMsg::Button(_) => Some(FlowMsg::Info),
|
||||
});
|
||||
|
||||
let store = flow_store()
|
||||
.add(content_slider)?
|
||||
.add(content_menu)?
|
||||
.add(content_confirm)?;
|
||||
|
||||
let res = SwipeFlow::new(SetBrightness::Slider, store)?;
|
||||
|
||||
Ok(LayoutObj::new(res)?.into())
|
||||
}
|
||||
}
|
@ -217,15 +217,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentMsgObj for SetBrightnessDialog {
|
||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||
match msg {
|
||||
CancelConfirmMsg::Confirmed => Ok(CONFIRMED.as_obj()),
|
||||
CancelConfirmMsg::Cancelled => Ok(CANCELLED.as_obj()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentMsgObj for Progress {
|
||||
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
|
||||
unreachable!()
|
||||
@ -1025,18 +1016,6 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_set_brightness(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let current: Option<u16> = kwargs.get(Qstr::MP_QSTR_current)?.try_into_option()?;
|
||||
let obj = LayoutObj::new(Frame::centered(
|
||||
TR::brightness__title.into(),
|
||||
SetBrightnessDialog::new(current),
|
||||
))?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
@ -1734,7 +1713,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// current: int | None = None
|
||||
/// ) -> LayoutObj[UiResult]:
|
||||
/// """Show the brightness configuration dialog."""
|
||||
Qstr::MP_QSTR_set_brightness => obj_fn_kw!(0, new_set_brightness).as_obj(),
|
||||
Qstr::MP_QSTR_set_brightness => obj_fn_kw!(0, flow::set_brightness::new_set_brightness).as_obj(),
|
||||
|
||||
/// def show_checklist(
|
||||
/// *,
|
||||
|
@ -79,7 +79,7 @@ class TR:
|
||||
bitcoin__unverified_external_inputs: str = "The transaction contains unverified external inputs."
|
||||
bitcoin__valid_signature: str = "The signature is valid."
|
||||
bitcoin__voting_rights: str = "Voting rights to:"
|
||||
brightness__title: str = "Set brightness"
|
||||
brightness__title: str = "Change display brightness"
|
||||
buttons__abort: str = "Abort"
|
||||
buttons__access: str = "Access"
|
||||
buttons__again: str = "Again"
|
||||
|
@ -81,7 +81,7 @@
|
||||
"bitcoin__unverified_external_inputs": "The transaction contains unverified external inputs.",
|
||||
"bitcoin__valid_signature": "The signature is valid.",
|
||||
"bitcoin__voting_rights": "Voting rights to:",
|
||||
"brightness__title": "Set brightness",
|
||||
"brightness__title": "Change display brightness",
|
||||
"buttons__abort": "Abort",
|
||||
"buttons__access": "Access",
|
||||
"buttons__again": "Again",
|
||||
|
Loading…
Reference in New Issue
Block a user