mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 14:28:07 +00:00
fix(core/ui): T2T1: display coinjoin icon on lockscreen
[no changelog]
This commit is contained in:
parent
9a36b1f880
commit
9e33eb3e48
BIN
core/assets/model_r/coinjoin.png
Normal file
BIN
core/assets/model_r/coinjoin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 155 B |
@ -37,6 +37,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_cancel_arrow;
|
||||
MP_QSTR_case_sensitive;
|
||||
MP_QSTR_chunkify;
|
||||
MP_QSTR_coinjoin_authorized;
|
||||
MP_QSTR_confirm_action;
|
||||
MP_QSTR_confirm_address;
|
||||
MP_QSTR_confirm_backup;
|
||||
|
@ -27,6 +27,7 @@ const NOTIFICATION_HEIGHT: i16 = 12;
|
||||
const LABEL_OUTSET: i16 = 3;
|
||||
const NOTIFICATION_FONT: Font = Font::NORMAL;
|
||||
const NOTIFICATION_ICON: Icon = theme::ICON_WARNING;
|
||||
const COINJOIN_CORNER: Point = AREA.top_right().ofs(Offset::new(-2, 2));
|
||||
|
||||
fn paint_default_image() {
|
||||
theme::ICON_LOGO.draw(
|
||||
@ -171,13 +172,15 @@ where
|
||||
instruction: Child<Label<T>>,
|
||||
/// Used for unlocking the device from lockscreen
|
||||
invisible_buttons: Child<ButtonController<T>>,
|
||||
/// Display coinjoin icon?
|
||||
coinjoin_icon: Option<Icon>,
|
||||
}
|
||||
|
||||
impl<T> Lockscreen<T>
|
||||
where
|
||||
T: StringType + Clone,
|
||||
{
|
||||
pub fn new(label: T, bootscreen: bool) -> Self {
|
||||
pub fn new(label: T, bootscreen: bool, coinjoin_authorized: bool) -> Self {
|
||||
// Buttons will not be visible, we only need all three of them to be present,
|
||||
// so that even middle-click triggers the event.
|
||||
let invisible_btn_layout = ButtonLayout::arrow_armed_arrow("".into());
|
||||
@ -190,6 +193,7 @@ where
|
||||
label: Child::new(Label::centered(label, theme::TEXT_BIG)),
|
||||
instruction: Child::new(Label::centered(instruction_str.into(), theme::TEXT_NORMAL)),
|
||||
invisible_buttons: Child::new(ButtonController::new(invisible_btn_layout)),
|
||||
coinjoin_icon: coinjoin_authorized.then_some(theme::ICON_COINJOIN),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -223,6 +227,14 @@ where
|
||||
);
|
||||
self.instruction.paint();
|
||||
self.label.paint();
|
||||
if let Some(i) = &self.coinjoin_icon {
|
||||
i.draw(
|
||||
COINJOIN_CORNER,
|
||||
Alignment2D::TOP_RIGHT,
|
||||
theme::FG,
|
||||
theme::BG,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1587,9 +1587,10 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut
|
||||
.try_into_option()?
|
||||
.unwrap_or_else(|| model::FULL_NAME.into());
|
||||
let bootscreen: bool = kwargs.get(Qstr::MP_QSTR_bootscreen)?.try_into()?;
|
||||
let coinjoin_authorized: bool = kwargs.get_or(Qstr::MP_QSTR_coinjoin_authorized, false)?;
|
||||
let skip_first_paint: bool = kwargs.get(Qstr::MP_QSTR_skip_first_paint)?.try_into()?;
|
||||
|
||||
let obj = LayoutObj::new(Lockscreen::new(label, bootscreen))?;
|
||||
let obj = LayoutObj::new(Lockscreen::new(label, bootscreen, coinjoin_authorized))?;
|
||||
if skip_first_paint {
|
||||
obj.skip_first_paint();
|
||||
}
|
||||
@ -2008,6 +2009,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// label: str | None,
|
||||
/// bootscreen: bool,
|
||||
/// skip_first_paint: bool,
|
||||
/// coinjoin_authorized: bool = False,
|
||||
/// ) -> CANCELLED:
|
||||
/// """Homescreen for locked device."""
|
||||
Qstr::MP_QSTR_show_lockscreen => obj_fn_kw!(0, new_show_lockscreen).as_obj(),
|
||||
|
BIN
core/embed/rust/src/ui/model_tr/res/coinjoin.toif
Normal file
BIN
core/embed/rust/src/ui/model_tr/res/coinjoin.toif
Normal file
Binary file not shown.
@ -80,6 +80,7 @@ include_icon!(
|
||||
"model_tr/res/cancel.toif",
|
||||
empty_right_col = true
|
||||
); // 7*7
|
||||
include_icon!(ICON_COINJOIN, "model_tr/res/coinjoin.toif"); // 12*12
|
||||
include_icon!(
|
||||
ICON_DELETE,
|
||||
"model_tr/res/delete.toif",
|
||||
|
@ -36,6 +36,7 @@ const LABEL_Y: i16 = HEIGHT - 18;
|
||||
const LOCKED_Y: i16 = HEIGHT / 2 - 13;
|
||||
const TAP_Y: i16 = HEIGHT / 2 + 14;
|
||||
const HOLD_Y: i16 = 35;
|
||||
const COINJOIN_Y: i16 = 30;
|
||||
const LOADER_OFFSET: Offset = Offset::y(-10);
|
||||
const LOADER_DELAY: Duration = Duration::from_millis(500);
|
||||
const LOADER_DURATION: Duration = Duration::from_millis(2000);
|
||||
@ -198,7 +199,7 @@ where
|
||||
let text = HomescreenText {
|
||||
text: self.label.as_ref(),
|
||||
style: label_style,
|
||||
offset: Offset::new(10, LABEL_Y),
|
||||
offset: Offset::y(LABEL_Y),
|
||||
icon: None,
|
||||
};
|
||||
|
||||
@ -266,11 +267,16 @@ impl<T: AsRef<str>> crate::trace::Trace for Homescreen<T> {
|
||||
pub struct Lockscreen<T> {
|
||||
label: T,
|
||||
bootscreen: bool,
|
||||
coinjoin_authorized: bool,
|
||||
}
|
||||
|
||||
impl<T> Lockscreen<T> {
|
||||
pub fn new(label: T, bootscreen: bool) -> Self {
|
||||
Lockscreen { label, bootscreen }
|
||||
pub fn new(label: T, bootscreen: bool, coinjoin_authorized: bool) -> Self {
|
||||
Lockscreen {
|
||||
label,
|
||||
bootscreen,
|
||||
coinjoin_authorized,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,27 +307,37 @@ where
|
||||
let mut label_style = theme::TEXT_DEMIBOLD;
|
||||
label_style.text_color = theme::GREY_LIGHT;
|
||||
|
||||
let texts: [HomescreenText; 3] = [
|
||||
let mut texts: &[HomescreenText] = &[
|
||||
HomescreenText {
|
||||
text: "",
|
||||
style: theme::TEXT_NORMAL,
|
||||
offset: Offset::new(2, COINJOIN_Y),
|
||||
icon: Some(theme::ICON_COINJOIN),
|
||||
},
|
||||
HomescreenText {
|
||||
text: locked,
|
||||
style: theme::TEXT_BOLD,
|
||||
offset: Offset::new(10, LOCKED_Y),
|
||||
offset: Offset::y(LOCKED_Y),
|
||||
icon: Some(theme::ICON_LOCK),
|
||||
},
|
||||
HomescreenText {
|
||||
text: tap,
|
||||
style: theme::TEXT_NORMAL,
|
||||
offset: Offset::new(10, TAP_Y),
|
||||
offset: Offset::y(TAP_Y),
|
||||
icon: None,
|
||||
},
|
||||
HomescreenText {
|
||||
text: self.label.as_ref(),
|
||||
style: label_style,
|
||||
offset: Offset::new(10, LABEL_Y),
|
||||
offset: Offset::y(LABEL_Y),
|
||||
icon: None,
|
||||
},
|
||||
];
|
||||
|
||||
if !self.coinjoin_authorized {
|
||||
texts = &texts[1..];
|
||||
}
|
||||
|
||||
let res = get_user_custom_image();
|
||||
let mut show_default = true;
|
||||
|
||||
@ -330,14 +346,14 @@ where
|
||||
let mut input = BufferInput(data.as_ref());
|
||||
let mut pool = BufferJpegWork::get_cleared();
|
||||
let mut hs_img = HomescreenJpeg::new(&mut input, pool.buffer.as_mut_slice());
|
||||
homescreen_blurred(&mut hs_img, &texts);
|
||||
homescreen_blurred(&mut hs_img, texts);
|
||||
show_default = false;
|
||||
} else if is_image_toif(data.as_ref()) {
|
||||
let input = unwrap!(Toif::new(data.as_ref()));
|
||||
let mut window = [0; UZLIB_WINDOW_SIZE];
|
||||
let mut hs_img =
|
||||
HomescreenToif::new(input.decompression_context(Some(&mut window)));
|
||||
homescreen_blurred(&mut hs_img, &texts);
|
||||
homescreen_blurred(&mut hs_img, texts);
|
||||
show_default = false;
|
||||
}
|
||||
}
|
||||
@ -346,7 +362,7 @@ where
|
||||
let mut input = BufferInput(IMAGE_HOMESCREEN);
|
||||
let mut pool = BufferJpegWork::get_cleared();
|
||||
let mut hs_img = HomescreenJpeg::new(&mut input, pool.buffer.as_mut_slice());
|
||||
homescreen_blurred(&mut hs_img, &texts);
|
||||
homescreen_blurred(&mut hs_img, texts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -230,9 +230,11 @@ fn homescreen_position_text(
|
||||
|
||||
let text_top = screen().y0 + text.offset.y - font_max_height + font_baseline;
|
||||
let text_bottom = screen().y0 + text.offset.y + font_baseline;
|
||||
let icon_left = screen().center().x - (text_width_clamped + icon_size.x + TEXT_ICON_SPACE) / 2;
|
||||
|
||||
let total_width = text_width_clamped + icon_size.x + TEXT_ICON_SPACE;
|
||||
let icon_left = screen().center().x + text.offset.x - total_width / 2;
|
||||
let text_left = icon_left + icon_size.x + TEXT_ICON_SPACE;
|
||||
let text_right = screen().center().x + (text_width_clamped + icon_size.x + TEXT_ICON_SPACE) / 2;
|
||||
let text_right = screen().center().x + text.offset.x + total_width / 2;
|
||||
|
||||
let text_area = Rect::new(
|
||||
Point::new(text_left, text_top),
|
||||
|
@ -1557,9 +1557,10 @@ extern "C" fn new_show_lockscreen(n_args: usize, args: *const Obj, kwargs: *mut
|
||||
.try_into_option()?
|
||||
.unwrap_or_else(|| model::FULL_NAME.into());
|
||||
let bootscreen: bool = kwargs.get(Qstr::MP_QSTR_bootscreen)?.try_into()?;
|
||||
let coinjoin_authorized: bool = kwargs.get_or(Qstr::MP_QSTR_coinjoin_authorized, false)?;
|
||||
let skip_first_paint: bool = kwargs.get(Qstr::MP_QSTR_skip_first_paint)?.try_into()?;
|
||||
|
||||
let obj = LayoutObj::new(Lockscreen::new(label, bootscreen))?;
|
||||
let obj = LayoutObj::new(Lockscreen::new(label, bootscreen, coinjoin_authorized))?;
|
||||
if skip_first_paint {
|
||||
obj.skip_first_paint();
|
||||
}
|
||||
@ -1988,6 +1989,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// label: str | None,
|
||||
/// bootscreen: bool,
|
||||
/// skip_first_paint: bool,
|
||||
/// coinjoin_authorized: bool = False,
|
||||
/// ) -> CANCELLED:
|
||||
/// """Homescreen for locked device."""
|
||||
Qstr::MP_QSTR_show_lockscreen => obj_fn_kw!(0, new_show_lockscreen).as_obj(),
|
||||
|
@ -433,6 +433,7 @@ def show_lockscreen(
|
||||
label: str | None,
|
||||
bootscreen: bool,
|
||||
skip_first_paint: bool,
|
||||
coinjoin_authorized: bool = False,
|
||||
) -> CANCELLED:
|
||||
"""Homescreen for locked device."""
|
||||
|
||||
@ -883,6 +884,7 @@ def show_lockscreen(
|
||||
label: str | None,
|
||||
bootscreen: bool,
|
||||
skip_first_paint: bool,
|
||||
coinjoin_authorized: bool = False,
|
||||
) -> CANCELLED:
|
||||
"""Homescreen for locked device."""
|
||||
|
||||
|
@ -51,7 +51,10 @@ async def lockscreen() -> None:
|
||||
|
||||
# Only show the lockscreen UI if the device can in fact be locked.
|
||||
if can_lock_device():
|
||||
await Lockscreen(label=storage.device.get_label())
|
||||
await Lockscreen(
|
||||
label=storage.device.get_label(),
|
||||
coinjoin_authorized=is_set_any_session(MessageType.AuthorizeCoinJoin),
|
||||
)
|
||||
# Otherwise proceed directly to unlock() call. If the device is already unlocked,
|
||||
# it should be a no-op storage-wise, but it resets the internal configuration
|
||||
# to an unlocked state.
|
||||
|
@ -80,6 +80,7 @@ class Lockscreen(HomescreenBase):
|
||||
self,
|
||||
label: str | None,
|
||||
bootscreen: bool = False,
|
||||
coinjoin_authorized: bool = False,
|
||||
) -> None:
|
||||
self.bootscreen = bootscreen
|
||||
skip = (
|
||||
@ -90,6 +91,7 @@ class Lockscreen(HomescreenBase):
|
||||
label=label,
|
||||
bootscreen=bootscreen,
|
||||
skip_first_paint=skip,
|
||||
coinjoin_authorized=coinjoin_authorized,
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -92,6 +92,7 @@ class Lockscreen(HomescreenBase):
|
||||
self,
|
||||
label: str | None,
|
||||
bootscreen: bool = False,
|
||||
coinjoin_authorized: bool = False,
|
||||
) -> None:
|
||||
self.bootscreen = bootscreen
|
||||
if bootscreen:
|
||||
@ -105,6 +106,7 @@ class Lockscreen(HomescreenBase):
|
||||
label=label,
|
||||
bootscreen=bootscreen,
|
||||
skip_first_paint=skip,
|
||||
coinjoin_authorized=coinjoin_authorized,
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -737,7 +737,7 @@
|
||||
},
|
||||
"TR": {
|
||||
"click_tests": {
|
||||
"TR_test_autolock.py::test_autolock_does_not_interrupt_preauthorized": "b96ab80af28b6d5e13ef32a8cc19812445c6258a2ad64f15870c7490a37edc06",
|
||||
"TR_test_autolock.py::test_autolock_does_not_interrupt_preauthorized": "22f65f6d9edc7659e5c54bdda6bd38c68c96637d2eb1f8475a536c9f49423b30",
|
||||
"TR_test_autolock.py::test_autolock_does_not_interrupt_signing": "3d0833002f39256a15ee5008af9d2cd304c61bc2932cb6dc844c027bfed3ed1d",
|
||||
"TR_test_autolock.py::test_autolock_interrupts_passphrase": "1ab8da65492ade3e6301f784b818d355959c665ea4b91e38f6dd2de8c8b21c84",
|
||||
"TR_test_autolock.py::test_autolock_interrupts_signing": "5f26a18a711ec7d17c035cc60478249281edeeac512d4561e55bd7a3c2d2ef94",
|
||||
@ -795,8 +795,8 @@
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_get_address": "a96bebc82d5aff9c6a8583ddb354e6427689a3be4fddf082c3cd0e8722e54d46",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_get_public_key": "4c2bba305bab30de2fcff0cec5ab1192f2e4d826d86f91f7172dfa624f5f3139",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_multisession_authorization": "5f70b535406a6254113ed2a5f780ba98b8205abf6425eb7038d22395953aa560",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx[False]": "76fe57750f0bfbaa84aaa99f67329dc93e505d51521c2a2490d523996b403aa3",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx[True]": "76fe57750f0bfbaa84aaa99f67329dc93e505d51521c2a2490d523996b403aa3",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx[False]": "ebe4ac22942f10915507491103d1151b2416ffebfd6c3ca6f2b28be8b35d4262",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx[True]": "ebe4ac22942f10915507491103d1151b2416ffebfd6c3ca6f2b28be8b35d4262",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx_large": "4f275de439c812363140d3839ebddd9243e2bb34d80d02a487361148b2bbab71",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx_migration": "4cf48d6bb48a9efbff9e2949d657fde4dea7ae9e92f47cafdfcd11d7765d76b8",
|
||||
"TR_bitcoin-test_authorize_coinjoin.py::test_sign_tx_spend": "db453154c6d8318befea7230eb2a9639fece5bdfd83c62fbb7a1e9195b77ac1b",
|
||||
@ -2017,7 +2017,7 @@
|
||||
},
|
||||
"TT": {
|
||||
"click_tests": {
|
||||
"TT_test_autolock.py::test_autolock_does_not_interrupt_preauthorized": "a46dce1eef3df4b242e90af5f6c6a1f2acdb27e7b56a1af0ab0982483bc0d9b7",
|
||||
"TT_test_autolock.py::test_autolock_does_not_interrupt_preauthorized": "521b6ce07207c262b832fb4e78477f89211dc02a4b6e02a6fe8d389a2be909cf",
|
||||
"TT_test_autolock.py::test_autolock_does_not_interrupt_signing": "e8ff223f44e97a98fbef62c2ed314bdc2d3a2f160d0396d09733847ce103494d",
|
||||
"TT_test_autolock.py::test_autolock_interrupts_passphrase": "15ce8ca8c46be745296ad39b2df4e4503f1b3208c3f5b3e3f48d7bd172779605",
|
||||
"TT_test_autolock.py::test_autolock_interrupts_signing": "a9b983a624b6ca20fd976fc59b570e0bfebc847a448a1db63717932d96cde15c",
|
||||
@ -2078,8 +2078,8 @@
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_get_address": "f4de0499dac628067619c6081d4ebdba0ad196af7bf9662c5387386eba9e9729",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_get_public_key": "38a7eac0cf0be45770fb28da9c2f74bac6404e85f2a3801acdd4b0107d99f2ff",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_multisession_authorization": "d39b3290ddfecd5a3ceaf249543eaccb2b71c21eb2dbeabef94fe866ad7ce6a8",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx[False]": "a5601b1f876c598cfe9361b4203a0b2908e860bef93d3fcc1a4fd2f89eeddfec",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx[True]": "a5601b1f876c598cfe9361b4203a0b2908e860bef93d3fcc1a4fd2f89eeddfec",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx[False]": "00f8d6cc8ad60877dc4629295e438f29912456f0767997ce3ba9277d1e1bbf22",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx[True]": "00f8d6cc8ad60877dc4629295e438f29912456f0767997ce3ba9277d1e1bbf22",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx_large": "312fca890a6e93da6c3705e3b3c97ba38dd336374634dbed9134362420273380",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx_migration": "a0757616e39b5883ccfba01af3b386d1fc2d4a00517b2c3d79519ce0f60bc5cd",
|
||||
"TT_bitcoin-test_authorize_coinjoin.py::test_sign_tx_spend": "b8ca0b72adfb0cfa1ff653c83a0995517b71f8bfc217753e16aab49dd82a3a65",
|
||||
|
Loading…
Reference in New Issue
Block a user