feat(core): show new homescreen preview for T2B1

[no changelog]
pull/3290/head
grdddj 9 months ago committed by Jiří Musil
parent 1f7c78a4ed
commit 0c4540ae0a

@ -12,7 +12,7 @@ use crate::{
use super::{
super::constant, common::display_center, theme, ButtonController, ButtonControllerMsg,
ButtonLayout,
ButtonLayout, ButtonPos, CancelConfirmMsg,
};
const AREA: Rect = constant::screen();
@ -220,6 +220,70 @@ where
}
}
pub struct ConfirmHomescreen<T, F>
where
T: StringType,
{
title: Child<Label<T>>,
buffer_func: F,
buttons: Child<ButtonController<T>>,
}
impl<T, F> ConfirmHomescreen<T, F>
where
T: StringType + Clone,
{
pub fn new(title: T, buffer_func: F) -> Self {
let btn_layout = ButtonLayout::cancel_none_text("CHANGE".into());
ConfirmHomescreen {
title: Child::new(Label::centered(title, theme::TEXT_BOLD)),
buffer_func,
buttons: Child::new(ButtonController::new(btn_layout)),
}
}
}
impl<'a, T, F> Component for ConfirmHomescreen<T, F>
where
T: StringType + Clone,
F: Fn() -> &'a [u8],
{
type Msg = CancelConfirmMsg;
fn place(&mut self, bounds: Rect) -> Rect {
let (title_content_area, button_area) = bounds.split_bottom(theme::BUTTON_HEIGHT);
let title_height = theme::TEXT_BOLD.text_font.line_height();
let (title_area, _) = title_content_area.split_top(title_height);
self.title.place(title_area);
self.buttons.place(button_area);
bounds
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
// Left button cancels, right confirms
if let Some(ButtonControllerMsg::Triggered(pos)) = self.buttons.event(ctx, event) {
match pos {
ButtonPos::Left => return Some(CancelConfirmMsg::Cancelled),
ButtonPos::Right => return Some(CancelConfirmMsg::Confirmed),
_ => {}
}
}
None
}
fn paint(&mut self) {
// Drawing the image full-screen first and then other things on top
let toif_data = unwrap!(Toif::new((self.buffer_func)()));
toif_data.draw(TOP_CENTER, Alignment2D::TOP_CENTER, theme::FG, theme::BG);
// Need to make all the title background black, so the title text is well
// visible
let title_area = self.title.inner().area();
rect_fill(title_area, theme::BG);
self.title.paint();
self.buttons.paint();
}
}
// DEBUG-ONLY SECTION BELOW
#[cfg(feature = "ui_debug")]
@ -243,3 +307,14 @@ where
t.child("label", &self.label);
}
}
#[cfg(feature = "ui_debug")]
impl<T, F> crate::trace::Trace for ConfirmHomescreen<T, F>
where
T: StringType,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.component("ConfirmHomescreen");
t.child("title", &self.title);
}
}

@ -50,7 +50,7 @@ pub use flow::Flow;
pub use flow_pages::{FlowPages, Page};
pub use frame::{Frame, ScrollableContent, ScrollableFrame};
#[cfg(feature = "micropython")]
pub use homescreen::{Homescreen, Lockscreen};
pub use homescreen::{ConfirmHomescreen, Homescreen, Lockscreen};
pub use input_methods::{
number_input::NumberInput,
passphrase::PassphraseEntry,

@ -6,8 +6,15 @@ use crate::{
error::Error,
maybe_trace::MaybeTrace,
micropython::{
buffer::StrBuffer, gc::Gc, iter::IterBuf, list::List, map::Map, module::Module, obj::Obj,
qstr::Qstr, util,
buffer::{get_buffer, StrBuffer},
gc::Gc,
iter::IterBuf,
list::List,
map::Map,
module::Module,
obj::Obj,
qstr::Qstr,
util,
},
strutil::StringType,
ui::{
@ -38,9 +45,10 @@ use crate::{
use super::{
component::{
AddressDetails, ButtonActions, ButtonDetails, ButtonLayout, ButtonPage, CancelConfirmMsg,
CancelInfoConfirmMsg, CoinJoinProgress, Flow, FlowPages, Frame, Homescreen, Lockscreen,
NumberInput, Page, PassphraseEntry, PinEntry, Progress, ScrollableContent, ScrollableFrame,
ShareWords, ShowMore, SimpleChoice, WelcomeScreen, WordlistEntry, WordlistType,
CancelInfoConfirmMsg, CoinJoinProgress, ConfirmHomescreen, Flow, FlowPages, Frame,
Homescreen, Lockscreen, NumberInput, Page, PassphraseEntry, PinEntry, Progress,
ScrollableContent, ScrollableFrame, ShareWords, ShowMore, SimpleChoice, WelcomeScreen,
WordlistEntry, WordlistType,
},
constant, theme,
};
@ -242,6 +250,19 @@ where
}
}
impl<'a, T, F> ComponentMsgObj for ConfirmHomescreen<T, F>
where
T: StringType + Clone,
F: Fn() -> &'a [u8],
{
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()),
}
}
}
/// Function to create and call a `ButtonPage` dialog based on paginable content
/// (e.g. `Paragraphs` or `FormattedText`).
/// Has optional title (supply empty `StrBuffer` for that) and hold-to-confirm
@ -392,6 +413,24 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?;
// Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8]
// in every paint pass.
// SAFETY: We expect no existing mutable reference. Resulting reference is
// discarded before returning to micropython.
let buffer_func = move || unsafe { unwrap!(get_buffer(data)) };
let obj = LayoutObj::new(ConfirmHomescreen::new(title, buffer_func))?;
Ok(obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
@ -1587,6 +1626,14 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Confirm action."""
Qstr::MP_QSTR_confirm_action => obj_fn_kw!(0, new_confirm_action).as_obj(),
/// def confirm_homescreen(
/// *,
/// title: str,
/// image: bytes,
/// ) -> object:
/// """Confirm homescreen."""
Qstr::MP_QSTR_confirm_homescreen => obj_fn_kw!(0, new_confirm_homescreen).as_obj(),
/// def confirm_blob(
/// *,
/// title: str,

@ -29,6 +29,15 @@ def confirm_action(
"""Confirm action."""
# rust/src/ui/model_tr/layout.rs
def confirm_homescreen(
*,
title: str,
image: bytes,
) -> object:
"""Confirm homescreen."""
# rust/src/ui/model_tr/layout.rs
def confirm_blob(
*,

@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
import trezorui2
from trezor import utils
from trezor.enums import ButtonRequestType
from trezor.ui.layouts import confirm_action, confirm_homescreen, confirm_single
from trezor.ui.layouts import confirm_action
from trezor.wire import DataError
if TYPE_CHECKING:
@ -151,6 +151,8 @@ async def apply_settings(msg: ApplySettings) -> Success:
async def _require_confirm_change_homescreen(homescreen: bytes) -> None:
from trezor.ui.layouts import confirm_homescreen
if homescreen == b"":
await confirm_action(
"set_homescreen",
@ -159,12 +161,12 @@ async def _require_confirm_change_homescreen(homescreen: bytes) -> None:
br_code=BRT_PROTECT_CALL,
)
else:
await confirm_homescreen(
homescreen,
)
await confirm_homescreen(homescreen)
async def _require_confirm_change_label(label: str) -> None:
from trezor.ui.layouts import confirm_single
await confirm_single(
"set_label",
"Device name",

@ -443,12 +443,17 @@ async def confirm_path_warning(
async def confirm_homescreen(
image: bytes,
) -> None:
# TODO: show homescreen preview?
await confirm_action(
"set_homescreen",
"Set homescreen",
description="Do you really want to set new homescreen image?",
br_code=ButtonRequestType.ProtectCall,
await raise_if_not_confirmed(
interact(
RustLayout(
trezorui2.confirm_homescreen(
title="CHANGE HOMESCREEN?",
image=image,
)
),
"set_homesreen",
ButtonRequestType.ProtectCall,
)
)

Loading…
Cancel
Save