1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 15:38:11 +00:00

feat(core): confirm homescreen image with thumbnail

[no changelog]
This commit is contained in:
tychovrahe 2023-01-03 16:13:30 +01:00 committed by TychoVrahe
parent d00e87ea80
commit 1359b21508
6 changed files with 104 additions and 11 deletions

View File

@ -20,6 +20,7 @@ static void _librust_qstrs(void) {
MP_QSTR_jpeg_info;
MP_QSTR_jpeg_test;
MP_QSTR_confirm_action;
MP_QSTR_confirm_homescreen;
MP_QSTR_confirm_blob;
MP_QSTR_confirm_properties;
MP_QSTR_confirm_coinjoin;
@ -99,6 +100,7 @@ static void _librust_qstrs(void) {
MP_QSTR_min_count;
MP_QSTR_max_count;
MP_QSTR_items;
MP_QSTR_image;
MP_QSTR_active;
MP_QSTR_info_button;
MP_QSTR_time_ms;

View File

@ -1,3 +1,5 @@
#[cfg(feature = "jpeg")]
use crate::ui::geometry::Offset;
use crate::ui::{
component::{Component, Event, EventCtx, Never},
display,
@ -64,3 +66,14 @@ pub fn image_painter(image: &'static [u8]) -> Painter<impl FnMut(Rect)> {
let f = move |area: Rect| display::image(area.center(), image);
Painter::new(f)
}
#[cfg(feature = "jpeg")]
pub fn jpeg_painter<'a>(
image: impl Fn() -> &'a [u8],
size: Offset,
scale: u8,
) -> Painter<impl FnMut(Rect)> {
let off = Offset::new(size.x / (2 << scale), size.y / (2 << scale));
let f = move |area: Rect| display::tjpgd::jpeg(image(), area.center() - off, scale);
Painter::new(f)
}

View File

@ -1,9 +1,10 @@
use core::{cmp::Ordering, convert::TryInto};
use cstr_core::cstr;
use crate::{
error::Error,
micropython::{
buffer::StrBuffer,
buffer::{get_buffer, StrBuffer},
gc::Gc,
iter::{Iter, IterBuf},
list::List,
@ -28,6 +29,7 @@ use crate::{
},
Border, Component, Empty, Timeout, TimeoutMsg,
},
display::tjpgd::jpeg_info,
geometry,
layout::{
obj::{ComponentMsgObj, LayoutObj},
@ -466,6 +468,37 @@ 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 size = match jpeg_info(buffer_func()) {
Some(info) => info.0,
_ => return Err(Error::ValueError(cstr!("Invalid image."))),
};
let buttons = Button::cancel_confirm_text(None, "CONFIRM");
let obj = LayoutObj::new(
Frame::centered(
theme::label_title(),
title,
Dialog::new(painter::jpeg_painter(buffer_func, size, 1), buttons),
)
.with_border(theme::borders()),
)?;
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()?;
@ -1322,6 +1355,15 @@ 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,

View File

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

View File

@ -1,7 +1,7 @@
from typing import TYPE_CHECKING
from trezor.enums import ButtonRequestType
from trezor.ui.layouts import confirm_action
from trezor.ui.layouts import confirm_action, confirm_homescreen
from trezor.wire import DataError
if TYPE_CHECKING:
@ -73,7 +73,7 @@ async def apply_settings(ctx: Context, msg: ApplySettings) -> Success:
if homescreen is not None:
_validate_homescreen(homescreen)
await _require_confirm_change_homescreen(ctx)
await _require_confirm_change_homescreen(ctx, homescreen)
try:
storage_device.set_homescreen(homescreen)
except ValueError:
@ -122,14 +122,22 @@ async def apply_settings(ctx: Context, msg: ApplySettings) -> Success:
return Success(message="Settings applied")
async def _require_confirm_change_homescreen(ctx: GenericContext) -> None:
async def _require_confirm_change_homescreen(
ctx: GenericContext, homescreen: bytes
) -> None:
if homescreen == b"":
await confirm_action(
ctx,
"set_homescreen",
"Set homescreen",
description="Do you really want to change the homescreen image?",
description="Do you really want to set default homescreen image?",
br_code=BRT_PROTECT_CALL,
)
else:
await confirm_homescreen(
ctx,
homescreen,
)
async def _require_confirm_change_label(ctx: GenericContext, label: str) -> None:

View File

@ -334,6 +334,25 @@ async def confirm_path_warning(
)
async def confirm_homescreen(
ctx: GenericContext,
image: bytes,
) -> None:
await raise_if_not_confirmed(
interact(
ctx,
RustLayout(
trezorui2.confirm_homescreen(
title="SET HOMESCREEN",
image=image,
)
),
"set_homesreen",
ButtonRequestType.ProtectCall,
)
)
def _show_xpub(xpub: str, title: str, cancel: str | None) -> ui.Layout:
content = RustLayout(
trezorui2.confirm_blob(